Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_btree_newDatabase.c195 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Wrapper provided by the build per instructions */7int test_newDatabase(BtShared *pBt);8 9static sqlite3 *gDb = NULL;10 11static Btree* getMainBtree(sqlite3 *db){12  /* Access internal aDb[0].pBt (Btree*) from sqliteInt.h */13  return db->aDb[0].pBt;14}15 16static void beginWriteTrans(Btree *p){17  int rc = sqlite3BtreeBeginTrans(p, 1, 0);18  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);19}20 21static void commitTrans(Btree *p){22  int rc = sqlite3BtreeCommit(p);23  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);24}25 26void setUp(void) {27  int rc = sqlite3_initialize();28  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);29  rc = sqlite3_open(":memory:", &gDb);30  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);31}32 33void tearDown(void) {34  if( gDb ){35    sqlite3_close(gDb);36    gDb = NULL;37  }38}39 40/* Helper to copy first 100 bytes of db header */41static void copy_header_100(BtShared *pBt, unsigned char *dst){42  MemPage *pP1 = pBt->pPage1;43  TEST_ASSERT_NOT_NULL(pP1);44  TEST_ASSERT_NOT_NULL(pP1->aData);45  memcpy(dst, pP1->aData, 100);46}47 48static void assert_header_100_equal(BtShared *pBt, const unsigned char *hdr){49  MemPage *pP1 = pBt->pPage1;50  TEST_ASSERT_NOT_NULL(pP1);51  TEST_ASSERT_EQUAL_INT8_ARRAY(hdr, pP1->aData, 100);52}53 54static void load_magic_header(unsigned char *dst16){55  /* SQLITE_FILE_HEADER is 16 bytes, available via btree.c static const,56     but not directly visible here. Instead, read current db -> it should57     already contain the correct file header after open().58 59     For tests that require an exact comparison, we can take the header60     from current page before forcing nPage=0, then after newDatabase()61     it should still match. For initialization test we'll validate specific62     bytes instead of full compare to avoid platform-dependent values. */63  (void)dst16;64}65 66/* TEST 1: When nPage > 0, newDatabase should be a no-op and return SQLITE_OK */67void test_newDatabase_noop_when_nPage_gt_zero(void){68  TEST_ASSERT_NOT_NULL(gDb);69  Btree *pBtree = getMainBtree(gDb);70  TEST_ASSERT_NOT_NULL(pBtree);71  BtShared *pBt = pBtree->pBt;72  TEST_ASSERT_NOT_NULL(pBt);73 74  beginWriteTrans(pBtree);75 76  /* Capture initial state */77  unsigned char hdrBefore[100];78  sqlite3BtreeEnter(pBtree);79  TEST_ASSERT_TRUE(pBt->nPage > 0);80  Pgno nPageBefore = pBt->nPage;81  copy_header_100(pBt, hdrBefore);82 83  /* Call target wrapper while holding the mutex */84  int rc = test_newDatabase(pBt);85  sqlite3BtreeLeave(pBtree);86 87  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);88 89  /* Verify no changes */90  sqlite3BtreeEnter(pBtree);91  TEST_ASSERT_EQUAL_INT(nPageBefore, (int)pBt->nPage);92  assert_header_100_equal(pBt, hdrBefore);93  sqlite3BtreeLeave(pBtree);94 95  commitTrans(pBtree);96}97 98/* TEST 2: When nPage == 0, newDatabase initializes header and root correctly */99void test_newDatabase_initializes_header_and_root(void){100  TEST_ASSERT_NOT_NULL(gDb);101  Btree *pBtree = getMainBtree(gDb);102  TEST_ASSERT_NOT_NULL(pBtree);103  BtShared *pBt = pBtree->pBt;104  TEST_ASSERT_NOT_NULL(pBt);105 106  beginWriteTrans(pBtree);107 108  sqlite3BtreeEnter(pBtree);109 110  /* Force nPage to 0 to trigger initialization */111  pBt->nPage = 0;112 113  /* Capture page1 and parameters */114  MemPage *pP1 = pBt->pPage1;115  TEST_ASSERT_NOT_NULL(pP1);116  TEST_ASSERT_NOT_NULL(pP1->aData);117  unsigned char *data = pP1->aData;118  u32 pageSize = pBt->pageSize;119  u32 usableSize = pBt->usableSize;120 121  int rc = test_newDatabase(pBt);122  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);123 124  /* Validate header bytes set by newDatabase */125  /* 16-23 as per code: endian parts of pageSize, read/write versions, reserved, fractions */126  TEST_ASSERT_EQUAL_HEX8((u8)((pageSize>>8)&0xff), data[16]);127  TEST_ASSERT_EQUAL_HEX8((u8)((pageSize>>16)&0xff), data[17]);128  TEST_ASSERT_EQUAL_HEX8(1, data[18]); /* read version */129  TEST_ASSERT_EQUAL_HEX8(1, data[19]); /* write version */130  TEST_ASSERT_EQUAL_HEX8((u8)(pageSize - usableSize), data[20]); /* reserved size */131  TEST_ASSERT_EQUAL_HEX8(64, data[21]); /* max fraction */132  TEST_ASSERT_EQUAL_HEX8(32, data[22]); /* min fraction */133  TEST_ASSERT_EQUAL_HEX8(32, data[23]); /* leaf fraction */134  /* data[31] set to 1 */135  TEST_ASSERT_EQUAL_HEX8(1, data[31]);136 137  /* Check that root page (page 1) header at offset 100 has correct flags */138  int hdr = pP1->hdrOffset; /* should be 100 */139  TEST_ASSERT_EQUAL_INT(100, hdr);140  /* Flags PTF_INTKEY | PTF_LEAFDATA | PTF_LEAF */141  TEST_ASSERT_EQUAL_HEX8(PTF_INTKEY | PTF_LEAFDATA | PTF_LEAF, data[hdr + 0]);142 143  /* nPage set to 1 and BTS_PAGESIZE_FIXED set */144  TEST_ASSERT_EQUAL_UINT32(1, pBt->nPage);145  TEST_ASSERT_TRUE((pBt->btsFlags & BTS_PAGESIZE_FIXED) != 0);146 147  sqlite3BtreeLeave(pBtree);148 149  commitTrans(pBtree);150}151 152#ifndef SQLITE_OMIT_AUTOVACUUM153/* TEST 3: Verify autovacuum meta fields are written according to flags */154void test_newDatabase_writes_autovacuum_meta(void){155  TEST_ASSERT_NOT_NULL(gDb);156  Btree *pBtree = getMainBtree(gDb);157  TEST_ASSERT_NOT_NULL(pBtree);158  BtShared *pBt = pBtree->pBt;159  TEST_ASSERT_NOT_NULL(pBt);160 161  beginWriteTrans(pBtree);162 163  sqlite3BtreeEnter(pBtree);164 165  /* Force fresh initialization */166  pBt->nPage = 0;167  pBt->autoVacuum = 1;168  pBt->incrVacuum = 1;169 170  int rc = test_newDatabase(pBt);171  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);172 173  /* Verify meta fields set at offsets 36+4*4 and 36+7*4 */174  unsigned char *data = pBt->pPage1->aData;175  u32 av = get4byte(&data[36 + 4*4]);176  u32 iv = get4byte(&data[36 + 7*4]);177  TEST_ASSERT_EQUAL_UINT32(1u, av);178  TEST_ASSERT_EQUAL_UINT32(1u, iv);179 180  sqlite3BtreeLeave(pBtree);181  commitTrans(pBtree);182}183#endif184 185int main(void) {186  UNITY_BEGIN();187 188  RUN_TEST(test_newDatabase_noop_when_nPage_gt_zero);189  RUN_TEST(test_newDatabase_initializes_header_and_root);190#ifndef SQLITE_OMIT_AUTOVACUUM191  RUN_TEST(test_newDatabase_writes_autovacuum_meta);192#endif193 194  return UNITY_END();195}