AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6/* Wrapper provided in the module for the static function */7extern void test_exprSetHeight(Expr *p);8 9/* Helper to allocate and zero memory for an Expr */10static Expr* allocExpr(void){11 Expr *p = (Expr*)sqlite3_malloc(sizeof(Expr));12 TEST_ASSERT_NOT_NULL(p);13 memset(p, 0, sizeof(Expr));14 return p;15}16 17/* Helper to allocate and zero memory for a Select */18static Select* allocSelect(void){19 Select *p = (Select*)sqlite3_malloc(sizeof(Select));20 TEST_ASSERT_NOT_NULL(p);21 memset(p, 0, sizeof(Select));22 return p;23}24 25/* Helper to allocate an ExprList with n items */26static ExprList* allocExprList(int n){27 ExprList *pList = (ExprList*)sqlite3_malloc(sizeof(ExprList));28 TEST_ASSERT_NOT_NULL(pList);29 memset(pList, 0, sizeof(ExprList));30 pList->nExpr = n;31 if( n>0 ){32 pList->a = (ExprList_item*)sqlite3_malloc(sizeof(pList->a[0]) * n);33 TEST_ASSERT_NOT_NULL(pList->a);34 memset(pList->a, 0, sizeof(pList->a[0]) * n);35 }36 return pList;37}38 39/* Unity required functions */40void setUp(void) {41 /* No global setup needed */42}43void tearDown(void) {44 /* No global teardown needed */45}46 47/* Test 1: Leaf expression should get height 1 */48void test_exprSetHeight_leaf_sets_to_1(void){49 Expr *p = allocExpr();50 /* Ensure it's a leaf: no children, no list/select */51 test_exprSetHeight(p);52 TEST_ASSERT_EQUAL_INT(1, p->nHeight);53 sqlite3_free(p);54}55 56/* Test 2: Height uses left child */57void test_exprSetHeight_uses_left_child_height(void){58 Expr *left = allocExpr();59 left->nHeight = 2; /* arbitrary preset height */60 61 Expr *p = allocExpr();62 p->pLeft = left;63 64 test_exprSetHeight(p);65 TEST_ASSERT_EQUAL_INT(3, p->nHeight); /* max(left=2) + 1 */66 67 sqlite3_free(left);68 sqlite3_free(p);69}70 71/* Test 3: Height uses max of left and right children */72void test_exprSetHeight_uses_max_of_left_and_right(void){73 Expr *left = allocExpr(); left->nHeight = 1;74 Expr *right = allocExpr(); right->nHeight = 7;75 76 Expr *p = allocExpr();77 p->pLeft = left;78 p->pRight = right;79 80 test_exprSetHeight(p);81 TEST_ASSERT_EQUAL_INT(8, p->nHeight); /* max(1,7)+1 */82 83 sqlite3_free(left);84 sqlite3_free(right);85 sqlite3_free(p);86}87 88/* Test 4: x.pList contributes to height and EP_Propagate flags are propagated */89void test_exprSetHeight_list_height_and_flag_propagation(void){90 /* Create list with two expressions: heights 4 and 2 */91 Expr *e1 = allocExpr(); e1->nHeight = 4;92 Expr *e2 = allocExpr(); e2->nHeight = 2;93 /* Make sure list flags include EP_Propagate bits so we can check propagation */94 e1->flags = EP_Propagate | 0x80000000u; /* include extra bit to ensure masking */95 e2->flags = 0; /* only e1 contributes */96 97 ExprList *pList = allocExprList(2);98 pList->a[0].pExpr = e1;99 pList->a[1].pExpr = e2;100 101 Expr *p = allocExpr();102 /* Also give a left child to verify max(left, list) is used */103 Expr *left = allocExpr(); left->nHeight = 3;104 p->pLeft = left;105 106 p->x.pList = pList;107 /* Ensure we are NOT treating x as Select */108 p->flags = 0;109 110 test_exprSetHeight(p);111 112 /* Height should be max(left=3, list=4) + 1 = 5 */113 TEST_ASSERT_EQUAL_INT(5, p->nHeight);114 115 /* EP_Propagate bits should be ORed into p->flags */116 TEST_ASSERT_BITS_HIGH_MASK(EP_Propagate, EP_Propagate, p->flags);117 118 /* Cleanup */119 sqlite3_free(left);120 sqlite3_free(e1);121 sqlite3_free(e2);122 sqlite3_free(pList->a);123 sqlite3_free(pList);124 sqlite3_free(p);125}126 127/* Test 5: x.pSelect contributes to height when EP_xIsSelect is set */128void test_exprSetHeight_select_height_used_when_flag_set(void){129 /* Create select with a pWhere expression of height 9 */130 Expr *whereExpr = allocExpr(); whereExpr->nHeight = 9;131 Select *pSel = allocSelect();132 pSel->pWhere = whereExpr;133 134 Expr *p = allocExpr();135 p->x.pSelect = pSel;136 p->flags = EP_xIsSelect; /* Ensure ExprUseXSelect(p) is true */137 138 test_exprSetHeight(p);139 140 /* Height should be 9 + 1 = 10 */141 TEST_ASSERT_EQUAL_INT(10, p->nHeight);142 143 sqlite3_free(whereExpr);144 sqlite3_free(pSel);145 sqlite3_free(p);146}147 148/* Test 6: Select height competes with children; max is used */149void test_exprSetHeight_select_competes_with_children(void){150 /* Select contributes height 5 (so nHeight=6 if alone) */151 Expr *limitExpr = allocExpr(); limitExpr->nHeight = 5;152 Select *pSel = allocSelect();153 pSel->pLimit = limitExpr;154 155 /* Left child has height 12 -> should dominate, yielding 13 */156 Expr *left = allocExpr(); left->nHeight = 12;157 158 Expr *p = allocExpr();159 p->pLeft = left;160 p->x.pSelect = pSel;161 p->flags = EP_xIsSelect;162 163 test_exprSetHeight(p);164 165 TEST_ASSERT_EQUAL_INT(13, p->nHeight);166 167 sqlite3_free(limitExpr);168 sqlite3_free(pSel);169 sqlite3_free(left);170 sqlite3_free(p);171}172 173int main(void){174 UNITY_BEGIN();175 RUN_TEST(test_exprSetHeight_leaf_sets_to_1);176 RUN_TEST(test_exprSetHeight_uses_left_child_height);177 RUN_TEST(test_exprSetHeight_uses_max_of_left_and_right);178 RUN_TEST(test_exprSetHeight_list_height_and_flag_propagation);179 RUN_TEST(test_exprSetHeight_select_height_used_when_flag_set);180 RUN_TEST(test_exprSetHeight_select_competes_with_children);181 return UNITY_END();182}