AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <sqlite3.h>4#include <string.h>5 6/* Unity setup/teardown */7void setUp(void) {8 /* Setup code here, or leave empty */9}10void tearDown(void) {11 /* Cleanup code here, or leave empty */12}13 14/* Helper to build an Expr that is a constant integer via EP_IntValue */15static void makeIntExpr(Expr *p, int v){16 memset(p, 0, sizeof(*p));17 p->op = TK_INTEGER;18 p->flags = EP_IntValue;19 p->u.iValue = v;20}21 22/* Helper to build a non-integer Expr (e.g., NULL literal) */23static void makeNonIntExpr(Expr *p){24 memset(p, 0, sizeof(*p));25 p->op = TK_NULL;26}27 28/* Test: EP_IntValue path returns 1 and the correct value */29void test_sqlite3ExprIsInteger_EpIntValue_basic(void){30 Expr e;31 makeIntExpr(&e, 42);32 int out = -1;33 int rc = sqlite3ExprIsInteger(&e, &out, NULL);34 TEST_ASSERT_EQUAL_INT(1, rc);35 TEST_ASSERT_EQUAL_INT(42, out);36}37 38/* Test: EP_IntValue with max 31-bit positive value */39void test_sqlite3ExprIsInteger_EpIntValue_max31bit(void){40 Expr e;41 makeIntExpr(&e, 0x7fffffff);42 int out = 0;43 int rc = sqlite3ExprIsInteger(&e, &out, NULL);44 TEST_ASSERT_EQUAL_INT(1, rc);45 TEST_ASSERT_EQUAL_INT(0x7fffffff, out);46}47 48/* Test: TK_UPLUS passes through integer child */49void test_sqlite3ExprIsInteger_TK_UPLUS_integer_child(void){50 Expr child, e;51 makeIntExpr(&child, 7);52 memset(&e, 0, sizeof(e));53 e.op = TK_UPLUS;54 e.pLeft = &child;55 56 int out = -100;57 int rc = sqlite3ExprIsInteger(&e, &out, NULL);58 TEST_ASSERT_EQUAL_INT(1, rc);59 TEST_ASSERT_EQUAL_INT(7, out);60}61 62/* Test: TK_UPLUS with non-integer child returns 0 and leaves out unchanged */63void test_sqlite3ExprIsInteger_TK_UPLUS_non_integer_child(void){64 Expr child, e;65 makeNonIntExpr(&child);66 memset(&e, 0, sizeof(e));67 e.op = TK_UPLUS;68 e.pLeft = &child;69 70 int out = 7777;71 int rc = sqlite3ExprIsInteger(&e, &out, NULL);72 TEST_ASSERT_EQUAL_INT(0, rc);73 TEST_ASSERT_EQUAL_INT(7777, out); /* unchanged */74}75 76/* Test: TK_UMINUS negates integer child */77void test_sqlite3ExprIsInteger_TK_UMINUS_integer_child(void){78 Expr child, e;79 makeIntExpr(&child, 9);80 memset(&e, 0, sizeof(e));81 e.op = TK_UMINUS;82 e.pLeft = &child;83 84 int out = 0;85 int rc = sqlite3ExprIsInteger(&e, &out, NULL);86 TEST_ASSERT_EQUAL_INT(1, rc);87 TEST_ASSERT_EQUAL_INT(-9, out);88}89 90/* Test: TK_UMINUS with zero remains zero */91void test_sqlite3ExprIsInteger_TK_UMINUS_zero_child(void){92 Expr child, e;93 makeIntExpr(&child, 0);94 memset(&e, 0, sizeof(e));95 e.op = TK_UMINUS;96 e.pLeft = &child;97 98 int out = 1234;99 int rc = sqlite3ExprIsInteger(&e, &out, NULL);100 TEST_ASSERT_EQUAL_INT(1, rc);101 TEST_ASSERT_EQUAL_INT(0, out);102}103 104/* Test: TK_VARIABLE with NULL Parse -> returns 0 */105void test_sqlite3ExprIsInteger_TK_VARIABLE_null_parse(void){106 Expr e;107 memset(&e, 0, sizeof(e));108 e.op = TK_VARIABLE;109 e.iColumn = 1;110 111 int out = 2468;112 int rc = sqlite3ExprIsInteger(&e, &out, NULL);113 TEST_ASSERT_EQUAL_INT(0, rc);114 TEST_ASSERT_EQUAL_INT(2468, out); /* unchanged */115}116 117/* Test: TK_VARIABLE with Parse but pVdbe==NULL -> returns 0 via early-exit */118void test_sqlite3ExprIsInteger_TK_VARIABLE_pVdbe_null(void){119 sqlite3 *db = NULL;120 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));121 TEST_ASSERT_NOT_NULL(db);122 123 Parse p;124 memset(&p, 0, sizeof(p));125 p.db = (sqlite3*)db;126 p.pVdbe = NULL; /* triggers early-exit before flags check */127 128 Expr e;129 memset(&e, 0, sizeof(e));130 e.op = TK_VARIABLE;131 e.iColumn = 1;132 133 int out = -5555;134 int rc = sqlite3ExprIsInteger(&e, &out, &p);135 TEST_ASSERT_EQUAL_INT(0, rc);136 TEST_ASSERT_EQUAL_INT(-5555, out); /* unchanged */137 138 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_close(db));139}140 141/* Test: TK_VARIABLE with SQLITE_EnableQPSG set -> early-exit before Vdbe use */142void test_sqlite3ExprIsInteger_TK_VARIABLE_qpsg_enabled(void){143 sqlite3 *db = NULL;144 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));145 TEST_ASSERT_NOT_NULL(db);146 147 /* Set the internal flag to trigger the early-exit path */148 db->flags |= SQLITE_EnableQPSG;149 150 Parse p;151 memset(&p, 0, sizeof(p));152 p.db = (sqlite3*)db;153 /* Use a non-NULL dummy pointer to pass the pVdbe==0 check. It won't be dereferenced. */154 p.pVdbe = (Vdbe*)0x1;155 156 Expr e;157 memset(&e, 0, sizeof(e));158 e.op = TK_VARIABLE;159 e.iColumn = 2;160 161 int out = 9999;162 int rc = sqlite3ExprIsInteger(&e, &out, &p);163 TEST_ASSERT_EQUAL_INT(0, rc);164 TEST_ASSERT_EQUAL_INT(9999, out); /* unchanged */165 166 /* Clean up and also clear flag for safety */167 db->flags &= ~SQLITE_EnableQPSG;168 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_close(db));169}170 171/* Test: NULL Expr pointer -> returns 0 */172void test_sqlite3ExprIsInteger_null_expr_pointer(void){173 int out = 31415;174 int rc = sqlite3ExprIsInteger(NULL, &out, NULL);175 TEST_ASSERT_EQUAL_INT(0, rc);176 TEST_ASSERT_EQUAL_INT(31415, out); /* unchanged */177}178 179/* Test: Non-integer, default op -> returns 0 */180void test_sqlite3ExprIsInteger_non_integer_default_op(void){181 Expr e;182 makeNonIntExpr(&e);183 int out = -123;184 int rc = sqlite3ExprIsInteger(&e, &out, NULL);185 TEST_ASSERT_EQUAL_INT(0, rc);186 TEST_ASSERT_EQUAL_INT(-123, out); /* unchanged */187}188 189int main(void) {190 UNITY_BEGIN();191 RUN_TEST(test_sqlite3ExprIsInteger_EpIntValue_basic);192 RUN_TEST(test_sqlite3ExprIsInteger_EpIntValue_max31bit);193 RUN_TEST(test_sqlite3ExprIsInteger_TK_UPLUS_integer_child);194 RUN_TEST(test_sqlite3ExprIsInteger_TK_UPLUS_non_integer_child);195 RUN_TEST(test_sqlite3ExprIsInteger_TK_UMINUS_integer_child);196 RUN_TEST(test_sqlite3ExprIsInteger_TK_UMINUS_zero_child);197 RUN_TEST(test_sqlite3ExprIsInteger_TK_VARIABLE_null_parse);198 RUN_TEST(test_sqlite3ExprIsInteger_TK_VARIABLE_pVdbe_null);199 RUN_TEST(test_sqlite3ExprIsInteger_TK_VARIABLE_qpsg_enabled);200 RUN_TEST(test_sqlite3ExprIsInteger_null_expr_pointer);201 RUN_TEST(test_sqlite3ExprIsInteger_non_integer_default_op);202 return UNITY_END();203}