AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Forward declaration of function under test */7void sqlite3RenameTokenRemap(Parse *pParse, const void *pTo, const void *pFrom);8 9static void* allocByte(unsigned char v){10 unsigned char *p = (unsigned char*)sqlite3_malloc(1);11 TEST_ASSERT_NOT_NULL(p);12 *p = v;13 return (void*)p;14}15 16static void freeIf(void *p){17 if(p) sqlite3_free(p);18}19 20static void initParseWithDb(Parse *pParse, sqlite3 **ppDb){21 int rc;22 sqlite3 *db = 0;23 24 memset(pParse, 0, sizeof(*pParse));25 rc = sqlite3_open(":memory:", &db);26 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);27 TEST_ASSERT_NOT_NULL(db);28 29 pParse->db = db;30 db->pParse = pParse;31 db->mallocFailed = 0;32 *ppDb = db;33}34 35static void cleanupDb(sqlite3 *db){36 if(db){37 db->pParse = 0;38 sqlite3_close(db);39 }40}41 42void setUp(void) {43 /* no-op */44}45 46void tearDown(void) {47 /* no-op */48}49 50/* Test 1: Basic remap when pFrom is found in the list (nErr==0).51 Ensure only the first matching token is updated and others unchanged. */52void test_sqlite3RenameTokenRemap_basic_remap(void){53 Parse parse;54 sqlite3 *db = NULL;55 initParseWithDb(&parse, &db);56 parse.nErr = 0;57 58 /* Create distinct valid pointers for dereference */59 void *pA = allocByte(0xA1);60 void *pB = allocByte(0xB2);61 void *pC = allocByte(0xC3);62 void *pX = allocByte(0x5A); /* pTo: ensure not equal to any existing p */63 64 /* Build RenameToken list: A -> B -> C */65 RenameToken rt1, rt2, rt3;66 memset(&rt1, 0, sizeof(rt1));67 memset(&rt2, 0, sizeof(rt2));68 memset(&rt3, 0, sizeof(rt3));69 rt1.p = pA; rt1.pNext = &rt2;70 rt2.p = pB; rt2.pNext = &rt3;71 rt3.p = pC; rt3.pNext = NULL;72 73 parse.pRename = &rt1;74 75 /* Act */76 sqlite3RenameTokenRemap(&parse, pX, pB);77 78 /* Assert */79 TEST_ASSERT_EQUAL_PTR(pA, rt1.p);80 TEST_ASSERT_EQUAL_PTR(pX, rt2.p);81 TEST_ASSERT_EQUAL_PTR(pC, rt3.p);82 83 /* Cleanup */84 freeIf(pA);85 freeIf(pB);86 freeIf(pC);87 freeIf(pX);88 cleanupDb(db);89}90 91/* Test 2: No match for pFrom in the list (nErr==0).92 Ensure list remains unchanged. */93void test_sqlite3RenameTokenRemap_no_match(void){94 Parse parse;95 sqlite3 *db = NULL;96 initParseWithDb(&parse, &db);97 parse.nErr = 0;98 99 void *pA = allocByte(0x11);100 void *pB = allocByte(0x22);101 void *pC = allocByte(0x33);102 void *pZ = allocByte(0x44); /* pFrom not in list */103 void *pTo = allocByte(0x55); /* unique pTo not in list */104 105 RenameToken rt1, rt2, rt3;106 memset(&rt1, 0, sizeof(rt1));107 memset(&rt2, 0, sizeof(rt2));108 memset(&rt3, 0, sizeof(rt3));109 rt1.p = pA; rt1.pNext = &rt2;110 rt2.p = pB; rt2.pNext = &rt3;111 rt3.p = pC; rt3.pNext = NULL;112 113 parse.pRename = &rt1;114 115 sqlite3RenameTokenRemap(&parse, pTo, pZ);116 117 TEST_ASSERT_EQUAL_PTR(pA, rt1.p);118 TEST_ASSERT_EQUAL_PTR(pB, rt2.p);119 TEST_ASSERT_EQUAL_PTR(pC, rt3.p);120 121 freeIf(pA);122 freeIf(pB);123 freeIf(pC);124 freeIf(pZ);125 freeIf(pTo);126 cleanupDb(db);127}128 129/* Test 3: Multiple matches for pFrom; only the first should be remapped (nErr==0). */130void test_sqlite3RenameTokenRemap_multiple_matches_first_only(void){131 Parse parse;132 sqlite3 *db = NULL;133 initParseWithDb(&parse, &db);134 parse.nErr = 0;135 136 void *pM = allocByte(0x77);137 void *pOther = allocByte(0x88);138 void *pNew = allocByte(0x99); /* unique pTo not in list */139 140 RenameToken rt1, rt2, rt3;141 memset(&rt1, 0, sizeof(rt1));142 memset(&rt2, 0, sizeof(rt2));143 memset(&rt3, 0, sizeof(rt3));144 rt1.p = pM; rt1.pNext = &rt2;145 rt2.p = pOther; rt2.pNext = &rt3;146 rt3.p = pM; rt3.pNext = NULL;147 148 parse.pRename = &rt1;149 150 sqlite3RenameTokenRemap(&parse, pNew, pM);151 152 TEST_ASSERT_EQUAL_PTR(pNew, rt1.p);153 TEST_ASSERT_EQUAL_PTR(pOther, rt2.p);154 TEST_ASSERT_EQUAL_PTR(pM, rt3.p); /* unchanged */155 156 freeIf(pM);157 freeIf(pOther);158 freeIf(pNew);159 cleanupDb(db);160}161 162/* Test 4: pParse->nErr != 0 bypasses the renameTokenCheckAll deref and P==pTo check.163 Here, pTo equals an existing pointer in the list. */164void test_sqlite3RenameTokenRemap_nErr_nonzero_allows_pTo_equal_existing(void){165 Parse parse;166 sqlite3 *db = NULL;167 initParseWithDb(&parse, &db);168 169 parse.nErr = 1; /* bypass renameTokenCheckAll internal deref and equality assert */170 171 void *pA = allocByte(0xAB);172 void *pB = allocByte(0xBC);173 174 RenameToken rt1, rt2;175 memset(&rt1, 0, sizeof(rt1));176 memset(&rt2, 0, sizeof(rt2));177 rt1.p = pA; rt1.pNext = &rt2;178 rt2.p = pB; rt2.pNext = NULL;179 180 parse.pRename = &rt1;181 182 /* pTo equals existing pointer (rt2.p) */183 sqlite3RenameTokenRemap(&parse, pB, pA);184 185 TEST_ASSERT_EQUAL_PTR(pB, rt1.p);186 TEST_ASSERT_EQUAL_PTR(pB, rt2.p);187 188 /* Cleanup: avoid double-free: both tokens point to pB now */189 freeIf(pA);190 freeIf(pB);191 cleanupDb(db);192}193 194/* Test 5: List contains a NULL pointer entry; function should skip it safely (nErr==0). */195void test_sqlite3RenameTokenRemap_handles_null_token_pointers(void){196 Parse parse;197 sqlite3 *db = NULL;198 initParseWithDb(&parse, &db);199 parse.nErr = 0;200 201 void *pA = allocByte(0x01);202 void *pNew = allocByte(0x02);203 204 RenameToken rt1, rt2;205 memset(&rt1, 0, sizeof(rt1));206 memset(&rt2, 0, sizeof(rt2));207 rt1.p = NULL; rt1.pNext = &rt2;208 rt2.p = pA; rt2.pNext = NULL;209 210 parse.pRename = &rt1;211 212 sqlite3RenameTokenRemap(&parse, pNew, pA);213 214 TEST_ASSERT_NULL(rt1.p);215 TEST_ASSERT_EQUAL_PTR(pNew, rt2.p);216 217 freeIf(pA);218 freeIf(pNew);219 cleanupDb(db);220}221 222int main(void){223 UNITY_BEGIN();224 RUN_TEST(test_sqlite3RenameTokenRemap_basic_remap);225 RUN_TEST(test_sqlite3RenameTokenRemap_no_match);226 RUN_TEST(test_sqlite3RenameTokenRemap_multiple_matches_first_only);227 RUN_TEST(test_sqlite3RenameTokenRemap_nErr_nonzero_allows_pTo_equal_existing);228 RUN_TEST(test_sqlite3RenameTokenRemap_handles_null_token_pointers);229 return UNITY_END();230}