Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_pcache_sqlite3PcacheMakeDirty.c203 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6/* No-op stress callback used for pcache open */7static int xStressNoop(void *p, PgHdr *pPg){ (void)p; (void)pPg; return SQLITE_OK; }8 9static PCache *allocCache(int purgeable){10  int rc;11  PCache *pc = (PCache*)sqlite3_malloc(sqlite3PcacheSize());12  TEST_ASSERT_NOT_NULL_MESSAGE(pc, "sqlite3_malloc for PCache failed");13  rc = sqlite3PcacheOpen(1024, 64, purgeable, xStressNoop, NULL, pc);14  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3PcacheOpen failed");15  return pc;16}17 18static PgHdr *getPage(PCache *pc, Pgno pgno){19  sqlite3_pcache_page *lower = sqlite3PcacheFetch(pc, pgno, 3);20  if( lower==NULL ){21    int rc = sqlite3PcacheFetchStress(pc, pgno, &lower);22    TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3PcacheFetchStress failed");23    TEST_ASSERT_NOT_NULL_MESSAGE(lower, "xFetch returned NULL after stress");24  }25  PgHdr *p = sqlite3PcacheFetchFinish(pc, pgno, lower);26  TEST_ASSERT_NOT_NULL_MESSAGE(p, "sqlite3PcacheFetchFinish returned NULL");27  return p;28}29 30void setUp(void) {31  int rc;32  rc = sqlite3_initialize();33  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_initialize failed");34  rc = sqlite3PcacheInitialize();35  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3PcacheInitialize failed");36}37 38void tearDown(void) {39  sqlite3PcacheShutdown();40  sqlite3_shutdown();41}42 43/* Test 1: Clean page becomes DIRTY and is placed on the dirty list (single page) */44void test_sqlite3PcacheMakeDirty_sets_dirty_and_list_for_clean_page(void){45  PCache *pc = allocCache(1); /* purgeable */46  PgHdr *p1 = getPage(pc, 1);47 48  /* Precondition: new page is CLEAN */49  TEST_ASSERT_TRUE_MESSAGE((p1->flags & PGHDR_CLEAN)!=0, "New page not CLEAN");50  TEST_ASSERT_TRUE_MESSAGE((p1->flags & PGHDR_DIRTY)==0, "New page unexpectedly DIRTY");51  TEST_ASSERT_EQUAL_INT64(1, sqlite3PcachePageRefcount(p1));52 53  sqlite3PcacheMakeDirty(p1);54 55  TEST_ASSERT_TRUE_MESSAGE((p1->flags & PGHDR_DIRTY)!=0, "Page not marked DIRTY");56  TEST_ASSERT_TRUE_MESSAGE((p1->flags & PGHDR_CLEAN)==0, "CLEAN flag not cleared");57 58  /* As the only dirty page, it should be the head: prev==NULL and next==NULL */59  TEST_ASSERT_NULL(p1->pDirtyPrev);60  TEST_ASSERT_NULL(p1->pDirtyNext);61 62  /* Cleanup */63  sqlite3PcacheDrop(p1);64  sqlite3PcacheClose(pc);65  sqlite3_free(pc);66}67 68/* Test 2: Calling MakeDirty on an already DIRTY page is a no-op on list links */69void test_sqlite3PcacheMakeDirty_noop_when_already_dirty(void){70  PCache *pc = allocCache(1);71  PgHdr *p1 = getPage(pc, 1);72 73  sqlite3PcacheMakeDirty(p1);74  unsigned origFlags = p1->flags;75  PgHdr *origPrev = p1->pDirtyPrev;76  PgHdr *origNext = p1->pDirtyNext;77 78  sqlite3PcacheMakeDirty(p1);79 80  TEST_ASSERT_EQUAL_HEX32(origFlags, p1->flags);81  TEST_ASSERT_EQUAL_PTR(origPrev, p1->pDirtyPrev);82  TEST_ASSERT_EQUAL_PTR(origNext, p1->pDirtyNext);83 84  /* Cleanup */85  sqlite3PcacheDrop(p1);86  sqlite3PcacheClose(pc);87  sqlite3_free(pc);88}89 90/* Test 3: DONT_WRITE is cleared on a DIRTY page without changing list links */91void test_sqlite3PcacheMakeDirty_clears_DONT_WRITE_on_dirty(void){92  PCache *pc = allocCache(1);93  PgHdr *p1 = getPage(pc, 1);94 95  sqlite3PcacheMakeDirty(p1);96  PgHdr *origPrev = p1->pDirtyPrev;97  PgHdr *origNext = p1->pDirtyNext;98 99  p1->flags |= PGHDR_DONT_WRITE;100  TEST_ASSERT_TRUE((p1->flags & PGHDR_DONT_WRITE)!=0);101 102  sqlite3PcacheMakeDirty(p1);103 104  TEST_ASSERT_TRUE((p1->flags & PGHDR_DIRTY)!=0);105  TEST_ASSERT_TRUE((p1->flags & PGHDR_DONT_WRITE)==0);106  TEST_ASSERT_EQUAL_PTR(origPrev, p1->pDirtyPrev);107  TEST_ASSERT_EQUAL_PTR(origNext, p1->pDirtyNext);108 109  /* Cleanup */110  sqlite3PcacheDrop(p1);111  sqlite3PcacheClose(pc);112  sqlite3_free(pc);113}114 115/* Test 4: Clean page with DONT_WRITE becomes DIRTY and clears DONT_WRITE */116void test_sqlite3PcacheMakeDirty_clears_DONT_WRITE_and_adds_on_clean(void){117  PCache *pc = allocCache(1);118  PgHdr *p1 = getPage(pc, 1);119 120  /* Set DONT_WRITE while still clean */121  TEST_ASSERT_TRUE((p1->flags & PGHDR_CLEAN)!=0);122  p1->flags |= PGHDR_DONT_WRITE;123 124  sqlite3PcacheMakeDirty(p1);125 126  TEST_ASSERT_TRUE((p1->flags & PGHDR_DIRTY)!=0);127  TEST_ASSERT_TRUE((p1->flags & PGHDR_CLEAN)==0);128  TEST_ASSERT_TRUE((p1->flags & PGHDR_DONT_WRITE)==0);129  TEST_ASSERT_NULL(p1->pDirtyPrev);130  TEST_ASSERT_NULL(p1->pDirtyNext);131 132  /* Cleanup */133  sqlite3PcacheDrop(p1);134  sqlite3PcacheClose(pc);135  sqlite3_free(pc);136}137 138/* Test 5: Multiple pages get linked in LRU order (newest at front) */139void test_sqlite3PcacheMakeDirty_dirty_list_ordering_multiple_pages(void){140  PCache *pc = allocCache(1);141  PgHdr *p1 = getPage(pc, 1);142  PgHdr *p2 = getPage(pc, 2);143  PgHdr *p3 = getPage(pc, 3);144 145  /* Make dirty in order: 1, then 2, then 3 */146  sqlite3PcacheMakeDirty(p1);147  TEST_ASSERT_NULL(p1->pDirtyPrev);148  TEST_ASSERT_NULL(p1->pDirtyNext);149 150  sqlite3PcacheMakeDirty(p2);151  /* p2 becomes head; p2->next == p1; p1->prev == p2 */152  TEST_ASSERT_NULL(p2->pDirtyPrev);153  TEST_ASSERT_EQUAL_PTR(p1, p2->pDirtyNext);154  TEST_ASSERT_EQUAL_PTR(p2, p1->pDirtyPrev);155  TEST_ASSERT_NULL(p1->pDirtyNext);156 157  sqlite3PcacheMakeDirty(p3);158  /* p3 becomes head; chain: p3 -> p2 -> p1 */159  TEST_ASSERT_NULL(p3->pDirtyPrev);160  TEST_ASSERT_EQUAL_PTR(p2, p3->pDirtyNext);161  TEST_ASSERT_EQUAL_PTR(p3, p2->pDirtyPrev);162  TEST_ASSERT_EQUAL_PTR(p1, p2->pDirtyNext);163  TEST_ASSERT_EQUAL_PTR(p2, p1->pDirtyPrev);164  TEST_ASSERT_NULL(p1->pDirtyNext);165 166  /* Cleanup: drop in any order - drop removes from list as needed */167  sqlite3PcacheDrop(p1);168  sqlite3PcacheDrop(p2);169  sqlite3PcacheDrop(p3);170  sqlite3PcacheClose(pc);171  sqlite3_free(pc);172}173 174/* Test 6: If NEED_SYNC is set on a clean page, it remains set after MakeDirty175          and MakeDirty still succeeds (we cannot directly test pSynced here) */176void test_sqlite3PcacheMakeDirty_respects_NEED_SYNC_flag(void){177  PCache *pc = allocCache(1);178  PgHdr *p1 = getPage(pc, 1);179 180  /* Set NEED_SYNC while clean */181  p1->flags |= PGHDR_NEED_SYNC;182  sqlite3PcacheMakeDirty(p1);183 184  TEST_ASSERT_TRUE((p1->flags & PGHDR_DIRTY)!=0);185  TEST_ASSERT_TRUE((p1->flags & PGHDR_CLEAN)==0);186  TEST_ASSERT_TRUE((p1->flags & PGHDR_NEED_SYNC)!=0);187 188  /* Cleanup */189  sqlite3PcacheDrop(p1);190  sqlite3PcacheClose(pc);191  sqlite3_free(pc);192}193 194int main(void){195  UNITY_BEGIN();196  RUN_TEST(test_sqlite3PcacheMakeDirty_sets_dirty_and_list_for_clean_page);197  RUN_TEST(test_sqlite3PcacheMakeDirty_noop_when_already_dirty);198  RUN_TEST(test_sqlite3PcacheMakeDirty_clears_DONT_WRITE_on_dirty);199  RUN_TEST(test_sqlite3PcacheMakeDirty_clears_DONT_WRITE_and_adds_on_clean);200  RUN_TEST(test_sqlite3PcacheMakeDirty_dirty_list_ordering_multiple_pages);201  RUN_TEST(test_sqlite3PcacheMakeDirty_respects_NEED_SYNC_flag);202  return UNITY_END();203}