Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_pcache_sqlite3PcacheTruncate.c186 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Dummy stress callback - not used by these tests but required by sqlite3PcacheOpen */7static int dummyStress(void *pStress, PgHdr *pPg){8  UNUSED_PARAMETER(pStress);9  UNUSED_PARAMETER(pPg);10  return SQLITE_OK;11}12 13static void *allocPCacheMem(void){14  int n = sqlite3PcacheSize();15  void *p = sqlite3_malloc(n);16  TEST_ASSERT_NOT_NULL_MESSAGE(p, "sqlite3_malloc for PCache failed");17  memset(p, 0, n);18  return p;19}20 21static void freePCacheMem(void *p){22  sqlite3_free(p);23}24 25void setUp(void) {26  /* Ensure the pcache subsystem is initialized for each test */27  int rc = sqlite3PcacheInitialize();28  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3PcacheInitialize failed");29}30 31void tearDown(void) {32  /* No global teardown needed specifically for these tests */33}34 35/* Helper: Try to fetch a page without creating it. If present, finish and release it.36** Returns 1 if page existed, 0 if not. */37static int pageExistsNoCreate(PCache *pCache, Pgno pgno){38  sqlite3_pcache_page *pLower = sqlite3PcacheFetch(pCache, pgno, 0);39  if( pLower ){40    PgHdr *pHdr = sqlite3PcacheFetchFinish(pCache, pgno, pLower);41    /* Release immediately to avoid leaking a reference */42    sqlite3PcacheRelease(pHdr);43    return 1;44  }45  return 0;46}47 48/* Helper: Count and verify dirty list contents using sqlite3PcacheDirtyList */49static int countDirtyPagesAndCheckMax(PCache *pCache, Pgno maxPgno, int *pHas2){50  PgHdr *p;51  int cnt = 0;52  if( pHas2 ) *pHas2 = 0;53  p = sqlite3PcacheDirtyList(pCache);54  while( p ){55    cnt++;56    TEST_ASSERT_TRUE_MESSAGE(p->pgno <= maxPgno, "Dirty page with pgno greater than expected max found after truncate");57    if( pHas2 && p->pgno==2 ) *pHas2 = 1;58    p = p->pDirty;59  }60  return cnt;61}62 63void test_sqlite3PcacheTruncate_cleans_and_drops_pages_above_threshold(void){64  const int pageSize = 64;65  void *pMem = allocPCacheMem();66  PCache *pCache = (PCache*)pMem;67 68  int rc = sqlite3PcacheOpen(pageSize, 32, 0, dummyStress, 0, pCache);69  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3PcacheOpen failed");70 71  /* Create pages 1..6 and mark 2,4,6 as dirty */72  for(Pgno i=1; i<=6; i++){73    sqlite3_pcache_page *pLower = sqlite3PcacheFetch(pCache, i, 3);74    TEST_ASSERT_NOT_NULL_MESSAGE(pLower, "Fetch(create) failed");75    PgHdr *pHdr = sqlite3PcacheFetchFinish(pCache, i, pLower);76    TEST_ASSERT_NOT_NULL(pHdr);77    if( i==2 || i==4 || i==6 ){78      sqlite3PcacheMakeDirty(pHdr);79    }80    sqlite3PcacheRelease(pHdr);81  }82 83  /* Truncate to pgno=3: pages >3 should be dropped; dirty pages >3 should be cleaned */84  sqlite3PcacheTruncate(pCache, 3);85 86  int has2 = 0;87  int dirtyCnt = countDirtyPagesAndCheckMax(pCache, 3, &has2);88  TEST_ASSERT_EQUAL_INT_MESSAGE(1, dirtyCnt, "Unexpected number of dirty pages after truncate to 3");89  TEST_ASSERT_TRUE_MESSAGE(has2, "Dirty page 2 expected to remain dirty after truncate to 3");90 91  /* Pages 4,5,6 should not exist anymore without creation */92  for(Pgno i=4; i<=6; i++){93    int exists = pageExistsNoCreate(pCache, i);94    TEST_ASSERT_EQUAL_INT_MESSAGE(0, exists, "Page >3 still present after truncate");95  }96 97  sqlite3PcacheClose(pCache);98  freePCacheMem(pMem);99}100 101void test_sqlite3PcacheTruncate_zeroes_page1_when_pgno_zero_and_ref_held(void){102  const int pageSize = 128;103  void *pMem = allocPCacheMem();104  PCache *pCache = (PCache*)pMem;105 106  int rc = sqlite3PcacheOpen(pageSize, 32, 0, dummyStress, 0, pCache);107  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3PcacheOpen failed");108 109  /* Create page 1 and keep a reference, fill with non-zero data */110  sqlite3_pcache_page *pLower1 = sqlite3PcacheFetch(pCache, 1, 3);111  TEST_ASSERT_NOT_NULL(pLower1);112  PgHdr *p1 = sqlite3PcacheFetchFinish(pCache, 1, pLower1);113  TEST_ASSERT_NOT_NULL(p1);114  memset(p1->pData, 0xAA, pageSize);115 116  /* Create pages 2 and 3, mark dirty, then release */117  for(Pgno i=2; i<=3; i++){118    sqlite3_pcache_page *pLower = sqlite3PcacheFetch(pCache, i, 3);119    TEST_ASSERT_NOT_NULL(pLower);120    PgHdr *pHdr = sqlite3PcacheFetchFinish(pCache, i, pLower);121    sqlite3PcacheMakeDirty(pHdr);122    sqlite3PcacheRelease(pHdr);123  }124 125  /* Truncate to 0: page 1 should be zeroed (still referenced), others dropped */126  sqlite3PcacheTruncate(pCache, 0);127 128  /* Verify page 1 content is zeroed */129  unsigned char *z = (unsigned char*)p1->pData;130  for(int i=0; i<pageSize; i++){131    if( z[i] != 0 ){132      TEST_FAIL_MESSAGE("Page 1 data not zeroed by truncate to 0");133    }134  }135 136  /* No dirty pages should remain */137  int dirtyCnt = countDirtyPagesAndCheckMax(pCache, 0, 0);138  TEST_ASSERT_EQUAL_INT_MESSAGE(0, dirtyCnt, "Dirty list should be empty after truncate to 0");139 140  /* Pages 2 and 3 should no longer exist without creation */141  for(Pgno i=2; i<=3; i++){142    int exists = pageExistsNoCreate(pCache, i);143    TEST_ASSERT_EQUAL_INT_MESSAGE(0, exists, "Page present after truncate to 0");144  }145 146  sqlite3PcacheRelease(p1); /* release page 1 reference */147  sqlite3PcacheClose(pCache);148  freePCacheMem(pMem);149}150 151void test_sqlite3PcacheTruncate_no_dirty_pages_still_drops_above_pgno(void){152  const int pageSize = 64;153  void *pMem = allocPCacheMem();154  PCache *pCache = (PCache*)pMem;155 156  int rc = sqlite3PcacheOpen(pageSize, 16, 0, dummyStress, 0, pCache);157  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3PcacheOpen failed");158 159  /* Create clean pages 1..5 and release */160  for(Pgno i=1; i<=5; i++){161    sqlite3_pcache_page *pLower = sqlite3PcacheFetch(pCache, i, 3);162    TEST_ASSERT_NOT_NULL(pLower);163    PgHdr *pHdr = sqlite3PcacheFetchFinish(pCache, i, pLower);164    /* Do not mark dirty; keep clean */165    sqlite3PcacheRelease(pHdr);166  }167 168  sqlite3PcacheTruncate(pCache, 3);169 170  /* Pages 4 and 5 should not be present without creation */171  for(Pgno i=4; i<=5; i++){172    int exists = pageExistsNoCreate(pCache, i);173    TEST_ASSERT_EQUAL_INT_MESSAGE(0, exists, "Clean page >pgno still present after truncate");174  }175 176  sqlite3PcacheClose(pCache);177  freePCacheMem(pMem);178}179 180int main(void){181  UNITY_BEGIN();182  RUN_TEST(test_sqlite3PcacheTruncate_cleans_and_drops_pages_above_threshold);183  RUN_TEST(test_sqlite3PcacheTruncate_zeroes_page1_when_pgno_zero_and_ref_held);184  RUN_TEST(test_sqlite3PcacheTruncate_no_dirty_pages_still_drops_above_pgno);185  return UNITY_END();186}