AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6/* Replicate minimal internal structures needed to call and inspect StatPage.7 These match the definitions in dbstat.c. */8typedef struct StatCell StatCell;9struct StatCell {10 int nLocal;11 u32 iChildPg;12 int nOvfl;13 u32 *aOvfl;14 int nLastOvfl;15 int iOvfl;16};17 18typedef struct StatPage StatPage;19struct StatPage {20 u32 iPgno;21 u8 *aPg;22 int iCell;23 char *zPath;24 25 /* Populated by statDecodePage() - not used by statGetPage() tests */26 u8 flags;27 int nCell;28 int nUnused;29 StatCell *aCell;30 u32 iRightChildPg;31 int nMxPayload;32};33 34/* Wrapper provided by dbstat.c */35extern int test_statGetPage(Btree *pBt, u32 iPg, StatPage *pPg);36 37static void execSQL(sqlite3 *db, const char *zSql){38 int rc = sqlite3_exec(db, zSql, 0, 0, 0);39 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, sqlite3_errmsg(db));40}41 42void setUp(void) {43 /* Setup code here */44}45 46void tearDown(void) {47 /* Cleanup code here */48}49 50/* Verify that statGetPage allocates the buffer if needed, copies the exact51 page content, and zero-fills the 256-byte padding region. */52void test_statGetPage_basic_alloc_and_copy(void){53 sqlite3 *db = 0;54 int rc = sqlite3_open(":memory:", &db);55 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);56 TEST_ASSERT_NOT_NULL(db);57 58 /* Access the internal Btree of the main database */59 Btree *pBt = db->aDb[0].pBt;60 TEST_ASSERT_NOT_NULL(pBt);61 62 /* Prepare StatPage */63 StatPage sp;64 memset(&sp, 0, sizeof(sp));65 66 rc = test_statGetPage(pBt, 1, &sp);67 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);68 TEST_ASSERT_NOT_NULL(sp.aPg);69 70 int pgsz = sqlite3BtreeGetPageSize(pBt);71 TEST_ASSERT_TRUE_MESSAGE(pgsz > 0, "Page size must be > 0");72 73 /* Compare copied data to pager data */74 DbPage *pDbPage = 0;75 rc = sqlite3PagerGet(sqlite3BtreePager(pBt), 1, &pDbPage, 0);76 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);77 const u8 *aRef = sqlite3PagerGetData(pDbPage);78 TEST_ASSERT_NOT_NULL(aRef);79 80 TEST_ASSERT_EQUAL_INT(0, memcmp(sp.aPg, aRef, pgsz));81 sqlite3PagerUnref(pDbPage);82 83 /* Verify the 256 bytes of padding are zeroed */84 for(int i=0; i<256; i++){85 TEST_ASSERT_EQUAL_UINT8(0, sp.aPg[pgsz + i]);86 }87 88 sqlite3_free(sp.aPg);89 sp.aPg = 0;90 91 sqlite3_close(db);92}93 94/* Ensure buffer reuse (no reallocation) and correct content for a second page,95 and that padding remains zero after reuse. */96void test_statGetPage_reuse_and_second_page(void){97 sqlite3 *db = 0;98 int rc = sqlite3_open(":memory:", &db);99 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);100 TEST_ASSERT_NOT_NULL(db);101 102 /* Create enough content to ensure multiple pages exist */103 execSQL(db, "PRAGMA journal_mode=OFF;");104 execSQL(db, "CREATE TABLE t(x);");105 execSQL(db, "BEGIN;");106 /* Insert 200 rows of 1000-byte blobs (~200KB) to ensure many pages */107 for(int i=0; i<200; i++){108 execSQL(db, "INSERT INTO t VALUES(zeroblob(1000));");109 }110 execSQL(db, "COMMIT;");111 112 Btree *pBt = db->aDb[0].pBt;113 TEST_ASSERT_NOT_NULL(pBt);114 Pager *pPager = sqlite3BtreePager(pBt);115 int nPage = 0;116 sqlite3PagerPagecount(pPager, &nPage);117 TEST_ASSERT_TRUE_MESSAGE(nPage >= 2, "Database should have at least 2 pages after inserts");118 119 StatPage sp;120 memset(&sp, 0, sizeof(sp));121 122 /* First load page 1 */123 rc = test_statGetPage(pBt, 1, &sp);124 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);125 TEST_ASSERT_NOT_NULL(sp.aPg);126 u8 *pBuf = sp.aPg;127 128 int pgsz = sqlite3BtreeGetPageSize(pBt);129 TEST_ASSERT_TRUE(pgsz > 0);130 131 /* Then load page 2 into the same StatPage - buffer should be reused */132 rc = test_statGetPage(pBt, 2, &sp);133 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);134 TEST_ASSERT_EQUAL_PTR(pBuf, sp.aPg);135 136 /* Compare copied data for page 2 */137 DbPage *pDbPage2 = 0;138 rc = sqlite3PagerGet(pPager, 2, &pDbPage2, 0);139 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);140 const u8 *aRef2 = sqlite3PagerGetData(pDbPage2);141 TEST_ASSERT_NOT_NULL(aRef2);142 TEST_ASSERT_EQUAL_INT(0, memcmp(sp.aPg, aRef2, pgsz));143 sqlite3PagerUnref(pDbPage2);144 145 /* Padding should still be zero after reuse */146 for(int i=0; i<256; i++){147 TEST_ASSERT_EQUAL_UINT8(0, sp.aPg[pgsz + i]);148 }149 150 sqlite3_free(sp.aPg);151 sp.aPg = 0;152 153 sqlite3_close(db);154}155 156/* Verify that calling statGetPage again for the same page leaves content consistent157 and does not change the buffer pointer. */158void test_statGetPage_idempotent_same_page(void){159 sqlite3 *db = 0;160 int rc = sqlite3_open(":memory:", &db);161 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);162 TEST_ASSERT_NOT_NULL(db);163 164 Btree *pBt = db->aDb[0].pBt;165 TEST_ASSERT_NOT_NULL(pBt);166 Pager *pPager = sqlite3BtreePager(pBt);167 int pgsz = sqlite3BtreeGetPageSize(pBt);168 169 StatPage sp;170 memset(&sp, 0, sizeof(sp));171 172 rc = test_statGetPage(pBt, 1, &sp);173 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);174 TEST_ASSERT_NOT_NULL(sp.aPg);175 u8 *pBuf = sp.aPg;176 177 /* Snapshot reference of page 1 */178 DbPage *pDbPage = 0;179 rc = sqlite3PagerGet(pPager, 1, &pDbPage, 0);180 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);181 const u8 *aRef = sqlite3PagerGetData(pDbPage);182 TEST_ASSERT_EQUAL_INT(0, memcmp(sp.aPg, aRef, pgsz));183 sqlite3PagerUnref(pDbPage);184 185 /* Call again for the same page and verify pointer and content */186 rc = test_statGetPage(pBt, 1, &sp);187 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);188 TEST_ASSERT_EQUAL_PTR(pBuf, sp.aPg);189 190 DbPage *pDbPageAgain = 0;191 rc = sqlite3PagerGet(pPager, 1, &pDbPageAgain, 0);192 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);193 const u8 *aRefAgain = sqlite3PagerGetData(pDbPageAgain);194 TEST_ASSERT_EQUAL_INT(0, memcmp(sp.aPg, aRefAgain, pgsz));195 sqlite3PagerUnref(pDbPageAgain);196 197 /* Padding still zero */198 for(int i=0; i<256; i++){199 TEST_ASSERT_EQUAL_UINT8(0, sp.aPg[pgsz + i]);200 }201 202 sqlite3_free(sp.aPg);203 sp.aPg = 0;204 205 sqlite3_close(db);206}207 208int main(void){209 UNITY_BEGIN();210 RUN_TEST(test_statGetPage_basic_alloc_and_copy);211 RUN_TEST(test_statGetPage_reuse_and_second_page);212 RUN_TEST(test_statGetPage_idempotent_same_page);213 return UNITY_END();214}