|
1 /* |
|
2 * Copyright (c) 2005-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 * (c) 1999 Symbian Ltd |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 /** |
|
23 @file |
|
24 */ |
|
25 |
|
26 #include <e32base.h> |
|
27 #include <e32std.h> |
|
28 #include <e32test.h> |
|
29 #include <random.h> |
|
30 #include <f32file.h> |
|
31 |
|
32 #include <randsvr.h> |
|
33 |
|
34 RTest test(_L("Random Number Generator Tests")); |
|
35 |
|
36 TInt gNumberOfRandomNumbers=10000; |
|
37 |
|
38 /** Wraps a console and logs output to a file. */ |
|
39 class CTestConsole:public CConsoleBase |
|
40 { |
|
41 public: |
|
42 static CTestConsole* NewL(CConsoleBase* aCon, const TDesC& aFilename); |
|
43 TInt Create(const TDesC16& aTitle,TSize aSize) {return iCon->Create(aTitle,aSize);}; |
|
44 void Read(TRequestStatus& aStatus) {iCon->Read(aStatus);}; |
|
45 void ReadCancel(void) {iCon->ReadCancel();}; |
|
46 void Write(const TDesC16& aString); |
|
47 TPoint CursorPos(void) const {return iCon->CursorPos();}; |
|
48 void SetCursorPosAbs(const TPoint& aPos) {iCon->SetCursorPosAbs(aPos);}; |
|
49 void SetCursorPosRel(const TPoint& aPos) {iCon->SetCursorPosRel(aPos);}; |
|
50 void SetCursorHeight(TInt aHeight) {iCon->SetCursorHeight(aHeight);}; |
|
51 void SetTitle(const TDesC16& aTitle) {iCon->SetTitle(aTitle);}; |
|
52 void ClearScreen(void) {iCon->ClearScreen();}; |
|
53 void ClearToEndOfLine(void) {iCon->ClearToEndOfLine();}; |
|
54 TSize ScreenSize(void) const {return iCon->ScreenSize();}; |
|
55 TKeyCode KeyCode(void) const {return iCon->KeyCode();}; |
|
56 TUint KeyModifiers(void) const {return iCon->KeyModifiers();}; |
|
57 ~CTestConsole(void); |
|
58 private: |
|
59 CTestConsole(CConsoleBase* aCon); |
|
60 void ConstructL(const TDesC& aFilename); |
|
61 CConsoleBase* iCon; ///< Pointer to wrapped console, we don't own this |
|
62 RFs iFs; |
|
63 RFile iFile; ///< Log file |
|
64 }; |
|
65 |
|
66 CTestConsole* CTestConsole::NewL(CConsoleBase* aCon, const TDesC& aFilename) |
|
67 |
|
68 { |
|
69 CTestConsole* self; |
|
70 self=new (ELeave) CTestConsole(aCon); |
|
71 CleanupStack::PushL(self); |
|
72 self->ConstructL(aFilename); |
|
73 CleanupStack::Pop(self); |
|
74 return self; |
|
75 } |
|
76 |
|
77 CTestConsole::CTestConsole(CConsoleBase* aCon) : |
|
78 CConsoleBase(), iCon(aCon) |
|
79 |
|
80 { |
|
81 } |
|
82 |
|
83 void CTestConsole::ConstructL(const TDesC& aFilename) |
|
84 |
|
85 { |
|
86 User::LeaveIfError(iFs.Connect()); |
|
87 User::LeaveIfError(iFile.Replace(iFs,aFilename,EFileShareAny|EFileWrite)); |
|
88 } |
|
89 |
|
90 CTestConsole::~CTestConsole(void) |
|
91 |
|
92 { |
|
93 iFile.Close(); |
|
94 iFs.Close(); |
|
95 } |
|
96 |
|
97 void CTestConsole::Write(const TDesC16& aString) |
|
98 |
|
99 { |
|
100 iCon->Write(aString); |
|
101 TUint8 space[200]; |
|
102 TPtr8 ptr(space,200); |
|
103 ptr.Copy(aString); |
|
104 iFile.Write(ptr); |
|
105 } |
|
106 |
|
107 void Monobit(const TUint8* aData) |
|
108 |
|
109 { |
|
110 const TInt bitcount[256]= |
|
111 { 0,1,1,2,1,2,2,3, // 00-07 |
|
112 1,2,2,3,2,3,3,4, // 08-0f |
|
113 1,2,2,3,2,3,3,4, // 10-17 |
|
114 2,3,3,4,3,4,4,5, // 18-1f |
|
115 1,2,2,3,2,3,3,4, // 20-27 |
|
116 2,3,3,4,3,4,4,5, // 28-2f |
|
117 2,3,3,4,3,4,4,5, // 30-37 |
|
118 3,4,4,5,4,5,5,6, // 38-3f |
|
119 |
|
120 1,2,2,3,2,3,3,4, // 40-47 |
|
121 2,3,3,4,3,4,4,5, // 48-4f |
|
122 2,3,3,4,3,4,4,5, // 50-57 |
|
123 3,4,4,5,4,5,5,6, // 58-5f |
|
124 2,3,3,4,3,4,4,5, // 60-67 |
|
125 3,4,4,5,4,5,5,6, // 68-6f |
|
126 3,4,4,5,4,5,5,6, // 70-77 |
|
127 4,5,5,6,5,6,6,7, // 78-7f |
|
128 |
|
129 1,2,2,3,2,3,3,4, // 80-87 |
|
130 2,3,3,4,3,4,4,5, // 88-8f |
|
131 2,3,3,4,3,4,4,5, // 90-97 |
|
132 3,4,4,5,4,5,5,6, // 98-9f |
|
133 2,3,3,4,3,4,4,5, // a0-a7 |
|
134 3,4,4,5,4,5,5,6, // a8-af |
|
135 3,4,4,5,4,5,5,6, // b0-b7 |
|
136 4,5,5,6,5,6,6,7, // b8-bf |
|
137 |
|
138 2,3,3,4,3,4,4,5, // c0-c7 |
|
139 3,4,4,5,4,5,5,6, // c8-cf |
|
140 3,4,4,5,4,5,5,6, // d0-d7 |
|
141 4,5,5,6,5,6,6,7, // d8-df |
|
142 3,4,4,5,4,5,5,6, // e0-e7 |
|
143 4,5,5,6,5,6,6,7, // e8-ef |
|
144 4,5,5,6,5,6,6,7, // f0-f7 |
|
145 5,6,6,7,6,7,7,8 // f8-ff |
|
146 }; |
|
147 TInt total=0; |
|
148 TInt i; |
|
149 for (i=0;i<2500;i++) |
|
150 { |
|
151 total+=bitcount[aData[i]]; |
|
152 } |
|
153 test.Printf(_L(" Total bitcount %d\r\n"),total); |
|
154 if ((total>9654)&&(total<10346)) |
|
155 { |
|
156 test.Printf(_L(" Passed Monobit\r\n")); |
|
157 } |
|
158 else |
|
159 { |
|
160 test.Printf(_L(" ***FAILED!\r\n")); |
|
161 User::Panic(_L("t_random.exe"), KErrGeneral); |
|
162 } |
|
163 } |
|
164 |
|
165 void Poker(const TUint8* aData) |
|
166 |
|
167 { |
|
168 TInt f[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; |
|
169 TInt i; |
|
170 for (i=0;i<2500;i++) |
|
171 { |
|
172 f[(aData[i]&0x0f)]++; |
|
173 f[((aData[i]&0xf0)>>4)]++; |
|
174 } |
|
175 TReal x=0; |
|
176 for (i=0;i<16;i++) |
|
177 { |
|
178 x+=f[i]*f[i]; |
|
179 } |
|
180 x*=16; |
|
181 x/=5000; |
|
182 x-=5000; |
|
183 if ((x>1.03)&&(x<57.4)) |
|
184 { |
|
185 test.Printf(_L(" Passed poker test\r\n")); |
|
186 } |
|
187 else |
|
188 { |
|
189 test.Printf(_L(" ***FAILED poker test\r\n")); |
|
190 User::Panic(_L("t_random.exe"), KErrGeneral); |
|
191 } |
|
192 } |
|
193 |
|
194 void Runs(const TUint8* aData) |
|
195 |
|
196 { |
|
197 TInt i; |
|
198 TInt lastbit=0; |
|
199 TInt count[7][2]={ |
|
200 { 0,0 }, |
|
201 { 0,0 }, |
|
202 { 0,0 }, |
|
203 { 0,0 }, |
|
204 { 0,0 }, |
|
205 { 0,0 }, |
|
206 { 0,0 } |
|
207 }; |
|
208 TInt thisrun=0; |
|
209 TInt longrun=0; |
|
210 for (i=0;i<2500;i++) |
|
211 { |
|
212 TInt bit; |
|
213 for (bit=0;bit<8;bit++) |
|
214 { |
|
215 if (((aData[i]>>bit)&1)==lastbit) |
|
216 { |
|
217 thisrun++; |
|
218 } |
|
219 else |
|
220 { |
|
221 if (thisrun<5) |
|
222 { |
|
223 count[thisrun][lastbit]++; |
|
224 } |
|
225 else |
|
226 { |
|
227 count[5][lastbit]++; |
|
228 } |
|
229 lastbit^=1; |
|
230 if (thisrun>longrun) |
|
231 { |
|
232 longrun=thisrun; |
|
233 } |
|
234 thisrun=0; |
|
235 } |
|
236 } |
|
237 } |
|
238 TInt bound[6][2]= |
|
239 { |
|
240 {2267,2733}, |
|
241 {1079,1421}, |
|
242 { 502, 748}, |
|
243 { 223, 402}, |
|
244 { 90, 223}, |
|
245 { 90, 223} |
|
246 }; |
|
247 TBool failed=EFalse; |
|
248 for (i=0;i<6;i++) |
|
249 { |
|
250 if (!((count[i][0]>bound[i][0])&&(count[i][0]<bound[i][1]))) |
|
251 { |
|
252 test.Printf(_L(" ***FAILED runs test\r\n")); |
|
253 failed=ETrue; |
|
254 } |
|
255 if (!((count[i][1]>bound[i][0])&&(count[i][1]<bound[i][1]))) |
|
256 { |
|
257 test.Printf(_L(" ***FAILED runs test\r\n")); |
|
258 failed=ETrue; |
|
259 } |
|
260 } |
|
261 if (!failed) |
|
262 { |
|
263 test.Printf(_L(" Passed runs test\r\n")); |
|
264 } |
|
265 if ( (longrun>34) || (failed) ) |
|
266 { |
|
267 test.Printf(_L(" ***FAILED longrun test\r\n")); |
|
268 User::Panic(_L("t_random.exe"), KErrGeneral); |
|
269 } |
|
270 } |
|
271 |
|
272 void FIPSTest(const TUint8* aData) |
|
273 // Run some basic tests to check it's returned some numbers |
|
274 // These will panic if a failure is detected |
|
275 { |
|
276 Monobit(aData); |
|
277 Poker(aData); |
|
278 Runs(aData); |
|
279 } |
|
280 |
|
281 void WriteFile(const TUint8* aData,const TDesC& aFileName) |
|
282 |
|
283 { |
|
284 RFs fs; |
|
285 fs.Connect(); |
|
286 RFile file; |
|
287 TInt err; |
|
288 err=file.Open(fs,aFileName,EFileShareAny|EFileWrite); |
|
289 if (err) |
|
290 { |
|
291 if (file.Create(fs,aFileName,EFileShareAny|EFileWrite)) |
|
292 { |
|
293 return; |
|
294 } |
|
295 } |
|
296 TPtrC8 ptr(aData,gNumberOfRandomNumbers); |
|
297 TInt size; |
|
298 file.Size(size); |
|
299 file.Write(size,ptr); |
|
300 file.Close(); |
|
301 fs.Close(); |
|
302 FIPSTest(aData); |
|
303 } |
|
304 |
|
305 class RTestRandomSession : public RRandomSession |
|
306 { |
|
307 public: |
|
308 void SendMalformedInputL() |
|
309 { |
|
310 test.Printf(_L("Test malformed input with negative buffer size\r\n")); |
|
311 TBuf8<1024> buffer; |
|
312 TInt err = SendReceive(CRandomSession::KRandomRequest, TIpcArgs(&buffer, -1)); |
|
313 if (err != KErrArgument) |
|
314 { |
|
315 test.Printf(_L("%d should have been returned on negative buffer size test, but %d was returned!\r\n"), KErrArgument, err); |
|
316 User::Leave(KErrGeneral); |
|
317 } |
|
318 } |
|
319 }; |
|
320 |
|
321 // Checks that RandomServer handles malformed length correctly - see INC113902 |
|
322 void TestMalformedInputL() |
|
323 { |
|
324 RTestRandomSession rs; |
|
325 TRAPD(err, rs.ConnectL()); |
|
326 User::LeaveIfError(err); // The connect method leaves with zero even if it succeeds, so we have to trap the error |
|
327 CleanupClosePushL(rs); |
|
328 rs.SendMalformedInputL(); |
|
329 CleanupStack::PopAndDestroy(&rs); |
|
330 } |
|
331 |
|
332 void DoTestsL() |
|
333 |
|
334 { |
|
335 TestMalformedInputL(); |
|
336 |
|
337 test.Printf(_L(" Run random tests with normal salting\r\n")); |
|
338 |
|
339 TInt i; |
|
340 TBuf8<16> buf2; |
|
341 for (i=0;i<16;i++) |
|
342 { |
|
343 buf2.SetLength(i); |
|
344 TRandom::RandomL(buf2); |
|
345 } |
|
346 HBufC8* buf=HBufC8::NewMaxL(gNumberOfRandomNumbers); |
|
347 TPtr8 buffer=buf->Des(); |
|
348 for (i=0;i<11;i++) |
|
349 { |
|
350 User::After(10000000); |
|
351 TPtr8 thePtr(buf->Des()); |
|
352 thePtr.FillZ(); |
|
353 // Generate the random data |
|
354 TRandom::RandomL(buffer); |
|
355 if (buf->Length()!=gNumberOfRandomNumbers) |
|
356 User::Leave(KErrGeneral); |
|
357 |
|
358 |
|
359 WriteFile(buffer.Ptr(),_L("User.rnd")); |
|
360 test.Printf(_L(".")); |
|
361 } |
|
362 delete buf; |
|
363 } |
|
364 |
|
365 void TestsL(void) |
|
366 { |
|
367 TDriveUnit sysDrive (RFs::GetSystemDrive()); |
|
368 TDriveName driveName(sysDrive.Name()); |
|
369 TBuf<64> logFile (driveName); |
|
370 logFile.Append(_L("\\t_random.log")); |
|
371 CTestConsole* con = CTestConsole::NewL(test.Console(), logFile); |
|
372 test.SetConsole(con); |
|
373 |
|
374 DoTestsL(); |
|
375 |
|
376 // If test reached here, no tests failed, otherwise it would have panicked |
|
377 // and terminated prematurely. Print this out for tester's reference. |
|
378 test.Printf(_L("\n0 tests failed out of 12\r\n")); |
|
379 } |
|
380 |
|
381 GLDEF_C TInt E32Main(void) |
|
382 |
|
383 { |
|
384 CTrapCleanup* cleanup; |
|
385 cleanup=CTrapCleanup::New(); |
|
386 |
|
387 __UHEAP_MARK; |
|
388 |
|
389 test.Start(_L("Starting random number generator tests\r\n")); |
|
390 CConsoleBase* originalConsole = test.Console(); |
|
391 |
|
392 TRAPD(ret,TestsL()); |
|
393 if (ret) |
|
394 { |
|
395 test.Printf(_L("Unexpected leave\r\n")); |
|
396 // Print something to let the build system know we failed |
|
397 test.Printf(_L("\n1 tests failed out of 11\r\n")); |
|
398 } |
|
399 test.End(); |
|
400 |
|
401 if (test.Console() != originalConsole) |
|
402 { |
|
403 delete test.Console(); |
|
404 test.SetConsole(originalConsole); |
|
405 } |
|
406 test.Close(); |
|
407 |
|
408 __UHEAP_MARKEND; |
|
409 |
|
410 delete cleanup; |
|
411 return(KErrNone); |
|
412 } |