AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5#include <stdint.h>6 7/* Wrapper for the static function under test (provided by module) */8extern void test_nullifFunc(sqlite3_context *context, int NotUsed, sqlite3_value **argv);9 10/* Global database handle for tests */11static sqlite3 *gDb = NULL;12 13/* Unity setup/teardown */14void setUp(void) {15 int rc = sqlite3_open(":memory:", &gDb);16 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);17 TEST_ASSERT_NOT_NULL(gDb);18}19void tearDown(void) {20 if (gDb) {21 sqlite3_close(gDb);22 gDb = NULL;23 }24}25 26/* Helpers to create sqlite3_value instances */27static sqlite3_value *make_int(i64 v){28 sqlite3_value *p = sqlite3ValueNew(gDb);29 TEST_ASSERT_NOT_NULL(p);30 sqlite3VdbeMemSetInt64((Mem*)p, v);31 return p;32}33static sqlite3_value *make_double(double v){34 sqlite3_value *p = sqlite3ValueNew(gDb);35 TEST_ASSERT_NOT_NULL(p);36 sqlite3VdbeMemSetDouble((Mem*)p, v);37 return p;38}39static sqlite3_value *make_text(const char *z){40 sqlite3_value *p = sqlite3ValueNew(gDb);41 TEST_ASSERT_NOT_NULL(p);42 /* SQLITE_TRANSIENT forces an owned copy inside the Mem */43 sqlite3VdbeMemSetStr((Mem*)p, z, -1, SQLITE_UTF8, SQLITE_TRANSIENT);44 return p;45}46static sqlite3_value *make_null(void){47 sqlite3_value *p = sqlite3ValueNew(gDb);48 TEST_ASSERT_NOT_NULL(p);49 sqlite3VdbeMemSetNull((Mem*)p);50 return p;51}52 53/* Helper to initialize a sqlite3_context and call test_nullifFunc */54static void call_nullif_with_coll(CollSeq *pColl, sqlite3_value *a, sqlite3_value *b, Mem *pOut){55 sqlite3_context ctx;56 memset(&ctx, 0, sizeof(ctx));57 ctx.db = gDb;58 ctx.pColl = pColl;59 ctx.pOut = pOut;60 61 sqlite3VdbeMemInit(pOut, gDb, 0);62 sqlite3VdbeMemSetNull(pOut);63 64 sqlite3_value *argv[2];65 argv[0] = a;66 argv[1] = b;67 68 test_nullifFunc(&ctx, 2, argv);69}70 71/* Convenience to fetch a built-in collation */72static CollSeq* get_collation(const char *name){73 CollSeq *p = sqlite3FindCollSeq(gDb, SQLITE_UTF8, name, 0);74 TEST_ASSERT_NOT_NULL_MESSAGE(p, "Built-in collation not found");75 return p;76}77 78/* Assertions */79static void assert_mem_is_null(const Mem *p){80 TEST_ASSERT_NOT_NULL(p);81 TEST_ASSERT_TRUE_MESSAGE((p->flags & MEM_Null)!=0, "Expected NULL result");82}83static void assert_mem_is_int_value(const Mem *p, i64 v){84 TEST_ASSERT_NOT_NULL(p);85 TEST_ASSERT_TRUE_MESSAGE((p->flags & MEM_Int)!=0, "Expected integer result");86 TEST_ASSERT_EQUAL_INT64(v, p->u.i);87}88static void assert_mem_is_text_equals(const Mem *p, const char *expect){89 TEST_ASSERT_NOT_NULL(p);90 TEST_ASSERT_TRUE_MESSAGE((p->flags & MEM_Str)!=0, "Expected text result");91 const unsigned char *z = sqlite3_value_text((const sqlite3_value*)p);92 TEST_ASSERT_NOT_NULL(z);93 TEST_ASSERT_EQUAL_STRING(expect, (const char*)z);94}95 96/* Tests */97 98/* x=5, y=5 -> equal -> result is NULL */99void test_nullifFunc_equal_int_returns_null(void){100 sqlite3_value *x = make_int(5);101 sqlite3_value *y = make_int(5);102 CollSeq *bin = get_collation("BINARY");103 Mem out;104 call_nullif_with_coll(bin, x, y, &out);105 106 assert_mem_is_null(&out);107 108 sqlite3VdbeMemRelease(&out);109 sqlite3ValueFree(x);110 sqlite3ValueFree(y);111}112 113/* x=5, y=6 -> not equal -> result is x (5) */114void test_nullifFunc_unequal_int_returns_x(void){115 sqlite3_value *x = make_int(5);116 sqlite3_value *y = make_int(6);117 CollSeq *bin = get_collation("BINARY");118 Mem out;119 call_nullif_with_coll(bin, x, y, &out);120 121 assert_mem_is_int_value(&out, 5);122 123 sqlite3VdbeMemRelease(&out);124 sqlite3ValueFree(x);125 sqlite3ValueFree(y);126}127 128/* x=NULL, y=6 -> not equal -> result is x (NULL) */129void test_nullifFunc_xnull_ynonnull_returns_null(void){130 sqlite3_value *x = make_null();131 sqlite3_value *y = make_int(6);132 CollSeq *bin = get_collation("BINARY");133 Mem out;134 call_nullif_with_coll(bin, x, y, &out);135 136 assert_mem_is_null(&out);137 138 sqlite3VdbeMemRelease(&out);139 sqlite3ValueFree(x);140 sqlite3ValueFree(y);141}142 143/* x=6, y=NULL -> not equal -> result is x (6) */144void test_nullifFunc_xnonnull_ynull_returns_x(void){145 sqlite3_value *x = make_int(6);146 sqlite3_value *y = make_null();147 CollSeq *bin = get_collation("BINARY");148 Mem out;149 call_nullif_with_coll(bin, x, y, &out);150 151 assert_mem_is_int_value(&out, 6);152 153 sqlite3VdbeMemRelease(&out);154 sqlite3ValueFree(x);155 sqlite3ValueFree(y);156}157 158/* Strings "abc" vs "ABC" with BINARY collation (case-sensitive) -> not equal -> result is "abc" */159void test_nullifFunc_strings_binary_case_diff_returns_x(void){160 sqlite3_value *x = make_text("abc");161 sqlite3_value *y = make_text("ABC");162 CollSeq *bin = get_collation("BINARY");163 Mem out;164 call_nullif_with_coll(bin, x, y, &out);165 166 assert_mem_is_text_equals(&out, "abc");167 168 sqlite3VdbeMemRelease(&out);169 sqlite3ValueFree(x);170 sqlite3ValueFree(y);171}172 173/* Strings "abc" vs "ABC" with NOCASE collation -> equal -> result is NULL */174void test_nullifFunc_strings_nocase_equal_returns_null(void){175 sqlite3_value *x = make_text("abc");176 sqlite3_value *y = make_text("ABC");177 CollSeq *nocase = get_collation("NOCASE");178 Mem out;179 call_nullif_with_coll(nocase, x, y, &out);180 181 assert_mem_is_null(&out);182 183 sqlite3VdbeMemRelease(&out);184 sqlite3ValueFree(x);185 sqlite3ValueFree(y);186}187 188/* Strings "abc " vs "abc" with RTRIM collation -> equal (ignoring trailing spaces) -> result is NULL */189void test_nullifFunc_strings_rtrim_trailing_space_equal_returns_null(void){190 sqlite3_value *x = make_text("abc ");191 sqlite3_value *y = make_text("abc");192 CollSeq *rtrim = get_collation("RTRIM");193 Mem out;194 call_nullif_with_coll(rtrim, x, y, &out);195 196 assert_mem_is_null(&out);197 198 sqlite3VdbeMemRelease(&out);199 sqlite3ValueFree(x);200 sqlite3ValueFree(y);201}202 203/* Numeric equality across types: x=5 (int), y=5.0 (double) -> equal -> result is NULL */204void test_nullifFunc_integer_double_numerically_equal_returns_null(void){205 sqlite3_value *x = make_int(5);206 sqlite3_value *y = make_double(5.0);207 CollSeq *bin = get_collation("BINARY");208 Mem out;209 call_nullif_with_coll(bin, x, y, &out);210 211 assert_mem_is_null(&out);212 213 sqlite3VdbeMemRelease(&out);214 sqlite3ValueFree(x);215 sqlite3ValueFree(y);216}217 218/* Equality for identical strings under BINARY -> NULL */219void test_nullifFunc_strings_identical_binary_returns_null(void){220 sqlite3_value *x = make_text("same");221 sqlite3_value *y = make_text("same");222 CollSeq *bin = get_collation("BINARY");223 Mem out;224 call_nullif_with_coll(bin, x, y, &out);225 226 assert_mem_is_null(&out);227 228 sqlite3VdbeMemRelease(&out);229 sqlite3ValueFree(x);230 sqlite3ValueFree(y);231}232 233int main(void){234 UNITY_BEGIN();235 RUN_TEST(test_nullifFunc_equal_int_returns_null);236 RUN_TEST(test_nullifFunc_unequal_int_returns_x);237 RUN_TEST(test_nullifFunc_xnull_ynonnull_returns_null);238 RUN_TEST(test_nullifFunc_xnonnull_ynull_returns_x);239 RUN_TEST(test_nullifFunc_strings_binary_case_diff_returns_x);240 RUN_TEST(test_nullifFunc_strings_nocase_equal_returns_null);241 RUN_TEST(test_nullifFunc_strings_rtrim_trailing_space_equal_returns_null);242 RUN_TEST(test_nullifFunc_integer_double_numerically_equal_returns_null);243 RUN_TEST(test_nullifFunc_strings_identical_binary_returns_null);244 return UNITY_END();245}