AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Unity setup/teardown */7void setUp(void) {8 /* Ensure SQLite memory subsystem is initialized */9 sqlite3_initialize();10}11void tearDown(void) {12 /* Shutdown between tests to help catch leaks and reset subsystems */13 sqlite3_shutdown();14}15 16/* Helper: allocate and initialize an empty Schema */17static Schema* alloc_empty_schema(void){18 Schema *pSchema = (Schema*)sqlite3DbMallocZero(0, sizeof(Schema));19 TEST_ASSERT_NOT_NULL(pSchema);20 sqlite3HashInit(&pSchema->tblHash);21 sqlite3HashInit(&pSchema->trigHash);22 sqlite3HashInit(&pSchema->idxHash);23 sqlite3HashInit(&pSchema->fkeyHash);24 pSchema->enc = SQLITE_UTF8;25 return pSchema;26}27 28/* Helper: insert a Table into schema->tblHash */29static void schema_insert_table(Schema *pSchema, const char *zName){30 Table *pTab = (Table*)sqlite3DbMallocZero(0, sizeof(Table));31 TEST_ASSERT_NOT_NULL(pTab);32 pTab->zName = sqlite3DbStrDup(0, zName);33 TEST_ASSERT_NOT_NULL(pTab->zName);34 pTab->pSchema = pSchema; /* safe to set */35 /* Key is duplicated internally by sqlite3HashInsert */36 (void)sqlite3HashInsert(&pSchema->tblHash, zName, pTab);37}38 39/* Helper: insert a Trigger into schema->trigHash */40static void schema_insert_trigger(Schema *pSchema, const char *zName){41 Trigger *pTrig = (Trigger*)sqlite3DbMallocZero(0, sizeof(Trigger));42 TEST_ASSERT_NOT_NULL(pTrig);43 pTrig->zName = sqlite3DbStrDup(0, zName);44 TEST_ASSERT_NOT_NULL(pTrig->zName);45 (void)sqlite3HashInsert(&pSchema->trigHash, zName, pTrig);46}47 48/* Helper: insert dummy keys into idxHash and fkeyHash */49static void schema_insert_dummy_index_key(Schema *pSchema, const char *zName){50 (void)sqlite3HashInsert(&pSchema->idxHash, zName, 0);51}52static void schema_insert_dummy_fkey_key(Schema *pSchema, const char *zName){53 (void)sqlite3HashInsert(&pSchema->fkeyHash, zName, 0);54}55 56/* Test 1: Clearing an empty schema resets flags, generation and leaves hashes empty */57void test_sqlite3SchemaClear_clears_empty_schema(void){58 Schema *pSchema = alloc_empty_schema();59 Table *pSeq = (Table*)sqlite3DbMallocZero(0, sizeof(Table));60 TEST_ASSERT_NOT_NULL(pSeq);61 62 pSchema->schemaFlags = DB_SchemaLoaded | DB_ResetWanted;63 pSchema->iGeneration = 41;64 pSchema->pSeqTab = pSeq;65 66 /* Pre-conditions */67 TEST_ASSERT_EQUAL_INT(0, sqliteHashCount(&pSchema->tblHash));68 TEST_ASSERT_EQUAL_INT(0, sqliteHashCount(&pSchema->trigHash));69 TEST_ASSERT_EQUAL_INT(0, sqliteHashCount(&pSchema->idxHash));70 TEST_ASSERT_EQUAL_INT(0, sqliteHashCount(&pSchema->fkeyHash));71 TEST_ASSERT_NOT_NULL(pSchema->pSeqTab);72 73 sqlite3SchemaClear((void*)pSchema);74 75 /* Post-conditions: hashes empty and reinitialized */76 TEST_ASSERT_EQUAL_INT(0, sqliteHashCount(&pSchema->tblHash));77 TEST_ASSERT_EQUAL_INT(0, sqliteHashCount(&pSchema->trigHash));78 TEST_ASSERT_EQUAL_INT(0, sqliteHashCount(&pSchema->idxHash));79 TEST_ASSERT_EQUAL_INT(0, sqliteHashCount(&pSchema->fkeyHash));80 TEST_ASSERT_NULL(pSchema->pSeqTab);81 82 /* Generation incremented only because DB_SchemaLoaded was set */83 TEST_ASSERT_EQUAL_UINT32(42u, pSchema->iGeneration);84 85 /* Flags cleared */86 TEST_ASSERT_EQUAL_INT(0, (pSchema->schemaFlags & (DB_SchemaLoaded|DB_ResetWanted)));87 88 /* Cleanup allocations owned by test */89 sqlite3DbFree(0, pSeq);90 sqlite3DbFree(0, pSchema);91}92 93/* Test 2: Tables and triggers are deleted; idx/fkey hashes cleared; flags/generation updated */94void test_sqlite3SchemaClear_deletes_tables_triggers_and_clears_hashes(void){95 Schema *pSchema = alloc_empty_schema();96 Table *pSeq = (Table*)sqlite3DbMallocZero(0, sizeof(Table));97 TEST_ASSERT_NOT_NULL(pSeq);98 99 /* Populate schema */100 schema_insert_table(pSchema, "t1");101 schema_insert_table(pSchema, "t2");102 schema_insert_trigger(pSchema, "tr1");103 schema_insert_trigger(pSchema, "tr2");104 schema_insert_dummy_index_key(pSchema, "i1");105 schema_insert_dummy_fkey_key(pSchema, "fk1");106 107 pSchema->schemaFlags = DB_SchemaLoaded;108 pSchema->iGeneration = 0;109 pSchema->pSeqTab = pSeq;110 111 /* Pre-conditions: counts reflect inserts */112 TEST_ASSERT_EQUAL_INT(2, sqliteHashCount(&pSchema->tblHash));113 TEST_ASSERT_EQUAL_INT(2, sqliteHashCount(&pSchema->trigHash));114 TEST_ASSERT_EQUAL_INT(1, sqliteHashCount(&pSchema->idxHash));115 TEST_ASSERT_EQUAL_INT(1, sqliteHashCount(&pSchema->fkeyHash));116 117 sqlite3SchemaClear((void*)pSchema);118 119 /* All hashes empty */120 TEST_ASSERT_EQUAL_INT(0, sqliteHashCount(&pSchema->tblHash));121 TEST_ASSERT_EQUAL_INT(0, sqliteHashCount(&pSchema->trigHash));122 TEST_ASSERT_EQUAL_INT(0, sqliteHashCount(&pSchema->idxHash));123 TEST_ASSERT_EQUAL_INT(0, sqliteHashCount(&pSchema->fkeyHash));124 125 /* Flags cleared and generation incremented since DB_SchemaLoaded was set */126 TEST_ASSERT_EQUAL_INT(0, (pSchema->schemaFlags & (DB_SchemaLoaded|DB_ResetWanted)));127 TEST_ASSERT_EQUAL_UINT32(1u, pSchema->iGeneration);128 129 /* pSeqTab reset, free our dummy */130 TEST_ASSERT_NULL(pSchema->pSeqTab);131 132 sqlite3DbFree(0, pSeq);133 sqlite3DbFree(0, pSchema);134}135 136/* Test 3: iGeneration not incremented if DB_SchemaLoaded not set */137void test_sqlite3SchemaClear_no_generation_increment_when_not_loaded(void){138 Schema *pSchema = alloc_empty_schema();139 schema_insert_dummy_index_key(pSchema, "i1");140 pSchema->schemaFlags = 0;141 pSchema->iGeneration = 100;142 143 sqlite3SchemaClear((void*)pSchema);144 145 TEST_ASSERT_EQUAL_UINT32(100u, pSchema->iGeneration);146 TEST_ASSERT_EQUAL_INT(0, (pSchema->schemaFlags & (DB_SchemaLoaded|DB_ResetWanted)));147 TEST_ASSERT_EQUAL_INT(0, sqliteHashCount(&pSchema->tblHash));148 TEST_ASSERT_EQUAL_INT(0, sqliteHashCount(&pSchema->trigHash));149 TEST_ASSERT_EQUAL_INT(0, sqliteHashCount(&pSchema->idxHash));150 TEST_ASSERT_EQUAL_INT(0, sqliteHashCount(&pSchema->fkeyHash));151 152 sqlite3DbFree(0, pSchema);153}154 155/* Test 4: Idempotency - calling twice is safe; generation increments at most once */156void test_sqlite3SchemaClear_idempotent_on_second_call(void){157 Schema *pSchema = alloc_empty_schema();158 Table *pSeq = (Table*)sqlite3DbMallocZero(0, sizeof(Table));159 TEST_ASSERT_NOT_NULL(pSeq);160 schema_insert_table(pSchema, "t1");161 schema_insert_trigger(pSchema, "tr1");162 163 pSchema->schemaFlags = DB_SchemaLoaded;164 pSchema->iGeneration = 7;165 pSchema->pSeqTab = pSeq;166 167 sqlite3SchemaClear((void*)pSchema);168 169 /* After first clear */170 TEST_ASSERT_EQUAL_UINT32(8u, pSchema->iGeneration);171 TEST_ASSERT_EQUAL_INT(0, (pSchema->schemaFlags & (DB_SchemaLoaded|DB_ResetWanted)));172 TEST_ASSERT_EQUAL_INT(0, sqliteHashCount(&pSchema->tblHash));173 TEST_ASSERT_EQUAL_INT(0, sqliteHashCount(&pSchema->trigHash));174 175 /* Second call should be a no-op regarding generation and remain stable */176 sqlite3SchemaClear((void*)pSchema);177 TEST_ASSERT_EQUAL_UINT32(8u, pSchema->iGeneration);178 TEST_ASSERT_EQUAL_INT(0, sqliteHashCount(&pSchema->tblHash));179 TEST_ASSERT_EQUAL_INT(0, sqliteHashCount(&pSchema->trigHash));180 181 sqlite3DbFree(0, pSeq);182 sqlite3DbFree(0, pSchema);183}184 185int main(void) {186 UNITY_BEGIN();187 RUN_TEST(test_sqlite3SchemaClear_clears_empty_schema);188 RUN_TEST(test_sqlite3SchemaClear_deletes_tables_triggers_and_clears_hashes);189 RUN_TEST(test_sqlite3SchemaClear_no_generation_increment_when_not_loaded);190 RUN_TEST(test_sqlite3SchemaClear_idempotent_on_second_call);191 return UNITY_END();192}