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-op */8}9void tearDown(void) {10 /* no-op */11}12 13/* Helper to zero an Expr quickly */14static void zeroExpr(Expr *p){15 memset(p, 0, sizeof(*p));16}17 18/* Test: Passing NULL should be a no-op (should not crash) */19void test_sqlite3ExprToRegister_null_pointer_ok(void) {20 sqlite3ExprToRegister(NULL, 5);21 /* If no crash, test passes */22 TEST_PASS(); /* Explicit for clarity */23}24 25/* Test: Non-register op is converted to TK_REGISTER with proper field updates */26void test_sqlite3ExprToRegister_converts_and_sets_register(void) {27 Expr e;28 zeroExpr(&e);29 e.op = TK_COLUMN; /* some non-register opcode */30 e.flags = EP_Skip | EP_Agg; /* include EP_Skip to verify it is cleared */31 e.iTable = 0;32 e.op2 = 0;33 34 int iReg = 7;35 sqlite3ExprToRegister(&e, iReg);36 37 TEST_ASSERT_EQUAL_INT(TK_REGISTER, e.op);38 TEST_ASSERT_EQUAL_INT(TK_COLUMN, e.op2); /* preserved original op */39 TEST_ASSERT_EQUAL_INT(iReg, e.iTable); /* register index copied */40 TEST_ASSERT_TRUE((e.flags & EP_Skip) == 0); /* EP_Skip cleared */41 TEST_ASSERT_TRUE((e.flags & EP_Agg) != 0); /* other flags preserved */42}43 44/* Test: When already TK_REGISTER, nothing should change */45void test_sqlite3ExprToRegister_idempotent_when_already_register(void) {46 Expr e;47 zeroExpr(&e);48 e.op = TK_REGISTER;49 e.iTable = 15;50 e.op2 = 321; /* sentinel to ensure unchanged */51 e.flags = EP_Skip | EP_Agg; /* ensure flags are untouched in this branch */52 53 sqlite3ExprToRegister(&e, 15);54 55 TEST_ASSERT_EQUAL_INT(TK_REGISTER, e.op);56 TEST_ASSERT_EQUAL_INT(15, e.iTable);57 TEST_ASSERT_EQUAL_INT(321, e.op2);58 TEST_ASSERT_TRUE((e.flags & EP_Skip) != 0); /* remains unchanged in this branch */59 TEST_ASSERT_TRUE((e.flags & EP_Agg) != 0);60}61 62/* Test: Function should act on the node returned by sqlite3ExprSkipCollateAndLikely()63 Create a TK_COLLATE wrapper whose left child is the actual expression.64 Only the child should be updated; wrapper remains unchanged. */65void test_sqlite3ExprToRegister_skips_COLLATE_wrapper_and_updates_inner(void) {66 Expr inner, wrapper;67 zeroExpr(&inner);68 zeroExpr(&wrapper);69 70 inner.op = TK_INTEGER; /* inner node to be transformed */71 inner.flags = EP_Skip | EP_Agg; /* EP_Skip should be cleared on inner */72 73 wrapper.op = TK_COLLATE; /* wrapper to be skipped */74 wrapper.pLeft = &inner;75 wrapper.iTable = 99; /* sentinel to ensure wrapper untouched */76 wrapper.op2 = 88;77 78 int iReg = 3;79 sqlite3ExprToRegister(&wrapper, iReg);80 81 /* Inner node updated */82 TEST_ASSERT_EQUAL_INT(TK_REGISTER, inner.op);83 TEST_ASSERT_EQUAL_INT(TK_INTEGER, inner.op2);84 TEST_ASSERT_EQUAL_INT(iReg, inner.iTable);85 TEST_ASSERT_TRUE((inner.flags & EP_Skip) == 0);86 TEST_ASSERT_TRUE((inner.flags & EP_Agg) != 0);87 88 /* Wrapper unchanged */89 TEST_ASSERT_EQUAL_INT(TK_COLLATE, wrapper.op);90 TEST_ASSERT_EQUAL_PTR(&inner, wrapper.pLeft);91 TEST_ASSERT_EQUAL_INT(99, wrapper.iTable);92 TEST_ASSERT_EQUAL_INT(88, wrapper.op2);93}94 95/* Test: Negative iReg values are stored as-is in iTable */96void test_sqlite3ExprToRegister_handles_negative_register_index(void) {97 Expr e;98 zeroExpr(&e);99 e.op = TK_INTEGER;100 e.flags = EP_Skip;101 102 int iReg = -2;103 sqlite3ExprToRegister(&e, iReg);104 105 TEST_ASSERT_EQUAL_INT(TK_REGISTER, e.op);106 TEST_ASSERT_EQUAL_INT(TK_INTEGER, e.op2);107 TEST_ASSERT_EQUAL_INT(iReg, e.iTable);108 TEST_ASSERT_TRUE((e.flags & EP_Skip) == 0);109}110 111/* Main runner */112int main(void) {113 UNITY_BEGIN();114 RUN_TEST(test_sqlite3ExprToRegister_null_pointer_ok);115 RUN_TEST(test_sqlite3ExprToRegister_converts_and_sets_register);116 RUN_TEST(test_sqlite3ExprToRegister_idempotent_when_already_register);117 RUN_TEST(test_sqlite3ExprToRegister_skips_COLLATE_wrapper_and_updates_inner);118 RUN_TEST(test_sqlite3ExprToRegister_handles_negative_register_index);119 return UNITY_END();120}