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 "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: //
sl@0: 
sl@0: // MSVC++ up to 5.0 has problems with expanding inline functions
sl@0: // This disables the mad warnings for the whole project
sl@0: #if defined(NDEBUG) && defined(__VC32__) && _MSC_VER<=1100
sl@0: #pragma warning(disable : 4710)			// function not expanded. MSVC 5.0 is stupid
sl@0: #endif
sl@0: 
sl@0: #include <d32dbms.h>
sl@0: #include <s32file.h>
sl@0: #include <e32test.h>
sl@0: #include <e32math.h>
sl@0: 
sl@0: #include "crccheck.h"
sl@0: 
sl@0: #undef __UHEAP_MARK
sl@0: #define __UHEAP_MARK
sl@0: #undef __UHEAP_MARKEND
sl@0: #define __UHEAP_MARKEND
sl@0: 
sl@0: LOCAL_D TDBMS_CRCChecks TheCrcChecker;
sl@0: 
sl@0: #ifndef __linux__ //No CRC test on LINUX
sl@0: #ifdef __TOOLS2__
sl@0: const TPtrC	KCrcRecord=_L("\\epoc32\\winscw\\c\\dbms-tst\\T_COMP.CRC");
sl@0: #else
sl@0: const TPtrC	KCrcRecord=_L("C:\\dbms-tst\\T_COMP.CRC");
sl@0: #endif
sl@0: #endif
sl@0: 
sl@0: LOCAL_D RTest test(_L("T_COMP"));
sl@0: LOCAL_D CTrapCleanup* TheTrapCleanup;
sl@0: LOCAL_D RFs TheFs;
sl@0: 
sl@0: const TInt KTestCleanupStack=0x20;
sl@0: 
sl@0: #ifdef __TOOLS2__
sl@0: const TPtrC KTestDir=_L(".\\dbms-tst\\");
sl@0: #else
sl@0: const TPtrC KTestDir=_L("C:\\dbms-tst\\");
sl@0: #endif
sl@0: 
sl@0: //T_BENCH.DB file is created by T_BENCH test and is used by the current test (T_COMP).
sl@0: //T_COMP test will delete T_BENCH.DB at the end as it is no more needed. 
sl@0: //If you want to rerun T_COMP test again, you have to ensure that T_BENCH.DB file exists - 
sl@0: //run T_BENCH test again.
sl@0: _LIT(KTestFile,"T_BENCH.DB");
sl@0: 
sl@0: _LIT(KRomTestFile,"Z:\\TEST\\T_COMP.DAT");
sl@0: _LIT(KCompressedFile,"T_COMP.DB1");
sl@0: _LIT(KDecompressedFile,"T_COMP.DB2");
sl@0: 
sl@0: const TStreamId KHelpId=2;
sl@0: 
sl@0: //
sl@0: // Compress the database
sl@0: //
sl@0: LOCAL_C void CompressL(const TDesC& aSource,const TDesC& aTarget,TBool aCompress)
sl@0: 	{
sl@0: #ifndef __TOOLS2__
sl@0: 	CFileMan* man=CFileMan::NewL(TheFs);
sl@0: 	TInt r=man->Copy(aSource,aTarget);
sl@0: 	delete man;
sl@0: 	User::LeaveIfError(r);
sl@0: #else
sl@0: 	TInt r;
sl@0:     RFile f1;
sl@0:     r = f1.Open(TheFs, aSource, EFileStreamText|EFileShareReadersOnly);
sl@0:     test(r==KErrNone);
sl@0:     RFile f2;
sl@0:     r=f2.Replace(TheFs, aTarget, EFileWrite);
sl@0:     test(r==KErrNone);
sl@0: 
sl@0:     TBuf8<512> copyBuf;
sl@0: 	TInt rem;
sl@0: 	r=f1.Size(rem);
sl@0: 	test(r==KErrNone);
sl@0: 	TInt pos=0;
sl@0: 	while (rem)
sl@0: 		{
sl@0: 		TInt s=Min(rem,copyBuf.MaxSize());
sl@0: 		r=f1.Read(pos,copyBuf,s);
sl@0: 		test(r==KErrNone);
sl@0: 		test(copyBuf.Length()==s);
sl@0: 		r=f2.Write(pos,copyBuf,s);
sl@0: 		test(r==KErrNone);
sl@0: 		pos+=s;
sl@0: 		rem-=s;
sl@0: 		}
sl@0: 	f1.Close();
sl@0: 	f2.Close();	
sl@0: #endif
sl@0: #ifndef __TOOLS2__
sl@0: 	User::LeaveIfError(TheFs.SetAtt(aTarget,0,KEntryAttReadOnly));
sl@0: #endif
sl@0: 	CFileStore* store=CFileStore::OpenLC(TheFs,aTarget,EFileRead|EFileWrite);
sl@0: 	TUint t=User::TickCount();
sl@0: 	if (aCompress)
sl@0: 		RDbStoreDatabase::CompressL(*store,store->Root());
sl@0: 	else
sl@0: 		RDbStoreDatabase::DecompressL(*store,store->Root());
sl@0: 	t=User::TickCount()-t;
sl@0: 	test.Printf(_L("%d ticks\r\n"),t);
sl@0: 	store->CompactL();
sl@0: 	store->CommitL();
sl@0: 	CleanupStack::PopAndDestroy();	// store
sl@0: 	TInt err;
sl@0: 	TRAPD(lc, err = TheCrcChecker.GenerateCrcL(aTarget));
sl@0: 	test(err == KErrNone);
sl@0: 	test(lc == KErrNone);
sl@0: 	}
sl@0: 
sl@0: LOCAL_C void CheckTableL(RDbDatabase& aDatabase,RDbDatabase& aCopy,const TDesC& aTable)
sl@0: 	{
sl@0: 	test.Printf(_L("Processing table %S\n"),&aTable);
sl@0: 	RDbTable table;
sl@0: 	test (table.Open(aDatabase,aTable,table.EReadOnly)==KErrNone);
sl@0: 	RDbTable copy;
sl@0: 	test (copy.Open(aCopy,aTable,table.EReadOnly)==KErrNone);
sl@0: 	TInt columns=table.ColCount();
sl@0: 	while (table.NextL())
sl@0: 		{
sl@0: 		table.GetL();
sl@0: 		test (copy.NextL());
sl@0: 		copy.GetL();
sl@0: 		for (TInt ii=1;ii<=columns;++ii)
sl@0: 			{
sl@0: 			if (TDbCol::IsLong(table.ColType(ii)))
sl@0: 				{
sl@0: 				TInt len=table.ColSize(ii);
sl@0: 				test (len==copy.ColSize(ii));
sl@0: 				RDbColReadStream strm1;
sl@0: 				strm1.OpenLC(table,ii);
sl@0: 				RDbColReadStream strm2;
sl@0: 				strm2.OpenLC(copy,ii);
sl@0: 				TBuf8<512> buf1;
sl@0: 				TBuf8<512> buf2;
sl@0: 				while (len)
sl@0: 					{
sl@0: 					TInt block=Min(512,len);
sl@0: 					strm1.ReadL(buf1,block);
sl@0: 					strm2.ReadL(buf2,block);
sl@0: 					test (buf1==buf2);
sl@0: 					len-=block;
sl@0: 					}
sl@0: 				CleanupStack::PopAndDestroy(2);
sl@0: 				}
sl@0: 			else
sl@0: 				{
sl@0: 				test (table.ColDes8(ii)==copy.ColDes8(ii));
sl@0: 				}
sl@0: 			}
sl@0: 		}
sl@0: 	table.Close();
sl@0: 	copy.Close();
sl@0: 	}
sl@0: 
sl@0: LOCAL_C void CheckL(const TDesC& aSource,const TDesC& aTarget)
sl@0: 	{
sl@0: 	RDbNamedDatabase comp;
sl@0: 	RDbNamedDatabase copy;
sl@0: 	test (comp.Open(TheFs,aSource,TPtrC(),comp.EReadOnly)==KErrNone);
sl@0: 	test (copy.Open(TheFs,aTarget,TPtrC(),copy.EReadOnly)==KErrNone);
sl@0: 	CDbTableNames* tables=comp.TableNamesL();
sl@0: 	for (TInt ii=0;ii<tables->Count();++ii)
sl@0: 		CheckTableL(comp,copy,(*tables)[ii]);
sl@0: 	delete tables;
sl@0: 	copy.Close();
sl@0: 	comp.Close();
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-DBMS-CT-0593
sl@0: @SYMTestCaseDesc        Database compression tests.
sl@0: @SYMTestPriority        Medium
sl@0: @SYMTestActions         Tests for RDbStoreDatabase::CompressL(),RDbStoreDatabase::DecompressL() functions 
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */
sl@0: LOCAL_C void Test(const TDesC& aSource,const TDesC& aTarget,TBool aCompress)
sl@0: 	{
sl@0: 	test.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0593 Converting database "));
sl@0: 	TRAPD(r,CompressL(aSource,aTarget,aCompress));
sl@0: 	test (r==KErrNone);
sl@0: 	test.Next(_L("Checking database"));
sl@0: 	TRAP(r,CheckL(aSource,aTarget));
sl@0: 	test (r==KErrNone);
sl@0: 	test.End();
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // Prepare the test directory.
sl@0: //
sl@0: LOCAL_C void setupTestDirectory()
sl@0:     {
sl@0: 	TInt r=TheFs.Connect();
sl@0: 	test(r==KErrNone);
sl@0: //
sl@0: 	r=TheFs.MkDir(KTestDir);
sl@0: 	test(r==KErrNone || r==KErrAlreadyExists);
sl@0: 	r=TheFs.SetSessionPath(KTestDir);
sl@0: 	test(r==KErrNone);
sl@0: // On TOOLS2 - RFs::SetSessionPath() will affect all RFs Sessions, 
sl@0: // the two RFs need same session path anyway
sl@0: #ifdef __WINSCW__ 
sl@0: 	r=TheCrcChecker.SetSessionPath(KTestDir);
sl@0: 	test(r==KErrNone);
sl@0: #endif
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // Initialise the cleanup stack.
sl@0: //
sl@0: LOCAL_C void setupCleanup()
sl@0:     {
sl@0: 	TheTrapCleanup=CTrapCleanup::New();
sl@0: 	test(TheTrapCleanup!=NULL);
sl@0: 	TRAPD(r,\
sl@0: 		{\
sl@0: 		for (TInt i=KTestCleanupStack;i>0;i--)\
sl@0: 			CleanupStack::PushL((TAny*)0);\
sl@0: 		CleanupStack::Pop(KTestCleanupStack);\
sl@0: 		});
sl@0: 	test(r==KErrNone);
sl@0: 	}
sl@0: 
sl@0: LOCAL_C void DeleteDataFile(const TDesC& aFullName)
sl@0: 	{
sl@0: 	RFs fsSession;
sl@0: 	TInt err = fsSession.Connect();
sl@0: 	if(err == KErrNone)
sl@0: 		{
sl@0: 		TEntry entry;
sl@0: 		if(fsSession.Entry(aFullName, entry) == KErrNone)
sl@0: 			{
sl@0: 			RDebug::Print(_L("Deleting \"%S\" file.\n"), &aFullName);
sl@0: 			err = fsSession.SetAtt(aFullName, 0, KEntryAttReadOnly);
sl@0: 			if(err != KErrNone) 
sl@0: 				{
sl@0: 				RDebug::Print(_L("Error %d changing \"%S\" file attributes.\n"), err, &aFullName);
sl@0: 				}
sl@0: 			err = fsSession.Delete(aFullName);
sl@0: 			if(err != KErrNone) 
sl@0: 				{
sl@0: 				RDebug::Print(_L("Error %d deleting \"%S\" file.\n"), err, &aFullName);
sl@0: 				}
sl@0: 			}
sl@0: 		fsSession.Close();
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		RDebug::Print(_L("Error %d connecting file session. File: %S.\n"), err, &aFullName);
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // Test streaming conversions.
sl@0: //
sl@0: GLDEF_C TInt E32Main()
sl@0:     {
sl@0: 	__UHEAP_MARK;
sl@0: 	test.Title();
sl@0: 	setupTestDirectory();
sl@0: 	setupCleanup();
sl@0: //
sl@0: 	test.Start(_L("Compressing..."));
sl@0: // Don't use the rom test file.
sl@0: /*
sl@0: 	TUint dummy;
sl@0:     TInt err = TheFs.Att(KRomTestFile,dummy);
sl@0: 	if (err==KErrNone)
sl@0: 		Test(KRomTestFile,KCompressedFile,ETrue);
sl@0: 	else
sl@0: 		Test(KTestFile,KCompressedFile,ETrue);
sl@0: */
sl@0: 	Test(KTestFile,KCompressedFile,ETrue);
sl@0: 	test.Next(_L("Decompressing..."));
sl@0: 	Test(KCompressedFile,KDecompressedFile,EFalse);
sl@0: 	
sl@0: //
sl@0: 
sl@0: #ifndef __TOOLS2__
sl@0: 	_LIT(KTestDbName,"C:\\dbms-tst\\T_BENCH.DB");
sl@0: 	::DeleteDataFile(KTestDbName);
sl@0: 	_LIT(KTestDbName1,"C:\\dbms-tst\\T_COMP.DB1");
sl@0: 	::DeleteDataFile(KTestDbName1);
sl@0: 	_LIT(KTestDbName2,"C:\\dbms-tst\\T_COMP.DB2");
sl@0: 	::DeleteDataFile(KTestDbName2);
sl@0: #else
sl@0: 	_LIT(KTestDbName,"T_BENCH.DB");
sl@0: 	::DeleteDataFile(KTestDbName);
sl@0: 	_LIT(KTestDbName1,"T_COMP.DB1");
sl@0: 	::DeleteDataFile(KTestDbName1);
sl@0: 	_LIT(KTestDbName2,"T_COMP.DB2");
sl@0: 	::DeleteDataFile(KTestDbName2);
sl@0: #endif
sl@0: 
sl@0: #ifndef __linux__
sl@0: #ifdef CRC_COMP  // Exclude Crc checking for this test. It's out of scope.
sl@0: 	TInt err;
sl@0: #ifndef __TOOLS2__
sl@0: 	TRAPD(lc, err = TheCrcChecker.DumpCrcRecordsL(KCrcRecord));
sl@0: 	test(err==KErrNone);
sl@0: 	test(lc==KErrNone);
sl@0: #else
sl@0: 	TRAPD(lc, err = TheCrcChecker.ValidateCrcRecordsL(KCrcRecord));
sl@0: 	TPtrC errmsg;
sl@0: 	TheCrcChecker.ErrorReportL(err, errmsg);
sl@0: 	RDebug::Print(errmsg);
sl@0: 	test(err==KErrNone || err==TDBMS_CRCChecks::ECrcCheckOk);
sl@0: #endif
sl@0: #endif
sl@0: #endif
sl@0: 
sl@0: 	delete TheTrapCleanup;
sl@0: 	test.End(); //call to end must be after deletion of files - DEF047652
sl@0: 	
sl@0: 	TheFs.Close();
sl@0: 	test.Close();
sl@0: 	__UHEAP_MARKEND;
sl@0: 	return 0;
sl@0:     }