Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_build_sqlite3TableLock.c230 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdio.h>4#include <string.h>5#include <stdlib.h>6 7/* Helper: initialize a Parse struct with a given db */8static void initParse(Parse *p, sqlite3 *db){9  memset(p, 0, sizeof(*p));10  p->db = db;11}12 13/* Helper: open a database with shared cache enabled and return whether14** the main btree is sharable. Uses a URI filename with cache=shared.15*/16static int open_shared_db(sqlite3 **ppDb, const char *fname){17  int rc;18  char uri[256];19  sqlite3_enable_shared_cache(1);20  snprintf(uri, sizeof(uri), "file:%s?cache=shared&mode=rwc", fname);21  rc = sqlite3_open_v2(uri, ppDb,22        SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_URI, 0);23  if( rc!=SQLITE_OK ){24    *ppDb = NULL;25    return 0;26  }27  /* Confirm sharable btree if possible */28  if( (*ppDb)->aDb[0].pBt==0 ) return 0;29  return sqlite3BtreeSharable((*ppDb)->aDb[0].pBt)!=0;30}31 32/* Helper: open a non-shared-cache in-memory db */33static int open_noshare_memory_db(sqlite3 **ppDb){34  int rc;35  sqlite3_enable_shared_cache(0);36  rc = sqlite3_open(":memory:", ppDb);37  return rc==SQLITE_OK;38}39 40/* Helper: free TableLock array on a Parse/top-level */41static void freeTableLocks(Parse *p){42  if( p && p->db && p->aTableLock ){43    sqlite3DbFree(p->db, p->aTableLock);44    p->aTableLock = 0;45    p->nTableLock = 0;46  }47}48 49void setUp(void) {50  /* No global setup required */51}52 53void tearDown(void) {54  /* No global teardown required */55}56 57/* Test: iDb==1 (TEMP database) is always ignored */58void test_sqlite3TableLock_noop_when_temp_db(void){59  sqlite3 *db = NULL;60  TEST_ASSERT_TRUE_MESSAGE(open_noshare_memory_db(&db), "Failed to open db");61  Parse p;62  initParse(&p, db);63 64  TEST_ASSERT_EQUAL_INT(0, p.nTableLock);65  sqlite3TableLock(&p, 1 /* TEMP */, 5 /* tab pgno */, 1 /* write */, "temp.t");66  TEST_ASSERT_EQUAL_INT(0, p.nTableLock);67  TEST_ASSERT_EQUAL_PTR(NULL, p.aTableLock);68 69  sqlite3_close(db);70}71 72/* Test: When btree is not sharable, no lock is recorded */73void test_sqlite3TableLock_noop_when_not_sharable(void){74  sqlite3 *db = NULL;75  TEST_ASSERT_TRUE_MESSAGE(open_noshare_memory_db(&db), "Failed to open db");76  /* Ensure btree is not sharable */77  if( db->aDb[0].pBt ){78    TEST_ASSERT_EQUAL_INT(0, sqlite3BtreeSharable(db->aDb[0].pBt));79  }80 81  Parse p;82  initParse(&p, db);83 84  sqlite3TableLock(&p, 0 /* main */, 3, 1, "main.t");85  TEST_ASSERT_EQUAL_INT(0, p.nTableLock);86  TEST_ASSERT_EQUAL_PTR(NULL, p.aTableLock);87 88  sqlite3_close(db);89}90 91/* Test: With shared-cache enabled, a lock is recorded */92void test_sqlite3TableLock_records_lock_when_sharable(void){93  sqlite3 *db = NULL;94  int sharable = open_shared_db(&db, "test_sc_1.db");95  if( !sharable ){96    if( db ) sqlite3_close(db);97    TEST_IGNORE_MESSAGE("Shared-cache not available; skipping test.");98  }99 100  /* Precondition: btree sharable */101  TEST_ASSERT_NOT_NULL(db->aDb[0].pBt);102  TEST_ASSERT_NOT_EQUAL(0, sqlite3BtreeSharable(db->aDb[0].pBt));103 104  Parse p;105  initParse(&p, db);106 107  const char *zName = "main.table1";108  sqlite3TableLock(&p, 0, 42, 0, zName);109 110  TEST_ASSERT_EQUAL_INT(1, p.nTableLock);111  TEST_ASSERT_NOT_NULL(p.aTableLock);112  TEST_ASSERT_EQUAL_INT(0, p.aTableLock[0].iDb);113  TEST_ASSERT_EQUAL_INT(42, (int)p.aTableLock[0].iTab);114  TEST_ASSERT_EQUAL_INT(0, p.aTableLock[0].isWriteLock);115  TEST_ASSERT_EQUAL_PTR(zName, p.aTableLock[0].zLockName);116 117  freeTableLocks(&p);118  sqlite3_close(db);119}120 121/* Test: Duplicate (iDb,iTab) entries are merged and write-lock is upgraded */122void test_sqlite3TableLock_merges_and_upgrades_write_lock(void){123  sqlite3 *db = NULL;124  int sharable = open_shared_db(&db, "test_sc_2.db");125  if( !sharable ){126    if( db ) sqlite3_close(db);127    TEST_IGNORE_MESSAGE("Shared-cache not available; skipping test.");128  }129 130  Parse p;131  initParse(&p, db);132 133  const char *zFirst = "main.tA.first";134  const char *zSecond = "main.tA.second";135  sqlite3TableLock(&p, 0, 100, 0 /* read */, zFirst);136  sqlite3TableLock(&p, 0, 100, 1 /* write */, zSecond); /* Should merge */137 138  TEST_ASSERT_EQUAL_INT(1, p.nTableLock);139  TEST_ASSERT_NOT_NULL(p.aTableLock);140  TEST_ASSERT_EQUAL_INT(0, p.aTableLock[0].iDb);141  TEST_ASSERT_EQUAL_INT(100, (int)p.aTableLock[0].iTab);142  TEST_ASSERT_EQUAL_INT(1, p.aTableLock[0].isWriteLock);143  /* Name should remain from first call */144  TEST_ASSERT_EQUAL_PTR(zFirst, p.aTableLock[0].zLockName);145 146  /* Another duplicate that does not downgrade */147  sqlite3TableLock(&p, 0, 100, 0 /* read */, "ignored");148  TEST_ASSERT_EQUAL_INT(1, p.nTableLock);149  TEST_ASSERT_EQUAL_INT(1, p.aTableLock[0].isWriteLock);150  TEST_ASSERT_EQUAL_PTR(zFirst, p.aTableLock[0].zLockName);151 152  freeTableLocks(&p);153  sqlite3_close(db);154}155 156/* Test: Distinct (iDb,iTab) entries both get recorded */157void test_sqlite3TableLock_multiple_distinct_entries(void){158  sqlite3 *db = NULL;159  int sharable = open_shared_db(&db, "test_sc_3.db");160  if( !sharable ){161    if( db ) sqlite3_close(db);162    TEST_IGNORE_MESSAGE("Shared-cache not available; skipping test.");163  }164 165  Parse p;166  initParse(&p, db);167 168  sqlite3TableLock(&p, 0, 7, 0, "t7");169  sqlite3TableLock(&p, 0, 8, 1, "t8");170 171  TEST_ASSERT_EQUAL_INT(2, p.nTableLock);172  TEST_ASSERT_NOT_NULL(p.aTableLock);173 174  /* First entry */175  TEST_ASSERT_EQUAL_INT(0, p.aTableLock[0].iDb);176  TEST_ASSERT_EQUAL_INT(7, (int)p.aTableLock[0].iTab);177  TEST_ASSERT_EQUAL_INT(0, p.aTableLock[0].isWriteLock);178  TEST_ASSERT_EQUAL_PTR("t7", p.aTableLock[0].zLockName);179 180  /* Second entry */181  TEST_ASSERT_EQUAL_INT(0, p.aTableLock[1].iDb);182  TEST_ASSERT_EQUAL_INT(8, (int)p.aTableLock[1].iTab);183  TEST_ASSERT_EQUAL_INT(1, p.aTableLock[1].isWriteLock);184  TEST_ASSERT_EQUAL_PTR("t8", p.aTableLock[1].zLockName);185 186  freeTableLocks(&p);187  sqlite3_close(db);188}189 190/* Test: Locks are recorded on the top-level Parse when called with a child Parse */191void test_sqlite3TableLock_records_on_toplevel(void){192  sqlite3 *db = NULL;193  int sharable = open_shared_db(&db, "test_sc_4.db");194  if( !sharable ){195    if( db ) sqlite3_close(db);196    TEST_IGNORE_MESSAGE("Shared-cache not available; skipping test.");197  }198 199  Parse top, child;200  initParse(&top, db);201  initParse(&child, db);202  child.pToplevel = &top;203 204  sqlite3TableLock(&child, 0, 55, 1, "child.to.top");205 206  TEST_ASSERT_EQUAL_INT(1, top.nTableLock);207  TEST_ASSERT_NOT_NULL(top.aTableLock);208  TEST_ASSERT_EQUAL_INT(0, top.aTableLock[0].iDb);209  TEST_ASSERT_EQUAL_INT(55, (int)top.aTableLock[0].iTab);210  TEST_ASSERT_EQUAL_INT(1, top.aTableLock[0].isWriteLock);211  TEST_ASSERT_EQUAL_PTR("child.to.top", top.aTableLock[0].zLockName);212 213  /* Child should remain untouched */214  TEST_ASSERT_EQUAL_INT(0, child.nTableLock);215  TEST_ASSERT_NULL(child.aTableLock);216 217  freeTableLocks(&top);218  sqlite3_close(db);219}220 221int main(void){222  UNITY_BEGIN();223  RUN_TEST(test_sqlite3TableLock_noop_when_temp_db);224  RUN_TEST(test_sqlite3TableLock_noop_when_not_sharable);225  RUN_TEST(test_sqlite3TableLock_records_lock_when_sharable);226  RUN_TEST(test_sqlite3TableLock_merges_and_upgrades_write_lock);227  RUN_TEST(test_sqlite3TableLock_multiple_distinct_entries);228  RUN_TEST(test_sqlite3TableLock_records_on_toplevel);229  return UNITY_END();230}