File size: 4,073 Bytes
7510827 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
#include "sqliteInt.h"
#include "unity.h"
#include <string.h>
/* Global database handle for allocations */
static sqlite3 *gDb = NULL;
static Expr* make_id_expr(Parse *pParse, const char *zId){
Token t;
t.z = (char*)zId;
t.n = (int)strlen(zId);
return sqlite3ExprAlloc(pParse->db, TK_ID, &t, 0);
}
static Expr* make_int_expr(Parse *pParse, const char *zNum){
Token t;
t.z = (char*)zNum;
t.n = (int)strlen(zNum);
return sqlite3ExprAlloc(pParse->db, TK_INTEGER, &t, 0);
}
void setUp(void) {
if (!gDb) {
int rc = sqlite3_open(":memory:", &gDb);
TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "Failed to open in-memory DB");
}
}
void tearDown(void) {
if (gDb) {
int rc = sqlite3_close(gDb);
TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "Failed to close in-memory DB");
gDb = NULL;
}
}
/* Helper to initialize a Parse object */
static void initParse(Parse *pParse){
memset(pParse, 0, sizeof(Parse));
pParse->db = gDb;
/* Set a non-UNMAP mode to verify restoration */
pParse->eParseMode = PARSE_MODE_RENAME;
}
/* Test: NULL expression must be safe and must restore eParseMode */
void test_sqlite3RenameExprUnmap_restores_mode_when_expr_null(void){
Parse sParse;
initParse(&sParse);
u8 orig = sParse.eParseMode;
sqlite3RenameExprUnmap(&sParse, NULL);
TEST_ASSERT_EQUAL_UINT8(orig, sParse.eParseMode);
TEST_ASSERT_EQUAL_INT(0, sParse.nErr);
}
/* Test: Simple literal expression, mode restored after call */
void test_sqlite3RenameExprUnmap_restores_mode_when_expr_simple(void){
Parse sParse;
initParse(&sParse);
Expr *pInt = make_int_expr(&sParse, "123");
TEST_ASSERT_NOT_NULL(pInt);
u8 orig = sParse.eParseMode;
sqlite3RenameExprUnmap(&sParse, pInt);
TEST_ASSERT_EQUAL_UINT8(orig, sParse.eParseMode);
TEST_ASSERT_EQUAL_INT(0, sParse.nErr);
sqlite3ExprDelete(sParse.db, pInt);
}
/* Test: Expression tree should not be modified by Unmap (structure intact) */
void test_sqlite3RenameExprUnmap_does_not_modify_tree(void){
Parse sParse;
initParse(&sParse);
Expr *pA = make_id_expr(&sParse, "a");
Expr *pB = make_id_expr(&sParse, "b");
TEST_ASSERT_NOT_NULL(pA);
TEST_ASSERT_NOT_NULL(pB);
Expr *pPlus = sqlite3PExpr(&sParse, TK_PLUS, pA, pB);
TEST_ASSERT_NOT_NULL(pPlus);
Expr *pLeftBefore = pPlus->pLeft;
Expr *pRightBefore = pPlus->pRight;
sqlite3RenameExprUnmap(&sParse, pPlus);
/* Validate the expression shape is unchanged */
TEST_ASSERT_EQUAL_PTR(pLeftBefore, pPlus->pLeft);
TEST_ASSERT_EQUAL_PTR(pRightBefore, pPlus->pRight);
TEST_ASSERT_EQUAL_INT(0, sParse.nErr);
sqlite3ExprDelete(sParse.db, pPlus); /* deletes pA and pB as well */
}
/* Test: Nested expression trees traverse without errors and restore mode */
void test_sqlite3RenameExprUnmap_handles_nested_tree_no_side_effects(void){
Parse sParse;
initParse(&sParse);
/* Build (a + b) * 3 */
Expr *pA = make_id_expr(&sParse, "a");
Expr *pB = make_id_expr(&sParse, "b");
Expr *pPlus = sqlite3PExpr(&sParse, TK_PLUS, pA, pB);
TEST_ASSERT_NOT_NULL(pA);
TEST_ASSERT_NOT_NULL(pB);
TEST_ASSERT_NOT_NULL(pPlus);
Expr *pThree = make_int_expr(&sParse, "3");
TEST_ASSERT_NOT_NULL(pThree);
/* Multiplication operator is TK_STAR in SQLite */
Expr *pMul = sqlite3PExpr(&sParse, TK_STAR, pPlus, pThree);
TEST_ASSERT_NOT_NULL(pMul);
u8 orig = sParse.eParseMode;
sqlite3RenameExprUnmap(&sParse, pMul);
/* No parse errors introduced and mode restored */
TEST_ASSERT_EQUAL_UINT8(orig, sParse.eParseMode);
TEST_ASSERT_EQUAL_INT(0, sParse.nErr);
/* Tree is intact */
TEST_ASSERT_EQUAL_PTR(pPlus, pMul->pLeft);
TEST_ASSERT_EQUAL_PTR(pThree, pMul->pRight);
sqlite3ExprDelete(sParse.db, pMul); /* deletes entire tree */
}
int main(void) {
UNITY_BEGIN();
RUN_TEST(test_sqlite3RenameExprUnmap_restores_mode_when_expr_null);
RUN_TEST(test_sqlite3RenameExprUnmap_restores_mode_when_expr_simple);
RUN_TEST(test_sqlite3RenameExprUnmap_does_not_modify_tree);
RUN_TEST(test_sqlite3RenameExprUnmap_handles_nested_tree_no_side_effects);
return UNITY_END();
} |