AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <stdio.h>4#include <string.h>5 6/* Helper to lookup a function definition using SQLite's internal lookup */7static FuncDef *lookupFunc(sqlite3 *db, const char *zName, int nArg){8 return sqlite3FindFunction(db, zName, nArg, SQLITE_UTF8, 0);9}10 11void setUp(void) {12 /* No global setup required */13}14 15void tearDown(void) {16 /* No global teardown required */17}18 19/* Verify that core scalar built-in functions are registered and discoverable */20void test_sqlite3RegisterBuiltinFunctions_core_scalars_registered(void){21 sqlite3 *db = 0;22 int rc = sqlite3_open(":memory:", &db);23 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_open failed");24 sqlite3RegisterBuiltinFunctions();25 26 struct {27 const char *zName;28 int nArg;29 } cases[] = {30 { "length", 1 },31 { "typeof", 1 },32 { "subtype", 1 },33 { "octet_length", 1 },34 { "instr", 2 },35 { "printf", 1 },36 { "printf", 3 },37 { "format", 1 },38 { "format", 3 },39 { "unicode", 1 },40 { "char", 1 },41 { "abs", 1 },42 { "upper", 1 },43 { "lower", 1 },44 { "hex", 1 },45 { "unhex", 1 },46 { "unhex", 2 },47 { "concat", 2 },48 { "concat", 3 },49 { "concat_ws", 3 },50 { "ifnull", 2 },51 { "nullif", 2 },52 { "replace", 3 },53 { "zeroblob", 1 },54 { "substr", 2 },55 { "substr", 3 },56 { "substring", 2 },57 { "substring", 3 },58 { "sign", 1 },59 { "coalesce", 2 },60 { "coalesce", 3 },61 { "iif", 3 },62 { "if", 3 },63 { "trim", 1 },64 { "trim", 2 },65 { "ltrim", 1 },66 { "ltrim", 2 },67 { "rtrim", 1 },68 { "rtrim", 2 },69 { "quote", 1 },70 { "unistr_quote", 1 }71 };72 73 for(unsigned i=0; i<sizeof(cases)/sizeof(cases[0]); i++){74 FuncDef *p = lookupFunc(db, cases[i].zName, cases[i].nArg);75 char msg[200];76 sqlite3_snprintf(sizeof(msg), msg,77 "Function '%s' with %d args not found",78 cases[i].zName, cases[i].nArg);79 TEST_ASSERT_MESSAGE(p!=0, msg);80 81 sqlite3_snprintf(sizeof(msg), msg,82 "Function '%s' found but not marked SQLITE_FUNC_BUILTIN",83 cases[i].zName);84 TEST_ASSERT_TRUE_MESSAGE((p->funcFlags & SQLITE_FUNC_BUILTIN)!=0, msg);85 }86 87 sqlite3_close(db);88}89 90/* Verify that common aggregate/minmax functions are registered */91void test_sqlite3RegisterBuiltinFunctions_aggregates_registered(void){92 sqlite3 *db = 0;93 int rc = sqlite3_open(":memory:", &db);94 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);95 sqlite3RegisterBuiltinFunctions();96 97 struct {98 const char *zName;99 int nArg;100 } cases[] = {101 { "count", 0 },102 { "count", 1 },103 { "sum", 1 },104 { "total", 1 },105 { "avg", 1 },106 { "group_concat", 1 },107 { "group_concat", 2 },108 { "string_agg", 2 },109 { "min", 2 },110 { "max", 2 }111 };112 113 for(unsigned i=0; i<sizeof(cases)/sizeof(cases[0]); i++){114 FuncDef *p = lookupFunc(db, cases[i].zName, cases[i].nArg);115 char msg[200];116 sqlite3_snprintf(sizeof(msg), msg,117 "Aggregate function '%s' with %d args not found",118 cases[i].zName, cases[i].nArg);119 TEST_ASSERT_MESSAGE(p!=0, msg);120 sqlite3_snprintf(sizeof(msg), msg,121 "Aggregate function '%s' not marked SQLITE_FUNC_BUILTIN",122 cases[i].zName);123 TEST_ASSERT_TRUE_MESSAGE((p->funcFlags & SQLITE_FUNC_BUILTIN)!=0, msg);124 }125 126 sqlite3_close(db);127}128 129/* Verify that unknown function lookups fail (createFlag=0) */130void test_sqlite3RegisterBuiltinFunctions_unknown_function_not_found(void){131 sqlite3 *db = 0;132 int rc = sqlite3_open(":memory:", &db);133 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);134 sqlite3RegisterBuiltinFunctions();135 136 const char *unknowns[] = {137 "no_such_function_abc123",138 "definitely_not_builtin_xyz",139 "___made_up___"140 };141 142 for(unsigned i=0; i<sizeof(unknowns)/sizeof(unknowns[0]); i++){143 FuncDef *p = lookupFunc(db, unknowns[i], 1);144 char msg[200];145 sqlite3_snprintf(sizeof(msg), msg,146 "Unknown function '%s' should not be found", unknowns[i]);147 TEST_ASSERT_MESSAGE(p==0, msg);148 }149 150 sqlite3_close(db);151}152 153/* Verify calling the registration routine twice is safe */154void test_sqlite3RegisterBuiltinFunctions_double_registration_safe(void){155 sqlite3 *db = 0;156 int rc = sqlite3_open(":memory:", &db);157 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);158 159 /* First registration */160 sqlite3RegisterBuiltinFunctions();161 FuncDef *p1 = lookupFunc(db, "length", 1);162 TEST_ASSERT_NOT_NULL(p1);163 TEST_ASSERT_TRUE((p1->funcFlags & SQLITE_FUNC_BUILTIN)!=0);164 165 /* Second registration */166 sqlite3RegisterBuiltinFunctions();167 FuncDef *p2 = lookupFunc(db, "length", 1);168 TEST_ASSERT_NOT_NULL(p2);169 TEST_ASSERT_TRUE((p2->funcFlags & SQLITE_FUNC_BUILTIN)!=0);170 171 /* Do not require pointer identity; just ensure still resolvable */172 sqlite3_close(db);173}174 175/* Verify that variable-argument functions are discoverable across arities */176void test_sqlite3RegisterBuiltinFunctions_vararg_lookup(void){177 sqlite3 *db = 0;178 int rc = sqlite3_open(":memory:", &db);179 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);180 sqlite3RegisterBuiltinFunctions();181 182 struct {183 const char *zName;184 int nArgVariants[4];185 int nVariants;186 } varFuncs[] = {187 { "printf", {1, 2, 4}, 3 },188 { "format", {1, 3}, 2 },189 { "concat", {2, 3, 5}, 3 },190 { "coalesce", {2, 3, 4}, 3 },191 };192 193 for(unsigned i=0; i<sizeof(varFuncs)/sizeof(varFuncs[0]); i++){194 for(int j=0; j<varFuncs[i].nVariants; j++){195 int nArg = varFuncs[i].nArgVariants[j];196 FuncDef *p = lookupFunc(db, varFuncs[i].zName, nArg);197 char msg[200];198 sqlite3_snprintf(sizeof(msg), msg,199 "Vararg function '%s' with %d args not found",200 varFuncs[i].zName, nArg);201 TEST_ASSERT_MESSAGE(p!=0, msg);202 sqlite3_snprintf(sizeof(msg), msg,203 "Vararg function '%s' not marked SQLITE_FUNC_BUILTIN",204 varFuncs[i].zName);205 TEST_ASSERT_TRUE_MESSAGE((p->funcFlags & SQLITE_FUNC_BUILTIN)!=0, msg);206 }207 }208 209 sqlite3_close(db);210}211 212/* Main entry point for Unity */213int main(void){214 UNITY_BEGIN();215 RUN_TEST(test_sqlite3RegisterBuiltinFunctions_core_scalars_registered);216 RUN_TEST(test_sqlite3RegisterBuiltinFunctions_aggregates_registered);217 RUN_TEST(test_sqlite3RegisterBuiltinFunctions_unknown_function_not_found);218 RUN_TEST(test_sqlite3RegisterBuiltinFunctions_double_registration_safe);219 RUN_TEST(test_sqlite3RegisterBuiltinFunctions_vararg_lookup);220 return UNITY_END();221}