Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_pager_sqlite3PagerSharedLock.c173 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3 4#include <stdio.h>5#include <stdlib.h>6#include <string.h>7#include <time.h>8 9/* Helpers to generate unique db filenames per test */10static int g_file_counter = 0;11static void make_test_db_path(char *buf, size_t buflen, const char *suffix){12  snprintf(buf, buflen, "test_pager_%ld_%d%s", (long)time(NULL), g_file_counter++, suffix?suffix:"");13}14 15static void cleanup_db_files(const char *base){16  if( base==NULL ) return;17  char path[1024];18  /* base */19  snprintf(path, sizeof(path), "%s", base);20  remove(path);21  /* -journal */22  snprintf(path, sizeof(path), "%s-journal", base);23  remove(path);24  /* -wal */25  snprintf(path, sizeof(path), "%s-wal", base);26  remove(path);27  /* -shm */28  snprintf(path, sizeof(path), "%s-shm", base);29  remove(path);30}31 32static Pager* getPagerFromDb(sqlite3 *db){33  if( db==0 ) return 0;34  /* Ensure schema is initialized to guarantee pBt ready */35  (void)sqlite3_exec(db, "SELECT 1", 0, 0, 0);36  if( db->nDb<=0 || db->aDb[0].pBt==0 ) return 0;37  return sqlite3BtreePager(db->aDb[0].pBt);38}39 40static void ensure_db_nonempty(sqlite3 *db){41  char *zErr = 0;42  int rc = sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS t(x); INSERT INTO t(x) VALUES(1);", 0, 0, &zErr);43  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, zErr ? zErr : "exec failed");44  if( zErr ) sqlite3_free(zErr);45}46 47void setUp(void) {48  /* Nothing for now */49}50void tearDown(void) {51  /* Nothing for now */52}53 54/* Test 1: Basic successful shared lock acquisition and idempotency */55void test_sqlite3PagerSharedLock_basic_and_idempotent(void){56  char dbpath[1024];57  sqlite3 *db = 0;58  Pager *pPager = 0;59  int rc;60 61  make_test_db_path(dbpath, sizeof(dbpath), ".sqlite");62  cleanup_db_files(dbpath);63 64  rc = sqlite3_open(dbpath, &db);65  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);66  TEST_ASSERT_NOT_NULL(db);67 68  /* Ensure the database file exists and has no WAL mode */69  ensure_db_nonempty(db);70 71  pPager = getPagerFromDb(db);72  TEST_ASSERT_NOT_NULL(pPager);73 74  /* First call - should acquire shared lock and transition to READER */75  rc = sqlite3PagerSharedLock(pPager);76  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);77  TEST_ASSERT_EQUAL_INT(PAGER_READER, pPager->eState);78  TEST_ASSERT_TRUE(pPager->hasHeldSharedLock!=0);79 80  /* Second call - idempotent/no-op behavior - remains READER and OK */81  rc = sqlite3PagerSharedLock(pPager);82  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);83  TEST_ASSERT_EQUAL_INT(PAGER_READER, pPager->eState);84 85  sqlite3_close(db);86  cleanup_db_files(dbpath);87}88 89/* Test 2: Read-only connection detects hot journal and returns SQLITE_READONLY_ROLLBACK */90void test_sqlite3PagerSharedLock_readonly_hot_journal_error(void){91  char dbpath[1024];92  sqlite3 *db_rw = 0;93  sqlite3 *db_ro = 0;94  Pager *pPager = 0;95  int rc;96 97  make_test_db_path(dbpath, sizeof(dbpath), ".sqlite");98  cleanup_db_files(dbpath);99 100  /* Create non-empty DB using a read-write connection */101  rc = sqlite3_open(dbpath, &db_rw);102  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);103  TEST_ASSERT_NOT_NULL(db_rw);104  ensure_db_nonempty(db_rw);105  sqlite3_close(db_rw);106 107  /* Open a separate read-only connection */108  rc = sqlite3_open_v2(dbpath, &db_ro, SQLITE_OPEN_READONLY, NULL);109  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);110  TEST_ASSERT_NOT_NULL(db_ro);111 112  pPager = getPagerFromDb(db_ro);113  TEST_ASSERT_NOT_NULL(pPager);114  TEST_ASSERT_TRUE_MESSAGE(pPager->readOnly!=0, "Pager should reflect read-only connection");115 116  /* Create a hot-journal file: exists and first byte != 0 */117  {118    FILE *jf = fopen(pPager->zJournal, "wb");119    TEST_ASSERT_NOT_NULL_MESSAGE(jf, "Failed to create journal file");120    unsigned char b = 0x01;121    size_t nw = fwrite(&b, 1, 1, jf);122    TEST_ASSERT_EQUAL_size_t(1, nw);123    fclose(jf);124  }125 126  /* Call target: should detect hot journal and return SQLITE_READONLY_ROLLBACK */127  rc = sqlite3PagerSharedLock(pPager);128  TEST_ASSERT_EQUAL_INT(SQLITE_READONLY_ROLLBACK, rc);129 130  sqlite3_close(db_ro);131  cleanup_db_files(dbpath);132}133 134/* Test 3: Behavior in WAL mode - ensure function works and ends in READER state */135void test_sqlite3PagerSharedLock_wal_mode(void){136  char dbpath[1024];137  sqlite3 *db = 0;138  Pager *pPager = 0;139  int rc;140 141  make_test_db_path(dbpath, sizeof(dbpath), ".sqlite");142  cleanup_db_files(dbpath);143 144  rc = sqlite3_open(dbpath, &db);145  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);146  TEST_ASSERT_NOT_NULL(db);147 148  /* Switch to WAL mode */149  rc = sqlite3_exec(db, "PRAGMA journal_mode=WAL;", 0, 0, 0);150  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);151 152  pPager = getPagerFromDb(db);153  TEST_ASSERT_NOT_NULL(pPager);154 155  /* Call target: in WAL, should begin read transaction and become READER */156  rc = sqlite3PagerSharedLock(pPager);157  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);158  TEST_ASSERT_EQUAL_INT(PAGER_READER, pPager->eState);159#ifndef SQLITE_OMIT_WAL160  TEST_ASSERT_NOT_NULL_MESSAGE(pPager->pWal, "Pager should be in WAL mode with pWal opened");161#endif162 163  sqlite3_close(db);164  cleanup_db_files(dbpath);165}166 167int main(void){168  UNITY_BEGIN();169  RUN_TEST(test_sqlite3PagerSharedLock_basic_and_idempotent);170  RUN_TEST(test_sqlite3PagerSharedLock_readonly_hot_journal_error);171  RUN_TEST(test_sqlite3PagerSharedLock_wal_mode);172  return UNITY_END();173}