Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_pcache_sqlite3PcacheSetPageSize.c246 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5#include <stdint.h>6 7/*8** Test suite for: int sqlite3PcacheSetPageSize(PCache *pCache, int szPage)9**10** Strategy:11** - Create a valid PCache using sqlite3PcacheOpen (using size returned by sqlite3PcacheSize).12** - Swap sqlite3GlobalConfig.pcache2 with a stub implementation to capture and verify13**   xCreate, xCachesize, and xDestroy calls made by sqlite3PcacheSetPageSize.14** - Validate correct handling of success, OOM, and numberOfCachePages behavior.15*/16 17/* ---- Stub pcache2 machinery ---- */18static sqlite3_pcache_methods2 g_savedMethods;19static int g_stubInstalled = 0;20 21/* Captured call info */22static int g_xCreate_calls = 0;23static int g_xCreate_last_szPage = 0;24static int g_xCreate_last_szExtra = 0;25static int g_xCreate_last_bPurgeable = -1;26static int g_xCachesize_calls = 0;27static int g_xCachesize_last = -1;28static int g_xDestroy_calls = 0;29static sqlite3_pcache *g_xDestroy_last_arg = 0;30static int g_xCreate_return_null = 0;31static int g_xPagecount_return = 123; /* Sentinel for verifying handle switch */32 33/* Provide a stable, lifetime-long pointer to return from stub xCreate. */34static union { char z[16]; void *align; } g_stubPcacheObj1;35 36static sqlite3_pcache *stub_xCreate(int szPage, int szExtra, int bPurgeable){37  g_xCreate_calls++;38  g_xCreate_last_szPage = szPage;39  g_xCreate_last_szExtra = szExtra;40  g_xCreate_last_bPurgeable = bPurgeable;41  if( g_xCreate_return_null ) return 0;42  return (sqlite3_pcache*)(void*)&g_stubPcacheObj1;43}44static void stub_xCachesize(sqlite3_pcache *p, int nCachesize){45  (void)p;46  g_xCachesize_calls++;47  g_xCachesize_last = nCachesize;48}49static int stub_xPagecount(sqlite3_pcache *p){50  (void)p;51  return g_xPagecount_return;52}53static sqlite3_pcache_page *stub_xFetch(sqlite3_pcache *p, unsigned k, int cf){54  (void)p; (void)k; (void)cf; return 0;55}56static void stub_xUnpin(sqlite3_pcache *p, sqlite3_pcache_page *pg, int d){57  (void)p; (void)pg; (void)d;58}59static void stub_xRekey(sqlite3_pcache *p, sqlite3_pcache_page *pg, unsigned o, unsigned n){60  (void)p; (void)pg; (void)o; (void)n;61}62static void stub_xTruncate(sqlite3_pcache *p, unsigned lim){ (void)p; (void)lim; }63static void stub_xDestroy(sqlite3_pcache *p){ g_xDestroy_calls++; g_xDestroy_last_arg = p; }64static void stub_xShrink(sqlite3_pcache *p){ (void)p; }65static int stub_xInit(void *pArg){ (void)pArg; return SQLITE_OK; }66static void stub_xShutdown(void *pArg){ (void)pArg; }67 68static void installStub(void){69  if( !g_stubInstalled ){70    g_savedMethods = sqlite3GlobalConfig.pcache2;71    sqlite3_pcache_methods2 m;72    memset(&m, 0, sizeof(m));73    m.iVersion = 1;74    m.pArg = 0;75    m.xInit = stub_xInit;        /* not used here */76    m.xShutdown = stub_xShutdown;/* not used here */77    m.xCreate = stub_xCreate;78    m.xCachesize = stub_xCachesize;79    m.xPagecount = stub_xPagecount;80    m.xFetch = stub_xFetch;81    m.xUnpin = stub_xUnpin;82    m.xRekey = stub_xRekey;83    m.xTruncate = stub_xTruncate;84    m.xDestroy = stub_xDestroy;85    m.xShrink = stub_xShrink;86    sqlite3GlobalConfig.pcache2 = m;87    g_stubInstalled = 1;88  }89}90static void restoreStub(void){91  if( g_stubInstalled ){92    sqlite3GlobalConfig.pcache2 = g_savedMethods;93    g_stubInstalled = 0;94  }95}96static void resetStubCapture(void){97  g_xCreate_calls = 0;98  g_xCreate_last_szPage = 0;99  g_xCreate_last_szExtra = 0;100  g_xCreate_last_bPurgeable = -1;101  g_xCachesize_calls = 0;102  g_xCachesize_last = -1;103  g_xDestroy_calls = 0;104  g_xDestroy_last_arg = 0;105  g_xCreate_return_null = 0;106  g_xPagecount_return = 123;107}108 109void setUp(void) {110  /* Ensure SQLite is initialized */111  sqlite3_initialize();112  resetStubCapture();113}114 115void tearDown(void) {116  /* Restore default pcache2 methods in case a test left the stub installed */117  restoreStub();118}119 120/* Helper: allocate and open a PCache with given parameters */121static PCache *openPCacheOrFail(int szPage, int szExtra, int bPurgeable){122  int rc;123  int n = sqlite3PcacheSize();124  PCache *pCache = (PCache*)sqlite3_malloc(n);125  TEST_ASSERT_NOT_NULL(pCache);126  rc = sqlite3PcacheOpen(szPage, szExtra, bPurgeable, 0, 0, pCache);127  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);128  return pCache;129}130 131/* Test 1: Success path. Verify xCreate args, xCachesize value, xDestroy fired, and handle switch. */132void test_sqlite3PcacheSetPageSize_success_and_calls(void){133  /* Open a cache with known parameters */134  const int initialSzPage = 512;135  const int szExtra = 64;136  const int bPurgeable = 1;137  PCache *p = openPCacheOrFail(initialSzPage, szExtra, bPurgeable);138 139  /* Set a positive cache-size and prepare stub */140  sqlite3PcacheSetCachesize(p, 7);141  installStub();142  resetStubCapture();143 144  /* Call under test with new page size */145  const int newSzPage = 1024;146  int rc = sqlite3PcacheSetPageSize(p, newSzPage);147  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);148 149  /* xCreate should be called once with: szPage=newSzPage,150  ** szExtra = p->szExtra + ROUND8(sizeof(PgHdr)) (151  **           we passed szExtra to sqlite3PcacheOpen),152  ** bPurgeable carried over from open. */153  TEST_ASSERT_EQUAL_INT(1, g_xCreate_calls);154  TEST_ASSERT_EQUAL_INT(newSzPage, g_xCreate_last_szPage);155  TEST_ASSERT_EQUAL_INT(szExtra + ROUND8(sizeof(PgHdr)), g_xCreate_last_szExtra);156  TEST_ASSERT_EQUAL_INT(bPurgeable, g_xCreate_last_bPurgeable);157 158  /* xCachesize should be called once with the configured cache size (7). */159  TEST_ASSERT_EQUAL_INT(1, g_xCachesize_calls);160  TEST_ASSERT_EQUAL_INT(7, g_xCachesize_last);161 162  /* Old cache should have been destroyed exactly once */163  TEST_ASSERT_EQUAL_INT(1, g_xDestroy_calls);164 165  /* Verify the PCache now uses the stub by checking pagecount sentinel */166  g_xPagecount_return = 42;167  TEST_ASSERT_EQUAL_INT(42, sqlite3PcachePagecount(p));168 169  /* Do not close this PCache: it now refers to a stub handle. */170  sqlite3_free(p);171}172 173/* Test 2: OOM path. xCreate returns NULL -> SQLITE_NOMEM_BKPT and no xDestroy/xCachesize. */174void test_sqlite3PcacheSetPageSize_oom_returns_nomem_and_no_side_effects(void){175  /* Open with default implementation */176  PCache *p = openPCacheOrFail(1024, 48, 0);177 178  installStub();179  resetStubCapture();180  g_xCreate_return_null = 1; /* Force OOM */181 182  int rc = sqlite3PcacheSetPageSize(p, 2048);183  TEST_ASSERT_EQUAL_INT(SQLITE_NOMEM_BKPT, rc);184 185  /* Ensure we did not proceed past xCreate failure */186  TEST_ASSERT_EQUAL_INT(1, g_xCreate_calls);187  TEST_ASSERT_EQUAL_INT(0, g_xCachesize_calls);188  TEST_ASSERT_EQUAL_INT(0, g_xDestroy_calls);189 190  /* Restore default vtable and close the cache safely (it still uses default). */191  restoreStub();192  sqlite3PcacheClose(p);193  sqlite3_free(p);194}195 196/* Test 3: numberOfCachePages behavior with negative cache-size.197** Verify xCachesize argument equals bytes/(oldPage+szExtra) and that the198** "old page size" used is the size before updating p->szPage. */199void test_sqlite3PcacheSetPageSize_negative_cachesize_uses_old_page_size(void){200  const int oldSzPage = 512;201  const int szExtra = 32;202  PCache *p = openPCacheOrFail(oldSzPage, szExtra, 1);203 204  /* Configure negative cache-size: approximately 4MB */205  const int negCacheKB = -4096; /* -4096 KB */206  sqlite3PcacheSetCachesize(p, negCacheKB);207 208  installStub();209  resetStubCapture();210 211  /* First call: new page size 1024, numberOfCachePages uses oldSzPage (512) */212  int rc = sqlite3PcacheSetPageSize(p, 1024);213  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);214  /* Expected pages = ((-1024 * (i64)negCacheKB) / (oldSzPage + szExtra)) */215  {216    i64 bytes = (-1024 * (i64)negCacheKB);217    int expectedPages = (int)(bytes / (oldSzPage + szExtra));218    TEST_ASSERT_EQUAL_INT(1, g_xCachesize_calls);219    TEST_ASSERT_EQUAL_INT(expectedPages, g_xCachesize_last);220  }221 222  /* Second call: new page size 2048, numberOfCachePages uses old=1024 now */223  resetStubCapture();224  rc = sqlite3PcacheSetPageSize(p, 2048);225  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);226  {227    i64 bytes = (-1024 * (i64)negCacheKB);228    int expectedPages = (int)(bytes / (1024 + szExtra));229    TEST_ASSERT_EQUAL_INT(1, g_xCachesize_calls);230    TEST_ASSERT_EQUAL_INT(expectedPages, g_xCachesize_last);231  }232 233  /* Two calls -> old handle destroyed twice */234  TEST_ASSERT_TRUE(g_xDestroy_calls >= 2);235 236  /* Leave stub handle attached; don't close with default vtable. */237  sqlite3_free(p);238}239 240int main(void){241  UNITY_BEGIN();242  RUN_TEST(test_sqlite3PcacheSetPageSize_success_and_calls);243  RUN_TEST(test_sqlite3PcacheSetPageSize_oom_returns_nomem_and_no_side_effects);244  RUN_TEST(test_sqlite3PcacheSetPageSize_negative_cachesize_uses_old_page_size);245  return UNITY_END();246}