#include "sqliteInt.h" #include "unity.h" #include /* Wrapper for the static function under test (provided by build system) */ extern int test_renameTableSelectCb(Walker *pWalker, Select *pSelect); /* Global test fixtures */ static sqlite3 *gDb = NULL; static Parse gParse; /* Helpers */ static SrcList* allocSrcList(int nSrc){ int nByte = (int)sizeof(SrcList); if( nSrc>1 ){ nByte += (nSrc-1) * (int)sizeof(SrcItem); } SrcList *p = (SrcList*)sqlite3DbMallocZero(gDb, nByte); if( p ){ p->nSrc = (u8)nSrc; } return p; } void setUp(void) { int rc = sqlite3_open(":memory:", &gDb); TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc); memset(&gParse, 0, sizeof(gParse)); gParse.db = gDb; } void tearDown(void) { if( gDb ){ sqlite3_close(gDb); gDb = NULL; } } /* Test: When SF_View is set, the callback should prune traversal */ void test_renameTableSelectCb_returns_prune_for_SF_View(void){ Select s; memset(&s, 0, sizeof(s)); s.selFlags = SF_View; /* triggers early return */ /* pSrc can be NULL safely because of early return */ Walker w; memset(&w, 0, sizeof(w)); RenameCtx rcRename; memset(&rcRename, 0, sizeof(rcRename)); w.u.pRename = &rcRename; w.pParse = &gParse; int rc = test_renameTableSelectCb(&w, &s); TEST_ASSERT_EQUAL_INT(WRC_Prune, rc); } /* Test: When SF_CopyCte is set, the callback should prune traversal */ void test_renameTableSelectCb_returns_prune_for_SF_CopyCte(void){ Select s; memset(&s, 0, sizeof(s)); s.selFlags = SF_CopyCte; /* triggers early return */ Walker w; memset(&w, 0, sizeof(w)); RenameCtx rcRename; memset(&rcRename, 0, sizeof(rcRename)); w.u.pRename = &rcRename; w.pParse = &gParse; int rc = test_renameTableSelectCb(&w, &s); TEST_ASSERT_EQUAL_INT(WRC_Prune, rc); } /* Test: With empty source list, should continue traversal (no renameTokenFind) */ void test_renameTableSelectCb_returns_continue_with_empty_src(void){ Select s; memset(&s, 0, sizeof(s)); s.selFlags = 0; s.pWith = 0; /* Avoid WITH processing */ s.pSrc = allocSrcList(0); /* Ensure pSrc != NULL to avoid NEVER-assert path */ TEST_ASSERT_NOT_NULL(s.pSrc); Walker w; memset(&w, 0, sizeof(w)); RenameCtx rcRename; memset(&rcRename, 0, sizeof(rcRename)); w.u.pRename = &rcRename; w.pParse = &gParse; int rc = test_renameTableSelectCb(&w, &s); TEST_ASSERT_EQUAL_INT(WRC_Continue, rc); sqlite3DbFree(gDb, s.pSrc); } /* Test: With one non-matching source item, should continue traversal */ void test_renameTableSelectCb_returns_continue_with_non_matching_src(void){ /* Prepare tables for pointer comparison */ Table tWanted; memset(&tWanted, 0, sizeof(tWanted)); Table tOther; memset(&tOther, 0, sizeof(tOther)); /* Build Select with one source item that does NOT match RenameCtx.pTab */ Select s; memset(&s, 0, sizeof(s)); s.selFlags = 0; s.pWith = 0; SrcList *pSrc = allocSrcList(1); TEST_ASSERT_NOT_NULL(pSrc); pSrc->a[0].pSTab = &tOther; /* does not match */ pSrc->a[0].zName = "t_other"; /* benign name for potential token lookup */ s.pSrc = pSrc; Walker w; memset(&w, 0, sizeof(w)); RenameCtx rcRename; memset(&rcRename, 0, sizeof(rcRename)); rcRename.pTab = &tWanted; /* different from pSTab above */ w.u.pRename = &rcRename; w.pParse = &gParse; int rc = test_renameTableSelectCb(&w, &s); TEST_ASSERT_EQUAL_INT(WRC_Continue, rc); sqlite3DbFree(gDb, s.pSrc); } int main(void) { UNITY_BEGIN(); RUN_TEST(test_renameTableSelectCb_returns_prune_for_SF_View); RUN_TEST(test_renameTableSelectCb_returns_prune_for_SF_CopyCte); RUN_TEST(test_renameTableSelectCb_returns_continue_with_empty_src); RUN_TEST(test_renameTableSelectCb_returns_continue_with_non_matching_src); return UNITY_END(); }