Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_pcache1_pcache1ResizeHash.c196 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5#include <stdio.h>6 7/* Forward declaration for the internal PCache1 type so we can pass pointers */8typedef struct PCache1 PCache1;9/* Wrapper provided in the module for testing the static function */10extern void test_pcache1ResizeHash(PCache1 *p);11 12static sqlite3_pcache_methods2 g_pcacheMethods;13 14/* Acquire both static mutexes that pcache1 may use for its PCache1Group(s).15   This ensures the precondition "PCache mutex must be held" is satisfied. */16static sqlite3_mutex* g_mutex_lru = NULL;17static sqlite3_mutex* g_mutex_pmem = NULL;18 19static void lock_pcache_group_mutexes(void){20  if( g_mutex_lru==NULL ) g_mutex_lru = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);21  if( g_mutex_pmem==NULL ) g_mutex_pmem = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM);22  /* Both may be the same or different underlying mutexes. Lock both safely. */23  if( g_mutex_lru ) sqlite3_mutex_enter(g_mutex_lru);24  if( g_mutex_pmem ) sqlite3_mutex_enter(g_mutex_pmem);25}26static void unlock_pcache_group_mutexes(void){27  if( g_mutex_pmem ) sqlite3_mutex_leave(g_mutex_pmem);28  if( g_mutex_lru ) sqlite3_mutex_leave(g_mutex_lru);29}30 31void setUp(void) {32  int rc = sqlite3_initialize();33  (void)rc; /* rc is typically SQLITE_OK; ignore in tests setup */34  /* Capture default pcache2 methods installed by initialization */35  g_pcacheMethods = sqlite3GlobalConfig.pcache2;36  /* Ensure initialized, if xInit is provided */37  if( g_pcacheMethods.xInit ){38    g_pcacheMethods.xInit(g_pcacheMethods.pArg);39  }40  TEST_ASSERT_NOT_NULL(g_pcacheMethods.xCreate);41  TEST_ASSERT_NOT_NULL(g_pcacheMethods.xCachesize);42  TEST_ASSERT_NOT_NULL(g_pcacheMethods.xFetch);43  TEST_ASSERT_NOT_NULL(g_pcacheMethods.xUnpin);44  TEST_ASSERT_NOT_NULL(g_pcacheMethods.xDestroy);45}46 47void tearDown(void) {48  /* Nothing to clean here; individual tests destroy their caches */49}50 51/* Helpers */52static sqlite3_pcache* new_cache(int pageSize, int extraSize, int purgeable, int cacheSize){53  sqlite3_pcache *pc = g_pcacheMethods.xCreate(pageSize, extraSize, purgeable);54  TEST_ASSERT_NOT_NULL(pc);55  g_pcacheMethods.xCachesize(pc, cacheSize);56  return pc;57}58 59static void fill_cache_with_pages(sqlite3_pcache *pc, int nPages){60  for(int i=1; i<=nPages; i++){61    sqlite3_pcache_page *pg = g_pcacheMethods.xFetch(pc, (unsigned int)i, 2);62    TEST_ASSERT_NOT_NULL(pg);63    /* Release into cache (do not discard) so it is stored and findable */64    g_pcacheMethods.xUnpin(pc, pg, 0);65  }66}67 68static void verify_cached_pages_findable(sqlite3_pcache *pc, int nPages){69  for(int i=1; i<=nPages; i++){70    sqlite3_pcache_page *pg = g_pcacheMethods.xFetch(pc, (unsigned int)i, 0);71    TEST_ASSERT_NOT_NULL(pg);72    g_pcacheMethods.xUnpin(pc, pg, 0);73  }74}75 76/* Call the tested function on a given sqlite3_pcache* by casting to PCache1*,77   while holding the pcache1 group mutex(es). */78static void invoke_resize(sqlite3_pcache *pc){79  lock_pcache_group_mutexes();80  test_pcache1ResizeHash((PCache1*)pc);81  unlock_pcache_group_mutexes();82}83 84/* Tests */85 86/* 1) Initial call on a new cache: ensure no crash and cache operates normally. */87void test_pcache1ResizeHash_initial_on_empty_cache(void){88  sqlite3_pcache *pc = new_cache(1024, 0, 1, 32);89  /* Invoke resize before any page is added */90  invoke_resize(pc);91 92  /* Add a few pages and ensure they are retrievable */93  fill_cache_with_pages(pc, 16);94  verify_cached_pages_findable(pc, 16);95 96  g_pcacheMethods.xDestroy(pc);97}98 99/* 2) Rehash after moderate population: all entries preserved. */100void test_pcache1ResizeHash_rehash_preserves_100_pages(void){101  sqlite3_pcache *pc = new_cache(1024, 0, 1, 200);102  fill_cache_with_pages(pc, 100);103 104  /* Verify they are findable before resize */105  verify_cached_pages_findable(pc, 100);106 107  /* Resize the hash table explicitly */108  invoke_resize(pc);109 110  /* Verify they are still all findable after resize */111  verify_cached_pages_findable(pc, 100);112 113  g_pcacheMethods.xDestroy(pc);114}115 116/* 3) Rehash after large population: all entries preserved. */117void test_pcache1ResizeHash_rehash_preserves_1000_pages(void){118  sqlite3_pcache *pc = new_cache(2048, 0, 1, 2048);119  fill_cache_with_pages(pc, 1000);120 121  /* Sanity pre-check */122  verify_cached_pages_findable(pc, 1000);123 124  /* Perform explicit resize */125  invoke_resize(pc);126 127  /* All entries should remain accessible */128  verify_cached_pages_findable(pc, 1000);129 130  g_pcacheMethods.xDestroy(pc);131}132 133/* 4) Multiple consecutive resizes do not affect correctness of lookups. */134void test_pcache1ResizeHash_multiple_consecutive_resizes(void){135  sqlite3_pcache *pc = new_cache(512, 0, 1, 512);136  fill_cache_with_pages(pc, 256);137 138  /* Perform two consecutive resizes to force multiple rehash cycles */139  invoke_resize(pc);140  invoke_resize(pc);141 142  /* Spot-check retrieval across a pattern of keys */143  for(int i=1; i<=256; i+=7){144    sqlite3_pcache_page *pg = g_pcacheMethods.xFetch(pc, (unsigned int)i, 0);145    TEST_ASSERT_NOT_NULL(pg);146    g_pcacheMethods.xUnpin(pc, pg, 0);147  }148 149  /* And verify full set remains intact */150  verify_cached_pages_findable(pc, 256);151 152  g_pcacheMethods.xDestroy(pc);153}154 155/* 5) Resize amidst mixed key distribution (including potential high-collision sets). */156void test_pcache1ResizeHash_mixed_keys_distribution(void){157  sqlite3_pcache *pc = new_cache(1024, 0, 1, 1024);158 159  /* Insert a mix: sequential and spaced keys to exercise different buckets */160  for(int i=1; i<=300; i++){161    unsigned int key = (i%2==0) ? (unsigned int)i : (unsigned int)(i*257); /* 257 is prime; wraps modulo various nHash */162    sqlite3_pcache_page *pg = g_pcacheMethods.xFetch(pc, key, 2);163    TEST_ASSERT_NOT_NULL(pg);164    g_pcacheMethods.xUnpin(pc, pg, 0);165  }166 167  /* Resize explicitly */168  invoke_resize(pc);169 170  /* Verify a subset then all */171  for(int i=1; i<=300; i+=5){172    unsigned int key = (i%2==0) ? (unsigned int)i : (unsigned int)(i*257);173    sqlite3_pcache_page *pg = g_pcacheMethods.xFetch(pc, key, 0);174    TEST_ASSERT_NOT_NULL(pg);175    g_pcacheMethods.xUnpin(pc, pg, 0);176  }177  /* Full verification */178  for(int i=1; i<=300; i++){179    unsigned int key = (i%2==0) ? (unsigned int)i : (unsigned int)(i*257);180    sqlite3_pcache_page *pg = g_pcacheMethods.xFetch(pc, key, 0);181    TEST_ASSERT_NOT_NULL(pg);182    g_pcacheMethods.xUnpin(pc, pg, 0);183  }184 185  g_pcacheMethods.xDestroy(pc);186}187 188int main(void) {189  UNITY_BEGIN();190  RUN_TEST(test_pcache1ResizeHash_initial_on_empty_cache);191  RUN_TEST(test_pcache1ResizeHash_rehash_preserves_100_pages);192  RUN_TEST(test_pcache1ResizeHash_rehash_preserves_1000_pages);193  RUN_TEST(test_pcache1ResizeHash_multiple_consecutive_resizes);194  RUN_TEST(test_pcache1ResizeHash_mixed_keys_distribution);195  return UNITY_END();196}