#include "sqliteInt.h" #include "unity.h" #include #include /* Wrapper for the static function under test (provided in the module) */ extern int test_renameParseSql( Parse *p, const char *zDb, sqlite3 *db, const char *zSql, int bTemp ); /* Internal free helpers from SQLite */ extern void sqlite3DeleteTable(sqlite3*, Table*); void setUp(void) { /* no-op */ } void tearDown(void) { /* no-op */ } static void freeParseOutputs(sqlite3 *db, Parse *p){ if( p->pNewTable ){ sqlite3DeleteTable(db, p->pNewTable); p->pNewTable = 0; } /* p->pNewIndex and p->pNewTrigger should be NULL in our tests */ } /* zSql == NULL should return SQLITE_NOMEM and not modify db->init.iDb or flags */ void test_renameParseSql_null_sql_returns_nomem_and_preserves_init_idb_and_flags(void) { sqlite3 *db = 0; int rc = sqlite3_open(":memory:", &db); TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc); TEST_ASSERT_NOT_NULL(db); Parse p; memset(&p, 0, sizeof(p)); /* Prime values to ensure they are preserved on early return */ db->init.iDb = 77; u64 origFlags = db->flags = 0; rc = test_renameParseSql(&p, "main", db, NULL, 0); TEST_ASSERT_EQUAL_INT(SQLITE_NOMEM, rc); TEST_ASSERT_EQUAL_UINT8(77, db->init.iDb); TEST_ASSERT_EQUAL_UINT64(origFlags, db->flags); sqlite3_close(db); } /* Non-CREATE prefix should return SQLITE_CORRUPT */ void test_renameParseSql_non_create_returns_corrupt(void) { sqlite3 *db = 0; int rc = sqlite3_open(":memory:", &db); TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc); TEST_ASSERT_NOT_NULL(db); Parse p; memset(&p, 0, sizeof(p)); const char *zSql = "DROP TABLE t1"; rc = test_renameParseSql(&p, "main", db, zSql, 0); TEST_ASSERT_EQUAL_INT(SQLITE_CORRUPT, rc); sqlite3_close(db); } /* CREATE TABLE on main schema: verify outputs and side-effects */ void test_renameParseSql_create_table_main_schema_ok_and_fields(void) { sqlite3 *db = 0; int rc = sqlite3_open(":memory:", &db); TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc); TEST_ASSERT_NOT_NULL(db); Parse p; memset(&p, 0, sizeof(p)); u64 origFlags = db->flags = 0; const char *zSql = "CREATE TABLE t1(x INTEGER)"; rc = test_renameParseSql(&p, "main", db, zSql, 0); TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc); /* Parse mode and loop count set */ TEST_ASSERT_EQUAL_INT(PARSE_MODE_RENAME, p.eParseMode); TEST_ASSERT_EQUAL_INT(1, p.nQueryLoop); /* New table constructed; index and trigger should be NULL */ TEST_ASSERT_NOT_NULL(p.pNewTable); TEST_ASSERT_NULL(p.pNewIndex); TEST_ASSERT_NULL(p.pNewTrigger); /* Schema should be main (db->aDb[0]) */ TEST_ASSERT_EQUAL_PTR(db->aDb[0].pSchema, p.pNewTable->pSchema); /* Flags restored and init.iDb reset */ TEST_ASSERT_EQUAL_UINT64(origFlags, db->flags); TEST_ASSERT_EQUAL_UINT8(0, db->init.iDb); freeParseOutputs(db, &p); sqlite3_close(db); } /* CREATE TABLE with bTemp=true should target temp schema (db->aDb[1]) */ void test_renameParseSql_create_table_temp_schema_bTemp_true(void) { sqlite3 *db = 0; int rc = sqlite3_open(":memory:", &db); TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc); TEST_ASSERT_NOT_NULL(db); Parse p; memset(&p, 0, sizeof(p)); u64 origFlags = db->flags = 0; const char *zSql = "CREATE TABLE ttemp(y TEXT) /* a comment to toggle comments flag */"; rc = test_renameParseSql(&p, "main", db, zSql, 1); TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc); TEST_ASSERT_NOT_NULL(p.pNewTable); TEST_ASSERT_NULL(p.pNewIndex); TEST_ASSERT_NULL(p.pNewTrigger); /* Schema should be temp (index 1) */ TEST_ASSERT_EQUAL_PTR(db->aDb[1].pSchema, p.pNewTable->pSchema); /* Flags restored and init.iDb reset */ TEST_ASSERT_EQUAL_UINT64(origFlags, db->flags); TEST_ASSERT_EQUAL_UINT8(0, db->init.iDb); freeParseOutputs(db, &p); sqlite3_close(db); } /* CREATE TABLE with zDb="temp" and bTemp==0 should still target temp schema */ void test_renameParseSql_create_table_temp_schema_by_name(void) { sqlite3 *db = 0; int rc = sqlite3_open(":memory:", &db); TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc); TEST_ASSERT_NOT_NULL(db); Parse p; memset(&p, 0, sizeof(p)); u64 origFlags = db->flags = 0; const char *zSql = "CREATE TABLE ttemp2(z BLOB)"; rc = test_renameParseSql(&p, "temp", db, zSql, 0); TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc); TEST_ASSERT_NOT_NULL(p.pNewTable); TEST_ASSERT_EQUAL_PTR(db->aDb[1].pSchema, p.pNewTable->pSchema); TEST_ASSERT_EQUAL_UINT64(origFlags, db->flags); TEST_ASSERT_EQUAL_UINT8(0, db->init.iDb); freeParseOutputs(db, &p); sqlite3_close(db); } /* Ensure flags are restored even if SQLITE_Comments is already set */ void test_renameParseSql_flags_restored_when_comments_flag_pre_set(void) { sqlite3 *db = 0; int rc = sqlite3_open(":memory:", &db); TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc); TEST_ASSERT_NOT_NULL(db); Parse p; memset(&p, 0, sizeof(p)); db->flags = SQLITE_Comments; /* Pre-set */ u64 origFlags = db->flags; const char *zSql = "CREATE TABLE c(a INTEGER) /* comment present */"; rc = test_renameParseSql(&p, "main", db, zSql, 0); TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc); TEST_ASSERT_NOT_NULL(p.pNewTable); TEST_ASSERT_EQUAL_UINT64(origFlags, db->flags); TEST_ASSERT_EQUAL_UINT8(0, db->init.iDb); freeParseOutputs(db, &p); sqlite3_close(db); } int main(void) { UNITY_BEGIN(); RUN_TEST(test_renameParseSql_null_sql_returns_nomem_and_preserves_init_idb_and_flags); RUN_TEST(test_renameParseSql_non_create_returns_corrupt); RUN_TEST(test_renameParseSql_create_table_main_schema_ok_and_fields); RUN_TEST(test_renameParseSql_create_table_temp_schema_bTemp_true); RUN_TEST(test_renameParseSql_create_table_temp_schema_by_name); RUN_TEST(test_renameParseSql_flags_restored_when_comments_flag_pre_set); return UNITY_END(); }