AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4 5/* The build system provides a wrapper for the static function under test. */6extern int test_ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno);7 8static void open_autovacuum_btree(Btree **ppBtree, sqlite3 **ppDb){9 int rc;10 sqlite3 *db = 0;11 Btree *pBtree = 0;12 sqlite3_vfs *pVfs = sqlite3_vfs_find(0);13 TEST_ASSERT_NOT_NULL_MESSAGE(pVfs, "sqlite3_vfs_find failed");14 15 rc = sqlite3_open(":memory:", &db);16 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_open failed");17 18 /* Open an ephemeral btree (zFilename = NULL). */19 rc = sqlite3BtreeOpen(pVfs, 0, db, &pBtree, 0, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY);20 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3BtreeOpen failed");21 22 /* Enable autovacuum BEFORE the database is initialized. */23 rc = sqlite3BtreeSetAutoVacuum(pBtree, 1);24 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3BtreeSetAutoVacuum failed");25 26 /* Begin a write transaction and initialize a new database image. */27 rc = sqlite3BtreeBeginTrans(pBtree, 1, 0);28 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3BtreeBeginTrans failed");29 30 rc = sqlite3BtreeNewDb(pBtree);31 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3BtreeNewDb failed");32 33 *ppBtree = pBtree;34 *ppDb = db;35}36 37static void close_btree_and_db(Btree *pBtree, sqlite3 *db){38 if( pBtree ){39 /* Commit and close */40 sqlite3BtreeCommit(pBtree);41 sqlite3BtreeClose(pBtree);42 }43 if( db ){44 sqlite3_close(db);45 }46}47 48void setUp(void) {49 /* no-op */50}51 52void tearDown(void) {53 /* no-op */54}55 56/* Helper: Create one new table and return its root page number. */57static Pgno create_one_table(Btree *pBtree){58 int rc;59 Pgno root = 0;60 /* Create a table with integer keys and data (ordinary rowid table). */61 rc = sqlite3BtreeCreateTable(pBtree, &root, BTREE_INTKEY | BTREE_LEAFDATA);62 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3BtreeCreateTable failed");63 TEST_ASSERT_TRUE_MESSAGE(root >= 2, "root page should be >= 2");64 return root;65}66 67void test_ptrmapGet_rootpage_basic(void){68 sqlite3 *db = 0;69 Btree *pBtree = 0;70 open_autovacuum_btree(&pBtree, &db);71 72 /* Create a table and verify its root page has PTRMAP_ROOTPAGE with parent 0. */73 Pgno root = create_one_table(pBtree);74 75 u8 eType = 0;76 Pgno parent = 0;77 int rc = test_ptrmapGet(pBtree->pBt, root, &eType, &parent);78 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);79 TEST_ASSERT_EQUAL_UINT8(PTRMAP_ROOTPAGE, eType);80 TEST_ASSERT_EQUAL_UINT32(0u, parent);81 82 close_btree_and_db(pBtree, db);83}84 85void test_ptrmapGet_after_drop_freepage(void){86 sqlite3 *db = 0;87 Btree *pBtree = 0;88 open_autovacuum_btree(&pBtree, &db);89 90 Pgno root = create_one_table(pBtree);91 92 /* Drop the table: the former root page should become a freepage. */93 int moved = 0;94 int rc = sqlite3BtreeDropTable(pBtree, (int)root, &moved);95 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3BtreeDropTable failed");96 97 /* Verify pointer map entry for the dropped page is PTRMAP_FREEPAGE. */98 u8 eType = 0;99 Pgno parent = 12345; /* will be overwritten */100 rc = test_ptrmapGet(pBtree->pBt, root, &eType, &parent);101 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);102 TEST_ASSERT_EQUAL_UINT8(PTRMAP_FREEPAGE, eType);103 TEST_ASSERT_EQUAL_UINT32(0u, parent);104 105 close_btree_and_db(pBtree, db);106}107 108void test_ptrmapGet_invalid_type_corruption(void){109 sqlite3 *db = 0;110 Btree *pBtree = 0;111 open_autovacuum_btree(&pBtree, &db);112 113 Pgno root = create_one_table(pBtree);114 115 /* Corrupt the pointer map entry type byte for 'root'. */116 BtShared *pBt = pBtree->pBt;117 int iPtrmap = PTRMAP_PAGENO(pBt, root);118 DbPage *pPg = 0;119 int rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pPg, 0);120 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3PagerGet failed");121 122 u8 *pData = (u8*)sqlite3PagerGetData(pPg);123 int offset = PTRMAP_PTROFFSET(iPtrmap, root);124 TEST_ASSERT_TRUE_MESSAGE(offset >= 0, "PTRMAP_PTROFFSET returned negative");125 126 rc = sqlite3PagerWrite(pPg);127 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3PagerWrite failed");128 129 /* Set invalid type (0) */130 pData[offset] = 0;131 sqlite3PagerUnref(pPg);132 133 u8 eType = 0xFF;134 Pgno parent = 0xFFFFFFFF;135 rc = test_ptrmapGet(pBt, root, &eType, &parent);136 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_CORRUPT, (rc & 0xff), "Expected SQLITE_CORRUPT from ptrmapGet on invalid type");137 138 close_btree_and_db(pBtree, db);139}140 141int main(void){142 UNITY_BEGIN();143 RUN_TEST(test_ptrmapGet_rootpage_basic);144 RUN_TEST(test_ptrmapGet_after_drop_freepage);145 RUN_TEST(test_ptrmapGet_invalid_type_corruption);146 return UNITY_END();147}