First public contribution.
1 // Copyright (c) 2006-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.
21 #include "SqlSrvStartup.h" //KSqlMajorVer, KSqlMinorVer, KSqlBuildVer
23 ///////////////////////////////////////////////////////////////////////////////////////
26 RTest TheTest(_L("t_sqlbadclient test"));
27 _LIT(KTestDir, "c:\\test\\");
28 _LIT(KTestDbName1, "c:\\test\\t_sqlbadclient.db");
29 _LIT(KTestDbName2, "c:[1111D1C1]t_sqlbadclient.db");
31 #if defined __WINS__ || defined __WINSCW__
32 const TInt KTestIterCount = 5000;
34 const TInt KTestIterCount = 4000;
36 const TInt KMaxDesArgLen = 1000;
45 //////////////////////////////////////////////////////////////////////////////////////
47 //If the SQL server crashes and the test receives KErrServerTerminated error, then the
48 //next set will contain the last:
49 // - iteration number;
53 // - IPC arguments values;
57 TSqlSrvHandleType iHandleType;
60 TArgType iArgType[KMaxMessageArguments];
61 TInt iIntArg[KMaxMessageArguments];
62 TBuf<KMaxDesArgLen> iTextArg[KMaxMessageArguments];
63 TBuf8<KMaxDesArgLen> iBinArg[KMaxMessageArguments];
66 //////////////////////////////////////////////////////////////////////////////////////
68 _LIT(KPanicCategory, "SrvTerm");
69 _LIT(KPanicCategory2, "InvArg");
70 const TInt KPanicCode = 1111;
71 const TInt KPanicCode2 = 2222;
73 ///////////////////////////////////////////////////////////////////////////////////////
75 //Deletes all created test files.
76 void DeleteTestFiles()
78 RSqlDatabase::Delete(KTestDbName1);
81 ///////////////////////////////////////////////////////////////////////////////////////
82 ///////////////////////////////////////////////////////////////////////////////////////
83 //Test macros and functions
84 void Check1(TInt aValue, TInt aLine, TBool aPrintThreadName = EFalse)
92 TName name = th.Name();
93 RDebug::Print(_L("*** Thread %S, Line %d\r\n"), &name, aLine);
97 RDebug::Print(_L("*** Line %d\r\n"), aLine);
99 TheTest(EFalse, aLine);
102 void Check2(TInt aValue, TInt aExpected, TInt aLine, TBool aPrintThreadName = EFalse)
104 if(aValue != aExpected)
110 TName name = th.Name();
111 RDebug::Print(_L("*** Thread %S, Line %d Expected error: %d, got: %d\r\n"), &name, aLine, aExpected, aValue);
115 RDebug::Print(_L("*** Line %d, Expected error: %d, got: %d\r\n"), aLine, aExpected, aValue);
117 TheTest(EFalse, aLine);
120 #define TEST(arg) ::Check1((arg), __LINE__)
121 #define TEST2(aValue, aExpected) ::Check2(aValue, aExpected, __LINE__)
122 #define TTEST(arg) ::Check1((arg), __LINE__, ETrue)
123 #define TTEST2(aValue, aExpected) ::Check2(aValue, aExpected, __LINE__, ETrue)
125 ///////////////////////////////////////////////////////////////////////////////////////
127 //Creates file session instance and the test directory
130 TInt err = TheFs.Connect();
131 TEST2(err, KErrNone);
133 err = TheFs.MkDir(KTestDir);
134 TEST(err == KErrNone || err == KErrAlreadyExists);
137 //Starts the SQL server process.
138 TInt StartSqlServer()
140 const TUid KSqlSrvUid3 = {0x10281E17};//The same UID is in SqlSrv.mmp file
141 const TUidType serverUid(KNullUid, KNullUid, KSqlSrvUid3);
142 _LIT(KSqlSrvImg, "SqlSrv");//SQL server image name
144 TInt err = server.Create(KSqlSrvImg, KNullDesC, serverUid);
150 server.Rendezvous(stat);
151 if(stat != KRequestPending)
153 server.Kill(0); // abort startup
157 server.Resume(); // logon OK - start the server
159 User::WaitForRequest(stat); // wait for start or death
160 // we can't use the 'exit reason' if the server panicked as this
161 // is the panic 'reason' and may be '0' which cannot be distinguished
163 err = (server.ExitType() == EExitPanic) ? KErrGeneral : stat.Int();
168 //////////////////////////////////////////////////////////////////////////////////////////////////
169 ///////////////////////////// RTestSqlDbSession //////////////////////////////////
170 //////////////////////////////////////////////////////////////////////////////////////////////////
172 //Test client SQL session class
173 class RTestSqlDbSession : public RSessionBase
176 TInt Connect(const TVersion& aVersion);
178 TInt SendReceive(TInt aFunction);
179 TInt SendReceive(TInt aFunction, const TIpcArgs& aArgs);
182 TInt DoCreateSession(const TVersion& aVersion);
185 TInt RTestSqlDbSession::Connect(const TVersion& aVersion)
187 TInt err = DoCreateSession(aVersion);
190 TIpcArgs ipcArgs(KTestDbName1().Length(), &KTestDbName1(), 0, 0);
191 err = SendReceive(ESqlSrvDbOpen, ipcArgs);
193 if(err != KErrNone && err != KErrAlreadyExists)
200 void RTestSqlDbSession::Close()
204 (void)SendReceive(ESqlSrvDbClose);
206 RSessionBase::Close();
209 TInt RTestSqlDbSession::SendReceive(TInt aFunction)
211 return RSessionBase::SendReceive(aFunction);
214 TInt RTestSqlDbSession::SendReceive(TInt aFunction, const TIpcArgs& aArgs)
216 return RSessionBase::SendReceive(aFunction, aArgs);
219 TInt RTestSqlDbSession::DoCreateSession(const TVersion& aVersion)
221 const TInt KTimesToRetryConnection = 2;
222 TInt retry = KTimesToRetryConnection;
223 _LIT(KSqlSrvName, "!SQL Server");//SqlDb server name
226 TInt err = CreateSession(KSqlSrvName, aVersion);
227 if(err != KErrNotFound && err != KErrServerTerminated)
235 err = ::StartSqlServer();
236 if(err != KErrNone && err != KErrAlreadyExists)
243 //////////////////////////////////////////////////////////////////////////////////////////////////
244 //////////////////////////////////////////////////////////////////////////////////////////////////
246 TInt SendReceive(RTestSqlDbSession aSession, TSqlSrvHandleType aHandleType, TInt aFunction, TInt aHandle, TIpcArgs& aArgs)
248 return aSession.SendReceive(::MakeMsgCode(static_cast <TSqlSrvFunction> (aFunction), aHandleType, aHandle), aArgs);
251 TInt SendReceive(RTestSqlDbSession aSession, TInt aFunction, TIpcArgs& aArgs)
253 return aSession.SendReceive(aFunction, aArgs);
256 void PrintIterationCount(TInt aIteration)
258 if((aIteration % 100) == 0)
262 TDateTime dt = time.DateTime();
264 tbuf.Format(_L("%02d:%02d:%02d.%06d"), dt.Hour(), dt.Minute(), dt.Second(), dt.MicroSecond());
265 RDebug::Print(_L("-----[%S] Test iterations: %d\r\n"), &tbuf, aIteration);
269 //Worker thread function.
270 //It behaves as a malicious client. Connects to the SQL server. In each test iteration generates some random values
271 //for the function number, handle, handle type, IPC arguments. Then sends a command to the server using these
272 //randomly generated values. If the server crashes and the thread function receives KErrServerTerminated error,
273 //then the thread kills itself and the main thread will get KPanicCategory and KPanicCode as a reason for the
274 //worker thread's death. The last set of randomly generated values will be stored in the memory, pointed by aData argument.
275 TInt ThreadFunc1(void* aData)
279 CTrapCleanup* tc = CTrapCleanup::New();
282 TThreadData* p = static_cast <TThreadData*> (aData);
284 TThreadData& data = *p;
286 TVersion sqlSoftwareVersion(KSqlMajorVer, KSqlMinorVer, KSqlBuildVer);
287 RTestSqlDbSession sess;
288 TInt err = sess.Connect(sqlSoftwareVersion);
289 TTEST2(err, KErrNone);
291 while(++data.iIteration <= KTestIterCount)
293 PrintIterationCount(data.iIteration);
297 data.iFunction = Math::Rand(data.iSeed) % (ESqlSrvStreamClose + 1);//ESqlSrvStreamClose - the last server message number)
299 while(data.iFunction >= ESqlSrvResourceMark && data.iFunction <= ESqlSrvSetHeapFailure);
300 for(TInt i=0;i<KMaxMessageArguments;++i)
302 //Initialize arguments
303 data.iArgType[i] = static_cast <TArgType> (Math::Rand(data.iSeed) % ELastArgType);
304 switch(data.iArgType[i])
307 data.iIntArg[i] = Math::Rand(data.iSeed) % 9711;
308 args.Set(i, data.iIntArg[i]);
312 TInt len = Math::Rand(data.iSeed) % KMaxDesArgLen;
313 data.iTextArg[i].SetLength(len);
314 args.Set(i, &data.iTextArg[i]);
319 TInt len = Math::Rand(data.iSeed) % KMaxDesArgLen;
320 data.iBinArg[i].SetLength(len);
321 args.Set(i, &data.iBinArg[i]);
325 User::Panic(KPanicCategory2, KPanicCode2);
330 User::SetJustInTime(EFalse);
332 if((Math::Rand(data.iSeed) % 5) == 0) //Pass a handle (statement or stream)
334 data.iHandleType = (Math::Rand(data.iSeed) % 2) ? ESqlSrvStatementHandle : ESqlSrvStreamHandle;
335 data.iHandle = Math::Rand(data.iSeed) % 64;
336 err = ::SendReceive(sess, data.iHandleType, data.iFunction, data.iHandle, args);
340 err = ::SendReceive(sess, data.iFunction, args);
342 if(err == KErrServerTerminated)
344 User::Panic(KPanicCategory, KPanicCode);
346 User::SetJustInTime(ETrue);
359 @SYMTestCaseID SYSLIB-SQL-CT-1769
360 @SYMTestCaseDesc In a loop, where the loop iterations are less than KTestIterCount (5000 at the moment),
361 the test creates a public shared database and a worker thread, which will behave as
362 malicious client. If the worker thread crashes the SQL server, then the worker thread
363 dies notifying the main thread about the SQL server crash. The main thread prints the
364 values used in the last IPC call and crashes the test.
365 @SYMTestPriority High
366 @SYMTestActions SQL, Malicious client simulation test.
367 @SYMTestExpectedResults Test must not fail
375 TThreadData* p = new TThreadData;
377 TThreadData& data = *p;
381 data.iSeed = now.Int64();
383 _LIT(KThreadName, "WorkThrd");
385 for(data.iIteration=0;data.iIteration<KTestIterCount;++data.iIteration)
387 PrintIterationCount(data.iIteration);
388 //Create/open the test database
390 TInt err = db.Create(KTestDbName1);
391 TEST(err == KErrNone || err == KErrAlreadyExists);
394 err = db.Exec(_L8("CREATE TABLE A(Id INTEGER); INSERT INTO A(Id) VALUES(1); INSERT INTO A(Id) VALUES(2);"));
398 //Run the malicious client (one worker theread which will try to crash the SQL server)
400 TEST2(thread.Create(KThreadName, &ThreadFunc1, 0x2000, 0x1000, 0x10000, &data, EOwnerProcess), KErrNone);
401 TRequestStatus status;
402 thread.Logon(status);
403 TEST2(status.Int(), KRequestPending);
405 User::WaitForRequest(status);
406 User::SetJustInTime(ETrue); // enable debugger panic handling
407 if(thread.ExitType() == EExitPanic)
409 if(thread.ExitReason() == KPanicCode)
411 TheTest.Printf(_L("##Server terminated!\r\n"));
412 TheTest.Printf(_L("##Iteration=%d, Handle type(hex)=%X, Function(hex)=%X, Handle=%d\r\n"), data.iIteration, data.iHandleType, data.iFunction, data.iHandle);
413 for(TInt i=0;i<KMaxMessageArguments;++i)
415 switch(data.iArgType[i])
418 TheTest.Printf(_L("##Arg %d, Integer, value=%d\r\n"), i, data.iIntArg[i]);
421 TheTest.Printf(_L("##Arg %d, Text, length=%d\r\n"), i, data.iTextArg[i].Length());
424 TheTest.Printf(_L("##Arg %d, Binary, length=%d\r\n"), i, data.iBinArg[i].Length());
427 TheTest.Printf(_L("##Arg %d, Invalid argument type: %d\r\n"), i, data.iArgType[i]);
436 User::SetJustInTime(ETrue); // enable debugger panic handling
440 RSqlSecurityPolicy CreateSecurityPolicy()
442 RSqlSecurityPolicy securityPolicy;
443 const TSecurityPolicy KDefaultPolicy(TSecurityPolicy::EAlwaysPass);
444 TInt err = securityPolicy.Create(KDefaultPolicy);
445 TEST2(err, KErrNone);
446 return securityPolicy;
449 void DoBadNameTest(RSqlDatabase& aDb)
451 TFileName invalidFileName1;
452 invalidFileName1.SetLength(KMaxFileName);
453 //Initialise the first character so that it is not treated as an empty descriptor by the sever
454 invalidFileName1[0] = TChar(204); //0xCC
455 TFileName invalidFileName2;
456 invalidFileName2.SetLength(KMaxFileName);
457 invalidFileName2.Fill(TChar(204));//0xCC
459 TInt err = aDb.Attach(invalidFileName1, invalidFileName2);
460 TheTest.Printf(_L("Attach, invalid database name-1, err=%d\r\n"), err);
461 TEST(err != KErrNone);
462 err = aDb.Attach(invalidFileName2, invalidFileName1);
463 TheTest.Printf(_L("Attach, invalid database name-2, err=%d\r\n"), err);
464 TEST(err != KErrNone);
465 err = aDb.Attach(KTestDbName2, invalidFileName2);
466 TheTest.Printf(_L("Attach, invalid database name-3, err=%d\r\n"), err);
467 TEST(err != KErrDied);
470 err = aDb.Detach(invalidFileName2);
471 TheTest.Printf(_L("Detach, invalid database name-3, err=%d\r\n"), err);
472 TEST2(err, KErrNone);
474 err = aDb.Attach(KTestDbName2, invalidFileName1);
475 TheTest.Printf(_L("Attach, invalid database name-4, err=%d\r\n"), err);
476 TEST(err != KErrDied);
479 err = aDb.Detach(invalidFileName1);
480 TheTest.Printf(_L("Detach, invalid database name-4, err=%d\r\n"), err);
481 TEST2(err, KErrNone);
484 RSqlDatabase::TSize size;
486 err = aDb.Size(size, invalidFileName1);
487 TheTest.Printf(_L("Size, invalid database name-1, err=%d\r\n"), err);
488 TEST(err != KErrNone);
489 err = aDb.Size(size, invalidFileName2);
490 TheTest.Printf(_L("Size, invalid database name-2, err=%d\r\n"), err);
491 TEST(err != KErrNone);
493 err = aDb.Compact(RSqlDatabase::EMaxCompaction, invalidFileName1);
494 TheTest.Printf(_L("Compact, invalid database name-1, err=%d\r\n"), err);
495 TEST(err != KErrNone);
496 err = aDb.Compact(RSqlDatabase::EMaxCompaction, invalidFileName2);
497 TheTest.Printf(_L("Compact, invalid database name-2, err=%d\r\n"), err);
498 TEST(err != KErrNone);
501 err = stmt.Prepare(aDb, _L("SELECT * FROM A"));
502 TEST2(err, KErrNone);
504 err = stmt.ColumnIndex(invalidFileName1);
505 TheTest.Printf(_L("ColumnIndex, invalid column name-1, err=%d\r\n"), err);
506 TEST(err != KErrNone);
507 err = stmt.ColumnIndex(invalidFileName2);
508 TheTest.Printf(_L("ColumnIndex, invalid column name-2, err=%d\r\n"), err);
509 TEST(err != KErrNone);
510 err = stmt.ParameterIndex(invalidFileName1);
511 TheTest.Printf(_L("ParameterIndex, invalid parameter name-1, err=%d\r\n"), err);
512 TEST(err != KErrNone);
513 err = stmt.ParameterIndex(invalidFileName2);
514 TheTest.Printf(_L("ParameterIndex, invalid parameter name-2, err=%d\r\n"), err);
515 TEST(err != KErrNone);
521 @SYMTestCaseID SYSLIB-SQL-UT-4048
522 @SYMTestCaseDesc Bad database names - robustness test.
523 The test defines file names with invalid content and attempts to use
524 these file names with the SQL API. The test should not cause crashes
526 @SYMTestPriority High
527 @SYMTestActions Bad database names - robustness test.
528 @SYMTestExpectedResults Test must not fail
534 TFileName invalidFileName1;
535 invalidFileName1.SetLength(KMaxFileName);
536 TFileName invalidFileName2;
537 invalidFileName2.SetLength(KMaxFileName / 2);
539 //Initialise the first character so that it is not treated as an empty descriptor by the sever
540 invalidFileName1[0] = TChar(204); //0xCC
541 invalidFileName2[0] = TChar(204); //0xCC
543 (void)RSqlDatabase::Delete(KTestDbName1);
544 (void)RSqlDatabase::Delete(KTestDbName2);
547 TInt err = db.Create(invalidFileName1);
548 TEST(err != KErrNone);
549 err = db.Create(invalidFileName2);
550 TEST(err != KErrNone);
552 err = db.Open(invalidFileName1);
553 TEST(err != KErrNone);
554 err = db.Open(invalidFileName2);
555 TEST(err != KErrNone);
557 err = db.Create(KTestDbName1);
558 TEST2(err, KErrNone);
559 err = db.Exec(_L("CREATE TABLE A(I INTEGER)"));
563 RSqlSecurityPolicy sp = CreateSecurityPolicy();
564 err = db.Create(KTestDbName2, sp);
565 TEST2(err, KErrNone);
567 err = db.Exec(_L("CREATE TABLE A(I INTEGER)"));
571 TheTest.Printf(_L("Bad names test - public shared database\r\n"));
572 err = db.Open(KTestDbName1);
573 TEST2(err, KErrNone);
577 TheTest.Printf(_L("Bad names test - public secure shared database\r\n"));
578 err = db.Open(KTestDbName2);
579 TEST2(err, KErrNone);
583 (void)RSqlDatabase::Delete(KTestDbName2);
584 (void)RSqlDatabase::Delete(KTestDbName1);
586 err = RSqlDatabase::Copy(invalidFileName1, invalidFileName2);
587 TheTest.Printf(_L("Copy database, err=%d\r\n"), err);
588 TEST(err != KErrNone);
589 err = RSqlDatabase::Delete(invalidFileName1);
590 TheTest.Printf(_L("Delete database-1, err=%d\r\n"), err);
591 TEST(err != KErrNone);
592 err = RSqlDatabase::Delete(invalidFileName2);
593 TheTest.Printf(_L("Delete database-2, err=%d\r\n"), err);
594 TEST(err != KErrNone);
598 @SYMTestCaseID PDS-SQL-CT-4200
599 @SYMTestCaseDesc Invalid sql software version test.
600 @SYMTestPriority High
601 @SYMTestActions The test verifies that the SQL server checks that the software version of SQL sessions
602 to be created is less or equal to the current version of the server software.
603 If that is not true then the SQL server does not create the session annd returns KErrNotSupported.
604 @SYMTestExpectedResults Test must not fail
607 void InvalidSoftwareVersionTest()
609 (void)RSqlDatabase::Delete(KTestDbName1);
611 TInt err = db.Create(KTestDbName1);
612 TEST2(err, KErrNone);
615 //Smaller version number
616 TVersion sqlSoftwareVersion1(1, 0, 0);
617 RTestSqlDbSession sess1;
618 err = sess1.Connect(sqlSoftwareVersion1);
620 TEST2(err, KErrNone);
622 //Bigger version number 1
623 TVersion sqlSoftwareVersion2(1, 97, 3);
624 RTestSqlDbSession sess2;
625 err = sess2.Connect(sqlSoftwareVersion2);
626 TEST2(err, KErrNotSupported);
628 //Bigger version number 2
629 TVersion sqlSoftwareVersion3(78, 0, 1);
630 RTestSqlDbSession sess3;
631 err = sess3.Connect(sqlSoftwareVersion3);
632 TEST2(err, KErrNotSupported);
634 //The current version number
635 TVersion sqlSoftwareVersion4(KSqlMajorVer, KSqlMinorVer, KSqlBuildVer);
636 RTestSqlDbSession sess4;
637 err = sess4.Connect(sqlSoftwareVersion4);
639 TEST2(err, KErrNone);
641 (void)RSqlDatabase::Delete(KTestDbName1);
646 TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-SQL-CT-1769 Bad client test "));
648 TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4048 Bad names test"));
650 TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-CT-4200 Invalid software version test"));
651 InvalidSoftwareVersionTest();
658 CTrapCleanup* tc = CTrapCleanup::New();
675 User::Heap().Check();