#include "sqliteInt.h" #include "unity.h" #include #include /* The wrapper added for testing static function renameColumnIdlistNames */ extern void test_renameColumnIdlistNames( Parse *pParse, RenameCtx *pCtx, const IdList *pIdList, const char *zOld ); /* Globals for a simple db/parse lifecycle per test */ static sqlite3 *gDb = NULL; static Parse gParse; /* Helper: build an IdList by appending names using SQLite's own allocator */ static IdList *makeIdList(Parse *pParse, const char **azName, int nName){ IdList *pList = 0; for(int i = 0; i < nName; i++){ Token t; t.z = azName[i]; t.n = (int)strlen(azName[i]); pList = sqlite3IdListAppend(pParse, pList, &t); TEST_ASSERT_NOT_NULL_MESSAGE(pList, "sqlite3IdListAppend returned NULL"); } return pList; } /* Unity setup/teardown */ void setUp(void) { int rc = sqlite3_open(":memory:", &gDb); TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_open failed"); memset(&gParse, 0, sizeof(gParse)); gParse.db = gDb; } void tearDown(void) { if( gDb ){ sqlite3_close(gDb); gDb = NULL; } } /* Tests */ void test_renameColumnIdlistNames_null_list_noop(void){ RenameCtx ctx, ctxBefore; memset(&ctx, 0, sizeof(ctx)); memcpy(&ctxBefore, &ctx, sizeof(ctx)); test_renameColumnIdlistNames(&gParse, &ctx, NULL, "x"); TEST_ASSERT_EQUAL_MEMORY(&ctxBefore, &ctx, sizeof(ctx)); } void test_renameColumnIdlistNames_empty_list_noop(void){ RenameCtx ctx, ctxBefore; memset(&ctx, 0, sizeof(ctx)); memcpy(&ctxBefore, &ctx, sizeof(ctx)); IdList *pList = (IdList*)sqlite3DbMallocZero(gParse.db, sizeof(IdList)); TEST_ASSERT_NOT_NULL(pList); /* pList->nId is 0 and pList->a is NULL due to MallocZero */ test_renameColumnIdlistNames(&gParse, &ctx, pList, "anything"); TEST_ASSERT_EQUAL_MEMORY(&ctxBefore, &ctx, sizeof(ctx)); sqlite3IdListDelete(gParse.db, pList); } void test_renameColumnIdlistNames_no_match_ctx_unchanged(void){ const char *names[] = {"alpha","beta","gamma"}; IdList *pList = makeIdList(&gParse, names, 3); RenameCtx ctx, ctxBefore; memset(&ctx, 0, sizeof(ctx)); memcpy(&ctxBefore, &ctx, sizeof(ctx)); test_renameColumnIdlistNames(&gParse, &ctx, pList, "delta"); TEST_ASSERT_EQUAL_MEMORY(&ctxBefore, &ctx, sizeof(ctx)); sqlite3IdListDelete(gParse.db, pList); } void test_renameColumnIdlistNames_single_match_exact_no_crash(void){ const char *names[] = {"alpha","beta","gamma"}; IdList *pList = makeIdList(&gParse, names, 3); RenameCtx ctx; memset(&ctx, 0, sizeof(ctx)); /* Should not crash; we do not assert internal rename-token effects */ test_renameColumnIdlistNames(&gParse, &ctx, pList, "beta"); /* Ensure input list is intact */ TEST_ASSERT_EQUAL_INT(3, pList->nId); TEST_ASSERT_NOT_NULL(pList->a); TEST_ASSERT_NOT_NULL(pList->a[1].zName); TEST_ASSERT_EQUAL_STRING("beta", pList->a[1].zName); sqlite3IdListDelete(gParse.db, pList); } void test_renameColumnIdlistNames_single_match_case_insensitive_no_crash(void){ const char *names[] = {"alpha","BeTa","gamma"}; IdList *pList = makeIdList(&gParse, names, 3); RenameCtx ctx; memset(&ctx, 0, sizeof(ctx)); test_renameColumnIdlistNames(&gParse, &ctx, pList, "bEtA"); /* Input remains intact */ TEST_ASSERT_EQUAL_INT(3, pList->nId); TEST_ASSERT_NOT_NULL(pList->a[1].zName); TEST_ASSERT_EQUAL_STRING("BeTa", pList->a[1].zName); sqlite3IdListDelete(gParse.db, pList); } void test_renameColumnIdlistNames_multiple_matches_no_crash(void){ const char *names[] = {"a","A","b","a","c","A"}; IdList *pList = makeIdList(&gParse, names, 6); RenameCtx ctx; memset(&ctx, 0, sizeof(ctx)); test_renameColumnIdlistNames(&gParse, &ctx, pList, "a"); /* Validate the list content remains correct */ TEST_ASSERT_EQUAL_INT(6, pList->nId); TEST_ASSERT_EQUAL_STRING("a", pList->a[0].zName); TEST_ASSERT_EQUAL_STRING("A", pList->a[1].zName); TEST_ASSERT_EQUAL_STRING("a", pList->a[3].zName); TEST_ASSERT_EQUAL_STRING("A", pList->a[5].zName); sqlite3IdListDelete(gParse.db, pList); } void test_renameColumnIdlistNames_long_strings_and_mixed_case_no_crash(void){ const char *names[] = { "MiXeDCaSeName", "another_name_with_underscores", "yetAnotherName123", "LONGNAME_LONGNAME_LONGNAME" }; IdList *pList = makeIdList(&gParse, names, 4); RenameCtx ctx; memset(&ctx, 0, sizeof(ctx)); test_renameColumnIdlistNames(&gParse, &ctx, pList, "mixedcasename"); /* matches first */ /* Sanity check list intact */ TEST_ASSERT_EQUAL_STRING("MiXeDCaSeName", pList->a[0].zName); sqlite3IdListDelete(gParse.db, pList); } void test_renameColumnIdlistNames_large_list_no_match_no_crash(void){ enum { N = 200 }; const char *arr[N]; char *storage[N]; for(int i=0; i