Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_btree_setSharedCacheTableLock.c237 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4 5/* Wrapper for the static function under test (provided by build harness) */6#ifndef SQLITE_OMIT_SHARED_CACHE7extern int test_setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock);8#endif9 10/* Helpers to find and count locks for a given (Btree*, iTable) */11#ifndef SQLITE_OMIT_SHARED_CACHE12static BtLock* findLock(Btree *p, Pgno iTable){13  BtLock *pIter = p->pBt->pLock;14  while( pIter ){15    if( pIter->pBtree==p && pIter->iTable==(u32)iTable ){16      return pIter;17    }18    pIter = pIter->pNext;19  }20  return NULL;21}22static int countLocks(Btree *p, Pgno iTable){23  int c = 0;24  BtLock *pIter = p->pBt->pLock;25  while( pIter ){26    if( pIter->pBtree==p && pIter->iTable==(u32)iTable ) c++;27    pIter = pIter->pNext;28  }29  return c;30}31#endif32 33/* Utility to open a sharable Btree on a file */34#ifndef SQLITE_OMIT_SHARED_CACHE35static void openSharableBtree(const char *zFile, sqlite3 **ppDb, Btree **ppBt){36  int rc;37  sqlite3 *db = 0;38  sqlite3_vfs *pVfs = sqlite3_vfs_find(0);39  Btree *pBt = 0;40 41  rc = sqlite3_open_v2(":memory:", &db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, 0);42  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);43  TEST_ASSERT_NOT_NULL(db);44 45  /* Open the Btree directly with SHAREDCACHE flag to ensure p->sharable==1 */46  sqlite3_mutex_enter(db->mutex);47  rc = sqlite3BtreeOpen(pVfs, zFile, db, &pBt, 0,48                        SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_SHAREDCACHE);49  sqlite3_mutex_leave(db->mutex);50  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);51  TEST_ASSERT_NOT_NULL(pBt);52  TEST_ASSERT_TRUE_MESSAGE(pBt->sharable!=0, "Btree is not sharable; shared-cache likely disabled");53 54  *ppDb = db;55  *ppBt = pBt;56}57#endif58 59/* Utility to close a Btree and its owning db */60#ifndef SQLITE_OMIT_SHARED_CACHE61static void closeBtreeAndDb(sqlite3 *db, Btree *pBt){62  if( db && pBt ){63    sqlite3_mutex_enter(db->mutex);64    /* Ensure any open transaction is committed/ended before closing */65    (void)sqlite3BtreeCommit(pBt);66    (void)sqlite3BtreeClose(pBt);67    sqlite3_mutex_leave(db->mutex);68  }69  if( db ){70    sqlite3_close(db);71  }72}73#endif74 75void setUp(void) {76  /* nothing */77}78 79void tearDown(void) {80  /* nothing */81}82 83#ifndef SQLITE_OMIT_SHARED_CACHE84/* Basic READ lock creation */85void test_setSharedCacheTableLock_add_read_lock(void){86  sqlite3 *db = 0;87  Btree *pBt = 0;88  const Pgno iTable = 2; /* avoid schema table 1 */89 90  openSharableBtree("test_sc_readlock.db", &db, &pBt);91 92  /* Call the function under test while holding required mutex/enter */93  sqlite3_mutex_enter(db->mutex);94  sqlite3BtreeEnter(pBt);95  /* Precondition: querySharedCacheTableLock() should be OK for READ_LOCK.96     The assert inside the target function requires this. */97  {98    int rcQ = SQLITE_OK; /* no-op in non-debug or ensures correctness */99    (void)rcQ;100  }101  int rc = test_setSharedCacheTableLock(pBt, iTable, READ_LOCK);102  sqlite3BtreeLeave(pBt);103  sqlite3_mutex_leave(db->mutex);104 105  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);106 107  /* Verify a BtLock exists for this (Btree,iTable) with READ_LOCK */108  BtLock *pLk = findLock(pBt, iTable);109  TEST_ASSERT_NOT_NULL(pLk);110  TEST_ASSERT_EQUAL_PTR(pBt, pLk->pBtree);111  TEST_ASSERT_EQUAL_UINT32(iTable, pLk->iTable);112  TEST_ASSERT_EQUAL_INT(READ_LOCK, pLk->eLock);113 114  closeBtreeAndDb(db, pBt);115}116 117/* Upgrade from READ to WRITE lock */118void test_setSharedCacheTableLock_upgrade_to_write(void){119  sqlite3 *db = 0;120  Btree *pBt = 0;121  const Pgno iTable = 2;122 123  openSharableBtree("test_sc_upgrade.db", &db, &pBt);124 125  /* First, add a READ lock */126  sqlite3_mutex_enter(db->mutex);127  sqlite3BtreeEnter(pBt);128  TEST_ASSERT_EQUAL_INT(SQLITE_OK, test_setSharedCacheTableLock(pBt, iTable, READ_LOCK));129  sqlite3BtreeLeave(pBt);130  sqlite3_mutex_leave(db->mutex);131 132  /* Begin a write transaction to satisfy WRITE_LOCK asserts */133  sqlite3_mutex_enter(db->mutex);134  int rc = sqlite3BtreeBeginTrans(pBt, 1, 0);135  sqlite3_mutex_leave(db->mutex);136  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);137 138  /* Now upgrade to WRITE lock */139  sqlite3_mutex_enter(db->mutex);140  sqlite3BtreeEnter(pBt);141  rc = test_setSharedCacheTableLock(pBt, iTable, WRITE_LOCK);142  sqlite3BtreeLeave(pBt);143  sqlite3_mutex_leave(db->mutex);144 145  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);146 147  /* Verify lock exists and is WRITE */148  BtLock *pLk = findLock(pBt, iTable);149  TEST_ASSERT_NOT_NULL(pLk);150  TEST_ASSERT_EQUAL_INT(WRITE_LOCK, pLk->eLock);151 152  /* Clean up transaction */153  sqlite3_mutex_enter(db->mutex);154  (void)sqlite3BtreeCommit(pBt);155  sqlite3_mutex_leave(db->mutex);156 157  closeBtreeAndDb(db, pBt);158}159 160/* Ensure READ after WRITE does not downgrade the lock */161void test_setSharedCacheTableLock_no_downgrade_on_read_after_write(void){162  sqlite3 *db = 0;163  Btree *pBt = 0;164  const Pgno iTable = 2;165 166  openSharableBtree("test_sc_nodowngrade.db", &db, &pBt);167 168  /* Begin write transaction and set WRITE lock */169  sqlite3_mutex_enter(db->mutex);170  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3BtreeBeginTrans(pBt, 1, 0));171  sqlite3_mutex_leave(db->mutex);172 173  sqlite3_mutex_enter(db->mutex);174  sqlite3BtreeEnter(pBt);175  TEST_ASSERT_EQUAL_INT(SQLITE_OK, test_setSharedCacheTableLock(pBt, iTable, WRITE_LOCK));176  sqlite3BtreeLeave(pBt);177  sqlite3_mutex_leave(db->mutex);178 179  /* Now call with READ_LOCK — should remain WRITE_LOCK */180  sqlite3_mutex_enter(db->mutex);181  sqlite3BtreeEnter(pBt);182  TEST_ASSERT_EQUAL_INT(SQLITE_OK, test_setSharedCacheTableLock(pBt, iTable, READ_LOCK));183  sqlite3BtreeLeave(pBt);184  sqlite3_mutex_leave(db->mutex);185 186  BtLock *pLk = findLock(pBt, iTable);187  TEST_ASSERT_NOT_NULL(pLk);188  TEST_ASSERT_EQUAL_INT(WRITE_LOCK, pLk->eLock);189 190  /* Ensure only one lock entry exists for this (pBt,iTable) */191  TEST_ASSERT_EQUAL_INT(1, countLocks(pBt, iTable));192 193  /* Clean up */194  sqlite3_mutex_enter(db->mutex);195  (void)sqlite3BtreeCommit(pBt);196  sqlite3_mutex_leave(db->mutex);197  closeBtreeAndDb(db, pBt);198}199 200/* Multiple calls should not create duplicate BtLock entries */201void test_setSharedCacheTableLock_no_duplicate_entries(void){202  sqlite3 *db = 0;203  Btree *pBt = 0;204  const Pgno iTable = 2;205 206  openSharableBtree("test_sc_nodup.db", &db, &pBt);207 208  sqlite3_mutex_enter(db->mutex);209  sqlite3BtreeEnter(pBt);210  TEST_ASSERT_EQUAL_INT(SQLITE_OK, test_setSharedCacheTableLock(pBt, iTable, READ_LOCK));211  TEST_ASSERT_EQUAL_INT(SQLITE_OK, test_setSharedCacheTableLock(pBt, iTable, READ_LOCK));212  TEST_ASSERT_EQUAL_INT(SQLITE_OK, test_setSharedCacheTableLock(pBt, iTable, READ_LOCK));213  sqlite3BtreeLeave(pBt);214  sqlite3_mutex_leave(db->mutex);215 216  TEST_ASSERT_EQUAL_INT(1, countLocks(pBt, iTable));217  BtLock *pLk = findLock(pBt, iTable);218  TEST_ASSERT_NOT_NULL(pLk);219  TEST_ASSERT_EQUAL_INT(READ_LOCK, pLk->eLock);220 221  closeBtreeAndDb(db, pBt);222}223#else  /* SQLITE_OMIT_SHARED_CACHE */224void test_setSharedCacheTableLock_add_read_lock(void){ TEST_IGNORE_MESSAGE("Shared cache omitted at build time"); }225void test_setSharedCacheTableLock_upgrade_to_write(void){ TEST_IGNORE_MESSAGE("Shared cache omitted at build time"); }226void test_setSharedCacheTableLock_no_downgrade_on_read_after_write(void){ TEST_IGNORE_MESSAGE("Shared cache omitted at build time"); }227void test_setSharedCacheTableLock_no_duplicate_entries(void){ TEST_IGNORE_MESSAGE("Shared cache omitted at build time"); }228#endif /* SQLITE_OMIT_SHARED_CACHE */229 230int main(void){231  UNITY_BEGIN();232  RUN_TEST(test_setSharedCacheTableLock_add_read_lock);233  RUN_TEST(test_setSharedCacheTableLock_upgrade_to_write);234  RUN_TEST(test_setSharedCacheTableLock_no_downgrade_on_read_after_write);235  RUN_TEST(test_setSharedCacheTableLock_no_duplicate_entries);236  return UNITY_END();237}