AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4 5/* External wrapper added for testing static function */6extern void test_clearAllSharedCacheTableLocks(Btree *p);7 8/* Helpers to create minimal objects */9static Btree *allocBtreeWithShared(sqlite3_mutex *pMutex){10 Btree *p = (Btree*)sqlite3MallocZero(sizeof(Btree));11 BtShared *pBt = (BtShared*)sqlite3MallocZero(sizeof(BtShared));12 TEST_ASSERT_NOT_NULL(p);13 TEST_ASSERT_NOT_NULL(pBt);14 p->pBt = pBt;15 p->inTrans = TRANS_WRITE; /* >= any eLock */16 p->sharable = 1;17 pBt->mutex = pMutex;18 pBt->pLock = NULL;19 pBt->nTransaction = 0;20 pBt->btsFlags = 0;21 pBt->pWriter = NULL;22 return p;23}24 25static BtLock *makeLock(Btree *owner, Pgno iTable, u8 eLock){26 BtLock *pL = (BtLock*)sqlite3MallocZero(sizeof(BtLock));27 TEST_ASSERT_NOT_NULL(pL);28 pL->pBtree = owner;29 pL->iTable = iTable;30 pL->eLock = eLock;31 pL->pNext = NULL;32 return pL;33}34 35/* Global for setUp/tearDown */36static sqlite3_mutex *gFastMutex = NULL;37 38void setUp(void) {39 /* Initialize SQLite mutex system */40 sqlite3_initialize();41 gFastMutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST);42 TEST_ASSERT_NOT_NULL(gFastMutex);43}44 45void tearDown(void) {46 /* Note: SQLite core owns the fast static mutex; do not free it here. */47 gFastMutex = NULL;48}49 50/* Test 1: Remove only target Btree locks; keep others; clear pending when nTransaction==2 and p is not writer */51void test_clearAllSharedCacheTableLocks_removes_target_and_clears_pending(void){52 Btree *p = allocBtreeWithShared(gFastMutex);53 Btree *pOther = allocBtreeWithShared(gFastMutex);54 pOther->pBt = p->pBt; /* Share the same BtShared */55 p->pBt->nTransaction = 2;56 p->pBt->btsFlags |= BTS_PENDING;57 58 /* Build lock list: other -> p (t2) -> p (t3) */59 BtLock *lockA = makeLock(pOther, 5, READ_LOCK);60 BtLock *lockB = makeLock(p, 2, READ_LOCK);61 BtLock *lockC = makeLock(p, 3, WRITE_LOCK);62 p->pBt->pLock = lockA;63 lockA->pNext = lockB;64 lockB->pNext = lockC;65 66 /* Preconditions */67 TEST_ASSERT_NOT_NULL(p->pBt->pLock);68 TEST_ASSERT_TRUE( (p->pBt->btsFlags & BTS_PENDING)!=0 );69 70 sqlite3_mutex_enter(p->pBt->mutex);71 test_clearAllSharedCacheTableLocks(p);72 sqlite3_mutex_leave(p->pBt->mutex);73 74 /* Postconditions:75 - locks belonging to p are gone; only lockA remains76 - pending flag cleared (nTransaction==2 case)77 - writer unchanged (NULL) */78 TEST_ASSERT_EQUAL_PTR(lockA, p->pBt->pLock);79 TEST_ASSERT_NULL(lockA->pNext);80 TEST_ASSERT_TRUE( (p->pBt->btsFlags & BTS_PENDING)==0 );81 TEST_ASSERT_NULL(p->pBt->pWriter);82 83 /* Cleanup */84 sqlite3_free(lockA);85 sqlite3_free(pOther->pBt); sqlite3_free(pOther);86 sqlite3_free(p->pBt); sqlite3_free(p);87}88 89/* Test 2: When p is writer, writer and flags cleared; schema lock (iTable==1) removed without freeing */90void test_clearAllSharedCacheTableLocks_writer_and_schema_lock(void){91 Btree *p = allocBtreeWithShared(gFastMutex);92 p->pBt->pWriter = p;93 p->pBt->btsFlags |= (BTS_EXCLUSIVE | BTS_PENDING);94 p->lock.pBtree = p;95 p->lock.iTable = 1; /* schema table */96 p->lock.eLock = READ_LOCK;97 p->lock.pNext = NULL;98 99 /* p->lock is embedded; add to list */100 p->pBt->pLock = &p->lock;101 102 sqlite3_mutex_enter(p->pBt->mutex);103 test_clearAllSharedCacheTableLocks(p);104 sqlite3_mutex_leave(p->pBt->mutex);105 106 /* Postconditions:107 - lock list empty108 - writer cleared; flags cleared109 - embedded lock still accessible and unchanged */110 TEST_ASSERT_NULL(p->pBt->pLock);111 TEST_ASSERT_NULL(p->pBt->pWriter);112 TEST_ASSERT_TRUE( (p->pBt->btsFlags & (BTS_EXCLUSIVE|BTS_PENDING))==0 );113 TEST_ASSERT_EQUAL_UINT(1, p->lock.iTable);114 TEST_ASSERT_EQUAL_PTR(p, p->lock.pBtree);115 116 sqlite3_free(p->pBt); sqlite3_free(p);117}118 119/* Test 3: Non-sharable with no locks: clears pending when nTransaction==2; no crash */120void test_clearAllSharedCacheTableLocks_nonsharable_no_locks(void){121 Btree *p = allocBtreeWithShared(gFastMutex);122 p->sharable = 0; /* Non-sharable */123 p->pBt->pLock = NULL;124 p->pBt->nTransaction = 2;125 p->pBt->btsFlags |= BTS_PENDING;126 127 sqlite3_mutex_enter(p->pBt->mutex);128 test_clearAllSharedCacheTableLocks(p);129 sqlite3_mutex_leave(p->pBt->mutex);130 131 TEST_ASSERT_TRUE( (p->pBt->btsFlags & BTS_PENDING)==0 );132 TEST_ASSERT_NULL(p->pBt->pLock);133 134 sqlite3_free(p->pBt); sqlite3_free(p);135}136 137int main(void) {138 UNITY_BEGIN();139 RUN_TEST(test_clearAllSharedCacheTableLocks_removes_target_and_clears_pending);140 RUN_TEST(test_clearAllSharedCacheTableLocks_writer_and_schema_lock);141 RUN_TEST(test_clearAllSharedCacheTableLocks_nonsharable_no_locks);142 return UNITY_END();143}