AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Prototypes to silence potential C warnings if needed */7/* The target function is declared in the module under test */8void sqlite3ExprListSetSpan(Parse *pParse, ExprList *pList, const char *zStart, const char *zEnd);9 10static ExprList* createExprList(sqlite3 *db, int n){11 ExprList *p = (ExprList*)sqlite3DbMallocZero(db, sizeof(ExprList));12 TEST_ASSERT_NOT_NULL_MESSAGE(p, "Failed to allocate ExprList");13 p->nExpr = n;14 p->a = (struct ExprList_item*)sqlite3DbMallocZero(db, sizeof(struct ExprList_item)*n);15 TEST_ASSERT_NOT_NULL_MESSAGE(p->a, "Failed to allocate ExprList_item array");16 return p;17}18 19void setUp(void) {20 /* No-op setup */21}22 23void tearDown(void) {24 /* No-op teardown */25}26 27static void freeExprList(sqlite3 *db, ExprList *pList){28 if( pList ){29 if( pList->a ){30 for( int i=0; i<pList->nExpr; i++ ){31 if( pList->a[i].zEName ){32 sqlite3DbFree(db, pList->a[i].zEName);33 pList->a[i].zEName = 0;34 }35 }36 sqlite3DbFree(db, pList->a);37 pList->a = 0;38 }39 sqlite3DbFree(db, pList);40 }41}42 43/* Test: sets span on last item and sets flag, does not affect other items */44void test_sqlite3ExprListSetSpan_sets_span_on_last_item_and_flag(void){45 sqlite3 *db = 0;46 int rc = sqlite3_open(":memory:", &db);47 TEST_ASSERT_EQUAL_INT(0, rc);48 TEST_ASSERT_NOT_NULL(db);49 50 Parse parse;51 memset(&parse, 0, sizeof(parse));52 parse.db = db;53 54 ExprList *pList = createExprList(db, 2);55 /* First item has an existing name that should remain unchanged */56 pList->a[0].zEName = sqlite3DbStrDup(db, "keep");57 TEST_ASSERT_NOT_NULL(pList->a[0].zEName);58 pList->a[0].fg.eEName = 0;59 60 /* Last item starts with no name */61 pList->a[1].zEName = 0;62 pList->a[1].fg.eEName = 0;63 64 char buf[] = "xyzabcdefg"; /* indices: 0..9, letters start at 3 */65 const char *zStart = &buf[3]; /* 'a' */66 const char *zEnd = &buf[6]; /* points just past 'c'; span "abc" */67 68 sqlite3ExprListSetSpan(&parse, pList, zStart, zEnd);69 70 struct ExprList_item *pLast = &pList->a[pList->nExpr-1];71 TEST_ASSERT_NOT_NULL(pLast->zEName);72 TEST_ASSERT_EQUAL_STRING_LEN("abc", pLast->zEName, 3);73 TEST_ASSERT_EQUAL_CHAR('\0', pLast->zEName[3]);74 TEST_ASSERT_EQUAL_UINT8(ENAME_SPAN, pLast->fg.eEName);75 76 /* Ensure first item unchanged */77 TEST_ASSERT_NOT_NULL(pList->a[0].zEName);78 TEST_ASSERT_EQUAL_STRING("keep", pList->a[0].zEName);79 TEST_ASSERT_EQUAL_UINT8(0, pList->a[0].fg.eEName);80 81 freeExprList(db, pList);82 sqlite3_close(db);83}84 85/* Test: does not overwrite existing zEName and leaves eEName unchanged */86void test_sqlite3ExprListSetSpan_does_not_overwrite_existing_zEName(void){87 sqlite3 *db = 0;88 int rc = sqlite3_open(":memory:", &db);89 TEST_ASSERT_EQUAL_INT(0, rc);90 TEST_ASSERT_NOT_NULL(db);91 92 Parse parse;93 memset(&parse, 0, sizeof(parse));94 parse.db = db;95 96 ExprList *pList = createExprList(db, 1);97 pList->a[0].zEName = sqlite3DbStrDup(db, "already");98 TEST_ASSERT_NOT_NULL(pList->a[0].zEName);99 /* Pre-set some eEName value (0) and ensure it remains after call */100 pList->a[0].fg.eEName = 0;101 102 const char text[] = "hello world";103 const char *zStart = &text[0];104 const char *zEnd = &text[5]; /* "hello" */105 106 char *oldPtr = pList->a[0].zEName;107 unsigned char oldFlag = pList->a[0].fg.eEName;108 109 sqlite3ExprListSetSpan(&parse, pList, zStart, zEnd);110 111 TEST_ASSERT_EQUAL_PTR(oldPtr, pList->a[0].zEName);112 TEST_ASSERT_EQUAL_STRING("already", pList->a[0].zEName);113 TEST_ASSERT_EQUAL_UINT8(oldFlag, pList->a[0].fg.eEName);114 115 freeExprList(db, pList);116 sqlite3_close(db);117}118 119/* Test: pList == NULL is tolerated if db->mallocFailed is non-zero (per assert) */120void test_sqlite3ExprListSetSpan_handles_null_list_when_mallocFailed(void){121 sqlite3 *db = 0;122 int rc = sqlite3_open(":memory:", &db);123 TEST_ASSERT_EQUAL_INT(0, rc);124 TEST_ASSERT_NOT_NULL(db);125 126 Parse parse;127 memset(&parse, 0, sizeof(parse));128 parse.db = db;129 130 /* Satisfy the assert: pList==NULL is allowed only if mallocFailed!=0 */131 db->mallocFailed = 1;132 133 const char s[] = "span";134 sqlite3ExprListSetSpan(&parse, NULL, &s[0], &s[2]);135 136 /* Ensure mallocFailed state unchanged */137 TEST_ASSERT_EQUAL_INT(1, db->mallocFailed);138 139 /* Clear flag to avoid affecting other tests before closing */140 db->mallocFailed = 0;141 142 sqlite3_close(db);143}144 145/* Test: boundary cases for span duplication (empty, single-char, full) */146void test_sqlite3ExprListSetSpan_span_boundaries(void){147 sqlite3 *db = 0;148 int rc = sqlite3_open(":memory:", &db);149 TEST_ASSERT_EQUAL_INT(0, rc);150 TEST_ASSERT_NOT_NULL(db);151 152 Parse parse;153 memset(&parse, 0, sizeof(parse));154 parse.db = db;155 156 const char s[] = "ABCDE";157 158 /* Empty span */159 {160 ExprList *pList = createExprList(db, 1);161 sqlite3ExprListSetSpan(&parse, pList, &s[2], &s[2]); /* empty */162 TEST_ASSERT_NOT_NULL(pList->a[0].zEName);163 TEST_ASSERT_EQUAL_INT(0, (int)strlen(pList->a[0].zEName));164 TEST_ASSERT_EQUAL_UINT8(ENAME_SPAN, pList->a[0].fg.eEName);165 freeExprList(db, pList);166 }167 168 /* Single character span */169 {170 ExprList *pList = createExprList(db, 1);171 sqlite3ExprListSetSpan(&parse, pList, &s[4], &s[5]); /* "E" */172 TEST_ASSERT_NOT_NULL(pList->a[0].zEName);173 TEST_ASSERT_EQUAL_STRING("E", pList->a[0].zEName);174 TEST_ASSERT_EQUAL_UINT8(ENAME_SPAN, pList->a[0].fg.eEName);175 freeExprList(db, pList);176 }177 178 /* Full string span */179 {180 ExprList *pList = createExprList(db, 1);181 sqlite3ExprListSetSpan(&parse, pList, &s[0], &s[strlen(s)]); /* "ABCDE" */182 TEST_ASSERT_NOT_NULL(pList->a[0].zEName);183 TEST_ASSERT_EQUAL_STRING("ABCDE", pList->a[0].zEName);184 TEST_ASSERT_EQUAL_UINT8(ENAME_SPAN, pList->a[0].fg.eEName);185 freeExprList(db, pList);186 }187 188 sqlite3_close(db);189}190 191/* Test: repeat call does not replace already-set zEName (pointer stable) */192void test_sqlite3ExprListSetSpan_second_call_no_overwrite(void){193 sqlite3 *db = 0;194 int rc = sqlite3_open(":memory:", &db);195 TEST_ASSERT_EQUAL_INT(0, rc);196 TEST_ASSERT_NOT_NULL(db);197 198 Parse parse;199 memset(&parse, 0, sizeof(parse));200 parse.db = db;201 202 const char s[] = "0123456789";203 ExprList *pList = createExprList(db, 1);204 205 /* First call sets "1234" */206 sqlite3ExprListSetSpan(&parse, pList, &s[1], &s[5]);207 TEST_ASSERT_NOT_NULL(pList->a[0].zEName);208 TEST_ASSERT_EQUAL_STRING_LEN("1234", pList->a[0].zEName, 4);209 char *firstPtr = pList->a[0].zEName;210 211 /* Second call attempted with different span; should not change */212 sqlite3ExprListSetSpan(&parse, pList, &s[2], &s[7]);213 214 TEST_ASSERT_EQUAL_PTR(firstPtr, pList->a[0].zEName);215 TEST_ASSERT_EQUAL_STRING_LEN("1234", pList->a[0].zEName, 4);216 TEST_ASSERT_EQUAL_UINT8(ENAME_SPAN, pList->a[0].fg.eEName);217 218 freeExprList(db, pList);219 sqlite3_close(db);220}221 222int main(void){223 UNITY_BEGIN();224 RUN_TEST(test_sqlite3ExprListSetSpan_sets_span_on_last_item_and_flag);225 RUN_TEST(test_sqlite3ExprListSetSpan_does_not_overwrite_existing_zEName);226 RUN_TEST(test_sqlite3ExprListSetSpan_handles_null_list_when_mallocFailed);227 RUN_TEST(test_sqlite3ExprListSetSpan_span_boundaries);228 RUN_TEST(test_sqlite3ExprListSetSpan_second_call_no_overwrite);229 return UNITY_END();230}