Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_pcache_sqlite3PcachePageSanity.c173 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6/* Helper stress callback for PCache - not used in these tests but required by open */7static int testStressCb(void *p, PgHdr *pPg){8  (void)p; (void)pPg;9  return SQLITE_OK;10}11 12static PCache* helperCreateCache(int pageSize){13  int rc;14  void *mem = sqlite3_malloc(sqlite3PcacheSize());15  TEST_ASSERT_NOT_NULL(mem);16 17  PCache *pCache = (PCache*)mem;18  rc = sqlite3PcacheOpen(pageSize, 64, 1, testStressCb, NULL, pCache);19  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);20  return pCache;21}22 23static void helperDestroyCache(PCache *pCache){24  if( pCache ){25    sqlite3PcacheClose(pCache);26    sqlite3_free(pCache);27  }28}29 30static PgHdr* helperFetchPage(PCache *pCache, Pgno pgno){31  sqlite3_pcache_page *pLower = sqlite3PcacheFetch(pCache, pgno, 3);32  TEST_ASSERT_NOT_NULL(pLower);33  PgHdr *pPg = sqlite3PcacheFetchFinish(pCache, pgno, pLower);34  TEST_ASSERT_NOT_NULL(pPg);35  return pPg;36}37 38void setUp(void){39  /* Initialize SQLite core and pcache each test */40  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_initialize());41  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3PcacheInitialize());42}43 44void tearDown(void){45  /* Shutdown pcache and SQLite core to avoid cross-test interference */46  sqlite3PcacheShutdown();47  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_shutdown());48}49 50#ifdef SQLITE_DEBUG51 52/* Basic: a newly fetched page is clean and sane */53void test_sqlite3PcachePageSanity_clean_page(void){54  PCache *pc = helperCreateCache(512);55  PgHdr *p1 = helperFetchPage(pc, 1);56  TEST_ASSERT_EQUAL_INT(1, sqlite3PcachePageSanity(p1));57  /* Cleanup */58  sqlite3PcacheMakeClean(p1); /* no-op but safe */59  sqlite3PcacheRelease(p1);60  helperDestroyCache(pc);61}62 63/* Single dirty page has correct list linkage and is sane */64void test_sqlite3PcachePageSanity_single_dirty(void){65  PCache *pc = helperCreateCache(512);66  PgHdr *p1 = helperFetchPage(pc, 1);67  sqlite3PcacheMakeDirty(p1);68  TEST_ASSERT_EQUAL_INT(1, sqlite3PcachePageSanity(p1));69  /* Cleanup */70  sqlite3PcacheMakeClean(p1);71  sqlite3PcacheRelease(p1);72  helperDestroyCache(pc);73}74 75/* Two dirty pages linked in LRU order remain sane */76void test_sqlite3PcachePageSanity_two_dirty_pages(void){77  PCache *pc = helperCreateCache(512);78  PgHdr *p1 = helperFetchPage(pc, 1);79  PgHdr *p2 = helperFetchPage(pc, 2);80  sqlite3PcacheMakeDirty(p1);81  sqlite3PcacheMakeDirty(p2);82  TEST_ASSERT_EQUAL_INT(1, sqlite3PcachePageSanity(p1));83  TEST_ASSERT_EQUAL_INT(1, sqlite3PcachePageSanity(p2));84  /* Cleanup */85  sqlite3PcacheMakeClean(p1);86  sqlite3PcacheMakeClean(p2);87  sqlite3PcacheRelease(p1);88  sqlite3PcacheRelease(p2);89  helperDestroyCache(pc);90}91 92/* Making a dirty page clean removes it from the dirty list; page stays sane */93void test_sqlite3PcachePageSanity_make_clean(void){94  PCache *pc = helperCreateCache(512);95  PgHdr *p1 = helperFetchPage(pc, 1);96  sqlite3PcacheMakeDirty(p1);97  sqlite3PcacheMakeClean(p1);98  TEST_ASSERT_EQUAL_INT(1, sqlite3PcachePageSanity(p1));99  /* Cleanup */100  sqlite3PcacheRelease(p1);101  helperDestroyCache(pc);102}103 104/* WRITEABLE implies DIRTY; sanity should pass if both are set */105void test_sqlite3PcachePageSanity_writeable_implies_dirty(void){106  PCache *pc = helperCreateCache(512);107  PgHdr *p1 = helperFetchPage(pc, 1);108  sqlite3PcacheMakeDirty(p1);109  p1->flags |= PGHDR_WRITEABLE; /* Valid combination: WRITEABLE implies DIRTY */110  TEST_ASSERT_EQUAL_INT(1, sqlite3PcachePageSanity(p1));111  /* Cleanup */112  sqlite3PcacheMakeClean(p1);113  sqlite3PcacheRelease(p1);114  helperDestroyCache(pc);115}116 117/* Releasing the last reference to a dirty page moves it to front of dirty list; page remains sane */118void test_sqlite3PcachePageSanity_release_moves_front_and_sane(void){119  PCache *pc = helperCreateCache(512);120  PgHdr *p1 = helperFetchPage(pc, 1);121  PgHdr *p2 = helperFetchPage(pc, 2);122  sqlite3PcacheMakeDirty(p1);123  sqlite3PcacheMakeDirty(p2);124  /* Add an extra ref to p2 and then release twice to trigger FRONT move on dirty list */125  sqlite3PcacheRef(p2);126  sqlite3PcacheRelease(p2);127  sqlite3PcacheRelease(p2); /* nRef now 0 but still dirty and on list */128  TEST_ASSERT_EQUAL_INT(1, sqlite3PcachePageSanity(p2));129  TEST_ASSERT_EQUAL_INT(1, sqlite3PcachePageSanity(p1));130  /* Cleanup: clean all and close */131  sqlite3PcacheCleanAll(pc);132  /* p1 had nRef=1; p2 had nRef=0. Release p1 */133  sqlite3PcacheRelease(p1);134  helperDestroyCache(pc);135}136 137/* Moving a dirty page with NEED_SYNC set stays sane after move */138void test_sqlite3PcachePageSanity_move_dirty_need_sync(void){139  PCache *pc = helperCreateCache(512);140  PgHdr *p3 = helperFetchPage(pc, 3);141  sqlite3PcacheMakeDirty(p3);142  p3->flags |= PGHDR_NEED_SYNC;143  sqlite3PcacheMove(p3, 5);144  TEST_ASSERT_EQUAL_INT(1, sqlite3PcachePageSanity(p3));145  /* Cleanup */146  sqlite3PcacheMakeClean(p3);147  sqlite3PcacheRelease(p3);148  helperDestroyCache(pc);149}150 151#else /* !SQLITE_DEBUG */152 153void test_sqlite3PcachePageSanity_unavailable_when_not_SQLITE_DEBUG(void){154  TEST_IGNORE_MESSAGE("sqlite3PcachePageSanity() is only available when SQLITE_DEBUG is defined");155}156 157#endif /* SQLITE_DEBUG */158 159int main(void){160  UNITY_BEGIN();161#ifdef SQLITE_DEBUG162  RUN_TEST(test_sqlite3PcachePageSanity_clean_page);163  RUN_TEST(test_sqlite3PcachePageSanity_single_dirty);164  RUN_TEST(test_sqlite3PcachePageSanity_two_dirty_pages);165  RUN_TEST(test_sqlite3PcachePageSanity_make_clean);166  RUN_TEST(test_sqlite3PcachePageSanity_writeable_implies_dirty);167  RUN_TEST(test_sqlite3PcachePageSanity_release_moves_front_and_sane);168  RUN_TEST(test_sqlite3PcachePageSanity_move_dirty_need_sync);169#else170  RUN_TEST(test_sqlite3PcachePageSanity_unavailable_when_not_SQLITE_DEBUG);171#endif172  return UNITY_END();173}