Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_pager_pagerOpenSavepoint.c218 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/* Prototype of the provided test wrapper for the static function */8int test_pagerOpenSavepoint(Pager *pPager, int nSavepoint);9 10static void exec_sql_ok(sqlite3 *db, const char *sql){11  char *zErr = 0;12  int rc = sqlite3_exec(db, sql, 0, 0, &zErr);13  if( rc!=SQLITE_OK ){14    fprintf(stderr, "SQL error (%d): %s while executing: %s\n", rc, zErr?zErr:"(null)", sql);15  }16  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);17  if( zErr ) sqlite3_free(zErr);18}19 20static sqlite3* open_file_db(const char *zFilename){21  sqlite3 *db = 0;22  int rc = sqlite3_open(zFilename, &db);23  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);24  TEST_ASSERT_NOT_NULL(db);25  return db;26}27 28static Pager* getPagerFromDb(sqlite3 *db){29  TEST_ASSERT_NOT_NULL(db);30  /* Main database at schema index 0 */31  TEST_ASSERT_NOT_NULL(db->aDb);32  TEST_ASSERT_NOT_NULL(db->aDb[0].pBt);33  return sqlite3BtreePager(db->aDb[0].pBt);34}35 36static void prepare_db_baseline(sqlite3 *db){37  /* Ensure rollback-journal mode (not WAL) and create content so dbSize>0 */38  exec_sql_ok(db, "PRAGMA journal_mode=DELETE;");39  exec_sql_ok(db, "BEGIN IMMEDIATE;");  /* Ensure db file exists/writable if needed */40  exec_sql_ok(db, "CREATE TABLE IF NOT EXISTS t(x);");41  exec_sql_ok(db, "COMMIT;");           /* Persist initial content */42}43 44static void begin_immediate(sqlite3 *db){45  exec_sql_ok(db, "BEGIN IMMEDIATE;");46}47 48static void rollback_and_close(sqlite3 *db, const char *zFilename){49  /* Safe rollback (in case transaction is active) and close */50  if( db ){51    sqlite3_exec(db, "ROLLBACK;", 0, 0, 0);52    sqlite3_close(db);53  }54  if( zFilename ){55    /* Best-effort cleanup */56    remove(zFilename);57  }58}59 60void setUp(void) {61  /* No-op */62}63 64void tearDown(void) {65  /* No-op */66}67 68/* Test 1: Create a single savepoint with no prior journal activity (journalOff==0).69   Validate that the savepoint is created and initialized correctly. */70void test_pagerOpenSavepoint_basic_no_dirty(void){71  const char *zDb = "test_pagerOpenSavepoint_basic_no_dirty.sqlite";72  sqlite3 *db = open_file_db(zDb);73  prepare_db_baseline(db);74 75  begin_immediate(db);76  Pager *pPager = getPagerFromDb(db);77 78  /* Preconditions expected by the function/asserts */79  TEST_ASSERT_TRUE(pPager->useJournal!=0);80  TEST_ASSERT_TRUE(pPager->eState>=PAGER_WRITER_LOCKED);81 82  int n0 = pPager->nSavepoint;83  TEST_ASSERT_EQUAL_INT(0, n0);84 85  Pgno dbSizeAtCall = pPager->dbSize;86  i64 joBefore = pPager->journalOff;  /* likely 0 since no dirty pages yet */87 88  int rc = test_pagerOpenSavepoint(pPager, 1);89  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);90 91  TEST_ASSERT_EQUAL_INT(1, pPager->nSavepoint);92  TEST_ASSERT_NOT_NULL(pPager->aSavepoint);93 94  PagerSavepoint *ps0 = &pPager->aSavepoint[0];95  TEST_ASSERT_NOT_NULL(ps0->pInSavepoint);96  TEST_ASSERT_EQUAL_INT(1, ps0->bTruncateOnRelease);97 98  TEST_ASSERT_EQUAL_UINT(dbSizeAtCall, ps0->nOrig);99  TEST_ASSERT_EQUAL_INT(pPager->nSubRec, ps0->iSubRec);100 101  if( joBefore>0 ){102    TEST_ASSERT_TRUE(((sqlite3_int64)ps0->iOffset) == joBefore);103  }else{104    /* When journalOff==0 at call time, pagerOpenSavepoint uses header size.105       We can at least assert it is non-zero and not negative. */106    TEST_ASSERT_TRUE(ps0->iOffset > 0);107  }108 109  rollback_and_close(db, zDb);110}111 112/* Test 2: Create a savepoint after performing a write, ensuring journalOff>0.113   Validate iOffset captured equals journalOff at time of creation and other fields match. */114void test_pagerOpenSavepoint_after_journal_activity(void){115  const char *zDb = "test_pagerOpenSavepoint_after_journal.sqlite";116  sqlite3 *db = open_file_db(zDb);117  prepare_db_baseline(db);118 119  begin_immediate(db);120  Pager *pPager = getPagerFromDb(db);121 122  /* Perform a write to ensure journal file is opened and journalOff>0 */123  exec_sql_ok(db, "INSERT INTO t VALUES(1);");124 125  Pgno dbSizeAtCall = pPager->dbSize;126  i64 joBefore = pPager->journalOff;127  int subRecBefore = pPager->nSubRec;128 129  TEST_ASSERT_TRUE_MESSAGE(joBefore>0, "Expected journalOff>0 after write");130 131  int rc = test_pagerOpenSavepoint(pPager, 1);132  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);133 134  TEST_ASSERT_EQUAL_INT(1, pPager->nSavepoint);135  TEST_ASSERT_NOT_NULL(pPager->aSavepoint);136 137  PagerSavepoint *ps0 = &pPager->aSavepoint[0];138  TEST_ASSERT_NOT_NULL(ps0->pInSavepoint);139  TEST_ASSERT_EQUAL_INT(1, ps0->bTruncateOnRelease);140 141  TEST_ASSERT_EQUAL_UINT(dbSizeAtCall, ps0->nOrig);142  TEST_ASSERT_EQUAL_INT(subRecBefore, ps0->iSubRec);143  TEST_ASSERT_TRUE(((sqlite3_int64)ps0->iOffset) == joBefore);144 145  rollback_and_close(db, zDb);146}147 148/* Test 3: Grow the savepoint array (realloc path). Ensure prior entries are preserved and149   new entries reflect the current pager state at the time of growth. */150void test_pagerOpenSavepoint_grow_and_preserve(void){151  const char *zDb = "test_pagerOpenSavepoint_grow.sqlite";152  sqlite3 *db = open_file_db(zDb);153  prepare_db_baseline(db);154 155  begin_immediate(db);156  Pager *pPager = getPagerFromDb(db);157 158  /* First write to open journal, then create first savepoint */159  exec_sql_ok(db, "INSERT INTO t VALUES(10);");160  Pgno dbSize0 = pPager->dbSize;161  i64 jo0 = pPager->journalOff;162  int subRec0 = pPager->nSubRec;163 164  TEST_ASSERT_TRUE_MESSAGE(jo0>0, "Expected journalOff>0 after first write");165  int rc = test_pagerOpenSavepoint(pPager, 1);166  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);167  TEST_ASSERT_EQUAL_INT(1, pPager->nSavepoint);168 169  /* Snapshot the first savepoint's fields */170  PagerSavepoint ps0 = pPager->aSavepoint[0];171 172  /* Perform additional write to advance journal state, then grow to 3 savepoints */173  exec_sql_ok(db, "INSERT INTO t VALUES(20);");174  Pgno dbSize1 = pPager->dbSize;175  i64 jo1 = pPager->journalOff;176  int subRec1 = pPager->nSubRec;177  TEST_ASSERT_TRUE_MESSAGE(jo1>0, "Expected journalOff>0 after second write");178 179  rc = test_pagerOpenSavepoint(pPager, 3);180  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);181  TEST_ASSERT_EQUAL_INT(3, pPager->nSavepoint);182  TEST_ASSERT_NOT_NULL(pPager->aSavepoint);183 184  /* Verify first savepoint preserved */185  TEST_ASSERT_NOT_NULL(pPager->aSavepoint[0].pInSavepoint);186  TEST_ASSERT_EQUAL_INT(ps0.bTruncateOnRelease, pPager->aSavepoint[0].bTruncateOnRelease);187  TEST_ASSERT_EQUAL_UINT(ps0.nOrig, pPager->aSavepoint[0].nOrig);188  TEST_ASSERT_EQUAL_INT(ps0.iSubRec, pPager->aSavepoint[0].iSubRec);189  TEST_ASSERT_TRUE(((sqlite3_int64)ps0.iOffset) == (sqlite3_int64)pPager->aSavepoint[0].iOffset);190 191  /* Verify new savepoints [1] and [2] reflect current pager state at creation */192  PagerSavepoint *ps1 = &pPager->aSavepoint[1];193  PagerSavepoint *ps2 = &pPager->aSavepoint[2];194 195  TEST_ASSERT_NOT_NULL(ps1->pInSavepoint);196  TEST_ASSERT_NOT_NULL(ps2->pInSavepoint);197  TEST_ASSERT_EQUAL_INT(1, ps1->bTruncateOnRelease);198  TEST_ASSERT_EQUAL_INT(1, ps2->bTruncateOnRelease);199 200  TEST_ASSERT_EQUAL_UINT(dbSize1, ps1->nOrig);201  TEST_ASSERT_EQUAL_UINT(dbSize1, ps2->nOrig);202 203  TEST_ASSERT_EQUAL_INT(subRec1, ps1->iSubRec);204  TEST_ASSERT_EQUAL_INT(subRec1, ps2->iSubRec);205 206  TEST_ASSERT_TRUE(((sqlite3_int64)ps1->iOffset) == jo1);207  TEST_ASSERT_TRUE(((sqlite3_int64)ps2->iOffset) == jo1);208 209  rollback_and_close(db, zDb);210}211 212int main(void) {213  UNITY_BEGIN();214  RUN_TEST(test_pagerOpenSavepoint_basic_no_dirty);215  RUN_TEST(test_pagerOpenSavepoint_after_journal_activity);216  RUN_TEST(test_pagerOpenSavepoint_grow_and_preserve);217  return UNITY_END();218}