Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_func_minMaxValueFinalize.c254 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6/* External wrapper for the static function under test */7extern void test_minMaxValueFinalize(sqlite3_context *context, int bValue);8 9/* Test harness state */10static sqlite3 *gDb = NULL;11 12/* Control structure passed to aggregate via sqlite3_user_data */13typedef struct AggCtl {14  int mode;    /* 0: no agg ctx, 1: flags=0, 2: int value, 3: dyn string */15  int bValue;  /* argument passed to test_minMaxValueFinalize */16} AggCtl;17 18/* Aggregate step function to set up the aggregate context in various ways */19static void test_step(sqlite3_context *ctx, int argc, sqlite3_value **argv){20  AggCtl *ctl = (AggCtl*)sqlite3_user_data(ctx);21  UNUSED_PARAMETER(argc);22  UNUSED_PARAMETER(argv);23 24  if( ctl==NULL ) return;25 26  if( ctl->mode==0 ){27    /* Do not call sqlite3_aggregate_context at all */28    return;29  }30 31  /* Allocate aggregate context memory sized for Mem/sqlite3_value */32  Mem *p = (Mem*)sqlite3_aggregate_context(ctx, sizeof(Mem));33  if( p==NULL ) return; /* Out of memory or error, let SQLite handle it */34 35  /* Ensure it's initialized (aggregate_context should zero memory) */36  /* Set db pointer for any potential releases in finalize */37  p->db = sqlite3_context_db_handle(ctx);38 39  switch( ctl->mode ){40    case 1: {41      /* Leave flags==0 meaning "no value stored" */42      p->flags = 0;43      break;44    }45    case 2: {46      /* Store an integer value */47      p->flags = MEM_Int;48      p->u.i = 12345;49      break;50    }51    case 3: {52      /* Store a dynamically allocated UTF-8 string to exercise release */53      const char *msg = "hello";54      int n = (int)strlen(msg);55      char *z = (char*)sqlite3DbMallocZero(p->db, n+1);56      if( z ){57        memcpy(z, msg, n+1);58        p->z = z;59        p->n = n;60        p->enc = SQLITE_UTF8;61        p->flags = MEM_Str | MEM_Term | MEM_Dyn;62      }else{63        /* If allocation failed, leave flags at 0 so result will be NULL */64        p->flags = 0;65      }66      break;67    }68    default:69      /* Unknown mode: do nothing */70      break;71  }72}73 74/* Aggregate finalizer that calls the target function wrapper */75static void test_final(sqlite3_context *ctx){76  AggCtl *ctl = (AggCtl*)sqlite3_user_data(ctx);77  int bValue = ctl ? ctl->bValue : 0;78  test_minMaxValueFinalize(ctx, bValue);79}80 81/* Helper to register an aggregate function with given control */82static void register_test_agg(sqlite3 *db, const char *zName, AggCtl *ctl){83  int rc = sqlite3_create_function(db, zName, 1, SQLITE_UTF8, ctl,84                                   NULL, test_step, test_final);85  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_create_function failed");86}87 88/* Run a query "SELECT f(1)" and capture the single result */89static void run_select_single(sqlite3 *db, const char *zFuncName,90                              int *pType, sqlite3_int64 *pI64, const unsigned char **pText){91  char sql[128];92  sqlite3_stmt *pStmt = NULL;93  snprintf(sql, sizeof(sql), "SELECT %s(1)", zFuncName);94  int rc = sqlite3_prepare_v2(db, sql, -1, &pStmt, 0);95  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "prepare failed");96  rc = sqlite3_step(pStmt);97  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_ROW, rc, "expected one row");98  int t = sqlite3_column_type(pStmt, 0);99  if( pType ) *pType = t;100  if( t==SQLITE_INTEGER && pI64 ){101    *pI64 = sqlite3_column_int64(pStmt, 0);102  }else if( t==SQLITE_TEXT && pText ){103    *pText = sqlite3_column_text(pStmt, 0);104  }105  rc = sqlite3_step(pStmt);106  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_DONE, rc, "expected exactly one row");107  sqlite3_finalize(pStmt);108}109 110void setUp(void) {111  /* Empty; open per-test to ensure isolation */112}113 114void tearDown(void) {115  if( gDb ){116    sqlite3_close(gDb);117    gDb = NULL;118  }119}120 121/* Test: pRes==NULL path (no aggregate context ever allocated) -> result NULL */122void test_minMaxValueFinalize_null_when_no_aggctx_bValue0(void){123  int rc = sqlite3_open(":memory:", &gDb);124  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);125 126  AggCtl *ctl = (AggCtl*)sqlite3_malloc(sizeof(AggCtl));127  TEST_ASSERT_NOT_NULL(ctl);128  ctl->mode = 0; /* do not allocate aggregate context */129  ctl->bValue = 0;130 131  register_test_agg(gDb, "xf_none_b0", ctl);132 133  int type = 0;134  run_select_single(gDb, "xf_none_b0", &type, NULL, NULL);135  TEST_ASSERT_EQUAL_INT(SQLITE_NULL, type);136 137  sqlite3_free(ctl);138}139 140/* Test: pRes exists but flags==0 -> result NULL (bValue doesn't matter) */141void test_minMaxValueFinalize_null_when_flags_zero_bValue1(void){142  int rc = sqlite3_open(":memory:", &gDb);143  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);144 145  AggCtl *ctl = (AggCtl*)sqlite3_malloc(sizeof(AggCtl));146  TEST_ASSERT_NOT_NULL(ctl);147  ctl->mode = 1; /* aggregate context allocated, flags=0 */148  ctl->bValue = 1;149 150  register_test_agg(gDb, "xf_empty_b1", ctl);151 152  int type = 0;153  run_select_single(gDb, "xf_empty_b1", &type, NULL, NULL);154  TEST_ASSERT_EQUAL_INT(SQLITE_NULL, type);155 156  sqlite3_free(ctl);157}158 159/* Test: integer value stored, bValue==0 -> returns integer (and may release) */160void test_minMaxValueFinalize_returns_int_bValue0(void){161  int rc = sqlite3_open(":memory:", &gDb);162  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);163 164  AggCtl *ctl = (AggCtl*)sqlite3_malloc(sizeof(AggCtl));165  TEST_ASSERT_NOT_NULL(ctl);166  ctl->mode = 2; /* integer value */167  ctl->bValue = 0;168 169  register_test_agg(gDb, "xf_int_b0", ctl);170 171  int type = 0;172  sqlite3_int64 v = 0;173  run_select_single(gDb, "xf_int_b0", &type, &v, NULL);174  TEST_ASSERT_EQUAL_INT(SQLITE_INTEGER, type);175  TEST_ASSERT_EQUAL_INT64(12345, v);176 177  sqlite3_free(ctl);178}179 180/* Test: integer value stored, bValue==1 -> returns integer (no release) */181void test_minMaxValueFinalize_returns_int_bValue1(void){182  int rc = sqlite3_open(":memory:", &gDb);183  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);184 185  AggCtl *ctl = (AggCtl*)sqlite3_malloc(sizeof(AggCtl));186  TEST_ASSERT_NOT_NULL(ctl);187  ctl->mode = 2; /* integer value */188  ctl->bValue = 1;189 190  register_test_agg(gDb, "xf_int_b1", ctl);191 192  int type = 0;193  sqlite3_int64 v = 0;194  run_select_single(gDb, "xf_int_b1", &type, &v, NULL);195  TEST_ASSERT_EQUAL_INT(SQLITE_INTEGER, type);196  TEST_ASSERT_EQUAL_INT64(12345, v);197 198  sqlite3_free(ctl);199}200 201/* Test: dynamic string stored, bValue==0 -> returns text and exercises release path */202void test_minMaxValueFinalize_returns_text_bValue0_release(void){203  int rc = sqlite3_open(":memory:", &gDb);204  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);205 206  AggCtl *ctl = (AggCtl*)sqlite3_malloc(sizeof(AggCtl));207  TEST_ASSERT_NOT_NULL(ctl);208  ctl->mode = 3; /* dynamic string value */209  ctl->bValue = 0;210 211  register_test_agg(gDb, "xf_text_b0", ctl);212 213  int type = 0;214  const unsigned char *txt = NULL;215  run_select_single(gDb, "xf_text_b0", &type, NULL, &txt);216  TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, type);217  TEST_ASSERT_NOT_NULL(txt);218  TEST_ASSERT_EQUAL_INT(0, strcmp((const char*)txt, "hello"));219 220  sqlite3_free(ctl);221}222 223/* Test: dynamic string stored, bValue==1 -> returns text (no release in finalize) */224void test_minMaxValueFinalize_returns_text_bValue1_no_release(void){225  int rc = sqlite3_open(":memory:", &gDb);226  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);227 228  AggCtl *ctl = (AggCtl*)sqlite3_malloc(sizeof(AggCtl));229  TEST_ASSERT_NOT_NULL(ctl);230  ctl->mode = 3; /* dynamic string value */231  ctl->bValue = 1;232 233  register_test_agg(gDb, "xf_text_b1", ctl);234 235  int type = 0;236  const unsigned char *txt = NULL;237  run_select_single(gDb, "xf_text_b1", &type, NULL, &txt);238  TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, type);239  TEST_ASSERT_NOT_NULL(txt);240  TEST_ASSERT_EQUAL_INT(0, strcmp((const char*)txt, "hello"));241 242  sqlite3_free(ctl);243}244 245int main(void) {246  UNITY_BEGIN();247  RUN_TEST(test_minMaxValueFinalize_null_when_no_aggctx_bValue0);248  RUN_TEST(test_minMaxValueFinalize_null_when_flags_zero_bValue1);249  RUN_TEST(test_minMaxValueFinalize_returns_int_bValue0);250  RUN_TEST(test_minMaxValueFinalize_returns_int_bValue1);251  RUN_TEST(test_minMaxValueFinalize_returns_text_bValue0_release);252  RUN_TEST(test_minMaxValueFinalize_returns_text_bValue1_no_release);253  return UNITY_END();254}