diff -r cce6680bbf1c -r ba1c4f4a893f persistentstorage/sql/TEST/t_sqloslayer.cpp --- a/persistentstorage/sql/TEST/t_sqloslayer.cpp Thu Jul 01 17:02:22 2010 +0100 +++ b/persistentstorage/sql/TEST/t_sqloslayer.cpp Tue Jul 06 11:54:49 2010 +0100 @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2006-2010 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" @@ -27,6 +27,7 @@ #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif +#include "SqliteUtil.h" /////////////////////////////////////////////////////////////////////////////////////// @@ -52,6 +53,9 @@ TInt TheSqlSrvProfilerFileSetSize = 0; #endif +//SQLite panic category. +_LIT(KSqlitePanicCategory, "Sqlite"); + /////////////////////////////////////////////////////////////////////////////////////// void DeleteTestFiles() @@ -623,16 +627,24 @@ User::Free(osFile); } +TInt DoDeleteTempFiles() + { + CFileMan* fm = NULL; + TRAPD(err, fm = CFileMan::NewL(TheFs)); + TEST2(err, KErrNone); + TFileName path; + path.Copy(KPrivateDir); + path.Append(_L("temp\\")); + path.Append(_L("*.$$$")); + err = fm->Delete(path); + delete fm; + return err; + } + void VfsOpenTempFileOomTest() { //Delete all temp files in this test private data cage. - CFileMan* fm = NULL; - TRAPD(err, fm = CFileMan::NewL(TheFs)); - TEST2(err, KErrNone); - TBuf<50> path; - path.Copy(KPrivateDir); - path.Append(_L("*.$$$")); - err = fm->Delete(path); + TInt err = DoDeleteTempFiles(); TEST(err == KErrNone || err == KErrNotFound); sqlite3_vfs* vfs = sqlite3_vfs_find(NULL); @@ -653,7 +665,9 @@ err = sqlite3OsOpen(vfs, NULL, osFile, SQLITE_OPEN_READWRITE, &outFlags); if(err == SQLITE_OK) { - err = sqlite3OsClose(osFile); + //Since this is a temp file, its creation will be delayed till the first file write operation. + err = sqlite3OsWrite(osFile, "1234", 4, 0); + (void)sqlite3OsClose(osFile); } OomPostStep(); if(err != SQLITE_OK) @@ -662,16 +676,68 @@ } //If the iteration has failed, then no temp file should exist in the test private data cage. //If the iteration has succeeded, then sqlite3OsClose() should have deleted the temp file. - TInt err2 = fm->Delete(path); + TInt err2 = DoDeleteTempFiles(); TEST2(err2, KErrNotFound); } TEST2(err, SQLITE_OK); TheTest.Printf(_L("\r\n=== TVfs::Open() OOM test succeeded at allcoation %d\r\n"), failingAllocNum); User::Free(osFile); - delete fm; } +void VfsOpenTempFileFileIoErrTest() + { + //Delete all temp files in this test private data cage. + TInt err = DoDeleteTempFiles(); + TEST(err == KErrNone || err == KErrNotFound); + + sqlite3_vfs* vfs = sqlite3_vfs_find(NULL); + TEST(vfs != NULL); + + sqlite3_file* osFile = (sqlite3_file*)User::Alloc(vfs->szOsFile); + TEST(osFile != NULL); + + err = SQLITE_ERROR; + TInt cnt = 1; + while(err != SQLITE_OK) + { + TInt processHandleCnt = 0; + TInt threadHandleCnt = 0; + RThread().HandleCount(processHandleCnt, threadHandleCnt); + TInt allocCellsCnt = User::CountAllocCells(); + + TheTest.Printf(_L("%d "), cnt); + (void)TheFs.SetErrorCondition(KErrGeneral, cnt); + int outFlags = 0; + err = sqlite3OsOpen(vfs, NULL, osFile, SQLITE_OPEN_READWRITE, &outFlags); + if(err == SQLITE_OK) + { + //Since this is a temp file, its creation will be delayed till the first file write operation. + err = sqlite3OsWrite(osFile, "1234", 4, 0); + (void)sqlite3OsClose(osFile); + } + (void)TheFs.SetErrorCondition(KErrNone); + if(err != SQLITE_OK) + { + TInt processHandleCnt2 = 0; + TInt threadHandleCnt2 = 0; + RThread().HandleCount(processHandleCnt2, threadHandleCnt2); + TEST2(processHandleCnt2, processHandleCnt); + TEST2(threadHandleCnt2, threadHandleCnt); + TInt allocCellsCnt2 = User::CountAllocCells(); + TEST2(allocCellsCnt2, allocCellsCnt); + ++cnt; + } + //If the iteration has failed, then no temp file should exist in the test private data cage. + //If the iteration has succeeded, then sqlite3OsClose() should have deleted the temp file. + TInt err2 = DoDeleteTempFiles(); + TEST2(err2, KErrNotFound); + } + TEST2(err, SQLITE_OK); + TheTest.Printf(_L("\r\n=== TVfs::Open() file I/O error simulation test succeeded at iteration %d\r\n"), cnt); + User::Free(osFile); + } + void VfsCreateDeleteOnCloseFileOomTest() { sqlite3_vfs* vfs = sqlite3_vfs_find(NULL); @@ -711,6 +777,71 @@ User::Free(osFile); } +/////////////////////////////////////////////////////////////////////////////////////// + +//Panic thread function. +//It will cast aData parameter to a TFunctor pointer and call it. +//The expectation is that the called function will panic and kill the panic thread. +TInt ThreadFunc(void* aData) + { + CTrapCleanup* tc = CTrapCleanup::New(); + TEST(tc != NULL); + + User::SetJustInTime(EFalse); // disable debugger panic handling + + TFunctor* obj = reinterpret_cast (aData); + TEST(obj != NULL); + (*obj)();//call the panic function + + delete tc; + + return KErrNone; + } + +//Panic test. +//PanicTest function will create a new thread - panic thread, giving it a pointer to the function which has to +//be executed and the expectation is that the function will panic and kill the panic thread. +//PanicTest function will check the panic thread exit code, exit category and the panic code. +void PanicTest(TFunctor& aFunctor, TExitType aExpectedExitType, const TDesC& aExpectedCategory, TInt aExpectedPanicCode) + { + RThread thread; + _LIT(KThreadName,"OsLayerPanicThread"); + TEST2(thread.Create(KThreadName, &ThreadFunc, 0x2000, 0x1000, 0x10000, (void*)&aFunctor, EOwnerThread), KErrNone); + + TRequestStatus status; + thread.Logon(status); + TEST2(status.Int(), KRequestPending); + thread.Resume(); + User::WaitForRequest(status); + User::SetJustInTime(ETrue); // enable debugger panic handling + + TEST2(thread.ExitType(), aExpectedExitType); + TEST(thread.ExitCategory() == aExpectedCategory); + TEST2(thread.ExitReason(), aExpectedPanicCode); + + CLOSE_AND_WAIT(thread); + } + +//////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////// Panic test functions ///////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef _DEBUG + +//Panic when calling COsLayerData::Create() is called and the OS layer data has been already created. +class TOsLayerDataDuplicated : public TFunctor + { +private: + virtual void operator()() + { + (void)sqlite3SymbianLibInit();//This should crash the thread in debug mode (because the Os layer + //data was created already in TestEnvInit()). + } + }; +static TOsLayerDataDuplicated TheOsLayerDataDuplicated; + +#endif //_DEBUG + /** @SYMTestCaseID SYSLIB-SQL-CT-1650 @SYMTestCaseDesc SQL, OS porting layer tests. @@ -740,8 +871,14 @@ NegativeTest(); TheTest.Printf(_L("TVfs::Open() OOM test\r\n")); VfsOpenTempFileOomTest(); + TheTest.Printf(_L("TVfs::Open() file I/O error simulation test\r\n")); + VfsOpenTempFileFileIoErrTest(); TheTest.Printf(_L("TVfs::Open(<'delete on close' file>) OOM test\r\n")); VfsCreateDeleteOnCloseFileOomTest(); +#ifdef _DEBUG + TheTest.Printf(_L("'An attempt to create the OS layer data again' panic\r\n")); + PanicTest(TheOsLayerDataDuplicated, EExitPanic, KSqlitePanicCategory, ESqliteOsPanicOsLayerDataExists); +#endif //_DEBUG } TInt E32Main()