Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_callback_sqlite3InsertBuiltinFuncs.c199 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4 5/* Save/restore the global builtin functions hash across tests */6static FuncDefHash savedBuiltinFuncs;7 8void setUp(void) {9  /* Save current global and clear it so each test starts from a clean slate */10  savedBuiltinFuncs = sqlite3BuiltinFunctions;11  memset(&sqlite3BuiltinFunctions, 0, sizeof(sqlite3BuiltinFunctions));12}13void tearDown(void) {14  /* Restore original global */15  sqlite3BuiltinFunctions = savedBuiltinFuncs;16}17 18/* Helper to compute the hash bucket like the target function does */19static int bucket_for(const char *zName){20  int nName = sqlite3Strlen30(zName);21  return SQLITE_FUNC_HASH(zName[0], nName);22}23 24/* Minimal no-op scalar function pointer to mark validity if needed */25static void dummy_xSFunc(sqlite3_context *ctx, int argc, sqlite3_value **argv){26  (void)ctx; (void)argc; (void)argv;27}28 29/* Test: insert into empty bucket -> becomes head, pNext==NULL, u.pHash==old head (NULL) */30void test_sqlite3InsertBuiltinFuncs_insert_into_empty_bucket(void){31  FuncDef def;32  memset(&def, 0, sizeof(def));33  def.zName = "abc";34  def.funcFlags = SQLITE_FUNC_BUILTIN;35  def.xSFunc = dummy_xSFunc;36 37  int h = bucket_for(def.zName);38  TEST_ASSERT_NULL(sqlite3BuiltinFunctions.a[h]);39 40  sqlite3InsertBuiltinFuncs(&def, 1);41 42  TEST_ASSERT_EQUAL_PTR(&def, sqlite3BuiltinFunctions.a[h]);43  TEST_ASSERT_NULL(def.pNext);44  TEST_ASSERT_NULL(def.u.pHash);45}46 47/* Test: insert into bucket with different existing name -> new head, u.pHash points to old head */48void test_sqlite3InsertBuiltinFuncs_bucket_collision_new_name_becomes_head(void){49  /* Existing head in same bucket: "abx" length 3 shares bucket with "aby" */50  FuncDef existing;51  memset(&existing, 0, sizeof(existing));52  existing.zName = "abx";53  existing.funcFlags = SQLITE_FUNC_BUILTIN;54  existing.xSFunc = dummy_xSFunc;55 56  int h = bucket_for(existing.zName);57  sqlite3BuiltinFunctions.a[h] = &existing;58  existing.u.pHash = NULL;59  existing.pNext = NULL;60 61  FuncDef newcomer;62  memset(&newcomer, 0, sizeof(newcomer));63  newcomer.zName = "aby"; /* same first char and length => same bucket, different name */64  newcomer.funcFlags = SQLITE_FUNC_BUILTIN;65  newcomer.xSFunc = dummy_xSFunc;66 67  sqlite3InsertBuiltinFuncs(&newcomer, 1);68 69  /* Newcomer should be new bucket head; its u.pHash should point to previous head */70  TEST_ASSERT_EQUAL_PTR(&newcomer, sqlite3BuiltinFunctions.a[h]);71  TEST_ASSERT_EQUAL_PTR(&existing, newcomer.u.pHash);72  TEST_ASSERT_NULL(newcomer.pNext);73 74  /* Existing head remains otherwise unchanged */75  TEST_ASSERT_NULL(existing.u.pHash);76  TEST_ASSERT_NULL(existing.pNext);77}78 79/* Test: insert new variant for an existing name -> splice into pNext chain after head */80void test_sqlite3InsertBuiltinFuncs_insert_variant_into_pNext_chain(void){81  /* Prepare existing head "foo" with one variant in pNext */82  FuncDef head, variant1;83  memset(&head, 0, sizeof(head));84  memset(&variant1, 0, sizeof(variant1));85  head.zName = "foo";86  head.funcFlags = SQLITE_FUNC_BUILTIN;87  head.xSFunc = dummy_xSFunc;88  variant1.zName = "foo";89  variant1.funcFlags = SQLITE_FUNC_BUILTIN;90  variant1.xSFunc = dummy_xSFunc;91 92  head.pNext = &variant1;93  variant1.pNext = NULL;94 95  int h = bucket_for(head.zName);96  sqlite3BuiltinFunctions.a[h] = &head;97  head.u.pHash = NULL;98 99  /* New variant to insert */100  FuncDef newcomer;101  memset(&newcomer, 0, sizeof(newcomer));102  newcomer.zName = "foo";103  newcomer.funcFlags = SQLITE_FUNC_BUILTIN;104  newcomer.xSFunc = dummy_xSFunc;105 106  sqlite3InsertBuiltinFuncs(&newcomer, 1);107 108  /* Newcomer should be spliced immediately after head, before variant1 */109  TEST_ASSERT_EQUAL_PTR(&newcomer, head.pNext);110  TEST_ASSERT_EQUAL_PTR(&variant1, newcomer.pNext);111 112  /* u.pHash should not be modified in this branch */113  TEST_ASSERT_NULL(head.u.pHash);114  /* We do not assert newcomer.u.pHash value (unspecified by API in this branch) */115}116 117/* Test: inserting multiple entries in one call, including two with same name, preserves loop order118   i.e., second insertion for the same name becomes first in the pNext chain after the head. */119void test_sqlite3InsertBuiltinFuncs_multiple_insertions_ordering(void){120  /* Existing head "bar" */121  FuncDef head;122  memset(&head, 0, sizeof(head));123  head.zName = "bar";124  head.funcFlags = SQLITE_FUNC_BUILTIN;125  head.xSFunc = dummy_xSFunc;126  head.pNext = NULL;127  head.u.pHash = NULL;128 129  int h = bucket_for(head.zName);130  sqlite3BuiltinFunctions.a[h] = &head;131 132  /* Two newcomers for the same name "bar" inserted together */133  FuncDef newcomers[2];134  memset(newcomers, 0, sizeof(newcomers));135  newcomers[0].zName = "bar";136  newcomers[0].funcFlags = SQLITE_FUNC_BUILTIN;137  newcomers[0].xSFunc = dummy_xSFunc;138 139  newcomers[1].zName = "bar";140  newcomers[1].funcFlags = SQLITE_FUNC_BUILTIN;141  newcomers[1].xSFunc = dummy_xSFunc;142 143  sqlite3InsertBuiltinFuncs(newcomers, 2);144 145  /* After first insert: head.pNext = newcomers[0]146     After second insert: head.pNext = newcomers[1], newcomers[1].pNext = newcomers[0]147  */148  TEST_ASSERT_EQUAL_PTR(&newcomers[1], head.pNext);149  TEST_ASSERT_EQUAL_PTR(&newcomers[0], newcomers[1].pNext);150  TEST_ASSERT_NULL(newcomers[0].pNext);151}152 153/* Test: mixed insertion, one new name (new bucket head), one variant for existing name */154void test_sqlite3InsertBuiltinFuncs_mixed_new_and_existing_names(void){155  /* Existing head in bucket for "qux" */156  FuncDef quxHead;157  memset(&quxHead, 0, sizeof(quxHead));158  quxHead.zName = "qux";159  quxHead.funcFlags = SQLITE_FUNC_BUILTIN;160  quxHead.xSFunc = dummy_xSFunc;161 162  int h_qux = bucket_for(quxHead.zName);163  sqlite3BuiltinFunctions.a[h_qux] = &quxHead;164 165  /* Another bucket currently empty: "zed" */166  int h_zed = bucket_for("zed");167  TEST_ASSERT_NULL(sqlite3BuiltinFunctions.a[h_zed]);168 169  FuncDef defs[2];170  memset(defs, 0, sizeof(defs));171  defs[0].zName = "qux"; /* variant for existing name */172  defs[0].funcFlags = SQLITE_FUNC_BUILTIN;173  defs[0].xSFunc = dummy_xSFunc;174 175  defs[1].zName = "zed"; /* new name in empty bucket */176  defs[1].funcFlags = SQLITE_FUNC_BUILTIN;177  defs[1].xSFunc = dummy_xSFunc;178 179  sqlite3InsertBuiltinFuncs(defs, 2);180 181  /* Check "qux" got a new variant inserted after head */182  TEST_ASSERT_EQUAL_PTR(&defs[0], quxHead.pNext);183  TEST_ASSERT_NULL(defs[0].pNext);184 185  /* Check "zed" became new head of its (previously empty) bucket */186  TEST_ASSERT_EQUAL_PTR(&defs[1], sqlite3BuiltinFunctions.a[h_zed]);187  TEST_ASSERT_NULL(defs[1].u.pHash);188  TEST_ASSERT_NULL(defs[1].pNext);189}190 191int main(void){192  UNITY_BEGIN();193  RUN_TEST(test_sqlite3InsertBuiltinFuncs_insert_into_empty_bucket);194  RUN_TEST(test_sqlite3InsertBuiltinFuncs_bucket_collision_new_name_becomes_head);195  RUN_TEST(test_sqlite3InsertBuiltinFuncs_insert_variant_into_pNext_chain);196  RUN_TEST(test_sqlite3InsertBuiltinFuncs_multiple_insertions_ordering);197  RUN_TEST(test_sqlite3InsertBuiltinFuncs_mixed_new_and_existing_names);198  return UNITY_END();199}