AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6/* The module provides a global wrapper for the static function under test */7extern void test_heightOfSelect(const Select *pSelect, int *pnHeight);8 9/* Unity fixtures */10void setUp(void) {11 /* no-op */12}13void tearDown(void) {14 /* no-op */15}16 17/* Helpers to construct minimal AST nodes for testing */18 19static Expr *newExprWithHeight(int h){20 Expr *p = (Expr*)calloc(1, sizeof(Expr));21 if( p ){22 p->nHeight = (u16)h;23 }24 return p;25}26 27static ExprList *newExprListFromHeights(const int *heights, int n){28 ExprList *pList = (ExprList*)calloc(1, sizeof(ExprList));29 if( !pList ) return NULL;30 pList->nExpr = n;31 if( n>0 ){32 /* ExprList_item is declared in sqliteInt.h */33 struct ExprList_item *a =34 (struct ExprList_item*)calloc((size_t)n, sizeof(struct ExprList_item));35 if( !a ){36 free(pList);37 return NULL;38 }39 pList->a = a;40 for(int i=0; i<n; i++){41 if( heights ){42 a[i].pExpr = newExprWithHeight(heights[i]);43 }else{44 a[i].pExpr = NULL;45 }46 }47 }else{48 pList->a = NULL;49 }50 return pList;51}52 53static void freeExpr(Expr *p){54 free(p);55}56 57static void freeExprList(ExprList *p){58 if( !p ) return;59 if( p->a ){60 for(int i=0; i<p->nExpr; i++){61 if( p->a[i].pExpr ) freeExpr(p->a[i].pExpr);62 }63 free(p->a);64 }65 free(p);66}67 68static Select *newSelect(void){69 Select *p = (Select*)calloc(1, sizeof(Select));70 return p;71}72 73static void freeSelectDeep(Select *p, int freePrior){74 if( !p ) return;75 if( p->pWhere ) freeExpr(p->pWhere);76 if( p->pHaving ) freeExpr(p->pHaving);77 if( p->pLimit ) freeExpr(p->pLimit);78 if( p->pEList ) freeExprList(p->pEList);79 if( p->pGroupBy ) freeExprList(p->pGroupBy);80 if( p->pOrderBy ) freeExprList(p->pOrderBy);81 if( freePrior && p->pPrior ){82 freeSelectDeep(p->pPrior, 1);83 }84 free(p);85}86 87/* Tests */88 89void test_heightOfSelect_NULL_select_does_not_change_height(void){90 int h = 5;91 test_heightOfSelect(NULL, &h);92 TEST_ASSERT_EQUAL_INT(5, h);93}94 95void test_heightOfSelect_single_select_uses_max_of_all_sources(void){96 Select *p = newSelect();97 TEST_ASSERT_NOT_NULL(p);98 99 /* Single expressions */100 p->pWhere = newExprWithHeight(10);101 p->pHaving = newExprWithHeight(4);102 p->pLimit = newExprWithHeight(7);103 104 /* Expression lists */105 const int eHeights[] = {3, 8};106 const int gHeights[] = {2, 1, 9};107 const int oHeights[] = {6};108 p->pEList = newExprListFromHeights(eHeights, (int)(sizeof(eHeights)/sizeof(eHeights[0])));109 p->pGroupBy = newExprListFromHeights(gHeights, (int)(sizeof(gHeights)/sizeof(gHeights[0])));110 p->pOrderBy = newExprListFromHeights(oHeights, (int)(sizeof(oHeights)/sizeof(oHeights[0])));111 112 int h = 0;113 test_heightOfSelect(p, &h);114 TEST_ASSERT_EQUAL_INT(10, h);115 116 freeSelectDeep(p, 0);117}118 119void test_heightOfSelect_does_not_lower_existing_pnHeight(void){120 Select *p = newSelect();121 TEST_ASSERT_NOT_NULL(p);122 123 p->pWhere = newExprWithHeight(3);124 const int eHeights[] = {2};125 p->pEList = newExprListFromHeights(eHeights, 1);126 127 int h = 20; /* already above any expression height */128 test_heightOfSelect(p, &h);129 TEST_ASSERT_EQUAL_INT(20, h);130 131 freeSelectDeep(p, 0);132}133 134void test_heightOfSelect_prior_chain_considered(void){135 /* Build S1 <-prior- S2. Pass S2 to the function. */136 Select *s1 = newSelect();137 Select *s2 = newSelect();138 TEST_ASSERT_NOT_NULL(s1);139 TEST_ASSERT_NOT_NULL(s2);140 141 /* s1 has a large height in pHaving */142 s1->pHaving = newExprWithHeight(30);143 /* s2 has smaller max */144 s2->pWhere = newExprWithHeight(12);145 const int listH[] = {5, 11};146 s2->pEList = newExprListFromHeights(listH, 2);147 148 s2->pPrior = s1;149 150 int h = 0;151 test_heightOfSelect(s2, &h);152 TEST_ASSERT_EQUAL_INT(30, h);153 154 /* free entire chain */155 freeSelectDeep(s2, 1);156}157 158void test_heightOfSelect_handles_missing_and_empty_lists(void){159 Select *p = newSelect();160 TEST_ASSERT_NOT_NULL(p);161 162 /* Only pOrderBy present; pEList and pGroupBy missing */163 const int oHeights[] = {4};164 p->pOrderBy = newExprListFromHeights(oHeights, 1);165 166 /* Add an empty list for pEList and a NULL-entry list for GroupBy */167 p->pEList = newExprListFromHeights(NULL, 0); /* empty list */168 /* GroupBy with 3 items but all NULL pExpr entries */169 ExprList *g = newExprListFromHeights(NULL, 3);170 /* explicitly ensure NULL pExprs (already NULL from calloc) */171 p->pGroupBy = g;172 173 int h = 1;174 test_heightOfSelect(p, &h);175 /* Only pOrderBy has a non-NULL expr with height 4; so max should be 4 */176 TEST_ASSERT_EQUAL_INT(4, h);177 178 freeSelectDeep(p, 0);179}180 181void test_heightOfSelect_exprlist_with_null_entries_ignored(void){182 Select *p = newSelect();183 TEST_ASSERT_NOT_NULL(p);184 185 /* Build an ExprList with mixed NULL and non-NULL entries */186 ExprList *list = (ExprList*)calloc(1, sizeof(ExprList));187 TEST_ASSERT_NOT_NULL(list);188 list->nExpr = 4;189 list->a = (struct ExprList_item*)calloc(4, sizeof(struct ExprList_item));190 TEST_ASSERT_NOT_NULL(list->a);191 list->a[0].pExpr = NULL;192 list->a[1].pExpr = newExprWithHeight(2);193 list->a[2].pExpr = NULL;194 list->a[3].pExpr = newExprWithHeight(9);195 p->pEList = list;196 197 int h = 3; /* start below the max non-NULL (9) but above 2 */198 test_heightOfSelect(p, &h);199 TEST_ASSERT_EQUAL_INT(9, h);200 201 freeSelectDeep(p, 0);202}203 204/* Main */205int main(void){206 UNITY_BEGIN();207 RUN_TEST(test_heightOfSelect_NULL_select_does_not_change_height);208 RUN_TEST(test_heightOfSelect_single_select_uses_max_of_all_sources);209 RUN_TEST(test_heightOfSelect_does_not_lower_existing_pnHeight);210 RUN_TEST(test_heightOfSelect_prior_chain_considered);211 RUN_TEST(test_heightOfSelect_handles_missing_and_empty_lists);212 RUN_TEST(test_heightOfSelect_exprlist_with_null_entries_ignored);213 return UNITY_END();214}