AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdio.h>5#include <stdlib.h>6 7/* Globals used by tests */8static sqlite3 *gDb = NULL;9static Parse gParse;10 11/* Helper: allocate an Expr for a variable token using the connection allocator */12static Expr* newVarExpr(const char *zToken){13 Expr *p = (Expr*)sqlite3DbMallocZero(gDb, sizeof(Expr));14 TEST_ASSERT_NOT_NULL_MESSAGE(p, "Failed to allocate Expr");15 p->u.zToken = sqlite3DbStrDup(gDb, zToken);16 TEST_ASSERT_NOT_NULL_MESSAGE(p->u.zToken, "Failed to allocate token string");17 p->op = TK_VARIABLE; /* Reasonable op for variable tokens */18 p->flags = 0; /* Ensure not EP_IntValue/EP_Reduced/EP_TokenOnly */19 p->iColumn = 0;20 return p;21}22 23static void freeExpr(Expr *p){24 if( p ){25 if( p->u.zToken ){26 sqlite3DbFree(gDb, (void*)p->u.zToken);27 p->u.zToken = 0;28 }29 sqlite3DbFree(gDb, p);30 }31}32 33static void clearParseError(Parse *pParse){34 if( pParse->zErrMsg ){35 sqlite3DbFree(pParse->db, pParse->zErrMsg);36 pParse->zErrMsg = 0;37 }38}39 40/* Unity setup/teardown */41void setUp(void) {42 int rc = sqlite3_open(":memory:", &gDb);43 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "Failed to open in-memory SQLite DB");44 memset(&gParse, 0, sizeof(gParse));45 gParse.db = gDb;46}47 48void tearDown(void) {49 /* Free Parse-owned allocations we might have produced */50 clearParseError(&gParse);51 if( gParse.pVList ){52 sqlite3DbFree(gDb, gParse.pVList);53 gParse.pVList = 0;54 }55 if( gDb ){56 sqlite3_close(gDb);57 gDb = NULL;58 }59}60 61/* Tests */62 63void test_sqlite3ExprAssignVarNumber_qmark_sequence(void){64 /* First "?" -> var 1 */65 Expr *e1 = newVarExpr("?");66 u32 n1 = (u32)strlen(e1->u.zToken);67 sqlite3ExprAssignVarNumber(&gParse, e1, n1);68 TEST_ASSERT_EQUAL_INT(1, e1->iColumn);69 TEST_ASSERT_EQUAL_INT(1, gParse.nVar);70 TEST_ASSERT_NULL(gParse.pVList);71 TEST_ASSERT_NULL(gParse.zErrMsg);72 freeExpr(e1);73 74 /* Second "?" -> var 2 */75 Expr *e2 = newVarExpr("?");76 u32 n2 = (u32)strlen(e2->u.zToken);77 sqlite3ExprAssignVarNumber(&gParse, e2, n2);78 TEST_ASSERT_EQUAL_INT(2, e2->iColumn);79 TEST_ASSERT_EQUAL_INT(2, gParse.nVar);80 TEST_ASSERT_NULL(gParse.pVList);81 TEST_ASSERT_NULL(gParse.zErrMsg);82 freeExpr(e2);83}84 85void test_sqlite3ExprAssignVarNumber_qnnn_adds_and_mapping(void){86 /* "?3" when nVar==0 should set nVar=3 and add mapping for #3 */87 Expr *e = newVarExpr("?3");88 u32 n = (u32)strlen(e->u.zToken);89 90 sqlite3ExprAssignVarNumber(&gParse, e, n);91 TEST_ASSERT_EQUAL_INT(3, e->iColumn);92 TEST_ASSERT_EQUAL_INT(3, gParse.nVar);93 TEST_ASSERT_NOT_NULL(gParse.pVList);94 const char *z = sqlite3VListNumToName(gParse.pVList, 3);95 TEST_ASSERT_NOT_NULL(z);96 TEST_ASSERT_NULL(gParse.zErrMsg);97 freeExpr(e);98}99 100void test_sqlite3ExprAssignVarNumber_qnnn_lower_than_nVar_adds_missing_mapping(void){101 /* First create mapping for ?3 */102 Expr *e3 = newVarExpr("?3");103 u32 n3 = (u32)strlen(e3->u.zToken);104 sqlite3ExprAssignVarNumber(&gParse, e3, n3);105 TEST_ASSERT_EQUAL_INT(3, gParse.nVar);106 TEST_ASSERT_NOT_NULL(gParse.pVList);107 TEST_ASSERT_NOT_NULL(sqlite3VListNumToName(gParse.pVList, 3));108 freeExpr(e3);109 110 /* Now "?2" should not change nVar but should add mapping for #2 if missing */111 Expr *e2 = newVarExpr("?2");112 u32 n2 = (u32)strlen(e2->u.zToken);113 sqlite3ExprAssignVarNumber(&gParse, e2, n2);114 TEST_ASSERT_EQUAL_INT(2, e2->iColumn);115 TEST_ASSERT_EQUAL_INT(3, gParse.nVar);116 TEST_ASSERT_NOT_NULL(gParse.pVList);117 TEST_ASSERT_NOT_NULL(sqlite3VListNumToName(gParse.pVList, 2));118 TEST_ASSERT_NULL(gParse.zErrMsg);119 freeExpr(e2);120}121 122void test_sqlite3ExprAssignVarNumber_named_reuse_and_prefix_sensitivity(void){123 /* First occurrence of ":abc" -> var 1 */124 Expr *e1 = newVarExpr(":abc");125 u32 n1 = (u32)strlen(e1->u.zToken);126 sqlite3ExprAssignVarNumber(&gParse, e1, n1);127 TEST_ASSERT_EQUAL_INT(1, e1->iColumn);128 TEST_ASSERT_EQUAL_INT(1, gParse.nVar);129 TEST_ASSERT_NOT_NULL(gParse.pVList);130 TEST_ASSERT_EQUAL_INT(1, sqlite3VListNameToNum(gParse.pVList, ":abc", (int)n1));131 freeExpr(e1);132 133 /* Second occurrence of ":abc" -> reuse var 1, nVar unchanged */134 Expr *e2 = newVarExpr(":abc");135 u32 n2 = (u32)strlen(e2->u.zToken);136 sqlite3ExprAssignVarNumber(&gParse, e2, n2);137 TEST_ASSERT_EQUAL_INT(1, e2->iColumn);138 TEST_ASSERT_EQUAL_INT(1, gParse.nVar);139 TEST_ASSERT_EQUAL_INT(1, sqlite3VListNameToNum(gParse.pVList, ":abc", (int)n2));140 freeExpr(e2);141 142 /* Different prefix "$abc" -> different variable number (2) */143 Expr *e3 = newVarExpr("$abc");144 u32 n3 = (u32)strlen(e3->u.zToken);145 sqlite3ExprAssignVarNumber(&gParse, e3, n3);146 TEST_ASSERT_EQUAL_INT(2, e3->iColumn);147 TEST_ASSERT_EQUAL_INT(2, gParse.nVar);148 TEST_ASSERT_EQUAL_INT(2, sqlite3VListNameToNum(gParse.pVList, "$abc", (int)n3));149 freeExpr(e3);150 151 TEST_ASSERT_NULL(gParse.zErrMsg);152}153 154void test_sqlite3ExprAssignVarNumber_qnnn_invalid_zero_sets_error_and_no_change(void){155 int prevNVar = gParse.nVar;156 Expr *e = newVarExpr("?0");157 u32 n = (u32)strlen(e->u.zToken);158 159 sqlite3ExprAssignVarNumber(&gParse, e, n);160 161 TEST_ASSERT_EQUAL_INT(prevNVar, gParse.nVar);162 TEST_ASSERT_EQUAL_INT(0, e->iColumn); /* Not assigned on error */163 TEST_ASSERT_NOT_NULL(gParse.zErrMsg);164 TEST_ASSERT_NOT_EQUAL(0, (int)(strstr(gParse.zErrMsg, "variable number must be between") != NULL));165 freeExpr(e);166 clearParseError(&gParse);167}168 169void test_sqlite3ExprAssignVarNumber_qnnn_over_limit_sets_error_and_no_change(void){170 int limit = sqlite3_limit(gDb, SQLITE_LIMIT_VARIABLE_NUMBER, -1);171 int prevNVar = gParse.nVar;172 173 char *dyn = sqlite3_mprintf("?%d", limit+1);174 TEST_ASSERT_NOT_NULL(dyn);175 Expr *e = newVarExpr(dyn); /* duplicate into db memory */176 sqlite3_free(dyn);177 178 u32 n = (u32)strlen(e->u.zToken);179 sqlite3ExprAssignVarNumber(&gParse, e, n);180 181 TEST_ASSERT_EQUAL_INT(prevNVar, gParse.nVar);182 TEST_ASSERT_EQUAL_INT(0, e->iColumn); /* Not assigned on early-return error */183 TEST_ASSERT_NOT_NULL(gParse.zErrMsg);184 TEST_ASSERT_NOT_EQUAL(0, (int)(strstr(gParse.zErrMsg, "variable number must be between") != NULL));185 freeExpr(e);186 clearParseError(&gParse);187}188 189void test_sqlite3ExprAssignVarNumber_too_many_sql_variables_sequential_qmark(void){190 int limit = sqlite3_limit(gDb, SQLITE_LIMIT_VARIABLE_NUMBER, -1);191 192 /* Force nVar to the limit, then assign one more "?" */193 gParse.nVar = limit;194 195 Expr *e = newVarExpr("?");196 u32 n = (u32)strlen(e->u.zToken);197 sqlite3ExprAssignVarNumber(&gParse, e, n);198 199 TEST_ASSERT_EQUAL_INT(limit+1, e->iColumn);200 TEST_ASSERT_EQUAL_INT(limit+1, gParse.nVar);201 TEST_ASSERT_NOT_NULL(gParse.zErrMsg);202 TEST_ASSERT_NOT_EQUAL(0, (int)(strstr(gParse.zErrMsg, "too many SQL variables") != NULL));203 204 freeExpr(e);205 clearParseError(&gParse);206}207 208/* Main */209int main(void){210 UNITY_BEGIN();211 RUN_TEST(test_sqlite3ExprAssignVarNumber_qmark_sequence);212 RUN_TEST(test_sqlite3ExprAssignVarNumber_qnnn_adds_and_mapping);213 RUN_TEST(test_sqlite3ExprAssignVarNumber_qnnn_lower_than_nVar_adds_missing_mapping);214 RUN_TEST(test_sqlite3ExprAssignVarNumber_named_reuse_and_prefix_sensitivity);215 RUN_TEST(test_sqlite3ExprAssignVarNumber_qnnn_invalid_zero_sets_error_and_no_change);216 RUN_TEST(test_sqlite3ExprAssignVarNumber_qnnn_over_limit_sets_error_and_no_change);217 RUN_TEST(test_sqlite3ExprAssignVarNumber_too_many_sql_variables_sequential_qmark);218 return UNITY_END();219}