AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Unity setUp/tearDown */7void setUp(void) {8 /* No global setup needed */9}10void tearDown(void) {11 /* No global teardown needed */12}13 14/* Helper: open an in-memory SQLite DB and initialize a Parse object */15static void open_db_and_parse(sqlite3 **pDb, Parse *pParse){16 memset(pParse, 0, sizeof(Parse));17 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", pDb));18 pParse->db = *pDb;19}20 21/* Helper: create a simple leaf Expr (TK_NULL) */22static Expr* make_leaf_expr(sqlite3 *db){23 Expr *p = (Expr*)sqlite3DbMallocZero(db, sizeof(Expr));24 TEST_ASSERT_NOT_NULL(p);25 p->op = TK_NULL;26 return p;27}28 29/* Helper: create a deep left-linked Expr chain of given depth (>=1) */30static Expr* make_deep_left_chain(sqlite3 *db, int depth){31 TEST_ASSERT_TRUE(depth >= 1);32 Expr *root = make_leaf_expr(db);33 Expr *cur = root;34 for(int i=1; i<depth; i++){35 Expr *n = (Expr*)sqlite3DbMallocZero(db, sizeof(Expr));36 TEST_ASSERT_NOT_NULL(n);37 n->op = TK_NULL;38 n->pLeft = cur;39 cur = n;40 }41 return cur; /* return the top-most node */42}43 44/* Test 1: With non-NULL pExpr and NULL pSelect, flags set and height computed */45static void test_sqlite3PExprAddSelect_sets_flags_with_null_select(void){46 sqlite3 *db = NULL;47 Parse parse;48 open_db_and_parse(&db, &parse);49 50 Expr *pExpr = make_leaf_expr(db);51 pExpr->nHeight = 0;52 53 sqlite3PExprAddSelect(&parse, pExpr, NULL);54 55 TEST_ASSERT_NULL(pExpr->x.pSelect);56 TEST_ASSERT_TRUE( (pExpr->flags & EP_xIsSelect) != 0 );57 TEST_ASSERT_TRUE( (pExpr->flags & EP_Subquery) != 0 );58 TEST_ASSERT_GREATER_OR_EQUAL_INT(1, pExpr->nHeight);59 TEST_ASSERT_EQUAL_INT(0, parse.nErr);60 61 sqlite3ExprDelete(db, pExpr);62 sqlite3_close(db);63}64 65/* Test 2: With non-NULL pExpr and non-NULL pSelect, pointer assigned and flags set */66static void test_sqlite3PExprAddSelect_assigns_nonnull_select(void){67 sqlite3 *db = NULL;68 Parse parse;69 open_db_and_parse(&db, &parse);70 71 Expr *pExpr = make_leaf_expr(db);72 Select *pSel = (Select*)sqlite3DbMallocZero(db, sizeof(Select));73 TEST_ASSERT_NOT_NULL(pSel);74 75 sqlite3PExprAddSelect(&parse, pExpr, pSel);76 77 TEST_ASSERT_EQUAL_PTR(pSel, pExpr->x.pSelect);78 TEST_ASSERT_TRUE( (pExpr->flags & EP_xIsSelect) != 0 );79 TEST_ASSERT_TRUE( (pExpr->flags & EP_Subquery) != 0 );80 TEST_ASSERT_GREATER_OR_EQUAL_INT(1, pExpr->nHeight);81 TEST_ASSERT_EQUAL_INT(0, parse.nErr);82 83 /* Freeing the expression should also delete attached Select */84 sqlite3ExprDelete(db, pExpr);85 sqlite3_close(db);86}87 88/* Test 3: If parse.nErr is already non-zero, height is not recomputed */89static void test_sqlite3PExprAddSelect_does_not_set_height_if_parse_has_error(void){90 sqlite3 *db = NULL;91 Parse parse;92 open_db_and_parse(&db, &parse);93 94 Expr *pExpr = make_leaf_expr(db);95 pExpr->nHeight = 0;96 Select *pSel = (Select*)sqlite3DbMallocZero(db, sizeof(Select));97 TEST_ASSERT_NOT_NULL(pSel);98 99 parse.nErr = 1; /* Simulate prior error */100 101 sqlite3PExprAddSelect(&parse, pExpr, pSel);102 103 TEST_ASSERT_EQUAL_PTR(pSel, pExpr->x.pSelect);104 TEST_ASSERT_TRUE( (pExpr->flags & EP_xIsSelect) != 0 );105 TEST_ASSERT_TRUE( (pExpr->flags & EP_Subquery) != 0 );106 /* Since parse.nErr was non-zero, sqlite3ExprSetHeightAndFlags should not update nHeight */107 TEST_ASSERT_EQUAL_INT(0, pExpr->nHeight);108 109 /* Clean up */110 sqlite3ExprDelete(db, pExpr);111 sqlite3_close(db);112}113 114/* Test 4: Deep expression exceeds SQLITE_LIMIT_EXPR_DEPTH, causing an error */115static void test_sqlite3PExprAddSelect_enforces_expr_depth_limit(void){116 sqlite3 *db = NULL;117 Parse parse;118 open_db_and_parse(&db, &parse);119 120 /* Set a low expression depth limit */121 int old = sqlite3_limit(db, SQLITE_LIMIT_EXPR_DEPTH, 5);122 (void)old;123 124 /* Create a chain deeper than the limit */125 Expr *pExpr = make_deep_left_chain(db, 10);126 /* Use NULL Select; flags should still be set */127 sqlite3PExprAddSelect(&parse, pExpr, NULL);128 129 TEST_ASSERT_TRUE( (pExpr->flags & EP_xIsSelect) != 0 );130 TEST_ASSERT_TRUE( (pExpr->flags & EP_Subquery) != 0 );131 TEST_ASSERT_TRUE(parse.nErr > 0);132 133 sqlite3ExprDelete(db, pExpr);134 sqlite3_close(db);135}136 137/* Test 5: NULL pExpr path with mallocFailed set; should not crash and should handle NULL pSelect */138static void test_sqlite3PExprAddSelect_handles_null_expr_with_malloc_failed(void){139 sqlite3 *db = NULL;140 Parse parse;141 open_db_and_parse(&db, &parse);142 143 /* Simulate OOM failure that led to NULL pExpr */144 parse.db->mallocFailed = 1;145 146 /* pSelect is NULL; function should return without issues */147 sqlite3PExprAddSelect(&parse, NULL, NULL);148 149 /* Ensure no additional parse errors introduced */150 TEST_ASSERT_EQUAL_INT(0, parse.nErr);151 152 sqlite3_close(db);153}154 155int main(void) {156 UNITY_BEGIN();157 RUN_TEST(test_sqlite3PExprAddSelect_sets_flags_with_null_select);158 RUN_TEST(test_sqlite3PExprAddSelect_assigns_nonnull_select);159 RUN_TEST(test_sqlite3PExprAddSelect_does_not_set_height_if_parse_has_error);160 RUN_TEST(test_sqlite3PExprAddSelect_enforces_expr_depth_limit);161 RUN_TEST(test_sqlite3PExprAddSelect_handles_null_expr_with_malloc_failed);162 return UNITY_END();163}