Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_pcache_sqlite3PcacheMove.c166 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6/* Stub xStress callback for PCache */7static int stubStress(void *p, PgHdr *pPg){8  /* Attempt to make page clean if asked to spill */9  if( pPg && (pPg->flags & PGHDR_DIRTY) ){10    sqlite3PcacheMakeClean(pPg);11  }12  return SQLITE_OK;13}14 15static PCache *pcache_new(int szPage, int szExtra, int bPurgeable){16  int rc;17  PCache *p = (PCache*)sqlite3_malloc(sqlite3PcacheSize());18  TEST_ASSERT_NOT_NULL(p);19  rc = sqlite3PcacheOpen(szPage, szExtra, bPurgeable, stubStress, NULL, p);20  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);21  return p;22}23 24static void pcache_free(PCache *p){25  if( p ){26    /* Close underlying cache */27    sqlite3PcacheClose(p);28    sqlite3_free(p);29  }30}31 32static PgHdr* pcache_alloc_page(PCache *pCache, Pgno pgno){33  sqlite3_pcache_page *pLower = sqlite3PcacheFetch(pCache, pgno, 3);34  TEST_ASSERT_NOT_NULL_MESSAGE(pLower, "Fetch for create returned NULL");35  PgHdr *pPg = sqlite3PcacheFetchFinish(pCache, pgno, pLower);36  TEST_ASSERT_NOT_NULL(pPg);37  TEST_ASSERT_EQUAL_INT(pgno, (int)pPg->pgno);38  return pPg;39}40 41/* Fetch an existing page (createFlag=0). If found, convert to PgHdr and42** return it with a new reference. Caller must sqlite3PcacheRelease().43*/44static PgHdr* pcache_get_existing_pg(PCache *pCache, Pgno pgno){45  sqlite3_pcache_page *pLower = sqlite3PcacheFetch(pCache, pgno, 0);46  if( pLower==NULL ) return NULL;47  return sqlite3PcacheFetchFinish(pCache, pgno, pLower);48}49 50void setUp(void) {51  int rc = sqlite3_initialize();52  (void)rc; /* ignore return; SQLite may already be initialized */53}54 55void tearDown(void) {56  sqlite3_shutdown();57}58 59/* Test 1: Move a page to an unoccupied page number. */60void test_sqlite3PcacheMove_rekey_to_empty(void){61  PCache *pc = pcache_new(256, 64, 1);62 63  PgHdr *p = pcache_alloc_page(pc, 5);64  /* Baseline: ensure new target 10 does not exist */65  PgHdr *pre = pcache_get_existing_pg(pc, 10);66  if( pre ){ sqlite3PcacheRelease(pre); TEST_FAIL_MESSAGE("Target unexpectedly exists before move"); }67 68  sqlite3_pcache_page *lowerBefore = p->pPage;69  TEST_ASSERT_NOT_NULL(lowerBefore);70 71  /* Move to new pgno */72  sqlite3PcacheMove(p, 10);73 74  /* PgHdr.pgno updated */75  TEST_ASSERT_EQUAL_INT(10, (int)p->pgno);76 77  /* Old key should be gone */78  PgHdr *chkOld = pcache_get_existing_pg(pc, 5);79  TEST_ASSERT_NULL(chkOld);80 81  /* New key should return the same underlying page as p->pPage */82  sqlite3_pcache_page *lowerFetched = sqlite3PcacheFetch(pc, 10, 0);83  TEST_ASSERT_NOT_NULL(lowerFetched);84  /* Convert to PgHdr to balance refs then release */85  PgHdr *pChk = sqlite3PcacheFetchFinish(pc, 10, lowerFetched);86  TEST_ASSERT_NOT_NULL(pChk);87  TEST_ASSERT_EQUAL_PTR(p, pChk);88  sqlite3PcacheRelease(pChk);89 90  /* Release original ref and cleanup */91  sqlite3PcacheRelease(p);92  pcache_free(pc);93}94 95/* Test 2: Move a page to an existing unreferenced destination page.96** The destination must be dropped and replaced by the moved page.97*/98void test_sqlite3PcacheMove_overwrites_existing_unref_destination(void){99  PCache *pc = pcache_new(512, 64, 1);100 101  PgHdr *pA = pcache_alloc_page(pc, 4);102  PgHdr *pB = pcache_alloc_page(pc, 9);103 104  /* Release B to ensure nRef==0 so move can drop it */105  sqlite3PcacheRelease(pB);106 107  int nBefore = sqlite3PcachePagecount(pc);108  TEST_ASSERT_TRUE(nBefore >= 1);109 110  /* Perform the move */111  sqlite3PcacheMove(pA, 9);112 113  /* Old key should be absent */114  PgHdr *chkOld = pcache_get_existing_pg(pc, 4);115  TEST_ASSERT_NULL(chkOld);116 117  /* New key should return pA */118  PgHdr *chkNew = pcache_get_existing_pg(pc, 9);119  TEST_ASSERT_NOT_NULL(chkNew);120  TEST_ASSERT_EQUAL_PTR(pA, chkNew);121  sqlite3PcacheRelease(chkNew);122 123  /* Pagecount should have decreased by 1 due to dropping original dest */124  int nAfter = sqlite3PcachePagecount(pc);125  TEST_ASSERT_EQUAL_INT(nBefore - 1, nAfter);126 127  /* Release and cleanup */128  sqlite3PcacheRelease(pA);129  pcache_free(pc);130}131 132/* Test 3: Move a dirty page with NEED_SYNC set; flags should be preserved. */133void test_sqlite3PcacheMove_preserves_dirty_and_need_sync_flags(void){134  PCache *pc = pcache_new(1024, 64, 1);135 136  PgHdr *p = pcache_alloc_page(pc, 12);137 138  /* Make it dirty and set NEED_SYNC + WRITEABLE */139  sqlite3PcacheMakeDirty(p);140  p->flags |= (PGHDR_NEED_SYNC | PGHDR_WRITEABLE);141 142  /* Sanity before move */143  TEST_ASSERT_TRUE( (p->flags & PGHDR_DIRTY)!=0 );144  TEST_ASSERT_TRUE( (p->flags & PGHDR_NEED_SYNC)!=0 );145 146  /* Move to a new, empty pgno */147  sqlite3PcacheMove(p, 15);148 149  /* Flags preserved */150  TEST_ASSERT_TRUE( (p->flags & PGHDR_DIRTY)!=0 );151  TEST_ASSERT_TRUE( (p->flags & PGHDR_NEED_SYNC)!=0 );152  TEST_ASSERT_EQUAL_INT(15, (int)p->pgno);153 154  /* Cleanup: make clean then release */155  sqlite3PcacheMakeClean(p);156  sqlite3PcacheRelease(p);157  pcache_free(pc);158}159 160int main(void){161  UNITY_BEGIN();162  RUN_TEST(test_sqlite3PcacheMove_rekey_to_empty);163  RUN_TEST(test_sqlite3PcacheMove_overwrites_existing_unref_destination);164  RUN_TEST(test_sqlite3PcacheMove_preserves_dirty_and_need_sync_flags);165  return UNITY_END();166}