First public contribution.
1 // Copyright (c) 1998-2010 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 "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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
20 const TInt KTestCleanupStack=0x20;
22 // This is a path specification and should not be used as is
23 _LIT(KFileLocationSpec, "Z:\\STOR-TST\\T_COMPACT.DAT");
24 _LIT(KResultsFile,"RESULTS_%d.TXT");
26 static TFileName TheResultsFile;
27 static TBool AllTests=ETrue;
28 static TInt Iterations=10000;
29 static TInt DataVolume=160;
30 static TInt CompactFrequency=40;
35 void CreateL(RFs& aFs, const TDesC& aFile);
37 void PrintL(const char* aFormat, ...);
39 RFileWriteStream iLog;
42 LOCAL_D CTrapCleanup* TheTrapCleanup;
43 LOCAL_D RTest test(_L("t_storfcomp"));
56 void StopWatch::Start()
58 iTime.UniversalTime();
61 TUint StopWatch::Stop()
65 TInt64 i = ((t.MicroSecondsFrom(iTime).Int64()) + 500)/1000;
71 void CompactL(CFileStore& aStore)
73 // Compact the file and record the stats
78 User::LeaveIfError(aStore.File().Size(startSize));
80 TInt wasted = aStore.CompactL();
82 TUint ms = CompactSW.Stop();
84 User::LeaveIfError(aStore.File().Size(endSize));
85 TheLog.PrintL("%d\t%d\t%d\t%u\n",startSize, endSize, wasted, ms);
88 void ReclaimCompactL(CFileStore& aStore, TInt aTrigger)
90 // Reclaim the file and compact on trigger
94 User::LeaveIfError(aStore.File().Size(startSize));
96 TBool compacted = EFalse;
97 if (aTrigger == 0 || aStore.ReclaimL() * 100 > startSize * aTrigger)
103 TUint ms = CompactSW.Stop();
105 User::LeaveIfError(aStore.File().Size(endSize));
106 TheLog.PrintL("%s\t%d\t%u\n",compacted ? "Compact" : "Reclaim", startSize - endSize, ms);
109 void WriteBytesL(RWriteStream& s, TInt aCount)
111 const TInt KBufSize = 512;
112 TUint8 buf[KBufSize];
113 while (aCount > KBufSize)
115 s.WriteL(buf, KBufSize);
118 s.WriteL(buf, aCount);
122 TStreamId CreateStreamL(CStreamStore& aStore, TInt aSize)
125 TStreamId id = s.CreateLC(aStore);
126 WriteBytesL(s, aSize);
127 CleanupStack::PopAndDestroy(&s);
131 TInt Random(TUint aLimit)
133 return Math::Random() % aLimit;
137 TBool AllocationFailure()
139 User::__DbgSetAllocFail(RHeap::EUser,RHeap::EFailNext,1);
140 TAny* cell = User::Alloc(4);
142 User::__DbgSetAllocFail(RHeap::EUser,RHeap::ENone,1);
146 @SYMTestCaseID SYSLIB-STORE-CT-1144
147 @SYMTestCaseDesc Tests for CFileStore::CompactL() function
148 @SYMTestPriority High
149 @SYMTestActions Attempt for compaction process on the store.Tests for KErrNone flag
150 @SYMTestExpectedResults Test must not fail
153 void BasicCompactionTestsL()
155 const TInt KTestCount = 40;
156 const TInt KTestSize = 50;
157 TParsePtrC parse(KFileLocationSpec);
159 test.Next(_L(" @SYMTestCaseID:SYSLIB-STORE-CT-1144 "));
160 CFileStore* store = CPermanentFileStore::ReplaceLC(TheFs, parse.NameAndExt(), EFileRead|EFileWrite);
162 store->SetTypeL(store->Layout());
164 TheLog.PrintL("Compact uncommitted empty store\n");
165 TRAPD(r, store->CompactL());
166 test (r == KErrNone);
168 TheLog.PrintL("Compact committed empty store\n");
170 test (r == KErrNone);
171 TRAP(r, store->CompactL());
172 test (r == KErrNone);
174 TheLog.PrintL("Compact empty store with full TOC\n");
175 TStreamId streams[KTestCount];
177 for (i = 0; i < KTestCount; ++i)
178 streams[i] = CreateStreamL(*store, KTestSize);
180 for (i = 0; i < KTestCount; ++i)
181 store->DeleteL(streams[i]);
183 TRAP(r, store->CompactL());
184 test (r == KErrNone);
186 TheLog.PrintL("Compact empty store with delta TOC\n");
187 streams[0] = CreateStreamL(*store, KTestSize);
189 store->DeleteL(streams[0]);
191 TRAP(r, store->CompactL());
192 test (r == KErrNone);
194 CleanupStack::PopAndDestroy(store);
198 @SYMTestCaseID SYSLIB-STORE-CT-1145
199 @SYMTestCaseDesc Testing fallback compaction algorithm
200 @SYMTestPriority High
201 @SYMTestActions Tests for compaction process on the store,
202 If we have allocation failure we can test that the fallback algorithm is in place
203 @SYMTestExpectedResults Test must not fail
206 void CompactionAlgorithmTestL()
208 const TInt KTestCount = 200;
209 const TInt KTestSize = 50;
210 const TInt KBeyondSuccess = 2;
211 TInt stopat = KMaxTInt;
213 TParsePtrC parse(KFileLocationSpec);
215 test.Next(_L(" @SYMTestCaseID:SYSLIB-STORE-CT-1145 "));
216 TheLog.PrintL("Testing fallback compaction algorithm\n");
218 for (TInt failat = 1; failat <= stopat; ++failat)
220 TheLog.PrintL("Fail allocation #%d: ", failat);
222 // prepare the store. Leave a single hole at the beginning
223 CFileStore* store = CPermanentFileStore::ReplaceLC(TheFs, parse.NameAndExt(), EFileRead|EFileWrite);
224 store->SetTypeL(store->Layout());
225 TStreamId first = CreateStreamL(*store, KTestSize);
226 for (TInt i = 1; i < KTestCount; ++i)
227 CreateStreamL(*store, KTestSize);
229 store->DeleteL(first);
232 User::__DbgSetAllocFail(RHeap::EUser,RHeap::EFailNext,failat);
234 TRAPD(r, store->CompactL(); store->CommitL();)
235 TInt ms = CompactSW.Stop();
236 User::__DbgSetAllocFail(RHeap::EUser,RHeap::ENone,1);
240 test (bestTime == -1);
241 TheLog.PrintL("compaction failed\n");
245 TheLog.PrintL("compaction succeeded in %u ms\n", ms);
249 stopat = failat + KBeyondSuccess; //stop after a few passes after sucsss
251 else if (ms < bestTime)
254 stopat = failat + KBeyondSuccess; // new algorithm has kicked in
259 CleanupStack::PopAndDestroy(store);
270 CFileStore* InitialiseStoreLC(RArray<TTracker>& aStreams, TInt aDataVolume, TInt aAverageSize)
272 TParsePtrC parse(KFileLocationSpec);
273 CFileStore* store = CPermanentFileStore::ReplaceLC(TheFs, parse.NameAndExt(), EFileRead|EFileWrite);
274 store->SetTypeL(store->Layout());
275 for (TInt count = Max(1,(aDataVolume + aAverageSize/2)/aAverageSize); count > 0; --count)
282 size = aDataVolume / count;
283 TInt spread = Min(aAverageSize, size);
284 size += Random(spread) - spread/2;
288 e.iId = CreateStreamL(*store, size);
289 User::LeaveIfError(aStreams.Append(e));
296 @SYMTestCaseID SYSLIB-STORE-CT-1146
297 @SYMTestCaseDesc Tests for compaction on store
298 @SYMTestPriority High
299 @SYMTestActions Tests for CFileStore::CompactL() function
300 @SYMTestExpectedResults Test must not fail
303 void CompactionTestL(const TInt aIterations, const TInt aDataVolume, const TInt aAverageSize, const TInt aCommitFrequency, const TInt aCompactionFrequency)
305 test.Next(_L(" @SYMTestCaseID:SYSLIB-STORE-CT-1146 "));
306 TheLog.PrintL("CompactionTest : \n");
307 TheLog.PrintL("\tIterations:\t%d\n",aIterations);
308 TheLog.PrintL("\tDataVolume:\t%d\n",aDataVolume);
309 TheLog.PrintL("\tAverageSize:\t%d\n",aAverageSize);
310 TheLog.PrintL("\tCommitFrequency:\t%d\n",aCommitFrequency);
311 TheLog.PrintL("\tCompactionFrequency:\t%d\n\n",aCompactionFrequency);
313 RArray<TTracker> streams(8);
314 CleanupClosePushL(streams);
315 CFileStore* store = InitialiseStoreLC(streams, aDataVolume, aAverageSize);
316 const TInt maxCount = streams.Count() + (streams.Count() / 5);
317 TInt size = aDataVolume;
318 const TInt span = aDataVolume / 10; // +- 10%
319 for (TInt i = aIterations ; --i >= 0; )
321 TInt from = Random(streams.Count());
322 TInt to = Random(maxCount);
323 TInt tfr = to == from ? 0 : Random(streams[from].iSize + 1);
324 TInt adj = Random(span - 1) - span/2;
325 if (size > aDataVolume + span/2)
326 adj -= size - (aDataVolume + span/2);
327 else if (size < aDataVolume - span/2)
328 adj += (aDataVolume - span/2) - size;
331 if (adj < tfr - streams[from].iSize)
332 adj = tfr - streams[from].iSize;
334 TInt fromSize = streams[from].iSize - tfr;
335 if (adj < 0 || to == from)
340 s.ReplaceLC(*store, streams[from].iId);
341 WriteBytesL(s, fromSize);
342 CleanupStack::PopAndDestroy(&s);
343 streams[from].iSize = fromSize;
348 if (to < streams.Count())
350 TInt toSize = streams[to].iSize + tfr;
354 s.ReplaceLC(*store, streams[to].iId);
355 WriteBytesL(s, toSize);
356 CleanupStack::PopAndDestroy(&s);
357 streams[to].iSize = toSize;
366 e.iId = CreateStreamL(*store, toSize);
367 User::LeaveIfError(streams.Append(e));
372 store->DeleteL(streams[from].iId);
373 streams.Remove(from);
377 if (Random(aCommitFrequency) == 0)
380 if (aCompactionFrequency <= 0)
381 ReclaimCompactL(*store, -aCompactionFrequency);
383 if (aCompactionFrequency > 0 && Random(aCompactionFrequency) == 0)
386 CleanupStack::PopAndDestroy(store);
387 CleanupStack::PopAndDestroy(&streams);
388 TheLog.PrintL("\nCompactionTestEnd\n\n");
391 void RLog::CreateL(RFs& aFs, const TDesC& aFile)
394 User::LeaveIfError(iLog.Replace(aFs, aFile, EFileWrite));
403 void RLog::PrintL(const char* aFormat, ...)
406 VA_START(list,aFormat);
408 b.FormatList(_L8(aFormat),list);
415 test.Printf(_L("%S"),&b16);
421 User::CommandLine(options);
422 if (options.Length() > 0)
427 if (lex.Val(DataVolume) == KErrNone)
430 if (lex.Val(Iterations) == KErrNone)
433 lex.Val(CompactFrequency);
437 TheResultsFile.Format(KResultsFile,DataVolume);
443 TheLog.CreateL(TheFs, TheResultsFile);
446 BasicCompactionTestsL();
447 if (AllocationFailure())
448 CompactionAlgorithmTestL();
450 CompactionTestL(Iterations, DataVolume<<10, 300, 5, CompactFrequency);
454 LOCAL_C void setupTestDirectory()
456 // Prepare the test directory.
459 TInt r=TheFs.Connect();
462 TDriveUnit drive(static_cast<TUint>(RFs::GetSystemDrive()));
464 parse.Set(drive.Name(), &KFileLocationSpec, NULL);
466 r=TheFs.MkDir(parse.DriveAndPath());
467 test(r==KErrNone||r==KErrAlreadyExists);
468 r=TheFs.SetSessionPath(parse.DriveAndPath());
472 LOCAL_C void setupCleanup()
474 // Initialise the cleanup stack.
477 TheTrapCleanup=CTrapCleanup::New();
478 test(TheTrapCleanup!=NULL);
481 for (TInt i=KTestCleanupStack;i>0;i--)\
482 CleanupStack::PushL((TAny*)0);\
483 CleanupStack::Pop(KTestCleanupStack);\
488 LOCAL_C void DeleteDataFile(const TDesC& aFullName)
491 TInt err = fsSession.Connect();
495 if(fsSession.Entry(aFullName, entry) == KErrNone)
497 RDebug::Print(_L("Deleting \"%S\" file.\n"), &aFullName);
498 err = fsSession.SetAtt(aFullName, 0, KEntryAttReadOnly);
501 RDebug::Print(_L("Error %d changing \"%S\" file attributes.\n"), err, &aFullName);
503 err = fsSession.Delete(aFullName);
506 RDebug::Print(_L("Error %d deleting \"%S\" file.\n"), err, &aFullName);
513 RDebug::Print(_L("Error %d connecting file session. File: %S.\n"), err, &aFullName);
517 class CTestStreamStore : public CStreamStore
520 static CTestStreamStore* NewL();
521 virtual ~CTestStreamStore();
525 virtual MStreamBuf* DoReadL(TStreamId anId) const;
526 virtual MStreamBuf* DoCreateL(TStreamId& anId);
530 CTestStreamStore* CTestStreamStore::NewL()
532 return new (ELeave) CTestStreamStore;
535 CTestStreamStore::~CTestStreamStore()
539 CTestStreamStore::CTestStreamStore()
543 MStreamBuf* CTestStreamStore::DoReadL(TStreamId) const
548 MStreamBuf* CTestStreamStore::DoCreateL(TStreamId&)
554 @SYMTestCaseID PDS-STORE-CT-4063
555 @SYMTestCaseDesc CStreamStore tests.
556 @SYMTestActions CStreamStore provides couple of virtual methods in its private section:
557 DoExtendL(), DoDeleteL(), DoReplaceL(), DoReclaimL().
558 They are no-ops and are expected to be overriden in the class derived from
559 CStreamStore. Their implementations leave with KErrNotsupported.
560 The test uses a class derived from CStreamStore, which class does not implement
561 virtuals mentioned above. These virtuals should leave with KErrNotSupported when called.
562 @SYMTestPriority High
563 @SYMTestExpectedResults Test must not fail
565 void TestStreamStoreVirtualsL()
567 CTestStreamStore* store = CTestStreamStore::NewL();
568 TRAPD(err, store->CommitL());
569 test(err == KErrNone);
570 TRAP(err, store->RevertL());
571 test(err == KErrNotSupported);
572 TRAP(err, store->ReclaimL());
573 test(err == KErrNotSupported);
574 TRAP(err, store->CompactL());
575 test(err == KErrNotSupported);
576 TRAP(err, store->DeleteL(TStreamId(1)));
577 test(err == KErrNotSupported);
582 // Test permanent file store.
584 GLDEF_C TInt E32Main()
587 setupTestDirectory();
591 test.Start(_L("Test compaction"));
592 TRAPD(r,testCompactL());
594 test.Next(_L("@SYMTestCaseID:PDS-STORE-CT-4063: Test CStreamStore virtuals"));
595 TRAP(r, TestStreamStoreVirtualsL())
598 //deletion of data files must be before call to .End() - DEF047652
599 TDriveUnit drive(static_cast<TUint>(RFs::GetSystemDrive()));
601 parse.Set(drive.Name(), &KFileLocationSpec, NULL);
602 ::DeleteDataFile(parse.FullName());
608 delete TheTrapCleanup;