Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_dbstat_statGetPage.c214 linesDownload Raw Back to tests
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}