Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_btree_hasSharedCacheTableLock.c180 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdio.h>5 6/* Wrapper declared by the build system for the static target function */7extern int test_hasSharedCacheTableLock(Btree *pBtree, Pgno iRoot, int isIndex, int eLockType);8 9/* Helpers to extract root-page numbers from the loaded schema */10static Pgno findTableRoot(sqlite3 *db, const char *zName){11  Schema *pSchema = db->aDb[0].pSchema;12  if( pSchema==0 ) return 0;13  for(HashElem *p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){14    Table *pTab = (Table*)sqliteHashData(p);15    if( pTab && pTab->zName && 0==sqlite3StrICmp(pTab->zName, zName) ){16      return (Pgno)pTab->tnum;17    }18  }19  return 0;20}21 22static Pgno findIndexRoot(sqlite3 *db, const char *zName){23  Schema *pSchema = db->aDb[0].pSchema;24  if( pSchema==0 ) return 0;25  for(HashElem *p=sqliteHashFirst(&pSchema->idxHash); p; p=sqliteHashNext(p)){26    Index *pIdx = (Index*)sqliteHashData(p);27    if( pIdx && pIdx->zName && 0==sqlite3StrICmp(pIdx->zName, zName) ){28      return (Pgno)pIdx->tnum;29    }30  }31  return 0;32}33 34/* Simple helper to run SQL and assert OK */35static void execSQL(sqlite3 *db, const char *sql){36  char *zErr = 0;37  int rc = sqlite3_exec(db, sql, 0, 0, &zErr);38  if( rc!=SQLITE_OK ){39    fprintf(stderr, "SQL error: %s\n", zErr ? zErr : "(null)");40  }41  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);42  sqlite3_free(zErr);43}44 45void setUp(void) {46  /* no-op */47}48void tearDown(void) {49  /* no-op */50}51 52/* Test 1: READ_LOCK returns true under read-uncommitted regardless of locks */53void test_hasSharedCacheTableLock_read_uncommitted_READ_LOCK_true(void){54  sqlite3 *db = 0;55  int rc;56  sqlite3_enable_shared_cache(1);57  rc = sqlite3_open("file:lock_ru.db?cache=shared", &db);58  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);59  /* Put connection into read-uncommitted mode */60  execSQL(db, "PRAGMA read_uncommitted=ON");61 62  Btree *pBt = db->aDb[0].pBt;63  /* Root page 1 (schema). Expect true because READ_LOCK && ReadUncommitted. */64  int ok = test_hasSharedCacheTableLock(pBt, 1, 0, READ_LOCK);65  TEST_ASSERT_EQUAL_INT(1, ok);66 67  sqlite3_close(db);68}69 70/* Test 2: isIndex==true and schema is not loaded -> returns true */71void test_hasSharedCacheTableLock_index_schema_not_loaded_true(void){72  sqlite3 *db = 0;73  int rc;74  sqlite3_enable_shared_cache(1);75  rc = sqlite3_open("file:lock_schema_not_loaded.db?cache=shared", &db);76  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);77 78  /* Without running any SQL, schema should not be loaded (pSchema == NULL) */79  Btree *pBt = db->aDb[0].pBt;80  /* Arbitrary root page argument; isIndex=1; READ_LOCK */81  int ok = test_hasSharedCacheTableLock(pBt, 2, 1, READ_LOCK);82  TEST_ASSERT_EQUAL_INT(1, ok);83 84  sqlite3_close(db);85}86 87/* Test 3: With write-lock on a table, hasSharedCacheTableLock is true for both88** (a) table write-lock, and (b) index write-lock via associated table.89** Also verify a second connection without locks returns false. */90void test_hasSharedCacheTableLock_write_lock_on_table_and_index(void){91  sqlite3 *db1 = 0;92  sqlite3 *db2 = 0;93  int rc;94 95  sqlite3_enable_shared_cache(1);96  rc = sqlite3_open("file:lock3.db?cache=shared", &db1);97  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);98  rc = sqlite3_open("file:lock3.db?cache=shared", &db2);99  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);100 101  /* Create a table and index */102  execSQL(db1, "PRAGMA journal_mode=memory;");103  execSQL(db1, "BEGIN;");104  execSQL(db1, "CREATE TABLE t(a);");105  execSQL(db1, "CREATE INDEX i1 ON t(a);");106  execSQL(db1, "COMMIT;");107 108  /* Schema now loaded; find root pages */109  Pgno tRoot = findTableRoot(db1, "t");110  Pgno iRoot = findIndexRoot(db1, "i1");111  TEST_ASSERT(tRoot>1);112  TEST_ASSERT(iRoot>1);113 114  Btree *p1 = db1->aDb[0].pBt;115  Btree *p2 = db2->aDb[0].pBt;116 117  /* Begin a write transaction on db1 and obtain a write-lock on table t */118  rc = sqlite3BtreeBeginTrans(p1, 1, 0);119  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);120  rc = sqlite3BtreeLockTable(p1, tRoot, 1);121  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);122 123  /* Positive checks on p1: table write-lock and index write-lock via table */124  int ok_tbl_w = test_hasSharedCacheTableLock(p1, tRoot, 0, WRITE_LOCK);125  TEST_ASSERT_EQUAL_INT(1, ok_tbl_w);126  int ok_idx_w = test_hasSharedCacheTableLock(p1, iRoot, 1, WRITE_LOCK);127  TEST_ASSERT_EQUAL_INT(1, ok_idx_w);128 129  /* Negative checks on p2 (no locks held): should be false */130  int no_tbl_w = test_hasSharedCacheTableLock(p2, tRoot, 0, WRITE_LOCK);131  TEST_ASSERT_EQUAL_INT(0, no_tbl_w);132  int no_idx_r = test_hasSharedCacheTableLock(p2, iRoot, 1, READ_LOCK);133  TEST_ASSERT_EQUAL_INT(0, no_idx_r);134 135  /* Cleanup */136  sqlite3_close(db2);137  sqlite3_close(db1);138}139 140/* Test 4: Schema (root page 1) write-lock is sufficient for any table/index */141void test_hasSharedCacheTableLock_schema_write_lock_satisfies(void){142  sqlite3 *db = 0;143  int rc;144  sqlite3_enable_shared_cache(1);145  rc = sqlite3_open("file:lock_schema.db?cache=shared", &db);146  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);147 148  execSQL(db, "CREATE TABLE t(a); CREATE INDEX i1 ON t(a);");149  Pgno tRoot = findTableRoot(db, "t");150  Pgno iRoot = findIndexRoot(db, "i1");151  TEST_ASSERT(tRoot>1);152  TEST_ASSERT(iRoot>1);153 154  Btree *p = db->aDb[0].pBt;155  rc = sqlite3BtreeBeginTrans(p, 1, 0);156  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);157 158  /* Acquire write lock on schema table (root page 1) */159  rc = sqlite3BtreeLockTable(p, 1, 1);160  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);161 162  /* Now both table and index should be satisfied for WRITE_LOCK */163  int ok_tbl = test_hasSharedCacheTableLock(p, tRoot, 0, WRITE_LOCK);164  int ok_idx = test_hasSharedCacheTableLock(p, iRoot, 1, WRITE_LOCK);165  TEST_ASSERT_EQUAL_INT(1, ok_tbl);166  TEST_ASSERT_EQUAL_INT(1, ok_idx);167 168  sqlite3_close(db);169}170 171int main(void){172  UNITY_BEGIN();173 174  RUN_TEST(test_hasSharedCacheTableLock_read_uncommitted_READ_LOCK_true);175  RUN_TEST(test_hasSharedCacheTableLock_index_schema_not_loaded_true);176  RUN_TEST(test_hasSharedCacheTableLock_write_lock_on_table_and_index);177  RUN_TEST(test_hasSharedCacheTableLock_schema_write_lock_satisfies);178 179  return UNITY_END();180}