Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_func_percentCompute.c253 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5#include <stdint.h>6 7/* External wrapper provided in the module under test */8extern void test_percentCompute(sqlite3_context *pCtx, int bIsFinal);9 10/*11** We construct the aggregate context memory expected by percentCompute.12** This local struct mirrors the fields that percentCompute uses:13**   - a: array of doubles14**   - nUsed: number of used elements in a15**   - nAlloc: capacity (not strictly needed but set sensibly)16**   - bSorted: whether a is already sorted17**   - bKeepSorted: flag set when not final18**   - rPct: percentile fraction in [0,1]19** The exact internal name/type is not referenced; we only write20** the expected fields into the aggregate context memory that21** percentCompute will read.22*/23typedef struct TestPercentile {24  double *a;25  unsigned int nUsed;26  unsigned int nAlloc;27  unsigned int bSorted;28  unsigned int bKeepSorted;29  double rPct;30} TestPercentile;31 32/* Helper to initialize a sqlite3_context and its Mems */33static void init_context(sqlite3 *db,34                         sqlite3_context *pCtx,35                         Mem *pOut,36                         Mem *pAgg,37                         FuncDef *pDef,38                         void *pUserData,39                         void *pAggBuf,40                         int nAggBuf){41  memset(pCtx, 0, sizeof(*pCtx));42  memset(pOut, 0, sizeof(*pOut));43  memset(pAgg, 0, sizeof(*pAgg));44  memset(pDef, 0, sizeof(*pDef));45 46  /* Set up function user-data for settings (discrete/continuous) */47  pDef->pUserData = pUserData;48  pCtx->pFunc = pDef;49 50  /* Output register for sqlite3_result_* */51  pOut->db = db;52  pCtx->pOut = pOut;53 54  /* Aggregate context storage */55  pAgg->db = db;56  if( pAggBuf ){57    pAgg->flags = MEM_Agg;    /* signal that aggregate context exists */58    pAgg->z = (char*)pAggBuf; /* sqlite3_aggregate_context(...,0) returns this */59    pAgg->n = nAggBuf;60  }61  pCtx->pMem = pAgg;62}63 64void setUp(void) {65  /* empty */66}67 68void tearDown(void) {69  /* empty */70}71 72static double get_result_double(Mem *pOut){73  /* Mem is compatible with sqlite3_value */74  return sqlite3_value_double((sqlite3_value*)pOut);75}76 77/* Test: continuous percentile with interpolation; array unsorted -> sort inside percentCompute */78void test_percentCompute_continuous_basic(void){79  sqlite3 *db = 0;80  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(0, &db));81 82  sqlite3_context ctx; Mem outMem; Mem aggMem; FuncDef def;83  /* Allocate ample buffer for aggregate context */84  int const aggBufSize = 256;85  void *aggBuf = sqlite3_malloc(aggBufSize);86  TEST_ASSERT_NOT_NULL(aggBuf);87  memset(aggBuf, 0, aggBufSize);88 89  init_context(db, &ctx, &outMem, &aggMem, &def, (void*)(intptr_t)0 /* continuous */, aggBuf, aggBufSize);90 91  /* Prepare unsorted data: [40,10,30,20] -> sorted [10,20,30,40] */92  int n = 4;93  double *arr = (double*)sqlite3_malloc(n * sizeof(double));94  TEST_ASSERT_NOT_NULL(arr);95  arr[0]=40.0; arr[1]=10.0; arr[2]=30.0; arr[3]=20.0;96 97  TestPercentile *P = (TestPercentile*)aggBuf;98  P->a = arr;99  P->nUsed = (unsigned)n;100  P->nAlloc = (unsigned)n;101  P->bSorted = 0;            /* require sort */102  P->bKeepSorted = 0;103  P->rPct = 0.25;            /* 25th percentile: ix=0.75 -> 17.5 */104 105  test_percentCompute(&ctx, 0 /* not final */);106 107  double got = get_result_double(&outMem);108  TEST_ASSERT_DOUBLE_WITHIN(1e-12, 17.5, got);109  /* Non-final should set bKeepSorted */110  TEST_ASSERT_EQUAL_UINT(1U, P->bKeepSorted);111 112  /* Clean up; non-final did not free arr */113  sqlite3_free(arr);114  sqlite3_free(aggBuf);115  sqlite3_close(db);116}117 118/* Test: discrete setting (no interpolation) */119void test_percentCompute_discrete_basic(void){120  sqlite3 *db = 0;121  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(0, &db));122 123  sqlite3_context ctx; Mem outMem; Mem aggMem; FuncDef def;124  int const aggBufSize = 256;125  void *aggBuf = sqlite3_malloc(aggBufSize);126  TEST_ASSERT_NOT_NULL(aggBuf);127  memset(aggBuf, 0, aggBufSize);128 129  init_context(db, &ctx, &outMem, &aggMem, &def, (void*)(intptr_t)1 /* discrete flag */, aggBuf, aggBufSize);130 131  int n = 4;132  double *arr = (double*)sqlite3_malloc(n * sizeof(double));133  TEST_ASSERT_NOT_NULL(arr);134  arr[0]=40.0; arr[1]=10.0; arr[2]=30.0; arr[3]=20.0;135 136  TestPercentile *P = (TestPercentile*)aggBuf;137  P->a = arr;138  P->nUsed = (unsigned)n;139  P->nAlloc = (unsigned)n;140  P->bSorted = 0;   /* will be sorted */141  P->bKeepSorted = 0;142  P->rPct = 0.25;   /* i1=0 -> choose a[0] after sort -> 10 */143 144  test_percentCompute(&ctx, 0 /* not final */);145 146  double got = get_result_double(&outMem);147  TEST_ASSERT_DOUBLE_WITHIN(1e-12, 10.0, got);148 149  sqlite3_free(arr);150  sqlite3_free(aggBuf);151  sqlite3_close(db);152}153 154/* Test: exact-index/last-element behavior (continuous should pick endpoint cleanly) */155void test_percentCompute_exact_last_value(void){156  sqlite3 *db = 0;157  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(0, &db));158 159  sqlite3_context ctx; Mem outMem; Mem aggMem; FuncDef def;160  int const aggBufSize = 256;161  void *aggBuf = sqlite3_malloc(aggBufSize);162  TEST_ASSERT_NOT_NULL(aggBuf);163  memset(aggBuf, 0, aggBufSize);164 165  init_context(db, &ctx, &outMem, &aggMem, &def, (void*)(intptr_t)0 /* continuous */, aggBuf, aggBufSize);166 167  int n = 4;168  double *arr = (double*)sqlite3_malloc(n * sizeof(double));169  TEST_ASSERT_NOT_NULL(arr);170  arr[0]=5.0; arr[1]=15.0; arr[2]=25.0; arr[3]=35.0;171 172  TestPercentile *P = (TestPercentile*)aggBuf;173  P->a = arr;174  P->nUsed = (unsigned)n;175  P->nAlloc = (unsigned)n;176  P->bSorted = 0;   /* allow internal sort */177  P->bKeepSorted = 0;178  P->rPct = 1.0;    /* ix = nUsed-1 => choose last value */179 180  test_percentCompute(&ctx, 0 /* not final */);181 182  double got = get_result_double(&outMem);183  TEST_ASSERT_DOUBLE_WITHIN(1e-12, 35.0, got);184 185  sqlite3_free(arr);186  sqlite3_free(aggBuf);187  sqlite3_close(db);188}189 190/* Test: finalization cleans up memory and zeroes the accumulator */191void test_percentCompute_finalizes_and_zeros(void){192  sqlite3 *db = 0;193  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(0, &db));194 195  sqlite3_context ctx; Mem outMem; Mem aggMem; FuncDef def;196  int const aggBufSize = 256;197  void *aggBuf = sqlite3_malloc(aggBufSize);198  TEST_ASSERT_NOT_NULL(aggBuf);199  memset(aggBuf, 0, aggBufSize);200 201  init_context(db, &ctx, &outMem, &aggMem, &def, (void*)(intptr_t)0 /* continuous */, aggBuf, aggBufSize);202 203  /* nUsed==0 to avoid reading a[]; but set a non-NULL so free() is exercised */204  double *arr = (double*)sqlite3_malloc(2*sizeof(double));205  TEST_ASSERT_NOT_NULL(arr);206  arr[0]=1.0; arr[1]=2.0;207 208  TestPercentile *P = (TestPercentile*)aggBuf;209  P->a = arr;210  P->nUsed = 0;      /* no results, but finalization should still free a and zero struct */211  P->nAlloc = 2;212  P->bSorted = 0;213  P->bKeepSorted = 0;214  P->rPct = 0.5;215 216  test_percentCompute(&ctx, 1 /* final */);217 218  /* After finalization, the aggregate buffer should be zeroed */219  unsigned char zero[64]; memset(zero, 0, sizeof(zero));220  TEST_ASSERT_EQUAL_INT(0, memcmp(aggBuf, zero, sizeof(zero)));221 222  /* arr was freed by percentCompute; do not free arr here */223  sqlite3_free(aggBuf);224  sqlite3_close(db);225}226 227/* Test: handles missing aggregate context (p==NULL) gracefully */228void test_percentCompute_handles_no_context(void){229  sqlite3 *db = 0;230  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(0, &db));231 232  sqlite3_context ctx; Mem outMem; Mem aggMem; FuncDef def;233  /* No aggregate buffer provided: sqlite3_aggregate_context(ctx,0) -> NULL */234  init_context(db, &ctx, &outMem, &aggMem, &def, (void*)(intptr_t)0, NULL, 0);235 236  test_percentCompute(&ctx, 0 /* not final */);237 238  /* No result should be produced; type remains NULL */239  int t = sqlite3_value_type((sqlite3_value*)&outMem);240  TEST_ASSERT_EQUAL_INT(SQLITE_NULL, t);241 242  sqlite3_close(db);243}244 245int main(void) {246  UNITY_BEGIN();247  RUN_TEST(test_percentCompute_continuous_basic);248  RUN_TEST(test_percentCompute_discrete_basic);249  RUN_TEST(test_percentCompute_exact_last_value);250  RUN_TEST(test_percentCompute_finalizes_and_zeros);251  RUN_TEST(test_percentCompute_handles_no_context);252  return UNITY_END();253}