sl@0: /* sl@0: * Copyright (c) 2007-2009 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: sl@0: sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include "sqliteTestUtl.h" sl@0: sl@0: static sqlite3* TheDb = 0; sl@0: static sqlite3* TheDb2 = 0; sl@0: static sqlite3_stmt* TheStmt = 0; sl@0: static sqlite3_stmt* TheStmt2 = 0; sl@0: const char* const TheTestDirName = "c:\\test"; sl@0: const char* const TheTestDbName = "c:\\test\\a1.db"; sl@0: sl@0: const int KTestThreadCount = 2; sl@0: static int TheInsertRecCnt[KTestThreadCount] = {0, 0}; sl@0: static int TheLockErrCnt[KTestThreadCount] = {0, 0}; sl@0: const char* const KThreadNames[KTestThreadCount] = {"THRD1", "THRD2"}; sl@0: static sem_t TheSemaphores[KTestThreadCount]; sl@0: sl@0: #define UNUSED_ARG(a) (a) = (a) sl@0: sl@0: /* ///////////////////////////////////////////////////////////////////////////////////// */ sl@0: sl@0: /* The standard C library does not have abs() function with a double argument */ sl@0: static double dabs(double arg) sl@0: { sl@0: return arg < 0.0 ? -arg : arg; sl@0: } sl@0: sl@0: /* ///////////////////////////////////////////////////////////////////////////////////// */ sl@0: sl@0: static void TestEnvDestroy() sl@0: { sl@0: if(TheStmt2) sl@0: { sl@0: (void)sqlite3_finalize(TheStmt2); sl@0: TheStmt2 = 0; sl@0: } sl@0: if(TheStmt) sl@0: { sl@0: (void)sqlite3_finalize(TheStmt); sl@0: TheStmt = 0; sl@0: } sl@0: if(TheDb2) sl@0: { sl@0: (void)sqlite3_close(TheDb2); sl@0: TheDb2 = 0; sl@0: } sl@0: if(TheDb) sl@0: { sl@0: (void)sqlite3_close(TheDb); sl@0: TheDb = 0; sl@0: } sl@0: (void)remove(TheTestDbName); sl@0: } sl@0: sl@0: /* ///////////////////////////////////////////////////////////////////////////////////// */ sl@0: /* Test macros and functions */ sl@0: sl@0: static void Check1(int aValue, int aLine) sl@0: { sl@0: if(!aValue) sl@0: { sl@0: if(TheDb) sl@0: { sl@0: const char* errmsg = sqlite3_errmsg(TheDb); sl@0: PrintS("*** DB1: SQLITE error message: %s\r\n", errmsg); sl@0: } sl@0: if(TheDb2) sl@0: { sl@0: const char* errmsg = sqlite3_errmsg(TheDb2); sl@0: PrintS("*** DB2: SQLITE error message: %s\r\n", errmsg); sl@0: } sl@0: PrintI("*** Test check failed! Line=%d\r\n", aLine); sl@0: TestEnvDestroy(); sl@0: TestAbort(aLine); sl@0: } sl@0: } sl@0: sl@0: static void Check2(int aValue, int aExpected, int aLine) sl@0: { sl@0: if(aValue != aExpected) sl@0: { sl@0: if(TheDb) sl@0: { sl@0: const char* errmsg = sqlite3_errmsg(TheDb); sl@0: PrintS("*** DB1: SQLITE error message: %s\r\n", errmsg); sl@0: } sl@0: if(TheDb2) sl@0: { sl@0: const char* errmsg = sqlite3_errmsg(TheDb2); sl@0: PrintS("*** DB2: SQLITE error message: %s\r\n", errmsg); sl@0: } sl@0: PrintIII("*** Test check failed! Line=%d. Expected error: %d, got: %d\r\n", aLine, aExpected, aValue); sl@0: TestEnvDestroy(); sl@0: TestAbort(aLine); sl@0: } sl@0: } sl@0: sl@0: static void Check64(sqlite_int64 aValue, sqlite_int64 aExpected, int aLine) sl@0: { sl@0: if(aValue != aExpected) sl@0: { sl@0: if(TheDb) sl@0: { sl@0: const char* errmsg = sqlite3_errmsg(TheDb); sl@0: PrintS("*** DB1: SQLITE error message: %s\r\n", errmsg); sl@0: } sl@0: if(TheDb2) sl@0: { sl@0: const char* errmsg = sqlite3_errmsg(TheDb2); sl@0: PrintS("*** DB2: SQLITE error message: %s\r\n", errmsg); sl@0: } sl@0: PrintII64I64("*** Test check failed! Line=%ld. Expected error: %ld, got: %d\r\n", aLine, aExpected, aValue); sl@0: TestEnvDestroy(); sl@0: TestAbort(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 TEST64(aValue, aExpected) Check64(aValue, aExpected, __LINE__) sl@0: sl@0: /* ///////////////////////////////////////////////////////////////////////////////////// */ sl@0: sl@0: static void TestEnvCreate() sl@0: { sl@0: int err; sl@0: (void)remove(TheTestDbName); sl@0: err = mkdir(TheTestDirName, S_IREAD | S_IWRITE); sl@0: if(err != 0) sl@0: { sl@0: err = errno; sl@0: } sl@0: TEST(err == 0 || err == EEXIST); sl@0: sl@0: //Creating the private data cage directory here to suppress a capability warning sl@0: CreatePrivateDir(); sl@0: } sl@0: sl@0: /* ///////////////////////////////////////////////////////////////////////////////////// */ sl@0: /* Callbacks */ sl@0: sl@0: static int exec_callback(void* udata, int argc, char** argv, char** colname) sl@0: { sl@0: UNUSED_ARG(udata); sl@0: UNUSED_ARG(argc); sl@0: UNUSED_ARG(argv); sl@0: UNUSED_ARG(colname); sl@0: return 0; sl@0: } sl@0: sl@0: static int authorizer_callback(void* udata, int optype, const char* name1, const char* name2, const char* name, const char* viewname) sl@0: { sl@0: UNUSED_ARG(udata); sl@0: UNUSED_ARG(optype); sl@0: UNUSED_ARG(name1); sl@0: UNUSED_ARG(name2); sl@0: UNUSED_ARG(name); sl@0: UNUSED_ARG(viewname); sl@0: return SQLITE_OK; sl@0: } sl@0: sl@0: static int commit_hook(void* udata) sl@0: { sl@0: UNUSED_ARG(udata); sl@0: return SQLITE_OK; sl@0: } sl@0: sl@0: static void rollback_hook(void* udata) sl@0: { sl@0: UNUSED_ARG(udata); sl@0: } sl@0: sl@0: static void update_hook(void* udata, int type, char const* dbname, char const* tblname, sqlite_int64 rowid) sl@0: { sl@0: UNUSED_ARG(udata); sl@0: UNUSED_ARG(type); sl@0: UNUSED_ARG(dbname); sl@0: UNUSED_ARG(tblname); sl@0: UNUSED_ARG(rowid); sl@0: } sl@0: sl@0: /* ///////////////////////////////////////////////////////////////////////////////////// */ sl@0: sl@0: /** sl@0: @SYMTestCaseID SYSLIB-SQLITE3-UT-4001 sl@0: @SYMTestCaseDesc sqlite3_exec() tests. sl@0: List of called SQLITE3 functions: sl@0: - sqlite3_exec; sl@0: - sqlite3_errcode; sl@0: - sqlite3_errmsg; sl@0: - sqlite3_last_insert_rowid; sl@0: - sqlite3_changes; sl@0: - sqlite3_total_changes; sl@0: - sqlite3_get_autocommit; sl@0: @SYMTestPriority High sl@0: @SYMTestActions sqlite3_exec() tests. sl@0: @SYMTestExpectedResults Test must not fail sl@0: @SYMREQ REQ8782 sl@0: */ sl@0: static void TestExec() sl@0: { sl@0: int err; sl@0: sqlite_int64 lastrowid; sl@0: int val; sl@0: sl@0: TEST(TheDb != 0); sl@0: sl@0: err = sqlite3_exec(TheDb, "CREATE TABLE A(F1 INTEGER, F2 BIGINT, F3 REAL, F4 TEXT, F5 BLOB)", &exec_callback, 0, 0); sl@0: TEST2(err, SQLITE_OK); sl@0: sl@0: err = sqlite3_exec(TheDb, "INSERT INTO A VALUES(1, 1234567891234, 56.12, 'TEXT', x'313233343536')", &exec_callback, 0, 0); sl@0: TEST2(err, SQLITE_OK); sl@0: sl@0: err = sqlite3_errcode(TheDb); sl@0: TEST2(err, SQLITE_OK); sl@0: sl@0: (void)sqlite3_errmsg(TheDb); sl@0: sl@0: lastrowid = sqlite3_last_insert_rowid(TheDb); sl@0: TEST(lastrowid > 0LL); sl@0: sl@0: val = sqlite3_changes(TheDb); sl@0: TEST2(val, 1); sl@0: sl@0: val = sqlite3_total_changes(TheDb); sl@0: TEST(val >= 1); sl@0: sl@0: val = sqlite3_get_autocommit(TheDb); sl@0: TEST(val != 0); sl@0: } sl@0: sl@0: /* ///////////////////////////////////////////////////////////////////////////////////// */ sl@0: sl@0: static void DoTestStatement() sl@0: { sl@0: int err, val; sl@0: sqlite_int64 val64; sl@0: double dblval; sl@0: const unsigned char* textval; sl@0: const unsigned short* textval16; sl@0: const unsigned char* blob; sl@0: const char *coltype, *colname; sl@0: const unsigned short *coltype16, *colname16; sl@0: sqlite3* db; sl@0: sl@0: TEST(TheDb != 0); sl@0: TEST(TheStmt != 0); sl@0: sl@0: val = sqlite3_column_count(TheStmt); sl@0: TEST2(val, 5); sl@0: sl@0: db = sqlite3_db_handle(TheStmt); sl@0: TEST2((unsigned int)db, (unsigned int)TheDb); sl@0: sl@0: err = sqlite3_step(TheStmt); sl@0: TEST2(err, SQLITE_ROW); sl@0: sl@0: #ifdef SQLITE_ENABLE_COLUMN_METADATA sl@0: sqlite3_column_database_name(TheStmt, 0); sl@0: sqlite3_column_database_name16(TheStmt, 1); sl@0: sqlite3_column_table_name(TheStmt, 2); sl@0: sqlite3_column_table_name16(TheStmt, 3); sl@0: sqlite3_column_origin_name(TheStmt, 4); sl@0: sqlite3_column_origin_name16(TheStmt, 0); sl@0: #endif sl@0: sl@0: coltype = sqlite3_column_decltype(TheStmt, 0); sl@0: TEST2(strcmp(coltype, "INTEGER"), 0); sl@0: sl@0: coltype16 = (const unsigned short*)sqlite3_column_decltype16(TheStmt, 2); sl@0: TEST2(wcscmp(coltype16, L"REAL"), 0); sl@0: sl@0: colname = sqlite3_column_name(TheStmt, 1); sl@0: TEST2(strcmp(colname, "F2"), 0); sl@0: sl@0: colname16 = (const unsigned short *)sqlite3_column_name16(TheStmt, 4); sl@0: TEST2(wcscmp(colname16, L"F5"), 0); sl@0: sl@0: val = sqlite3_column_int(TheStmt, 0); sl@0: TEST2(val, 1); sl@0: sl@0: val64 = sqlite3_column_int64(TheStmt, 1); sl@0: TEST64(val64, 1234567891234LL); sl@0: sl@0: dblval = sqlite3_column_double(TheStmt, 2); sl@0: TEST(dabs(dblval - 56.12) < 0.00001); sl@0: sl@0: textval = sqlite3_column_text(TheStmt, 3); sl@0: TEST2(strcmp((const char*)textval, "TEXT"), 0); sl@0: sl@0: textval16 = sqlite3_column_text16(TheStmt, 3); sl@0: TEST2(wcscmp(textval16, L"TEXT"), 0); sl@0: sl@0: blob = (const unsigned char*)sqlite3_column_blob(TheStmt, 4); sl@0: TEST2(memcmp(blob, "123456", 6), 0); sl@0: sl@0: err = sqlite3_step(TheStmt); sl@0: TEST2(err, SQLITE_DONE); sl@0: } sl@0: sl@0: /* ///////////////////////////////////////////////////////////////////////////////////// */ sl@0: sl@0: /** sl@0: @SYMTestCaseID SYSLIB-SQLITE3-UT-4002 sl@0: @SYMTestCaseDesc Statement handle SQLITE3 tests. sl@0: List of called SQLITE3 functions: sl@0: - sqlite3_complete; sl@0: - sqlite3_complete16; sl@0: - sqlite3_prepare; sl@0: - sqlite3_finalize; sl@0: - sqlite3_column_count; sl@0: - sqlite3_db_handle; sl@0: - sqlite3_step; sl@0: - sqlite3_column_decltype; sl@0: - sqlite3_column_decltype16; sl@0: - sqlite3_column_name; sl@0: - sqlite3_column_name16; sl@0: - sqlite3_column_int; sl@0: - sqlite3_column_int64; sl@0: - sqlite3_column_double; sl@0: - sqlite3_column_text; sl@0: - sqlite3_column_text16; sl@0: - sqlite3_column_blob; sl@0: @SYMTestPriority High sl@0: @SYMTestActions Statement handle SQLITE3 tests. sl@0: @SYMTestExpectedResults Test must not fail sl@0: @SYMREQ REQ8782 sl@0: */ sl@0: static void TestStatement1() sl@0: { sl@0: const char* tail = 0; sl@0: int err; sl@0: sl@0: TEST(TheDb != 0); sl@0: TEST(!TheStmt); sl@0: sl@0: err = sqlite3_complete("SELECT * FROM A;"); sl@0: TEST(err != 0); sl@0: sl@0: err = sqlite3_complete16(L"SELECT * FROM A;"); sl@0: TEST(err != 0); sl@0: sl@0: err = sqlite3_prepare(TheDb, "SELECT * FROM A", -1, &TheStmt, &tail); sl@0: TEST2(err, SQLITE_OK); sl@0: TEST((unsigned int)TheStmt); sl@0: TEST(!tail || strlen(tail) == 0); sl@0: sl@0: DoTestStatement(); sl@0: sl@0: err = sqlite3_finalize(TheStmt); sl@0: TEST2(err, SQLITE_OK); sl@0: TheStmt = 0; sl@0: } sl@0: sl@0: /* ///////////////////////////////////////////////////////////////////////////////////// */ sl@0: sl@0: /** sl@0: @SYMTestCaseID SYSLIB-SQLITE3-UT-4003 sl@0: @SYMTestCaseDesc Statement handle SQLITE3 tests. sl@0: List of called SQLITE3 functions: sl@0: - sqlite3_prepare; sl@0: - sqlite3_finalize; sl@0: - sqlite3_bind_int; sl@0: - sqlite3_bind_int64; sl@0: - sqlite3_bind_double; sl@0: - sqlite3_bind_text; sl@0: @SYMTestPriority High sl@0: @SYMTestActions Statement handle SQLITE3 tests. sl@0: @SYMTestExpectedResults Test must not fail sl@0: @SYMREQ REQ8782 sl@0: */ sl@0: static void TestStatement2() sl@0: { sl@0: const char* tail = 0; sl@0: int err; sl@0: sl@0: TEST(TheDb != 0); sl@0: TEST(!TheStmt); sl@0: sl@0: err = sqlite3_prepare(TheDb, "SELECT * FROM A WHERE F1=? AND F2=? AND F3 0); sl@0: sl@0: next = sqlite3_next_stmt(TheDb, 0); sl@0: TEST(!next); sl@0: sl@0: memset(buf, 0, sizeof(buf)); sl@0: sqlite3_randomness(8, buf); sl@0: sl@0: memset(buf, 0, sizeof(buf)); sl@0: sqlite3_randomness(7, buf); sl@0: sl@0: memset(buf, 0, sizeof(buf)); sl@0: sqlite3_randomness(3, buf); sl@0: sl@0: } sl@0: sl@0: /* ///////////////////////////////////////////////////////////////////////////////////// */ sl@0: sl@0: /** sl@0: @SYMTestCaseID PDS-SQLITE3-UT-4039 sl@0: @SYMTestCaseDesc SQLITE3 - blob API tests. sl@0: List of called SQLITE3 functions: sl@0: - sqlite3_bind_zeroblob; sl@0: - sqlite3_blob_bytes; sl@0: - sqlite3_blob_close; sl@0: - sqlite3_blob_open; sl@0: - sqlite3_blob_read; sl@0: - sqlite3_blob_write; sl@0: - sqlite3_sql; sl@0: @SYMTestPriority High sl@0: @SYMTestActions SQLITE3 - blob API tests. sl@0: @SYMTestExpectedResults Test must not fail sl@0: @SYMREQ REQ10424 sl@0: */ sl@0: static void TestSqliteBlobApi() sl@0: { sl@0: int err; sl@0: const char* tail = 0; sl@0: sqlite3_blob* blob = 0; sl@0: int bytes = 0; sl@0: const char KBlobData[] = "ABCDEFGH"; sl@0: char sql[100]; sl@0: const int KBlobLen = strlen(KBlobData); sl@0: const char* sql2 = 0; sl@0: const char KSqlFmt[] = "UPDATE BlobTbl SET B=:Prm WHERE ROWID=1"; sl@0: sl@0: TEST(TheDb != 0); sl@0: TEST(!TheStmt); sl@0: sl@0: /* Create the table, insert one record with a blob */ sl@0: sl@0: err = sqlite3_exec(TheDb, "CREATE TABLE BlobTbl(I INTEGER PRIMARY KEY, B BLOB)", 0, 0, 0); sl@0: TEST2(err, SQLITE_OK); sl@0: sl@0: sprintf(sql, "INSERT INTO BlobTbl VALUES(1, zeroblob(%d))", KBlobLen); sl@0: err = sqlite3_exec(TheDb, sql, 0, 0, 0); sl@0: TEST2(err, SQLITE_OK); sl@0: sl@0: err = sqlite3_prepare_v2(TheDb, KSqlFmt, -1, &TheStmt, &tail); sl@0: TEST2(err, SQLITE_OK); sl@0: TEST(TheStmt != 0); sl@0: sl@0: sql2 = sqlite3_sql(TheStmt); sl@0: TEST(sql2 != NULL); sl@0: err = strcmp(sql2, KSqlFmt); sl@0: TEST2(err, 0); sl@0: sl@0: err = sqlite3_bind_zeroblob(TheStmt, 1, KBlobLen); sl@0: TEST2(err, SQLITE_OK); sl@0: sl@0: err = sqlite3_step(TheStmt); sl@0: TEST2(err, SQLITE_DONE); sl@0: sl@0: err = sqlite3_finalize(TheStmt); sl@0: TEST2(err, SQLITE_OK); sl@0: TheStmt = 0; sl@0: sl@0: /* Open the blob and write to it */ sl@0: sl@0: err = sqlite3_blob_open(TheDb, "main", "BlobTbl", "B", 1, 1, &blob); sl@0: TEST2(err, SQLITE_OK); sl@0: TEST(blob != 0); sl@0: sl@0: bytes = sqlite3_blob_bytes(blob); sl@0: TEST2(bytes, KBlobLen); sl@0: sl@0: err = sqlite3_blob_write(blob, KBlobData, KBlobLen, 0); sl@0: TEST2(err, SQLITE_OK); sl@0: sl@0: err = sqlite3_blob_close(blob); sl@0: TEST2(err, SQLITE_OK); sl@0: blob = 0; sl@0: sl@0: /* Open the blob and read from it */ sl@0: sl@0: err = sqlite3_blob_open(TheDb, "main", "BlobTbl", "B", 1, 1, &blob); sl@0: TEST2(err, SQLITE_OK); sl@0: TEST(blob != 0); sl@0: sl@0: bytes = sqlite3_blob_bytes(blob); sl@0: TEST2(bytes, KBlobLen); sl@0: sl@0: err = sqlite3_blob_read(blob, sql, KBlobLen, 0); sl@0: TEST2(err, SQLITE_OK); sl@0: sql[bytes] = 0; sl@0: sl@0: err = sqlite3_blob_close(blob); sl@0: TEST2(err, SQLITE_OK); sl@0: blob = 0; sl@0: sl@0: err = strcmp(sql, KBlobData); sl@0: TEST2(err, 0); sl@0: sl@0: err = sqlite3_exec(TheDb, "DROP TABLE BlobTbl", 0, 0, 0); sl@0: TEST2(err, SQLITE_OK); sl@0: } sl@0: sl@0: /* ///////////////////////////////////////////////////////////////////////////////////// */ sl@0: sl@0: /** sl@0: @SYMTestCaseID PDS-SQLITE3-UT-4040 sl@0: @SYMTestCaseDesc SQLITE3 - mutex API tests. sl@0: List of called SQLITE3 functions: sl@0: - sqlite3_mutex_alloc; sl@0: - sqlite3_mutex_enter; sl@0: - sqlite3_mutex_free; sl@0: - sqlite3_mutex_held; sl@0: - sqlite3_mutex_leave; sl@0: - sqlite3_mutex_notheld; sl@0: - sqlite3_mutex_try; sl@0: @SYMTestPriority High sl@0: @SYMTestActions SQLITE3 - mutex API tests. sl@0: @SYMTestExpectedResults Test must not fail sl@0: @SYMREQ REQ10424 sl@0: */ sl@0: static void TestSqliteMutexApi() sl@0: { sl@0: sqlite3_mutex* mtx = 0; sl@0: int err; sl@0: int type; sl@0: sl@0: TEST(TheDb != 0); sl@0: sl@0: for(type=SQLITE_MUTEX_FAST;type<=SQLITE_MUTEX_STATIC_LRU2;++type) sl@0: { sl@0: mtx = sqlite3_mutex_alloc(type); sl@0: TEST(mtx != NULL); sl@0: sl@0: err = sqlite3_mutex_try(mtx); sl@0: TEST(err == SQLITE_BUSY || err == SQLITE_OK); sl@0: sl@0: sqlite3_mutex_enter(mtx); sl@0: sl@0: sqlite3_mutex_leave(mtx); sl@0: sl@0: if(type <= SQLITE_MUTEX_RECURSIVE) sl@0: { sl@0: sqlite3_mutex_free(mtx); sl@0: } sl@0: mtx = 0; sl@0: } sl@0: } sl@0: sl@0: /* ///////////////////////////////////////////////////////////////////////////////////// */ sl@0: sl@0: /** sl@0: @SYMTestCaseID SYSLIB-SQLITE3-UT-4004 sl@0: @SYMTestCaseDesc Database handle SQLITE3 tests. sl@0: List of called SQLITE3 functions: sl@0: - sqlite3_config; sl@0: - sqlite3_initialize; sl@0: - sqlite3_threadsafe; sl@0: - sqlite3_vfs_find; sl@0: - sqlite3_open; sl@0: - sqlite3_db_config; sl@0: - sqlite3_libversion; sl@0: - sqlite3_libversion_number; sl@0: - sqlite3_set_authorizer; sl@0: - sqlite3_commit_hook; sl@0: - sqlite3_rollback_hook; sl@0: - sqlite3_update_hook; sl@0: - sqlite3_close; sl@0: - sqlite3_shutdown; sl@0: @SYMTestPriority High sl@0: @SYMTestActions Database handle SQLITE3 tests. sl@0: @SYMTestExpectedResults Test must not fail sl@0: @SYMREQ REQ8782 sl@0: */ sl@0: static void TestSqliteApi() sl@0: { sl@0: void* prev = 0; sl@0: const char* libverstr = 0; sl@0: int libvernum = 0; sl@0: int err; sl@0: int threadSafe = -1; sl@0: sqlite3_vfs* vfs = 0; sl@0: sl@0: TEST(!TheDb); sl@0: sl@0: TestStart("@SYMTestCaseID:SYSLIB-SQLITE3-UT-4004: Test \"sqlite3_config()\""); sl@0: err = sqlite3_config(SQLITE_CONFIG_MEMSTATUS, 0); sl@0: TEST2(err, SQLITE_OK); sl@0: sl@0: TestNext("Test \"sqlite3_initialize()\""); sl@0: err = sqlite3_initialize(); sl@0: TEST2(err, SQLITE_OK); sl@0: sl@0: TestNext("Test \"sqlite3_threadsafe()\""); sl@0: threadSafe = sqlite3_threadsafe(); sl@0: PrintI("SQLITE_THREADSAFE=%d\r\n", threadSafe); sl@0: sl@0: vfs = sqlite3_vfs_find(0); sl@0: TEST(vfs != NULL); sl@0: PrintS("Vfs name=\"%s\"\r\n", vfs->zName); sl@0: sl@0: err = sqlite3_open(TheTestDbName, &TheDb); sl@0: TEST2(err, SQLITE_OK); sl@0: TEST(TheDb != 0); sl@0: sl@0: err = sqlite3_db_config(TheDb, SQLITE_DBCONFIG_LOOKASIDE, 0, 128, 100); sl@0: TEST2(err, SQLITE_OK); sl@0: sl@0: libverstr = sqlite3_libversion(); sl@0: libvernum = sqlite3_libversion_number(); sl@0: PrintSI("SQLITE version: \"%s\", Number: %d\r\n", libverstr, libvernum); sl@0: sl@0: err = sqlite3_set_authorizer(TheDb, &authorizer_callback, 0); sl@0: TEST2(err, SQLITE_OK); sl@0: sl@0: prev = sqlite3_commit_hook(TheDb, &commit_hook, 0); sl@0: TEST(!prev); sl@0: prev = sqlite3_rollback_hook(TheDb, &rollback_hook, 0); sl@0: TEST(!prev); sl@0: prev = sqlite3_update_hook(TheDb, &update_hook, 0); sl@0: TEST(!prev); sl@0: sl@0: TestNext("@SYMTestCaseID:SYSLIB-SQLITE3-UT-4001: Test \"sqlite3\" handle API"); sl@0: TestExec(); sl@0: TestNext("@SYMTestCaseID:SYSLIB-SQLITE3-UT-4002: Test \"sqlite3_stmt\" handle API-1"); sl@0: TestStatement1(); sl@0: TestNext("@SYMTestCaseID:SYSLIB-SQLITE3-UT-4003: Test \"sqlite3_stmt\" handle API-2"); sl@0: TestStatement2(); sl@0: TestNext("@SYMTestCaseID:PDS-SQLITE3-UT-4038: Test more sqlite3 API"); sl@0: TestSqliteApi2(); sl@0: TestNext("@SYMTestCaseID:PDS-SQLITE3-UT-4039: Test blob API"); sl@0: TestSqliteBlobApi(); sl@0: TestNext("@SYMTestCaseID:PDS-SQLITE3-UT-4040: Test mutex API"); sl@0: TestSqliteMutexApi(); sl@0: sl@0: err = sqlite3_close(TheDb); sl@0: TEST2(err, SQLITE_OK); sl@0: TheDb = 0; sl@0: sl@0: TestNext("Test \"sqlite3_shutdown()\""); sl@0: err = sqlite3_shutdown(); sl@0: TEST2(err, SQLITE_OK); sl@0: sl@0: err = remove(TheTestDbName); sl@0: TEST2(err, 0); sl@0: } sl@0: sl@0: static void CreateTestDb() sl@0: { sl@0: int err; sl@0: sl@0: err = sqlite3_open(TheTestDbName, &TheDb); sl@0: TEST2(err, SQLITE_OK); sl@0: TEST(TheDb != 0); sl@0: sl@0: err = sqlite3_exec(TheDb, "CREATE TABLE A(F1 INTEGER, F2 BIGINT, F3 REAL, F4 TEXT, F5 BLOB)", &exec_callback, 0, 0); sl@0: TEST2(err, SQLITE_OK); sl@0: sl@0: err = sqlite3_exec(TheDb, "INSERT INTO A VALUES(1, 1234567891234, 56.12, 'TEXT', x'313233343536')", &exec_callback, 0, 0); sl@0: TEST2(err, SQLITE_OK); sl@0: sl@0: err = sqlite3_close(TheDb); sl@0: TEST2(err, SQLITE_OK); sl@0: TheDb = 0; sl@0: } sl@0: sl@0: /** sl@0: @SYMTestCaseID SYSLIB-SQLITE3-UT-4005 sl@0: @SYMTestCaseDesc Two database connections in the same thread - "read operations" test. sl@0: The test creates two connections to the same database in the same thread. sl@0: Both connections prepare a SELECT statement and call sqlite3_step() each sl@0: thus testing that the file locking in the OS porting layer works properly sl@0: (the SQLite library permits multiple connections to read from the database simultaneously, sl@0: using a shared file locking mode). sl@0: List of called SQLITE3 functions: sl@0: - sqlite3_open; sl@0: - sqlite3_prepare; sl@0: - sqlite3_step; sl@0: - sqlite3_finalize; sl@0: - sqlite3_close; sl@0: @SYMTestPriority High sl@0: @SYMTestActions Two database connections in the same thread - "read operations" test. sl@0: @SYMTestExpectedResults Test must not fail sl@0: @SYMREQ REQ8782 sl@0: */ sl@0: static void TwoReadersTest() sl@0: { sl@0: int err; sl@0: const char* tail = 0; sl@0: sl@0: TestNext("@SYMTestCaseID:SYSLIB-SQLITE3-UT-4005: Test two readers"); sl@0: sl@0: CreateTestDb(); sl@0: sl@0: err = sqlite3_open(TheTestDbName, &TheDb); sl@0: TEST2(err, SQLITE_OK); sl@0: TEST(TheDb != 0); sl@0: sl@0: err = sqlite3_open(TheTestDbName, &TheDb2); sl@0: TEST2(err, SQLITE_OK); sl@0: TEST(TheDb2 != 0); sl@0: sl@0: /* ------------- */ sl@0: err = sqlite3_prepare(TheDb, "SELECT * FROM A", -1, &TheStmt, &tail); sl@0: TEST2(err, SQLITE_OK); sl@0: TEST((unsigned int)TheStmt); sl@0: TEST(!tail || strlen(tail) == 0); sl@0: sl@0: err = sqlite3_prepare(TheDb2, "SELECT * FROM A", -1, &TheStmt2, &tail); sl@0: TEST2(err, SQLITE_OK); sl@0: TEST((unsigned int)TheStmt2); sl@0: TEST(!tail || strlen(tail) == 0); sl@0: sl@0: err = sqlite3_step(TheStmt); sl@0: TEST2(err, SQLITE_ROW); sl@0: sl@0: err = sqlite3_step(TheStmt2); sl@0: TEST2(err, SQLITE_ROW); sl@0: sl@0: /* ------------- */ sl@0: sl@0: (void)sqlite3_finalize(TheStmt2); sl@0: TheStmt2 = 0; sl@0: sl@0: (void)sqlite3_finalize(TheStmt); sl@0: TheStmt = 0; sl@0: sl@0: err = sqlite3_close(TheDb2); sl@0: TEST2(err, SQLITE_OK); sl@0: TheDb2 = 0; sl@0: sl@0: err = sqlite3_close(TheDb); sl@0: TEST2(err, SQLITE_OK); sl@0: TheDb = 0; sl@0: sl@0: (void)remove(TheTestDbName); sl@0: } sl@0: sl@0: /* ///////////////////////////////////////////////////////////////////////////////////// */ sl@0: sl@0: /** sl@0: @SYMTestCaseID SYSLIB-SQLITE3-UT-4006 sl@0: @SYMTestCaseDesc Two database connections in the same thread - "write operations" test. sl@0: The test creates two connections to the same database in the same thread. sl@0: Both connections attempt to execute INSERT statements using an explicit transaction sl@0: thus testing that the file locking in the OS porting layer works properly sl@0: (the SQLite library permits only one connection at a time to write to the database). sl@0: List of called SQLITE3 functions: sl@0: - sqlite3_open; sl@0: - sqlite3_exec; sl@0: - sqlite3_free; sl@0: - sqlite3_close; sl@0: Test case steps: sl@0: - Two connections to the same database created; sl@0: - Both connections begin a deferred transaction; sl@0: - The first connection executes an INSERT statement. The database file should be locked sl@0: for a writing by this connection; sl@0: - The second connection attempts to execute an INSERT statement too. The operation should fail, sl@0: because the database file has been locked by the first connection; sl@0: - The first connection completes the transaction executing a ROLLBACK statement; sl@0: - The second connection makes second attempt to execute the INSERT statement. The execution should sl@0: complete without errors; sl@0: @SYMTestPriority High sl@0: @SYMTestActions Two database connections in the same thread - "write operations" test. sl@0: @SYMTestExpectedResults Test must not fail sl@0: @SYMREQ REQ8782 sl@0: */ sl@0: static void TwoWritersTest() sl@0: { sl@0: int err; sl@0: char* errmsg = 0; sl@0: sl@0: TestNext("@SYMTestCaseID:SYSLIB-SQLITE3-UT-4006: Test two writers"); sl@0: sl@0: CreateTestDb(); sl@0: sl@0: err = sqlite3_open(TheTestDbName, &TheDb); sl@0: TEST2(err, SQLITE_OK); sl@0: TEST(TheDb != 0); sl@0: sl@0: err = sqlite3_open(TheTestDbName, &TheDb2); sl@0: TEST2(err, SQLITE_OK); sl@0: TEST(TheDb2 != 0); sl@0: sl@0: /* ------------- */ sl@0: Print("Two database connections, begin a transaction in each of them.\r\n"); sl@0: err = sqlite3_exec(TheDb, "BEGIN", 0, 0, 0); sl@0: TEST2(err, SQLITE_OK); sl@0: sl@0: err = sqlite3_exec(TheDb2, "BEGIN", 0, 0, 0); sl@0: TEST2(err, SQLITE_OK); sl@0: sl@0: Print("Connection 1. Execute an \"INSERT\" statement. Success.\r\n"); sl@0: err = sqlite3_exec(TheDb, "INSERT INTO A VALUES(0,0,0.0,'',x'00')", 0, 0, &errmsg); sl@0: if(errmsg) sl@0: { sl@0: PrintSI("Err msg: %s. Err: %d.\r\n", errmsg, err); sl@0: sqlite3_free(errmsg); sl@0: } sl@0: errmsg = 0; sl@0: TEST2(err, SQLITE_OK); sl@0: sl@0: Print("Connection 2. Execute an \"INSERT\" statement. Failure. The database is locked.\r\n"); sl@0: err = sqlite3_exec(TheDb2, "INSERT INTO A VALUES(0,0,0.0,'',x'00')", 0, 0, &errmsg); sl@0: if(errmsg) sl@0: { sl@0: PrintSI("*** %s. Err: %d.\r\n", errmsg, err); sl@0: sqlite3_free(errmsg); sl@0: } sl@0: errmsg = 0; sl@0: TEST2(err, SQLITE_BUSY); sl@0: sl@0: Print("Connection 1. Rollback. The database is unlocked.\r\n"); sl@0: err = sqlite3_exec(TheDb, "ROLLBACK", 0, 0, 0); sl@0: TEST2(err, SQLITE_OK); sl@0: sl@0: Print("Connection 2. Execute an \"INSERT\" statement. Success.\r\n"); sl@0: err = sqlite3_exec(TheDb2, "INSERT INTO A VALUES(0,0,0.0,'',x'00')", 0, 0, &errmsg); sl@0: if(errmsg) sl@0: { sl@0: PrintSI("*** %s. Err: %d.\r\n", errmsg, err); sl@0: sqlite3_free(errmsg); sl@0: } sl@0: errmsg = 0; sl@0: TEST2(err, SQLITE_OK); sl@0: sl@0: err = sqlite3_exec(TheDb2, "ROLLBACK", 0, 0, 0); sl@0: TEST2(err, SQLITE_OK); sl@0: sl@0: Print("Close database connections.\r\n"); sl@0: /* ------------- */ sl@0: sl@0: err = sqlite3_close(TheDb2); sl@0: TEST2(err, SQLITE_OK); sl@0: TheDb2 = 0; sl@0: sl@0: err = sqlite3_close(TheDb); sl@0: TEST2(err, SQLITE_OK); sl@0: TheDb = 0; sl@0: sl@0: (void)remove(TheTestDbName); sl@0: } sl@0: sl@0: /* ///////////////////////////////////////////////////////////////////////////////////// */ sl@0: sl@0: static void* ThreadFunc(void* pname) sl@0: { sl@0: int records = 0, err, i; sl@0: sqlite3* db; sl@0: char* errmsg = 0; sl@0: int threadIdx = -1; sl@0: const int KRecordsCount = 500; sl@0: const int KCommitRecordsCount = 2; sl@0: sl@0: for(i=0;i