Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_pcache_sqlite3PcacheRelease.c188 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6/* Stress callback stub (not used by these tests but required by sqlite3PcacheOpen) */7static int stress_cb(void *p, PgHdr *pPg){8  (void)p; (void)pPg;9  return SQLITE_OK;10}11 12void setUp(void) {13  /* Ensure SQLite is initialized, so the default pcache module is ready */14  int rc = sqlite3_initialize();15  TEST_ASSERT_TRUE(rc==SQLITE_OK || rc==SQLITE_MISUSE);16}17 18void tearDown(void) {19  /* Shutdown between tests for a clean environment */20  sqlite3_shutdown();21}22 23/* Helper: initialize a PCache */24static void init_pcache(PCache *pCache, int purgeable){25  int rc = sqlite3PcacheOpen(512, 128, purgeable, stress_cb, NULL, pCache);26  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);27}28 29/* Helper: fetch a page and finish to get PgHdr */30static PgHdr* fetch_page(PCache *pCache, Pgno pgno, sqlite3_pcache_page **ppLower){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  if( ppLower ) *ppLower = pLower;36  return pPg;37}38 39/* Helper: check if a given PgHdr appears on the dirty list */40static int dirty_list_contains(PCache *pCache, PgHdr *target){41  PgHdr *p;42  PgHdr *pList = sqlite3PcacheDirtyList(pCache);43  for(p = pList; p; p = p->pDirty){44    if( p==target ) return 1;45  }46  return 0;47}48 49void test_sqlite3PcacheRelease_clean_ref1_inmemory(void){50  PCache cache;51  init_pcache(&cache, 0); /* in-memory, unpin is no-op */52 53  PgHdr *p = fetch_page(&cache, 10, NULL);54  TEST_ASSERT_EQUAL_INT64(1, sqlite3PcacheRefCount(&cache));55  TEST_ASSERT_EQUAL_INT(1, p->nRef);56  TEST_ASSERT_TRUE((p->flags & PGHDR_CLEAN)!=0);57  TEST_ASSERT_TRUE((p->flags & PGHDR_DIRTY)==0);58 59  sqlite3PcacheRelease(p);60 61  TEST_ASSERT_EQUAL_INT(0, p->nRef);62  TEST_ASSERT_EQUAL_INT64(0, sqlite3PcacheRefCount(&cache));63  TEST_ASSERT_TRUE((p->flags & PGHDR_CLEAN)!=0);64  TEST_ASSERT_TRUE((p->flags & PGHDR_DIRTY)==0);65 66  /* Dirty list should be empty */67  TEST_ASSERT_NULL(sqlite3PcacheDirtyList(&cache));68 69  sqlite3PcacheClose(&cache);70}71 72void test_sqlite3PcacheRelease_dirty_ref1_inmemory(void){73  PCache cache;74  init_pcache(&cache, 0); /* in-memory, unpin is no-op */75 76  PgHdr *p = fetch_page(&cache, 3, NULL);77  sqlite3PcacheMakeDirty(p);78  TEST_ASSERT_TRUE((p->flags & PGHDR_DIRTY)!=0);79  TEST_ASSERT_TRUE((p->flags & PGHDR_CLEAN)==0);80  TEST_ASSERT_EQUAL_INT(1, p->nRef);81  TEST_ASSERT_EQUAL_INT64(1, sqlite3PcacheRefCount(&cache));82 83  sqlite3PcacheRelease(p);84 85  TEST_ASSERT_EQUAL_INT(0, p->nRef);86  TEST_ASSERT_EQUAL_INT64(0, sqlite3PcacheRefCount(&cache));87  TEST_ASSERT_TRUE((p->flags & PGHDR_DIRTY)!=0);88  TEST_ASSERT_TRUE((p->flags & PGHDR_CLEAN)==0);89 90  /* Page should still be on the dirty list */91  TEST_ASSERT_TRUE(dirty_list_contains(&cache, p));92 93  sqlite3PcacheClose(&cache);94}95 96void test_sqlite3PcacheRelease_clean_decrement_only(void){97  PCache cache;98  init_pcache(&cache, 0);99 100  PgHdr *p = fetch_page(&cache, 44, NULL);101  sqlite3PcacheRef(p); /* nRef becomes 2 */102  TEST_ASSERT_EQUAL_INT(2, p->nRef);103  TEST_ASSERT_EQUAL_INT64(2, sqlite3PcacheRefCount(&cache));104  TEST_ASSERT_TRUE((p->flags & PGHDR_CLEAN)!=0);105 106  sqlite3PcacheRelease(p); /* nRef -> 1, no unpin, no list change */107 108  TEST_ASSERT_EQUAL_INT(1, p->nRef);109  TEST_ASSERT_EQUAL_INT64(1, sqlite3PcacheRefCount(&cache));110  TEST_ASSERT_TRUE((p->flags & PGHDR_CLEAN)!=0);111  TEST_ASSERT_TRUE((p->flags & PGHDR_DIRTY)==0);112 113  /* Cleanup: release final ref */114  sqlite3PcacheRelease(p);115  TEST_ASSERT_EQUAL_INT(0, p->nRef);116  TEST_ASSERT_EQUAL_INT64(0, sqlite3PcacheRefCount(&cache));117 118  sqlite3PcacheClose(&cache);119}120 121void test_sqlite3PcacheRelease_dirty_decrement_only(void){122  PCache cache;123  init_pcache(&cache, 0);124 125  PgHdr *p = fetch_page(&cache, 45, NULL);126  sqlite3PcacheMakeDirty(p);127  sqlite3PcacheRef(p); /* nRef becomes 2 */128  TEST_ASSERT_EQUAL_INT(2, p->nRef);129  TEST_ASSERT_EQUAL_INT64(2, sqlite3PcacheRefCount(&cache));130  TEST_ASSERT_TRUE((p->flags & PGHDR_DIRTY)!=0);131 132  sqlite3PcacheRelease(p); /* nRef -> 1; since still >0, nothing else */133 134  TEST_ASSERT_EQUAL_INT(1, p->nRef);135  TEST_ASSERT_EQUAL_INT64(1, sqlite3PcacheRefCount(&cache));136  TEST_ASSERT_TRUE((p->flags & PGHDR_DIRTY)!=0);137  TEST_ASSERT_TRUE((p->flags & PGHDR_CLEAN)==0);138 139  /* Cleanup: release final ref */140  sqlite3PcacheRelease(p);141  TEST_ASSERT_EQUAL_INT(0, p->nRef);142  TEST_ASSERT_EQUAL_INT64(0, sqlite3PcacheRefCount(&cache));143 144  /* Still dirty */145  TEST_ASSERT_TRUE(dirty_list_contains(&cache, p));146 147  sqlite3PcacheClose(&cache);148}149 150void test_sqlite3PcacheRelease_clean_ref1_purgeable(void){151  PCache cache;152  init_pcache(&cache, 1); /* purgeable: unpin will be called on clean release */153 154  sqlite3_pcache_page *pLower1 = NULL;155  PgHdr *p = fetch_page(&cache, 7, &pLower1);156  TEST_ASSERT_NOT_NULL(pLower1);157  TEST_ASSERT_EQUAL_INT(1, p->nRef);158  TEST_ASSERT_TRUE((p->flags & PGHDR_CLEAN)!=0);159 160  sqlite3PcacheRelease(p); /* nRef -> 0, should unpin underlying page */161  TEST_ASSERT_EQUAL_INT(0, p->nRef);162  TEST_ASSERT_EQUAL_INT64(0, sqlite3PcacheRefCount(&cache));163 164  /* The page should still be present in cache and fetchable without creating */165  sqlite3_pcache_page *pLower2 = sqlite3PcacheFetch(&cache, 7, 0);166  TEST_ASSERT_NOT_NULL(pLower2);167 168  /* Typically the same underlying pointer remains */169  TEST_ASSERT_EQUAL_PTR(pLower1, pLower2);170 171  /* Finish and release to balance */172  PgHdr *p2 = sqlite3PcacheFetchFinish(&cache, 7, pLower2);173  TEST_ASSERT_NOT_NULL(p2);174  TEST_ASSERT_EQUAL_INT(1, p2->nRef);175  sqlite3PcacheRelease(p2);176 177  sqlite3PcacheClose(&cache);178}179 180int main(void) {181  UNITY_BEGIN();182  RUN_TEST(test_sqlite3PcacheRelease_clean_ref1_inmemory);183  RUN_TEST(test_sqlite3PcacheRelease_dirty_ref1_inmemory);184  RUN_TEST(test_sqlite3PcacheRelease_clean_decrement_only);185  RUN_TEST(test_sqlite3PcacheRelease_dirty_decrement_only);186  RUN_TEST(test_sqlite3PcacheRelease_clean_ref1_purgeable);187  return UNITY_END();188}