Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_main_sqlite3_create_function.c238 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6/* Helper scalar function: double the integer argument */7static void xDouble(sqlite3_context *ctx, int argc, sqlite3_value **argv){8  int v = 0;9  if( argc>=1 && sqlite3_value_type(argv[0])!=SQLITE_NULL ){10    v = sqlite3_value_int(argv[0]);11  }12  sqlite3_result_int(ctx, v*2);13}14 15/* Helper scalar function: triple the integer argument (used to test overwrite) */16static void xTimes3(sqlite3_context *ctx, int argc, sqlite3_value **argv){17  int v = 0;18  if( argc>=1 && sqlite3_value_type(argv[0])!=SQLITE_NULL ){19    v = sqlite3_value_int(argv[0]);20  }21  sqlite3_result_int(ctx, v*3);22}23 24/* Helper zero-arg scalar function: returns constant 1234 */25static void xConst1234(sqlite3_context *ctx, int argc, sqlite3_value **argv){26  (void)argc; (void)argv;27  sqlite3_result_int(ctx, 1234);28}29 30/* Helper varargs scalar function: return number of arguments passed */31static void xVarCount(sqlite3_context *ctx, int argc, sqlite3_value **argv){32  (void)argv;33  sqlite3_result_int(ctx, argc);34}35 36/* Aggregate: sum of integer arguments */37static void xAggSumStep(sqlite3_context *ctx, int argc, sqlite3_value **argv){38  long long *pSum = (long long*)sqlite3_aggregate_context(ctx, (int)sizeof(long long));39  if( pSum && argc>=1 && sqlite3_value_type(argv[0])!=SQLITE_NULL ){40    *pSum += sqlite3_value_int64(argv[0]);41  }42}43static void xAggSumFinal(sqlite3_context *ctx){44  long long *pSum = (long long*)sqlite3_aggregate_context(ctx, 0);45  if( pSum ){46    sqlite3_result_int64(ctx, *pSum);47  }else{48    sqlite3_result_int64(ctx, 0);49  }50}51 52/* Small helper to evaluate a single-row/single-column integer result */53static int eval_int(sqlite3 *db, const char *zSql, int *pOut){54  sqlite3_stmt *pStmt = 0;55  int rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);56  if( rc!=SQLITE_OK ) return rc;57  rc = sqlite3_step(pStmt);58  if( rc==SQLITE_ROW ){59    if( pOut ) *pOut = sqlite3_column_int(pStmt, 0);60    rc = SQLITE_OK;61  }else if( rc==SQLITE_DONE ){62    rc = SQLITE_EMPTY; /* No row returned */63  }64  sqlite3_finalize(pStmt);65  return rc;66}67 68void setUp(void) {69  /* Setup code here, or leave empty */70}71 72void tearDown(void) {73  /* Cleanup code here, or leave empty */74}75 76void test_sqlite3_create_function_scalar_basic(void){77  sqlite3 *db = 0;78  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));79 80  int rc = sqlite3_create_function(81      db, "xdouble", 1, SQLITE_UTF8, NULL, xDouble, NULL, NULL);82  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);83 84  /* Direct constant */85  int out = 0;86  rc = eval_int(db, "SELECT xdouble(21)", &out);87  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);88  TEST_ASSERT_EQUAL_INT(42, out);89 90  /* With bound parameter */91  sqlite3_stmt *pStmt = 0;92  rc = sqlite3_prepare_v2(db, "SELECT xdouble(?1)", -1, &pStmt, 0);93  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);94  TEST_ASSERT_NOT_NULL(pStmt);95  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_bind_int(pStmt, 1, 7));96  rc = sqlite3_step(pStmt);97  TEST_ASSERT_EQUAL_INT(SQLITE_ROW, rc);98  TEST_ASSERT_EQUAL_INT(14, sqlite3_column_int(pStmt, 0));99  sqlite3_finalize(pStmt);100 101  sqlite3_close(db);102}103 104void test_sqlite3_create_function_zero_arg(void){105  sqlite3 *db = 0;106  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));107 108  int rc = sqlite3_create_function(109      db, "zerof", 0, SQLITE_UTF8, NULL, xConst1234, NULL, NULL);110  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);111 112  int out = 0;113  rc = eval_int(db, "SELECT zerof()", &out);114  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);115  TEST_ASSERT_EQUAL_INT(1234, out);116 117  sqlite3_close(db);118}119 120void test_sqlite3_create_function_aggregate_basic(void){121  sqlite3 *db = 0;122  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));123 124  int rc = sqlite3_create_function(125      db, "mysum", 1, SQLITE_UTF8, NULL, NULL, xAggSumStep, xAggSumFinal);126  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);127 128  int out = 0;129  /* Use VALUES table with alias for column name */130  rc = eval_int(db, "SELECT mysum(x) FROM (VALUES(1),(2),(3),(4)) AS t(x)", &out);131  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);132  TEST_ASSERT_EQUAL_INT(10, out);133 134  sqlite3_close(db);135}136 137void test_sqlite3_create_function_varargs(void){138  sqlite3 *db = 0;139  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));140 141  int rc = sqlite3_create_function(142      db, "varcnt", -1, SQLITE_UTF8, NULL, xVarCount, NULL, NULL);143  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);144 145  int out = 0;146 147  rc = eval_int(db, "SELECT varcnt()", &out);148  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);149  TEST_ASSERT_EQUAL_INT(0, out);150 151  rc = eval_int(db, "SELECT varcnt(10)", &out);152  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);153  TEST_ASSERT_EQUAL_INT(1, out);154 155  rc = eval_int(db, "SELECT varcnt(1,2,3,4,5)", &out);156  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);157  TEST_ASSERT_EQUAL_INT(5, out);158 159  sqlite3_close(db);160}161 162void test_sqlite3_create_function_overwrite_existing(void){163  sqlite3 *db = 0;164  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));165 166  /* Register xdouble as doubling function */167  int rc = sqlite3_create_function(168      db, "xdouble", 1, SQLITE_UTF8, NULL, xDouble, NULL, NULL);169  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);170 171  int out = 0;172  rc = eval_int(db, "SELECT xdouble(5)", &out);173  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);174  TEST_ASSERT_EQUAL_INT(10, out);175 176  /* Overwrite with a tripling function under same name/arity */177  rc = sqlite3_create_function(178      db, "xdouble", 1, SQLITE_UTF8, NULL, xTimes3, NULL, NULL);179  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);180 181  rc = eval_int(db, "SELECT xdouble(5)", &out);182  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);183  TEST_ASSERT_EQUAL_INT(15, out);184 185  sqlite3_close(db);186}187 188void test_sqlite3_create_function_wrong_arity_prepare_error(void){189  sqlite3 *db = 0;190  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));191 192  int rc = sqlite3_create_function(193      db, "only1", 1, SQLITE_UTF8, NULL, xDouble, NULL, NULL);194  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);195 196  /* Using wrong number of arguments should cause prepare to fail */197  sqlite3_stmt *pStmt = 0;198  rc = sqlite3_prepare_v2(db, "SELECT only1(1,2)", -1, &pStmt, 0);199  TEST_ASSERT_NOT_EQUAL(INT, SQLITE_OK, rc);200  if( pStmt ) sqlite3_finalize(pStmt);201 202  /* Correct arity should work */203  int out = 0;204  rc = eval_int(db, "SELECT only1(9)", &out);205  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);206  TEST_ASSERT_EQUAL_INT(18, out);207 208  sqlite3_close(db);209}210 211void test_sqlite3_create_function_invalid_name_fails(void){212  sqlite3 *db = 0;213  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));214 215  /* NULL function name should fail (but must not crash) */216  int rc = sqlite3_create_function(217      db, NULL, 1, SQLITE_UTF8, NULL, xDouble, NULL, NULL);218  TEST_ASSERT_NOT_EQUAL(INT, SQLITE_OK, rc);219 220  /* Empty string name should also fail */221  rc = sqlite3_create_function(222      db, "", 1, SQLITE_UTF8, NULL, xDouble, NULL, NULL);223  TEST_ASSERT_NOT_EQUAL(INT, SQLITE_OK, rc);224 225  sqlite3_close(db);226}227 228int main(void){229  UNITY_BEGIN();230  RUN_TEST(test_sqlite3_create_function_scalar_basic);231  RUN_TEST(test_sqlite3_create_function_zero_arg);232  RUN_TEST(test_sqlite3_create_function_aggregate_basic);233  RUN_TEST(test_sqlite3_create_function_varargs);234  RUN_TEST(test_sqlite3_create_function_overwrite_existing);235  RUN_TEST(test_sqlite3_create_function_wrong_arity_prepare_error);236  RUN_TEST(test_sqlite3_create_function_invalid_name_fails);237  return UNITY_END();238}