Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_pcache1_pcache1RemoveFromHash.c314 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6/* Wrapper provided in the module for the static function */7void test_pcache1RemoveFromHash(PgHdr1 *pPage, int freeFlag);8 9/* Helpers to build minimal PCache1/PgHdr1 environments */10 11static PCache1* makeCache(12  int nHash,13  PGroup **ppGroupOut,14  sqlite3_mutex **ppMutexOut,15  int **ppPurgeableOut16){17  /* Initialize SQLite (mutex subsystem) */18  sqlite3_initialize();19 20  PGroup *pGroup = (PGroup*)sqlite3_malloc(sizeof(*pGroup));21  TEST_ASSERT_NOT_NULL(pGroup);22  memset(pGroup, 0, sizeof(*pGroup));23 24  sqlite3_mutex *pMx = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);25  TEST_ASSERT_NOT_NULL(pMx);26  pGroup->mutex = pMx;27 28  PCache1 *pCache = (PCache1*)sqlite3_malloc(sizeof(*pCache));29  TEST_ASSERT_NOT_NULL(pCache);30  memset(pCache, 0, sizeof(*pCache));31  pCache->pGroup = pGroup;32  pCache->nHash = (unsigned int)nHash;33 34  PgHdr1 **apHash = (PgHdr1**)sqlite3_malloc(sizeof(PgHdr1*) * nHash);35  TEST_ASSERT_NOT_NULL(apHash);36  memset(apHash, 0, sizeof(PgHdr1*) * nHash);37  pCache->apHash = apHash;38 39  int *pnPurgeable = (int*)sqlite3_malloc(sizeof(int));40  TEST_ASSERT_NOT_NULL(pnPurgeable);41  *pnPurgeable = 0;42  pCache->pnPurgeable = pnPurgeable;43 44  if( ppGroupOut ) *ppGroupOut = pGroup;45  if( ppMutexOut ) *ppMutexOut = pMx;46  if( ppPurgeableOut ) *ppPurgeableOut = pnPurgeable;47  return pCache;48}49 50static void freeCache(PCache1 *pCache){51  if( pCache==NULL ) return;52  /* Free any pages on pFree list that our tests may have stashed */53  PgHdr1 *p = pCache->pFree;54  while( p ){55    PgHdr1 *pNext = p->pNext;56    /* For bulk-local pages we didn't allocate p->page.pBuf, so no free of pBuf */57    sqlite3_free(p);58    p = pNext;59  }60  if( pCache->apHash ){61    sqlite3_free(pCache->apHash);62  }63  if( pCache->pnPurgeable ){64    sqlite3_free(pCache->pnPurgeable);65  }66  if( pCache->pGroup ){67    if( pCache->pGroup->mutex ){68      sqlite3_mutex_free(pCache->pGroup->mutex);69    }70    sqlite3_free(pCache->pGroup);71  }72  sqlite3_free(pCache);73}74 75static PgHdr1* makePage(PCache1 *pCache, unsigned int key, int isBulkLocal, int allocBuf){76  PgHdr1 *p = (PgHdr1*)sqlite3_malloc(sizeof(*p));77  TEST_ASSERT_NOT_NULL(p);78  memset(p, 0, sizeof(*p));79  p->pCache = pCache;80  p->iKey = key;81  p->isBulkLocal = (u8)(isBulkLocal!=0);82  p->pNext = NULL;83  p->page.pBuf = allocBuf ? sqlite3_malloc(64) : NULL;84  /* We don't use p->page.pExtra in these tests */85  return p;86}87 88/* Unity setUp/tearDown */89void setUp(void) {90  /* Ensure SQLite core is initialized for mutex/malloc */91  sqlite3_initialize();92}93void tearDown(void) {94  /* No global teardown needed */95}96 97/* Tests */98 99/* Remove single element bucket without freeing */100void test_pcache1RemoveFromHash_single_no_free(void){101  PGroup *pGroup = NULL;102  sqlite3_mutex *pMx = NULL;103  int *pnPurgeable = NULL;104  PCache1 *pCache = makeCache(8, &pGroup, &pMx, &pnPurgeable);105 106  unsigned int key = 3;107  PgHdr1 *p = makePage(pCache, key, /*isBulkLocal=*/0, /*allocBuf=*/1);108  unsigned int h = key % pCache->nHash;109  pCache->apHash[h] = p;110  pCache->nPage = 1;111  *pCache->pnPurgeable = 5;112 113  sqlite3_mutex_enter(pGroup->mutex);114  test_pcache1RemoveFromHash(p, /*freeFlag=*/0);115  sqlite3_mutex_leave(pGroup->mutex);116 117  TEST_ASSERT_NULL(pCache->apHash[h]);118  TEST_ASSERT_EQUAL_INT(0, pCache->nPage);119  TEST_ASSERT_EQUAL_INT(5, *pCache->pnPurgeable);120  TEST_ASSERT_NULL(pCache->pFree);121 122  /* Cleanup: page not freed by function since freeFlag=0 */123  sqlite3_free(p->page.pBuf);124  sqlite3_free(p);125  freeCache(pCache);126}127 128/* Remove middle of a 3-element chain without freeing */129void test_pcache1RemoveFromHash_middle_of_chain_no_free(void){130  PGroup *pGroup = NULL;131  sqlite3_mutex *pMx = NULL;132  PCache1 *pCache = makeCache(4, &pGroup, &pMx, NULL);133 134  unsigned int base = 1;135  unsigned int kA = base;136  unsigned int kB = base + pCache->nHash;137  unsigned int kC = base + 2*pCache->nHash;138  unsigned int h = base % pCache->nHash;139 140  PgHdr1 *A = makePage(pCache, kA, 0, 1);141  PgHdr1 *B = makePage(pCache, kB, 0, 1);142  PgHdr1 *C = makePage(pCache, kC, 0, 1);143 144  pCache->apHash[h] = A;145  A->pNext = B;146  B->pNext = C;147  C->pNext = NULL;148  pCache->nPage = 3;149 150  sqlite3_mutex_enter(pGroup->mutex);151  test_pcache1RemoveFromHash(B, 0);152  sqlite3_mutex_leave(pGroup->mutex);153 154  TEST_ASSERT_EQUAL_PTR(A, pCache->apHash[h]);155  TEST_ASSERT_EQUAL_PTR(C, A->pNext);156  TEST_ASSERT_NULL(C->pNext);157  TEST_ASSERT_EQUAL_INT(2, pCache->nPage);158 159  /* Cleanup */160  sqlite3_free(A->page.pBuf);161  sqlite3_free(B->page.pBuf);162  sqlite3_free(C->page.pBuf);163  sqlite3_free(A);164  sqlite3_free(B);165  sqlite3_free(C);166  freeCache(pCache);167}168 169/* Remove head of chain without freeing */170void test_pcache1RemoveFromHash_head_of_chain_no_free(void){171  PGroup *pGroup = NULL;172  sqlite3_mutex *pMx = NULL;173  PCache1 *pCache = makeCache(4, &pGroup, &pMx, NULL);174 175  unsigned int base = 2;176  unsigned int kH = base;177  unsigned int kX = base + pCache->nHash;178  unsigned int h = base % pCache->nHash;179 180  PgHdr1 *H = makePage(pCache, kH, 0, 1);181  PgHdr1 *X = makePage(pCache, kX, 0, 1);182 183  pCache->apHash[h] = H;184  H->pNext = X;185  X->pNext = NULL;186  pCache->nPage = 2;187 188  sqlite3_mutex_enter(pGroup->mutex);189  test_pcache1RemoveFromHash(H, 0);190  sqlite3_mutex_leave(pGroup->mutex);191 192  TEST_ASSERT_EQUAL_PTR(X, pCache->apHash[h]);193  TEST_ASSERT_NULL(X->pNext);194  TEST_ASSERT_EQUAL_INT(1, pCache->nPage);195 196  /* Cleanup */197  sqlite3_free(H->page.pBuf);198  sqlite3_free(X->page.pBuf);199  sqlite3_free(H);200  sqlite3_free(X);201  freeCache(pCache);202}203 204/* Remove tail of chain without freeing */205void test_pcache1RemoveFromHash_tail_of_chain_no_free(void){206  PGroup *pGroup = NULL;207  sqlite3_mutex *pMx = NULL;208  PCache1 *pCache = makeCache(4, &pGroup, &pMx, NULL);209 210  unsigned int base = 0;211  unsigned int kA = base;212  unsigned int kB = base + pCache->nHash;213  unsigned int h = base % pCache->nHash;214 215  PgHdr1 *A = makePage(pCache, kA, 0, 1);216  PgHdr1 *B = makePage(pCache, kB, 0, 1);217 218  pCache->apHash[h] = A;219  A->pNext = B;220  B->pNext = NULL;221  pCache->nPage = 2;222 223  sqlite3_mutex_enter(pGroup->mutex);224  test_pcache1RemoveFromHash(B, 0);225  sqlite3_mutex_leave(pGroup->mutex);226 227  TEST_ASSERT_EQUAL_PTR(A, pCache->apHash[h]);228  TEST_ASSERT_NULL(A->pNext);229  TEST_ASSERT_EQUAL_INT(1, pCache->nPage);230 231  /* Cleanup */232  sqlite3_free(A->page.pBuf);233  sqlite3_free(B->page.pBuf);234  sqlite3_free(A);235  sqlite3_free(B);236  freeCache(pCache);237}238 239/* Remove with freeFlag=1 where page is bulk-local: should go to pFree and pnPurgeable decremented */240void test_pcache1RemoveFromHash_free_bulkLocal(void){241  PGroup *pGroup = NULL;242  sqlite3_mutex *pMx = NULL;243  int *pnPurgeable = NULL;244  PCache1 *pCache = makeCache(8, &pGroup, &pMx, &pnPurgeable);245 246  unsigned int key = 5;247  unsigned int h = key % pCache->nHash;248  PgHdr1 *p = makePage(pCache, key, /*isBulkLocal=*/1, /*allocBuf=*/0);249  pCache->apHash[h] = p;250  pCache->nPage = 1;251  *pnPurgeable = 7;252 253  sqlite3_mutex_enter(pGroup->mutex);254  test_pcache1RemoveFromHash(p, /*freeFlag=*/1);255  sqlite3_mutex_leave(pGroup->mutex);256 257  TEST_ASSERT_NULL(pCache->apHash[h]);258  TEST_ASSERT_EQUAL_INT(0, pCache->nPage);259  TEST_ASSERT_EQUAL_INT(6, *pnPurgeable);260  TEST_ASSERT_EQUAL_PTR(p, pCache->pFree);261  TEST_ASSERT_NULL(p->pNext); /* was added to empty free list */262 263  /* Cleanup: remove from pFree and free node */264  pCache->pFree = NULL;265  sqlite3_free(p);266  freeCache(pCache);267}268 269/* Remove with freeFlag=1 where page is NOT bulk-local: should free buffer, not add to pFree, pnPurgeable decremented */270void test_pcache1RemoveFromHash_free_nonBulkLocal(void){271  PGroup *pGroup = NULL;272  sqlite3_mutex *pMx = NULL;273  int *pnPurgeable = NULL;274  PCache1 *pCache = makeCache(8, &pGroup, &pMx, &pnPurgeable);275 276  /* Prepare a dummy existing free-list head to ensure it remains unchanged */277  PgHdr1 *dummyFree = makePage(pCache, /*key*/123, /*isBulkLocal=*/1, /*allocBuf=*/0);278  dummyFree->pNext = NULL;279  pCache->pFree = dummyFree;280 281  unsigned int key = 6;282  unsigned int h = key % pCache->nHash;283  PgHdr1 *p = makePage(pCache, key, /*isBulkLocal=*/0, /*allocBuf=*/1);284  pCache->apHash[h] = p;285  pCache->nPage = 1;286  *pnPurgeable = 3;287 288  sqlite3_mutex_enter(pGroup->mutex);289  test_pcache1RemoveFromHash(p, /*freeFlag=*/1);290  sqlite3_mutex_leave(pGroup->mutex);291 292  TEST_ASSERT_NULL(pCache->apHash[h]);293  TEST_ASSERT_EQUAL_INT(0, pCache->nPage);294  TEST_ASSERT_EQUAL_INT(2, *pnPurgeable);295  /* Non-bulk pages should not be added to pFree; existing pFree remains unchanged */296  TEST_ASSERT_EQUAL_PTR(dummyFree, pCache->pFree);297 298  /* Cleanup: 'p->page.pBuf' should have been freed by pcache1FreePage, so only free 'p' itself */299  sqlite3_free(p);300  sqlite3_free(dummyFree);301  pCache->pFree = NULL;302  freeCache(pCache);303}304 305int main(void){306  UNITY_BEGIN();307  RUN_TEST(test_pcache1RemoveFromHash_single_no_free);308  RUN_TEST(test_pcache1RemoveFromHash_middle_of_chain_no_free);309  RUN_TEST(test_pcache1RemoveFromHash_head_of_chain_no_free);310  RUN_TEST(test_pcache1RemoveFromHash_tail_of_chain_no_free);311  RUN_TEST(test_pcache1RemoveFromHash_free_bulkLocal);312  RUN_TEST(test_pcache1RemoveFromHash_free_nonBulkLocal);313  return UNITY_END();314}