AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Dummy sqlite3_file instances to satisfy isOpen() checks in asserts */7static sqlite3_file gOpenFile;8static sqlite3_file gClosedFile;9 10/* Minimal io_methods to mark a file as "open". Only the pointer being non-NULL matters here. */11static const sqlite3_io_methods gDummyIoMethods = {12 1, /* iVersion */13 0, /* xClose */14 0, /* xRead */15 0, /* xWrite */16 0, /* xTruncate */17 0, /* xSync */18 0, /* xFileSize */19 0, /* xLock */20 0, /* xUnlock */21 0, /* xCheckReservedLock */22 0, /* xFileControl */23 0, /* xSectorSize */24 0, /* xDeviceCharacteristics */25 0, /* xShmMap */26 0, /* xShmLock */27 0, /* xShmBarrier */28 0, /* xShmUnmap */29 0, /* xFetch */30 0 /* xUnfetch */31};32 33void setUp(void) {34 /* Initialize dummy files: one "open", one "closed" */35 memset(&gOpenFile, 0, sizeof(gOpenFile));36 memset(&gClosedFile, 0, sizeof(gClosedFile));37 gOpenFile.pMethods = &gDummyIoMethods; /* Marks as open for isOpen() */38 gClosedFile.pMethods = 0; /* Marks as closed for isOpen() */39}40 41void tearDown(void) {42 /* No cleanup needed */43}44 45/* Helper to initialize common Pager fields safely for tests */46static void initPagerCommon(Pager *p){47 memset(p, 0, sizeof(*p));48 p->zFilename = (char*)"testdb";49 p->jfd = &gClosedFile; /* journal file handle; "closed" for OFF mode assert */50 p->fd = &gOpenFile; /* main db file handle; may be overridden per test */51 p->journalMode = PAGER_JOURNALMODE_OFF; /* Satisfy (journalMode==OFF || useJournal) */52 p->useJournal = 0;53 p->setSuper = 0;54 p->errCode = SQLITE_OK;55 p->pWal = 0;56 /* Ensure size fields match when required by asserts */57 p->dbSize = 0;58 p->dbOrigSize = 0;59 p->dbFileSize = 0;60 p->dbHintSize = 0;61 /* Change-counter state */62 p->changeCountDone = 0;63 /* Lock state not unknown and at least RESERVED when needed */64 p->eLock = RESERVED_LOCK;65}66 67/* 1) Early return when no database changes have been made:68 eState == PAGER_WRITER_LOCKED (< PAGER_WRITER_CACHEMOD) */69void test_sqlite3PagerCommitPhaseOne_early_return_no_changes(void) {70 Pager p;71 initPagerCommon(&p);72 p.eState = PAGER_WRITER_LOCKED;73 p.tempFile = 0; /* Not a temp file; assert needs isOpen(fd) true */74 p.fd = &gOpenFile; /* isOpen(fd) satisfied */75 76 int rc = sqlite3PagerCommitPhaseOne(&p, 0, 0);77 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);78 /* Since it returns early, eState should remain unchanged */79 TEST_ASSERT_EQUAL_INT(PAGER_WRITER_LOCKED, p.eState);80}81 82/* 2) Flush-on-commit returns false for temp file with closed fd.83 Should restart backup (internally) and then set eState=FINISHED on exit (non-WAL). */84void test_sqlite3PagerCommitPhaseOne_tempfile_flush_false_sets_finished_nonwal(void) {85 Pager p;86 initPagerCommon(&p);87 p.eState = PAGER_WRITER_CACHEMOD;88 p.tempFile = 1;89 p.eLock = EXCLUSIVE_LOCK; /* tempFile implies exclusive lock in asserts */90 p.changeCountDone = 1; /* tempFile => changeCountDone must be true in asserts */91 p.fd = &gClosedFile; /* !isOpen(fd) => pagerFlushOnCommit returns 0 */92 93 int rc = sqlite3PagerCommitPhaseOne(&p, 0, 0);94 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);95 /* Not in WAL => commit_phase_one_exit should set FINISHED */96 TEST_ASSERT_EQUAL_INT(PAGER_WRITER_FINISHED, p.eState);97}98 99/* 3) Prior error is propagated immediately */100void test_sqlite3PagerCommitPhaseOne_prior_error_is_returned(void) {101 Pager p;102 initPagerCommon(&p);103 p.eState = PAGER_WRITER_LOCKED; /* Valid state for initial assert */104 p.errCode = SQLITE_IOERR; /* Prior error -> immediate return */105 p.tempFile = 0;106 p.fd = &gOpenFile; /* isOpen(fd) true to satisfy initial assert */107 108 int rc = sqlite3PagerCommitPhaseOne(&p, 0, 0);109 TEST_ASSERT_EQUAL_INT(SQLITE_IOERR, rc);110 TEST_ASSERT_EQUAL_INT(PAGER_WRITER_LOCKED, p.eState);111}112 113/* 4) Same flush-false path, but with WAL active (pWal!=NULL).114 Should NOT set eState to FINISHED on exit. */115void test_sqlite3PagerCommitPhaseOne_tempfile_flush_false_wal_does_not_finish(void) {116 Pager p;117 initPagerCommon(&p);118 p.eState = PAGER_WRITER_CACHEMOD;119 p.tempFile = 1;120 p.eLock = EXCLUSIVE_LOCK;121 p.changeCountDone = 1;122 p.fd = &gClosedFile; /* !isOpen(fd) => pagerFlushOnCommit returns 0 */123 p.pWal = (Wal*)&p; /* Non-NULL => pagerUseWal(pPager) is true */124 125 int rc = sqlite3PagerCommitPhaseOne(&p, 0, 0);126 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);127 /* Since WAL is in use, eState should not be updated to FINISHED */128 TEST_ASSERT_EQUAL_INT(PAGER_WRITER_CACHEMOD, p.eState);129}130 131int main(void) {132 UNITY_BEGIN();133 RUN_TEST(test_sqlite3PagerCommitPhaseOne_early_return_no_changes);134 RUN_TEST(test_sqlite3PagerCommitPhaseOne_tempfile_flush_false_sets_finished_nonwal);135 RUN_TEST(test_sqlite3PagerCommitPhaseOne_prior_error_is_returned);136 RUN_TEST(test_sqlite3PagerCommitPhaseOne_tempfile_flush_false_wal_does_not_finish);137 return UNITY_END();138}