AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5#include <math.h>6 7/* External wrapper for the static function under test */8extern void test_logFunc(sqlite3_context *context, int argc, sqlite3_value **argv);9 10/* Global database handle for allocating sqlite3_value/Mem */11static sqlite3 *gdb = NULL;12 13/* Helper: initialize a sqlite3_context with given userData and fresh pOut Mem */14static void init_context(sqlite3_context *ctx, FuncDef *fd, void *userData, Mem **ppOut){15 memset(ctx, 0, sizeof(*ctx));16 memset(fd, 0, sizeof(*fd));17 fd->pUserData = userData;18 19 Mem *pOut = sqlite3ValueNew(gdb);20 TEST_ASSERT_NOT_NULL(pOut);21 sqlite3VdbeMemSetNull(pOut);22 23 ctx->pFunc = fd;24 ctx->pOut = pOut;25 ctx->pMem = 0;26 ctx->pVdbe = 0;27 ctx->isError = 0;28 ctx->pColl = 0;29 ctx->skipFlag = 0;30 31 *ppOut = pOut;32}33 34/* Helpers: create sqlite3_value of different types */35static sqlite3_value* make_double_val(double d){36 Mem *v = sqlite3ValueNew(gdb);37 TEST_ASSERT_NOT_NULL(v);38 sqlite3VdbeMemSetDouble(v, d);39 return (sqlite3_value*)v;40}41static sqlite3_value* make_int_val(sqlite3_int64 i){42 Mem *v = sqlite3ValueNew(gdb);43 TEST_ASSERT_NOT_NULL(v);44 sqlite3VdbeMemSetInt64(v, i);45 return (sqlite3_value*)v;46}47static sqlite3_value* make_text_val(const char *z){48 Mem *v = sqlite3ValueNew(gdb);49 TEST_ASSERT_NOT_NULL(v);50 sqlite3VdbeMemSetStr(v, z, -1, SQLITE_UTF8, SQLITE_TRANSIENT);51 return (sqlite3_value*)v;52}53 54/* Helper: free sqlite3_value (Mem) */55static void free_val(sqlite3_value *v){56 if(v){57 sqlite3ValueFree((Mem*)v);58 }59}60 61/* Unity fixtures */62void setUp(void) {63 int rc = sqlite3_open(":memory:", &gdb);64 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);65 TEST_ASSERT_NOT_NULL(gdb);66}67void tearDown(void) {68 if(gdb){69 sqlite3_close(gdb);70 gdb = NULL;71 }72}73 74/* Tests */75 76void test_logFunc_ln_of_e_is_1(void){77 sqlite3_context ctx;78 FuncDef fd;79 Mem *pOut = NULL;80 init_context(&ctx, &fd, SQLITE_INT_TO_PTR(0), &pOut);81 82 sqlite3_value *argv[1];83 argv[0] = make_double_val(exp(1.0)); /* e */84 85 test_logFunc(&ctx, 1, argv);86 87 TEST_ASSERT_FALSE(pOut->flags & MEM_Null);88 TEST_ASSERT_TRUE(pOut->flags & MEM_Real);89 double got = sqlite3_value_double((sqlite3_value*)pOut);90 TEST_ASSERT_DOUBLE_WITHIN(1e-12, 1.0, got);91 92 free_val(argv[0]);93 sqlite3ValueFree(pOut);94}95 96void test_logFunc_log10_of_1000_is_3(void){97 sqlite3_context ctx;98 FuncDef fd;99 Mem *pOut = NULL;100 init_context(&ctx, &fd, SQLITE_INT_TO_PTR(1), &pOut); /* log10 */101 102 sqlite3_value *argv[1];103 argv[0] = make_int_val(1000);104 105 test_logFunc(&ctx, 1, argv);106 107 TEST_ASSERT_FALSE(pOut->flags & MEM_Null);108 double got = sqlite3_value_double((sqlite3_value*)pOut);109 TEST_ASSERT_DOUBLE_WITHIN(1e-12, 3.0, got);110 111 free_val(argv[0]);112 sqlite3ValueFree(pOut);113}114 115void test_logFunc_log2_of_8_is_3(void){116 sqlite3_context ctx;117 FuncDef fd;118 Mem *pOut = NULL;119 init_context(&ctx, &fd, SQLITE_INT_TO_PTR(2), &pOut); /* log2 */120 121 sqlite3_value *argv[1];122 argv[0] = make_int_val(8);123 124 test_logFunc(&ctx, 1, argv);125 126 TEST_ASSERT_FALSE(pOut->flags & MEM_Null);127 double got = sqlite3_value_double((sqlite3_value*)pOut);128 TEST_ASSERT_DOUBLE_WITHIN(1e-12, 3.0, got);129 130 free_val(argv[0]);131 sqlite3ValueFree(pOut);132}133 134void test_logFunc_one_arg_negative_returns_null(void){135 sqlite3_context ctx;136 FuncDef fd;137 Mem *pOut = NULL;138 init_context(&ctx, &fd, SQLITE_INT_TO_PTR(0), &pOut);139 140 sqlite3_value *argv[1];141 argv[0] = make_int_val(-5);142 143 test_logFunc(&ctx, 1, argv);144 145 TEST_ASSERT_TRUE(pOut->flags & MEM_Null);146 147 free_val(argv[0]);148 sqlite3ValueFree(pOut);149}150 151void test_logFunc_one_arg_zero_returns_null(void){152 sqlite3_context ctx;153 FuncDef fd;154 Mem *pOut = NULL;155 init_context(&ctx, &fd, SQLITE_INT_TO_PTR(1), &pOut); /* log10 variant */156 157 sqlite3_value *argv[1];158 argv[0] = make_int_val(0);159 160 test_logFunc(&ctx, 1, argv);161 162 TEST_ASSERT_TRUE(pOut->flags & MEM_Null);163 164 free_val(argv[0]);165 sqlite3ValueFree(pOut);166}167 168void test_logFunc_two_arg_log_base10_100_returns_2(void){169 sqlite3_context ctx;170 FuncDef fd;171 Mem *pOut = NULL;172 init_context(&ctx, &fd, NULL, &pOut); /* user_data ignored for 2-arg */173 174 sqlite3_value *argv[2];175 argv[0] = make_int_val(10); /* base */176 argv[1] = make_int_val(100); /* X */177 178 test_logFunc(&ctx, 2, argv);179 180 TEST_ASSERT_FALSE(pOut->flags & MEM_Null);181 double got = sqlite3_value_double((sqlite3_value*)pOut);182 TEST_ASSERT_DOUBLE_WITHIN(1e-12, 2.0, got);183 184 free_val(argv[0]);185 free_val(argv[1]);186 sqlite3ValueFree(pOut);187}188 189void test_logFunc_two_arg_base_e_and_e3_returns_3(void){190 sqlite3_context ctx;191 FuncDef fd;192 Mem *pOut = NULL;193 init_context(&ctx, &fd, NULL, &pOut);194 195 double base = exp(1.0);196 double x = exp(3.0);197 198 sqlite3_value *argv[2];199 argv[0] = make_double_val(base);200 argv[1] = make_double_val(x);201 202 test_logFunc(&ctx, 2, argv);203 204 TEST_ASSERT_FALSE(pOut->flags & MEM_Null);205 double got = sqlite3_value_double((sqlite3_value*)pOut);206 TEST_ASSERT_DOUBLE_WITHIN(1e-12, 3.0, got);207 208 free_val(argv[0]);209 free_val(argv[1]);210 sqlite3ValueFree(pOut);211}212 213void test_logFunc_two_arg_invalid_base_one_returns_null(void){214 sqlite3_context ctx;215 FuncDef fd;216 Mem *pOut = NULL;217 init_context(&ctx, &fd, NULL, &pOut);218 219 sqlite3_value *argv[2];220 argv[0] = make_int_val(1); /* base = 1 -> ln(base)=0 -> NULL */221 argv[1] = make_int_val(123);222 223 test_logFunc(&ctx, 2, argv);224 225 TEST_ASSERT_TRUE(pOut->flags & MEM_Null);226 227 free_val(argv[0]);228 free_val(argv[1]);229 sqlite3ValueFree(pOut);230}231 232void test_logFunc_two_arg_invalid_base_between0and1_returns_null(void){233 sqlite3_context ctx;234 FuncDef fd;235 Mem *pOut = NULL;236 init_context(&ctx, &fd, NULL, &pOut);237 238 sqlite3_value *argv[2];239 argv[0] = make_double_val(0.5); /* ln(0.5) < 0 -> NULL */240 argv[1] = make_int_val(10);241 242 test_logFunc(&ctx, 2, argv);243 244 TEST_ASSERT_TRUE(pOut->flags & MEM_Null);245 246 free_val(argv[0]);247 free_val(argv[1]);248 sqlite3ValueFree(pOut);249}250 251void test_logFunc_two_arg_negative_x_returns_null(void){252 sqlite3_context ctx;253 FuncDef fd;254 Mem *pOut = NULL;255 init_context(&ctx, &fd, NULL, &pOut);256 257 sqlite3_value *argv[2];258 argv[0] = make_int_val(2); /* valid base */259 argv[1] = make_int_val(-4); /* invalid X */260 261 test_logFunc(&ctx, 2, argv);262 263 TEST_ASSERT_TRUE(pOut->flags & MEM_Null);264 265 free_val(argv[0]);266 free_val(argv[1]);267 sqlite3ValueFree(pOut);268}269 270void test_logFunc_two_arg_non_numeric_first_arg_returns_null(void){271 sqlite3_context ctx;272 FuncDef fd;273 Mem *pOut = NULL;274 init_context(&ctx, &fd, NULL, &pOut);275 276 sqlite3_value *argv[2];277 argv[0] = make_text_val("abc"); /* non-numeric base */278 argv[1] = make_int_val(100);279 280 test_logFunc(&ctx, 2, argv);281 282 TEST_ASSERT_TRUE(pOut->flags & MEM_Null);283 284 free_val(argv[0]);285 free_val(argv[1]);286 sqlite3ValueFree(pOut);287}288 289void test_logFunc_one_arg_string_numeric_works(void){290 sqlite3_context ctx;291 FuncDef fd;292 Mem *pOut = NULL;293 init_context(&ctx, &fd, SQLITE_INT_TO_PTR(1), &pOut); /* log10 */294 295 sqlite3_value *argv[1];296 argv[0] = make_text_val("1000"); /* numeric string */297 298 test_logFunc(&ctx, 1, argv);299 300 TEST_ASSERT_FALSE(pOut->flags & MEM_Null);301 double got = sqlite3_value_double((sqlite3_value*)pOut);302 TEST_ASSERT_DOUBLE_WITHIN(1e-12, 3.0, got);303 304 free_val(argv[0]);305 sqlite3ValueFree(pOut);306}307 308void test_logFunc_two_arg_string_numeric_works(void){309 sqlite3_context ctx;310 FuncDef fd;311 Mem *pOut = NULL;312 init_context(&ctx, &fd, NULL, &pOut);313 314 sqlite3_value *argv[2];315 argv[0] = make_text_val("10"); /* base as numeric string */316 argv[1] = make_text_val("1000"); /* X as numeric string */317 318 test_logFunc(&ctx, 2, argv);319 320 TEST_ASSERT_FALSE(pOut->flags & MEM_Null);321 double got = sqlite3_value_double((sqlite3_value*)pOut);322 TEST_ASSERT_DOUBLE_WITHIN(1e-12, 3.0, got);323 324 free_val(argv[0]);325 free_val(argv[1]);326 sqlite3ValueFree(pOut);327}328 329int main(void){330 UNITY_BEGIN();331 RUN_TEST(test_logFunc_ln_of_e_is_1);332 RUN_TEST(test_logFunc_log10_of_1000_is_3);333 RUN_TEST(test_logFunc_log2_of_8_is_3);334 RUN_TEST(test_logFunc_one_arg_negative_returns_null);335 RUN_TEST(test_logFunc_one_arg_zero_returns_null);336 RUN_TEST(test_logFunc_two_arg_log_base10_100_returns_2);337 RUN_TEST(test_logFunc_two_arg_base_e_and_e3_returns_3);338 RUN_TEST(test_logFunc_two_arg_invalid_base_one_returns_null);339 RUN_TEST(test_logFunc_two_arg_invalid_base_between0and1_returns_null);340 RUN_TEST(test_logFunc_two_arg_negative_x_returns_null);341 RUN_TEST(test_logFunc_two_arg_non_numeric_first_arg_returns_null);342 RUN_TEST(test_logFunc_one_arg_string_numeric_works);343 RUN_TEST(test_logFunc_two_arg_string_numeric_works);344 return UNITY_END();345}