os/persistentdata/persistentstorage/dbms/pcdbms/tdbms/src/t_dbmsstrcomp.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2005-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 "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 // Testing DBMS ordering and searching functionality when the key field is unicode string.
    15 // The idea is to verify that collation level 0 is used when doing string based searching 
    16 // and collation level > 0 is used when doing string based ordering.
    17 // 
    18 //
    19 
    20 #include <e32test.h>
    21 #include <f32file.h>
    22 #include <d32dbms.h>
    23 
    24 #include "crccheck.h"
    25 
    26 #undef __UHEAP_MARK
    27 #define __UHEAP_MARK
    28 #undef __UHEAP_MARKEND
    29 #define __UHEAP_MARKEND
    30 
    31 LOCAL_D TDBMS_CRCChecks TheCrcChecker;
    32 
    33 #ifndef __linux__ //No CRC test on LINUX
    34 #ifdef __TOOLS2__
    35 const TPtrC	KCrcRecord=_L("\\epoc32\\winscw\\c\\dbms-tst\\T_DBMSSTRCOMP.CRC");
    36 #else
    37 const TPtrC	KCrcRecord=_L("C:\\dbms-tst\\T_DBMSSTRCOMP.CRC");
    38 #endif
    39 #endif
    40 
    41 /////////////////////////////////////////////////////////////////
    42 //Globals
    43 
    44 #ifdef __TOOLS2__
    45 const TPtrC KTestDatabase = _L(".\\dbms-tst\\T_DbmsStrComp.db");
    46 #else
    47 const TPtrC KTestDatabase = _L("c:\\dbms-tst\\T_DbmsStrComp.db");
    48 #endif
    49 
    50 const TUint             KExitDelay = 6 * 1000000;//6 seconds
    51 
    52 static RTest			TheTest(_L("T_DbmsStrComp test"));
    53 static RFs				TheFs;
    54 static RDbNamedDatabase TheDb;
    55 static RDbs				TheDbSession;
    56 
    57 //Test table defs
    58 _LIT(KTestTableName1, "TABLE1");//EDbColText16 key field
    59 _LIT(KTestTableName2, "TABLE2");//EDbColLongText16 key field
    60 
    61 struct TColDef
    62 	{
    63 	const TText*	iName;
    64 	TDbColType		iType;
    65 	TInt			iAttributes;
    66 	};
    67 static TColDef const KColDefs1[]=
    68 	{
    69 		{_S("ID"), EDbColText16, 0},
    70 		{_S("DATA"), EDbColUint32, 0},
    71 		{0}
    72 	};
    73 static TColDef const KColDefs2[]=
    74 	{
    75 		{_S("ID"), EDbColLongText16, 0},
    76 		{_S("DATA"), EDbColUint32, 0},
    77 		{0}
    78 	};
    79 
    80 //Test strings
    81 const TInt KTestStrLen = 3; //The length of test strings
    82 typedef TBuf16<KTestStrLen> TNameBuf;
    83 //Test strings array - using upper and lower case - which will force the DBMS server to make
    84 //different decisions depending on what is the current case: ordering or searching.
    85 const TNameBuf KTestStr[] = 
    86 	{
    87 	_L16("aaa"),
    88 	_L16("aAa"),
    89 	_L16("bbB"),
    90 	_L16("BbB")
    91 	};
    92 const TInt KTestStrCnt = sizeof(KTestStr) / sizeof(KTestStr[0]);
    93 
    94 ///////////////////////////////////////////////////////////////////////////////////////
    95 ///////////////////////////////////////////////////////////////////////////////////////
    96 //Destroy test environment - global functions
    97 
    98 //Deletes "aFullName" file.
    99 static TInt DeleteDataFile(const TDesC& aFullName)
   100 	{
   101 	RFs fsSession;
   102 	TInt err = fsSession.Connect();
   103 	if(err == KErrNone)
   104 		{
   105 		TEntry entry;
   106 		err = fsSession.Entry(aFullName, entry);
   107 		if(err == KErrNone)
   108 			{
   109 			RDebug::Print(_L("Deleting \"%S\" file.\n"), &aFullName);
   110 			err = fsSession.SetAtt(aFullName, 0, KEntryAttReadOnly);
   111 			if(err != KErrNone) 
   112 				{
   113 				RDebug::Print(_L("Error %d changing \"%S\" file attributes.\n"), err, &aFullName);
   114 				}
   115 			err = fsSession.Delete(aFullName);
   116 			if(err != KErrNone) 
   117 				{
   118 				RDebug::Print(_L("Error %d deleting \"%S\" file.\n"), err, &aFullName);
   119 				}
   120 			}
   121 		fsSession.Close();
   122 		}
   123 	else
   124 		{
   125 		RDebug::Print(_L("Error %d connecting file session. File: %S.\n"), err, &aFullName);
   126 		}
   127 	return err;
   128 	}
   129 
   130 ///////////////////////////////////////////////////////////////////////////////////////
   131 ///////////////////////////////////////////////////////////////////////////////////////
   132 //Tests macros and functions.
   133 //If (!aValue) then the test will be panicked, the test data files will be deleted.
   134 static void Check(TInt aValue, TInt aLine)
   135 	{
   136 	if(!aValue)
   137 		{
   138 		::DeleteDataFile(KTestDatabase);
   139 		TheTest(EFalse, aLine);
   140 		}
   141 	}
   142 //If (aValue != aExpected) then the test will be panicked, the test data files will be deleted.
   143 static void Check(TInt aValue, TInt aExpected, TInt aLine)
   144 	{
   145 	if(aValue != aExpected)
   146 		{
   147 		RDebug::Print(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue);
   148 		::DeleteDataFile(KTestDatabase);
   149 		TheTest(EFalse, aLine);
   150 		}
   151 	}
   152 //Use these to test conditions.
   153 #define TEST(arg) ::Check((arg), __LINE__)
   154 #define TEST2(aValue, aExpected) ::Check(aValue, aExpected, __LINE__)
   155 
   156 ///////////////////////////////////////////////////////////////////////////////////////
   157 ///////////////////////////////////////////////////////////////////////////////////////
   158 //Global functions
   159 
   160 //Prepares the test directory.
   161 //TheFs.Connect() has to be called already.
   162 static void SetupTestDirectory()
   163     {
   164 	TInt err = TheFs.MkDir(KTestDatabase);
   165 	TEST(err == KErrNone || err == KErrAlreadyExists);
   166 	}
   167 
   168 //Leaves with info message printed out
   169 static void Leave(TInt aError, TInt aLine)
   170 	{
   171 	RDebug::Print(_L("*** Leave. Error: %d, Line: %d\r\n"), aError, aLine);
   172 	User::Leave(aError);
   173 	}
   174 
   175 //Leaves if aError < 0 with info message printed out
   176 static void LeaveIfError(TInt aError, TInt aLine)
   177 	{
   178 	if(aError < KErrNone)
   179 		{
   180 		::Leave(aError, aLine);
   181 		}
   182 	}
   183 
   184 //Use LEAVE() macro instead of User::Leave() and LEAVE_IF_ERROR() macro instead of
   185 //User::LeaveIfError(). They will print the line number, where the "leave" was called.
   186 #define LEAVE(aError) ::Leave(aError, __LINE__)
   187 #define LEAVE_IF_ERROR(aError) ::LeaveIfError(aError, __LINE__)
   188 
   189 //Creates the test DBMS session
   190 static void CreateTestDbSession()
   191 	{
   192 #ifndef __TOOLS2__
   193 	RDebug::Print(_L("Create DBMS session\n"));
   194 	TInt err = TheDbSession.Connect();
   195 	TEST2(err, KErrNone);
   196 #endif
   197 	}
   198 
   199 
   200 //Creates the test database
   201 //TheDbSession instance has to be connected already.
   202 //TheFs.Connect() has to be called already.
   203 static void CreateTestDatabase(RDbs& aDbs, RDbNamedDatabase& aDb)
   204 	{
   205 	RDebug::Print(_L("Create test database\n"));
   206 	TInt err = aDb.Replace(TheFs, KTestDatabase);
   207 	TEST2(err, KErrNone);
   208 	TheDb.Close();
   209 	err = aDb.Open(aDbs, KTestDatabase);
   210 	TEST2(err, KErrNone);
   211 	}
   212 
   213 //Creates test table
   214 static void DoCreateTestTableL(RDbNamedDatabase& aDb, const TDesC& aTblName, const TColDef aColDefs[])
   215 	{
   216 	CDbColSet* colSet = CDbColSet::NewLC();
   217 	for(const TColDef* colDef=aColDefs;colDef->iName;++colDef)
   218 		{
   219 		TDbCol col(TPtrC(colDef->iName), colDef->iType);
   220 		col.iAttributes = colDef->iAttributes;
   221 		colSet->AddL(col);
   222 		}
   223 	TEST2(aDb.CreateTable(aTblName, *colSet), KErrNone);
   224 	CleanupStack::PopAndDestroy(colSet);
   225 	}
   226 
   227 //Creates test tables
   228 static void CreateTestTablesL(RDbNamedDatabase& aDb)
   229 	{
   230 	RDebug::Print(_L("Create test tables\n"));
   231 	::DoCreateTestTableL(aDb, KTestTableName1, KColDefs1);
   232 	::DoCreateTestTableL(aDb, KTestTableName2, KColDefs2);
   233 	}
   234 
   235 //Gets the value of the string field, which type may be EDbColText16 or EDbColLongText16
   236 void GetStrFieldValue(RDbRowSet& aTbl, const TDesC& aTblName, TDes& aStrFldVal)
   237 	{
   238 	if(aTblName.CompareF(KTestTableName1) == 0)
   239 		{
   240 		aStrFldVal = aTbl.ColDes16(1);
   241 		}
   242 	else
   243 		{
   244 		RDbColReadStream blob;
   245 		blob.OpenLC(aTbl, 1);
   246 		blob.ReadL(aStrFldVal, aTbl.ColLength(1));
   247 		CleanupStack::PopAndDestroy();
   248 		}
   249 	}
   250 
   251 //Prints all table records
   252 static TInt PrintRecordsL(RDbRowSet& aTbl, const TDesC& aTblName)
   253 	{
   254 	RDebug::Print(_L("Table: %S\n"), &aTblName);
   255     aTbl.FirstL();
   256 	TInt rec = 0;
   257     while(aTbl.AtRow())
   258         {
   259         aTbl.GetL();
   260 		TNameBuf strFldVal;
   261 		::GetStrFieldValue(aTbl, aTblName, strFldVal);
   262 		TUint32 v = aTbl.ColUint32(2);
   263 		RDebug::Print(_L("   Record %d, Str: %S, Val: %d\n"), ++rec, &strFldVal, v);
   264         aTbl.NextL(); 
   265         }
   266 	return rec;
   267 	}
   268 
   269 //Checks if the records order (based on a string key field comparison) matches the order of the
   270 //strings in aTestStrArray
   271 static void AssertRecordsOrder(RDbRowSet& aTbl, const TDesC& aTblName, const RArray<TNameBuf>& aTestStrArray)
   272 	{
   273     aTbl.FirstL();
   274 	TInt rec = 0;
   275     while(aTbl.AtRow())
   276         {
   277         aTbl.GetL();
   278 		TNameBuf strFldVal;
   279 		::GetStrFieldValue(aTbl, aTblName, strFldVal);
   280 		TEST(aTestStrArray[rec] == strFldVal);
   281 		++rec;
   282         aTbl.NextL(); 
   283         }
   284 	}
   285 
   286 //Adds test data to the specified table. Make sure that the records are not in
   287 //order (assuming that the first field will be the key).
   288 static void AddTestDataL(RDbNamedDatabase& aDb, const TDesC& aTblName)
   289 	{
   290 	RDbTable tbl;
   291 	CleanupClosePushL(tbl);
   292 	TEST2(tbl.Open(aDb, aTblName, RDbRowSet::EUpdatable), KErrNone);
   293 	for(TInt i=0;i<KTestStrCnt;++i)
   294 		{
   295 		tbl.InsertL();
   296 		tbl.SetColL(1, KTestStr[KTestStrCnt - i - 1]);
   297 		tbl.SetColL(2, i + 1);
   298 		tbl.PutL();
   299 		}
   300 	TEST(tbl.CountL() == KTestStrCnt);
   301 	(void)::PrintRecordsL(tbl, aTblName);
   302 	CleanupStack::PopAndDestroy(&tbl);
   303 	}
   304 
   305 //Adds the test data to test tables
   306 static void AddTestDataL(RDbNamedDatabase& aDb)
   307 	{
   308 	RDebug::Print(_L("Add data to test tables\n"));
   309 	::AddTestDataL(aDb, KTestTableName1);
   310 	::AddTestDataL(aDb, KTestTableName2);
   311 	}
   312 
   313 //Init test environment
   314 static void InitEnvL()
   315 	{
   316 	::CreateTestDbSession();
   317     //Create test database and tables. Add some test data to them.
   318 	::CreateTestDatabase(TheDbSession, TheDb);
   319 	::CreateTestTablesL(TheDb);
   320 	::AddTestDataL(TheDb);
   321 	}
   322 
   323 //String comparison function, used in FillStrArraySorted() function.
   324 static TInt CompareC(const TNameBuf& aName1, const TNameBuf& aName2)
   325     {
   326     return aName1.CompareC(aName2);
   327     }
   328 
   329 //Inserts all test string into an ordered array - aTestStrArray
   330 static void FillStrArraySortedL(RArray<TNameBuf>& aTestStrArray)
   331 	{
   332 	for(TInt i=0;i<KTestStrCnt;++i)
   333 		{
   334     	User::LeaveIfError(aTestStrArray.InsertInOrder(KTestStr[i], TLinearOrder<TNameBuf>(CompareC)));
   335 		}
   336 	}
   337 
   338 static void CreateIndexL(RDbNamedDatabase& aDb, const TDesC& aTblName, const TDesC& aColumnName)
   339 	{
   340 	RDebug::Print(_L("Create index. Table: %S, column: %S\n"), &aTblName, &aColumnName);
   341 	CDbKey* key = CDbKey::NewLC();
   342 	key->AddL(aColumnName);
   343 	key->MakeUnique();
   344 	key->SetComparison(EDbCompareCollated);
   345 	LEAVE_IF_ERROR(aDb.CreateIndex(aColumnName, aTblName, *key));
   346 	CleanupStack::PopAndDestroy(key);
   347 	}
   348 
   349 ///////////////////////////////////////////////////////////////////////////////////////
   350 ///////////////////////////////////////////////////////////////////////////////////////
   351 //Test cases
   352 
   353 //Test case 1. Check SELECT statement with ORDER BY clause when the key field is a string.
   354 static void OrderByTestL(RDbNamedDatabase& aDb, const TDesC& aTblName, const RArray<TNameBuf>& aTestStrArray)
   355 	{
   356     RDbView view;
   357     CleanupClosePushL(view);
   358     
   359     TBuf<128> sqlStmt;
   360     sqlStmt.Append(_L("SELECT ID, DATA FROM "));
   361     sqlStmt.Append(aTblName);
   362     sqlStmt.Append(_L(" ORDER BY ID"));
   363     User::LeaveIfError(view.Prepare(aDb, TDbQuery(sqlStmt, EDbCompareCollated), TDbWindow::EUnlimited));
   364     User::LeaveIfError(view.EvaluateAll());
   365 
   366 	(void)::PrintRecordsL(view, aTblName);
   367 	::AssertRecordsOrder(view, aTblName, aTestStrArray);
   368 
   369     CleanupStack::PopAndDestroy(&view);
   370 	}
   371 
   372 //Test case 2. Check SELECT statement with LIKE keyword when the key field is a string.
   373 static void LikeTestL(RDbNamedDatabase& aDb, const TDesC& aTblName)
   374 	{
   375     RDbView view;
   376     CleanupClosePushL(view);
   377     
   378     TBuf<128> sqlStmt;
   379     sqlStmt.Append(_L("SELECT ID, DATA FROM "));
   380     sqlStmt.Append(aTblName);
   381     sqlStmt.Append(_L(" WHERE ID LIKE 'B*'"));
   382     User::LeaveIfError(view.Prepare(aDb, TDbQuery(sqlStmt, EDbCompareCollated), TDbWindow::EUnlimited));
   383     User::LeaveIfError(view.EvaluateAll());
   384 
   385 	TInt cnt = ::PrintRecordsL(view, aTblName);
   386 	TEST(cnt == 2);
   387 
   388     CleanupStack::PopAndDestroy(&view);
   389 	}
   390 
   391 //Test case 3. Check SELECT statement with LIKE & ORDER BY keywords when the key field is a string.
   392 static void LikeOrderTestL(RDbNamedDatabase& aDb, const TDesC& aTblName, const RArray<TNameBuf>& aTestStrArray)
   393 	{
   394     RDbView view;
   395     CleanupClosePushL(view);
   396     
   397     TBuf<128> sqlStmt;
   398     sqlStmt.Append(_L("SELECT ID, DATA FROM "));
   399     sqlStmt.Append(aTblName);
   400     sqlStmt.Append(_L(" WHERE ID LIKE 'B*' ORDER BY ID"));
   401     User::LeaveIfError(view.Prepare(aDb, TDbQuery(sqlStmt, EDbCompareCollated), TDbWindow::EUnlimited));
   402     User::LeaveIfError(view.EvaluateAll());
   403 
   404 	TInt cnt = ::PrintRecordsL(view, aTblName);
   405 	TEST(cnt == 2);
   406 	::AssertRecordsOrder(view, aTblName, aTestStrArray);
   407 
   408     CleanupStack::PopAndDestroy(&view);
   409 	}
   410 
   411 //Test case 4. Indexed table. The index is a string field.
   412 static void IndexTestL(RDbNamedDatabase& aDb, const TDesC& aTblName, const RArray<TNameBuf>& aTestStrArray)
   413 	{
   414 	_LIT(KIdxName, "ID");
   415 	::CreateIndexL(aDb, aTblName, KIdxName);
   416 	
   417 	RDbTable tbl;
   418 	CleanupClosePushL(tbl);
   419 	TEST2(tbl.Open(aDb, aTblName, RDbRowSet::EReadOnly), KErrNone);
   420 	TEST2(tbl.SetIndex(KIdxName), KErrNone);
   421 
   422 	(void)::PrintRecordsL(tbl, aTblName);
   423 	::AssertRecordsOrder(tbl, aTblName, aTestStrArray);
   424 
   425     CleanupStack::PopAndDestroy(&tbl);
   426 	}
   427 
   428 ///////////////////////////////////////////////////////////////////////////////////////
   429 ///////////////////////////////////////////////////////////////////////////////////////
   430 //The main test function.
   431 //Call your new test functions from here
   432 static void RunTestsL()
   433 	{
   434 	TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-LEGACY-DBMSSTRCOMP-0001 Init test environment "));
   435 	::InitEnvL();
   436 
   437     RArray<TNameBuf> testStrArray;
   438     CleanupClosePushL(testStrArray);
   439 	::FillStrArraySortedL(testStrArray);
   440 
   441 	TheTest.Next(_L("SELECT, ORDER BY, EDbColText16"));
   442 	::OrderByTestL(TheDb, KTestTableName1, testStrArray);
   443 
   444 	TheTest.Next(_L("SELECT, ORDER BY, EDbColLongText16"));
   445 	::OrderByTestL(TheDb, KTestTableName2, testStrArray);
   446 	
   447 	TheTest.Next(_L("SELECT, LIKE, EDbColText16"));
   448 	::LikeTestL(TheDb, KTestTableName1);
   449 
   450 	TheTest.Next(_L("SELECT, LIKE, EDbColLongText16"));
   451 	::LikeTestL(TheDb, KTestTableName2);
   452 	
   453     RArray<TNameBuf> testStrArray2;
   454     CleanupClosePushL(testStrArray2);
   455     testStrArray2.AppendL(testStrArray[2]);//"bbB"
   456     testStrArray2.AppendL(testStrArray[3]);//"BbB"
   457 
   458 	TheTest.Next(_L("SELECT, LIKE, ORDER BY, EDbColText16"));
   459 	::LikeOrderTestL(TheDb, KTestTableName1, testStrArray2);
   460 
   461 	TheTest.Next(_L("SELECT, LIKE, ORDER BY, EDbColLongText16"));
   462 	::LikeOrderTestL(TheDb, KTestTableName2, testStrArray2);
   463 	
   464 	TheTest.Next(_L("Index, EDbColText16"));
   465 	::IndexTestL(TheDb, KTestTableName1, testStrArray);
   466 
   467 // Not possible to create a key with EDbColLongText16
   468 //	TheTest.Next(_L("Index, EDbColLongText16"));
   469 //	::IndexTestL(TheDb, KTestTableName2, testStrArray);
   470 	
   471 	//Add tests here!
   472 	
   473     CleanupStack::PopAndDestroy(&testStrArray2);
   474     CleanupStack::PopAndDestroy(&testStrArray);
   475 	}
   476 
   477 TInt E32Main()
   478 	{
   479 	TheTest.Title();
   480 
   481 	__UHEAP_MARK;
   482 
   483 	CTrapCleanup* trapCleanup = CTrapCleanup::New();
   484 	TEST(trapCleanup != NULL);
   485 
   486 	TInt err = TheFs.Connect();
   487 	TEST2(err, KErrNone);
   488 	::SetupTestDirectory();
   489 
   490 	::DeleteDataFile(KTestDatabase);
   491 
   492 	TRAP(err, ::RunTestsL());
   493 	TheDb.Close();
   494 #ifndef __TOOLS2__
   495 	TheDbSession.Close();
   496 #endif
   497 	TheFs.Close();
   498 	TEST2(err, KErrNone);
   499 
   500 #ifndef __linux__
   501 	TRAP(err, TheCrcChecker.GenerateCrcL(KTestDatabase));
   502 	TEST(err==KErrNone);
   503 #ifndef __TOOLS2__
   504 	TRAPD(lc, err = TheCrcChecker.DumpCrcRecordsL(KCrcRecord));
   505 	TEST(err==KErrNone);
   506 	TEST(lc==KErrNone);
   507 #else
   508 	TRAPD(lc, err = TheCrcChecker.ValidateCrcRecordsL(KCrcRecord));
   509 	TPtrC errmsg;
   510 	TheCrcChecker.ErrorReportL(err, errmsg);
   511 	RDebug::Print(errmsg);
   512 	TheTest(err==KErrNone || err==TDBMS_CRCChecks::ECrcCheckOk);
   513 #endif
   514 #endif
   515 
   516 	::DeleteDataFile(KTestDatabase);
   517 
   518 	TheTest.Printf(_L("Wait DBMS server shutdown...\n"));
   519 	User::After(KExitDelay);
   520 
   521 	TheTest.End();
   522 	TheTest.Close();
   523 
   524 	delete trapCleanup;
   525 
   526 	__UHEAP_MARKEND;
   527 
   528 	return 0;
   529 	}
   530 
   531