AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4 5/* Unity setUp/tearDown */6void setUp(void) {7 /* No global setup needed */8}9void tearDown(void) {10 /* No global teardown needed */11}12 13/* Helper: open an in-memory database and assert success */14static sqlite3* openTestDb(void){15 sqlite3 *db = 0;16 int rc = sqlite3_open(":memory:", &db);17 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);18 TEST_ASSERT_NOT_NULL(db);19 return db;20}21 22/* Helper: create a Parse with the given db */23static void initParse(Parse *pParse, sqlite3 *db){24 memset(pParse, 0, sizeof(Parse));25 pParse->db = db;26 /* Default parse mode is the normal mode (0) */27}28 29/* Helper: create an ExprList with a single simple expression item */30static ExprList* makeOneItemExprList(Parse *pParse){31 Token tk = { "1", 1 }; /* Simple integer token for expression */32 Expr *pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &tk, 0);33 TEST_ASSERT_NOT_NULL(pExpr);34 ExprList *pList = sqlite3ExprListAppend(pParse, 0, pExpr);35 TEST_ASSERT_NOT_NULL(pList);36 /* The append takes ownership of pExpr; do not free separately */37 return pList;38}39 40/* Test: Basic name set without dequote */41void test_sqlite3ExprListSetName_basic_no_dequote(void){42 sqlite3 *db = openTestDb();43 Parse sParse;44 initParse(&sParse, db);45 46 ExprList *pList = makeOneItemExprList(&sParse);47 48 const char *zName = "simpleName";49 Token nameTok = { zName, (int)strlen(zName) };50 51 sqlite3ExprListSetName(&sParse, pList, &nameTok, 0);52 53 /* Verify the last item's zEName matches exactly (no dequote) */54 TEST_ASSERT_NOT_NULL(pList->a[pList->nExpr-1].zEName);55 TEST_ASSERT_EQUAL_STRING(zName, pList->a[pList->nExpr-1].zEName);56 57 sqlite3ExprListDelete(db, pList);58 sqlite3_close(db);59}60 61/* Test: Name set with dequote removes surrounding double-quotes */62void test_sqlite3ExprListSetName_dequote_double_quotes(void){63 sqlite3 *db = openTestDb();64 Parse sParse;65 initParse(&sParse, db);66 67 ExprList *pList = makeOneItemExprList(&sParse);68 69 const char *zName = "\"colName\"";70 Token nameTok = { zName, (int)strlen(zName) };71 72 sqlite3ExprListSetName(&sParse, pList, &nameTok, 1);73 74 TEST_ASSERT_NOT_NULL(pList->a[pList->nExpr-1].zEName);75 TEST_ASSERT_EQUAL_STRING("colName", pList->a[pList->nExpr-1].zEName);76 77 sqlite3ExprListDelete(db, pList);78 sqlite3_close(db);79}80 81/* Test: Dequote handles escaped double quotes ("a""b""c" -> a"b"c) */82void test_sqlite3ExprListSetName_dequote_escaped_double_quotes(void){83 sqlite3 *db = openTestDb();84 Parse sParse;85 initParse(&sParse, db);86 87 ExprList *pList = makeOneItemExprList(&sParse);88 89 const char *zName = "\"a\"\"b\"\"c\"";90 Token nameTok = { zName, (int)strlen(zName) };91 92 sqlite3ExprListSetName(&sParse, pList, &nameTok, 1);93 94 TEST_ASSERT_NOT_NULL(pList->a[pList->nExpr-1].zEName);95 TEST_ASSERT_EQUAL_STRING("a\"b\"c", pList->a[pList->nExpr-1].zEName);96 97 sqlite3ExprListDelete(db, pList);98 sqlite3_close(db);99}100 101/* Test: Dequote with backtick quoting (`back`) -> back */102void test_sqlite3ExprListSetName_dequote_backtick(void){103 sqlite3 *db = openTestDb();104 Parse sParse;105 initParse(&sParse, db);106 107 ExprList *pList = makeOneItemExprList(&sParse);108 109 const char *zName = "`back`";110 Token nameTok = { zName, (int)strlen(zName) };111 112 sqlite3ExprListSetName(&sParse, pList, &nameTok, 1);113 114 TEST_ASSERT_NOT_NULL(pList->a[pList->nExpr-1].zEName);115 TEST_ASSERT_EQUAL_STRING("back", pList->a[pList->nExpr-1].zEName);116 117 sqlite3ExprListDelete(db, pList);118 sqlite3_close(db);119}120 121/* Test: Dequote when no quotes present leaves name unchanged */122void test_sqlite3ExprListSetName_dequote_without_quotes_is_noop(void){123 sqlite3 *db = openTestDb();124 Parse sParse;125 initParse(&sParse, db);126 127 ExprList *pList = makeOneItemExprList(&sParse);128 129 const char *zName = "AlreadyPlain";130 Token nameTok = { zName, (int)strlen(zName) };131 132 sqlite3ExprListSetName(&sParse, pList, &nameTok, 1);133 134 TEST_ASSERT_NOT_NULL(pList->a[pList->nExpr-1].zEName);135 TEST_ASSERT_EQUAL_STRING("AlreadyPlain", pList->a[pList->nExpr-1].zEName);136 137 sqlite3ExprListDelete(db, pList);138 sqlite3_close(db);139}140 141/* Test: pList may be NULL if db->mallocFailed is already set (assert condition) */142void test_sqlite3ExprListSetName_null_list_with_mallocFailed_flag(void){143 sqlite3 *db = openTestDb();144 Parse sParse;145 initParse(&sParse, db);146 147 /* Manually set mallocFailed to satisfy the assert when pList==NULL */148 db->mallocFailed = 1;149 150 const char *zName = "X";151 Token nameTok = { zName, (int)strlen(zName) };152 153 /* Should be a no-op and not crash */154 sqlite3ExprListSetName(&sParse, NULL, &nameTok, 0);155 156 /* Clear the flag to not affect later tests */157 db->mallocFailed = 0;158 159 sqlite3_close(db);160}161 162/* Test: With PARSE_MODE_UNMAP, dequote must be 0 (assert path) */163void test_sqlite3ExprListSetName_unmap_mode_dequote0_allows_call(void){164#ifdef PARSE_MODE_UNMAP165 sqlite3 *db = openTestDb();166 Parse sParse;167 initParse(&sParse, db);168 sParse.eParseMode = PARSE_MODE_UNMAP;169 170 ExprList *pList = makeOneItemExprList(&sParse);171 172 const char *zName = "no_dequote";173 Token nameTok = { zName, (int)strlen(zName) };174 175 /* This should not trigger the assert: UNMAP allows only dequote==0 */176 sqlite3ExprListSetName(&sParse, pList, &nameTok, 0);177 178 TEST_ASSERT_NOT_NULL(pList->a[pList->nExpr-1].zEName);179 TEST_ASSERT_EQUAL_STRING("no_dequote", pList->a[pList->nExpr-1].zEName);180 181 sqlite3ExprListDelete(db, pList);182 sqlite3_close(db);183#endif184}185 186int main(void){187 UNITY_BEGIN();188 RUN_TEST(test_sqlite3ExprListSetName_basic_no_dequote);189 RUN_TEST(test_sqlite3ExprListSetName_dequote_double_quotes);190 RUN_TEST(test_sqlite3ExprListSetName_dequote_escaped_double_quotes);191 RUN_TEST(test_sqlite3ExprListSetName_dequote_backtick);192 RUN_TEST(test_sqlite3ExprListSetName_dequote_without_quotes_is_noop);193 RUN_TEST(test_sqlite3ExprListSetName_null_list_with_mallocFailed_flag);194 RUN_TEST(test_sqlite3ExprListSetName_unmap_mode_dequote0_allows_call);195 return UNITY_END();196}