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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
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.
28 #undef __UHEAP_MARKEND
29 #define __UHEAP_MARKEND
31 LOCAL_D TDBMS_CRCChecks TheCrcChecker;
33 #ifndef __linux__ //No CRC test on LINUX
35 const TPtrC KCrcRecord=_L("\\epoc32\\winscw\\c\\dbms-tst\\T_DBMSSTRCOMP.CRC");
37 const TPtrC KCrcRecord=_L("C:\\dbms-tst\\T_DBMSSTRCOMP.CRC");
41 /////////////////////////////////////////////////////////////////
45 const TPtrC KTestDatabase = _L(".\\dbms-tst\\T_DbmsStrComp.db");
47 const TPtrC KTestDatabase = _L("c:\\dbms-tst\\T_DbmsStrComp.db");
50 const TUint KExitDelay = 6 * 1000000;//6 seconds
52 static RTest TheTest(_L("T_DbmsStrComp test"));
54 static RDbNamedDatabase TheDb;
55 static RDbs TheDbSession;
58 _LIT(KTestTableName1, "TABLE1");//EDbColText16 key field
59 _LIT(KTestTableName2, "TABLE2");//EDbColLongText16 key field
67 static TColDef const KColDefs1[]=
69 {_S("ID"), EDbColText16, 0},
70 {_S("DATA"), EDbColUint32, 0},
73 static TColDef const KColDefs2[]=
75 {_S("ID"), EDbColLongText16, 0},
76 {_S("DATA"), EDbColUint32, 0},
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[] =
92 const TInt KTestStrCnt = sizeof(KTestStr) / sizeof(KTestStr[0]);
94 ///////////////////////////////////////////////////////////////////////////////////////
95 ///////////////////////////////////////////////////////////////////////////////////////
96 //Destroy test environment - global functions
98 //Deletes "aFullName" file.
99 static TInt DeleteDataFile(const TDesC& aFullName)
102 TInt err = fsSession.Connect();
106 err = fsSession.Entry(aFullName, entry);
109 RDebug::Print(_L("Deleting \"%S\" file.\n"), &aFullName);
110 err = fsSession.SetAtt(aFullName, 0, KEntryAttReadOnly);
113 RDebug::Print(_L("Error %d changing \"%S\" file attributes.\n"), err, &aFullName);
115 err = fsSession.Delete(aFullName);
118 RDebug::Print(_L("Error %d deleting \"%S\" file.\n"), err, &aFullName);
125 RDebug::Print(_L("Error %d connecting file session. File: %S.\n"), err, &aFullName);
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)
138 ::DeleteDataFile(KTestDatabase);
139 TheTest(EFalse, aLine);
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)
145 if(aValue != aExpected)
147 RDebug::Print(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue);
148 ::DeleteDataFile(KTestDatabase);
149 TheTest(EFalse, aLine);
152 //Use these to test conditions.
153 #define TEST(arg) ::Check((arg), __LINE__)
154 #define TEST2(aValue, aExpected) ::Check(aValue, aExpected, __LINE__)
156 ///////////////////////////////////////////////////////////////////////////////////////
157 ///////////////////////////////////////////////////////////////////////////////////////
160 //Prepares the test directory.
161 //TheFs.Connect() has to be called already.
162 static void SetupTestDirectory()
164 TInt err = TheFs.MkDir(KTestDatabase);
165 TEST(err == KErrNone || err == KErrAlreadyExists);
168 //Leaves with info message printed out
169 static void Leave(TInt aError, TInt aLine)
171 RDebug::Print(_L("*** Leave. Error: %d, Line: %d\r\n"), aError, aLine);
175 //Leaves if aError < 0 with info message printed out
176 static void LeaveIfError(TInt aError, TInt aLine)
178 if(aError < KErrNone)
180 ::Leave(aError, aLine);
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__)
189 //Creates the test DBMS session
190 static void CreateTestDbSession()
193 RDebug::Print(_L("Create DBMS session\n"));
194 TInt err = TheDbSession.Connect();
195 TEST2(err, KErrNone);
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)
205 RDebug::Print(_L("Create test database\n"));
206 TInt err = aDb.Replace(TheFs, KTestDatabase);
207 TEST2(err, KErrNone);
209 err = aDb.Open(aDbs, KTestDatabase);
210 TEST2(err, KErrNone);
214 static void DoCreateTestTableL(RDbNamedDatabase& aDb, const TDesC& aTblName, const TColDef aColDefs[])
216 CDbColSet* colSet = CDbColSet::NewLC();
217 for(const TColDef* colDef=aColDefs;colDef->iName;++colDef)
219 TDbCol col(TPtrC(colDef->iName), colDef->iType);
220 col.iAttributes = colDef->iAttributes;
223 TEST2(aDb.CreateTable(aTblName, *colSet), KErrNone);
224 CleanupStack::PopAndDestroy(colSet);
227 //Creates test tables
228 static void CreateTestTablesL(RDbNamedDatabase& aDb)
230 RDebug::Print(_L("Create test tables\n"));
231 ::DoCreateTestTableL(aDb, KTestTableName1, KColDefs1);
232 ::DoCreateTestTableL(aDb, KTestTableName2, KColDefs2);
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)
238 if(aTblName.CompareF(KTestTableName1) == 0)
240 aStrFldVal = aTbl.ColDes16(1);
244 RDbColReadStream blob;
245 blob.OpenLC(aTbl, 1);
246 blob.ReadL(aStrFldVal, aTbl.ColLength(1));
247 CleanupStack::PopAndDestroy();
251 //Prints all table records
252 static TInt PrintRecordsL(RDbRowSet& aTbl, const TDesC& aTblName)
254 RDebug::Print(_L("Table: %S\n"), &aTblName);
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);
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)
279 ::GetStrFieldValue(aTbl, aTblName, strFldVal);
280 TEST(aTestStrArray[rec] == strFldVal);
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)
291 CleanupClosePushL(tbl);
292 TEST2(tbl.Open(aDb, aTblName, RDbRowSet::EUpdatable), KErrNone);
293 for(TInt i=0;i<KTestStrCnt;++i)
296 tbl.SetColL(1, KTestStr[KTestStrCnt - i - 1]);
297 tbl.SetColL(2, i + 1);
300 TEST(tbl.CountL() == KTestStrCnt);
301 (void)::PrintRecordsL(tbl, aTblName);
302 CleanupStack::PopAndDestroy(&tbl);
305 //Adds the test data to test tables
306 static void AddTestDataL(RDbNamedDatabase& aDb)
308 RDebug::Print(_L("Add data to test tables\n"));
309 ::AddTestDataL(aDb, KTestTableName1);
310 ::AddTestDataL(aDb, KTestTableName2);
313 //Init test environment
314 static void InitEnvL()
316 ::CreateTestDbSession();
317 //Create test database and tables. Add some test data to them.
318 ::CreateTestDatabase(TheDbSession, TheDb);
319 ::CreateTestTablesL(TheDb);
320 ::AddTestDataL(TheDb);
323 //String comparison function, used in FillStrArraySorted() function.
324 static TInt CompareC(const TNameBuf& aName1, const TNameBuf& aName2)
326 return aName1.CompareC(aName2);
329 //Inserts all test string into an ordered array - aTestStrArray
330 static void FillStrArraySortedL(RArray<TNameBuf>& aTestStrArray)
332 for(TInt i=0;i<KTestStrCnt;++i)
334 User::LeaveIfError(aTestStrArray.InsertInOrder(KTestStr[i], TLinearOrder<TNameBuf>(CompareC)));
338 static void CreateIndexL(RDbNamedDatabase& aDb, const TDesC& aTblName, const TDesC& aColumnName)
340 RDebug::Print(_L("Create index. Table: %S, column: %S\n"), &aTblName, &aColumnName);
341 CDbKey* key = CDbKey::NewLC();
342 key->AddL(aColumnName);
344 key->SetComparison(EDbCompareCollated);
345 LEAVE_IF_ERROR(aDb.CreateIndex(aColumnName, aTblName, *key));
346 CleanupStack::PopAndDestroy(key);
349 ///////////////////////////////////////////////////////////////////////////////////////
350 ///////////////////////////////////////////////////////////////////////////////////////
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)
357 CleanupClosePushL(view);
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());
366 (void)::PrintRecordsL(view, aTblName);
367 ::AssertRecordsOrder(view, aTblName, aTestStrArray);
369 CleanupStack::PopAndDestroy(&view);
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)
376 CleanupClosePushL(view);
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());
385 TInt cnt = ::PrintRecordsL(view, aTblName);
388 CleanupStack::PopAndDestroy(&view);
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)
395 CleanupClosePushL(view);
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());
404 TInt cnt = ::PrintRecordsL(view, aTblName);
406 ::AssertRecordsOrder(view, aTblName, aTestStrArray);
408 CleanupStack::PopAndDestroy(&view);
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)
414 _LIT(KIdxName, "ID");
415 ::CreateIndexL(aDb, aTblName, KIdxName);
418 CleanupClosePushL(tbl);
419 TEST2(tbl.Open(aDb, aTblName, RDbRowSet::EReadOnly), KErrNone);
420 TEST2(tbl.SetIndex(KIdxName), KErrNone);
422 (void)::PrintRecordsL(tbl, aTblName);
423 ::AssertRecordsOrder(tbl, aTblName, aTestStrArray);
425 CleanupStack::PopAndDestroy(&tbl);
428 ///////////////////////////////////////////////////////////////////////////////////////
429 ///////////////////////////////////////////////////////////////////////////////////////
430 //The main test function.
431 //Call your new test functions from here
432 static void RunTestsL()
434 TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-LEGACY-DBMSSTRCOMP-0001 Init test environment "));
437 RArray<TNameBuf> testStrArray;
438 CleanupClosePushL(testStrArray);
439 ::FillStrArraySortedL(testStrArray);
441 TheTest.Next(_L("SELECT, ORDER BY, EDbColText16"));
442 ::OrderByTestL(TheDb, KTestTableName1, testStrArray);
444 TheTest.Next(_L("SELECT, ORDER BY, EDbColLongText16"));
445 ::OrderByTestL(TheDb, KTestTableName2, testStrArray);
447 TheTest.Next(_L("SELECT, LIKE, EDbColText16"));
448 ::LikeTestL(TheDb, KTestTableName1);
450 TheTest.Next(_L("SELECT, LIKE, EDbColLongText16"));
451 ::LikeTestL(TheDb, KTestTableName2);
453 RArray<TNameBuf> testStrArray2;
454 CleanupClosePushL(testStrArray2);
455 testStrArray2.AppendL(testStrArray[2]);//"bbB"
456 testStrArray2.AppendL(testStrArray[3]);//"BbB"
458 TheTest.Next(_L("SELECT, LIKE, ORDER BY, EDbColText16"));
459 ::LikeOrderTestL(TheDb, KTestTableName1, testStrArray2);
461 TheTest.Next(_L("SELECT, LIKE, ORDER BY, EDbColLongText16"));
462 ::LikeOrderTestL(TheDb, KTestTableName2, testStrArray2);
464 TheTest.Next(_L("Index, EDbColText16"));
465 ::IndexTestL(TheDb, KTestTableName1, testStrArray);
467 // Not possible to create a key with EDbColLongText16
468 // TheTest.Next(_L("Index, EDbColLongText16"));
469 // ::IndexTestL(TheDb, KTestTableName2, testStrArray);
473 CleanupStack::PopAndDestroy(&testStrArray2);
474 CleanupStack::PopAndDestroy(&testStrArray);
483 CTrapCleanup* trapCleanup = CTrapCleanup::New();
484 TEST(trapCleanup != NULL);
486 TInt err = TheFs.Connect();
487 TEST2(err, KErrNone);
488 ::SetupTestDirectory();
490 ::DeleteDataFile(KTestDatabase);
492 TRAP(err, ::RunTestsL());
495 TheDbSession.Close();
498 TEST2(err, KErrNone);
501 TRAP(err, TheCrcChecker.GenerateCrcL(KTestDatabase));
504 TRAPD(lc, err = TheCrcChecker.DumpCrcRecordsL(KCrcRecord));
508 TRAPD(lc, err = TheCrcChecker.ValidateCrcRecordsL(KCrcRecord));
510 TheCrcChecker.ErrorReportL(err, errmsg);
511 RDebug::Print(errmsg);
512 TheTest(err==KErrNone || err==TDBMS_CRCChecks::ECrcCheckOk);
516 ::DeleteDataFile(KTestDatabase);
518 TheTest.Printf(_L("Wait DBMS server shutdown...\n"));
519 User::After(KExitDelay);