sl@0: // Copyright (c) 2006-2010 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: #include <e32test.h>
sl@0: #include <bautils.h>
sl@0: #include <e32math.h>
sl@0: #include <sqldb.h>
sl@0: #include "SqlUtil.h"
sl@0: #include "SqlSrvStartup.h" //KSqlMajorVer, KSqlMinorVer, KSqlBuildVer
sl@0: 
sl@0: ///////////////////////////////////////////////////////////////////////////////////////
sl@0: 
sl@0: static RFs TheFs;
sl@0: RTest TheTest(_L("t_sqlbadclient test"));
sl@0: _LIT(KTestDir, "c:\\test\\");
sl@0: _LIT(KTestDbName1, "c:\\test\\t_sqlbadclient.db");
sl@0: _LIT(KTestDbName2, "c:[1111D1C1]t_sqlbadclient.db");
sl@0: 
sl@0: #if defined __WINS__ || defined __WINSCW__
sl@0: const TInt KTestIterCount = 5000;
sl@0: #else
sl@0: const TInt KTestIterCount = 4000;
sl@0: #endif
sl@0: const TInt KMaxDesArgLen = 1000;
sl@0: enum TArgType 
sl@0: 	{
sl@0: 	EIntArgType, 
sl@0: 	ETextArgType, 
sl@0: 	EBinArgType, 
sl@0: 	ELastArgType
sl@0: 	};
sl@0: 
sl@0: //////////////////////////////////////////////////////////////////////////////////////
sl@0: 
sl@0: //If the SQL server crashes and the test receives KErrServerTerminated error, then the 
sl@0: //next set will contain the last:
sl@0: // - iteration number;
sl@0: // - handle type;
sl@0: // - function code;
sl@0: // - handle;
sl@0: // - IPC arguments values;
sl@0: struct TThreadData
sl@0: 	{
sl@0: 	TInt				iIteration;
sl@0: 	TSqlSrvHandleType 	iHandleType;
sl@0: 	TInt 				iFunction;
sl@0: 	TInt 				iHandle;
sl@0: 	TArgType 			iArgType[KMaxMessageArguments];
sl@0: 	TInt 				iIntArg[KMaxMessageArguments];
sl@0: 	TBuf<KMaxDesArgLen> iTextArg[KMaxMessageArguments];
sl@0: 	TBuf8<KMaxDesArgLen> iBinArg[KMaxMessageArguments];
sl@0: 	TInt64 				iSeed;
sl@0: 	};
sl@0: //////////////////////////////////////////////////////////////////////////////////////
sl@0: 
sl@0: _LIT(KPanicCategory, "SrvTerm");
sl@0: _LIT(KPanicCategory2, "InvArg");
sl@0: const TInt KPanicCode = 1111;
sl@0: const TInt KPanicCode2 = 2222;
sl@0: 
sl@0: ///////////////////////////////////////////////////////////////////////////////////////
sl@0: 
sl@0: //Deletes all created test files.
sl@0: void DeleteTestFiles()
sl@0: 	{
sl@0: 	RSqlDatabase::Delete(KTestDbName1);
sl@0: 	}
sl@0: 
sl@0: ///////////////////////////////////////////////////////////////////////////////////////
sl@0: ///////////////////////////////////////////////////////////////////////////////////////
sl@0: //Test macros and functions
sl@0: void Check1(TInt aValue, TInt aLine, TBool aPrintThreadName = EFalse)
sl@0: 	{
sl@0: 	if(!aValue)
sl@0: 		{
sl@0: 		DeleteTestFiles();
sl@0: 		if(aPrintThreadName)
sl@0: 			{
sl@0: 			RThread th;
sl@0: 			TName name = th.Name();
sl@0: 			RDebug::Print(_L("*** Thread %S, Line %d\r\n"), &name, aLine);
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			RDebug::Print(_L("*** Line %d\r\n"), aLine);
sl@0: 			}
sl@0: 		TheTest(EFalse, aLine);
sl@0: 		}
sl@0: 	}
sl@0: void Check2(TInt aValue, TInt aExpected, TInt aLine, TBool aPrintThreadName = EFalse)
sl@0: 	{
sl@0: 	if(aValue != aExpected)
sl@0: 		{
sl@0: 		DeleteTestFiles();
sl@0: 		if(aPrintThreadName)
sl@0: 			{
sl@0: 			RThread th;
sl@0: 			TName name = th.Name();
sl@0: 			RDebug::Print(_L("*** Thread %S, Line %d Expected error: %d, got: %d\r\n"), &name, aLine, aExpected, aValue);
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			RDebug::Print(_L("*** Line %d, Expected error: %d, got: %d\r\n"), aLine, aExpected, aValue);
sl@0: 			}
sl@0: 		TheTest(EFalse, aLine);
sl@0: 		}
sl@0: 	}
sl@0: #define TEST(arg) ::Check1((arg), __LINE__)
sl@0: #define TEST2(aValue, aExpected) ::Check2(aValue, aExpected, __LINE__)
sl@0: #define TTEST(arg) ::Check1((arg), __LINE__, ETrue)
sl@0: #define TTEST2(aValue, aExpected) ::Check2(aValue, aExpected, __LINE__, ETrue)
sl@0: 
sl@0: ///////////////////////////////////////////////////////////////////////////////////////
sl@0: 
sl@0: //Creates file session instance and the test directory
sl@0: void CreateTestEnv()
sl@0:     {
sl@0: 	TInt err = TheFs.Connect();
sl@0: 	TEST2(err, KErrNone);
sl@0: 
sl@0: 	err = TheFs.MkDir(KTestDir);
sl@0: 	TEST(err == KErrNone || err == KErrAlreadyExists);
sl@0: 	}
sl@0: 
sl@0: //Starts the SQL server process.
sl@0: TInt StartSqlServer()
sl@0: 	{
sl@0: 	const TUid KSqlSrvUid3 = {0x10281E17};//The same UID is in SqlSrv.mmp file
sl@0: 	const TUidType serverUid(KNullUid, KNullUid, KSqlSrvUid3);
sl@0: 	_LIT(KSqlSrvImg, "SqlSrv");//SQL server image name
sl@0: 	RProcess server;
sl@0: 	TInt err = server.Create(KSqlSrvImg, KNullDesC, serverUid);
sl@0: 	if(err != KErrNone)
sl@0: 		{
sl@0: 		return err;
sl@0: 		}
sl@0: 	TRequestStatus stat;
sl@0: 	server.Rendezvous(stat);
sl@0: 	if(stat != KRequestPending)
sl@0: 		{
sl@0: 		server.Kill(0);		// abort startup
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		server.Resume();	// logon OK - start the server
sl@0: 		}
sl@0: 	User::WaitForRequest(stat);		// wait for start or death
sl@0: 	// we can't use the 'exit reason' if the server panicked as this
sl@0: 	// is the panic 'reason' and may be '0' which cannot be distinguished
sl@0: 	// from KErrNone
sl@0: 	err = (server.ExitType() == EExitPanic) ? KErrGeneral : stat.Int();
sl@0: 	server.Close();
sl@0: 	return err;
sl@0: 	}
sl@0: 
sl@0: //////////////////////////////////////////////////////////////////////////////////////////////////
sl@0: /////////////////////////////        RTestSqlDbSession          //////////////////////////////////
sl@0: //////////////////////////////////////////////////////////////////////////////////////////////////
sl@0: 
sl@0: //Test client SQL session class
sl@0: class RTestSqlDbSession : public RSessionBase
sl@0: 	{
sl@0: public:	
sl@0: 	TInt Connect(const TVersion& aVersion);
sl@0: 	void Close();
sl@0: 	TInt SendReceive(TInt aFunction);
sl@0: 	TInt SendReceive(TInt aFunction, const TIpcArgs& aArgs);
sl@0: 
sl@0: private:
sl@0: 	TInt DoCreateSession(const TVersion& aVersion);
sl@0: 	};
sl@0: 	
sl@0: TInt RTestSqlDbSession::Connect(const TVersion& aVersion)
sl@0: 	{
sl@0: 	TInt err = DoCreateSession(aVersion);
sl@0: 	if(err == KErrNone)
sl@0: 		{
sl@0: 		TIpcArgs ipcArgs(KTestDbName1().Length(), &KTestDbName1(), 0, 0);
sl@0: 		err = SendReceive(ESqlSrvDbOpen, ipcArgs);
sl@0: 		}
sl@0: 	if(err != KErrNone && err != KErrAlreadyExists)
sl@0: 		{
sl@0: 		Close();	
sl@0: 		}
sl@0: 	return err;
sl@0: 	}
sl@0: 
sl@0: void RTestSqlDbSession::Close()
sl@0: 	{
sl@0: 	if(Handle())
sl@0: 		{
sl@0: 		(void)SendReceive(ESqlSrvDbClose);
sl@0: 		}
sl@0: 	RSessionBase::Close();
sl@0: 	}
sl@0: 
sl@0: TInt RTestSqlDbSession::SendReceive(TInt aFunction)
sl@0: 	{
sl@0: 	return RSessionBase::SendReceive(aFunction);	
sl@0: 	}
sl@0: 	
sl@0: TInt RTestSqlDbSession::SendReceive(TInt aFunction, const TIpcArgs& aArgs)
sl@0: 	{
sl@0: 	return RSessionBase::SendReceive(aFunction, aArgs);	
sl@0: 	}
sl@0: 
sl@0: TInt RTestSqlDbSession::DoCreateSession(const TVersion& aVersion)
sl@0: 	{
sl@0: 	const TInt KTimesToRetryConnection = 2;
sl@0: 	TInt retry = KTimesToRetryConnection;
sl@0: 	_LIT(KSqlSrvName, "!SQL Server");//SqlDb server name
sl@0: 	for(;;)
sl@0: 		{
sl@0: 		TInt err = CreateSession(KSqlSrvName, aVersion);
sl@0: 		if(err != KErrNotFound && err != KErrServerTerminated)
sl@0: 			{
sl@0: 			return err;
sl@0: 			}
sl@0: 		if(--retry == 0)
sl@0: 			{
sl@0: 			return err;
sl@0: 			}
sl@0: 		err = ::StartSqlServer();
sl@0: 		if(err != KErrNone && err != KErrAlreadyExists)
sl@0: 			{
sl@0: 			return err;
sl@0: 			}
sl@0: 		}
sl@0: 	}
sl@0: 	
sl@0: //////////////////////////////////////////////////////////////////////////////////////////////////
sl@0: //////////////////////////////////////////////////////////////////////////////////////////////////
sl@0: 
sl@0: TInt SendReceive(RTestSqlDbSession aSession, TSqlSrvHandleType aHandleType, TInt aFunction, TInt aHandle, TIpcArgs& aArgs)
sl@0: 	{
sl@0: 	return aSession.SendReceive(::MakeMsgCode(static_cast <TSqlSrvFunction> (aFunction), aHandleType, aHandle), aArgs);
sl@0: 	}
sl@0: 
sl@0: TInt SendReceive(RTestSqlDbSession aSession, TInt aFunction, TIpcArgs& aArgs)
sl@0: 	{
sl@0: 	return aSession.SendReceive(aFunction, aArgs);
sl@0: 	}
sl@0: 
sl@0: void PrintIterationCount(TInt aIteration)
sl@0: 	{
sl@0: 	if((aIteration % 100) == 0)
sl@0: 		{
sl@0: 		TTime time;
sl@0: 		time.HomeTime();
sl@0: 		TDateTime dt = time.DateTime();
sl@0: 		TBuf<16> tbuf;
sl@0: 		tbuf.Format(_L("%02d:%02d:%02d.%06d"), dt.Hour(), dt.Minute(), dt.Second(), dt.MicroSecond());
sl@0: 		RDebug::Print(_L("-----[%S] Test iterations: %d\r\n"), &tbuf, aIteration);
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: //Worker thread function.
sl@0: //It behaves as a malicious client. Connects to the SQL server. In each test iteration generates some random values
sl@0: //for the function number, handle, handle type, IPC arguments. Then sends a command to the server using these
sl@0: //randomly generated values. If the server crashes and the thread function receives KErrServerTerminated error,
sl@0: //then the thread kills itself and the main thread will get KPanicCategory and KPanicCode as a reason for the
sl@0: //worker thread's death. The last set of randomly generated values will be stored in the memory, pointed by aData argument.
sl@0: TInt ThreadFunc1(void* aData)
sl@0: 	{
sl@0: 	__UHEAP_MARK;
sl@0: 	
sl@0: 	CTrapCleanup* tc = CTrapCleanup::New();
sl@0: 	TTEST(tc != NULL);
sl@0: 
sl@0: 	TThreadData* p = static_cast <TThreadData*> (aData);
sl@0: 	TTEST(p != NULL);
sl@0: 	TThreadData& data = *p;
sl@0: 
sl@0: 	TVersion sqlSoftwareVersion(KSqlMajorVer, KSqlMinorVer, KSqlBuildVer);
sl@0: 	RTestSqlDbSession sess;
sl@0: 	TInt err = sess.Connect(sqlSoftwareVersion);
sl@0: 	TTEST2(err, KErrNone);
sl@0: 
sl@0: 	while(++data.iIteration <= KTestIterCount)
sl@0: 		{
sl@0: 		PrintIterationCount(data.iIteration);
sl@0: 		TIpcArgs args;
sl@0: 		do
sl@0: 			{
sl@0: 			data.iFunction = Math::Rand(data.iSeed) % (ESqlSrvStreamClose + 1);//ESqlSrvStreamClose - the last server message number)
sl@0: 			}
sl@0: 		while(data.iFunction >= ESqlSrvResourceMark && data.iFunction <= ESqlSrvSetHeapFailure);
sl@0: 		for(TInt i=0;i<KMaxMessageArguments;++i)
sl@0: 			{
sl@0: 			//Initialize arguments
sl@0: 			data.iArgType[i] = static_cast <TArgType> (Math::Rand(data.iSeed) % ELastArgType);
sl@0: 			switch(data.iArgType[i])
sl@0: 				{
sl@0: 				case EIntArgType:
sl@0: 					data.iIntArg[i] = Math::Rand(data.iSeed) % 9711;
sl@0: 					args.Set(i, data.iIntArg[i]);
sl@0: 					break;
sl@0: 				case ETextArgType:
sl@0: 					{
sl@0: 					TInt len = Math::Rand(data.iSeed) % KMaxDesArgLen;	
sl@0: 					data.iTextArg[i].SetLength(len);
sl@0: 					args.Set(i, &data.iTextArg[i]);
sl@0: 					}
sl@0: 					break;
sl@0: 				case EBinArgType:
sl@0: 					{
sl@0: 					TInt len = Math::Rand(data.iSeed) % KMaxDesArgLen;	
sl@0: 					data.iBinArg[i].SetLength(len);
sl@0: 					args.Set(i, &data.iBinArg[i]);
sl@0: 					}
sl@0: 					break;
sl@0: 				default:
sl@0: 					User::Panic(KPanicCategory2, KPanicCode2);
sl@0: 					break;
sl@0: 				}
sl@0: 			}
sl@0: 		//Send arguments
sl@0: 		User::SetJustInTime(EFalse);
sl@0: 		TInt err = KErrNone;
sl@0: 		if((Math::Rand(data.iSeed) % 5) == 0)	//Pass a handle (statement or stream)
sl@0: 			{
sl@0: 			data.iHandleType = (Math::Rand(data.iSeed) % 2) ? ESqlSrvStatementHandle : ESqlSrvStreamHandle;
sl@0: 			data.iHandle = Math::Rand(data.iSeed) % 64;
sl@0: 			err = ::SendReceive(sess, data.iHandleType, data.iFunction, data.iHandle, args);
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			err = ::SendReceive(sess, data.iFunction, args);
sl@0: 			}
sl@0: 		if(err == KErrServerTerminated)
sl@0: 			{
sl@0: 			User::Panic(KPanicCategory, KPanicCode);
sl@0: 			}
sl@0: 		User::SetJustInTime(ETrue);
sl@0: 		}
sl@0: 
sl@0: 	sess.Close();
sl@0: 
sl@0: 	delete tc;	
sl@0: 	
sl@0: 	__UHEAP_MARKEND;
sl@0: 	
sl@0: 	return KErrNone;		
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID			SYSLIB-SQL-CT-1769
sl@0: @SYMTestCaseDesc		In a loop, where the loop iterations are less than KTestIterCount (5000 at the moment), 
sl@0: 						the test creates a public shared database and a worker thread, which will behave as 
sl@0: 						malicious client. If the worker thread crashes the SQL server, then the worker thread
sl@0: 						dies notifying the main thread about the SQL server crash. The main thread prints the 
sl@0: 						values used in the last IPC call and crashes the test.
sl@0: @SYMTestPriority		High
sl@0: @SYMTestActions			SQL, Malicious client simulation test.
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ					REQ5792
sl@0:                         REQ5793
sl@0: 						REQ10405
sl@0: 						REQ10407
sl@0: */	
sl@0: void BadClientTest()
sl@0: 	{
sl@0: 	TThreadData* p = new TThreadData;
sl@0: 	TEST(p != NULL);
sl@0: 	TThreadData& data = *p;
sl@0: 	data.iFunction = 0;
sl@0: 	TTime now;
sl@0: 	now.UniversalTime();
sl@0: 	data.iSeed = now.Int64();
sl@0: 	
sl@0: 	_LIT(KThreadName, "WorkThrd");
sl@0: 	
sl@0: 	for(data.iIteration=0;data.iIteration<KTestIterCount;++data.iIteration)
sl@0: 		{
sl@0: 		PrintIterationCount(data.iIteration);
sl@0: 		//Create/open the test database
sl@0: 		RSqlDatabase db;
sl@0: 		TInt err = db.Create(KTestDbName1);
sl@0: 		TEST(err == KErrNone || err == KErrAlreadyExists);
sl@0: 		if(err == KErrNone)
sl@0: 			{
sl@0: 			err = db.Exec(_L8("CREATE TABLE A(Id INTEGER); INSERT INTO A(Id) VALUES(1); INSERT INTO A(Id) VALUES(2);"));	
sl@0: 			TEST(err >= 0);
sl@0: 			}
sl@0: 		db.Close();
sl@0: 		//Run the malicious client (one worker theread which will try to crash the SQL server)
sl@0: 		RThread thread;
sl@0: 		TEST2(thread.Create(KThreadName, &ThreadFunc1, 0x2000, 0x1000, 0x10000, &data, EOwnerProcess), KErrNone);
sl@0: 		TRequestStatus status;
sl@0: 		thread.Logon(status);
sl@0: 		TEST2(status.Int(), KRequestPending);
sl@0: 		thread.Resume();
sl@0: 		User::WaitForRequest(status);
sl@0: 		User::SetJustInTime(ETrue);	// enable debugger panic handling
sl@0: 		if(thread.ExitType() == EExitPanic)
sl@0: 			{
sl@0: 			if(thread.ExitReason() == KPanicCode)
sl@0: 				{
sl@0: 				TheTest.Printf(_L("##Server terminated!\r\n"));
sl@0: 				TheTest.Printf(_L("##Iteration=%d, Handle type(hex)=%X, Function(hex)=%X, Handle=%d\r\n"), data.iIteration, data.iHandleType, data.iFunction, data.iHandle);
sl@0: 				for(TInt i=0;i<KMaxMessageArguments;++i)
sl@0: 					{
sl@0: 					switch(data.iArgType[i])
sl@0: 						{
sl@0: 						case EIntArgType:
sl@0: 							TheTest.Printf(_L("##Arg %d, Integer, value=%d\r\n"), i, data.iIntArg[i]);
sl@0: 							break;
sl@0: 						case ETextArgType:
sl@0: 							TheTest.Printf(_L("##Arg %d, Text,    length=%d\r\n"), i, data.iTextArg[i].Length());
sl@0: 							break;
sl@0: 						case EBinArgType:
sl@0: 							TheTest.Printf(_L("##Arg %d, Binary,  length=%d\r\n"), i, data.iBinArg[i].Length());
sl@0: 							break;
sl@0: 						default:
sl@0: 							TheTest.Printf(_L("##Arg %d, Invalid argument type: %d\r\n"), i, data.iArgType[i]);
sl@0: 							break;
sl@0: 						}
sl@0: 					}
sl@0: 				TEST(0);
sl@0: 				}
sl@0: 			}
sl@0: 		thread.Close();
sl@0: 		}
sl@0: 	User::SetJustInTime(ETrue);	// enable debugger panic handling
sl@0: 	delete p;
sl@0: 	}
sl@0: 
sl@0: RSqlSecurityPolicy CreateSecurityPolicy()
sl@0: 	{
sl@0: 	RSqlSecurityPolicy securityPolicy;
sl@0: 	const TSecurityPolicy KDefaultPolicy(TSecurityPolicy::EAlwaysPass);
sl@0: 	TInt err = securityPolicy.Create(KDefaultPolicy);
sl@0: 	TEST2(err, KErrNone);
sl@0: 	return securityPolicy;
sl@0: 	}
sl@0: 
sl@0: void DoBadNameTest(RSqlDatabase& aDb)
sl@0: 	{
sl@0: 	TFileName invalidFileName1;
sl@0: 	invalidFileName1.SetLength(KMaxFileName);
sl@0: 	//Initialise the first character so that it is not treated as an empty descriptor by the sever
sl@0: 	invalidFileName1[0] = TChar(204); //0xCC
sl@0: 	TFileName invalidFileName2;
sl@0: 	invalidFileName2.SetLength(KMaxFileName);
sl@0: 	invalidFileName2.Fill(TChar(204));//0xCC
sl@0: 	
sl@0: 	TInt err = aDb.Attach(invalidFileName1, invalidFileName2);
sl@0: 	TheTest.Printf(_L("Attach, invalid database name-1, err=%d\r\n"), err);
sl@0: 	TEST(err != KErrNone);
sl@0: 	err = aDb.Attach(invalidFileName2, invalidFileName1);
sl@0: 	TheTest.Printf(_L("Attach, invalid database name-2, err=%d\r\n"), err);
sl@0: 	TEST(err != KErrNone);
sl@0: 	err = aDb.Attach(KTestDbName2, invalidFileName2);
sl@0: 	TheTest.Printf(_L("Attach, invalid database name-3, err=%d\r\n"), err);
sl@0: 	TEST(err != KErrDied);
sl@0: 	if(err == KErrNone)
sl@0: 		{
sl@0: 		err = aDb.Detach(invalidFileName2);
sl@0: 		TheTest.Printf(_L("Detach, invalid database name-3, err=%d\r\n"), err);
sl@0: 		TEST2(err, KErrNone);
sl@0: 		}
sl@0: 	err = aDb.Attach(KTestDbName2, invalidFileName1);
sl@0: 	TheTest.Printf(_L("Attach, invalid database name-4, err=%d\r\n"), err);
sl@0: 	TEST(err != KErrDied);
sl@0: 	if(err == KErrNone)
sl@0: 		{
sl@0: 		err = aDb.Detach(invalidFileName1);
sl@0: 		TheTest.Printf(_L("Detach, invalid database name-4, err=%d\r\n"), err);
sl@0: 		TEST2(err, KErrNone);
sl@0: 		}
sl@0: 	
sl@0: 	RSqlDatabase::TSize size;
sl@0: 
sl@0: 	err = aDb.Size(size, invalidFileName1);
sl@0: 	TheTest.Printf(_L("Size, invalid database name-1, err=%d\r\n"), err);
sl@0: 	TEST(err != KErrNone);
sl@0: 	err = aDb.Size(size, invalidFileName2);
sl@0: 	TheTest.Printf(_L("Size, invalid database name-2, err=%d\r\n"), err);
sl@0: 	TEST(err != KErrNone);
sl@0: 
sl@0: 	err = aDb.Compact(RSqlDatabase::EMaxCompaction, invalidFileName1);
sl@0: 	TheTest.Printf(_L("Compact, invalid database name-1, err=%d\r\n"), err);
sl@0: 	TEST(err != KErrNone);
sl@0: 	err = aDb.Compact(RSqlDatabase::EMaxCompaction, invalidFileName2);
sl@0: 	TheTest.Printf(_L("Compact, invalid database name-2, err=%d\r\n"), err);
sl@0: 	TEST(err != KErrNone);
sl@0: 
sl@0: 	RSqlStatement stmt;
sl@0: 	err = stmt.Prepare(aDb, _L("SELECT * FROM A"));
sl@0: 	TEST2(err, KErrNone);
sl@0: 	
sl@0: 	err = stmt.ColumnIndex(invalidFileName1);
sl@0: 	TheTest.Printf(_L("ColumnIndex, invalid column name-1, err=%d\r\n"), err);
sl@0: 	TEST(err != KErrNone);
sl@0: 	err = stmt.ColumnIndex(invalidFileName2);
sl@0: 	TheTest.Printf(_L("ColumnIndex, invalid column name-2, err=%d\r\n"), err);
sl@0: 	TEST(err != KErrNone);
sl@0: 	err = stmt.ParameterIndex(invalidFileName1);
sl@0: 	TheTest.Printf(_L("ParameterIndex, invalid parameter name-1, err=%d\r\n"), err);
sl@0: 	TEST(err != KErrNone);
sl@0: 	err = stmt.ParameterIndex(invalidFileName2);
sl@0: 	TheTest.Printf(_L("ParameterIndex, invalid parameter name-2, err=%d\r\n"), err);
sl@0: 	TEST(err != KErrNone);
sl@0: 
sl@0: 	stmt.Close();
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID			SYSLIB-SQL-UT-4048
sl@0: @SYMTestCaseDesc		Bad database names - robustness test.
sl@0: 						The test defines file names with invalid content and attempts to use 
sl@0: 						these file names with the SQL API. The test should not cause crashes 
sl@0: 						in the SQL server.
sl@0: @SYMTestPriority		High
sl@0: @SYMTestActions			Bad database names - robustness test.
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ					REQ10405
sl@0:                         REQ10407
sl@0: */
sl@0: void BadNameTest()
sl@0: 	{
sl@0: 	TFileName invalidFileName1;
sl@0: 	invalidFileName1.SetLength(KMaxFileName);
sl@0: 	TFileName invalidFileName2;
sl@0: 	invalidFileName2.SetLength(KMaxFileName / 2);
sl@0: 	
sl@0: 	//Initialise the first character so that it is not treated as an empty descriptor by the sever
sl@0: 	invalidFileName1[0] = TChar(204); //0xCC
sl@0: 	invalidFileName2[0] = TChar(204); //0xCC
sl@0: 	
sl@0: 	(void)RSqlDatabase::Delete(KTestDbName1);
sl@0: 	(void)RSqlDatabase::Delete(KTestDbName2);
sl@0: 		
sl@0: 	RSqlDatabase db;
sl@0: 	TInt err = db.Create(invalidFileName1);
sl@0: 	TEST(err != KErrNone);
sl@0: 	err = db.Create(invalidFileName2);
sl@0: 	TEST(err != KErrNone);
sl@0: 
sl@0: 	err = db.Open(invalidFileName1);
sl@0: 	TEST(err != KErrNone);
sl@0: 	err = db.Open(invalidFileName2);
sl@0: 	TEST(err != KErrNone);
sl@0: 
sl@0: 	err = db.Create(KTestDbName1);
sl@0: 	TEST2(err, KErrNone);
sl@0: 	err = db.Exec(_L("CREATE TABLE A(I INTEGER)"));
sl@0: 	TEST(err >= 0);
sl@0: 	db.Close();
sl@0: 	
sl@0: 	RSqlSecurityPolicy sp = CreateSecurityPolicy();
sl@0: 	err = db.Create(KTestDbName2, sp);
sl@0: 	TEST2(err, KErrNone);
sl@0: 	sp.Close();
sl@0: 	err = db.Exec(_L("CREATE TABLE A(I INTEGER)"));
sl@0: 	TEST(err >= 0);
sl@0: 	db.Close();
sl@0: 
sl@0: 	TheTest.Printf(_L("Bad names test - public shared database\r\n"));
sl@0: 	err = db.Open(KTestDbName1);	
sl@0: 	TEST2(err, KErrNone);
sl@0: 	DoBadNameTest(db);
sl@0: 	db.Close();
sl@0: 
sl@0: 	TheTest.Printf(_L("Bad names test - public secure shared database\r\n"));
sl@0: 	err = db.Open(KTestDbName2);	
sl@0: 	TEST2(err, KErrNone);
sl@0: 	DoBadNameTest(db);
sl@0: 	db.Close();
sl@0: 	
sl@0: 	(void)RSqlDatabase::Delete(KTestDbName2);
sl@0: 	(void)RSqlDatabase::Delete(KTestDbName1);
sl@0: 	
sl@0: 	err = RSqlDatabase::Copy(invalidFileName1, invalidFileName2);
sl@0: 	TheTest.Printf(_L("Copy database, err=%d\r\n"), err);
sl@0: 	TEST(err != KErrNone);
sl@0: 	err = RSqlDatabase::Delete(invalidFileName1);
sl@0: 	TheTest.Printf(_L("Delete database-1, err=%d\r\n"), err);
sl@0: 	TEST(err != KErrNone);
sl@0: 	err = RSqlDatabase::Delete(invalidFileName2);
sl@0: 	TheTest.Printf(_L("Delete database-2, err=%d\r\n"), err);
sl@0: 	TEST(err != KErrNone);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          PDS-SQL-CT-4200
sl@0: @SYMTestCaseDesc        Invalid sql software version test.
sl@0: @SYMTestPriority        High
sl@0: @SYMTestActions			The test verifies that the SQL server checks that the software version of SQL sessions
sl@0: 						to be created is less or equal to the current version of the server software. 
sl@0: 						If that is not true then the SQL server does not create the session annd returns KErrNotSupported.
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMDEF                 DEF145236
sl@0: */  
sl@0: void InvalidSoftwareVersionTest()
sl@0: 	{
sl@0: 	(void)RSqlDatabase::Delete(KTestDbName1);
sl@0: 	RSqlDatabase db;
sl@0: 	TInt err = db.Create(KTestDbName1);
sl@0: 	TEST2(err, KErrNone);
sl@0: 	db.Close();
sl@0: 	
sl@0: 	//Smaller version number
sl@0: 	TVersion sqlSoftwareVersion1(1, 0, 0);
sl@0: 	RTestSqlDbSession sess1;
sl@0: 	err = sess1.Connect(sqlSoftwareVersion1);
sl@0: 	sess1.Close();
sl@0: 	TEST2(err, KErrNone);
sl@0: 	
sl@0: 	//Bigger version number 1
sl@0: 	TVersion sqlSoftwareVersion2(1, 97, 3);
sl@0: 	RTestSqlDbSession sess2;
sl@0: 	err = sess2.Connect(sqlSoftwareVersion2);
sl@0: 	TEST2(err, KErrNotSupported);
sl@0: 	
sl@0: 	//Bigger version number 2
sl@0: 	TVersion sqlSoftwareVersion3(78, 0, 1);
sl@0: 	RTestSqlDbSession sess3;
sl@0: 	err = sess3.Connect(sqlSoftwareVersion3);
sl@0: 	TEST2(err, KErrNotSupported);
sl@0: 
sl@0: 	//The current version number
sl@0: 	TVersion sqlSoftwareVersion4(KSqlMajorVer, KSqlMinorVer, KSqlBuildVer);
sl@0: 	RTestSqlDbSession sess4;
sl@0: 	err = sess4.Connect(sqlSoftwareVersion4);
sl@0: 	sess4.Close();
sl@0: 	TEST2(err, KErrNone);
sl@0: 	
sl@0: 	(void)RSqlDatabase::Delete(KTestDbName1);
sl@0: 	}
sl@0: 
sl@0: void DoTests()
sl@0: 	{
sl@0: 	TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-SQL-CT-1769 Bad client test "));
sl@0: 	BadClientTest();
sl@0: 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4048 Bad names test"));
sl@0: 	BadNameTest();
sl@0: 	TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-CT-4200 Invalid software version test"));
sl@0: 	InvalidSoftwareVersionTest();
sl@0: 	}
sl@0: 
sl@0: TInt E32Main()
sl@0: 	{
sl@0: 	TheTest.Title();
sl@0: 	
sl@0: 	CTrapCleanup* tc = CTrapCleanup::New();
sl@0: 	
sl@0: 	__UHEAP_MARK;
sl@0: 	
sl@0: 	DeleteTestFiles();
sl@0: 	CreateTestEnv();
sl@0: 	DoTests();
sl@0: 	DeleteTestFiles();
sl@0: 	TheFs.Close();
sl@0: 
sl@0: 	__UHEAP_MARKEND;
sl@0: 	
sl@0: 	TheTest.End();
sl@0: 	TheTest.Close();
sl@0: 	
sl@0: 	delete tc;
sl@0: 
sl@0: 	User::Heap().Check();
sl@0: 	return KErrNone;
sl@0: 	}