diff -r 000000000000 -r bde4ae8d615e os/persistentdata/persistentstorage/dbms/tdbms/t_dbdefect.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/persistentdata/persistentstorage/dbms/tdbms/t_dbdefect.cpp Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,1333 @@ +// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include +#include +#include +#include +#include + +LOCAL_D RTest TheTest (_L ("t_dbdefect")); +LOCAL_D CTrapCleanup* TheTrapCleanup = NULL; +LOCAL_D RSemaphore TheWaitToStartSem; +LOCAL_D RSemaphore TheWaitForThreadsReadySem; +LOCAL_D RFs TheFs; +LOCAL_D RDbs TheDbs1, TheDbs2; +LOCAL_D RDbNamedDatabase TheDb1, TheDb2; + +_LIT (KName, "ConnectTestThread_"); +_LIT (KStart, "Starting thread %x.\n"); +_LIT (KConnect, "Thread %x: Waiting to connect...\n"); +_LIT (KConSuccess, "Thread %x: Connection succeeded.\n"); +_LIT (KConFailed, "Thread %x: Connection failed. Error %d.\n"); +_LIT (KStatus, "Status of thread %x is %d.\n"); + + +_LIT(KTable, "TABLE"); +_LIT(KColName, "Fld"); +_LIT(KCol2Name, "Fld2"); +_LIT(KDbName, "C:\\DBMS-TST\\TESTDB22.DB"); +_LIT(KSQLInsert1, "INSERT INTO TABLE (Fld, Fld2) VALUES ('ACDC\\','BLAH')"); +_LIT(KSQLInsert2, "INSERT INTO TABLE (Fld) VALUES ('ABCDEFGH')"); +_LIT(KSQLInsert3, "INSERT INTO TABLE (Fld) VALUES ('A?CDEFGH')"); +_LIT(KSQLInsert4, "INSERT INTO TABLE (Fld) VALUES ('A?*?CDEFGH')"); +_LIT(KSQLInsert5, "INSERT INTO TABLE (Fld) VALUES ('A*CDEFGH')"); +_LIT(KSQLInsert6, "INSERT INTO TABLE (Fld, Fld2) VALUES ('ADCDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOP','ADCB')"); +_LIT(KSQLInsert7, "INSERT INTO TABLE (Fld) VALUES ('XZD\\FZX')"); + +_LIT(KSqlRequestGranularity, "SELECT Fld FROM test WHERE (Fld LIKE '1' AND Fld LIKE '2') AND Fld LIKE '3' AND Fld LIKE '4' AND Fld LIKE '5' AND Fld LIKE '6'"); + +_LIT(KText16Name, "text16"); +_LIT(KTableName, "test"); +_LIT(KIndexName, "test_index"); +_LIT(KMaxStringFormat, "%0256d"); + +void TestCleanup() + { + TheDb2.Close(); + TheDb1.Close(); + TheDbs2.Close(); + TheDbs1.Close(); + (void)TheFs.Delete(KDbName); + TheFs.Close(); + } + +//----------------------------------------------------------------------------- +// +// Test macros and functions. +// +//----------------------------------------------------------------------------- +// If (!aValue) then the test will be panicked, the test data files will be +// deleted. +LOCAL_C void Check(TInt aValue, TInt aLine) + { + if(!aValue) + { + TestCleanup(); + TheTest(EFalse, aLine); + } + } + + +// If (aValue != aExpected) then the test will be panicked, the test data files +// will be deleted. +LOCAL_C void Check(TInt aValue, TInt aExpected, TInt aLine) + { + if(aValue != aExpected) + { + RDebug::Print(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue); + TestCleanup(); + TheTest(EFalse, aLine); + } + } + + +//Use these to test conditions. +#define TEST(arg) ::Check((arg), __LINE__) +#define TEST2(aValue, aExpected) ::Check((aValue), (aExpected), __LINE__) +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +struct TTest + { + const TText* result; + const TText* query; + }; + +const TTest KQuery[]= + { + {_S("ACDC\\"),_S("SELECT Fld FROM TABLE WHERE Fld LIKE 'ACDC\\' AND Fld2 LIKE '*BL*'")}, + {_S("A*CDEFGH"),_S("SELECT * FROM TABLE WHERE Fld LIKE '*A\\*C*' ESCAPE '\\'")}, + {_S("A?CDEFGH"),_S("SELECT * FROM TABLE WHERE Fld LIKE '*A\\?C*' ESCAPE '\\'")}, + {_S("A?*?CDEFGH"),_S("SELECT * FROM TABLE WHERE Fld LIKE '*A\\?\\*\\?C*' ESCAPE '\\'")}, + {_S("ADCDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOP"),_S("SELECT * FROM TABLE WHERE Fld LIKE '*1234*'")}, + {_S("BLAH"),_S("SELECT Fld2 FROM TABLE WHERE Fld LIKE '*AC*' AND Fld2 LIKE '?LA?'")}, + {_S("BLAH"),_S("SELECT Fld2 FROM TABLE WHERE Fld LIKE 'NOTINTABLE' OR Fld2 LIKE '?LA?'")}, + {_S("ADCDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOP"),_S("SELECT * FROM TABLE WHERE Fld LIKE '*ADC*' AND Fld2 LIKE 'ADC?'")}, + {_S("A*CDEFGH"),_S("SELECT Fld FROM TABLE WHERE Fld LIKE '*\\*C*' ESCAPE '\\'")}, + {_S("XZD\\FZX"),_S("SELECT Fld FROM TABLE WHERE Fld LIKE '*D\\\\*' ESCAPE '\\'")} + }; + +const TTest KBadQuery[]= + { + {_S(""),_S("SELECT * FROM TABLE WHERE Fld LIKE 'A?C' ESCAPE '\\'")}, + {_S(""),_S("SELECT * FROM TABLE WHERE Fld LIKE 'A*C' ESCAPE '\\'")}, + {_S(""),_S("SELECT * FROM TABLE WHERE Fld LIKE '?A\\?C' ESCAPE '\\'")}, + {_S(""),_S("SELECT * FROM TABLE WHERE Fld LIKE '?A\\?C?' ESCAPE '\\'")}, + {_S(""),_S("SELECT * FROM TABLE WHERE Fld LIKE '*A\\??\\?C*' ESCAPE '\\'")}, + {_S(""),_S("SELECT * FROM TABLE WHERE Fld LIKE '*A*\\*C*' ESCAPE '\\'")}, + {_S(""),_S("SELECT * FROM TABLE WHERE Fld LIKE 'ABC' ESCAPE '\\'")}, + {_S(""),_S("SELECT * FROM TABLE WHERE Fld LIKE 'ABC*' ESCAPE '\\'")}, + {_S(""),_S("SELECT * FROM TABLE WHERE Fld LIKE '*ABC' ESCAPE '\\'")} + }; + +const TInt KNumQueries = 10; +const TInt KNumBadQueries = 9; +const TInt KThreadCount = 3; +const TInt KOneSecond = 1000000; +const TInt KDbNameLen = 255; +const TInt KMaxColName = 32; + +static void DoDbmsConnectThreadSubFunctionL (TInt aThreadNumber) + { + // The session + RDbs TheDbSession; + CleanupClosePushL (TheDbSession); + + RDebug::Print (KStart (), aThreadNumber); + RDebug::Print (KConnect (), aThreadNumber); + + // Signal the main thread to continue + TheWaitForThreadsReadySem.Signal (1); + + // Wait until we are signalled + TheWaitToStartSem.Wait (); + + // Connect to Dbms + TInt r = TheDbSession.Connect (); + + if (r == KErrNone) + { + RDebug::Print (KConSuccess (), aThreadNumber); + TheDbSession.Close (); + } + else + { + RDebug::Print (KConFailed (), aThreadNumber, r); + User::Leave (r); + } + + CleanupStack::PopAndDestroy (1); // session + } + +static TInt DoDbmsConnectThread (TAny* aThreadNumber) + { + __UHEAP_MARK; + + CTrapCleanup* trapCleanup = CTrapCleanup::New (); + __ASSERT_ALWAYS (trapCleanup!=NULL, User::Invariant ()); + + TInt* threadNumber = static_cast (aThreadNumber); + TRAPD (err, DoDbmsConnectThreadSubFunctionL (*threadNumber)); + + delete trapCleanup; + + __UHEAP_MARKEND; + + return err; + } + +/** +@SYMTestCaseID SYSLIB-DBMS-CT-0644 +@SYMTestCaseDesc Test for defect no 44697 +@SYMTestPriority Medium +@SYMTestActions Test for defect fixes +@SYMTestExpectedResults Test must not fail +@SYMREQ REQ0000 +*/ +LOCAL_C void Defect_DEF44697L () + { + TheTest.Next (_L (" @SYMTestCaseID:SYSLIB-DBMS-CT-0644 Defect_DEF44697L ")); + + __UHEAP_MARK; + + // find out the number of open handles + TInt startProcessHandleCount; + TInt startThreadHandleCount; + RThread ().HandleCount (startProcessHandleCount, startThreadHandleCount); + + ///////////////////// + // The Test Begins... + + // Create semaphores + ::CleanupClosePushL (::TheWaitForThreadsReadySem); + User::LeaveIfError (::TheWaitForThreadsReadySem.CreateLocal (0)); + + ::CleanupClosePushL (::TheWaitToStartSem); + User::LeaveIfError (::TheWaitToStartSem.CreateLocal (0)); + + // Create the threads. + RThread createTestThread_1; + RThread createTestThread_2; + RThread createTestThread_3; + + TBuf<100> thread_name; + TInt KThreadNumber1 = 1; + TInt KThreadNumber2 = 2; + TInt KThreadNumber3 = 3; + + // Create the first test thread______________________________ + thread_name = KName (); + thread_name.AppendNum (KThreadNumber1); + + User::LeaveIfError ( + createTestThread_1.Create (thread_name, + (TThreadFunction) DoDbmsConnectThread, + KDefaultStackSize, + KMinHeapSize, + KMinHeapSize, + &KThreadNumber1)); + + // Default priority of Main thread is EPriorityNormal + createTestThread_1.SetPriority(EPriorityMore); + + TheTest.Printf (_L ("%S thread started\n"), &thread_name); + + // Request notification when the thread dies. + TRequestStatus threadStatus_1; + createTestThread_1.Logon (threadStatus_1); + + //___________________________________________________________ + + // Create the second test thread______________________________ + thread_name = KName (); + thread_name.AppendNum (KThreadNumber2); + + User::LeaveIfError ( + createTestThread_2.Create (thread_name, + (TThreadFunction) DoDbmsConnectThread, + KDefaultStackSize, + KMinHeapSize, + KMinHeapSize, + &KThreadNumber2)); + + // Default priority of Main thread is EPriorityNormal + createTestThread_2.SetPriority(EPriorityMore); + + TheTest.Printf (_L ("%S thread started\n"), &thread_name); + + // Request notification when the tread dies. + TRequestStatus threadStatus_2; + createTestThread_2.Logon (threadStatus_2); + + //___________________________________________________________ + + // Create the third test thread______________________________ + thread_name = KName (); + thread_name.AppendNum (KThreadNumber3); + + User::LeaveIfError ( + createTestThread_3.Create (thread_name, + (TThreadFunction) DoDbmsConnectThread, + KDefaultStackSize, + KMinHeapSize, + KMinHeapSize, + &KThreadNumber3)); + + // Default priority of Main thread is EPriorityNormal + createTestThread_3.SetPriority(EPriorityMore); + + TheTest.Printf (_L ("%S thread started\n"), &thread_name); + + // Request notification when the tread dies. + TRequestStatus threadStatus_3; + createTestThread_3.Logon (threadStatus_3); + + //___________________________________________________________ + + TheTest (threadStatus_1.Int () == KRequestPending); + TheTest (threadStatus_2.Int () == KRequestPending); + TheTest (threadStatus_3.Int () == KRequestPending); + + // Make threads eligible for execution + createTestThread_1.Resume (); + createTestThread_2.Resume (); + createTestThread_3.Resume (); + + // The way this works is that the main thread blocks until all + // the test threads are ready (semaphore 1) and then signals them + // (semaphore 2). + // + // 1: Main thread Waits for ALL test threads to become ready. + // 2: Main thread Signals ALL test threads to run. + // + // 1: Test thread Signals Main thread + // 2: Test thread Waits for Main thread + // + // There is still a slight race condition between the + // test thread signalling (semaphore 1) and then waiting + // (semaphore 2) which is why we use both higher priority test + // threads and a timer. + // + // The problems come with the way Time slicing works due to + // other threads of higher priority being run. + // + // Higher priority: Ensures the test thread runs before the + // the main thread. + // + // Timer: Safeguards when multiple core processors are being used. + // + // The Higher priority fixes the problem on single core processors + // and multiple cores processors (SMP) where each core can run a + // thread. + // + // It should also ensure that if the system is so busy that it + // affects the test thread execution, the test thread will still + // get to the Wait state before the Main thread can Signal. + // + // However, on multiple cores the Main thread may run at the same + // time as the test thread, so we need to make sure that when the + // test thread Signals it can acheive its Wait state before the + // Main thread Signals. For example, if the timer has elapsed on the + // Main thread and the sytem is busy, the test thread should still + // run before the Main thread due to it higher priority. + // + // We also have to think about things like priority inheritance + // where a thread that has a handle on a Mutex inherits the same + // priority as a thread Waiting on it. This shouldn't happen for + // Semaphores as there is no one handle, i.e. no critical section. + // + // This higher priority inheritance will take affect when a low + // priority thread that has a handle on the Mutex blocks because of + // another medium priority running thread. So in effect a high + // priority thread Waiting on this Mutex is also blocked. + // + // It is also worth noting that on EKA1 emulator, scheduling is + // performed by windows. On EKA2 emulator scheduling is performed + // by Symbian so that it is the same as hardware. + + TheWaitForThreadsReadySem.Wait(); + TheWaitForThreadsReadySem.Wait(); + TheWaitForThreadsReadySem.Wait(); + + // Sleep for a while to allow threads to block on the semaphore + User::After (KOneSecond<<2); // 4 seconds + + // Signal all the threads to continue + TheWaitToStartSem.Signal (KThreadCount); + + // Wait for all threads to complete, don't care on the order. + User::WaitForRequest (threadStatus_1); + User::WaitForRequest (threadStatus_2); + User::WaitForRequest (threadStatus_3); + + TheTest.Printf (KStatus, KThreadNumber1, threadStatus_1.Int ()); + TheTest.Printf (KStatus, KThreadNumber2, threadStatus_2.Int ()); + TheTest.Printf (KStatus, KThreadNumber3, threadStatus_3.Int ()); + + TheTest (threadStatus_1.Int () == KErrNone); + TheTest (threadStatus_2.Int () == KErrNone); + TheTest (threadStatus_3.Int () == KErrNone); + + CleanupStack::PopAndDestroy (&::TheWaitToStartSem); + CleanupStack::PopAndDestroy (&::TheWaitForThreadsReadySem); + + // The Test Ends... + ///////////////////// + + // check that no handles have leaked + TInt endProcessHandleCount; + TInt endThreadHandleCount; + RThread ().HandleCount (endProcessHandleCount, endThreadHandleCount); + + TheTest (startThreadHandleCount == endThreadHandleCount); + + __UHEAP_MARKEND; + } + + + +// Test for LIKE Predicate for EDbColLongText16 +LOCAL_C void LikePredicateDbColLongText16TestL() + { + TheTest.Next (_L ("LikePredicateDbColLongText16TestL")); + //Creating database + + RFs fsSession; + User::LeaveIfError(fsSession.Connect()); + CleanupClosePushL(fsSession); + RDbNamedDatabase database; + User::LeaveIfError(database.Replace(fsSession, KDbName)); + CleanupClosePushL(database); + + //Create table + + CDbColSet* columns= CDbColSet::NewLC(); + + TDbCol name(KColName,EDbColLongText16,KDbNameLen); + name.iAttributes = TDbCol::ENotNull; + + TDbCol name2(KCol2Name,EDbColLongText16,KDbNameLen); + + columns->AddL(name); + columns->AddL(name2); + User::LeaveIfError (database.CreateTable (KTable, *columns)); + CleanupStack::PopAndDestroy(); // columns + + // Insert values into table + TInt error = database.Execute(KSQLInsert1); + TheTest(error>=0); + error =database.Execute(KSQLInsert2); + TheTest(error>=0); + error =database.Execute(KSQLInsert3); + TheTest(error>=0); + error = database.Execute(KSQLInsert4); + TheTest(error>=0); + error = database.Execute(KSQLInsert5); + TheTest(error>=0); + error = database.Execute(KSQLInsert6); + TheTest(error>=0); + error = database.Execute(KSQLInsert7); + TheTest(error>=0); + + + TheTest.Next(_L("Test for valid LIKE predicate queries")); + + + for(TInt i =0;i TScriptLine; + TInt count =0; + while (view.AtRow()) + { + view.GetL(); + count++; + RDbColReadStream rd; + rd.OpenLC(view,1); + TScriptLine text; + rd.ReadL(text,view.ColLength(1)); + CleanupStack::PopAndDestroy(); + RDebug::Print(_L("Expected result: %s Actual Result: %S\n"),(KQuery[i].result),&text); + TInt err = text.Compare(TPtrC(KQuery[i].result)); + TheTest(err ==0); + view.NextL(); + } + view.Close(); + } + + + // test for illegal statements, check they return KErrArgument + TheTest.Next(_L("Test that illegal queries return KErrArgument")); + + + for(TInt j =0;jAddL(name); + columns->AddL(name2); + + User::LeaveIfError (database.CreateTable (KTable, *columns)); + CleanupStack::PopAndDestroy(); // columns + + // Insert values into the table + TInt error = database.Execute(KSQLInsert1); + TheTest(error>=0); + error =database.Execute(KSQLInsert2); + TheTest(error>=0); + error =database.Execute(KSQLInsert3); + TheTest(error>=0); + error = database.Execute(KSQLInsert4); + TheTest(error>=0); + error = database.Execute(KSQLInsert5); + TheTest(error>=0); + error = database.Execute(KSQLInsert6); + TheTest(error>=0); + error = database.Execute(KSQLInsert7); + TheTest(error>=0); + + TheTest.Next(_L("Test for valid LIKE predicate queries")); + + + for(TInt i =0;i=0); + TInt evErr = view.EvaluateAll(); + TheTest(evErr==0); + TBuf8<256> result; + TBuf8<256> colname; + result.Copy(TPtrC(KQuery[i].result)); + view.FirstL(); + + while (view.AtRow()) + { + view.GetL(); + RDbColReadStream rd; + rd.OpenLC(view,1); + rd.ReadL(colname,view.ColLength(1)); + CleanupStack::PopAndDestroy(); + RDebug::Print(_L("Expected result: %S Actual Result: %S\n"),&result,&colname); + TInt err = colname.CompareF(result); + TheTest(err ==0); + + view.NextL(); + } + + view.Close(); + } + + // test for illegal statements, check they return KErrArgument + TheTest.Next(_L("Test that illegal queries return KErrArgument")); + + + + for(TInt j =0;jAddL(name); + columns->AddL(name2); + + User::LeaveIfError (database.CreateTable (KTable, *columns)); + CleanupStack::PopAndDestroy(); // columns + + // Insert values into the table + TInt error = database.Execute(KSQLInsert1); + TheTest(error>=0); + error =database.Execute(KSQLInsert2); + TheTest(error>=0); + error =database.Execute(KSQLInsert3); + TheTest(error>=0); + error = database.Execute(KSQLInsert4); + TheTest(error>=0); + error = database.Execute(KSQLInsert5); + TheTest(error>=0); + error = database.Execute(KSQLInsert6); + TheTest(error>=0); + error = database.Execute(KSQLInsert7); + TheTest(error>=0); + + + TheTest.Next(_L("Test for valid LIKE predicate queries")); + + + for(TInt i =0;i colname; + TBufC<256> res; + view.FirstL(); + while (view.AtRow()) + { + view.GetL(); + colname = view.ColDes(1); + res= KQuery[i].result; + RDebug::Print(_L("Expected result: %s Actual Result: %S\n"),(KQuery[i].result),&colname); + TInt err = colname.Compare(TPtrC(KQuery[i].result)); + TheTest(err ==0); + view.NextL(); + } + view.Close(); + } + + // test for illegal statements, check they return KErrArgument + TheTest.Next(_L("Test that illegal queries return KErrArgument")); + + for(TInt j =0;jAddL(text16Col); + + TBuf targetColName; + targetColName = KText16Name; + + // create table + User::LeaveIfError(database.CreateTable(KTableName, *columns)); + + //create index + CDbKey* key = CDbKey::NewLC(); + TInt keyLength = 122; + TDbKeyCol keyCol(targetColName, keyLength); + key->AddL(keyCol); + User::LeaveIfError(database.CreateIndex(KIndexName, KTableName, *key)); + CleanupStack::PopAndDestroy(2); // key and columns + + //insert rows + HBufC* sqlQueryBuf = HBufC::NewLC(512); + TPtr sqlQuery(sqlQueryBuf->Des()); + _LIT(KSQLInsertFormat, "SELECT %S FROM %S"); + sqlQuery.Format(KSQLInsertFormat, &targetColName, &KTableName); + + RDbView insertview; + User::LeaveIfError(insertview.Prepare(database, TDbQuery(sqlQuery), RDbView::EInsertOnly)); + + HBufC* tmpBuf = HBufC::NewLC(maxTextLength); + TPtr maxString(tmpBuf->Des()); + maxString.Format(KMaxStringFormat, 0); + insertview.InsertL(); + insertview.SetColL(1, maxString); + insertview.PutL(); + insertview.Close(); + + //delete the row + RDbView deleteview; + User::LeaveIfError(deleteview.Prepare(database, TDbQuery(sqlQuery), RDbView::EUpdatable)); + User::LeaveIfError(deleteview.EvaluateAll()); + + while (deleteview.NextL()) + { + deleteview.GetL(); + TRAPD(err , deleteview.DeleteL()); + TheTest(err==KErrNone); + } + deleteview.Close(); + + CleanupStack::PopAndDestroy(2); // tmpBuf, sqlQueryBuf + CleanupStack::PopAndDestroy(&database); // database + CleanupStack::PopAndDestroy(&fs); // fs + } + + /** +@SYMTestCaseID SYSLIB-DBMS-UT-1894 +@SYMTestCaseDesc Testing memory handling in CSqlMultiNode::Concatenate() +@SYMTestPriority Medium +@SYMTestActions Execute a special request to a database which will trigger CSqlMultiNode::Concatenate(), and the size of one of the SQL nodes will be divisible by the CSqlMultiNode granularity +@SYMTestExpectedResults The test should not fail or panic. +@SYMDEF INC093657 +*/ +LOCAL_C void Defect_INC093657L () + { + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-DBMS-UT-1894 Defect INC093657 ")); + RFs fs; + CleanupClosePushL(fs); + User::LeaveIfError(fs.Connect()); + + // create database + RDbNamedDatabase database; + CleanupClosePushL(database); + User::LeaveIfError(database.Replace(fs, _L("c:\\test.db"))); + + CDbColSet* columns = CDbColSet::NewLC(); + const TInt maxTextLength = 256; + TDbCol column(KColName, EDbColLongText16, maxTextLength); + columns->AddL(column); + + // create table + User::LeaveIfError(database.CreateTable(KTableName, *columns)); + CleanupStack::PopAndDestroy(); // columns + + //execute a pointless request that is intended to detect subtle memory corruptions in CSqlMultiNode::Concatenate + RDbView view; + TInt err = view.Prepare(database, TDbQuery(KSqlRequestGranularity)); + + TheTest(err==KErrNone); + + view.Close(); + database.Destroy(); + + CleanupStack::PopAndDestroy(&database); // database + CleanupStack::PopAndDestroy(&fs); // fs + } + +/** +@SYMTestCaseID SYSLIB-DBMS-UT-3467 +@SYMTestCaseDesc Test for DEF105615 "DBMS, CDbColSet::operator[](TDbColNo) operator may access an invalid memory". + The test creates a table with 3 coluumns and a multi-column key (3 columns). The column + names length is such that when RDbRowSet::ColSetL() is called for retrieving the column + names, the CDbColSet array data member will make just a single memory allocation, where + all TDbCol elements will be stored. Then the test repeats 100 times, the following statements: + ; + ; + 100). + Create 2 database connections. + Open that database from connection 1 and execute an incremental update operation + in a transaction. At the same time try to open and close the same table from + connection 2, mixing these operations with the RDbUpdate::Next() calls from + connection 1. So the call pattern should be: + @code + RDbUpdate dbUpdate; + .... + while((err = dbUpdate.Next()) > 0) //from "Conenction 1" + { + RDbTable tbl; + err = tbl.Open(TheDb2, _L("A")); //from "Conenction 2" + ... + } + @endcode +@SYMTestExpectedResults The test should not fail or panic. +@SYMDEF INC101720 +*/ +void Defect_INC101720() + { + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-DBMS-UT-3413 ")); + //Create the test database + TInt err = TheDb1.Replace(TheFs, KDbName); + TEST2(err, KErrNone); + TheDb1.Close(); + //Establish the first database connection + err = TheDbs1.Connect(); + TEST2(err, KErrNone); + err = TheDb1.Open(TheDbs1, KDbName); + TEST2(err, KErrNone); + //Create a test table and fill the table with enough test records (> 100) + err = TheDb1.Execute(_L("CREATE TABLE A(Id COUNTER, Id2 INTEGER, Name LONG VARCHAR)")); + TEST2(err, KErrNone); + const TInt KTestRecCount = 200; + err = TheDb1.Begin(); + TEST2(err, KErrNone); + for(TInt i=0;i sql; + TUint32 id = Math::Random() % KTestRecCount; + sql.Format(KSqlFmtStr, id + 1); + err = TheDb1.Execute(sql); + TEST2(err, 1); + } + err = TheDb1.Commit(); + TEST2(err, KErrNone); + //Establish a second connection with the same test database + err = TheDbs2.Connect(); + TEST2(err, KErrNone); + err = TheDb2.Open(TheDbs2, KDbName); + TEST2(err, KErrNone); + //The test: Conenction 1 - "incremental update" operation. + // Connection 2 - "open table/close table" operations mixed with the incremental Next-s. + //Expectation: The test must not fail. + err = TheDb1.Begin(); + TEST2(err, KErrNone); + RDbUpdate dbUpdate; + err = dbUpdate.Execute(TheDb1, _L("UPDATE A SET Name = 'ModifiedNameString' WHERE Id2 > 10")); + TEST2(err, KErrNone); + TInt step = 0; + while((err = dbUpdate.Next()) > 0) + { + ++step; + RDbTable tbl; + err = tbl.Open(TheDb2, _L("A")); + TEST2(err, KErrNone); + tbl.Close(); + } + TEST(step > 1);//just to be sure that the test executes dbUpdate.Next() more than once + TEST2(err, KErrNone); + dbUpdate.Close(); + err = TheDb1.Commit(); + TEST2(err, KErrNone); + //Cleanup + TheDb2.Close(); + TheDbs2.Close(); + TheDb1.Close(); + TheDbs1.Close(); + } + +/** +@SYMTestCaseID SYSLIB-DBMS-UT-3484 +@SYMTestCaseDesc DBMS Hindi collation doesn't work on long text fields. +@SYMTestPriority Medium +@SYMTestActions This test is to check that DBMS correctly sorts columns using Collation, when + the columns are of type EDbColLongText16. Previous implementations split the + strings to be compared into chunks, however this could cause it to be sorted + incorrectly if it was split on a combining or accent character. This fault + occurs on the default locale as well as Hindi. Test steps: + * Create a database table and adds several unicode strings to EDbColLongText16 + column in table. One set of strings have an ascii character followed by + an accent (e + ') and the other set have the combined equivilant ascii + character (è). These should have the same sort order,however if are split + then will compare differently. + * Sort the columns using EDbCompareCollated + * Check that the columns were sorted in the correct order +@SYMTestExpectedResults The columns should get sorted into ascending order correctly +@SYMDEF INC107268 +*/ +void Defect_INC107268L() + { + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-DBMS-UT-3484 Defect INC107268 - DBMS Hindi collation doesn't work on long text fields")); + + // some unicode characters + const TChar Ka(0x0061); // a + const TChar Kb(0x0062); // b + const TChar Ke(0x0065); // e + const TChar Kgrave(0x0060); // ' (grave) + const TChar Kegrave(0x00e8); // e with grave + const TChar K1(0x0031); // 1 + const TChar K2(0x0032); // 2 + + // the maximum characters in a EDbColLongText16 string before dbms stops storing + // the string inline, and we need to read it from a stream (see TBlobKey). + const TInt KInlineLimit = 127; + + // maximum number of characters buffered in TBlobKey when string stored out of line. + // (see TBlobKey::ETruncSize which is in bytes) + const TInt KTruncLimit = 16; + + const TInt KMaxStringSize = 256; + + TBuf inLineBoundryA; + TBuf inLineBoundryB; + TBuf truncBoundryA; + TBuf truncBoundryB; + TBuf padding; + + // this string will be stored inline. It should sort to be < stringB + inLineBoundryA.Fill(Ka, KInlineLimit-2); + inLineBoundryA.Append(Kegrave); + inLineBoundryA.Append(K1); + + // this string is just over the break point, so *is* truncated. + // this is expected to get sorted incorrecly as combining character is split off (negative test case) + inLineBoundryB.Fill(Ka, KInlineLimit-2); + inLineBoundryB.Append(Ke); + inLineBoundryB.Append(Kgrave); + inLineBoundryB.Append(K2); + + padding.Fill(Kb, KInlineLimit); + + // this string is longger that KInlineLimit so is stored out of line + truncBoundryA.Fill(Kb, KTruncLimit-2); + truncBoundryA.Append(Kegrave); + truncBoundryA.Append(K1); + truncBoundryA.Append(padding); + + // this string has combining characters that fall on boundry of ETruncSize value (32 bytes) + truncBoundryB.Fill(Kb, KTruncLimit-2); + truncBoundryB.Append(Ke); + truncBoundryB.Append(Kgrave); + truncBoundryB.Append(K2); + truncBoundryB.Append(padding); + + + // e and '(grave) characters seperately + TBuf<3> e_grave; + e_grave.Append( Ke ); + e_grave.Append( Kgrave ); + + // e with grave character - this should sort the same as e_grave + TBuf<3> egrave; + egrave.Append( Kegrave ); + + TBuf<1> nullString; + + e_grave.Append(K2); // make e_grave sort second + egrave.Append(K1); // make egrave sort first + + // Check with database + _LIT(KPosLmLandmarkTable, "lmt_landmark"); + _LIT(KPosLmLandmarkIdCol, "lmc_lmid"); + _LIT(KPosLmNameCol, "lmc_name"); + + TInt err = TheDb1.Replace( TheFs, KDbName ); + TEST2 (err, KErrNone); + CleanupClosePushL(TheDb1); + + CDbColSet* columns = CDbColSet::NewLC(); + TDbCol idField( KPosLmLandmarkIdCol, EDbColUint32 ); + idField.iAttributes |= TDbCol::EAutoIncrement; + columns->AddL( idField ); + columns->AddL( TDbCol( KPosLmNameCol, EDbColLongText16 ) ); // Works with EDbColText16. Defect only for EDbColLongText16. + + err = TheDb1.CreateTable( KPosLmLandmarkTable, *columns ); + TEST2 (err, KErrNone); + CleanupStack::PopAndDestroy(columns); + + RDbTable table; + err = table.Open( TheDb1, KPosLmLandmarkTable ); + TEST2 (err, KErrNone); + CleanupClosePushL(table); + + // add rows to table + table.InsertL(); + table.SetColL( 2, egrave); // row 0 - sorted 8th + table.PutL(); + + table.InsertL(); + table.SetColL( 2, e_grave ); // row 1 - sorted 9th + table.PutL(); + + table.InsertL(); + table.SetColL( 2, inLineBoundryA ); // row 2 - sorted 3rd (incorrectly - negative test case) + table.PutL(); + + table.InsertL(); + table.SetColL( 2, inLineBoundryB ); // row 3 - sorted 2nd (incorrectly - negative test case) + table.PutL(); + + table.InsertL(); + table.SetColL( 2, nullString ); // row 4 - sorted 1st + table.PutL(); + + table.InsertL(); + table.SetColL( 2, truncBoundryB ); // row 5 - sorted 5th + table.PutL(); + + table.InsertL(); + table.SetColL( 2, truncBoundryA ); // row 6 - sorted 4th + table.PutL(); + + + CleanupStack::PopAndDestroy(); // table.close() + + // do an sql select with Order By to sort columns + _LIT(KPosLmSqlSelectOrderByString, "SELECT %S, %S FROM %S ORDER BY %S"); + TBuf<200> sql; + sql.Format( KPosLmSqlSelectOrderByString, + &KPosLmLandmarkIdCol, + &KPosLmNameCol, + &KPosLmLandmarkTable, + &KPosLmNameCol); + + RDbView view; + CleanupClosePushL(view); + err = view.Prepare( TheDb1, TDbQuery( sql, EDbCompareCollated ) ); + TEST2 (err, KErrNone); + err = view.EvaluateAll(); + TEST2 (err, KErrNone); + + // Now check that view is ordered correctly + const TUint32 ExpectedOrder[] = {4,3,2,6,5,0,1}; + TInt x = 0; + while (view.NextL()) + { + view.GetL(); + TEST2(view.ColUint32(1), ExpectedOrder[x]); // check we got the expected order + x++; + } + TEST2(x, 7); // check we got the right number of values + CleanupStack::PopAndDestroy(2); // TheDb1.Close(); view.Close() + } + + +/** +@SYMTestCaseID PDS-DBMS-UT-4001 +@SYMTestCaseDesc INC128224 SQL statement with ESCAPE panics in DBMS. +@SYMTestPriority High +@SYMTestActions The test verifies that SELECT statement with a LIKE redicate with an ESCAPE clause + followed by another LIKE predicate does not causes a crash in DBMS. + The test creates a test database, inserts some records and then runs a SELECT + statement that has one LIKE predicate with an ESCAPE followed by another LIKE. +@SYMTestExpectedResults The test should pass and should not crash the DBMS +@SYMDEF INC128224 +*/ +void INC128224L() + { + TheTest.Next(_L(" @SYMTestCaseID:PDS-DBMS-UT-4001 INC128224 SQL statement with ESCAPE panics in DBMS")); + + TInt err = TheDb1.Replace(TheFs, KDbName); + TEST2(err, KErrNone); + + err = TheDb1.Execute(_L("CREATE TABLE A(T1 VARCHAR(100),T2 VARCHAR(150))")); + TEST2(err, KErrNone); + err = TheDb1.Execute(_L("INSERT INTO A(T1,T2) VALUES('AAAAAA','HGS')")); + TEST2(err, 1); + err = TheDb1.Execute(_L("INSERT INTO A(T1,T2) VALUES('BBBBBB','RRR')")); + TEST2(err, 1); + err = TheDb1.Execute(_L("INSERT INTO A(T1,T2) VALUES('C*CCCCC','AAQWWT')")); + TEST2(err, 1); + err = TheDb1.Execute(_L("INSERT INTO A(T1,T2) VALUES('DDDDDD','TUQQPQQQQSSS')")); + TEST2(err, 1); + err = TheDb1.Execute(_L("INSERT INTO A(T1,T2) VALUES('C*CABS','IAAAIAAAIA')")); + TEST2(err, 1); + + RDbView view; + err = view.Prepare(TheDb1, _L("SELECT * FROM A WHERE (T1 LIKE '*C\\*C*' ESCAPE '\\') AND (T2 LIKE 'I?A*')")); + TEST2(err, KErrNone); + TInt cnt = 0; + while(view.NextL()) + { + view.GetL(); + TPtrC t1 = view.ColDes(1); + TPtrC t2 = view.ColDes(2); + RDebug::Print(_L("T1=\"%S\", T2=\"%S\"\r\n"), &t1, &t2); + ++cnt; + } + view.Close(); + TEST2(cnt, 1); + + TheDb1.Close(); + (void)TheFs.Delete(KDbName); + } + +LOCAL_C void DoTestsL () + { + __UHEAP_MARK; + CleanupClosePushL(TheFs); + Defect_INC076370L(); + Defect_INC083027L(); + Defect_DEF44697L (); + Defect_INC093657L(); + Defect_INC101720(); + DEF105615L(); + DEF105615_2(); + Defect_INC107268L(); + INC128224L(); + CleanupStack::PopAndDestroy(); // TheFs.Close() + __UHEAP_MARKEND; + } + + +GLDEF_C TInt E32Main () + { + __UHEAP_MARK; + TheTest.Title (); + TheTest.Start (_L ("Verify Defect Fixes")); + + TheTrapCleanup = CTrapCleanup::New (); + __ASSERT_ALWAYS (TheTrapCleanup!=NULL, User::Invariant ()); + + TInt err = TheFs.Connect(); + TheTest(err == KErrNone); + + TRAP (err,DoTestsL ()); + TheTest (err==KErrNone); + + delete TheTrapCleanup; + + //Wait some time, because DBMS server won't be destroyed right after the last DBMS session + //being clossed. + TheTest.Printf(_L("Wait DBMS server shutdown...\n")); + const TInt KExitDelay = 6000000; + User::After(KExitDelay); + + TheTest.End (); + TheTest.Close (); + + __UHEAP_MARKEND; + return (0); + }