Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_pager_sqlite3PagerSetJournalMode.c236 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdio.h>4#include <string.h>5 6/* Utilities */7 8static void unlink_if_exists(sqlite3_vfs *pVfs, const char *zPath){9  if( zPath==NULL ) return;10  int exists = 0;11  (void)sqlite3OsAccess(pVfs, zPath, SQLITE_ACCESS_EXISTS, &exists);12  if( exists ){13    (void)sqlite3OsDelete(pVfs, zPath, 0);14  }15}16 17static sqlite3* open_db_filename(const char *zFilename){18  sqlite3 *db = 0;19  int rc = sqlite3_open(zFilename, &db);20  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);21  TEST_ASSERT_NOT_NULL(db);22  return db;23}24 25static void close_db_and_cleanup(sqlite3 *db, const char *zFilename){26  if( db ){27    sqlite3_close(db);28  }29  if( zFilename ){30    sqlite3_vfs *pVfs = sqlite3_vfs_find(0);31    if( pVfs ){32      /* Remove both the database and its journal if they exist */33      unlink_if_exists(pVfs, zFilename);34      /* Also try removing the "-journal" file if any (use Pager if possible). */35      /* We cannot get Pager after closing db easily, so derive journal name. */36      /* SQLite uses "-journal" suffix by default */37      char zJournal[1024];38      memset(zJournal, 0, sizeof(zJournal));39      size_t n = strlen(zFilename);40      if( n + 9 < sizeof(zJournal) ){41        memcpy(zJournal, zFilename, n);42        memcpy(zJournal + n, "-journal", 9);43        unlink_if_exists(pVfs, zJournal);44      }45      /* Also try wal file */46      char zWal[1024];47      memset(zWal, 0, sizeof(zWal));48      if( n + 4 < sizeof(zWal) ){49        memcpy(zWal, zFilename, n);50        memcpy(zWal + n, "-wal", 4);51        unlink_if_exists(pVfs, zWal);52      }53    }54  }55}56 57static Pager* get_main_pager(sqlite3 *db){58  /* Main database is index 0 */59  Btree *pBt = db->aDb[0].pBt;60  TEST_ASSERT_NOT_NULL(pBt);61  Pager *pPager = sqlite3BtreePager(pBt);62  TEST_ASSERT_NOT_NULL(pPager);63  return pPager;64}65 66static int file_exists(sqlite3_vfs *pVfs, const char *zPath){67  int exists = 0;68  if( zPath==NULL ) return 0;69  (void)sqlite3OsAccess(pVfs, zPath, SQLITE_ACCESS_EXISTS, &exists);70  return exists;71}72 73/* Open the pager's journal file explicitly via VFS (and create it if needed) */74static void open_pager_journal(Pager *pPager){75  TEST_ASSERT_NOT_NULL(pPager);76  TEST_ASSERT_NOT_NULL(pPager->pVfs);77  TEST_ASSERT_NOT_NULL(pPager->jfd);78  TEST_ASSERT_NOT_NULL(pPager->zJournal);79 80  int fout = 0;81  int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_JOURNAL;82  int rc = sqlite3OsOpen(pPager->pVfs, pPager->zJournal, pPager->jfd, flags, &fout);83  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);84  TEST_ASSERT_TRUE(isOpen(pPager->jfd));85}86 87/* Unity fixtures */88 89void setUp(void) {90  /* Nothing for now */91}92 93void tearDown(void) {94  /* Nothing for now */95}96 97/* Tests */98 99/* Basic mode change to DELETE on an on-disk DB */100void test_sqlite3PagerSetJournalMode_basic_change(void){101  const char *zDb = "test_pager_jm_basic.db";102  sqlite3 *db = open_db_filename(zDb);103  Pager *pPager = get_main_pager(db);104 105  /* Ensure we are not in WAL for this test */106  TEST_ASSERT_FALSE(pagerUseWal(pPager));107 108  int rcMode = sqlite3PagerSetJournalMode(pPager, PAGER_JOURNALMODE_DELETE);109  TEST_ASSERT_EQUAL_INT(PAGER_JOURNALMODE_DELETE, rcMode);110  TEST_ASSERT_EQUAL_INT(PAGER_JOURNALMODE_DELETE, (int)pPager->journalMode);111 112  close_db_and_cleanup(db, zDb);113}114 115/* Transition from PERSIST to DELETE should delete the on-disk journal file */116void test_sqlite3PagerSetJournalMode_persist_to_delete_removes_journal(void){117  const char *zDb = "test_pager_jm_persist_del.db";118  sqlite3 *db = open_db_filename(zDb);119  Pager *pPager = get_main_pager(db);120  sqlite3_vfs *pVfs = pPager->pVfs;121 122  TEST_ASSERT_FALSE(pagerUseWal(pPager));123 124  /* Set to PERSIST, create/open a journal file, and verify it exists */125  int ret = sqlite3PagerSetJournalMode(pPager, PAGER_JOURNALMODE_PERSIST);126  TEST_ASSERT_EQUAL_INT(PAGER_JOURNALMODE_PERSIST, ret);127  TEST_ASSERT_EQUAL_INT(PAGER_JOURNALMODE_PERSIST, (int)pPager->journalMode);128 129  open_pager_journal(pPager);130  TEST_ASSERT_NOT_NULL(pPager->zJournal);131  TEST_ASSERT_TRUE(file_exists(pVfs, pPager->zJournal));132 133  /* Switch to DELETE: this should close and delete the journal file */134  ret = sqlite3PagerSetJournalMode(pPager, PAGER_JOURNALMODE_DELETE);135  TEST_ASSERT_EQUAL_INT(PAGER_JOURNALMODE_DELETE, ret);136  TEST_ASSERT_EQUAL_INT(PAGER_JOURNALMODE_DELETE, (int)pPager->journalMode);137 138  int exists = file_exists(pVfs, pPager->zJournal);139  TEST_ASSERT_FALSE_MESSAGE(exists, "Journal file should have been deleted on PERSIST->DELETE transition");140 141  close_db_and_cleanup(db, zDb);142}143 144/* No-op when setting to the same mode (TRUNCATE): existing journal should not be deleted */145void test_sqlite3PagerSetJournalMode_noop_does_not_delete_existing_journal(void){146  const char *zDb = "test_pager_jm_noop.db";147  sqlite3 *db = open_db_filename(zDb);148  Pager *pPager = get_main_pager(db);149  sqlite3_vfs *pVfs = pPager->pVfs;150 151  TEST_ASSERT_FALSE(pagerUseWal(pPager));152 153  /* Set to TRUNCATE and create a journal file */154  int ret = sqlite3PagerSetJournalMode(pPager, PAGER_JOURNALMODE_TRUNCATE);155  TEST_ASSERT_EQUAL_INT(PAGER_JOURNALMODE_TRUNCATE, ret);156  TEST_ASSERT_EQUAL_INT(PAGER_JOURNALMODE_TRUNCATE, (int)pPager->journalMode);157 158  open_pager_journal(pPager);159  TEST_ASSERT_TRUE(file_exists(pVfs, pPager->zJournal));160 161  /* Set to same mode again - should be a no-op (journal should remain) */162  ret = sqlite3PagerSetJournalMode(pPager, PAGER_JOURNALMODE_TRUNCATE);163  TEST_ASSERT_EQUAL_INT(PAGER_JOURNALMODE_TRUNCATE, ret);164  TEST_ASSERT_TRUE(file_exists(pVfs, pPager->zJournal));165 166  /* Cleanup */167  unlink_if_exists(pVfs, pPager->zJournal);168  close_db_and_cleanup(db, zDb);169}170 171/* Setting to OFF from a non-(TRUNCATE/PERSIST) previous mode should at least close jfd */172void test_sqlite3PagerSetJournalMode_off_closes_jfd_when_no_delete_branch(void){173  const char *zDb = "test_pager_jm_off_closes.db";174  sqlite3 *db = open_db_filename(zDb);175  Pager *pPager = get_main_pager(db);176 177  TEST_ASSERT_FALSE(pagerUseWal(pPager));178 179  /* Ensure previous mode is DELETE (bitwise & 5 == 0) to skip delete-branch */180  int ret = sqlite3PagerSetJournalMode(pPager, PAGER_JOURNALMODE_DELETE);181  TEST_ASSERT_EQUAL_INT(PAGER_JOURNALMODE_DELETE, ret);182  TEST_ASSERT_EQUAL_INT(PAGER_JOURNALMODE_DELETE, (int)pPager->journalMode);183 184  /* Open the journal file descriptor explicitly */185  open_pager_journal(pPager);186  TEST_ASSERT_TRUE(isOpen(pPager->jfd));187 188  /* Now set mode to OFF; since previous mode is not TRUNCATE/PERSIST,189     the else-if branch should run and close jfd */190  ret = sqlite3PagerSetJournalMode(pPager, PAGER_JOURNALMODE_OFF);191  TEST_ASSERT_EQUAL_INT(PAGER_JOURNALMODE_OFF, ret);192  TEST_ASSERT_FALSE(isOpen(pPager->jfd));193 194  close_db_and_cleanup(db, zDb);195}196 197/* In-memory database only allows MEMORY or OFF. Other modes are ignored. */198void test_sqlite3PagerSetJournalMode_memdb_restricts_modes(void){199  sqlite3 *db = 0;200  int rc = sqlite3_open(":memory:", &db);201  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);202  TEST_ASSERT_NOT_NULL(db);203 204  Pager *pPager = get_main_pager(db);205 206  /* Verify MEMDB macro behavior: initial mode must be MEMORY or OFF */207  int eOld = (int)pPager->journalMode;208  TEST_ASSERT_TRUE_MESSAGE(209    eOld==PAGER_JOURNALMODE_MEMORY || eOld==PAGER_JOURNALMODE_OFF,210    "In-memory pager initial journalMode must be MEMORY or OFF"211  );212 213  /* Attempt to set to DELETE - should be ignored and return current mode */214  int ret = sqlite3PagerSetJournalMode(pPager, PAGER_JOURNALMODE_DELETE);215  TEST_ASSERT_EQUAL_INT(eOld, ret);216  TEST_ASSERT_EQUAL_INT(eOld, (int)pPager->journalMode);217 218  /* Setting to MEMORY should be allowed and result in MEMORY */219  ret = sqlite3PagerSetJournalMode(pPager, PAGER_JOURNALMODE_MEMORY);220  TEST_ASSERT_EQUAL_INT(PAGER_JOURNALMODE_MEMORY, ret);221  TEST_ASSERT_EQUAL_INT(PAGER_JOURNALMODE_MEMORY, (int)pPager->journalMode);222 223  sqlite3_close(db);224}225 226/* Main */227 228int main(void) {229  UNITY_BEGIN();230  RUN_TEST(test_sqlite3PagerSetJournalMode_basic_change);231  RUN_TEST(test_sqlite3PagerSetJournalMode_persist_to_delete_removes_journal);232  RUN_TEST(test_sqlite3PagerSetJournalMode_noop_does_not_delete_existing_journal);233  RUN_TEST(test_sqlite3PagerSetJournalMode_off_closes_jfd_when_no_delete_branch);234  RUN_TEST(test_sqlite3PagerSetJournalMode_memdb_restricts_modes);235  return UNITY_END();236}