Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_notify_sqlite3ConnectionUnlocked.c297 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY7 8/* Global callback trackers */9static int cbA_calls;10static int cbA_last_n;11static int cbA_total_args;12static void* cbA_args[1024];13 14static int cbB_calls;15static int cbB_last_n;16static int cbB_total_args;17static void* cbB_args[1024];18 19/* Sequence log to verify callback group order (e.g., 'A', then 'B') */20static char cbLog[64];21static int cbLogLen;22 23static void cbA(void **apArg, int nArg){24  int i;25  for(i=0; i<nArg; i++){26    if (cbA_total_args < (int)(sizeof(cbA_args)/sizeof(cbA_args[0]))){27      cbA_args[cbA_total_args++] = apArg[i];28    }29  }30  cbA_last_n = nArg;31  cbA_calls++;32  if (cbLogLen < (int)sizeof(cbLog)) cbLog[cbLogLen++] = 'A';33}34 35static void cbB(void **apArg, int nArg){36  int i;37  for(i=0; i<nArg; i++){38    if (cbB_total_args < (int)(sizeof(cbB_args)/sizeof(cbB_args[0]))){39      cbB_args[cbB_total_args++] = apArg[i];40    }41  }42  cbB_last_n = nArg;43  cbB_calls++;44  if (cbLogLen < (int)sizeof(cbLog)) cbLog[cbLogLen++] = 'B';45}46 47static sqlite3* open_memdb(void){48  sqlite3 *db = 0;49  int rc = sqlite3_open(":memory:", &db);50  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);51  TEST_ASSERT_NOT_NULL(db);52  return db;53}54 55static void close_db(sqlite3 *db){56  /* Ensure notify module is clean for this db before closing */57  sqlite3ConnectionClosed(db);58  int rc = sqlite3_close(db);59  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);60}61 62static int contains_ptr(void **arr, int n, void *p){63  int i;64  for(i=0;i<n;i++){65    if(arr[i]==p) return 1;66  }67  return 0;68}69 70void setUp(void) {71  /* Reset callback trackers */72  cbA_calls = cbA_last_n = cbA_total_args = 0;73  cbB_calls = cbB_last_n = cbB_total_args = 0;74  cbLogLen = 0;75 76  /* Explicit initialization (also done implicitly by sqlite3_open) */77  sqlite3_initialize();78}79 80void tearDown(void) {81  /* Nothing to clean here; each test closes its dbs */82}83 84/* Test 1: Clearing a block without any registered notify. */85void test_sqlite3ConnectionUnlocked_clears_blocking_without_notify(void){86  sqlite3 *db1 = open_memdb();87  sqlite3 *db2 = open_memdb();88 89  sqlite3ConnectionBlocked(db1, db2);90 91  TEST_ASSERT_EQUAL_PTR(db2, db1->pBlockingConnection);92  TEST_ASSERT_NULL(db1->pUnlockConnection);93  TEST_ASSERT_EQUAL_PTR(NULL, db1->xUnlockNotify);94 95  sqlite3ConnectionUnlocked(db2);96 97  /* No callbacks should have been invoked */98  TEST_ASSERT_EQUAL_INT(0, cbA_calls);99  TEST_ASSERT_EQUAL_INT(0, cbB_calls);100 101  /* Entry should be cleared and removed from list */102  TEST_ASSERT_NULL(db1->pBlockingConnection);103  TEST_ASSERT_NULL(db1->pUnlockConnection);104  TEST_ASSERT_EQUAL_PTR(NULL, db1->xUnlockNotify);105  TEST_ASSERT_EQUAL_PTR(NULL, db1->pUnlockArg);106  TEST_ASSERT_NULL(db1->pNextBlocked);107 108  close_db(db1);109  close_db(db2);110}111 112/* Test 2: Single blocked connection with notify registered -> single callback. */113void test_sqlite3ConnectionUnlocked_single_notify(void){114  sqlite3 *blocker = open_memdb();115  sqlite3 *db1 = open_memdb();116 117  int arg1 = 0x11;118 119  sqlite3ConnectionBlocked(db1, blocker);120  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_unlock_notify(db1, cbA, &arg1));121 122  /* Should not have been called yet */123  TEST_ASSERT_EQUAL_INT(0, cbA_calls);124 125  sqlite3ConnectionUnlocked(blocker);126 127  TEST_ASSERT_EQUAL_INT(1, cbA_calls);128  TEST_ASSERT_EQUAL_INT(1, cbA_last_n);129  TEST_ASSERT_EQUAL_INT(1, cbA_total_args);130  TEST_ASSERT_EQUAL_PTR(&arg1, cbA_args[0]);131 132  /* Entry should be cleared and removed */133  TEST_ASSERT_NULL(db1->pBlockingConnection);134  TEST_ASSERT_NULL(db1->pUnlockConnection);135  TEST_ASSERT_EQUAL_PTR(NULL, db1->xUnlockNotify);136  TEST_ASSERT_EQUAL_PTR(NULL, db1->pUnlockArg);137  TEST_ASSERT_NULL(db1->pNextBlocked);138 139  close_db(db1);140  close_db(blocker);141}142 143/* Test 3: Multiple listeners using the same callback are grouped into a single notification. */144void test_sqlite3ConnectionUnlocked_group_same_callback_once(void){145  sqlite3 *blocker = open_memdb();146 147  const int N = 5;148  sqlite3 *dbs[N];149  int args[N];150  int i;151 152  for(i=0;i<N;i++){153    dbs[i] = open_memdb();154    args[i] = 100 + i;155    sqlite3ConnectionBlocked(dbs[i], blocker);156    TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_unlock_notify(dbs[i], cbA, &args[i]));157  }158 159  sqlite3ConnectionUnlocked(blocker);160 161  TEST_ASSERT_EQUAL_INT(1, cbA_calls);162  TEST_ASSERT_EQUAL_INT(N, cbA_total_args);163  TEST_ASSERT_EQUAL_INT(N, cbA_last_n);164 165  for(i=0;i<N;i++){166    TEST_ASSERT_TRUE( contains_ptr(cbA_args, cbA_total_args, &args[i]) );167    TEST_ASSERT_NULL(dbs[i]->pBlockingConnection);168    TEST_ASSERT_NULL(dbs[i]->pUnlockConnection);169    TEST_ASSERT_EQUAL_PTR(NULL, dbs[i]->xUnlockNotify);170    TEST_ASSERT_EQUAL_PTR(NULL, dbs[i]->pUnlockArg);171    TEST_ASSERT_NULL(dbs[i]->pNextBlocked);172  }173 174  for(i=0;i<N;i++){175    close_db(dbs[i]);176  }177  close_db(blocker);178}179 180/* Test 4: Two distinct callback groups are invoked in order (A group, then B group). */181void test_sqlite3ConnectionUnlocked_two_groups_in_order(void){182  sqlite3 *blocker = open_memdb();183 184  sqlite3 *a1 = open_memdb();185  sqlite3 *b1 = open_memdb();186  sqlite3 *a2 = open_memdb();187  sqlite3 *b2 = open_memdb();188 189  int argA1 = 201, argA2 = 202;190  int argB1 = 301, argB2 = 302;191 192  /* Interleaved registration to create A-group then B-group in list order */193  sqlite3ConnectionBlocked(a1, blocker);194  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_unlock_notify(a1, cbA, &argA1));195 196  sqlite3ConnectionBlocked(b1, blocker);197  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_unlock_notify(b1, cbB, &argB1));198 199  sqlite3ConnectionBlocked(a2, blocker);200  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_unlock_notify(a2, cbA, &argA2));201 202  sqlite3ConnectionBlocked(b2, blocker);203  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_unlock_notify(b2, cbB, &argB2));204 205  sqlite3ConnectionUnlocked(blocker);206 207  /* Expect A group callback once, then B group callback once */208  TEST_ASSERT_EQUAL_INT(1, cbA_calls);209  TEST_ASSERT_EQUAL_INT(1, cbB_calls);210  TEST_ASSERT_EQUAL_INT(2, cbA_last_n);211  TEST_ASSERT_EQUAL_INT(2, cbB_last_n);212  TEST_ASSERT_EQUAL_INT(2, cbA_total_args);213  TEST_ASSERT_EQUAL_INT(2, cbB_total_args);214 215  TEST_ASSERT_TRUE( contains_ptr(cbA_args, cbA_total_args, &argA1) );216  TEST_ASSERT_TRUE( contains_ptr(cbA_args, cbA_total_args, &argA2) );217  TEST_ASSERT_TRUE( contains_ptr(cbB_args, cbB_total_args, &argB1) );218  TEST_ASSERT_TRUE( contains_ptr(cbB_args, cbB_total_args, &argB2) );219 220  /* Verify order of group callbacks: 'A' then 'B' */221  TEST_ASSERT_EQUAL_INT(2, cbLogLen);222  TEST_ASSERT_EQUAL_CHAR('A', cbLog[0]);223  TEST_ASSERT_EQUAL_CHAR('B', cbLog[1]);224 225  /* All entries should be cleared and removed */226  TEST_ASSERT_NULL(a1->pBlockingConnection); TEST_ASSERT_NULL(a1->pUnlockConnection); TEST_ASSERT_NULL(a1->xUnlockNotify); TEST_ASSERT_NULL(a1->pUnlockArg); TEST_ASSERT_NULL(a1->pNextBlocked);227  TEST_ASSERT_NULL(a2->pBlockingConnection); TEST_ASSERT_NULL(a2->pUnlockConnection); TEST_ASSERT_NULL(a2->xUnlockNotify); TEST_ASSERT_NULL(a2->pUnlockArg); TEST_ASSERT_NULL(a2->pNextBlocked);228  TEST_ASSERT_NULL(b1->pBlockingConnection); TEST_ASSERT_NULL(b1->pUnlockConnection); TEST_ASSERT_NULL(b1->xUnlockNotify); TEST_ASSERT_NULL(b1->pUnlockArg); TEST_ASSERT_NULL(b1->pNextBlocked);229  TEST_ASSERT_NULL(b2->pBlockingConnection); TEST_ASSERT_NULL(b2->pUnlockConnection); TEST_ASSERT_NULL(b2->xUnlockNotify); TEST_ASSERT_NULL(b2->pUnlockArg); TEST_ASSERT_NULL(b2->pNextBlocked);230 231  close_db(a1); close_db(a2); close_db(b1); close_db(b2);232  close_db(blocker);233}234 235/* Test 5: Many listeners (>16) with same callback to exercise dynamic array growth path. */236void test_sqlite3ConnectionUnlocked_dynamic_growth_many_listeners(void){237  sqlite3 *blocker = open_memdb();238 239  const int M = 25; /* > 16 to exceed aStatic[] size in sqlite3ConnectionUnlocked */240  sqlite3 *dbs[M];241  int args[M];242  int i;243 244  for(i=0;i<M;i++){245    dbs[i] = open_memdb();246    args[i] = 400 + i;247    sqlite3ConnectionBlocked(dbs[i], blocker);248    TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_unlock_notify(dbs[i], cbA, &args[i]));249  }250 251  sqlite3ConnectionUnlocked(blocker);252 253  TEST_ASSERT_EQUAL_INT(1, cbA_calls);254  TEST_ASSERT_EQUAL_INT(M, cbA_total_args);255  TEST_ASSERT_EQUAL_INT(M, cbA_last_n);256 257  for(i=0;i<M;i++){258    TEST_ASSERT_TRUE( contains_ptr(cbA_args, cbA_total_args, &args[i]) );259    TEST_ASSERT_NULL(dbs[i]->pBlockingConnection);260    TEST_ASSERT_NULL(dbs[i]->pUnlockConnection);261    TEST_ASSERT_EQUAL_PTR(NULL, dbs[i]->xUnlockNotify);262    TEST_ASSERT_EQUAL_PTR(NULL, dbs[i]->pUnlockArg);263    TEST_ASSERT_NULL(dbs[i]->pNextBlocked);264  }265 266  for(i=0;i<M;i++){267    close_db(dbs[i]);268  }269  close_db(blocker);270}271 272int main(void){273  UNITY_BEGIN();274  RUN_TEST(test_sqlite3ConnectionUnlocked_clears_blocking_without_notify);275  RUN_TEST(test_sqlite3ConnectionUnlocked_single_notify);276  RUN_TEST(test_sqlite3ConnectionUnlocked_group_same_callback_once);277  RUN_TEST(test_sqlite3ConnectionUnlocked_two_groups_in_order);278  RUN_TEST(test_sqlite3ConnectionUnlocked_dynamic_growth_many_listeners);279  return UNITY_END();280}281 282#else /* SQLITE_ENABLE_UNLOCK_NOTIFY not defined */283 284void setUp(void) {}285void tearDown(void) {}286 287void test_unlock_notify_feature_not_enabled(void){288  TEST_IGNORE_MESSAGE("SQLITE_ENABLE_UNLOCK_NOTIFY not enabled in this build.");289}290 291int main(void){292  UNITY_BEGIN();293  RUN_TEST(test_unlock_notify_feature_not_enabled);294  return UNITY_END();295}296 297#endif /* SQLITE_ENABLE_UNLOCK_NOTIFY */