|
1 /* |
|
2 * Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * Implementation for testing sequence object encoding/decoding |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 #include "testsequence.h" |
|
21 #include "tasn1normaltest.h" |
|
22 #include <asn1enc.h> |
|
23 #include <asn1dec.h> |
|
24 #include <e32math.h> |
|
25 #include <e32cons.h> |
|
26 |
|
27 #include <bigint.h> |
|
28 |
|
29 CTestSequence* CTestSequence::NewL(CASN1NormalTest &aASN1Action) |
|
30 { |
|
31 CTestSequence* test = new (ELeave) CTestSequence(aASN1Action); |
|
32 return test; |
|
33 } |
|
34 |
|
35 CTestSequence::CTestSequence(CASN1NormalTest &aASN1Action) : CTestBase(aASN1Action) |
|
36 { |
|
37 }; |
|
38 |
|
39 |
|
40 void CTestSequence::GetName(TDes& aBuf) |
|
41 { |
|
42 aBuf.Copy(_L("Test Sequence")); |
|
43 } |
|
44 |
|
45 void CTestSequence::FillParameterArray(void) |
|
46 { |
|
47 iParameters->Append(CTestParameter::EInt); |
|
48 iParameters->Append(CTestParameter::EInt); |
|
49 } |
|
50 |
|
51 |
|
52 TBool CTestSequence::PerformTest(CConsoleBase& aConsole, const TInt &aTestDepth, const TInt &aTestSize, const TInt &aTestNumber, const TInt &aTotalTests) |
|
53 { |
|
54 iObjectsEncoded = 1; |
|
55 CASN1EncBase* encoder = MakeSequenceEncoderLC(aTestDepth, 0, aTestSize); |
|
56 |
|
57 // Prepare a buffer |
|
58 TInt totalLength = encoder->LengthDER(); |
|
59 HBufC8* buf = HBufC8::NewMaxLC(totalLength); |
|
60 TPtr8 tBuf = buf->Des(); |
|
61 |
|
62 // Write into the buffer |
|
63 TUint writeLength = 0; |
|
64 encoder->WriteDERL(tBuf, writeLength); |
|
65 |
|
66 // Check number of objects in buffer reads OK and matches what we hoped |
|
67 TInt objectsRead = ReadAndCountL(tBuf); |
|
68 if (objectsRead != iObjectsEncoded) |
|
69 { |
|
70 aConsole.Write(_L("ERROR! Encoded sequence object count mismatch\n")); |
|
71 iASN1Action.ReportProgressL(KErrASN1EncodingError, aTestNumber, aTotalTests); |
|
72 CleanupStack::PopAndDestroy(2); // buf, encoder |
|
73 return(EFalse); |
|
74 } |
|
75 else |
|
76 { |
|
77 iASN1Action.ReportProgressL(KErrNone, aTestNumber, aTotalTests); |
|
78 CleanupStack::PopAndDestroy(2); // buf, encoder |
|
79 return(ETrue); |
|
80 } |
|
81 } |
|
82 |
|
83 |
|
84 CASN1EncSequence* CTestSequence::MakeSequenceEncoderLC(TInt aMaxDepth, |
|
85 TInt aMinSize, |
|
86 TInt aMaxSize) |
|
87 { |
|
88 __ASSERT_ALWAYS(aMaxDepth > 0, User::Leave(KErrArgument)); |
|
89 __ASSERT_ALWAYS(aMinSize >= 0, User::Leave(KErrArgument)); |
|
90 __ASSERT_ALWAYS(aMinSize <= aMaxSize, User::Leave(KErrArgument)); |
|
91 |
|
92 CASN1EncSequence* encoder = CASN1EncSequence::NewLC(); |
|
93 |
|
94 TUint targetSize = aMinSize + (Math::Random() % (aMaxSize + 1 - aMinSize)); |
|
95 TUint size = 0; |
|
96 while (size < targetSize) |
|
97 { |
|
98 const TInt KMaxChildType = 3; |
|
99 const TInt childTypes = aMaxDepth > 1 ? KMaxChildType + 1 : KMaxChildType; |
|
100 const TInt childType = (Math::Random() >> 5) % childTypes; |
|
101 CASN1EncBase* child = 0; |
|
102 CASN1EncSequence* seqEnc = 0; |
|
103 switch (childType) |
|
104 { |
|
105 case 0: |
|
106 child = CASN1EncInt::NewLC(Math::Random()); |
|
107 break; |
|
108 case 1: |
|
109 { |
|
110 RInteger i = RInteger::NewRandomL(1234, TInteger::EAllBitsRandom); |
|
111 CleanupStack::PushL(i); |
|
112 CASN1EncBigInt* encInt = CASN1EncBigInt::NewLC(i); |
|
113 CleanupStack::Pop(); // encInt |
|
114 CleanupStack::PopAndDestroy(&i); // a deep copy of the info is taken |
|
115 CleanupStack::PushL(encInt); |
|
116 child = encInt; |
|
117 break; |
|
118 } |
|
119 case 2: |
|
120 child = CASN1EncNull::NewLC(); |
|
121 break; |
|
122 case KMaxChildType: |
|
123 // last case must be for next-level sequence encoder |
|
124 seqEnc = MakeSequenceEncoderLC(aMaxDepth - 1, aMinSize, aMaxSize); |
|
125 child = seqEnc; |
|
126 break; |
|
127 default: |
|
128 User::Leave(KErrNotSupported); |
|
129 break; |
|
130 } |
|
131 |
|
132 if (child) |
|
133 { |
|
134 encoder->AddChildL(child); |
|
135 CleanupStack::Pop(); // child |
|
136 ++iObjectsEncoded; |
|
137 ++size; |
|
138 |
|
139 // If we've just added a sequence, want to test ability to add things to a sequence |
|
140 // *that is itself a child*, to check size changes propagate upwards to parent |
|
141 if (seqEnc) |
|
142 { |
|
143 child = CASN1EncInt::NewLC(Math::Random()); |
|
144 |
|
145 seqEnc->AddChildL(child); |
|
146 CleanupStack::Pop(); // child |
|
147 ++iObjectsEncoded; |
|
148 seqEnc = 0; |
|
149 } |
|
150 } |
|
151 } |
|
152 |
|
153 return encoder; |
|
154 } |
|
155 |
|
156 |
|
157 TInt CTestSequence::ReadAndCountL(const TDesC8& aBuf) |
|
158 { |
|
159 TInt result = 1; |
|
160 |
|
161 TASN1DecGeneric decoder(aBuf); |
|
162 decoder.InitL(); |
|
163 |
|
164 TInt bufLength = aBuf.Length(); |
|
165 TInt readLength = decoder.LengthDER(); |
|
166 |
|
167 __ASSERT_ALWAYS(bufLength >= readLength, User::Leave(KErrCorrupt)); |
|
168 if (bufLength > readLength) |
|
169 { |
|
170 // Read the remainder of this buffer too |
|
171 result += ReadAndCountL(aBuf.Mid(readLength)); |
|
172 } |
|
173 |
|
174 if (decoder.Encoding()[0] & 0x20 // Tagged as constructed |
|
175 && decoder.LengthDERContent() > 0) |
|
176 { |
|
177 // Read objects from inside the sequence too |
|
178 result += ReadAndCountL(decoder.GetContentDER()); |
|
179 } |
|
180 |
|
181 return result; |
|
182 } |
|
183 |
|
184 TBool CTestSequence::PerformTestsL(CConsoleBase& aConsole) |
|
185 { |
|
186 // Keep these two coprime to maximise combinations |
|
187 const TInt KMaxSize = 11; |
|
188 const TInt KMaxDepth = 10; |
|
189 CTestParameter* test; |
|
190 TInt totalTests, currentTest=0; |
|
191 TInt maxDepth; |
|
192 TInt maxSize; |
|
193 |
|
194 if(!CountTests(totalTests)) return(EFalse); |
|
195 |
|
196 for(TInt pos = 0; pos < iValues->Count(); pos++) |
|
197 { |
|
198 test = (*iValues)[pos]; |
|
199 switch(test->GetType()) |
|
200 { |
|
201 case CTestParameter::EInt : |
|
202 { |
|
203 CIntTestParameter *intTest = REINTERPRET_CAST(CIntTestParameter*, test); |
|
204 |
|
205 // Get the encoder and decoder |
|
206 maxDepth = intTest->Value(); |
|
207 test = (*iValues)[++pos]; |
|
208 if(test->GetType() != CTestParameter::EInt) |
|
209 { |
|
210 User::Leave(KErrNotSupported); |
|
211 } |
|
212 intTest = REINTERPRET_CAST(CIntTestParameter*, test); |
|
213 maxSize = intTest->Value(); |
|
214 if(!PerformTest(aConsole, maxDepth, maxSize, currentTest, totalTests)) |
|
215 { |
|
216 return(EFalse); |
|
217 } |
|
218 currentTest++; |
|
219 break; |
|
220 } |
|
221 case CTestParameter::ERandom : |
|
222 { |
|
223 CRandomTestParameter *randomTest = REINTERPRET_CAST(CRandomTestParameter*, test); |
|
224 // Get the encoder and decoder |
|
225 |
|
226 for(TInt test = 0; test <= randomTest->Interations(); test++) |
|
227 { |
|
228 |
|
229 // Get the encoder and decoder |
|
230 maxDepth = (test % KMaxDepth) + 1; |
|
231 maxSize = test % KMaxSize; |
|
232 |
|
233 currentTest++; |
|
234 // Don't do the too-big combinations (too slow) |
|
235 if (maxDepth + maxSize > 14) continue; |
|
236 if(!PerformTest(aConsole, maxDepth, maxSize, currentTest, totalTests)) |
|
237 { |
|
238 return(EFalse); |
|
239 } |
|
240 } |
|
241 break; |
|
242 } |
|
243 default: |
|
244 { |
|
245 return EFalse; |
|
246 } |
|
247 } |
|
248 } |
|
249 iASN1Action.ReportProgressL(KErrNone, totalTests, totalTests); |
|
250 return(ETrue); |
|
251 } |