AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5#include <stdio.h>6 7/* Forward declaration for the provided test wrapper around the static function */8void test_minmaxStep(sqlite3_context *context, int NotUsed, sqlite3_value **argv);9 10/* Helpers to initialize context and Mem values */11 12static void init_context(sqlite3 *db, sqlite3_context *pCtx, Mem *pAggMem, FuncDef *pFuncDef, void *userData){13 memset(pCtx, 0, sizeof(*pCtx));14 memset(pAggMem, 0, sizeof(*pAggMem));15 memset(pFuncDef, 0, sizeof(*pFuncDef));16 17 /* Aggregate storage cell */18 pAggMem->db = db;19 20 /* Context wiring */21 pCtx->pMem = pAggMem;22 pCtx->s.db = db; /* Ensure sqlite3_context_db_handle() works */23 pCtx->pFunc = pFuncDef; /* For sqlite3_user_data() */24 pCtx->pColl = 0; /* Default collation */25 pCtx->isError = 0;26 pCtx->skipFlag = 0;27 28 /* Control min/max via user data: NULL => min; non-NULL => max */29 pFuncDef->pUserData = userData;30}31 32static void set_mem_int(sqlite3 *db, Mem *p, sqlite3_int64 v){33 memset(p, 0, sizeof(*p));34 p->db = db;35 sqlite3VdbeMemSetInt64(p, v);36}37 38static void set_mem_null(sqlite3 *db, Mem *p){39 memset(p, 0, sizeof(*p));40 p->db = db;41 sqlite3VdbeMemSetNull(p);42}43 44static void set_mem_text(sqlite3 *db, Mem *p, const char *z){45 memset(p, 0, sizeof(*p));46 p->db = db;47 sqlite3VdbeMemSetStr(p, z, -1, SQLITE_UTF8, SQLITE_STATIC);48}49 50static void call_step(sqlite3_context *pCtx, Mem *pArg){51 sqlite3_value *argv[1];52 argv[0] = (sqlite3_value*)pArg;53 /* Reset skipFlag before each call so we can verify changes per step */54 pCtx->skipFlag = 0;55 test_minmaxStep(pCtx, 1, argv);56}57 58/* Unity fixtures */59void setUp(void) {60 /* empty */61}62void tearDown(void) {63 /* empty */64}65 66/* Tests */67 68void test_minmaxStep_min_integer_sequence(void){69 sqlite3 *db = 0;70 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));71 72 sqlite3_context ctx;73 Mem aggCell;74 FuncDef fd;75 init_context(db, &ctx, &aggCell, &fd, /* userData=NULL => min */ NULL);76 77 Mem arg;78 /* Step 1: value 5 -> initialize */79 set_mem_int(db, &arg, 5);80 call_step(&ctx, &arg);81 Mem *pBest = (Mem*)sqlite3_aggregate_context(&ctx, 0);82 TEST_ASSERT_NOT_NULL(pBest);83 TEST_ASSERT_EQUAL(0, ctx.skipFlag);84 TEST_ASSERT_TRUE(pBest->flags != 0);85 TEST_ASSERT_EQUAL_INT64(5, pBest->u.i);86 87 /* Step 2: value 3 -> update (min) */88 set_mem_int(db, &arg, 3);89 call_step(&ctx, &arg);90 pBest = (Mem*)sqlite3_aggregate_context(&ctx, 0);91 TEST_ASSERT_NOT_NULL(pBest);92 TEST_ASSERT_EQUAL(0, ctx.skipFlag);93 TEST_ASSERT_EQUAL_INT64(3, pBest->u.i);94 95 /* Step 3: value 7 -> no update, skipFlag set */96 set_mem_int(db, &arg, 7);97 call_step(&ctx, &arg);98 pBest = (Mem*)sqlite3_aggregate_context(&ctx, 0);99 TEST_ASSERT_NOT_NULL(pBest);100 TEST_ASSERT_EQUAL(1, ctx.skipFlag);101 TEST_ASSERT_EQUAL_INT64(3, pBest->u.i);102 103 sqlite3_close(db);104}105 106void test_minmaxStep_max_integer_sequence(void){107 sqlite3 *db = 0;108 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));109 110 sqlite3_context ctx;111 Mem aggCell;112 FuncDef fd;113 init_context(db, &ctx, &aggCell, &fd, /* userData!=NULL => max */ (void*)1);114 115 Mem arg;116 /* Step 1: value 5 -> initialize */117 set_mem_int(db, &arg, 5);118 call_step(&ctx, &arg);119 Mem *pBest = (Mem*)sqlite3_aggregate_context(&ctx, 0);120 TEST_ASSERT_NOT_NULL(pBest);121 TEST_ASSERT_EQUAL(0, ctx.skipFlag);122 TEST_ASSERT_EQUAL_INT64(5, pBest->u.i);123 124 /* Step 2: value 3 -> no update (max), skipFlag set */125 set_mem_int(db, &arg, 3);126 call_step(&ctx, &arg);127 pBest = (Mem*)sqlite3_aggregate_context(&ctx, 0);128 TEST_ASSERT_NOT_NULL(pBest);129 TEST_ASSERT_EQUAL(1, ctx.skipFlag);130 TEST_ASSERT_EQUAL_INT64(5, pBest->u.i);131 132 /* Step 3: value 7 -> update (max) */133 set_mem_int(db, &arg, 7);134 call_step(&ctx, &arg);135 pBest = (Mem*)sqlite3_aggregate_context(&ctx, 0);136 TEST_ASSERT_NOT_NULL(pBest);137 TEST_ASSERT_EQUAL(0, ctx.skipFlag);138 TEST_ASSERT_EQUAL_INT64(7, pBest->u.i);139 140 sqlite3_close(db);141}142 143void test_minmaxStep_null_handling_and_skipflag(void){144 sqlite3 *db = 0;145 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));146 147 sqlite3_context ctx;148 Mem aggCell;149 FuncDef fd;150 init_context(db, &ctx, &aggCell, &fd, /* min */ NULL);151 152 Mem arg;153 154 /* Step 1: NULL -> no initialization, skipFlag remains 0 */155 set_mem_null(db, &arg);156 call_step(&ctx, &arg);157 Mem *pBest = (Mem*)sqlite3_aggregate_context(&ctx, 0);158 TEST_ASSERT_NOT_NULL(pBest); /* aggregate context exists */159 TEST_ASSERT_EQUAL(0, ctx.skipFlag);160 TEST_ASSERT_EQUAL_INT(0, (pBest->flags!=0)); /* still empty (flags==0) */161 162 /* Step 2: 10 -> initializes aggregate */163 set_mem_int(db, &arg, 10);164 call_step(&ctx, &arg);165 pBest = (Mem*)sqlite3_aggregate_context(&ctx, 0);166 TEST_ASSERT_NOT_NULL(pBest);167 TEST_ASSERT_EQUAL(0, ctx.skipFlag);168 TEST_ASSERT_EQUAL_INT64(10, pBest->u.i);169 170 /* Step 3: NULL -> no change, skipFlag set */171 set_mem_null(db, &arg);172 call_step(&ctx, &arg);173 TEST_ASSERT_EQUAL(1, ctx.skipFlag);174 pBest = (Mem*)sqlite3_aggregate_context(&ctx, 0);175 TEST_ASSERT_EQUAL_INT64(10, pBest->u.i);176 177 /* Step 4: 2 -> update to 2, skipFlag cleared */178 set_mem_int(db, &arg, 2);179 call_step(&ctx, &arg);180 TEST_ASSERT_EQUAL(0, ctx.skipFlag);181 pBest = (Mem*)sqlite3_aggregate_context(&ctx, 0);182 TEST_ASSERT_EQUAL_INT64(2, pBest->u.i);183 184 sqlite3_close(db);185}186 187void test_minmaxStep_text_min(void){188 sqlite3 *db = 0;189 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));190 191 sqlite3_context ctx;192 Mem aggCell;193 FuncDef fd;194 init_context(db, &ctx, &aggCell, &fd, /* min */ NULL);195 196 Mem arg;197 /* Step 1: "banana" -> initialize */198 set_mem_text(db, &arg, "banana");199 call_step(&ctx, &arg);200 Mem *pBest = (Mem*)sqlite3_aggregate_context(&ctx, 0);201 TEST_ASSERT_NOT_NULL(pBest);202 TEST_ASSERT_EQUAL(0, ctx.skipFlag);203 const unsigned char *z = sqlite3_value_text((sqlite3_value*)pBest);204 TEST_ASSERT_NOT_NULL(z);205 TEST_ASSERT_EQUAL_STRING("banana", (const char*)z);206 207 /* Step 2: "apple" -> update (min) */208 set_mem_text(db, &arg, "apple");209 call_step(&ctx, &arg);210 TEST_ASSERT_EQUAL(0, ctx.skipFlag);211 z = sqlite3_value_text((sqlite3_value*)pBest);212 TEST_ASSERT_NOT_NULL(z);213 TEST_ASSERT_EQUAL_STRING("apple", (const char*)z);214 215 /* Step 3: "apricot" -> no update (since "apple" < "apricot"), skipFlag set */216 set_mem_text(db, &arg, "apricot");217 call_step(&ctx, &arg);218 TEST_ASSERT_EQUAL(1, ctx.skipFlag);219 z = sqlite3_value_text((sqlite3_value*)pBest);220 TEST_ASSERT_NOT_NULL(z);221 TEST_ASSERT_EQUAL_STRING("apple", (const char*)z);222 223 sqlite3_close(db);224}225 226void test_minmaxStep_text_max(void){227 sqlite3 *db = 0;228 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));229 230 sqlite3_context ctx;231 Mem aggCell;232 FuncDef fd;233 init_context(db, &ctx, &aggCell, &fd, /* max */ (void*)1);234 235 Mem arg;236 /* Step 1: "apple" -> initialize */237 set_mem_text(db, &arg, "apple");238 call_step(&ctx, &arg);239 Mem *pBest = (Mem*)sqlite3_aggregate_context(&ctx, 0);240 TEST_ASSERT_NOT_NULL(pBest);241 TEST_ASSERT_EQUAL(0, ctx.skipFlag);242 const unsigned char *z = sqlite3_value_text((sqlite3_value*)pBest);243 TEST_ASSERT_NOT_NULL(z);244 TEST_ASSERT_EQUAL_STRING("apple", (const char*)z);245 246 /* Step 2: "banana" -> update (max) */247 set_mem_text(db, &arg, "banana");248 call_step(&ctx, &arg);249 TEST_ASSERT_EQUAL(0, ctx.skipFlag);250 z = sqlite3_value_text((sqlite3_value*)pBest);251 TEST_ASSERT_NOT_NULL(z);252 TEST_ASSERT_EQUAL_STRING("banana", (const char*)z);253 254 /* Step 3: "apricot" -> no update (banana > apricot), skipFlag set */255 set_mem_text(db, &arg, "apricot");256 call_step(&ctx, &arg);257 TEST_ASSERT_EQUAL(1, ctx.skipFlag);258 z = sqlite3_value_text((sqlite3_value*)pBest);259 TEST_ASSERT_NOT_NULL(z);260 TEST_ASSERT_EQUAL_STRING("banana", (const char*)z);261 262 sqlite3_close(db);263}264 265int main(void){266 UNITY_BEGIN();267 RUN_TEST(test_minmaxStep_min_integer_sequence);268 RUN_TEST(test_minmaxStep_max_integer_sequence);269 RUN_TEST(test_minmaxStep_null_handling_and_skipflag);270 RUN_TEST(test_minmaxStep_text_min);271 RUN_TEST(test_minmaxStep_text_max);272 return UNITY_END();273}