#include "sqliteInt.h" #include "unity.h" #include #include /* Wrapper for the static function under test (provided by the build) */ extern void test_renameWalkTrigger(Walker *pWalker, Trigger *pTrigger); /* Global counters/state for callbacks */ typedef struct CallbackState { /* Totals */ int nExprCalls; int nSelectCalls; /* Specific node hits */ int hitWhen; int hitWhere; int hitList1; int hitList2; int hitUpTarget1; int hitUpSet1; int hitUpWhere; int hitUpTargetWhere; int hitSel1; int hitSel2; /* Unexpected nodes */ int unexpectedExpr; int unexpectedSelect; /* Expected node pointers */ Expr *pWhen; Expr *pWhere; Expr *pList1; Expr *pList2; Expr *pUpTarget1; Expr *pUpSet1; Expr *pUpWhere; Expr *pUpTargetWhere; Select *pSel1; Select *pSel2; } CallbackState; static CallbackState gCb; /* Walker callbacks */ static int testExprCallback(Walker *pWalker, Expr *pExpr){ (void)pWalker; gCb.nExprCalls++; if( pExpr==gCb.pWhen ) gCb.hitWhen++; else if( pExpr==gCb.pWhere ) gCb.hitWhere++; else if( pExpr==gCb.pList1 ) gCb.hitList1++; else if( pExpr==gCb.pList2 ) gCb.hitList2++; else if( pExpr==gCb.pUpTarget1 ) gCb.hitUpTarget1++; else if( pExpr==gCb.pUpSet1 ) gCb.hitUpSet1++; else if( pExpr==gCb.pUpWhere ) gCb.hitUpWhere++; else if( pExpr==gCb.pUpTargetWhere ) gCb.hitUpTargetWhere++; else gCb.unexpectedExpr++; return WRC_Continue; } static int testSelectCallback(Walker *pWalker, Select *pSelect){ (void)pWalker; gCb.nSelectCalls++; if( pSelect==gCb.pSel1 ) gCb.hitSel1++; else if( pSelect==gCb.pSel2 ) gCb.hitSel2++; else gCb.unexpectedSelect++; return WRC_Continue; } /* Helpers to create minimal nodes */ static Expr *mkLeafExpr(void){ Expr *p = (Expr*)sqlite3_malloc(sizeof(Expr)); TEST_ASSERT_NOT_NULL_MESSAGE(p, "sqlite3_malloc Expr failed"); memset(p, 0, sizeof(Expr)); p->op = TK_NULL; /* A safe leaf opcode */ return p; } static Select *mkEmptySelect(void){ Select *p = (Select*)sqlite3_malloc(sizeof(Select)); TEST_ASSERT_NOT_NULL_MESSAGE(p, "sqlite3_malloc Select failed"); memset(p, 0, sizeof(Select)); return p; } static ExprList *mkExprList1(Expr *e1){ ExprList *p = (ExprList*)sqlite3_malloc(sizeof(ExprList)); TEST_ASSERT_NOT_NULL_MESSAGE(p, "sqlite3_malloc ExprList failed"); memset(p, 0, sizeof(ExprList)); p->nExpr = 1; p->nAlloc = 1; p->a = (ExprList_item*)sqlite3_malloc(sizeof(ExprList_item) * 1); TEST_ASSERT_NOT_NULL_MESSAGE(p->a, "sqlite3_malloc ExprList_item[1] failed"); memset(p->a, 0, sizeof(ExprList_item) * 1); p->a[0].pExpr = e1; return p; } static ExprList *mkExprList2(Expr *e1, Expr *e2){ ExprList *p = (ExprList*)sqlite3_malloc(sizeof(ExprList)); TEST_ASSERT_NOT_NULL_MESSAGE(p, "sqlite3_malloc ExprList failed"); memset(p, 0, sizeof(ExprList)); p->nExpr = 2; p->nAlloc = 2; p->a = (ExprList_item*)sqlite3_malloc(sizeof(ExprList_item) * 2); TEST_ASSERT_NOT_NULL_MESSAGE(p->a, "sqlite3_malloc ExprList_item[2] failed"); memset(p->a, 0, sizeof(ExprList_item) * 2); p->a[0].pExpr = e1; p->a[1].pExpr = e2; return p; } static void freeExprList(ExprList *p){ if( p ){ sqlite3_free(p->a); sqlite3_free(p); } } /* Unity fixtures */ void setUp(void){ memset(&gCb, 0, sizeof(gCb)); } void tearDown(void){ /* Nothing global to cleanup */ } /* Test: No fields set => no callbacks */ void test_renameWalkTrigger_nulls(void){ Trigger *tr = (Trigger*)sqlite3_malloc(sizeof(Trigger)); TEST_ASSERT_NOT_NULL(tr); memset(tr, 0, sizeof(Trigger)); Walker w; memset(&w, 0, sizeof(w)); w.xExprCallback = testExprCallback; w.xSelectCallback = testSelectCallback; test_renameWalkTrigger(&w, tr); TEST_ASSERT_EQUAL_INT(0, gCb.nExprCalls); TEST_ASSERT_EQUAL_INT(0, gCb.nSelectCalls); TEST_ASSERT_EQUAL_INT(0, gCb.unexpectedExpr); TEST_ASSERT_EQUAL_INT(0, gCb.unexpectedSelect); sqlite3_free(tr); } /* Test: WHEN, SELECT, WHERE, and ExprList are all visited */ void test_renameWalkTrigger_basic_fields(void){ /* Build nodes */ Expr *eWhen = mkLeafExpr(); Expr *eWhere = mkLeafExpr(); Expr *eList1 = mkLeafExpr(); Expr *eList2 = mkLeafExpr(); ExprList *pList = mkExprList2(eList1, eList2); Select *pSel = mkEmptySelect(); /* Build step */ TriggerStep *st = (TriggerStep*)sqlite3_malloc(sizeof(TriggerStep)); TEST_ASSERT_NOT_NULL(st); memset(st, 0, sizeof(TriggerStep)); st->pSelect = pSel; st->pWhere = eWhere; st->pExprList = pList; /* Build trigger */ Trigger *tr = (Trigger*)sqlite3_malloc(sizeof(Trigger)); TEST_ASSERT_NOT_NULL(tr); memset(tr, 0, sizeof(Trigger)); tr->pWhen = eWhen; tr->step_list = st; /* Set expected pointers */ gCb.pWhen = eWhen; gCb.pWhere = eWhere; gCb.pList1 = eList1; gCb.pList2 = eList2; gCb.pSel1 = pSel; Walker w; memset(&w, 0, sizeof(w)); w.xExprCallback = testExprCallback; w.xSelectCallback = testSelectCallback; test_renameWalkTrigger(&w, tr); /* Expect: 1 WHEN + 1 WHERE + 2 list exprs = 4 expr callbacks */ TEST_ASSERT_EQUAL_INT(4, gCb.nExprCalls); TEST_ASSERT_EQUAL_INT(1, gCb.nSelectCalls); TEST_ASSERT_EQUAL_INT(1, gCb.hitWhen); TEST_ASSERT_EQUAL_INT(1, gCb.hitWhere); TEST_ASSERT_EQUAL_INT(1, gCb.hitList1); TEST_ASSERT_EQUAL_INT(1, gCb.hitList2); TEST_ASSERT_EQUAL_INT(1, gCb.hitSel1); TEST_ASSERT_EQUAL_INT(0, gCb.unexpectedExpr); TEST_ASSERT_EQUAL_INT(0, gCb.unexpectedSelect); /* Cleanup */ sqlite3_free(eWhen); sqlite3_free(eWhere); sqlite3_free(eList1); sqlite3_free(eList2); freeExprList(pList); sqlite3_free(pSel); sqlite3_free(st); sqlite3_free(tr); } /* Test: Upsert-related fields are visited */ void test_renameWalkTrigger_upsert_fields(void){ /* Build upsert components */ Expr *eUpTarget1 = mkLeafExpr(); Expr *eUpSet1 = mkLeafExpr(); Expr *eUpWhere = mkLeafExpr(); Expr *eUpTargetWhere = mkLeafExpr(); ExprList *pTarget = mkExprList1(eUpTarget1); ExprList *pSet = mkExprList1(eUpSet1); Upsert *pUp = (Upsert*)sqlite3_malloc(sizeof(Upsert)); TEST_ASSERT_NOT_NULL(pUp); memset(pUp, 0, sizeof(Upsert)); pUp->pUpsertTarget = pTarget; pUp->pUpsertSet = pSet; pUp->pUpsertWhere = eUpWhere; pUp->pUpsertTargetWhere = eUpTargetWhere; /* Step with only Upsert */ TriggerStep *st = (TriggerStep*)sqlite3_malloc(sizeof(TriggerStep)); TEST_ASSERT_NOT_NULL(st); memset(st, 0, sizeof(TriggerStep)); st->pUpsert = pUp; Trigger *tr = (Trigger*)sqlite3_malloc(sizeof(Trigger)); TEST_ASSERT_NOT_NULL(tr); memset(tr, 0, sizeof(Trigger)); tr->step_list = st; /* Expected pointers */ gCb.pUpTarget1 = eUpTarget1; gCb.pUpSet1 = eUpSet1; gCb.pUpWhere = eUpWhere; gCb.pUpTargetWhere = eUpTargetWhere; Walker w; memset(&w, 0, sizeof(w)); w.xExprCallback = testExprCallback; w.xSelectCallback = testSelectCallback; test_renameWalkTrigger(&w, tr); /* Expect: 1 target expr + 1 set expr + where + targetWhere = 4 exprs */ TEST_ASSERT_EQUAL_INT(4, gCb.nExprCalls); TEST_ASSERT_EQUAL_INT(0, gCb.nSelectCalls); TEST_ASSERT_EQUAL_INT(1, gCb.hitUpTarget1); TEST_ASSERT_EQUAL_INT(1, gCb.hitUpSet1); TEST_ASSERT_EQUAL_INT(1, gCb.hitUpWhere); TEST_ASSERT_EQUAL_INT(1, gCb.hitUpTargetWhere); TEST_ASSERT_EQUAL_INT(0, gCb.unexpectedExpr); TEST_ASSERT_EQUAL_INT(0, gCb.unexpectedSelect); /* Cleanup */ sqlite3_free(eUpTarget1); sqlite3_free(eUpSet1); sqlite3_free(eUpWhere); sqlite3_free(eUpTargetWhere); freeExprList(pTarget); freeExprList(pSet); sqlite3_free(pUp); sqlite3_free(st); sqlite3_free(tr); } /* Test: Multiple steps are iterated (one with SELECT, next with WHERE) */ void test_renameWalkTrigger_multiple_steps(void){ Select *pSel = mkEmptySelect(); Expr *eWhere2 = mkLeafExpr(); TriggerStep *st1 = (TriggerStep*)sqlite3_malloc(sizeof(TriggerStep)); TEST_ASSERT_NOT_NULL(st1); memset(st1, 0, sizeof(TriggerStep)); st1->pSelect = pSel; TriggerStep *st2 = (TriggerStep*)sqlite3_malloc(sizeof(TriggerStep)); TEST_ASSERT_NOT_NULL(st2); memset(st2, 0, sizeof(TriggerStep)); st2->pWhere = eWhere2; st1->pNext = st2; Trigger *tr = (Trigger*)sqlite3_malloc(sizeof(Trigger)); TEST_ASSERT_NOT_NULL(tr); memset(tr, 0, sizeof(Trigger)); tr->step_list = st1; /* Expected pointers */ gCb.pSel1 = pSel; gCb.pWhere = eWhere2; Walker w; memset(&w, 0, sizeof(w)); w.xExprCallback = testExprCallback; w.xSelectCallback = testSelectCallback; test_renameWalkTrigger(&w, tr); TEST_ASSERT_EQUAL_INT(1, gCb.nSelectCalls); TEST_ASSERT_EQUAL_INT(1, gCb.nExprCalls); TEST_ASSERT_EQUAL_INT(1, gCb.hitSel1); TEST_ASSERT_EQUAL_INT(1, gCb.hitWhere); TEST_ASSERT_EQUAL_INT(0, gCb.unexpectedExpr); TEST_ASSERT_EQUAL_INT(0, gCb.unexpectedSelect); /* Cleanup */ sqlite3_free(pSel); sqlite3_free(eWhere2); sqlite3_free(st1); sqlite3_free(st2); sqlite3_free(tr); } int main(void){ UNITY_BEGIN(); RUN_TEST(test_renameWalkTrigger_nulls); RUN_TEST(test_renameWalkTrigger_basic_fields); RUN_TEST(test_renameWalkTrigger_upsert_fields); RUN_TEST(test_renameWalkTrigger_multiple_steps); return UNITY_END(); }