kerneltest/e32test/lffs/tf_write.cpp
changeset 9 96e5fb8b040d
equal deleted inserted replaced
-1:000000000000 9:96e5fb8b040d
       
     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 	}