AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5#include <stdint.h>6 7/* Unity setup/teardown */8void setUp(void) {9 /* Ensure library is shut down before each test so sqlite3_config is allowed */10 sqlite3_shutdown();11}12void tearDown(void) {13 /* Cleanup - ensure shutdown after each test */14 sqlite3_shutdown();15}16 17/* Stubs for a custom pcache2 implementation used to verify override behavior.18 These are not called in the tests; pointers are used for identity checks. */19static int myPCache2Init(void *pArg){ (void)pArg; return SQLITE_OK; }20static void myPCache2Shutdown(void *pArg){ (void)pArg; }21static sqlite3_pcache *myPCache2Create(int a, int b, int c){ (void)a; (void)b; (void)c; return (sqlite3_pcache*)0; }22static void myPCache2Cachesize(sqlite3_pcache *p, int n){ (void)p; (void)n; }23static int myPCache2Pagecount(sqlite3_pcache *p){ (void)p; return 0; }24static sqlite3_pcache_page *myPCache2Fetch(sqlite3_pcache *p, unsigned int k, int f){25 (void)p; (void)k; (void)f; return (sqlite3_pcache_page*)0;26}27static void myPCache2Unpin(sqlite3_pcache *p, sqlite3_pcache_page *pg, int d){28 (void)p; (void)pg; (void)d;29}30static void myPCache2Rekey(sqlite3_pcache *p, sqlite3_pcache_page *pg, unsigned int ok, unsigned int nk){31 (void)p; (void)pg; (void)ok; (void)nk;32}33static void myPCache2Truncate(sqlite3_pcache *p, unsigned int lim){ (void)p; (void)lim; }34static void myPCache2Destroy(sqlite3_pcache *p){ (void)p; }35static void myPCache2Shrink(sqlite3_pcache *p){ (void)p; }36 37/* Helper to fetch current pcache2 methods into out parameter */38static int getPCache2(sqlite3_pcache_methods2 *pOut){39 memset(pOut, 0, sizeof(*pOut));40 return sqlite3_config(SQLITE_CONFIG_GETPCACHE2, pOut);41}42 43/* Test 1: sqlite3PCacheSetDefault sets non-NULL methods with expected version and pArg */44static void test_sqlite3PCacheSetDefault_sets_pcache2_methods_fields(void){45 int rc;46 sqlite3_pcache_methods2 m;47 48 /* Ensure not initialized and set default methods */49 sqlite3_shutdown();50 sqlite3PCacheSetDefault();51 52 rc = getPCache2(&m);53 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);54 TEST_ASSERT_EQUAL_INT(1, m.iVersion);55 TEST_ASSERT_NULL(m.pArg);56 57 /* All function pointers should be non-NULL */58 TEST_ASSERT_NOT_NULL(m.xInit);59 TEST_ASSERT_NOT_NULL(m.xShutdown);60 TEST_ASSERT_NOT_NULL(m.xCreate);61 TEST_ASSERT_NOT_NULL(m.xCachesize);62 TEST_ASSERT_NOT_NULL(m.xPagecount);63 TEST_ASSERT_NOT_NULL(m.xFetch);64 TEST_ASSERT_NOT_NULL(m.xUnpin);65 TEST_ASSERT_NOT_NULL(m.xRekey);66 TEST_ASSERT_NOT_NULL(m.xTruncate);67 TEST_ASSERT_NOT_NULL(m.xDestroy);68 TEST_ASSERT_NOT_NULL(m.xShrink);69}70 71/* Test 2: Idempotence - two calls produce identical method tables (pointer equality) */72static void test_sqlite3PCacheSetDefault_is_idempotent(void){73 int rc;74 sqlite3_pcache_methods2 m1, m2;75 76 sqlite3_shutdown();77 78 sqlite3PCacheSetDefault();79 rc = getPCache2(&m1);80 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);81 82 sqlite3PCacheSetDefault();83 rc = getPCache2(&m2);84 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);85 86 TEST_ASSERT_EQUAL_INT(m1.iVersion, m2.iVersion);87 TEST_ASSERT_EQUAL_PTR(m1.pArg, m2.pArg);88 TEST_ASSERT_EQUAL_PTR(m1.xInit, m2.xInit);89 TEST_ASSERT_EQUAL_PTR(m1.xShutdown, m2.xShutdown);90 TEST_ASSERT_EQUAL_PTR(m1.xCreate, m2.xCreate);91 TEST_ASSERT_EQUAL_PTR(m1.xCachesize, m2.xCachesize);92 TEST_ASSERT_EQUAL_PTR(m1.xPagecount, m2.xPagecount);93 TEST_ASSERT_EQUAL_PTR(m1.xFetch, m2.xFetch);94 TEST_ASSERT_EQUAL_PTR(m1.xUnpin, m2.xUnpin);95 TEST_ASSERT_EQUAL_PTR(m1.xRekey, m2.xRekey);96 TEST_ASSERT_EQUAL_PTR(m1.xTruncate, m2.xTruncate);97 TEST_ASSERT_EQUAL_PTR(m1.xDestroy, m2.xDestroy);98 TEST_ASSERT_EQUAL_PTR(m1.xShrink, m2.xShrink);99}100 101/* Test 3: A prior user configuration is overwritten by sqlite3PCacheSetDefault (pre-initialize) */102static void test_sqlite3PCacheSetDefault_overrides_previous_config_before_init(void){103 int rc;104 sqlite3_pcache_methods2 m;105 106 /* Install a custom pcache2 implementation before initialization */107 static int customArg = 0x51;108 sqlite3_pcache_methods2 custom = {109 1, /* iVersion */110 &customArg, /* pArg */111 myPCache2Init, /* xInit */112 myPCache2Shutdown, /* xShutdown */113 myPCache2Create, /* xCreate */114 myPCache2Cachesize, /* xCachesize */115 myPCache2Pagecount, /* xPagecount */116 myPCache2Fetch, /* xFetch */117 myPCache2Unpin, /* xUnpin */118 myPCache2Rekey, /* xRekey */119 myPCache2Truncate, /* xTruncate */120 myPCache2Destroy, /* xDestroy */121 myPCache2Shrink /* xShrink */122 };123 124 sqlite3_shutdown();125 126 rc = sqlite3_config(SQLITE_CONFIG_PCACHE2, &custom);127 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);128 129 rc = getPCache2(&m);130 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);131 TEST_ASSERT_EQUAL_INT(1, m.iVersion);132 TEST_ASSERT_EQUAL_PTR(&customArg, m.pArg);133 TEST_ASSERT_EQUAL_PTR(myPCache2Init, m.xInit);134 135 /* Now call the function under test - it should install the default, overwriting the custom */136 sqlite3PCacheSetDefault();137 138 rc = getPCache2(&m);139 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);140 141 /* Verify default replaced custom: pArg reset to NULL and xInit pointer changed */142 TEST_ASSERT_EQUAL_INT(1, m.iVersion);143 TEST_ASSERT_NULL(m.pArg);144 TEST_ASSERT(m.xInit != myPCache2Init);145 146 /* And all function pointers are non-NULL (sanity) */147 TEST_ASSERT_NOT_NULL(m.xShutdown);148 TEST_ASSERT_NOT_NULL(m.xCreate);149 TEST_ASSERT_NOT_NULL(m.xCachesize);150 TEST_ASSERT_NOT_NULL(m.xPagecount);151 TEST_ASSERT_NOT_NULL(m.xFetch);152 TEST_ASSERT_NOT_NULL(m.xUnpin);153 TEST_ASSERT_NOT_NULL(m.xRekey);154 TEST_ASSERT_NOT_NULL(m.xTruncate);155 TEST_ASSERT_NOT_NULL(m.xDestroy);156 TEST_ASSERT_NOT_NULL(m.xShrink);157}158 159int main(void){160 UNITY_BEGIN();161 RUN_TEST(test_sqlite3PCacheSetDefault_sets_pcache2_methods_fields);162 RUN_TEST(test_sqlite3PCacheSetDefault_is_idempotent);163 RUN_TEST(test_sqlite3PCacheSetDefault_overrides_previous_config_before_init);164 return UNITY_END();165}