sqlite / tests /tests_alter_sqlite3RenameExprUnmap.c
AryaWu's picture
Upload folder using huggingface_hub
7510827 verified
#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();
}