#define SQLITE_CORE 1 // Important! #include "unity.h" #include "sqliteInt.h" #include void setUp(void) {} void tearDown(void) {} // Declare wrapper ONLY for static functions extern int test_renameTableSelectCb(Walker *pWalker, Select *pSelect); // ========== Test 1: SF_View flag returns WRC_Prune ========== void test_renameTableSelectCb_prunes_view(void) { sqlite3 *db; sqlite3_open(":memory:", &db); Parse parse = {0}; parse.db = db; Walker walker = {0}; walker.pParse = &parse; Select select = {0}; select.selFlags = SF_View; select.pSrc = NULL; // Doesn't matter, exits early int result = test_renameTableSelectCb(&walker, &select); TEST_ASSERT_EQUAL(WRC_Prune, result); sqlite3_close(db); } // ========== Test 2: SF_CopyCte flag returns WRC_Prune ========== void test_renameTableSelectCb_prunes_copycte(void) { sqlite3 *db; sqlite3_open(":memory:", &db); Parse parse = {0}; parse.db = db; Walker walker = {0}; walker.pParse = &parse; Select select = {0}; select.selFlags = SF_CopyCte; select.pSrc = NULL; int result = test_renameTableSelectCb(&walker, &select); TEST_ASSERT_EQUAL(WRC_Prune, result); sqlite3_close(db); } // ========== Test 3: Both flags set returns WRC_Prune ========== void test_renameTableSelectCb_prunes_view_and_cte(void) { sqlite3 *db; sqlite3_open(":memory:", &db); Parse parse = {0}; parse.db = db; Walker walker = {0}; walker.pParse = &parse; Select select = {0}; select.selFlags = SF_View | SF_CopyCte; select.pSrc = NULL; int result = test_renameTableSelectCb(&walker, &select); TEST_ASSERT_EQUAL(WRC_Prune, result); sqlite3_close(db); } // ========== Test 4: NULL source list with mallocFailed returns WRC_Abort ========== void test_renameTableSelectCb_null_srclist_aborts(void) { sqlite3 *db; sqlite3_open(":memory:", &db); Parse parse = {0}; parse.db = db; db->mallocFailed = 1; // Simulate malloc failure Walker walker = {0}; walker.pParse = &parse; Select select = {0}; select.selFlags = 0; select.pSrc = NULL; int result = test_renameTableSelectCb(&walker, &select); TEST_ASSERT_EQUAL(WRC_Abort, result); sqlite3_close(db); } // ========== Test 5: Empty source list (nSrc=0) returns WRC_Continue ========== void test_renameTableSelectCb_empty_srclist_continues(void) { sqlite3 *db; sqlite3_open(":memory:", &db); Parse parse = {0}; parse.db = db; Table *pTab = sqlite3DbMallocZero(db, sizeof(Table)); pTab->zName = sqlite3DbStrDup(db, "old_table"); // Define RenameCtx - based on alter.c structure struct RenameCtx { Table *pTab; const char *zOld; }; struct RenameCtx *pRename = sqlite3DbMallocZero(db, sizeof(struct RenameCtx)); pRename->pTab = pTab; Walker walker = {0}; walker.pParse = &parse; walker.u.pRename = (void*)pRename; // Empty source list SrcList *pSrc = sqlite3DbMallocZero(db, sizeof(SrcList)); pSrc->nSrc = 0; // Empty! Select select = {0}; select.pSrc = pSrc; select.selFlags = 0; int result = test_renameTableSelectCb(&walker, &select); TEST_ASSERT_EQUAL(WRC_Continue, result); sqlite3DbFree(db, pRename); sqlite3DbFree(db, pSrc); sqlite3DbFree(db, pTab->zName); sqlite3DbFree(db, pTab); sqlite3_close(db); } // ========== Test 6: Table found in source list ========== void test_renameTableSelectCb_finds_table_reference(void) { sqlite3 *db; sqlite3_open(":memory:", &db); Parse parse = {0}; parse.db = db; // Create table to rename Table *pTab = sqlite3DbMallocZero(db, sizeof(Table)); pTab->zName = sqlite3DbStrDup(db, "old_table"); struct RenameCtx { Table *pTab; const char *zOld; }; struct RenameCtx *pRename = sqlite3DbMallocZero(db, sizeof(struct RenameCtx)); pRename->pTab = pTab; Walker walker = {0}; walker.pParse = &parse; walker.u.pRename = (void*)pRename; // Allocate SrcList with space for 1 item SrcList *pSrc = sqlite3DbMallocZero(db, sizeof(SrcList) + sizeof(SrcItem)); pSrc->nSrc = 1; pSrc->a[0].pSTab = pTab; // Points to our table - MATCH! pSrc->a[0].zName = "old_table"; Select select = {0}; select.pSrc = pSrc; select.selFlags = 0; int result = test_renameTableSelectCb(&walker, &select); // Should continue after processing TEST_ASSERT_EQUAL(WRC_Continue, result); sqlite3DbFree(db, pRename); sqlite3DbFree(db, pSrc); sqlite3DbFree(db, pTab->zName); sqlite3DbFree(db, pTab); sqlite3_close(db); } // ========== Test 7: Table NOT found in source list ========== void test_renameTableSelectCb_table_not_found(void) { sqlite3 *db; sqlite3_open(":memory:", &db); Parse parse = {0}; parse.db = db; // Table we're looking for Table *pTab = sqlite3DbMallocZero(db, sizeof(Table)); pTab->zName = sqlite3DbStrDup(db, "old_table"); struct RenameCtx { Table *pTab; const char *zOld; }; struct RenameCtx *pRename = sqlite3DbMallocZero(db, sizeof(struct RenameCtx)); pRename->pTab = pTab; Walker walker = {0}; walker.pParse = &parse; walker.u.pRename = (void*)pRename; // Different table in source list Table *pOtherTab = sqlite3DbMallocZero(db, sizeof(Table)); pOtherTab->zName = sqlite3DbStrDup(db, "other_table"); SrcList *pSrc = sqlite3DbMallocZero(db, sizeof(SrcList) + sizeof(SrcItem)); pSrc->nSrc = 1; pSrc->a[0].pSTab = pOtherTab; // Different table - NO MATCH pSrc->a[0].zName = "other_table"; Select select = {0}; select.pSrc = pSrc; select.selFlags = 0; int result = test_renameTableSelectCb(&walker, &select); TEST_ASSERT_EQUAL(WRC_Continue, result); sqlite3DbFree(db, pRename); sqlite3DbFree(db, pSrc); sqlite3DbFree(db, pTab->zName); sqlite3DbFree(db, pTab); sqlite3DbFree(db, pOtherTab->zName); sqlite3DbFree(db, pOtherTab); sqlite3_close(db); } // ========== Test 8: Multiple tables in source list, target found ========== void test_renameTableSelectCb_multiple_tables_found(void) { sqlite3 *db; sqlite3_open(":memory:", &db); Parse parse = {0}; parse.db = db; // Target table Table *pTab = sqlite3DbMallocZero(db, sizeof(Table)); pTab->zName = sqlite3DbStrDup(db, "target_table"); struct RenameCtx { Table *pTab; const char *zOld; }; struct RenameCtx *pRename = sqlite3DbMallocZero(db, sizeof(struct RenameCtx)); pRename->pTab = pTab; Walker walker = {0}; walker.pParse = &parse; walker.u.pRename = (void*)pRename; // Create other tables Table *pTab1 = sqlite3DbMallocZero(db, sizeof(Table)); pTab1->zName = sqlite3DbStrDup(db, "table1"); Table *pTab2 = sqlite3DbMallocZero(db, sizeof(Table)); pTab2->zName = sqlite3DbStrDup(db, "table2"); // Allocate SrcList with space for 3 items SrcList *pSrc = sqlite3DbMallocZero(db, sizeof(SrcList) + 3 * sizeof(SrcItem)); pSrc->nSrc = 3; pSrc->a[0].pSTab = pTab1; pSrc->a[0].zName = "table1"; pSrc->a[1].pSTab = pTab; // Target in middle pSrc->a[1].zName = "target_table"; pSrc->a[2].pSTab = pTab2; pSrc->a[2].zName = "table2"; Select select = {0}; select.pSrc = pSrc; select.selFlags = 0; int result = test_renameTableSelectCb(&walker, &select); TEST_ASSERT_EQUAL(WRC_Continue, result); sqlite3DbFree(db, pRename); sqlite3DbFree(db, pSrc); sqlite3DbFree(db, pTab->zName); sqlite3DbFree(db, pTab); sqlite3DbFree(db, pTab1->zName); sqlite3DbFree(db, pTab1); sqlite3DbFree(db, pTab2->zName); sqlite3DbFree(db, pTab2); sqlite3_close(db); } // ========== Test 9: Multiple tables, target NOT found ========== void test_renameTableSelectCb_multiple_tables_not_found(void) { sqlite3 *db; sqlite3_open(":memory:", &db); Parse parse = {0}; parse.db = db; // Target table (NOT in source list) Table *pTab = sqlite3DbMallocZero(db, sizeof(Table)); pTab->zName = sqlite3DbStrDup(db, "target_table"); struct RenameCtx { Table *pTab; const char *zOld; }; struct RenameCtx *pRename = sqlite3DbMallocZero(db, sizeof(struct RenameCtx)); pRename->pTab = pTab; Walker walker = {0}; walker.pParse = &parse; walker.u.pRename = (void*)pRename; // Different tables Table *pTab1 = sqlite3DbMallocZero(db, sizeof(Table)); pTab1->zName = sqlite3DbStrDup(db, "table1"); Table *pTab2 = sqlite3DbMallocZero(db, sizeof(Table)); pTab2->zName = sqlite3DbStrDup(db, "table2"); SrcList *pSrc = sqlite3DbMallocZero(db, sizeof(SrcList) + 2 * sizeof(SrcItem)); pSrc->nSrc = 2; pSrc->a[0].pSTab = pTab1; pSrc->a[0].zName = "table1"; pSrc->a[1].pSTab = pTab2; pSrc->a[1].zName = "table2"; // Target NOT in list! Select select = {0}; select.pSrc = pSrc; select.selFlags = 0; int result = test_renameTableSelectCb(&walker, &select); TEST_ASSERT_EQUAL(WRC_Continue, result); sqlite3DbFree(db, pRename); sqlite3DbFree(db, pSrc); sqlite3DbFree(db, pTab->zName); sqlite3DbFree(db, pTab); sqlite3DbFree(db, pTab1->zName); sqlite3DbFree(db, pTab1); sqlite3DbFree(db, pTab2->zName); sqlite3DbFree(db, pTab2); sqlite3_close(db); } int main(void) { UNITY_BEGIN(); RUN_TEST(test_renameTableSelectCb_prunes_view); RUN_TEST(test_renameTableSelectCb_prunes_copycte); RUN_TEST(test_renameTableSelectCb_prunes_view_and_cte); RUN_TEST(test_renameTableSelectCb_null_srclist_aborts); RUN_TEST(test_renameTableSelectCb_empty_srclist_continues); RUN_TEST(test_renameTableSelectCb_finds_table_reference); RUN_TEST(test_renameTableSelectCb_table_not_found); RUN_TEST(test_renameTableSelectCb_multiple_tables_found); RUN_TEST(test_renameTableSelectCb_multiple_tables_not_found); return UNITY_END(); }