Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_pager_sqlite3PagerMovepage.c258 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 8static int exec_sql(sqlite3 *db, const char *sql){9  return sqlite3_exec(db, sql, 0, 0, 0);10}11 12static Pgno get_rootpage(sqlite3 *db, const char *name){13  Pgno root = 0;14  sqlite3_stmt *stmt = 0;15  const char *zSql = "SELECT rootpage FROM sqlite_master WHERE name=?1";16  int rc = sqlite3_prepare_v2(db, zSql, -1, &stmt, 0);17  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);18  rc = sqlite3_bind_text(stmt, 1, name, -1, SQLITE_TRANSIENT);19  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);20  rc = sqlite3_step(stmt);21  TEST_ASSERT_EQUAL_INT(SQLITE_ROW, rc);22  root = (Pgno)sqlite3_column_int(stmt, 0);23  sqlite3_finalize(stmt);24  return root;25}26 27static void create_simple_schema(sqlite3 *db, const char *tname){28  char sql[256];29  int rc;30  rc = exec_sql(db, "BEGIN IMMEDIATE;");31  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);32  snprintf(sql, sizeof(sql), "CREATE TABLE %s(x);", tname);33  rc = exec_sql(db, sql);34  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);35  snprintf(sql, sizeof(sql), "INSERT INTO %s VALUES(1);", tname);36  rc = exec_sql(db, sql);37  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);38}39 40void setUp(void) {41  /* No global setup needed */42}43 44void tearDown(void) {45  /* No global teardown needed */46}47 48/* Test 1: Basic move on a disk database with an empty destination page */49void test_sqlite3PagerMovepage_basic_move_disk(void){50  sqlite3 *db = 0;51  int rc;52  DbPage *pSrc = 0;53  DbPage *pCheck = 0;54 55  rc = sqlite3_open("test_pager_move_disk1.sqlite", &db);56  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);57 58  create_simple_schema(db, "t1");59  Pgno srcPgno = get_rootpage(db, "t1");60  TEST_ASSERT_TRUE(srcPgno > 1); /* avoid page 1 */61 62  /* Access internal Pager */63  Btree *pBt = db->aDb[0].pBt;64  TEST_ASSERT_NOT_NULL(pBt);65  Pager *pPager = sqlite3BtreePager(pBt);66  TEST_ASSERT_NOT_NULL(pPager);67  TEST_ASSERT(pPager->tempFile==0); /* disk database for this test */68 69  /* Get the source page and mark it writeable to enter writer state */70  rc = sqlite3PagerGet(pPager, srcPgno, &pSrc, 0);71  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);72  TEST_ASSERT_NOT_NULL(pSrc);73  rc = sqlite3PagerWrite(pSrc);74  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);75 76  Pgno destPgno = srcPgno + 3; /* choose a different page number */77 78  /* Perform the move */79  rc = sqlite3PagerMovepage(pPager, pSrc, destPgno, 0);80  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);81  TEST_ASSERT_EQUAL_UINT(destPgno, pSrc->pgno);82 83  /* Verify the destination page is accessible */84  rc = sqlite3PagerGet(pPager, destPgno, &pCheck, 0);85  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);86  TEST_ASSERT_NOT_NULL(pCheck);87  /* pCheck may be the same PgHdr as pSrc; both refs must be released */88 89  /* Cleanup */90  sqlite3PagerUnrefNotNull(pCheck);91  sqlite3PagerUnrefNotNull(pSrc);92  rc = exec_sql(db, "ROLLBACK;");93  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);94  sqlite3_close(db);95}96 97/* Test 2: Move when destination page is already present in cache (nRef==1) on disk DB */98void test_sqlite3PagerMovepage_overwrite_existing_dest_in_cache_disk(void){99  sqlite3 *db = 0;100  int rc;101  DbPage *pSrc = 0;102  DbPage *pDestHold = 0;103  DbPage *pVerify = 0;104 105  rc = sqlite3_open("test_pager_move_disk2.sqlite", &db);106  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);107 108  create_simple_schema(db, "t2");109  Pgno srcPgno = get_rootpage(db, "t2");110  TEST_ASSERT_TRUE(srcPgno > 1);111 112  Btree *pBt = db->aDb[0].pBt;113  TEST_ASSERT_NOT_NULL(pBt);114  Pager *pPager = sqlite3BtreePager(pBt);115  TEST_ASSERT_NOT_NULL(pPager);116  TEST_ASSERT(pPager->tempFile==0);117 118  /* Prepare source page */119  rc = sqlite3PagerGet(pPager, srcPgno, &pSrc, 0);120  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);121  rc = sqlite3PagerWrite(pSrc);122  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);123 124  Pgno destPgno = srcPgno + 5;125 126  /* Ensure destination page is present in cache and referenced once */127  rc = sqlite3PagerGet(pPager, destPgno, &pDestHold, PAGER_GET_NOCONTENT);128  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);129  TEST_ASSERT_NOT_NULL(pDestHold);130  /* Do not unref pDestHold yet to keep nRef==1 during move */131 132  /* Move source to destination - should drop/move away the dest page */133  rc = sqlite3PagerMovepage(pPager, pSrc, destPgno, 0);134  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);135  TEST_ASSERT_EQUAL_UINT(destPgno, pSrc->pgno);136 137  /* Verify we can get the destination page (it should now be pSrc) */138  rc = sqlite3PagerGet(pPager, destPgno, &pVerify, 0);139  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);140  TEST_ASSERT_NOT_NULL(pVerify);141 142  /* Cleanup references. pVerify may equal pSrc. All refs must be released */143  sqlite3PagerUnrefNotNull(pVerify);144  sqlite3PagerUnrefNotNull(pDestHold);145  sqlite3PagerUnrefNotNull(pSrc);146 147  rc = exec_sql(db, "ROLLBACK;");148  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);149  sqlite3_close(db);150}151 152/* Test 3: In-memory (tempFile) database branch preserves original page at old pgno */153void test_sqlite3PagerMovepage_in_memory_preserves_oldpage(void){154  sqlite3 *db = 0;155  int rc;156  DbPage *pSrc = 0;157  DbPage *pDestHold = 0;158  DbPage *pBack = 0;159 160  rc = sqlite3_open(":memory:", &db);161  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);162 163  create_simple_schema(db, "t3");164  Pgno srcPgno = get_rootpage(db, "t3");165  TEST_ASSERT_TRUE(srcPgno > 1);166 167  Btree *pBt = db->aDb[0].pBt;168  TEST_ASSERT_NOT_NULL(pBt);169  Pager *pPager = sqlite3BtreePager(pBt);170  TEST_ASSERT_NOT_NULL(pPager);171  TEST_ASSERT(pPager->tempFile!=0); /* In-memory/temporary pager */172 173  /* Prepare source page */174  rc = sqlite3PagerGet(pPager, srcPgno, &pSrc, 0);175  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);176  /* For tempFile, sqlite3PagerMovepage will call sqlite3PagerWrite itself, */177  /* but calling it here is fine and ensures writer state. */178  rc = sqlite3PagerWrite(pSrc);179  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);180 181  Pgno destPgno = srcPgno + 7;182 183  /* Ensure destination page is present in cache and referenced */184  rc = sqlite3PagerGet(pPager, destPgno, &pDestHold, PAGER_GET_NOCONTENT);185  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);186  TEST_ASSERT_NOT_NULL(pDestHold);187 188  /* Move source to destination */189  rc = sqlite3PagerMovepage(pPager, pSrc, destPgno, 0);190  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);191  TEST_ASSERT_EQUAL_UINT(destPgno, pSrc->pgno);192 193  /* In tempFile case, original page should be preserved at old pgno */194  rc = sqlite3PagerGet(pPager, srcPgno, &pBack, 0);195  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);196  TEST_ASSERT_NOT_NULL(pBack);197  /* The preserved page at old pgno should not be the same PgHdr as pSrc */198  TEST_ASSERT(pBack != pSrc);199  TEST_ASSERT_EQUAL_UINT(srcPgno, pBack->pgno);200 201  /* Cleanup */202  sqlite3PagerUnrefNotNull(pBack);203  sqlite3PagerUnrefNotNull(pDestHold);204  sqlite3PagerUnrefNotNull(pSrc);205  rc = exec_sql(db, "ROLLBACK;");206  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);207  sqlite3_close(db);208}209 210/* Test 4: isCommit=1 path (should still move without extra sync dependencies) */211void test_sqlite3PagerMovepage_isCommit_flag(void){212  sqlite3 *db = 0;213  int rc;214  DbPage *pSrc = 0;215  DbPage *pCheck = 0;216 217  rc = sqlite3_open("test_pager_move_disk3.sqlite", &db);218  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);219 220  create_simple_schema(db, "t4");221  Pgno srcPgno = get_rootpage(db, "t4");222  TEST_ASSERT_TRUE(srcPgno > 1);223 224  Btree *pBt = db->aDb[0].pBt;225  TEST_ASSERT_NOT_NULL(pBt);226  Pager *pPager = sqlite3BtreePager(pBt);227  TEST_ASSERT_NOT_NULL(pPager);228 229  rc = sqlite3PagerGet(pPager, srcPgno, &pSrc, 0);230  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);231  rc = sqlite3PagerWrite(pSrc);232  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);233 234  Pgno destPgno = srcPgno + 9;235 236  rc = sqlite3PagerMovepage(pPager, pSrc, destPgno, 1 /* isCommit */);237  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);238  TEST_ASSERT_EQUAL_UINT(destPgno, pSrc->pgno);239 240  rc = sqlite3PagerGet(pPager, destPgno, &pCheck, 0);241  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);242  TEST_ASSERT_NOT_NULL(pCheck);243 244  sqlite3PagerUnrefNotNull(pCheck);245  sqlite3PagerUnrefNotNull(pSrc);246  rc = exec_sql(db, "ROLLBACK;");247  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);248  sqlite3_close(db);249}250 251int main(void){252  UNITY_BEGIN();253  RUN_TEST(test_sqlite3PagerMovepage_basic_move_disk);254  RUN_TEST(test_sqlite3PagerMovepage_overwrite_existing_dest_in_cache_disk);255  RUN_TEST(test_sqlite3PagerMovepage_in_memory_preserves_oldpage);256  RUN_TEST(test_sqlite3PagerMovepage_isCommit_flag);257  return UNITY_END();258}