Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_memdb_memdbLock.c226 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5#include <stdio.h>6 7/* The target function is static; use the provided global wrapper. */8extern int test_memdbLock(sqlite3_file *pFile, int eLock);9 10/* Ensure sqlite3MemdbInit is visible */11extern int sqlite3MemdbInit(void);12 13static int g_memdb_inited = 0;14 15static void open_shared_memdb(const char *name, sqlite3 **pDb, sqlite3_file **ppFile){16  int rc;17  char uri[256];18  sqlite3 *db = 0;19  sqlite3_file *pFile = 0;20 21  /* Construct a shared-memdb URI: leading slash makes it shared */22  sqlite3_snprintf(sizeof(uri), uri, "file:/%s?vfs=memdb", name);23  rc = sqlite3_open_v2(uri, &db,24                       SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_URI,25                       NULL);26  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "Failed to open shared memdb database");27  TEST_ASSERT_NOT_NULL(db);28 29  rc = sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, &pFile);30  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "SQLITE_FCNTL_FILE_POINTER failed");31  TEST_ASSERT_NOT_NULL(pFile);32 33  *pDb = db;34  *ppFile = pFile;35}36 37static void close_db(sqlite3 *db){38  if( db ){39    sqlite3_close(db);40  }41}42 43static void open_readonly_deserialized_memdb(sqlite3 **pDb, sqlite3_file **ppFile){44  /* Create a separate memdb via sqlite3_deserialize with READONLY */45  int rc;46  sqlite3 *db = 0;47  sqlite3_file *pFile = 0;48  const sqlite3_int64 szDb = 0;     /* 0-byte db content is fine for our locking tests */49  const sqlite3_int64 szBuf = 1024; /* backing buffer size */50  unsigned char *pData = (unsigned char*)sqlite3_malloc((int)szBuf);51  TEST_ASSERT_NOT_NULL_MESSAGE(pData, "sqlite3_malloc failed for deserialize buffer");52  memset(pData, 0, (size_t)szBuf);53 54  rc = sqlite3_open(":memory:", &db);55  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "Failed to open :memory:");56 57  /* READONLY plus FREEONCLOSE so buffer is freed on close */58  rc = sqlite3_deserialize(db, "main", pData, szDb, szBuf,59                           SQLITE_DESERIALIZE_READONLY | SQLITE_DESERIALIZE_FREEONCLOSE);60  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_deserialize failed");61 62  rc = sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, &pFile);63  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "SQLITE_FCNTL_FILE_POINTER failed after deserialize");64  TEST_ASSERT_NOT_NULL(pFile);65 66  *pDb = db;67  *ppFile = pFile;68}69 70void setUp(void) {71  if( !g_memdb_inited ){72    int rc = sqlite3MemdbInit();73    /* sqlite3MemdbInit may be called multiple times; first must succeed */74    TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3MemdbInit failed");75    g_memdb_inited = 1;76  }77}78 79void tearDown(void) {80  /* Nothing to do */81}82 83/* Test 1: Acquire SHARED lock on a fresh handle succeeds */84void test_memdbLock_shared_ok(void){85  sqlite3 *db = 0;86  sqlite3_file *pFile = 0;87  int rc;88 89  open_shared_memdb("t1_shared_ok", &db, &pFile);90 91  rc = test_memdbLock(pFile, SQLITE_LOCK_SHARED);92  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);93 94  /* Cleanup: unlock back to NONE */95  pFile->pMethods->xUnlock(pFile, SQLITE_LOCK_NONE);96  close_db(db);97}98 99/* Test 2: Two readers -> EXCLUSIVE on one should be SQLITE_BUSY */100void test_memdbLock_two_readers_then_exclusive_busy(void){101  sqlite3 *db1 = 0, *db2 = 0;102  sqlite3_file *f1 = 0, *f2 = 0;103  int rc;104 105  open_shared_memdb("t2_two_readers", &db1, &f1);106  open_shared_memdb("t2_two_readers", &db2, &f2);107 108  rc = test_memdbLock(f1, SQLITE_LOCK_SHARED);109  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);110 111  rc = test_memdbLock(f2, SQLITE_LOCK_SHARED);112  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);113 114  rc = test_memdbLock(f1, SQLITE_LOCK_EXCLUSIVE);115  TEST_ASSERT_EQUAL_INT(SQLITE_BUSY, rc);116 117  /* Cleanup: unlock both back to NONE */118  f1->pMethods->xUnlock(f1, SQLITE_LOCK_NONE);119  f2->pMethods->xUnlock(f2, SQLITE_LOCK_NONE);120  close_db(db1);121  close_db(db2);122}123 124/* Test 3: Writer reserved lock blocks new readers */125void test_memdbLock_reserved_blocks_new_shared(void){126  sqlite3 *db1 = 0, *db2 = 0;127  sqlite3_file *f1 = 0, *f2 = 0;128  int rc;129 130  open_shared_memdb("t3_reserved_blocks", &db1, &f1);131  open_shared_memdb("t3_reserved_blocks", &db2, &f2);132 133  rc = test_memdbLock(f1, SQLITE_LOCK_SHARED);134  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);135 136  rc = test_memdbLock(f1, SQLITE_LOCK_RESERVED);137  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);138 139  rc = test_memdbLock(f2, SQLITE_LOCK_SHARED);140  TEST_ASSERT_EQUAL_INT(SQLITE_BUSY, rc);141 142  /* Cleanup: release writer and close */143  f1->pMethods->xUnlock(f1, SQLITE_LOCK_NONE);144  f2->pMethods->xUnlock(f2, SQLITE_LOCK_NONE);145  close_db(db1);146  close_db(db2);147}148 149/* Test 4: Single reader can upgrade SHARED -> RESERVED -> EXCLUSIVE */150void test_memdbLock_upgrade_to_exclusive_single_reader_ok(void){151  sqlite3 *db = 0;152  sqlite3_file *f = 0;153  int rc;154 155  open_shared_memdb("t4_upgrade_ok", &db, &f);156 157  rc = test_memdbLock(f, SQLITE_LOCK_SHARED);158  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);159 160  rc = test_memdbLock(f, SQLITE_LOCK_RESERVED);161  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);162 163  rc = test_memdbLock(f, SQLITE_LOCK_EXCLUSIVE);164  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);165 166  /* Cleanup */167  f->pMethods->xUnlock(f, SQLITE_LOCK_NONE);168  close_db(db);169}170 171/* Test 5: Read-only store allows SHARED but refuses RESERVED/EXCLUSIVE */172void test_memdbLock_readonly_refuses_upgrades(void){173  sqlite3 *db = 0;174  sqlite3_file *f = 0;175  int rc;176 177  open_readonly_deserialized_memdb(&db, &f);178 179  rc = test_memdbLock(f, SQLITE_LOCK_SHARED);180  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);181 182  rc = test_memdbLock(f, SQLITE_LOCK_RESERVED);183  TEST_ASSERT_EQUAL_INT(SQLITE_READONLY, rc);184 185  rc = test_memdbLock(f, SQLITE_LOCK_EXCLUSIVE);186  TEST_ASSERT_EQUAL_INT(SQLITE_READONLY, rc);187 188  /* Cleanup */189  f->pMethods->xUnlock(f, SQLITE_LOCK_NONE);190  close_db(db);191}192 193/* Test 6: Idempotent / non-decreasing requests are OK */194void test_memdbLock_same_or_lower_level_ok(void){195  sqlite3 *db = 0;196  sqlite3_file *f = 0;197  int rc;198 199  open_shared_memdb("t6_idempotent", &db, &f);200 201  rc = test_memdbLock(f, SQLITE_LOCK_SHARED);202  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);203 204  /* Request same level again */205  rc = test_memdbLock(f, SQLITE_LOCK_SHARED);206  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);207 208  /* Request lower level (NONE) – should be OK (no-op inside memdbLock) */209  rc = test_memdbLock(f, SQLITE_LOCK_NONE);210  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);211 212  /* Cleanup */213  f->pMethods->xUnlock(f, SQLITE_LOCK_NONE);214  close_db(db);215}216 217int main(void){218  UNITY_BEGIN();219  RUN_TEST(test_memdbLock_shared_ok);220  RUN_TEST(test_memdbLock_two_readers_then_exclusive_busy);221  RUN_TEST(test_memdbLock_reserved_blocks_new_shared);222  RUN_TEST(test_memdbLock_upgrade_to_exclusive_single_reader_ok);223  RUN_TEST(test_memdbLock_readonly_refuses_upgrades);224  RUN_TEST(test_memdbLock_same_or_lower_level_ok);225  return UNITY_END();226}