Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_func_countStep.c197 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5#include <stdint.h>6 7/* Wrapper provided in the module for the static function under test */8extern void test_countStep(sqlite3_context *context, int argc, sqlite3_value **argv);9 10/* Dummy finalize function to satisfy potential asserts on pFunc->xFinalize */11static void dummyFinalize(sqlite3_context *pCtx){12  (void)pCtx;13}14 15/* Helper: initialize an aggregate sqlite3_context with a MEM_Agg Mem cell */16static void initAggSqlite3Context(sqlite3 *db, sqlite3_context *pCtx, Mem *pMem, FuncDef *pDef){17  memset(pCtx, 0, sizeof(*pCtx));18  memset(pMem, 0, sizeof(*pMem));19  memset(pDef, 0, sizeof(*pDef));20 21  /* Prepare the aggregate memory cell: mark as aggregate and attach db */22  pMem->flags = MEM_Agg;23  pMem->db = db;24  pMem->z = 0;          /* Force sqlite3_aggregate_context to allocate on first use */25  pMem->n = 0;26  pMem->szMalloc = 0;27 28  /* Provide a FuncDef with a finalize pointer (helps with asserts in debug builds) */29  pDef->xFinalize = dummyFinalize;30 31  /* Wire up the context */32  pCtx->pMem = pMem;33  pCtx->pFunc = pDef;34}35 36/* Helper: create a sqlite3_value representing an integer */37static void setIntValue(sqlite3 *db, sqlite3_value *pVal, sqlite3_int64 v){38  Mem *m = (Mem*)pVal;39  memset(m, 0, sizeof(*m));40  m->db = db;41  m->flags = MEM_Int;42  m->u.i = v;43}44 45/* Helper: create a sqlite3_value representing NULL */46static void setNullValue(sqlite3_value *pVal){47  Mem *m = (Mem*)pVal;48  memset(m, 0, sizeof(*m));49  m->flags = MEM_Null;50}51 52/* Helper: read the current CountCtx.n from the aggregate context memory.53   Assumes CountCtx.n is the first 8 bytes of the allocated buffer. */54static sqlite3_int64 readCountFromCtx(sqlite3_context *pCtx){55  TEST_ASSERT_NOT_NULL(pCtx);56  TEST_ASSERT_NOT_NULL(pCtx->pMem);57  TEST_ASSERT_NOT_NULL(pCtx->pMem->z);58  sqlite3_int64 *pn = (sqlite3_int64*)(void*)pCtx->pMem->z;59  return *pn;60}61 62/* Unity fixtures */63void setUp(void) {64  /* nothing */65}66void tearDown(void) {67  /* nothing */68}69 70/* Test: COUNT(x) increments when x is non-NULL */71void test_countStep_increments_on_non_null(void){72  sqlite3 *db = 0;73  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));74 75  sqlite3_context ctx;76  Mem ctxMem;77  FuncDef def;78  initAggSqlite3Context(db, &ctx, &ctxMem, &def);79 80  sqlite3_value val;81  setIntValue(db, &val, 123);82  sqlite3_value *argv[1] = { &val };83 84  /* Before any call, aggregate memory should be allocated on first call.85     After one non-NULL step, count should be 1. */86  test_countStep(&ctx, 1, argv);87  TEST_ASSERT_NOT_NULL(ctx.pMem->z);88  TEST_ASSERT_EQUAL_INT64(1, readCountFromCtx(&ctx));89 90  /* Another non-NULL step increments again */91  setIntValue(db, &val, 456);92  test_countStep(&ctx, 1, argv);93  TEST_ASSERT_EQUAL_INT64(2, readCountFromCtx(&ctx));94 95  /* Cleanup */96  if( ctxMem.z ) sqlite3DbFree(db, ctxMem.z);97  sqlite3_close(db);98}99 100/* Test: COUNT(x) does not increment when x is NULL */101void test_countStep_skips_on_null(void){102  sqlite3 *db = 0;103  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));104 105  sqlite3_context ctx;106  Mem ctxMem;107  FuncDef def;108  initAggSqlite3Context(db, &ctx, &ctxMem, &def);109 110  /* Prime with one non-NULL so we can see no change on NULL */111  sqlite3_value nonnull;112  setIntValue(db, &nonnull, 1);113  sqlite3_value *argv1[1] = { &nonnull };114  test_countStep(&ctx, 1, argv1);115  TEST_ASSERT_EQUAL_INT64(1, readCountFromCtx(&ctx));116 117  /* Now pass NULL and ensure count does not change */118  sqlite3_value nullv;119  setNullValue(&nullv);120  sqlite3_value *argv2[1] = { &nullv };121  test_countStep(&ctx, 1, argv2);122  TEST_ASSERT_EQUAL_INT64(1, readCountFromCtx(&ctx));123 124  /* Cleanup */125  if( ctxMem.z ) sqlite3DbFree(db, ctxMem.z);126  sqlite3_close(db);127}128 129/* Test: COUNT(*) behavior (argc==0) increments regardless of arguments */130void test_countStep_increments_on_count_star(void){131  sqlite3 *db = 0;132  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));133 134  sqlite3_context ctx;135  Mem ctxMem;136  FuncDef def;137  initAggSqlite3Context(db, &ctx, &ctxMem, &def);138 139  /* First COUNT(*) step increments to 1 */140  test_countStep(&ctx, 0, 0);141  TEST_ASSERT_EQUAL_INT64(1, readCountFromCtx(&ctx));142 143  /* Second COUNT(*) step increments to 2 */144  test_countStep(&ctx, 0, 0);145  TEST_ASSERT_EQUAL_INT64(2, readCountFromCtx(&ctx));146 147  /* Cleanup */148  if( ctxMem.z ) sqlite3DbFree(db, ctxMem.z);149  sqlite3_close(db);150}151 152/* Test: Mixed sequence of NULL/non-NULL/COUNT(*) accumulates correctly */153void test_countStep_mixed_sequence_accumulates(void){154  sqlite3 *db = 0;155  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));156 157  sqlite3_context ctx;158  Mem ctxMem;159  FuncDef def;160  initAggSqlite3Context(db, &ctx, &ctxMem, &def);161 162  sqlite3_value vInt, vNull;163  setIntValue(db, &vInt, 10);164  setNullValue(&vNull);165  sqlite3_value *argvInt[1] = { &vInt };166  sqlite3_value *argvNull[1] = { &vNull };167 168  /* Start at 0, apply sequence:169     non-NULL (+1) -> NULL (+0) -> COUNT(*) (+1) -> non-NULL (+1) -> NULL (+0) */170  test_countStep(&ctx, 1, argvInt);   /* 1 */171  TEST_ASSERT_EQUAL_INT64(1, readCountFromCtx(&ctx));172 173  test_countStep(&ctx, 1, argvNull);  /* 1 */174  TEST_ASSERT_EQUAL_INT64(1, readCountFromCtx(&ctx));175 176  test_countStep(&ctx, 0, 0);         /* 2 */177  TEST_ASSERT_EQUAL_INT64(2, readCountFromCtx(&ctx));178 179  test_countStep(&ctx, 1, argvInt);   /* 3 */180  TEST_ASSERT_EQUAL_INT64(3, readCountFromCtx(&ctx));181 182  test_countStep(&ctx, 1, argvNull);  /* 3 */183  TEST_ASSERT_EQUAL_INT64(3, readCountFromCtx(&ctx));184 185  /* Cleanup */186  if( ctxMem.z ) sqlite3DbFree(db, ctxMem.z);187  sqlite3_close(db);188}189 190int main(void){191  UNITY_BEGIN();192  RUN_TEST(test_countStep_increments_on_non_null);193  RUN_TEST(test_countStep_skips_on_null);194  RUN_TEST(test_countStep_increments_on_count_star);195  RUN_TEST(test_countStep_mixed_sequence_accumulates);196  return UNITY_END();197}