Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_func_math2Func.c172 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3 4#include <stdlib.h>5#include <string.h>6#include <math.h>7 8/* The target function is static in the module; use the provided wrapper. */9void test_math2Func(sqlite3_context *context, int argc, sqlite3_value **argv);10 11/* Unity required hooks */12void setUp(void) {13  /* No global setup needed for these tests */14}15void tearDown(void) {16  /* No global teardown needed for these tests */17}18 19/* Wrapper xFunc that calls the target function's test wrapper */20static void xFuncWrapper(sqlite3_context *ctx, int argc, sqlite3_value **argv){21  test_math2Func(ctx, argc, argv);22}23 24/* Helper: register a scalar function "tm2" with given user data pointer */25static void register_tm2(sqlite3 *db, void *pUserData){26  int rc = sqlite3_create_function_v2(27    db, "tm2", 2, SQLITE_UTF8, pUserData, xFuncWrapper, 0, 0, 028  );29  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);30}31 32/* Helper: run a single-row, single-column SELECT and fetch a double or NULL */33static int query_single_double(sqlite3 *db, const char *sql, double *pVal, int *pIsNull){34  sqlite3_stmt *stmt = 0;35  int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);36  if( rc!=SQLITE_OK ) return rc;37  rc = sqlite3_step(stmt);38  if( rc==SQLITE_ROW ){39    int t = sqlite3_column_type(stmt, 0);40    if( pIsNull ) *pIsNull = (t==SQLITE_NULL);41    if( t==SQLITE_NULL ){42      if( pVal ) *pVal = 0.0;43    }else{44      if( pVal ) *pVal = sqlite3_column_double(stmt, 0);45    }46    rc = SQLITE_OK;47  }48  sqlite3_finalize(stmt);49  return rc;50}51 52/* Custom function pointers for user data tests */53static double add2(double a, double b){ return a + b; }54static double mul2(double a, double b){ return a * b; }55 56/* Test: basic power computations using pow as user data */57static void test_math2Func_pow_basic(void){58  sqlite3 *db = 0;59  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));60  /* Pass pow as the user data function */61  register_tm2(db, (void*)pow);62 63  double v = 0.0; int isNull = 0;64  TEST_ASSERT_EQUAL_INT(SQLITE_OK, query_single_double(db, "SELECT tm2(2,3);", &v, &isNull));65  TEST_ASSERT_FALSE(isNull);66  TEST_ASSERT_DOUBLE_WITHIN(1e-12, 8.0, v);67 68  TEST_ASSERT_EQUAL_INT(SQLITE_OK, query_single_double(db, "SELECT tm2(2,-1);", &v, &isNull));69  TEST_ASSERT_FALSE(isNull);70  TEST_ASSERT_DOUBLE_WITHIN(1e-12, 0.5, v);71 72  sqlite3_close(db);73}74 75/* Test: TEXT that is numeric should coerce to numeric and be accepted */76static void test_math2Func_text_numeric_coercion(void){77  sqlite3 *db = 0;78  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));79  register_tm2(db, (void*)pow);80 81  double v = 0.0; int isNull = 0;82  TEST_ASSERT_EQUAL_INT(SQLITE_OK, query_single_double(db, "SELECT tm2('2','3.0');", &v, &isNull));83  TEST_ASSERT_FALSE(isNull);84  TEST_ASSERT_DOUBLE_WITHIN(1e-12, 8.0, v);85 86  TEST_ASSERT_EQUAL_INT(SQLITE_OK, query_single_double(db, "SELECT tm2('2.5','2');", &v, &isNull));87  TEST_ASSERT_FALSE(isNull);88  TEST_ASSERT_DOUBLE_WITHIN(1e-12, 6.25, v);89 90  sqlite3_close(db);91}92 93/* Test: non-numeric arguments result in NULL (function early returns) */94static void test_math2Func_non_numeric_args(void){95  sqlite3 *db = 0;96  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));97  register_tm2(db, (void*)pow);98 99  double v = 0.0; int isNull = 0;100  /* First arg non-numeric TEXT */101  TEST_ASSERT_EQUAL_INT(SQLITE_OK, query_single_double(db, "SELECT tm2('abc', 2);", &v, &isNull));102  TEST_ASSERT_TRUE(isNull);103 104  /* Second arg BLOB */105  TEST_ASSERT_EQUAL_INT(SQLITE_OK, query_single_double(db, "SELECT tm2(2, x'123456');", &v, &isNull));106  TEST_ASSERT_TRUE(isNull);107 108  sqlite3_close(db);109}110 111/* Test: NULL arguments propagate as NULL result */112static void test_math2Func_null_args(void){113  sqlite3 *db = 0;114  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));115  register_tm2(db, (void*)pow);116 117  double v = 0.0; int isNull = 0;118  TEST_ASSERT_EQUAL_INT(SQLITE_OK, query_single_double(db, "SELECT tm2(NULL, 1);", &v, &isNull));119  TEST_ASSERT_TRUE(isNull);120 121  TEST_ASSERT_EQUAL_INT(SQLITE_OK, query_single_double(db, "SELECT tm2(1, NULL);", &v, &isNull));122  TEST_ASSERT_TRUE(isNull);123 124  sqlite3_close(db);125}126 127/* Test: user data function pointer is honored (use multiplication) */128static void test_math2Func_user_data_custom(void){129  sqlite3 *db = 0;130  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));131  /* Register tm2 with our own function pointer: multiplication */132  register_tm2(db, (void*)mul2);133 134  double v = 0.0; int isNull = 0;135  TEST_ASSERT_EQUAL_INT(SQLITE_OK, query_single_double(db, "SELECT tm2(3, 4);", &v, &isNull));136  TEST_ASSERT_FALSE(isNull);137  TEST_ASSERT_DOUBLE_WITHIN(1e-12, 12.0, v);138 139  /* Re-register with addition to ensure pointer swap works */140  register_tm2(db, (void*)add2);141  TEST_ASSERT_EQUAL_INT(SQLITE_OK, query_single_double(db, "SELECT tm2(3.5, 4.25);", &v, &isNull));142  TEST_ASSERT_FALSE(isNull);143  TEST_ASSERT_DOUBLE_WITHIN(1e-12, 7.75, v);144 145  sqlite3_close(db);146}147 148/* Test: NaN propagation (e.g., pow(-2, 0.5)) */149static void test_math2Func_pow_nan(void){150  sqlite3 *db = 0;151  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));152  register_tm2(db, (void*)pow);153 154  double v = 0.0; int isNull = 0;155  TEST_ASSERT_EQUAL_INT(SQLITE_OK, query_single_double(db, "SELECT tm2(-2.0, 0.5);", &v, &isNull));156  TEST_ASSERT_FALSE(isNull);157  /* v should be NaN; isnan() returns non-zero for NaN */158  TEST_ASSERT_TRUE(isnan(v));159 160  sqlite3_close(db);161}162 163int main(void){164  UNITY_BEGIN();165  RUN_TEST(test_math2Func_pow_basic);166  RUN_TEST(test_math2Func_text_numeric_coercion);167  RUN_TEST(test_math2Func_non_numeric_args);168  RUN_TEST(test_math2Func_null_args);169  RUN_TEST(test_math2Func_user_data_custom);170  RUN_TEST(test_math2Func_pow_nan);171  return UNITY_END();172}