1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/lffs/tf_read.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1132 @@
1.4 +// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include <e32std.h>
1.20 +#include <e32std_private.h>
1.21 +#include <e32svr.h>
1.22 +#include <e32test.h>
1.23 +#include "randgen.h"
1.24 +#include "user_config.h"
1.25 +
1.26 +RTest test( _L("TF_READ") );
1.27 +
1.28 +
1.29 +const TInt KTestUserDataSize = 1024;
1.30 +const TInt KBufferGuardSize = 16384;
1.31 +
1.32 +const TInt KMaxWriteLength = 512;
1.33 +
1.34 +const TInt64 KSampleDataRandomSeed = MAKE_TINT64(0x3e000111,0xAFCBDF0F);
1.35 +const TInt64 KRandomTestSeed = MAKE_TINT64(0x90009901,0xABEF1011);
1.36 +
1.37 +enum TPanicNo
1.38 + {
1.39 + EPanicGetDesOverflow,
1.40 + EPanicGetDesInitialOverflow,
1.41 + EPanicCheckOverflow
1.42 + };
1.43 +
1.44 +LOCAL_D void Panic( TPanicNo aPanic )
1.45 + {
1.46 + _LIT( KPanicCat, "TF_READ" );
1.47 + User::Panic( KPanicCat, aPanic );
1.48 + }
1.49 +
1.50 +
1.51 +class CCheckedBuffer : public CBase
1.52 + {
1.53 + public:
1.54 + CCheckedBuffer( TInt auserDataSize, TInt aGuardSize );
1.55 + ~CCheckedBuffer();
1.56 +
1.57 + void CreateL();
1.58 + void InitialiseGuard();
1.59 + TBool CheckGuard( TInt aUserDataLength ) const;
1.60 + TBool CheckGuardAtStartOfUserData( TInt aGuardLength ) const;
1.61 + void GetDes( TPtrC8& aDes ) const;
1.62 + void GetDes( TPtr8& aDes, TInt aInitialLength, TInt aMaxLength ) const;
1.63 +
1.64 +
1.65 + private:
1.66 + CCheckedBuffer();
1.67 +
1.68 + private:
1.69 + TPtr8 iUserData; // pointer to user data area
1.70 + const TInt iUserDataSize;
1.71 + const TInt iGuardSize;
1.72 + TUint8* iAllocCell;
1.73 + };
1.74 +
1.75 +
1.76 +
1.77 +CCheckedBuffer::CCheckedBuffer( TInt aUserDataSize, TInt aGuardSize )
1.78 + : iUserData(0,0), iUserDataSize( aUserDataSize ), iGuardSize( aGuardSize )
1.79 + {
1.80 + }
1.81 +
1.82 +CCheckedBuffer::~CCheckedBuffer()
1.83 + {
1.84 + delete iAllocCell;
1.85 + }
1.86 +
1.87 +void CCheckedBuffer::CreateL()
1.88 + {
1.89 + TInt totalCellSizeRequired = iUserDataSize + (2 * iGuardSize);
1.90 +
1.91 + iAllocCell = (TUint8*)User::AllocL( totalCellSizeRequired );
1.92 +
1.93 + test.Printf( _L("Allocated heap cell for checked buffer\n") );
1.94 +
1.95 + iUserData.Set( iAllocCell + iGuardSize, iUserDataSize, iUserDataSize );
1.96 + }
1.97 +
1.98 +void CCheckedBuffer::GetDes( TPtrC8& aDes ) const
1.99 + //
1.100 + // Create descriptor to the whole user data area in aDes
1.101 + //
1.102 + {
1.103 + aDes.Set( iAllocCell + iGuardSize, iUserDataSize );
1.104 + }
1.105 +
1.106 +void CCheckedBuffer::GetDes( TPtr8& aDes, TInt aInitialLength, TInt aMaxLength ) const
1.107 + //
1.108 + // Create modifiable descriptor to the user data area in aDes,
1.109 + // with a maximum length aMaxLength, and initial length aInitialLength
1.110 + //
1.111 + {
1.112 + __ASSERT_ALWAYS( aMaxLength <= iUserDataSize, Panic(EPanicGetDesOverflow) );
1.113 + __ASSERT_ALWAYS( aInitialLength <= iUserDataSize, Panic(EPanicGetDesInitialOverflow) );
1.114 + aDes.Set( iAllocCell + iGuardSize, aInitialLength, aMaxLength );
1.115 + }
1.116 +
1.117 +
1.118 +void CCheckedBuffer::InitialiseGuard()
1.119 + //
1.120 + // Create the guard regions
1.121 + //
1.122 + {
1.123 + TInt totalCellSize = User::AllocLen( iAllocCell );
1.124 + Mem::Fill( iAllocCell, totalCellSize, 0x5A );
1.125 + }
1.126 +
1.127 +TBool CCheckedBuffer::CheckGuard( TInt aUserDataLength ) const
1.128 + //
1.129 + // Checks that the guard value is still present before the user data
1.130 + // area, and after aUserDataLength bytes of user data
1.131 + //
1.132 + {
1.133 + const TUint8* p = iAllocCell;
1.134 + const TUint8* pUserDataStart = iUserData.Ptr();
1.135 +
1.136 + for( ; p < pUserDataStart; p++ )
1.137 + {
1.138 + if( 0x5a != *p )
1.139 + {
1.140 + return EFalse;
1.141 + }
1.142 + }
1.143 +
1.144 + p = pUserDataStart + aUserDataLength;
1.145 + const TUint8* pEnd = iAllocCell + User::AllocLen( iAllocCell );
1.146 +
1.147 + for( ; p < pEnd; p++ )
1.148 + {
1.149 + if( 0x5a != *p )
1.150 + {
1.151 + return EFalse;
1.152 + }
1.153 + }
1.154 +
1.155 + return ETrue;
1.156 + }
1.157 +
1.158 +
1.159 +TBool CCheckedBuffer::CheckGuardAtStartOfUserData( TInt aGuardLength ) const
1.160 + //
1.161 + // Checks that the first aGuardLength bytes of the user data area
1.162 + // contain the guard value
1.163 + //
1.164 + {
1.165 + const TUint8* p = iUserData.Ptr();
1.166 + const TUint8* pEnd = p + aGuardLength;
1.167 +
1.168 + for( ; p < pEnd; p++ )
1.169 + {
1.170 + if( 0x5a != *p )
1.171 + {
1.172 + return EFalse;
1.173 + }
1.174 + }
1.175 +
1.176 + return ETrue;
1.177 + }
1.178 +
1.179 +
1.180 +
1.181 +class CReadTest : public CBase
1.182 + {
1.183 + public:
1.184 + ~CReadTest();
1.185 +
1.186 + void CreateL();
1.187 +
1.188 + void DoTest();
1.189 +
1.190 + private:
1.191 + static TInt DummyThread( TAny* aParam );
1.192 +
1.193 + void CreateSampleData();
1.194 + static TBool CheckZero( const TPtrC8& aDes );
1.195 + void CreateTestData( TInt aBlockNumber, TBool aEndOfBlock );
1.196 + TBool CompareAgainstFlash( TInt aFlashOffset, const TPtrC8& aDes, TInt aDescOffset );
1.197 +
1.198 + void TestSimpleReads();
1.199 + void TestSimpleThreadReads();
1.200 + void TestUnalignedReads();
1.201 + void TestUnalignedThreadReads();
1.202 + void TestOffsetBufferThreadReads();
1.203 + void TestOffsetBufferUnalignedThreadReads();
1.204 + void TestReadsFromAllBlocks();
1.205 + void TestSimpleScatterReads1();
1.206 + void TestSimpleScatterReads2();
1.207 + void TestScatterGather();
1.208 + void TestReadAcrossBlock();
1.209 +
1.210 + void PerformCheckedRead( TInt aReadPos, TInt aReadLen );
1.211 + void PerformCheckedThreadRead( TInt aReadPos, TInt aReadLen, TInt aDescOffset );
1.212 +
1.213 + private:
1.214 + TInt iFlashSize;
1.215 + TInt iBlockSize;
1.216 + TInt iBlockCount;
1.217 +
1.218 + TBusLocalDrive iDrive;
1.219 + TBool iDriveOpened;
1.220 + TBuf8<512> iReadBuffer;
1.221 +
1.222 + TRandomGenerator iRandom;
1.223 +
1.224 + TBuf8<KTestUserDataSize> iSampleData;
1.225 +
1.226 + CCheckedBuffer* iBuffer;
1.227 +
1.228 + RThread iDummyThread;
1.229 + };
1.230 +
1.231 +CReadTest::~CReadTest()
1.232 + {
1.233 + if( iDriveOpened )
1.234 + {
1.235 + iDrive.Disconnect();
1.236 + }
1.237 + }
1.238 +
1.239 +
1.240 +
1.241 +void CReadTest::CreateL()
1.242 + {
1.243 + //
1.244 + // Load the device drivers
1.245 + //
1.246 + TInt r;
1.247 +
1.248 +#ifndef SKIP_PDD_LOAD
1.249 + test.Printf( _L("Loading %S\n"), &KLfsDriverName );
1.250 + r = User::LoadPhysicalDevice( KLfsDriverName );
1.251 + test( KErrNone == r || KErrAlreadyExists == r );
1.252 +#endif
1.253 +
1.254 +#ifdef UNMOUNT_DRIVE
1.255 + RFs fs;
1.256 + test( KErrNone == fs.Connect() );
1.257 +#if 0 // XXX - API violation on EKA2
1.258 + test( KErrNone == fs.SetDefaultPath( _L("Z:\\") ) );
1.259 +#endif
1.260 + TFullName name;
1.261 + fs.FileSystemName( name, KLffsLogicalDriveNumber );
1.262 + if( name.Length() > 0 )
1.263 + {
1.264 + test.Printf( _L("Unmounting drive") );
1.265 + test( KErrNone == fs.DismountFileSystem( _L("Lffs"), KLffsLogicalDriveNumber) );
1.266 + User::After( 2000000 );
1.267 + test.Printf( _L("Drive unmounted") );
1.268 + }
1.269 +
1.270 + fs.Close();
1.271 +#endif
1.272 +
1.273 + //
1.274 + // Open a TBusLogicalDevice to it
1.275 + //
1.276 + test.Printf( _L("Opening media channel\n") );
1.277 + TBool changedFlag = EFalse;
1.278 + r = iDrive.Connect( KDriveNumber, changedFlag );
1.279 + User::LeaveIfError( r );
1.280 + iDriveOpened = ETrue;
1.281 +
1.282 + //
1.283 + // Get size of Flash drive
1.284 + //
1.285 + TLocalDriveCapsV2Buf info;
1.286 + iDrive.Caps(info);
1.287 + iFlashSize = I64LOW(info().iSize);
1.288 + iBlockSize = info().iEraseBlockSize;
1.289 + iBlockCount = iFlashSize / iBlockSize;
1.290 +
1.291 + test.Printf( _L("Flash size is 0x%x bytes\n"), iFlashSize );
1.292 +
1.293 + //
1.294 + // Create a dummy thread that we can use to force
1.295 + // other-thread write operations
1.296 + //
1.297 +#if 0
1.298 + test( KErrNone == iDummyThread.Create( _L("DUMMY"), DummyThread, 256, KMinHeapSize, KMinHeapSize, NULL ) );
1.299 +#else
1.300 + // XXX TONYL
1.301 + test( KErrNone == iDummyThread.Create( _L("DUMMY"), DummyThread, KDefaultStackSize, KMinHeapSize, KMinHeapSize, NULL ) );
1.302 +
1.303 +// test.Printf( _L("== do it"));
1.304 +// TInt pas = iDummyThread.Create( _L("DUMMY"), DummyThread, KDefaultStackSize, KMinHeapSize, KMinHeapSize, NULL );
1.305 +// test.Printf( _L("CREATE = %d"), pas);
1.306 +// test (pas == KErrNone);
1.307 +#endif
1.308 +#if 1
1.309 + iDummyThread.Resume();
1.310 +#endif
1.311 +
1.312 + //
1.313 + // Create a checked buffer
1.314 + //
1.315 + iBuffer = new(ELeave) CCheckedBuffer( KTestUserDataSize, KBufferGuardSize );
1.316 + iBuffer->CreateL();
1.317 +
1.318 + //
1.319 + // Seed the pseudo-random number generator
1.320 + //
1.321 + iRandom.SetSeed( KSampleDataRandomSeed );
1.322 +
1.323 + test.Printf( _L("CreateL complete\n") );
1.324 + }
1.325 +
1.326 +
1.327 +
1.328 +TInt CReadTest::DummyThread( TAny* /* aParam */ )
1.329 + //
1.330 + // Thread does nothing at all
1.331 + //
1.332 + {
1.333 +#if 1
1.334 + test.Printf( _L("== do it"));
1.335 +#endif
1.336 + for(;;)
1.337 + {
1.338 + User::WaitForAnyRequest(); // just block
1.339 + }
1.340 + }
1.341 +
1.342 +
1.343 +void CReadTest::TestSimpleReads()
1.344 + //
1.345 + // Makes reads of 1 byte to 512 bytes into the start of the
1.346 + // checked buffer and tests that only the expected bytes have changed
1.347 + // This uses the simple read function from TBusLocalDrive, and
1.348 + // reads from an aligned Flash address
1.349 + //
1.350 + {
1.351 + test.Next( _L("Testing simple reads\n") );
1.352 +
1.353 + //
1.354 + // Descriptor to user data area, passed to media driver
1.355 + //
1.356 + TPtr8 des(0,0);
1.357 +
1.358 + for( TInt readLen = 1; readLen <= 512; readLen++ )
1.359 + {
1.360 + test.Printf( _L("Reading %d bytes\n"), readLen );
1.361 +
1.362 + //
1.363 + // Prepare the guard data
1.364 + //
1.365 + iBuffer->InitialiseGuard();
1.366 +
1.367 + //
1.368 + // Set up the descriptor, length=0, maxlen=readLen
1.369 + //
1.370 + iBuffer->GetDes( des, 0, readLen );
1.371 +
1.372 + //
1.373 + // Now read some data into it
1.374 + //
1.375 + test( KErrNone == iDrive.Read( 0, readLen, des ) );
1.376 +
1.377 + //
1.378 + // Check what we got
1.379 + //
1.380 + test( des.Length() == readLen );
1.381 +
1.382 + TPtrC8 newDes;
1.383 +
1.384 + iBuffer->GetDes( newDes );
1.385 +
1.386 + test( newDes.Ptr() == des.Ptr() );
1.387 +
1.388 + test( iBuffer->CheckGuard( readLen ) );
1.389 +
1.390 + test( CompareAgainstFlash( 0, des, 0 ) );
1.391 +
1.392 + }
1.393 + }
1.394 +
1.395 +void CReadTest::TestSimpleThreadReads()
1.396 + //
1.397 + // Makes reads of 1 byte to 512 bytes into the start of the
1.398 + // checked buffer and tests that only the expected bytes have changed
1.399 + // This uses the more complex read function from TBusLocalDrive, and
1.400 + // reads from an aligned Flash address
1.401 + //
1.402 + {
1.403 + test.Next( _L("Testing simple reads using other-thread read function\n") );
1.404 +
1.405 + //
1.406 + // Descriptor to user data area, passed to media driver
1.407 + //
1.408 + TPtr8 des(0,0);
1.409 +
1.410 + for( TInt readLen = 1; readLen <= 512; readLen++ )
1.411 + {
1.412 + test.Printf( _L("Reading %d bytes\n"), readLen );
1.413 +
1.414 + //
1.415 + // Prepare the guard data
1.416 + //
1.417 + iBuffer->InitialiseGuard();
1.418 + test.Printf( _L("AA\n"));
1.419 +
1.420 + //
1.421 + // Set up the descriptor, length=0, maxlen=readLen
1.422 + //
1.423 + iBuffer->GetDes( des, 0, readLen );
1.424 + test.Printf( _L("BB\n"));
1.425 +
1.426 + //
1.427 + // Now read some data into it
1.428 + //
1.429 + test( KErrNone == iDrive.Read( 0, readLen, &des, KLocalMessageHandle, 0 ) );
1.430 + test.Printf( _L("CC\n"));
1.431 +#if 0
1.432 + test( KErrNone == iDrive.Read( 0, readLen, &des, iDummyThread.Handle(), 0 ) );
1.433 +#else
1.434 + // XXX - this works
1.435 + test( KErrNone == iDrive.Read( 0, readLen, &des, KLocalMessageHandle, 0 ) );
1.436 +#endif
1.437 +
1.438 + //
1.439 + // Check what we got
1.440 + //
1.441 + test.Printf( _L("DD\n"));
1.442 + test.Printf( _L("DD\n"));
1.443 + test.Printf( _L("DD\n"));
1.444 + test.Printf( _L("DD\n"));
1.445 + test( des.Length() == readLen );
1.446 +
1.447 + TPtrC8 newDes;
1.448 + test.Printf( _L("EE\n"));
1.449 + iBuffer->GetDes( newDes );
1.450 + test.Printf( _L("FF\n"));
1.451 + test( newDes.Ptr() == des.Ptr() );
1.452 +
1.453 + test( iBuffer->CheckGuard( readLen ) );
1.454 +
1.455 + test.Printf( _L("GG\n"));
1.456 + test( CompareAgainstFlash( 0, des, 0 ) );
1.457 + test.Printf( _L("HH\n"));
1.458 +
1.459 + }
1.460 + }
1.461 +
1.462 +
1.463 +void CReadTest::TestUnalignedReads()
1.464 + //
1.465 + // Makes reads of 1 byte to 512 bytes into the start of the
1.466 + // checked buffer and tests that only the expected bytes have changed
1.467 + // This uses the simple read function from TBusLocalDrive.
1.468 + // The data is read from an unaligned address (0ffset 1, 2, 3)
1.469 + //
1.470 + {
1.471 + test.Next( _L("Testing unaligned reads\n") );
1.472 +
1.473 + //
1.474 + // Descriptor to user data area, passed to media driver
1.475 + //
1.476 + TPtr8 des(0,0);
1.477 +
1.478 + for( TInt readLen = 1; readLen <= 512; readLen++ )
1.479 + {
1.480 + //
1.481 + // Set up the descriptor, length=0, maxlen=readLen
1.482 + //
1.483 + iBuffer->GetDes( des, 0, readLen );
1.484 +
1.485 + //
1.486 + // Repeat for each offset
1.487 + //
1.488 + for( TInt offs = 1; offs < 4; offs++ )
1.489 + {
1.490 + test.Printf( _L("Reading %d unaligned bytes from offset %d\n"), readLen, offs );
1.491 +
1.492 + iBuffer->InitialiseGuard();
1.493 + test( KErrNone == iDrive.Read( offs, readLen, des ) );
1.494 +
1.495 + test( des.Length() == readLen );
1.496 +
1.497 + TPtrC8 newDes;
1.498 + iBuffer->GetDes( newDes );
1.499 + test( newDes.Ptr() == des.Ptr() );
1.500 +
1.501 + test( iBuffer->CheckGuard( readLen ) );
1.502 +
1.503 + test( CompareAgainstFlash( offs, des, 0 ) );
1.504 + }
1.505 +
1.506 + }
1.507 + }
1.508 +
1.509 +
1.510 +void CReadTest::TestUnalignedThreadReads()
1.511 + //
1.512 + // Makes reads of 1 byte to 512 bytes into the start of the
1.513 + // checked buffer and tests that only the expected bytes have changed
1.514 + // This uses the thread read function from TBusLocalDrive.
1.515 + // The data is read from an unaligned address (0ffset 1, 2, 3)
1.516 + //
1.517 + {
1.518 + test.Next( _L("Testing unaligned other-thread reads\n") );
1.519 +
1.520 + //
1.521 + // Descriptor to user data area, passed to media driver
1.522 + //
1.523 + TPtr8 des(0,0);
1.524 +
1.525 + for( TInt readLen = 1; readLen <= 512; readLen++ )
1.526 + {
1.527 + //
1.528 + // Set up the descriptor, length=0, maxlen=readLen
1.529 + //
1.530 + iBuffer->GetDes( des, 0, readLen );
1.531 +
1.532 + //
1.533 + // Repeat for each offset
1.534 + //
1.535 + for( TInt offs = 1; offs < 4; offs++ )
1.536 + {
1.537 + test.Printf( _L("Reading %d unaligned bytes from offset %d\n"), readLen, offs );
1.538 +
1.539 + iBuffer->InitialiseGuard();
1.540 +#if 0
1.541 + test( KErrNone == iDrive.Read( offs, readLen, &des, iDummyThread.Handle(), 0 ) );
1.542 +#else
1.543 + test( KErrNone == iDrive.Read( offs, readLen, &des, KLocalMessageHandle, 0 ) );
1.544 +#endif
1.545 +
1.546 + test( des.Length() == readLen );
1.547 +
1.548 + TPtrC8 newDes;
1.549 + iBuffer->GetDes( newDes );
1.550 + test( newDes.Ptr() == des.Ptr() );
1.551 +
1.552 + test( iBuffer->CheckGuard( readLen ) );
1.553 +
1.554 + test( CompareAgainstFlash( offs, des, 0 ) );
1.555 + }
1.556 +
1.557 + }
1.558 + }
1.559 +
1.560 +
1.561 +void CReadTest::TestOffsetBufferThreadReads()
1.562 + //
1.563 + // Makes reads of 1 byte to 512 bytes to an offset position in the
1.564 + // checked buffer and tests that only the expected bytes have changed
1.565 + // This uses the more complex read function from TBusLocalDrive, and
1.566 + // reads from an aligned Flash address
1.567 + //
1.568 + {
1.569 + test.Next( _L("Testing other-thread reads into offset position in descriptor\n") );
1.570 +
1.571 + //
1.572 + // Descriptor to user data area, passed to media driver
1.573 + //
1.574 + TPtr8 des(0,0);
1.575 +
1.576 + for( TInt readLen = 1; readLen <= 512; readLen++ )
1.577 + {
1.578 + test.Printf( _L("Reading %d bytes\n"), readLen );
1.579 +
1.580 +
1.581 + //
1.582 + // Repeat test for offsets 0..64 in buffer
1.583 + //
1.584 + for( TInt destOffset = 1; destOffset < 64; destOffset++ )
1.585 + {
1.586 +// test.Printf( _L("... dest offset = %d"), destOffset );
1.587 +
1.588 + //
1.589 + // Prepare the guard data
1.590 + //
1.591 + iBuffer->InitialiseGuard();
1.592 +
1.593 + //
1.594 + // Set up the descriptor, length=0, maxlen=readLen+destOffset
1.595 + //
1.596 + iBuffer->GetDes( des, 0, readLen + destOffset );
1.597 +
1.598 +#if 0
1.599 + test( KErrNone == iDrive.Read( 0, readLen, &des, iDummyThread.Handle(), destOffset ) );
1.600 +#else
1.601 + test( KErrNone == iDrive.Read( 0, readLen, &des, KLocalMessageHandle, destOffset ) );
1.602 +#endif
1.603 +
1.604 + //
1.605 + // Check what we got
1.606 + //
1.607 + test( des.Length() == readLen + destOffset );
1.608 +
1.609 + TPtrC8 newDes;
1.610 + iBuffer->GetDes( newDes );
1.611 + test( newDes.Ptr() == des.Ptr() );
1.612 +
1.613 + //
1.614 + // end of written data is at readLen + destOffset
1.615 + //
1.616 + test( iBuffer->CheckGuard( readLen+destOffset ) );
1.617 + //
1.618 + // check the section between that start of the user data and
1.619 + // the offset position still contains guard data
1.620 + //
1.621 + test( iBuffer->CheckGuardAtStartOfUserData( destOffset ) );
1.622 +
1.623 + test( CompareAgainstFlash( 0, des, destOffset ) );
1.624 + }
1.625 +
1.626 + }
1.627 + }
1.628 +
1.629 +
1.630 +void CReadTest::TestOffsetBufferUnalignedThreadReads()
1.631 + //
1.632 + // Makes reads of 1 byte to 512 bytes to an offset position in the
1.633 + // checked buffer and tests that only the expected bytes have changed
1.634 + // This uses the more complex read function from TBusLocalDrive, and
1.635 + // reads from an aligned Flash address
1.636 + //
1.637 + {
1.638 + test.Next( _L("Testing other-thread unaligned reads into offset position in descriptor\n") );
1.639 +
1.640 + //
1.641 + // Descriptor to user data area, passed to media driver
1.642 + //
1.643 + TPtr8 des(0,0);
1.644 +
1.645 + for( TInt readLen = 1; readLen <= 500; readLen++ )
1.646 + {
1.647 + test.Printf( _L("Reading %d bytes\n"), readLen );
1.648 +
1.649 +
1.650 + //
1.651 + // Repeat test for offsets 0..64 in buffer
1.652 + //
1.653 + for( TInt destOffset = 1; destOffset < 64; destOffset++ )
1.654 + {
1.655 +// test.Printf( _L("... dest offset = %d"), destOffset );
1.656 +
1.657 + //
1.658 + // repeat for each source offset
1.659 + //
1.660 + for( TInt offs = 1; offs < 4; offs++ )
1.661 + {
1.662 + //
1.663 + // Prepare the guard data
1.664 + //
1.665 + iBuffer->InitialiseGuard();
1.666 +
1.667 + //
1.668 + // Set up the descriptor, length=0, maxlen=readLen+destOffset
1.669 + //
1.670 + iBuffer->GetDes( des, 0, readLen + destOffset );
1.671 +
1.672 +#if 0
1.673 + test( KErrNone == iDrive.Read( offs, readLen, &des, iDummyThread.Handle(), destOffset ) );
1.674 +#else
1.675 + test( KErrNone == iDrive.Read( offs, readLen, &des, KLocalMessageHandle, destOffset ) );
1.676 +#endif
1.677 +
1.678 +
1.679 + //
1.680 + // Check what we got
1.681 + //
1.682 + test( des.Length() == readLen + destOffset );
1.683 +
1.684 + TPtrC8 newDes;
1.685 + iBuffer->GetDes( newDes );
1.686 + test( newDes.Ptr() == des.Ptr() );
1.687 +
1.688 + //
1.689 + // end of written data is at readLen + destOffset
1.690 + //
1.691 + test( iBuffer->CheckGuard( readLen+destOffset ) );
1.692 + //
1.693 + // check the section between that start of the user data and
1.694 + // the offset position still contains guard data
1.695 + //
1.696 + test( iBuffer->CheckGuardAtStartOfUserData( destOffset ) );
1.697 +
1.698 + test( CompareAgainstFlash( offs, des, destOffset ) );
1.699 + } // end for
1.700 + }
1.701 + }
1.702 + }
1.703 +
1.704 +
1.705 +void CReadTest::PerformCheckedRead( TInt aReadPos, TInt aReadLen )
1.706 + {
1.707 + TPtr8 des(0,0);
1.708 + iBuffer->InitialiseGuard();
1.709 + iBuffer->GetDes( des, 0, aReadLen );
1.710 +
1.711 + test.Printf( _L("Reading %d byte(s) from offset 0x%x\n"), aReadLen, aReadPos );
1.712 + test( KErrNone == iDrive.Read( aReadPos, aReadLen, des ) );
1.713 + test( des.Length() == aReadLen );
1.714 + test( iBuffer->CheckGuard( aReadLen ) );
1.715 + test( CompareAgainstFlash( aReadPos, des, 0 ) );
1.716 + }
1.717 +
1.718 +void CReadTest::PerformCheckedThreadRead( TInt aReadPos, TInt aReadLen, TInt aDescOffset )
1.719 + {
1.720 + TPtr8 des(0,0);
1.721 + iBuffer->InitialiseGuard();
1.722 + iBuffer->GetDes( des, 0, aReadLen + aDescOffset );
1.723 +
1.724 + test.Printf( _L("Reading %d byte(s) from offset 0x%x to thread descriptor offset %d\n"), aReadLen, aReadPos, aDescOffset );
1.725 +#if 0
1.726 + test( KErrNone == iDrive.Read( aReadPos, aReadLen, &des, iDummyThread.Handle(), aDescOffset ) );
1.727 +#else
1.728 + test( KErrNone == iDrive.Read( aReadPos, aReadLen, &des, KLocalMessageHandle, aDescOffset ) );
1.729 +#endif
1.730 +
1.731 +// test.Printf( _L("Check descriptor length") );
1.732 + test( des.Length() == aReadLen + aDescOffset );
1.733 +// test.Printf( _L("Check guard") );
1.734 + test( iBuffer->CheckGuard( aReadLen + aDescOffset ) );
1.735 +// test.Printf( _L("Check guard at start of descriptor") );
1.736 + test( iBuffer->CheckGuardAtStartOfUserData( aDescOffset ) );
1.737 + test( CompareAgainstFlash( aReadPos, des, aDescOffset ) );
1.738 + }
1.739 +
1.740 +
1.741 +void CReadTest::TestReadsFromAllBlocks()
1.742 + //
1.743 + // Does some spot-test reads from all blocks to make sure
1.744 + // that reading across the whole Flash works
1.745 + //
1.746 + {
1.747 + test.Next( _L("Testing reads from all blocks\n") );
1.748 +
1.749 + for( TInt block = 0; block < iBlockCount; block++ )
1.750 + {
1.751 + test.Printf( _L("Reading from block %d"), block );
1.752 + TInt readBase = (block * iBlockSize);
1.753 +
1.754 + PerformCheckedRead( readBase, 1 );
1.755 + PerformCheckedRead( readBase, 24 );
1.756 + PerformCheckedRead( readBase, 99 );
1.757 + PerformCheckedRead( readBase, 511 );
1.758 + PerformCheckedRead( readBase+1, 1 );
1.759 + PerformCheckedRead( readBase+1, 24 );
1.760 + PerformCheckedRead( readBase+1, 99 );
1.761 + PerformCheckedRead( readBase+1, 511 );
1.762 + PerformCheckedRead( readBase+3, 1 );
1.763 + PerformCheckedRead( readBase+3, 24 );
1.764 + PerformCheckedRead( readBase+3, 99 );
1.765 + PerformCheckedRead( readBase+3, 511 );
1.766 +
1.767 + PerformCheckedThreadRead( readBase, 1, 0 );
1.768 + PerformCheckedThreadRead( readBase, 24, 0 );
1.769 + PerformCheckedThreadRead( readBase, 99, 2 );
1.770 + PerformCheckedThreadRead( readBase, 511, 0 );
1.771 + PerformCheckedThreadRead( readBase+1, 1, 11 );
1.772 + PerformCheckedThreadRead( readBase+1, 24, 4 );
1.773 + PerformCheckedThreadRead( readBase+1, 99, 24 );
1.774 + PerformCheckedThreadRead( readBase+1, 511, 0 );
1.775 + PerformCheckedThreadRead( readBase+3, 1, 32 );
1.776 + PerformCheckedThreadRead( readBase+3, 24, 333 );
1.777 + PerformCheckedThreadRead( readBase+3, 99, 0 );
1.778 + PerformCheckedThreadRead( readBase+3, 511, 1 );
1.779 + }
1.780 + }
1.781 +
1.782 +void CReadTest::TestSimpleScatterReads1()
1.783 + //
1.784 + // Does some simple reads of varying length from the
1.785 + // blocks in pseudo-random order.
1.786 + //
1.787 + {
1.788 + test.Next( _L("Testing simple scatter reads\n") );
1.789 +
1.790 + TRandomGenerator random;
1.791 + random.SetSeed( KRandomTestSeed );
1.792 +
1.793 + for( TInt readLen = 1; readLen <= 512; readLen++ )
1.794 + {
1.795 + TInt block = random.Next() % iBlockCount;
1.796 + test.Printf( _L("Reading block %d"), block );
1.797 + TInt readBase = (block * iBlockSize);
1.798 + PerformCheckedRead( readBase, readLen );
1.799 + }
1.800 + }
1.801 +
1.802 +void CReadTest::TestSimpleScatterReads2()
1.803 + //
1.804 + // Does some simple reads of varying length from the
1.805 + // blocks in pseudo-random order.
1.806 + //
1.807 + // This is similar to TestSimpleScatterReads1 except that
1.808 + // as the length reduces the read position is moved along
1.809 + // and the test uses the thread-read variant
1.810 + //
1.811 + {
1.812 + test.Next( _L("Testing simple scatter reads\n") );
1.813 +
1.814 + TRandomGenerator random;
1.815 + random.SetSeed( KRandomTestSeed );
1.816 +
1.817 + for( TInt readLen = 1; readLen <= 512; readLen++ )
1.818 + {
1.819 + TInt block = random.Next() % iBlockCount;
1.820 + test.Printf( _L("Reading block %d"), block );
1.821 + TInt readBase = (block * iBlockSize) + (512 - readLen);
1.822 + PerformCheckedRead( readBase, readLen );
1.823 + }
1.824 + }
1.825 +
1.826 +void CReadTest::TestScatterGather()
1.827 + //
1.828 + // This reads bytes from all over the Flash and concatenates
1.829 + // them into a single descriptor. This isn't representative of
1.830 + // anything a real filesystem would do (at present!) but
1.831 + // is an interesting test of the media driver
1.832 + //
1.833 + {
1.834 + test.Next( _L("Testing scatter-gather reads\n") );
1.835 +
1.836 + TRandomGenerator random;
1.837 + random.SetSeed( KRandomTestSeed );
1.838 +
1.839 + const TInt KMaxReads = 500;
1.840 + struct SReadInfo
1.841 + {
1.842 + TInt iOffset;
1.843 + TInt iLength;
1.844 + };
1.845 +
1.846 + SReadInfo* readInfoArray = new SReadInfo[KMaxReads];
1.847 + test( NULL != readInfoArray );
1.848 +
1.849 + TPtr8 des(0,0);
1.850 + iBuffer->InitialiseGuard();
1.851 + iBuffer->GetDes( des, 0, KTestUserDataSize );
1.852 + TInt descOffset = 0;
1.853 +
1.854 + TInt readCount;
1.855 + for( readCount = 0; readCount < KMaxReads; readCount++ )
1.856 + {
1.857 + //
1.858 + // Create random read position and length
1.859 + //
1.860 + TInt block = random.Next() % iBlockCount;
1.861 + TInt blockOffset = random.Next() % 1000;
1.862 + if( blockOffset > 500 )
1.863 + {
1.864 + blockOffset = iBlockSize - 1 - blockOffset;
1.865 + }
1.866 + TInt readOffset = (block * iBlockSize) + blockOffset;
1.867 + TInt readLength = (random.Next() % 8) + 1;
1.868 +
1.869 + if( des.Length() + readLength > des.MaxLength() )
1.870 + {
1.871 + break; // finished
1.872 + }
1.873 +
1.874 + //
1.875 + // Save the position & length
1.876 + //
1.877 + readInfoArray[readCount].iOffset = readOffset;
1.878 + readInfoArray[readCount].iLength = readLength;
1.879 +
1.880 + //
1.881 + // do the read
1.882 + //
1.883 + _LIT( KScatterReadMsg, "Reading Flash @%x %d bytes to desc offset %d" );
1.884 + test.Printf( KScatterReadMsg, readOffset, readLength, descOffset );
1.885 +#if 0
1.886 + test( KErrNone == iDrive.Read( readOffset, readLength, &des, iDummyThread.Handle(), descOffset ) );
1.887 +#else
1.888 + test( KErrNone == iDrive.Read( readOffset, readLength, &des, KLocalMessageHandle, descOffset ) );
1.889 +#endif
1.890 + test( des.Length() == descOffset + readLength );
1.891 +
1.892 + descOffset += readLength;
1.893 + }
1.894 +
1.895 + //
1.896 + // Now check all the data against the Flash contents
1.897 + //
1.898 + descOffset = 0;
1.899 + for( TInt i = 0; i < readCount; i++ )
1.900 + {
1.901 + TInt readOffset = readInfoArray[i].iOffset ;
1.902 + TInt readLength = readInfoArray[i].iLength;
1.903 +
1.904 + TPtrC8 ptr( des.Ptr() + descOffset, readLength );
1.905 + test( CompareAgainstFlash( readOffset, ptr, 0 ) );
1.906 + descOffset += readLength;
1.907 + }
1.908 +
1.909 + delete[] readInfoArray;
1.910 +
1.911 + }
1.912 +
1.913 +
1.914 +
1.915 +void CReadTest::TestReadAcrossBlock()
1.916 + //
1.917 + // Test reads that cross a block boundary
1.918 + //
1.919 + {
1.920 + test.Next( _L("Testing reads across block boundary\n") );
1.921 +
1.922 + for( TInt block = 1; block < iBlockCount - 1; block++ )
1.923 + {
1.924 + for( TInt readLen = 2; readLen <= 1024; readLen++ )
1.925 + {
1.926 + TInt blockBase = (block * iBlockSize);
1.927 + TInt readOffs = blockBase + (iBlockSize - (readLen/2));
1.928 + PerformCheckedRead( readOffs, readLen );
1.929 + }
1.930 + }
1.931 + }
1.932 +
1.933 +
1.934 +
1.935 +void CReadTest::CreateSampleData()
1.936 + //
1.937 + // Fills iSampleData with pseudo-random test data
1.938 + //
1.939 + {
1.940 + TUint32* p = (TUint32*)iSampleData.Ptr();
1.941 + for( TInt j = 0; j < KTestUserDataSize/4; j++ )
1.942 + {
1.943 + *p++ = iRandom.Next();
1.944 + }
1.945 +
1.946 + iSampleData.SetLength( KTestUserDataSize );
1.947 + }
1.948 +
1.949 +
1.950 +TBool CReadTest::CheckZero( const TPtrC8& aDes )
1.951 + //
1.952 + // Checks that all bytes in aDes are zero
1.953 + //
1.954 + {
1.955 + for( TInt i = aDes.Length(); i > 0; )
1.956 + {
1.957 + --i;
1.958 + if( 0 != aDes[i] )
1.959 + {
1.960 + return EFalse;
1.961 + }
1.962 + }
1.963 + return ETrue;
1.964 + }
1.965 +
1.966 +
1.967 +
1.968 +void CReadTest::CreateTestData( TInt aBlockNumber, TBool aEndOfBlock )
1.969 + //
1.970 + // Writes some test data to the Flash. If aEndOfBlock is EFalse the
1.971 + // data is created at the start of the block. If it is ETrue then
1.972 + // the data is created right at the end of the block
1.973 + //
1.974 + {
1.975 +
1.976 + test.Printf( _L("Writing test data to Flash block %d\n"), aBlockNumber );
1.977 +
1.978 + //
1.979 + // Generate some test data
1.980 + //
1.981 + CreateSampleData();
1.982 +
1.983 + test.Printf( _L("Erasing block") );
1.984 + TInt writeBaseOffset = (aBlockNumber * iBlockSize);
1.985 + test( KErrNone == iDrive.Format( writeBaseOffset, iBlockSize ) );
1.986 +
1.987 +
1.988 + TInt writeCount = iSampleData.Length() / KMaxWriteLength;
1.989 + TInt r = KErrNone;
1.990 + if( aEndOfBlock )
1.991 + {
1.992 + writeBaseOffset += iBlockSize - iSampleData.Length();
1.993 + }
1.994 +
1.995 + TInt writeOffset = writeBaseOffset;
1.996 +
1.997 + const TUint8* src = iSampleData.Ptr();
1.998 +
1.999 + test.Printf( _L("Writing data") );
1.1000 + for( ; (writeCount > 0) && (KErrNone == r); writeCount-- )
1.1001 + {
1.1002 + TPtrC8 buf( src, KMaxWriteLength );
1.1003 + test( KErrNone == iDrive.Write( writeOffset, buf ) );
1.1004 + writeOffset += KMaxWriteLength;
1.1005 + src += KMaxWriteLength;
1.1006 + }
1.1007 + test( r == KErrNone );
1.1008 +
1.1009 + //
1.1010 + // check that the data was written ok
1.1011 + //
1.1012 + test.Printf( _L("Verifying data") );
1.1013 + test( CompareAgainstFlash( writeBaseOffset, iSampleData, 0 ) );
1.1014 +
1.1015 + test.Printf( _L("... test data written\n") );
1.1016 + }
1.1017 +
1.1018 +TBool CReadTest::CompareAgainstFlash( TInt aFlashOffset, const TPtrC8& aDes, TInt aDescOffset )
1.1019 + //
1.1020 + // Checks that the data in aDes matches that in the Flash at position
1.1021 + // aFlashOffset.
1.1022 + // The test starts at offset aDescOffset in aSampleData. The data length
1.1023 + // tested is aDes->Length() - aDescOffset
1.1024 + //
1.1025 + {
1.1026 + TInt dataLength = aDes.Length() - aDescOffset;
1.1027 + const TUint8* srcPtr = aDes.Ptr() + aDescOffset;
1.1028 +
1.1029 + TUint offset = aFlashOffset;
1.1030 +
1.1031 + TBool failed = EFalse;
1.1032 + const TInt readBufLen = iReadBuffer.MaxLength();
1.1033 +
1.1034 + while( (dataLength > 0) && !failed )
1.1035 + {
1.1036 + TInt len = Min( dataLength, readBufLen );
1.1037 + TInt r = iDrive.Read( offset, len, iReadBuffer );
1.1038 + if( r != KErrNone )
1.1039 + {
1.1040 + test.Printf( _L("... FAIL: read failed (%d) at offset 0x%x\n"), r, offset );
1.1041 + test( KErrNone == r );
1.1042 + }
1.1043 + test( iReadBuffer.Length() == len );
1.1044 +
1.1045 + if( 0 != Mem::Compare( srcPtr, len, iReadBuffer.Ptr(), len ) )
1.1046 + {
1.1047 + test.Printf( _L("... FAIL: mismatch around offset 0x%x\n"), offset );
1.1048 + failed = ETrue;
1.1049 + }
1.1050 + offset += len;
1.1051 + dataLength -= len;
1.1052 + srcPtr += len;
1.1053 + }
1.1054 +
1.1055 + return !failed;
1.1056 + }
1.1057 +
1.1058 +
1.1059 +
1.1060 +void CReadTest::DoTest()
1.1061 + //
1.1062 + // Main test dispatcher
1.1063 + //
1.1064 + {
1.1065 + //
1.1066 + // Create some test data at start of block 0
1.1067 + //
1.1068 + CreateTestData( 0, EFalse );
1.1069 +
1.1070 + //
1.1071 + // Now do the simple tests, all reads will return zeros
1.1072 + //
1.1073 +#if 0
1.1074 + TestSimpleReads();
1.1075 +#endif
1.1076 + TestSimpleThreadReads();
1.1077 + TestUnalignedReads();
1.1078 + TestUnalignedThreadReads();
1.1079 + TestOffsetBufferThreadReads();
1.1080 + TestOffsetBufferUnalignedThreadReads();
1.1081 +
1.1082 + //
1.1083 + // Create some more data at start of all other blocks
1.1084 + //
1.1085 + test.Next( _L("Creating more test data in other blocks") );
1.1086 + for( TInt i = 1; i < iBlockCount; i++ )
1.1087 + {
1.1088 + CreateTestData( i, EFalse );
1.1089 + }
1.1090 +
1.1091 + //
1.1092 + // Make sure we can read valid data out of the other blocks
1.1093 + //
1.1094 + TestReadsFromAllBlocks();
1.1095 +
1.1096 + //
1.1097 + // Now do some scatter-read tests
1.1098 + //
1.1099 + TestSimpleScatterReads1();
1.1100 + TestSimpleScatterReads2();
1.1101 +
1.1102 + //
1.1103 + // Create some more testdata at end of all blocks
1.1104 + //
1.1105 + test.Next( _L("Creating test data at end of blocks") );
1.1106 + for( TInt i = 0; i < iBlockCount; i++ )
1.1107 + {
1.1108 + CreateTestData( i, ETrue );
1.1109 + }
1.1110 +
1.1111 + //
1.1112 + // Do a full scatter-gather test
1.1113 + //
1.1114 + TestScatterGather();
1.1115 +
1.1116 + TestReadAcrossBlock();
1.1117 + }
1.1118 +
1.1119 +
1.1120 +
1.1121 +
1.1122 +
1.1123 +TInt E32Main()
1.1124 + {
1.1125 + test.Title();
1.1126 + test.Start(_L("Testing media read operations"));
1.1127 +
1.1128 + CReadTest reader;
1.1129 + TRAPD( ret, reader.CreateL() );
1.1130 + test( KErrNone == ret );
1.1131 + reader.DoTest();
1.1132 + test.End();
1.1133 +
1.1134 + return 0;
1.1135 + }