#include "sqliteInt.h" #include "unity.h" #include #include /* Globals for test */ static sqlite3 *gDb = NULL; static Parse gParse; /* Helper: add a RenameToken to gParse.pRename pointing at p */ static RenameToken* addRenameToken(void *p){ RenameToken *r = (RenameToken*)sqlite3_malloc(sizeof(RenameToken)); TEST_ASSERT_NOT_NULL(r); memset(r, 0, sizeof(*r)); r->p = p; r->pNext = gParse.pRename; gParse.pRename = r; return r; } /* Helper: free all RenameToken nodes in gParse.pRename */ static void freeAllRenameTokens(void){ RenameToken *p = gParse.pRename; while( p ){ RenameToken *pNext = p->pNext; sqlite3_free(p); p = pNext; } gParse.pRename = NULL; } void setUp(void) { int rc = sqlite3_open(":memory:", &gDb); TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc); memset(&gParse, 0, sizeof(gParse)); gParse.db = gDb; gParse.pRename = NULL; } void tearDown(void) { freeAllRenameTokens(); if( gDb ){ int rc = sqlite3_close(gDb); TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc); gDb = NULL; } } /* Utility: create an ExprList with a single integer expression and assign alias */ static ExprList* makeExprListWithAlias(Parse *pParse, int val, const char *alias){ char buf[32]; sqlite3_snprintf(sizeof(buf), buf, "%d", val); Expr *pExpr = sqlite3Expr(pParse->db, TK_INTEGER, buf); TEST_ASSERT_NOT_NULL(pExpr); ExprList *pList = sqlite3ExprListAppend(pParse, NULL, pExpr); TEST_ASSERT_NOT_NULL(pList); Token t; t.z = (char*)alias; t.n = (int)strlen(alias); sqlite3ExprListSetName(pParse, pList, &t, 1); return pList; } /* Utility: append another integer expression with alias to an existing list */ static void appendExprWithAlias(Parse *pParse, ExprList **ppList, int val, const char *alias){ char buf[32]; sqlite3_snprintf(sizeof(buf), buf, "%d", val); Expr *pExpr = sqlite3Expr(pParse->db, TK_INTEGER, buf); TEST_ASSERT_NOT_NULL(pExpr); *ppList = sqlite3ExprListAppend(pParse, *ppList, pExpr); TEST_ASSERT_NOT_NULL(*ppList); Token t; t.z = (char*)alias; t.n = (int)strlen(alias); sqlite3ExprListSetName(pParse, *ppList, &t, 1); } /* Test: passing NULL pEList is a no-op (tokens unchanged) */ void test_sqlite3RenameExprlistUnmap_null_list_noop(void){ int dummy1 = 0x11; int dummy2 = 0x22; RenameToken *rt1 = addRenameToken(&dummy1); RenameToken *rt2 = addRenameToken(&dummy2); sqlite3RenameExprlistUnmap(&gParse, NULL); TEST_ASSERT_EQUAL_PTR(&dummy1, rt1->p); TEST_ASSERT_EQUAL_PTR(&dummy2, rt2->p); } /* Test: unmaps tokens for expression nodes and zEName aliases in the list */ void test_sqlite3RenameExprlistUnmap_unmaps_expr_nodes_and_aliases(void){ /* Build ExprList with two items: 1 AS a, 2 AS b */ ExprList *pList = makeExprListWithAlias(&gParse, 1, "a"); appendExprWithAlias(&gParse, &pList, 2, "b"); /* Capture pointers to alias names and one expression node */ TEST_ASSERT_TRUE(pList->nExpr >= 2); char *zName0 = pList->a[0].zEName; char *zName1 = pList->a[1].zEName; TEST_ASSERT_NOT_NULL(zName0); TEST_ASSERT_NOT_NULL(zName1); Expr *pExpr0 = pList->a[0].pExpr; TEST_ASSERT_NOT_NULL(pExpr0); /* Create RenameToken entries for: ** - The first expression node pointer (should be unmapped by walker) ** - Both alias zEName pointers (should be unmapped by explicit remap) ** - An unrelated pointer (should remain unchanged) */ int unrelatedDummy = 0xABCD; RenameToken *rtExpr = addRenameToken((void*)pExpr0); RenameToken *rtName0 = addRenameToken((void*)zName0); RenameToken *rtName1 = addRenameToken((void*)zName1); RenameToken *rtUnrelated = addRenameToken(&unrelatedDummy); /* Call function under test */ sqlite3RenameExprlistUnmap(&gParse, pList); /* Validate: mapped tokens for expr and names are cleared; unrelated unchanged */ TEST_ASSERT_NULL(rtExpr->p); TEST_ASSERT_NULL(rtName0->p); TEST_ASSERT_NULL(rtName1->p); TEST_ASSERT_EQUAL_PTR(&unrelatedDummy, rtUnrelated->p); sqlite3ExprListDelete(gDb, pList); } /* Test: when there are no matching tokens (neither expr nodes nor zEName), ** the rename list remains unchanged. */ void test_sqlite3RenameExprlistUnmap_no_matching_tokens(void){ ExprList *pList = makeExprListWithAlias(&gParse, 3, "c"); /* Create a token that does not correspond to any node or alias in pList */ int other = 123; RenameToken *rtOther = addRenameToken(&other); /* Sanity: ensure we did NOT add tokens pointing to pList's nodes or zEName */ TEST_ASSERT_NOT_NULL(pList->a[0].pExpr); TEST_ASSERT_NOT_NULL(pList->a[0].zEName); TEST_ASSERT_NOT_EQUAL_PTR(pList->a[0].pExpr, rtOther->p); TEST_ASSERT_NOT_EQUAL_PTR(pList->a[0].zEName, rtOther->p); sqlite3RenameExprlistUnmap(&gParse, pList); /* No changes expected */ TEST_ASSERT_EQUAL_PTR(&other, rtOther->p); sqlite3ExprListDelete(gDb, pList); } int main(void) { UNITY_BEGIN(); RUN_TEST(test_sqlite3RenameExprlistUnmap_null_list_noop); RUN_TEST(test_sqlite3RenameExprlistUnmap_unmaps_expr_nodes_and_aliases); RUN_TEST(test_sqlite3RenameExprlistUnmap_no_matching_tokens); return UNITY_END(); }