#include "sqliteInt.h" #include "unity.h" #include #include /* The test wrapper for the static function is expected to be provided */ extern int test_renameTableExprCb(Walker *pWalker, Expr *pExpr); static sqlite3 *gDb = NULL; void setUp(void) { int rc = sqlite3_open(":memory:", &gDb); TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc); TEST_ASSERT_NOT_NULL(gDb); } void tearDown(void) { if (gDb) { sqlite3_close(gDb); gDb = NULL; } } /* Helper to initialize a minimal Parse object */ static void initParse(Parse *pParse){ memset(pParse, 0, sizeof(*pParse)); pParse->db = gDb; } /* Helper to initialize a minimal Walker with a RenameCtx */ static void initWalkerWithRenameCtx(Walker *pWalker, RenameCtx *pCtx, Parse *pParse){ memset(pWalker, 0, sizeof(*pWalker)); memset(pCtx, 0, sizeof(*pCtx)); pWalker->pParse = pParse; pWalker->u.pRename = pCtx; } /* Helper to initialize an Expr with TK_COLUMN and specified Table* */ static void initColumnExprWithTab(Expr *pExpr, Table *pTab){ memset(pExpr, 0, sizeof(*pExpr)); pExpr->op = TK_COLUMN; /* ExprUseYTab() is true for TK_COLUMN, so fill y.pTab */ pExpr->y.pTab = pTab; } /* 1) Non-column expression: ensure return value is WRC_Continue and no crash */ void test_renameTableExprCb_returns_continue_for_non_column(void){ Parse sParse; initParse(&sParse); Walker sWalker; RenameCtx sCtx; initWalkerWithRenameCtx(&sWalker, &sCtx, &sParse); Expr sExpr; memset(&sExpr, 0, sizeof(sExpr)); sExpr.op = TK_INTEGER; /* Not TK_COLUMN, so condition should be false */ int rc = test_renameTableExprCb(&sWalker, &sExpr); TEST_ASSERT_EQUAL_INT(WRC_Continue, rc); } /* 2) TK_COLUMN but pExpr->y.pTab does not match RenameCtx.pTab: no-op, returns continue */ void test_renameTableExprCb_no_action_when_table_mismatch(void){ Parse sParse; initParse(&sParse); Walker sWalker; RenameCtx sCtx; initWalkerWithRenameCtx(&sWalker, &sCtx, &sParse); Table tabA, tabB; memset(&tabA, 0, sizeof(tabA)); memset(&tabB, 0, sizeof(tabB)); sCtx.pTab = &tabA; /* Context expects tabA */ Expr sExpr; initColumnExprWithTab(&sExpr, &tabB); /* Expression references tabB */ int rc = test_renameTableExprCb(&sWalker, &sExpr); TEST_ASSERT_EQUAL_INT(WRC_Continue, rc); } /* 3) TK_COLUMN and pExpr->y.pTab matches RenameCtx.pTab: should trigger renameTokenFind and return WRC_Continue */ void test_renameTableExprCb_triggers_on_match(void){ Parse sParse; initParse(&sParse); Walker sWalker; RenameCtx sCtx; initWalkerWithRenameCtx(&sWalker, &sCtx, &sParse); Table tabT; memset(&tabT, 0, sizeof(tabT)); sCtx.pTab = &tabT; Expr sExpr; initColumnExprWithTab(&sExpr, &tabT); int rc = test_renameTableExprCb(&sWalker, &sExpr); TEST_ASSERT_EQUAL_INT(WRC_Continue, rc); } /* 4) Multiple sequential invocations with mixed inputs to ensure robustness and idempotent return */ void test_renameTableExprCb_multiple_sequential_calls(void){ Parse sParse; initParse(&sParse); Walker sWalker; RenameCtx sCtx; initWalkerWithRenameCtx(&sWalker, &sCtx, &sParse); Table tab1, tab2; memset(&tab1, 0, sizeof(tab1)); memset(&tab2, 0, sizeof(tab2)); sCtx.pTab = &tab1; Expr e1, e2, e3; /* Non-column: should be ignored */ memset(&e1, 0, sizeof(e1)); e1.op = TK_NULL; /* Column but mismatch: should be ignored */ initColumnExprWithTab(&e2, &tab2); /* Column and match: should trigger renameTokenFind */ initColumnExprWithTab(&e3, &tab1); TEST_ASSERT_EQUAL_INT(WRC_Continue, test_renameTableExprCb(&sWalker, &e1)); TEST_ASSERT_EQUAL_INT(WRC_Continue, test_renameTableExprCb(&sWalker, &e2)); TEST_ASSERT_EQUAL_INT(WRC_Continue, test_renameTableExprCb(&sWalker, &e3)); } int main(void) { UNITY_BEGIN(); RUN_TEST(test_renameTableExprCb_returns_continue_for_non_column); RUN_TEST(test_renameTableExprCb_no_action_when_table_mismatch); RUN_TEST(test_renameTableExprCb_triggers_on_match); RUN_TEST(test_renameTableExprCb_multiple_sequential_calls); return UNITY_END(); }