sl@0: // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // f32test\server\t_resize.cpp sl@0: // This program is designed to test the CFatFileCB::ResizeIndex() method, sl@0: // especially wrt defect EDNMDON-4J2EWK, which occured when the index was sl@0: // resized by an extreme amount. sl@0: // This program must be run on a FAT formatted disk with at least 10Mb free. sl@0: // RFile::SetSize(TInt aSize) sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include "t_server.h" sl@0: sl@0: GLDEF_D RTest test(_L("T_RESIZE")); sl@0: sl@0: // const TInt KBrutusUidValue=0x09080001; /* Never used */ sl@0: // const TInt KWinsUidValue=0x00000001; /* Never used */ sl@0: const TInt K1K = 1 << 10; // 1K sl@0: const TInt K4K = 4 * K1K; sl@0: const TInt K1Mb = 1 << 20; sl@0: const TInt KBigFileSize = 10 * K1Mb; // 10Mb sl@0: const TInt KSmallFileSize = 10 * K1K; sl@0: const TInt KFillBufLength = K1K; sl@0: const TInt KNumberLength = 8; sl@0: const TInt KNumbersPerFillBuf = KFillBufLength / KNumberLength; sl@0: sl@0: LOCAL_C TBool IsDiskValid(TInt aDrive); sl@0: LOCAL_C void FillBuf(TDes8 &aBuf, TInt aStart); sl@0: sl@0: GLDEF_C void CallTestsL() sl@0: { sl@0: // sl@0: // Test with drive nearly full sl@0: // sl@0: CTrapCleanup* cleanup; // create cleanup stack sl@0: cleanup = CTrapCleanup::New(); sl@0: __UHEAP_MARK; sl@0: sl@0: test.Title(); sl@0: test.Start(_L("Starting tests")); sl@0: sl@0: test.Next(_L("Connecting to file server.")); sl@0: TInt r; sl@0: r = TheFs.Connect(); sl@0: test(r == KErrNone); sl@0: sl@0: if ( !gDriveToTest.IsLower() ) sl@0: { sl@0: gDriveToTest.LowerCase(); sl@0: } sl@0: sl@0: TInt gDriveNumber; // current drive number sl@0: test((r = RFs::CharToDrive(gDriveToTest, gDriveNumber)) == KErrNone); sl@0: sl@0: if (IsDiskValid(gDriveNumber)) sl@0: { sl@0: // Overflows occur because iSeekIndex is 128 elements long. sl@0: sl@0: // ASSUMES CLUSTER SIZE IS 512 BYTES sl@0: sl@0: // 1: Create a 10Mb file and resize it to 10k. sl@0: sl@0: // A 10Mb file will create force each member of CFatFileCB::iSeekIndex to sl@0: // mark the start of 2^8 blocks (512 * 128 * 2^8 = 2^9 * 2^7 * 2^8 = 2^24 = 16777216) sl@0: // A 10K file has an iSeekIndex with granularity 2^0 = 1 cluster. sl@0: // skip half-words = (1<<(iSeekIndexSize-aNewMult))-1 = (1 << (8 - 0)) - 1 = 255. sl@0: sl@0: test.Next(_L("Creating file.")); sl@0: test.Printf(_L("Writing %08x file.\n"), KBigFileSize); sl@0: RFile f; sl@0: TFileName fn; sl@0: fn.Format(_L("%c:\\resize.tst"), TUint(gDriveToTest)); sl@0: test((r = f.Create(TheFs, fn, EFileShareExclusive | EFileStream | EFileWrite)) == KErrNone); sl@0: TInt i; // bad for scope under VC sl@0: TBuf8 buf; // don't reconstruct for each iteration sl@0: for (i = 0; i < KBigFileSize / KNumberLength; i += KNumbersPerFillBuf) sl@0: { sl@0: if (((i * KNumberLength) % (KBigFileSize / 32)) == 0) sl@0: test.Printf(_L("writing to file posn %08x.\n"), i * 8); sl@0: sl@0: FillBuf(buf, i); sl@0: test(f.Write(buf) == KErrNone); sl@0: } sl@0: sl@0: // Resize the file to 10k. This should cause CFatFileCB::iSeekIndex to be filled sl@0: // with zeroes and not cause a Des16PanicDesIndexOutOfRange. sl@0: test.Next(_L("Resizing file downwards.\n")); sl@0: test.Printf(_L("Resizing %08x file to %08x.\n"), KBigFileSize, KSmallFileSize); sl@0: f.SetSize(KSmallFileSize); sl@0: sl@0: // Re-read the file up to 10k to make sure it is navigated properly. sl@0: test.Printf(_L("Checking first %08x bytes are maintained.\n"), KSmallFileSize); sl@0: TInt startPos = 0; sl@0: f.Seek(ESeekStart, startPos); sl@0: TBuf8 buf2; // don't reconstruct for each iteration sl@0: for (i = 0; i < KSmallFileSize / KNumberLength; i += KNumbersPerFillBuf) sl@0: { sl@0: test(f.Read(buf) == KErrNone); sl@0: test(buf.Length() == KFillBufLength); sl@0: FillBuf(buf2, i); sl@0: test(buf2.Compare(buf) == 0); sl@0: } sl@0: sl@0: // 2: Resize the 10K file to 10Mb. sl@0: // sl@0: // iSeekIndex will be cleared because the resize loop is never executed. sl@0: sl@0: // TUint16* newVal=(TUint16*)ptr; sl@0: // TInt step=1<<(aNewMult-iSeekIndexSize); // 256 sl@0: // ptr+=step-1; // ptr := &(*iSeekIndex[255]) sl@0: // while(ptr ptrEnd on first iteration sl@0: // { sl@0: // *newVal=*ptr; sl@0: // newVal++; sl@0: // ptr+=step; sl@0: // } sl@0: // while(newVal fsName; // _?_ length sl@0: sl@0: r = TheFs.FileSystemName(fsName, aDrive); sl@0: test(r == KErrNone || r == KErrNotFound); sl@0: test.Printf(_L("fsName = \"%S\".\n"), &fsName); sl@0: sl@0: if (machUid == HAL::EMachineUid_Brutus) sl@0: { sl@0: isFat = (fsName.CompareF(_L("Local")) == 0); sl@0: } sl@0: else sl@0: { sl@0: isFat = (fsName.CompareF(_L("Fat")) == 0); sl@0: } sl@0: sl@0: test.Printf(_L("isFat = %x.\n"), isFat); sl@0: if (! isFat) sl@0: { sl@0: isValid = EFalse; sl@0: } sl@0: else sl@0: { sl@0: TVolumeInfo vi; sl@0: test((r = TheFs.Volume(vi, aDrive)) == KErrNone); sl@0: test.Printf(_L("vi.iFree = %ld\n"), vi.iFree); sl@0: isValid = (vi.iFree >= TInt64(KBigFileSize)); sl@0: } sl@0: sl@0: if (! isValid) sl@0: { sl@0: test.Printf(_L("IsDiskValid: Skipped because drive %d is not a valid FAT volume (with 10Mb free).\n"), aDrive); sl@0: } sl@0: sl@0: return isValid; sl@0: } sl@0: sl@0: LOCAL_C void FillBuf(TDes8 &aBuf, TInt aStart) sl@0: // Fills aBuf with a list of ascending 8 digit numbers. sl@0: // Assumes aBuf.MaxLength() is divisible by 8. sl@0: { sl@0: aBuf.Zero(); sl@0: while (aBuf.Length() < aBuf.MaxLength()) sl@0: { sl@0: aBuf.AppendFormat(_L8("%08x"), aStart++); sl@0: } sl@0: }