|
1 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include <e32std.h> |
|
17 #include <e32std_private.h> |
|
18 #include <e32svr.h> |
|
19 #include <e32test.h> |
|
20 #include "randgen.h" |
|
21 #include "user_config.h" |
|
22 #include "tf_write.h" |
|
23 |
|
24 _LIT( KTestName, "TF_WRITE" ); |
|
25 RTest test( KTestName ); |
|
26 |
|
27 |
|
28 const TInt64 KRandomSeed1(MAKE_TINT64(0x3e000111,0xAFCBDF0F)); |
|
29 |
|
30 |
|
31 GLDEF_C void Panic( TPanicNo aPanic ) |
|
32 { |
|
33 User::Panic( KTestName, aPanic ); |
|
34 } |
|
35 |
|
36 |
|
37 // ********************************************************************** |
|
38 // Implementation of the writer classes |
|
39 |
|
40 TWriteBase::TWriteBase( CWriteTest& aOwner ) |
|
41 : iOwner( aOwner ) |
|
42 { |
|
43 } |
|
44 |
|
45 void TWriteBase::CheckedWrite(TInt aPos,const TDesC8& aSrc) |
|
46 { |
|
47 Write( aPos, aSrc ); |
|
48 test( iOwner.CompareAgainstFlash( aPos, aSrc ) ); |
|
49 } |
|
50 |
|
51 |
|
52 TSimpleWrite::TSimpleWrite( CWriteTest& aOwner ) |
|
53 : TWriteBase( aOwner ), iDrive( aOwner.Drive() ) |
|
54 { |
|
55 } |
|
56 |
|
57 void TSimpleWrite::Write(TInt aPos,const TDesC8& aSrc) |
|
58 { |
|
59 TInt64 pos( aPos ); |
|
60 // test( KErrNone == iDrive.Write( pos, aSrc ) ); |
|
61 TInt rv = iDrive.Write( pos, aSrc ); |
|
62 if( KErrNone != rv ) |
|
63 { |
|
64 test.Printf( _L("TBusLocalDrive::Write returned %d"), rv ); |
|
65 test( EFalse ); |
|
66 } |
|
67 } |
|
68 |
|
69 |
|
70 |
|
71 TThreadWrite::TThreadWrite( CWriteTest& aOwner ) |
|
72 : TWriteBase( aOwner ), iDrive( aOwner.Drive() ), |
|
73 iThreadHandle( aOwner.DummyThreadHandle() ) |
|
74 { |
|
75 } |
|
76 |
|
77 void TThreadWrite::Write(TInt aPos,const TDesC8& aSrc) |
|
78 { |
|
79 TInt64 pos( aPos ); |
|
80 #if 0 |
|
81 test( KErrNone == iDrive.Write( pos, aSrc.Length(), &aSrc, iThreadHandle, 0 ) ); |
|
82 #else |
|
83 test( KErrNone == iDrive.Write( pos, aSrc.Length(), &aSrc, KLocalMessageHandle, 0 ) ); |
|
84 #endif |
|
85 } |
|
86 |
|
87 |
|
88 void TThreadWrite::CheckedThreadWrite(TInt aPos, TInt aLength, const TDesC8& aSrc, TInt aDescOffset ) |
|
89 { |
|
90 TInt64 pos( aPos ); |
|
91 #if 0 |
|
92 test( KErrNone == iDrive.Write( pos, aLength, &aSrc, iThreadHandle, aDescOffset ) ); |
|
93 #else |
|
94 test( KErrNone == iDrive.Write( pos, aLength, &aSrc, KLocalMessageHandle, aDescOffset ) ); |
|
95 #endif |
|
96 test( iOwner.CompareAgainstFlash( aPos, aLength, aSrc, aDescOffset ) ); |
|
97 } |
|
98 |
|
99 void TThreadWrite::CurrentThreadCheckedThreadWrite(TInt aPos, TInt aLength, const TDesC8& aSrc, TInt aDescOffset ) |
|
100 { |
|
101 TInt64 pos( aPos ); |
|
102 #if 0 |
|
103 test( KErrNone == iDrive.Write( pos, aLength, &aSrc, RThread().Handle(), aDescOffset ) ); |
|
104 #else |
|
105 test( KErrNone == iDrive.Write( pos, aLength, &aSrc, KLocalMessageHandle, aDescOffset ) ); |
|
106 #endif |
|
107 test( iOwner.CompareAgainstFlash( aPos, aLength, aSrc, aDescOffset ) ); |
|
108 } |
|
109 |
|
110 // ********************************************************************** |
|
111 // Implementation of CBlockManager |
|
112 |
|
113 CBlockManager::CBlockManager( TBusLocalDrive& aDrive, CWriteTest& aOwner ) |
|
114 : iDrive( aDrive ), iOwner( aOwner ) |
|
115 { |
|
116 } |
|
117 |
|
118 CBlockManager::~CBlockManager() |
|
119 { |
|
120 delete[] iEraseArray; |
|
121 } |
|
122 |
|
123 void CBlockManager::CreateL() |
|
124 { |
|
125 // |
|
126 // Get size of Flash drive |
|
127 // |
|
128 test.Printf( _L("Reading block info...") ); |
|
129 TLocalDriveCapsV2Buf info; |
|
130 iDrive.Caps(info); |
|
131 TUint flashSize = I64LOW(info().iSize); |
|
132 test( 0 == I64HIGH(info().iSize)); |
|
133 iBlockSize = info().iEraseBlockSize; |
|
134 test( 0 == (iBlockSize & 3) ); |
|
135 iBlockCount = flashSize / iBlockSize; |
|
136 test( 0 != iBlockCount ); |
|
137 |
|
138 test.Printf( _L("Flash block size=0x%x; block count=%d\n"), iBlockSize, iBlockCount ); |
|
139 |
|
140 iEraseArray = new(ELeave) TEraseStatus[iBlockCount]; |
|
141 test.Printf( _L("Erase status array created") ); |
|
142 } |
|
143 |
|
144 |
|
145 void CBlockManager::EraseBlock( TInt aBlockNumber ) |
|
146 { |
|
147 __ASSERT_ALWAYS( aBlockNumber < iBlockCount, Panic( EPanicEraseBlockOOR ) ); |
|
148 __ASSERT_ALWAYS( aBlockNumber < iBlockCount, Panic( EPanicEraseBlockNeg ) ); |
|
149 _LIT( KEraseMsg, "Erasing block %d" ); |
|
150 test.Printf( KEraseMsg, aBlockNumber ); |
|
151 test( KErrNone == iDrive.Format( BlockAddress( aBlockNumber ), iBlockSize ) ); |
|
152 VerifyErased( aBlockNumber ); |
|
153 iEraseArray[ aBlockNumber ] = EErased; |
|
154 } |
|
155 |
|
156 void CBlockManager::EraseAllBlocks() |
|
157 { |
|
158 _LIT( KEraseMsg, "Erasing all blocks" ); |
|
159 test.Printf( KEraseMsg ); |
|
160 for( TInt i = 0; i < iBlockCount; i++ ) |
|
161 { |
|
162 EraseBlock( i ); |
|
163 } |
|
164 } |
|
165 |
|
166 void CBlockManager::VerifyErased( TInt aBlockNumber ) |
|
167 { |
|
168 TUint offset = aBlockNumber * iBlockSize; |
|
169 |
|
170 TBool failed = EFalse; |
|
171 const TInt readBufLen = iReadBuffer.MaxLength(); |
|
172 |
|
173 for( TInt remaining = iBlockSize; remaining > 0 && !failed ;) |
|
174 { |
|
175 TInt r = iDrive.Read( offset, readBufLen, iReadBuffer ); |
|
176 if( r != KErrNone ) |
|
177 { |
|
178 test.Printf( _L("... FAIL: read failed (%d) at offset 0x%x\n"), r, offset ); |
|
179 test( KErrNone == r ); |
|
180 } |
|
181 test( iReadBuffer.Length() == readBufLen ); |
|
182 |
|
183 const TUint32* p = (const TUint32*)iReadBuffer.Ptr(); |
|
184 for( TInt i = 0; i < readBufLen; i += 4 ) |
|
185 { |
|
186 if( 0xFFFFFFFF != *p ) |
|
187 { |
|
188 failed = ETrue; |
|
189 test.Printf( _L("... FAILED: byte @ offs=0x%x, read=0x%x, expected=0xFF\n"), |
|
190 offset+i, p[0] ); |
|
191 test(EFalse); |
|
192 } |
|
193 ++p; |
|
194 } |
|
195 offset += readBufLen; |
|
196 remaining -= readBufLen; |
|
197 } |
|
198 } |
|
199 |
|
200 |
|
201 void CBlockManager::InitialiseSequentialBlockAllocator() |
|
202 // |
|
203 // Clears the erase status and resets to block zero |
|
204 // |
|
205 { |
|
206 for( TInt i = 0; i < iBlockCount; i++ ) |
|
207 { |
|
208 iEraseArray[i] = ENotErased; |
|
209 } |
|
210 iNextBlock = 0; |
|
211 } |
|
212 |
|
213 |
|
214 TInt CBlockManager::NextErasedBlock() |
|
215 { |
|
216 if( iNextBlock >= iBlockCount ) |
|
217 { |
|
218 iNextBlock = 0; |
|
219 } |
|
220 |
|
221 if( ENotErased == iEraseArray[iNextBlock] ) |
|
222 { |
|
223 EraseBlock( iNextBlock ); |
|
224 } |
|
225 iEraseArray[iNextBlock] = ENotErased; // assume it is going to be used |
|
226 return iNextBlock; |
|
227 } |
|
228 |
|
229 void CBlockManager::InitialiseDataChunkAllocator() |
|
230 { |
|
231 iDataBlock = NextErasedBlock(); |
|
232 iDataOffset = 0; |
|
233 } |
|
234 |
|
235 |
|
236 TUint CBlockManager::NextErasedDataChunk( TInt aRequiredLength, TInt aMultiple ) |
|
237 // |
|
238 // Request a chunk of erased flash of size aRequiredLength bytes on a |
|
239 // boundary of aMultiple bytes. E,g, to allocate a buffer on 12 bytes length |
|
240 // on a 32-byte boundary, aRequiredLength = 12, aMultiple=12 |
|
241 // |
|
242 // The byte count is rounded up to a multiple of 4 bytes |
|
243 // |
|
244 { |
|
245 aRequiredLength = (aRequiredLength + 3) & ~0x3; |
|
246 |
|
247 TUint chunkBase = ((iDataOffset + aMultiple - 1) / aMultiple) * aMultiple; |
|
248 if( chunkBase > (TUint)iBlockSize || chunkBase + aRequiredLength > (TUint)iBlockSize ) |
|
249 { |
|
250 iDataBlock = NextErasedBlock(); |
|
251 chunkBase = 0; |
|
252 } |
|
253 |
|
254 iDataOffset = ( chunkBase + aRequiredLength + 3) & ~0x3; |
|
255 |
|
256 return BlockAddress( iDataBlock ) + chunkBase; |
|
257 } |
|
258 |
|
259 |
|
260 |
|
261 inline TInt CBlockManager::BlockCount() const |
|
262 { |
|
263 return iBlockCount; |
|
264 } |
|
265 |
|
266 inline TInt CBlockManager::BlockSize() const |
|
267 { |
|
268 return iBlockSize; |
|
269 } |
|
270 |
|
271 inline TInt CBlockManager::FlashSize() const |
|
272 { |
|
273 return iBlockSize * iBlockCount; |
|
274 } |
|
275 |
|
276 inline TUint CBlockManager::BlockAddress( TInt aBlockNumber ) const |
|
277 { |
|
278 return (TUint)aBlockNumber * (TUint)iBlockSize; |
|
279 } |
|
280 |
|
281 |
|
282 // ********************************************************************** |
|
283 // Implementation of CWriteTest |
|
284 |
|
285 CWriteTest::~CWriteTest() |
|
286 { |
|
287 if( iDriveOpened ) |
|
288 { |
|
289 iDrive.Disconnect(); |
|
290 } |
|
291 |
|
292 delete iBlocks; |
|
293 delete iSimpleWriter; |
|
294 delete iThreadWriter; |
|
295 } |
|
296 |
|
297 |
|
298 void CWriteTest::CreateL() |
|
299 { |
|
300 // |
|
301 // Load the device drivers |
|
302 // |
|
303 TInt r; |
|
304 #ifndef SKIP_PDD_LOAD |
|
305 test.Printf( _L("Loading %S\n"), &KLfsDriverName ); |
|
306 r = User::LoadPhysicalDevice( KLfsDriverName ); |
|
307 test( KErrNone == r || KErrAlreadyExists == r ); |
|
308 #endif |
|
309 |
|
310 #ifdef UNMOUNT_DRIVE |
|
311 RFs fs; |
|
312 test( KErrNone == fs.Connect() ); |
|
313 #if 0 |
|
314 // XXX - not EKA2 |
|
315 test( KErrNone == fs.SetDefaultPath( _L("Z:\\") ) ); |
|
316 #endif |
|
317 TFullName name; |
|
318 fs.FileSystemName( name, KLffsLogicalDriveNumber ); |
|
319 if( name.Length() > 0 ) |
|
320 { |
|
321 test.Printf( _L("Unmounting drive") ); |
|
322 test( KErrNone == fs.DismountFileSystem( _L("Lffs"), KLffsLogicalDriveNumber) ); |
|
323 User::After( 2000000 ); |
|
324 test.Printf( _L("Drive unmounted") ); |
|
325 } |
|
326 fs.Close(); |
|
327 #endif |
|
328 |
|
329 // |
|
330 // Open a TBusLogicalDevice to it |
|
331 // |
|
332 test.Printf( _L("Opening media channel\n") ); |
|
333 TBool changedFlag = EFalse; |
|
334 r = iDrive.Connect( KDriveNumber, changedFlag ); |
|
335 User::LeaveIfError( r ); |
|
336 iDriveOpened = ETrue; |
|
337 |
|
338 // |
|
339 // Initialise the block manager |
|
340 // |
|
341 iBlocks = new(ELeave) CBlockManager( iDrive, *this ); |
|
342 iBlocks->CreateL(); |
|
343 |
|
344 // |
|
345 // Create a dummy thread that we can use to force |
|
346 // other-thread write operations |
|
347 // |
|
348 #if 0 |
|
349 test( KErrNone == iDummyThread.Create( _L("DUMMY"), DummyThread, 256, KMinHeapSize, KMinHeapSize, NULL ) ); |
|
350 #else |
|
351 test( KErrNone == iDummyThread.Create( _L("DUMMY"), DummyThread, KDefaultStackSize, KMinHeapSize, KMinHeapSize, NULL ) ); |
|
352 #endif |
|
353 test.Printf( _L("Main thread handle=%d; dummy thread handle=%d"), |
|
354 RThread().Handle(), DummyThreadHandle() ); |
|
355 |
|
356 // |
|
357 // Create the writer classes |
|
358 // |
|
359 iSimpleWriter = new(ELeave) TSimpleWrite( *this ); |
|
360 iThreadWriter = new(ELeave) TThreadWrite( *this ); |
|
361 |
|
362 // |
|
363 // Seed the pseudo-random number generator |
|
364 // |
|
365 iRandom.SetSeed( KRandomSeed1 ); |
|
366 |
|
367 |
|
368 test.Printf( _L("CWriteTest::CreateL complete\n") ); |
|
369 } |
|
370 |
|
371 |
|
372 TInt CWriteTest::DummyThread( TAny* /* aParam */ ) |
|
373 // |
|
374 // Thread does nothing at all |
|
375 // |
|
376 { |
|
377 for(;;) |
|
378 { |
|
379 User::WaitForAnyRequest(); // just block |
|
380 } |
|
381 } |
|
382 |
|
383 void CWriteTest::CreateRandomData( TDes8& aDestBuf, TInt aLength ) |
|
384 // |
|
385 // Fills supplied descriptor with aLength bytes of pseudo-random test data |
|
386 // |
|
387 { |
|
388 aDestBuf.SetLength( aLength ); |
|
389 TUint32* p = (TUint32*)aDestBuf.Ptr(); |
|
390 for( TInt j = aLength/4; j > 0 ; j-- ) |
|
391 { |
|
392 *p++ = iRandom.Next(); |
|
393 } |
|
394 |
|
395 if( aLength & 0x3 ) |
|
396 { |
|
397 TUint8* q = (TUint8*)p; |
|
398 for( TInt k = aLength & 3; k > 0; k-- ) |
|
399 { |
|
400 *q++ = (TUint8)iRandom.Next(); |
|
401 } |
|
402 } |
|
403 } |
|
404 |
|
405 |
|
406 TBool CWriteTest::CheckOnes( TUint aFlashOffset, TInt aLength ) |
|
407 // |
|
408 // Checks that aLength bytes of data from offset aFlashOffset |
|
409 // all contain 0xFF |
|
410 // |
|
411 { |
|
412 TUint offset = aFlashOffset; |
|
413 |
|
414 TBool failed = EFalse; |
|
415 const TInt readBufLen = iReadBuffer.MaxLength(); |
|
416 |
|
417 for( TInt remaining = aLength; remaining > 0 && !failed ;) |
|
418 { |
|
419 TInt readLen = Min( remaining, readBufLen ); |
|
420 TInt r = iDrive.Read( offset, readLen, iReadBuffer ); |
|
421 if( r != KErrNone ) |
|
422 { |
|
423 test.Printf( _L("... FAIL: read failed (%d) at offset 0x%x\n"), r, offset ); |
|
424 test( KErrNone == r ); |
|
425 } |
|
426 test( iReadBuffer.Length() == readLen ); |
|
427 |
|
428 const TUint8* p = iReadBuffer.Ptr(); |
|
429 for( TInt i = 0; i < readLen; ++i ) |
|
430 { |
|
431 if( 0xFF != *p ) |
|
432 { |
|
433 failed = ETrue; |
|
434 test.Printf( _L("... FAILED: byte @ offs=0x%x, read=0x%x, expected=0xFF\n"), |
|
435 offset+i, p[0] ); |
|
436 break; |
|
437 } |
|
438 ++p; |
|
439 } |
|
440 offset += readLen; |
|
441 remaining -= readLen; |
|
442 } |
|
443 |
|
444 return !failed; |
|
445 } |
|
446 |
|
447 |
|
448 TBool CWriteTest::CompareAgainstFlash( TInt aFlashOffset, TInt aLength, const TDesC8& aDes, TInt aDescOffset ) |
|
449 // |
|
450 // Checks that the data in aDes matches that in the Flash at position |
|
451 // aFlashOffset. |
|
452 // The test starts at offset aDescOffset in aSampleData. aLength bytes |
|
453 // are tested. |
|
454 // |
|
455 { |
|
456 __ASSERT_ALWAYS( aDescOffset + aLength <= aDes.Length(), Panic( EPanicCompareDescOverflow ) ); |
|
457 TInt dataLength = aLength; |
|
458 const TUint8* srcPtr = aDes.Ptr() + aDescOffset; |
|
459 |
|
460 TUint offset = aFlashOffset; |
|
461 |
|
462 TBool failed = EFalse; |
|
463 const TInt readBufLen = iReadBuffer.MaxLength(); |
|
464 |
|
465 while( (dataLength > 0) && !failed ) |
|
466 { |
|
467 TInt len = Min( dataLength, readBufLen ); |
|
468 TInt r = iDrive.Read( offset, len, iReadBuffer ); |
|
469 if( r != KErrNone ) |
|
470 { |
|
471 test.Printf( _L("... FAIL: read failed (%d) at offset 0x%x\n"), r, offset ); |
|
472 test( KErrNone == r ); |
|
473 } |
|
474 test( iReadBuffer.Length() == len ); |
|
475 |
|
476 if( 0 != Mem::Compare( srcPtr, len, iReadBuffer.Ptr(), len ) ) |
|
477 { |
|
478 test.Printf( _L("... FAIL: mismatch around offset 0x%x\n"), offset ); |
|
479 failed = ETrue; |
|
480 } |
|
481 offset += len; |
|
482 dataLength -= len; |
|
483 srcPtr += len; |
|
484 } |
|
485 |
|
486 return !failed; |
|
487 } |
|
488 |
|
489 TBool CWriteTest::CompareAgainstFlash( TInt aFlashOffset, const TDesC8& aDes ) |
|
490 // |
|
491 // Checks that the data in aDes matches that in the Flash at position |
|
492 // aFlashOffset. |
|
493 // aDes->Length() bytes are tested. |
|
494 // |
|
495 { |
|
496 return CompareAgainstFlash( aFlashOffset, aDes.Length(), aDes, 0 ); |
|
497 } |
|
498 |
|
499 |
|
500 void CWriteTest::SimpleWriteTest() |
|
501 { |
|
502 test.Next( _L("Simple write test, simple write function") ); |
|
503 DoSimpleWriteTest( *iSimpleWriter ); |
|
504 } |
|
505 |
|
506 void CWriteTest::SimpleThreadWriteTest() |
|
507 { |
|
508 test.Next( _L("Simple write test, thread write function") ); |
|
509 DoSimpleWriteTest( *iThreadWriter ); |
|
510 } |
|
511 |
|
512 |
|
513 void CWriteTest::DoSimpleWriteTest( MGeneralizedWrite& aWriter ) |
|
514 // |
|
515 // Writes some random test data to the start of a block, checks that |
|
516 // it is written correctly and that the source data isn't modified |
|
517 // |
|
518 { |
|
519 TInt blockNo = iBlocks->NextErasedBlock(); |
|
520 TUint blockBase = iBlocks->BlockAddress( blockNo ); |
|
521 |
|
522 TBuf8<512> randomData; |
|
523 CreateRandomData( randomData, randomData.MaxLength() ); |
|
524 |
|
525 TBuf8<512> randomDataDuplicate; |
|
526 randomDataDuplicate.Copy( randomData ); |
|
527 test( randomDataDuplicate == randomData ); |
|
528 |
|
529 TBuf8<sizeof(TPtr)> ptrCopy; // used to take copies of descriptors |
|
530 |
|
531 // |
|
532 // Write using a constant descriptor TPtrC |
|
533 // |
|
534 test.Printf( _L("Write using TPtrC") ); |
|
535 TPtrC8 ptrC( randomData ); |
|
536 ptrCopy.Copy( (TUint8*)&ptrC, sizeof(ptrC) ); |
|
537 |
|
538 aWriter.CheckedWrite( blockBase + 0, ptrC ); |
|
539 |
|
540 test.Printf( _L("Check descriptor not modified by write function") ); |
|
541 test( 0 == Mem::Compare( (TUint8*)&ptrC, sizeof(ptrC), ptrCopy.Ptr(), sizeof(ptrC) ) ); |
|
542 |
|
543 test.Printf( _L("Check data not modified by write function") ); |
|
544 test( randomDataDuplicate == randomData ); |
|
545 |
|
546 // |
|
547 // Write using a modifiable descriptor TPtr |
|
548 // |
|
549 test.Printf( _L("Write using TPtr") ); |
|
550 TPtr8 ptr( (TUint8*)randomData.Ptr(), randomData.Length(), randomData.Length() ); |
|
551 ptrCopy.Copy( (TUint8*)&ptr, sizeof(ptr) ); |
|
552 |
|
553 aWriter.CheckedWrite( blockBase + 1024, ptr ); |
|
554 |
|
555 test.Printf( _L("Check descriptor not modified by write function") ); |
|
556 test( 0 == Mem::Compare( (TUint8*)&ptr, sizeof(ptr), ptrCopy.Ptr(), sizeof(ptr) ) ); |
|
557 |
|
558 test.Printf( _L("Check data not modified by write function") ); |
|
559 test( randomDataDuplicate == randomData ); |
|
560 |
|
561 // |
|
562 // Write using a modifiable descriptor TBuf |
|
563 // |
|
564 test.Printf( _L("Write using TBuf") ); |
|
565 |
|
566 aWriter.CheckedWrite( blockBase + 2048, randomData ); |
|
567 |
|
568 test.Printf( _L("Check descriptor not modified by write function") ); |
|
569 test( ptrC.Ptr() == randomData.Ptr() ); |
|
570 test( 512 == randomData.Length() ); |
|
571 test( 512 == randomData.MaxLength() ); |
|
572 |
|
573 test.Printf( _L("Check data not modified by write function") ); |
|
574 test( randomDataDuplicate == randomData ); |
|
575 |
|
576 // |
|
577 // Read the data back and check it matches |
|
578 // |
|
579 test.Printf( _L("Reading data back with TBusLocalDrive::Read") ); |
|
580 test( KErrNone == iDrive.Read( blockBase + 0, 512, randomDataDuplicate ) ); |
|
581 test( randomDataDuplicate == randomData ); |
|
582 test( KErrNone == iDrive.Read( blockBase + 1024, 512, randomDataDuplicate ) ); |
|
583 test( randomDataDuplicate == randomData ); |
|
584 test( KErrNone == iDrive.Read( blockBase + 2048, 512, randomDataDuplicate ) ); |
|
585 test( randomDataDuplicate == randomData ); |
|
586 } |
|
587 |
|
588 |
|
589 |
|
590 void CWriteTest::AlignedWriteTest() |
|
591 { |
|
592 test.Next( _L("Aligned write test, simple write function") ); |
|
593 DoAlignedWriteTest( *iSimpleWriter ); |
|
594 } |
|
595 |
|
596 void CWriteTest::AlignedThreadWriteTest() |
|
597 { |
|
598 test.Next( _L("Aligned write test, thread write function") ); |
|
599 DoAlignedWriteTest( *iThreadWriter ); |
|
600 } |
|
601 |
|
602 |
|
603 void CWriteTest::DoAlignedWriteTest( MGeneralizedWrite& aWriter ) |
|
604 // |
|
605 // Writes data of various lengths to word-aligned addresses |
|
606 // |
|
607 { |
|
608 iBlocks->InitialiseDataChunkAllocator(); |
|
609 |
|
610 TBuf8<512> data; |
|
611 |
|
612 _LIT( KWriteMsg, " writing %d bytes @0x%x" ); |
|
613 |
|
614 test.Printf( _L("Testing small writes") ); |
|
615 |
|
616 for( TInt length = 1; length < 16; length++ ) |
|
617 { |
|
618 CreateRandomData( data, length ); |
|
619 |
|
620 // get a 32-byte data chunk on a word boundary |
|
621 TUint offset = iBlocks->NextErasedDataChunk( 32, 4 ); |
|
622 |
|
623 test.Printf( KWriteMsg, length, offset ); |
|
624 aWriter.CheckedWrite( offset, data ); |
|
625 // check that the section after the data still contains all ones |
|
626 test( CheckOnes( offset + length, 32 - length ) ); |
|
627 } |
|
628 |
|
629 |
|
630 test.Printf( _L("Testing large writes") ); |
|
631 for( TInt length = 512-32; length <= 512 ; length++ ) |
|
632 { |
|
633 CreateRandomData( data, length ); |
|
634 |
|
635 // get a 544-byte data chunk on a word boundary |
|
636 TUint offset = iBlocks->NextErasedDataChunk( 544, 4 ); |
|
637 |
|
638 test.Printf( KWriteMsg, length, offset ); |
|
639 aWriter.CheckedWrite( offset, data ); |
|
640 |
|
641 // check that the section after the data still contains all ones |
|
642 test( CheckOnes( offset + length, 544 - length ) ); |
|
643 } |
|
644 } |
|
645 |
|
646 |
|
647 |
|
648 |
|
649 void CWriteTest::UnalignedWriteTest() |
|
650 { |
|
651 test.Next( _L("Unaligned write test, simple write function") ); |
|
652 DoUnalignedWriteTest( *iSimpleWriter ); |
|
653 } |
|
654 |
|
655 void CWriteTest::UnalignedThreadWriteTest() |
|
656 { |
|
657 test.Next( _L("Unaligned write test, thread write function") ); |
|
658 DoUnalignedWriteTest( *iThreadWriter ); |
|
659 } |
|
660 |
|
661 |
|
662 void CWriteTest::DoUnalignedWriteTest( MGeneralizedWrite& aWriter ) |
|
663 // |
|
664 // Tests writing to unaligned addresses. "Unaligned" here means |
|
665 // addresses that are not on a word boundary. |
|
666 // |
|
667 { |
|
668 TBuf8<32> data; |
|
669 |
|
670 _LIT( KWriteMsg, " writing 32 bytes @0x%x" ); |
|
671 |
|
672 |
|
673 for( TInt offset = 1; offset < 32; offset++ ) |
|
674 { |
|
675 CreateRandomData( data, data.MaxLength() ); |
|
676 |
|
677 // |
|
678 // get a 64-byte data chunk on a 256-byte boundary, then |
|
679 // start the write at <offset> bytes into this buffer |
|
680 // |
|
681 TUint dataChunk = iBlocks->NextErasedDataChunk( 64, 256 ); |
|
682 |
|
683 test.Printf( KWriteMsg, dataChunk + offset ); |
|
684 aWriter.CheckedWrite( dataChunk + offset, data ); |
|
685 |
|
686 _LIT( KBeforeMsg, " checking unused portion before data" ); |
|
687 test.Printf( KBeforeMsg ); |
|
688 test( CheckOnes( dataChunk, offset ) ); |
|
689 |
|
690 // check that the section after the data still contains all ones |
|
691 _LIT( KAfterMsg, " checking unused portion after data" ); |
|
692 test.Printf( KAfterMsg ); |
|
693 test( CheckOnes( dataChunk + offset + data.Length(), 64 - offset - data.Length() ) ); |
|
694 } |
|
695 } |
|
696 |
|
697 |
|
698 |
|
699 void CWriteTest::OffsetDescriptorAlignedWriteTest() |
|
700 // |
|
701 // Tests writing using an offset into the source data buffer. Writes |
|
702 // are done to word-aligned destination addresses. |
|
703 // |
|
704 { |
|
705 test.Next( _L("Offset-desc write test, aligned dest address") ); |
|
706 |
|
707 TBuf8<64> data; |
|
708 |
|
709 _LIT( KWriteMsg, " writing 32 bytes from offset %d to @0x%x" ); |
|
710 |
|
711 // CreateRandomData( data, data.MaxLength() ); |
|
712 data.SetLength(64); |
|
713 for( TInt i = 0; i < 64; i++ ) |
|
714 { |
|
715 data[i] = i; |
|
716 } |
|
717 |
|
718 for( TInt descOffset = 1; descOffset < 32; descOffset++ ) |
|
719 { |
|
720 // |
|
721 // Get a 32-byte data chunk on a word boundary. |
|
722 // |
|
723 TUint dataChunk = iBlocks->NextErasedDataChunk( 32, 4 ); |
|
724 |
|
725 test.Printf( KWriteMsg, descOffset, dataChunk ); |
|
726 iThreadWriter->CheckedThreadWrite( dataChunk, 32, data, descOffset ); |
|
727 |
|
728 // |
|
729 // Read the data back out and check it matches |
|
730 // |
|
731 _LIT( KReadBackMsg, "Reading back data" ); |
|
732 test.Printf( KReadBackMsg ); |
|
733 TBuf8<32> readData; |
|
734 iDrive.Read( dataChunk, 32, readData ); |
|
735 TPtrC8 ptr( data.Ptr() + descOffset, 32 ); |
|
736 test( ptr == readData ); |
|
737 } |
|
738 } |
|
739 |
|
740 |
|
741 void CWriteTest::OffsetDescriptorUnalignedWriteTest() |
|
742 // |
|
743 // This is a variation of OffsetDescriptorAlignedWriteTest that |
|
744 // also writes to non-word-aligned destionation addresses. |
|
745 // |
|
746 { |
|
747 test.Next( _L("Offset-desc write test, unaligned dest address") ); |
|
748 |
|
749 TBuf8<64> data; |
|
750 |
|
751 _LIT( KWriteMsg, " writing 32 bytes from offset %d to @0x%x" ); |
|
752 |
|
753 CreateRandomData( data, data.MaxLength() ); |
|
754 |
|
755 for( TInt descOffset = 1; descOffset < 32; descOffset++ ) |
|
756 { |
|
757 for( TInt unalign = 1; unalign < 4; unalign++ ) |
|
758 { |
|
759 // |
|
760 // Get a 40-byte data chunk on a word boundary. |
|
761 // |
|
762 TUint dataChunk = iBlocks->NextErasedDataChunk( 40, 4 ); |
|
763 TUint destOffset = dataChunk + unalign; |
|
764 |
|
765 test.Printf( KWriteMsg, descOffset, destOffset ); |
|
766 iThreadWriter->CheckedThreadWrite( destOffset, 32, data, descOffset ); |
|
767 |
|
768 // |
|
769 // Read the data back out and check it matches |
|
770 // |
|
771 _LIT( KReadBackMsg, "Reading back data" ); |
|
772 test.Printf( KReadBackMsg ); |
|
773 TBuf8<32> readData; |
|
774 iDrive.Read( destOffset, 32, readData ); |
|
775 TPtrC8 ptr( data.Ptr() + descOffset, 32 ); |
|
776 test( ptr == readData ); |
|
777 } |
|
778 } |
|
779 } |
|
780 |
|
781 |
|
782 void CWriteTest::OffsetDescriptorCurrentThreadAlignedWriteTest() |
|
783 // |
|
784 // Tests writing using an offset into the source data buffer. Writes |
|
785 // are done to word-aligned destination addresses. This uses the |
|
786 // thread variant of the write function but passes the handle |
|
787 // of this thread. |
|
788 // |
|
789 { |
|
790 test.Next( _L("Offset-desc write test, current thread, aligned dest address") ); |
|
791 |
|
792 TBuf8<64> data; |
|
793 |
|
794 _LIT( KWriteMsg, " writing 32 bytes from offset %d to @0x%x" ); |
|
795 |
|
796 // CreateRandomData( data, data.MaxLength() ); |
|
797 data.SetLength(64); |
|
798 for( TInt i = 0; i < 64; i++ ) |
|
799 { |
|
800 data[i] = i; |
|
801 } |
|
802 |
|
803 for( TInt descOffset = 1; descOffset < 32; descOffset++ ) |
|
804 { |
|
805 // |
|
806 // Get a 32-byte data chunk on a word boundary. |
|
807 // |
|
808 TUint dataChunk = iBlocks->NextErasedDataChunk( 32, 4 ); |
|
809 |
|
810 test.Printf( KWriteMsg, descOffset, dataChunk ); |
|
811 iThreadWriter->CurrentThreadCheckedThreadWrite( dataChunk, 32, data, descOffset ); |
|
812 |
|
813 // |
|
814 // Read the data back out and check it matches |
|
815 // |
|
816 _LIT( KReadBackMsg, "Reading back data" ); |
|
817 test.Printf( KReadBackMsg ); |
|
818 TBuf8<32> readData; |
|
819 iDrive.Read( dataChunk, 32, readData ); |
|
820 TPtrC8 ptr( data.Ptr() + descOffset, 32 ); |
|
821 test( ptr == readData ); |
|
822 } |
|
823 } |
|
824 |
|
825 |
|
826 void CWriteTest::OffsetDescriptorCurrentThreadUnalignedWriteTest() |
|
827 // |
|
828 // This is a variation of OffsetDescriptorCurrentThreadAlignedWriteTest |
|
829 // that also writes to non-word-aligned destionation addresses. |
|
830 // |
|
831 { |
|
832 test.Next( _L("Offset-desc write test, current thread, unaligned dest address") ); |
|
833 |
|
834 TBuf8<64> data; |
|
835 |
|
836 _LIT( KWriteMsg, " writing 32 bytes from offset %d to @0x%x" ); |
|
837 |
|
838 CreateRandomData( data, data.MaxLength() ); |
|
839 |
|
840 for( TInt descOffset = 1; descOffset < 32; descOffset++ ) |
|
841 { |
|
842 for( TInt unalign = 1; unalign < 4; unalign++ ) |
|
843 { |
|
844 // |
|
845 // Get a 40-byte data chunk on a word boundary. |
|
846 // |
|
847 TUint dataChunk = iBlocks->NextErasedDataChunk( 40, 4 ); |
|
848 TUint destOffset = dataChunk + unalign; |
|
849 |
|
850 test.Printf( KWriteMsg, descOffset, destOffset ); |
|
851 iThreadWriter->CurrentThreadCheckedThreadWrite( destOffset, 32, data, descOffset ); |
|
852 |
|
853 // |
|
854 // Read the data back out and check it matches |
|
855 // |
|
856 _LIT( KReadBackMsg, "Reading back data" ); |
|
857 test.Printf( KReadBackMsg ); |
|
858 TBuf8<32> readData; |
|
859 iDrive.Read( destOffset, 32, readData ); |
|
860 TPtrC8 ptr( data.Ptr() + descOffset, 32 ); |
|
861 test( ptr == readData ); |
|
862 } |
|
863 } |
|
864 } |
|
865 |
|
866 |
|
867 |
|
868 void CWriteTest::JoinedWriteTest() |
|
869 // |
|
870 // Makes two consecutive writes. Checks that the complete |
|
871 // data block was written correctly. The data is written within |
|
872 // a 64-byte window and the join position is moved along to each |
|
873 // possible location |
|
874 { |
|
875 |
|
876 test.Next( _L("Joined write test, simple writes") ); |
|
877 |
|
878 // |
|
879 // Reinitialise the chunk allocator |
|
880 // |
|
881 iBlocks->InitialiseDataChunkAllocator(); |
|
882 |
|
883 for( TInt join = 1; join < 63; join++ ) |
|
884 { |
|
885 TBuf8<64> fullData; |
|
886 CreateRandomData( fullData, fullData.MaxLength() ); |
|
887 |
|
888 // |
|
889 // Create two TPtrC8s to the two parts of the data |
|
890 // |
|
891 TPtrC8 first( fullData.Ptr(), join ); |
|
892 TPtrC8 second( fullData.Ptr() + join, fullData.MaxLength() - join ); |
|
893 __ASSERT_ALWAYS( first.Length() + second.Length() == 64, Panic( EPanicJoinMaths ) ); |
|
894 |
|
895 // |
|
896 // Get a location in the Flash to write to |
|
897 // |
|
898 TUint dataChunk = iBlocks->NextErasedDataChunk( 64, 64 ); |
|
899 |
|
900 // |
|
901 // Write the two halves of the data |
|
902 // |
|
903 _LIT( KWriteMsg, " writing %d bytes @ 0x%x and %d bytes @ 0x%x" ); |
|
904 test.Printf( KWriteMsg, first.Length(), dataChunk, |
|
905 second.Length(), dataChunk + first.Length() ); |
|
906 test( KErrNone == iDrive.Write( dataChunk, first ) ); |
|
907 test( KErrNone == iDrive.Write( dataChunk + first.Length(), second ) ); |
|
908 |
|
909 // |
|
910 // Compare the data |
|
911 // |
|
912 _LIT( KCompareMsg, " comparing data against Flash" ); |
|
913 test.Printf( KCompareMsg ); |
|
914 test( CompareAgainstFlash( dataChunk, fullData ) ); |
|
915 } |
|
916 } |
|
917 |
|
918 |
|
919 void CWriteTest::JoinedThreadWriteTest() |
|
920 // |
|
921 // Makes two consecutive writes. Checks that the complete |
|
922 // data block was written correctly. The data is written within |
|
923 // a 64-byte window and the join position is moved along to each |
|
924 // possible location |
|
925 // |
|
926 // This is similar to JoinedWriteTest except that the thread write |
|
927 // function is used with a descriptor offset to chop up the |
|
928 // source data |
|
929 // |
|
930 { |
|
931 |
|
932 test.Next( _L("Joined write test, thread writes") ); |
|
933 |
|
934 // |
|
935 // Reinitialise the chunk allocator |
|
936 // |
|
937 iBlocks->InitialiseDataChunkAllocator(); |
|
938 |
|
939 for( TInt join = 1; join < 63; join++ ) |
|
940 { |
|
941 TBuf8<64> fullData; |
|
942 CreateRandomData( fullData, fullData.MaxLength() ); |
|
943 |
|
944 // |
|
945 // Get a location in the Flash to write to |
|
946 // |
|
947 TUint dataChunk = iBlocks->NextErasedDataChunk( 64, 64 ); |
|
948 |
|
949 // |
|
950 // Write the two halves of the data |
|
951 // |
|
952 _LIT( KWriteMsg, " writing %d bytes @ 0x%x and %d bytes @ 0x%x" ); |
|
953 test.Printf( KWriteMsg, join, dataChunk, 64 - join, dataChunk + join ); |
|
954 #if 0 |
|
955 test( KErrNone == iDrive.Write( dataChunk, join, &fullData, DummyThreadHandle(), 0 ) ); |
|
956 test( KErrNone == iDrive.Write( dataChunk + join, 64-join, &fullData, DummyThreadHandle(), join ) ); |
|
957 #else |
|
958 test( KErrNone == iDrive.Write( dataChunk, join, &fullData, KLocalMessageHandle, 0 ) ); |
|
959 test( KErrNone == iDrive.Write( dataChunk + join, 64-join, &fullData, KLocalMessageHandle, join ) ); |
|
960 #endif |
|
961 |
|
962 |
|
963 // |
|
964 // Compare the data |
|
965 // |
|
966 _LIT( KCompareMsg, " comparing data against Flash" ); |
|
967 test.Printf( KCompareMsg ); |
|
968 test( CompareAgainstFlash( dataChunk, fullData ) ); |
|
969 } |
|
970 } |
|
971 |
|
972 |
|
973 |
|
974 void CWriteTest::SingleBitOverwriteTest() |
|
975 // |
|
976 // Tests overwriting single bits within a byte. a 32-byte |
|
977 // section of Flash is filled with data, with one byte initially |
|
978 // 0xFF. A bit is then written to zero and the whole data block |
|
979 // is verified. |
|
980 // |
|
981 { |
|
982 test.Next( _L("Single bit overwrite test") ); |
|
983 |
|
984 iBlocks->InitialiseDataChunkAllocator(); |
|
985 |
|
986 for( TInt testByteOffset = 0; testByteOffset < 32; testByteOffset++ ) |
|
987 { |
|
988 for( TInt testBitNumber = 0; testBitNumber < 8; testBitNumber++ ) |
|
989 { |
|
990 TBuf8<32> data; |
|
991 CreateRandomData( data, data.MaxLength() ); |
|
992 data[ testByteOffset ] = 0xFF; // force test byte to 0xFF |
|
993 |
|
994 TUint flashOffset = iBlocks->NextErasedDataChunk( 32, 32 ); |
|
995 |
|
996 _LIT( KWriteMsg, "writing test data @0x%x, test byte offset=%d; test bit #%d"); |
|
997 test.Printf( KWriteMsg, flashOffset, testByteOffset, testBitNumber ); |
|
998 |
|
999 iSimpleWriter->CheckedWrite( flashOffset, data ); |
|
1000 |
|
1001 // clear the test bit |
|
1002 TBuf8<1> byte; |
|
1003 byte.SetLength(1); |
|
1004 byte[0] = ~(1 << testBitNumber); |
|
1005 data[ testByteOffset ] = byte[0]; |
|
1006 |
|
1007 iSimpleWriter->CheckedWrite( flashOffset + testByteOffset, byte ); |
|
1008 |
|
1009 // check that the contents of the Flash matches the buffer |
|
1010 test( CompareAgainstFlash( flashOffset, data ) ); |
|
1011 } |
|
1012 } |
|
1013 } |
|
1014 |
|
1015 void CWriteTest::TwoBitOverwriteTest() |
|
1016 // |
|
1017 // Tests overwriting two bits within a byte. a 32-byte |
|
1018 // section of Flash is filled with data, with one byte initially |
|
1019 // 0xFF. Two bits are then written to zero and the whole data block |
|
1020 // is verified. |
|
1021 // |
|
1022 { |
|
1023 static const TUint pattConv[16] = |
|
1024 { |
|
1025 // used to create a string representation of binary value |
|
1026 0x0000, 0x0001, 0x0010, 0x0011, 0x0100, 0x0101, 0x0110, 0x0111, |
|
1027 0x1000, 0x1001, 0x1010, 0x1011, 0x1100, 0x1101, 0x1110, 0x1111 |
|
1028 }; |
|
1029 test.Next( _L("Two bit overwrite test") ); |
|
1030 |
|
1031 for( TInt testByteOffset = 0; testByteOffset < 32; testByteOffset++ ) |
|
1032 { |
|
1033 for( TInt testBitJ = 0; testBitJ < 7; testBitJ++ ) |
|
1034 { |
|
1035 for( TInt testBitK = testBitJ+1; testBitK < 8; testBitK++ ) |
|
1036 { |
|
1037 TBuf8<32> data; |
|
1038 CreateRandomData( data, data.MaxLength() ); |
|
1039 data[ testByteOffset ] = 0xFF; // force test byte to 0xFF |
|
1040 |
|
1041 TUint flashOffset = iBlocks->NextErasedDataChunk( 32, 32 ); |
|
1042 |
|
1043 TUint8 testPattern = ~((1 << testBitJ) | (1 << testBitK)); |
|
1044 |
|
1045 _LIT( KWriteMsg, "writing test data @0x%x, test byte offset=%d; test pattern = %04x%04x"); |
|
1046 test.Printf( KWriteMsg, flashOffset, testByteOffset, |
|
1047 pattConv[ testPattern >> 4 ], pattConv[ testPattern&0xF ] ); |
|
1048 |
|
1049 iSimpleWriter->CheckedWrite( flashOffset, data ); |
|
1050 |
|
1051 TBuf8<1> byte; |
|
1052 byte.SetLength(1); |
|
1053 byte[0] = testPattern; |
|
1054 data[ testByteOffset ] = testPattern; |
|
1055 |
|
1056 iSimpleWriter->CheckedWrite( flashOffset + testByteOffset, byte ); |
|
1057 |
|
1058 // check that the contents of the Flash matches the buffer |
|
1059 test( CompareAgainstFlash( flashOffset, data ) ); |
|
1060 } |
|
1061 } |
|
1062 } |
|
1063 } |
|
1064 |
|
1065 |
|
1066 void CWriteTest::RunSimulationTest() |
|
1067 // |
|
1068 // A simulation of the way the LFFS filesystem will use a Flash block |
|
1069 // Alternately writes 24 bytes to bottom of block, 512 bytes to top, |
|
1070 // clears a bit in the 24-byte block. Repeats until block is full. |
|
1071 // |
|
1072 { |
|
1073 test.Next( _L("Simulation test") ); |
|
1074 |
|
1075 TUint blockBase = iBlocks->BlockAddress( iBlocks->NextErasedBlock() ); |
|
1076 |
|
1077 TUint lowAddress = blockBase; |
|
1078 TUint highAddress = blockBase + iBlocks->BlockSize() - 512; |
|
1079 |
|
1080 TBuf8<24> lowData; |
|
1081 TBuf8<512> highData; |
|
1082 TPtrC8 overwritePtr( lowData.Ptr(), 1 ); |
|
1083 |
|
1084 while( lowAddress + 24 < highAddress ) |
|
1085 { |
|
1086 CreateRandomData( lowData, lowData.MaxLength() ); |
|
1087 CreateRandomData( highData, highData.MaxLength() ); |
|
1088 lowData[0] = 0xE7; // just some non-0xFF value |
|
1089 |
|
1090 _LIT( KWriteMsg, "Writing block size 24 @ 0x%x; block size 512 @ 0x%x" ); |
|
1091 test.Printf( KWriteMsg, lowAddress, highAddress ); |
|
1092 |
|
1093 iSimpleWriter->CheckedWrite( lowAddress, lowData ); |
|
1094 iSimpleWriter->Write( highAddress, highData ); |
|
1095 |
|
1096 // Overwrite the byte |
|
1097 lowData[0] = 0xA7; |
|
1098 iSimpleWriter->Write( lowAddress, overwritePtr ); |
|
1099 |
|
1100 test( CompareAgainstFlash( lowAddress, lowData ) ); |
|
1101 test( CompareAgainstFlash( highAddress, highData ) ); |
|
1102 |
|
1103 lowAddress += lowData.Length(); |
|
1104 highAddress -= highData.Length(); |
|
1105 } |
|
1106 } |
|
1107 |
|
1108 |
|
1109 |
|
1110 void CWriteTest::DoTests() |
|
1111 // |
|
1112 // Main test dispatcher |
|
1113 // |
|
1114 { |
|
1115 test.Next( _L("Erasing all blocks") ); |
|
1116 iBlocks->InitialiseSequentialBlockAllocator(); |
|
1117 iBlocks->EraseAllBlocks(); |
|
1118 |
|
1119 // |
|
1120 // Basic tests that we can write data correctly without corrupting |
|
1121 // the source buffer |
|
1122 // |
|
1123 SimpleWriteTest(); |
|
1124 SimpleThreadWriteTest(); |
|
1125 |
|
1126 // |
|
1127 // Test aligned writes of various lengths |
|
1128 // |
|
1129 AlignedWriteTest(); |
|
1130 AlignedThreadWriteTest(); |
|
1131 |
|
1132 // |
|
1133 // Test writing to unaligned locations |
|
1134 // |
|
1135 UnalignedWriteTest(); |
|
1136 UnalignedThreadWriteTest(); |
|
1137 |
|
1138 // |
|
1139 // Test writes with offset into source desriptor |
|
1140 // |
|
1141 OffsetDescriptorCurrentThreadAlignedWriteTest(); |
|
1142 OffsetDescriptorCurrentThreadUnalignedWriteTest(); |
|
1143 OffsetDescriptorAlignedWriteTest(); |
|
1144 OffsetDescriptorUnalignedWriteTest(); |
|
1145 |
|
1146 // |
|
1147 // Test two consecutive writes |
|
1148 // |
|
1149 JoinedWriteTest(); |
|
1150 JoinedThreadWriteTest(); |
|
1151 |
|
1152 // |
|
1153 // Test that we can overwrite bits |
|
1154 // |
|
1155 SingleBitOverwriteTest(); |
|
1156 TwoBitOverwriteTest(); |
|
1157 |
|
1158 // |
|
1159 // A simulation test of LFFS usage |
|
1160 // |
|
1161 RunSimulationTest(); |
|
1162 } |
|
1163 |
|
1164 |
|
1165 |
|
1166 |
|
1167 |
|
1168 |
|
1169 |
|
1170 |
|
1171 |
|
1172 |
|
1173 TInt E32Main() |
|
1174 { |
|
1175 test.Title(); |
|
1176 test.Start(_L("Testing media read operations")); |
|
1177 |
|
1178 CWriteTest writeTest; |
|
1179 TRAPD( ret, writeTest.CreateL() ); |
|
1180 test( KErrNone == ret ); |
|
1181 writeTest.DoTests(); |
|
1182 test.End(); |
|
1183 |
|
1184 return 0; |
|
1185 } |