// Copyright (c) 2006-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 <e32test.h>
#include <bautils.h>
#include <stdlib.h>
#include <string.h>
#include <hal.h>
#include "SqliteSymbian.h"
#ifdef __cplusplus
extern "C" {
#endif
	#include "sqliteInt.h"
	#include "os.h"
#ifdef __cplusplus
}  /* End of the 'extern "C"' block */
#endif

///////////////////////////////////////////////////////////////////////////////////////

const char* KSymbianVfsNameZ = "SymbianSql";

RTest TheTest(_L("t_sqloslayer test"));
RFs   TheFs;

_LIT(KTestDir, "c:\\test\\");
_LIT(KTestFile1, "c:\\test\\t_sqloslayer.bin");
_LIT(KTestFile3, "c:\\test\\t_sqloslayer.db");
const char* KTestFile1Z = "c:\\test\\t_sqloslayer.bin";
const char* KTestFile2Z = "z:\\test\\TestDb1.db";
const char* KTestFile3Z = "c:\\test\\t_sqloslayer.db";

//In order to be able to compile the test, the following variables are defined (used inside the OS porting layer, when _SQLPROFILER macro is defined)
#ifdef _SQLPROFILER
TInt TheSqlSrvProfilerFileRead = 0;
TInt TheSqlSrvProfilerFileWrite = 0;
TInt TheSqlSrvProfilerFileSync = 0;
TInt TheSqlSrvProfilerFileSetSize = 0;
#endif

///////////////////////////////////////////////////////////////////////////////////////

void DeleteTestFiles()
	{
	(void)TheFs.Delete(KTestFile3);
	(void)TheFs.Delete(KTestFile1);
	}

void TestEnvDestroy()
	{
	sqlite3SymbianLibFinalize();
	DeleteTestFiles();
	TheFs.Close();
	}

///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
//Test macros and functions
void Check1(TInt aValue, TInt aLine)
	{
	if(!aValue)
		{
		TestEnvDestroy();
		RDebug::Print(_L("*** Line %d\r\n"), aLine);
		TheTest(EFalse, aLine);
		}
	}
void Check2(TInt aValue, TInt aExpected, TInt aLine)
	{
	if(aValue != aExpected)
		{
		TestEnvDestroy();
		RDebug::Print(_L("*** Line %d, Expected error: %d, got: %d\r\n"), aLine, aExpected, aValue);
		TheTest(EFalse, aLine);
		}
	}
#define TEST(arg) ::Check1((arg), __LINE__)
#define TEST2(aValue, aExpected) ::Check2(aValue, aExpected, __LINE__)

///////////////////////////////////////////////////////////////////////////////////////

void TestEnvInit()
    {
	TInt err = TheFs.Connect();
	TEST2(err, KErrNone);

	err = TheFs.MkDir(KTestDir);
	TEST(err == KErrNone || err == KErrAlreadyExists);

	err = sqlite3SymbianLibInit();
	TEST2(err, KErrNone);
	}

TInt CalcMs(TUint32 aStartTicks, TUint32 aEndTicks)
	{
	static TInt freq = 0;
	if(freq == 0)
		{
		TEST2(HAL::Get(HAL::EFastCounterFrequency, freq), KErrNone);
		}
	TInt64 diffTicks = (TInt64)aEndTicks - (TInt64)aStartTicks;
	if(diffTicks < 0)
		{
		diffTicks = KMaxTUint32 + diffTicks + 1;
		}
	const TInt KMicroSecIn1Sec = 1000000;
	TInt32 us = (diffTicks * KMicroSecIn1Sec) / freq;
	return us / 1000;
	}
	
///////////////////////////////////////////////////////////////////////////////////////

//Create/open/close/delete a file
void Test1()
	{
	sqlite3_vfs* vfs = sqlite3_vfs_find(KSymbianVfsNameZ);
	TEST(vfs != NULL);

  	sqlite3_file* osFile = (sqlite3_file*)User::Alloc(vfs->szOsFile);
	TEST(osFile != NULL);
		
	//Creating a new file
	int outFlags = 0;
	int err = sqlite3OsOpen(vfs, KTestFile1Z, osFile, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, &outFlags);
	TEST2(err, SQLITE_OK);
	TEST(outFlags & SQLITE_OPEN_READWRITE);
	err = sqlite3OsClose(osFile);
	TEST2(err, SQLITE_OK);
	//Opening an existing file for R/W
	err = sqlite3OsOpen(vfs, KTestFile1Z, osFile, SQLITE_OPEN_READWRITE, &outFlags);
	TEST2(err, SQLITE_OK);
	TEST(outFlags & SQLITE_OPEN_READWRITE);
	err = sqlite3OsClose(osFile);
	TEST2(err, SQLITE_OK);
	//Opening a read-only file
	err = sqlite3OsOpen(vfs, KTestFile2Z, osFile, SQLITE_OPEN_READWRITE, &outFlags);
	TEST2(err, SQLITE_OK);
	TEST(outFlags & SQLITE_OPEN_READONLY);
	//Truncate a read-only file
	err = osFile->pMethods->xTruncate(osFile, 0);
	TEST2(err, SQLITE_IOERR);
	//xAccess - read-only file
	int res = 0;
	err = vfs->xAccess(vfs, KTestFile2Z, SQLITE_ACCESS_READ, &res);
	TEST2(err, SQLITE_OK);
	TEST(res != 0);
	//xAccess - invalid request
	res = 0;
	err = vfs->xAccess(vfs, KTestFile2Z, 122, &res);
	TEST2(err, SQLITE_OK);
	TEST2(res, 0);
	//
	err = sqlite3OsClose(osFile);
	TEST2(err, SQLITE_OK);
	//Creating a new file
	err = sqlite3OsOpen(vfs, KTestFile3Z, osFile, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, &outFlags);
	TEST2(err, SQLITE_OK);
	TEST(outFlags & SQLITE_OPEN_READWRITE);
	err = sqlite3OsClose(osFile);
	TEST2(err, SQLITE_OK);
	//Open a file for a read-only access
	err = sqlite3OsOpen(vfs, KTestFile1Z, osFile, SQLITE_OPEN_READONLY, &outFlags);
	TEST2(err, SQLITE_OK);
	TEST(outFlags & SQLITE_OPEN_READONLY);
	err = sqlite3OsWrite(osFile, "1234", 4, 0);
	TEST(err != SQLITE_OK);
	err = sqlite3SymbianLastOsError();
	TEST2(err, KErrAccessDenied);
	err = vfs->xGetLastError(vfs, 0, 0);
	TEST2(err, 0);//Default implementation
	err = sqlite3OsClose(osFile);
	TEST2(err, SQLITE_OK);
	//Delete KTestFile3Z file
	err = sqlite3OsDelete(vfs, KTestFile3Z, 0);
	TEST2(err, SQLITE_OK);
	res = 0;
	err = sqlite3OsAccess(vfs, KTestFile3Z, SQLITE_ACCESS_EXISTS, &res);
	TEST2(err, SQLITE_OK);
	TEST2(res, 0);
	//Open a file for an exclusive access
	err = sqlite3OsOpen(vfs, KTestFile3Z, osFile, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_DELETEONCLOSE | SQLITE_OPEN_EXCLUSIVE, &outFlags);
	TEST2(err, SQLITE_OK);
	err = sqlite3OsClose(osFile);
	TEST2(err, SQLITE_OK);
	//The file should not exist now
	err = sqlite3OsAccess(vfs, KTestFile3Z, SQLITE_ACCESS_EXISTS, &res);
	TEST2(err, SQLITE_OK);
	TEST2(res, 0);
	//Open a file for an exclusive access without deleting it after 
	err = sqlite3OsOpen(vfs, KTestFile3Z, osFile, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE, &outFlags);
	TEST2(err, SQLITE_OK);
	err = sqlite3OsClose(osFile);
	TEST2(err, SQLITE_OK);
	//The file should exist now
	err = sqlite3OsAccess(vfs, KTestFile3Z, SQLITE_ACCESS_EXISTS, &res);
	TEST2(err, SQLITE_OK);
	TEST2(res, 1);
	//Delete KTestFile3Z file
	err = sqlite3OsDelete(vfs, KTestFile3Z, 0);
	TEST2(err, SQLITE_OK);
	err = sqlite3OsAccess(vfs, KTestFile3Z, SQLITE_ACCESS_EXISTS, &res);
	TEST2(err, SQLITE_OK);
	TEST2(res, 0);
	//
	User::Free(osFile);
	}

//Read/Write/Seek/Truncate test	
void Test2()
	{
	sqlite3_vfs* vfs = sqlite3_vfs_find(KSymbianVfsNameZ);
	TEST(vfs != NULL);

  	sqlite3_file* osFile = (sqlite3_file*)User::Alloc(vfs->szOsFile);
	TEST(osFile != NULL);
	
	//Creating a new file
	int err = sqlite3OsDelete(vfs, KTestFile1Z, 0);
	TEST2(err, SQLITE_OK);
	int res = 0;
	err = sqlite3OsAccess(vfs, KTestFile1Z, SQLITE_ACCESS_EXISTS, &res);
	TEST2(err, SQLITE_OK);
	TEST2(res, 0);
	err = sqlite3OsOpen(vfs, KTestFile1Z, osFile, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
	TEST2(err, SQLITE_OK);
	//Writing at the beginning of the file
	err = sqlite3OsWrite(osFile, "123456", 6, 0);
	TEST2(err, SQLITE_OK);
	//Verify the written data
	char data[20];
	err = sqlite3OsRead(osFile, data, 6, 0);
	TEST2(err, SQLITE_OK);
	err = memcmp(data, "123456", 6);
	TEST2(err, 0);
	//Writing at beyond the end of the file
	err = sqlite3OsWrite(osFile, "abcdefgh", 8, 100);
	TEST2(err, SQLITE_OK);
	//Verify the written data
	err = sqlite3OsRead(osFile, data, 8, 100);
	TEST2(err, SQLITE_OK);
	err = memcmp(data, "abcdefgh", 8);
	TEST2(err, 0);
	//Truncate the file
	err = sqlite3OsTruncate(osFile, 3);
	TEST2(err, SQLITE_OK);
	//Write more data
	err = sqlite3OsWrite(osFile, "xyz", 3, 3);
	TEST2(err, SQLITE_OK);
	//Verify the written data
	err = sqlite3OsRead(osFile, data, 6, 0);
	TEST2(err, SQLITE_OK);
	err = memcmp(data, "123xyz", 6);
	TEST2(err, 0);
	//Check the file size
	TInt64 fileSize = 0;
	err = sqlite3OsFileSize(osFile, &fileSize);
	TEST2(err, SQLITE_OK);
	TEST(fileSize == 6);
	//FileControl - lock type
	int lockType = -1;
	err = osFile->pMethods->xFileControl(osFile, SQLITE_FCNTL_LOCKSTATE, &lockType);
	TEST2(err, SQLITE_OK);
	TEST2(lockType, NO_LOCK);
	//FileControl - set callback - NULL callback
	err = osFile->pMethods->xFileControl(osFile, KSqlFcntlRegisterFreePageCallback, 0);
	TEST2(err, SQLITE_ERROR);
	//FileControl - set callback - invalid callback object
	TSqlFreePageCallback cbck;
	err = osFile->pMethods->xFileControl(osFile, KSqlFcntlRegisterFreePageCallback, &cbck);
	TEST2(err, SQLITE_ERROR);
	//FileControl - invalid op-code
	err = osFile->pMethods->xFileControl(osFile, 90234, 0);
	TEST2(err, SQLITE_ERROR);
	//Close the file
	err = sqlite3OsClose(osFile);
	TEST2(err, SQLITE_OK);
	//
	err = sqlite3OsDelete(vfs, KTestFile1Z, 0);
	TEST2(err, SQLITE_OK);
	User::Free(osFile);
	}

//Miscellaneous tests
void Test3()
	{
	sqlite3_vfs* vfs = sqlite3_vfs_find(KSymbianVfsNameZ);
	TEST(vfs != NULL);
	//Full path name - the full file name is specified
	char fname[KMaxFileName];
	const char* testFileName1 = "c:\\test\\abv.db";
	int err = sqlite3OsFullPathname(vfs, testFileName1, KMaxFileName, fname);
	TEST2(err, SQLITE_OK);
	err = strncasecmp(fname, testFileName1, strlen(testFileName1));
	TEST2(err, 0);
	//Full path name - no drive, the full file name is not specified
	const char* testFileName2 = "abv.db";
	const char* expectedFileName2 = "c:\\private\\21F12127\\abv.db";//"21F12127", the UID of the current test app
	err = sqlite3OsFullPathname(vfs, testFileName2, KMaxFileName, fname);
	TEST2(err, SQLITE_OK);
	err = strncasecmp(fname, expectedFileName2, strlen(expectedFileName2));
	TEST2(err, 0);
	//Full path name - drive present, the full file name is not specified
	const char* testFileName3 = "z:abv.db";
	const char* expectedFileName3 = "z:\\private\\21F12127\\abv.db";//"21F12127", the UID of the current test app
	err = sqlite3OsFullPathname(vfs, testFileName3, KMaxFileName, fname);
	TEST2(err, SQLITE_OK);
	err = strncasecmp(fname, expectedFileName3, strlen(expectedFileName3));
	TEST2(err, 0);
	//Is directory writable - test 1
	int res = 0;
	err = sqlite3OsAccess(vfs, "c:\\test", SQLITE_ACCESS_READWRITE, &res);
	TEST2(err, SQLITE_OK);
	TEST2(res, 1);
	//Is directory writable - test 2
	err = sqlite3OsAccess(vfs, "c:\\test\\", SQLITE_ACCESS_READWRITE, &res);
	TEST2(err, SQLITE_OK);
	TEST2(res, 1);
	//Is directory writable - test 3
	//Not a valid test. It is the media that's read only, not the directory.
	//err = sqlite3OsAccess(vfs, "z:\\test\\", SQLITE_ACCESS_READWRITE, &res);
	//TEST2(err, SQLITE_OK);
	//TEST2(res, 0);
	//Random seed
	const int KBufLen = 100;
	char buf[KBufLen];
	err = sqlite3OsRandomness(vfs, KBufLen, buf);
	TEST2(err, KBufLen);
	//Sleep
	TUint32 start = User::FastCounter();
	const TInt KSleepTime = 200000;//us
	(void)sqlite3OsSleep(vfs, KSleepTime);
	TUint32 end = User::FastCounter();
	TInt ms = CalcMs(start, end);
	TheTest.Printf(_L(" === sqlite3OsSleep() time=%d ms\r\n"), ms);
	TEST(ms >= 80 && ms <= 320);// -60%..+60%
	}

//Lock/unlock tests
void Test5()
	{
	sqlite3_vfs* vfs = sqlite3_vfs_find(KSymbianVfsNameZ);
	TEST(vfs != NULL);

  	sqlite3_file* osFile = (sqlite3_file*)User::Alloc(vfs->szOsFile);
	TEST(osFile != NULL);
	
	//Creating a new file
	int res = 0;
	int err = sqlite3OsAccess(vfs, KTestFile1Z, SQLITE_ACCESS_EXISTS, &res);
	TEST2(err, SQLITE_OK);
	TEST2(res, 0);
	err = sqlite3OsOpen(vfs, KTestFile1Z, osFile, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
	TEST2(err, SQLITE_OK);
	//Lock/unlock
	//SHARED_LOCK
	err = sqlite3OsLock(osFile, SHARED_LOCK);
	TEST2(err, SQLITE_OK);
	err = sqlite3OsCheckReservedLock(osFile, &res);
	TEST2(err, SQLITE_OK);
	TEST2(res, 0);
	//RESERVED_LOCK
	err = sqlite3OsLock(osFile, RESERVED_LOCK);
	TEST2(err, SQLITE_OK);
	err = sqlite3OsCheckReservedLock(osFile, &res);
	TEST2(err, SQLITE_OK);
	TEST2(res, 1);
	//PENDING_LOCK
	err = sqlite3OsLock(osFile, PENDING_LOCK);
	TEST2(err, SQLITE_OK);
	//EXCLUSIVE_LOCK
	err = sqlite3OsLock(osFile, EXCLUSIVE_LOCK);
	TEST2(err, SQLITE_OK);
	//back to SHARED_LOCK
	err = sqlite3OsLock(osFile, SHARED_LOCK);
	TEST2(err, SQLITE_OK);
	//UNLOCK
	err = sqlite3OsUnlock(osFile, NO_LOCK);
	//Close the file
	err = sqlite3OsClose(osFile);
	TEST2(err, SQLITE_OK);
	//
	err = sqlite3OsDelete(vfs, KTestFile1Z, 0);
	TEST2(err, SQLITE_OK);
	User::Free(osFile);
	}

//sqlite3SymbianLibInit() - OOM test
void sqlite3SymbianLibInitOomTest()
	{
	sqlite3SymbianLibFinalize();
	
	TInt failingAllocNum = 0;
	TInt err = KErrNoMemory;
	while(err == KErrNoMemory)
		{
		TInt processHandleCnt = 0;
		TInt threadHandleCnt = 0;
		RThread().HandleCount(processHandleCnt, threadHandleCnt);
		TInt allocCellsCnt = User::CountAllocCells();
		
		__UHEAP_MARK;
		
		__UHEAP_SETBURSTFAIL(RHeap::EDeterministic, ++failingAllocNum, 10);
		
		err = sqlite3SymbianLibInit();
		
		__UHEAP_SETBURSTFAIL(RHeap::ENone, 0, 0);

		if(err != KErrNoMemory)
			{
			TEST2(err, KErrNone);
			sqlite3SymbianLibFinalize();
			}

		__UHEAP_MARKEND;

		TInt processHandleCnt2 = 0;
		TInt threadHandleCnt2 = 0;
		RThread().HandleCount(processHandleCnt2, threadHandleCnt2);
		TEST2(processHandleCnt2, processHandleCnt);
		TEST2(threadHandleCnt2, threadHandleCnt);

		TInt allocCellsCnt2 = User::CountAllocCells();
		TEST2(allocCellsCnt2, allocCellsCnt);
		}
	TEST2(err, KErrNone);
	TheTest.Printf(_L("=== sqlite3SymbianLibInit() OOM test succeeded at allcoation %d\r\n"), failingAllocNum);
	}

//sqlite3SymbianLibInit() - 'File I/O error simulation' test
void sqlite3SymbianLibInitFsErrTest()
	{
	sqlite3SymbianLibFinalize();
	
	TInt sysDrive = static_cast<TInt>(RFs::GetSystemDrive());
	TDriveUnit drvUnit(sysDrive);
	TDriveName drvName = drvUnit.Name();
	
	TFileName path;
	TInt err = TheFs.PrivatePath(path);
	TEST2(err, KErrNone);
	
	TParse privDataCage;
	err = privDataCage.Set(drvName, &path, 0);
	TEST2(err, KErrNone);
	
	err = KErrNotFound;
	TInt cnt = 1;
	for(;err<KErrNone;++cnt)
		{
		for (TInt fsError=KErrNotFound;fsError>=KErrDied;--fsError)
			{
			(void)TheFs.RmDir(privDataCage.FullName());
	
			TInt processHandleCnt = 0;
			TInt threadHandleCnt = 0;
			RThread().HandleCount(processHandleCnt, threadHandleCnt);
			TInt allocCellsCnt = User::CountAllocCells();
			
			(void)TheFs.SetErrorCondition(fsError, cnt);
			err = sqlite3SymbianLibInit();
			(void)TheFs.SetErrorCondition(KErrNone);
			
			if(err != KErrNone)
				{
				TInt processHandleCnt2 = 0;
				TInt threadHandleCnt2 = 0;
				RThread().HandleCount(processHandleCnt2, threadHandleCnt2);
				TEST2(processHandleCnt2, processHandleCnt);
				TEST2(threadHandleCnt2, threadHandleCnt);
				TInt allocCellsCnt2 = User::CountAllocCells();
				TEST2(allocCellsCnt2, allocCellsCnt);
				}
			else
				{
				sqlite3SymbianLibFinalize();
				}
			}
		}
	sqlite3SymbianLibFinalize();
	TheTest.Printf(_L("=== sqlite3SymbianLibInit() 'File I/O error simulation' test succeeded at iteration %d\r\n"), cnt);
	}

//If _SQLPROFILER macro is not defined then all profiling PS porting layer functions should return KErrNotSupported.
void ProfilerDisabledTest()
	{
#ifndef _SQLPROFILER
	TInt err = sqlite3SymbianProfilerStart(0);
	TEST2(err, KErrNotSupported);
	
	err = sqlite3SymbianProfilerStop(0);
	TEST2(err, KErrNotSupported);
	
	err = sqlite3SymbianProfilerReset(0);
	TEST2(err, KErrNotSupported);
	
	TBuf8<1> res;
	err = sqlite3SymbianProfilerQuery(0, res);
	TEST2(err, KErrNotSupported);
	res = res;
#else	
	TheTest.Printf(_L("  The _SQLPROFILER macro is defined. The Profliling OS porting layer functions are tested in t_sqlapi2\r\n"));
#endif
	}

void NegativeTest()
	{
	TInt err = sqlite3SymbianLibInit();
	TEST2(err, KErrNone);
	
	sqlite3_vfs* vfs = sqlite3_vfs_find(KSymbianVfsNameZ);
	TEST(vfs != NULL);

  	sqlite3_file* osFile = (sqlite3_file*)User::Alloc(vfs->szOsFile);
	TEST(osFile != NULL);
		
	//Creating a new file - the name is too long
	const char* KLongFileNameZ = "c:\\test\\0123456789-0123456789-0123456789-0123456789-0123456789-0123456789-0123456789-0123456789-0123456789-0123456789-0123456789-0123456789-0123456789-0123456789-0123456789-0123456789-0123456789-0123456789-0123456789-0123456789-0123456789-0123456789-0123456789-0123456789-0123456789-0123456789-0123456789.bin";
	int outFlags = 0;
	err = sqlite3OsOpen(vfs, KLongFileNameZ, osFile, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, &outFlags);
	TEST2(err, SQLITE_CANTOPEN);

	//Open a file - the name contains the '|', but not at position 0 (private database - bad name)
	const char* KBadFileNameZ = "c:\\test\\01|23456.bin";
	err = sqlite3OsOpen(vfs, KBadFileNameZ, osFile, SQLITE_OPEN_READWRITE, &outFlags);
	TEST2(err, SQLITE_CANTOPEN);

	//FullPathName() - the output buffer is too small
	const char* KFileNameZ = "c:\\test\\0123456.bin";
	char buf[5];
	err = vfs->xFullPathname(vfs, KFileNameZ, 5, buf);
	TEST2(err, SQLITE_ERROR);

	//FullPathName() - NULL output buffer
	err = vfs->xFullPathname(vfs, KFileNameZ, 5, NULL);
	TEST2(err, SQLITE_ERROR);

	//FullPathName() - NULL file name
	err = vfs->xFullPathname(vfs, NULL, 5, buf);
	TEST2(err, SQLITE_ERROR);

	//FullPathName() - the file name is too long
	err = vfs->xFullPathname(vfs, KLongFileNameZ, 5, buf);
	TEST2(err, SQLITE_ERROR);

	//FullPathName() - NULL file name
	err = vfs->xFullPathname(vfs, NULL, 5, buf);
	TEST2(err, SQLITE_ERROR);

	//Dellete file - NULL file name
	err = vfs->xDelete(vfs, 0, 0);
	TEST2(err, SQLITE_ERROR);

	//Delete file - the output buffer for the unicode file name is too small	
	err = vfs->xDelete(vfs, KLongFileNameZ, 0);
	TEST2(err, SQLITE_ERROR);

	//Open file - NULL file name - this is a temp file name
	err = sqlite3OsOpen(vfs, NULL, osFile, SQLITE_OPEN_READWRITE, &outFlags);
	TEST2(err, SQLITE_OK);
	err = osFile->pMethods->xClose(osFile);
	TEST2(err, SQLITE_OK);
	
	//xAccess - too long file name
	int res = -1;
	err = vfs->xAccess(vfs, KLongFileNameZ, SQLITE_ACCESS_EXISTS, &res);
	TEST2(err, SQLITE_IOERR_ACCESS);

	//xAccess - NULL file name
	err = vfs->xAccess(vfs, 0, SQLITE_ACCESS_EXISTS, &res);
	TEST2(err, SQLITE_IOERR_ACCESS);

	User::Free(osFile);
	}

/**
@SYMTestCaseID			SYSLIB-SQL-CT-1650
@SYMTestCaseDesc		SQL, OS porting layer tests.
@SYMTestPriority		High
@SYMTestActions			SQL, OS porting layer tests.
@SYMTestExpectedResults Test must not fail
@SYMREQ					REQ5792
                        REQ5793
*/	
void DoTests()
	{
	TheTest.Printf(_L("OS porting layer test - create/open/close/delete a file\r\n"));
	Test1();
	TheTest.Printf(_L("OS porting layer test - read/write/seek/truncate\r\n"));
	Test2();
	TheTest.Printf(_L("OS porting layer test - miscellaneous tests\r\n"));
	Test3();
	TheTest.Printf(_L("OS porting layer test - lock/unlock\r\n"));
	Test5();
	TheTest.Printf(_L("OS porting layer test - sqlite3SymbianLibInit() - OOM test\r\n"));
	sqlite3SymbianLibInitOomTest();
	TheTest.Printf(_L("OS porting layer test - sqlite3SymbianLibInit() - 'File I/O error simulation' test\r\n"));
	sqlite3SymbianLibInitFsErrTest();
	TheTest.Printf(_L("OS porting layer test - 'profiler disabled' tests\r\n"));
	ProfilerDisabledTest();
	TheTest.Printf(_L("OS porting layer test - negative tests\r\n"));
	NegativeTest();
	}

TInt E32Main()
	{
	TheTest.Title();
	
	CTrapCleanup* tc = CTrapCleanup::New();
	
	__UHEAP_MARK;
	
	TestEnvInit();
	DeleteTestFiles();
	TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-SQL-CT-1650 OS porting layer tests"));
	DoTests();
	TestEnvDestroy();

	__UHEAP_MARKEND;
	
	TheTest.End();
	TheTest.Close();
	
	delete tc;

	User::Heap().Check();
	return KErrNone;
	}
