AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Wrapper declaration provided by the source under test */7int test_decodeFlags(MemPage *pPage, int flagByte);8 9/* Convenience constants (from btreeInt.h), included via sqliteInt.h */10#ifndef PTF_ZERODATA11# error "PTF_ZERODATA not defined"12#endif13 14/* Helper to create a BtShared with specific parameters and an entered mutex */15static BtShared* helperCreateBtShared(u8 max1bytePayload,16 u16 maxLeaf, u16 minLeaf,17 u16 maxLocal, u16 minLocal){18 BtShared *pBt = (BtShared*)sqlite3MallocZero(sizeof(BtShared));19 TEST_ASSERT_NOT_NULL(pBt);20 pBt->max1bytePayload = max1bytePayload;21 pBt->maxLeaf = maxLeaf;22 pBt->minLeaf = minLeaf;23 pBt->maxLocal = maxLocal;24 pBt->minLocal = minLocal;25 /* Allocate and enter a mutex to satisfy decodeFlags assertion */26 pBt->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);27 TEST_ASSERT_NOT_NULL(pBt->mutex);28 sqlite3_mutex_enter(pBt->mutex);29 return pBt;30}31 32/* Helper to destroy BtShared and release mutex */33static void helperDestroyBtShared(BtShared *pBt){34 if( pBt ){35 if( pBt->mutex ){36 sqlite3_mutex_leave(pBt->mutex);37 sqlite3_mutex_free(pBt->mutex);38 pBt->mutex = 0;39 }40 sqlite3_free(pBt);41 }42}43 44/* Helper to create a MemPage referencing BtShared with proper hdrOffset */45static MemPage* helperCreateMemPage(BtShared *pBt, Pgno pgno){46 MemPage *pPage = (MemPage*)sqlite3MallocZero(sizeof(MemPage));47 TEST_ASSERT_NOT_NULL(pPage);48 pPage->pBt = pBt;49 pPage->pgno = pgno;50 pPage->hdrOffset = (pgno==1 ? 100 : 0);51 return pPage;52}53 54/* Helper to destroy MemPage */55static void helperDestroyMemPage(MemPage *pPage){56 if( pPage ){57 sqlite3_free(pPage);58 }59}60 61void setUp(void) {62 sqlite3_initialize();63}64 65void tearDown(void) {66}67 68/* Valid: Table leaf node (0x0d) */69void test_decodeFlags_table_leaf_ok(void){70 /* Arbitrary but distinct values */71 BtShared *pBt = helperCreateBtShared(127, 900, 30, 800, 25);72 MemPage *pPage = helperCreateMemPage(pBt, 2);73 int rc = test_decodeFlags(pPage, PTF_LEAFDATA | PTF_INTKEY | PTF_LEAF); /* 0x0d */74 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);75 TEST_ASSERT_EQUAL_UINT8(1, pPage->leaf);76 TEST_ASSERT_EQUAL_UINT8(0, pPage->childPtrSize);77 TEST_ASSERT_EQUAL_UINT8(1, pPage->intKeyLeaf);78 TEST_ASSERT_EQUAL_UINT8(1, pPage->intKey);79 TEST_ASSERT_NOT_NULL(pPage->xCellSize);80 TEST_ASSERT_NOT_NULL(pPage->xParseCell);81 TEST_ASSERT_EQUAL_UINT16(pBt->maxLeaf, pPage->maxLocal);82 TEST_ASSERT_EQUAL_UINT16(pBt->minLeaf, pPage->minLocal);83 TEST_ASSERT_EQUAL_UINT8(pBt->max1bytePayload, pPage->max1bytePayload);84 helperDestroyMemPage(pPage);85 helperDestroyBtShared(pBt);86}87 88/* Valid: Index leaf node (0x0a) */89void test_decodeFlags_index_leaf_ok(void){90 BtShared *pBt = helperCreateBtShared(120, 700, 20, 600, 15);91 MemPage *pPage = helperCreateMemPage(pBt, 3);92 int rc = test_decodeFlags(pPage, PTF_ZERODATA | PTF_LEAF); /* 0x0a */93 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);94 TEST_ASSERT_EQUAL_UINT8(1, pPage->leaf);95 TEST_ASSERT_EQUAL_UINT8(0, pPage->childPtrSize);96 TEST_ASSERT_EQUAL_UINT8(0, pPage->intKeyLeaf);97 TEST_ASSERT_EQUAL_UINT8(0, pPage->intKey);98 TEST_ASSERT_NOT_NULL(pPage->xCellSize);99 TEST_ASSERT_NOT_NULL(pPage->xParseCell);100 TEST_ASSERT_EQUAL_UINT16(pBt->maxLocal, pPage->maxLocal);101 TEST_ASSERT_EQUAL_UINT16(pBt->minLocal, pPage->minLocal);102 TEST_ASSERT_EQUAL_UINT8(pBt->max1bytePayload, pPage->max1bytePayload);103 helperDestroyMemPage(pPage);104 helperDestroyBtShared(pBt);105}106 107/* Valid: Index internal node (0x02) */108void test_decodeFlags_index_internal_ok(void){109 BtShared *pBt = helperCreateBtShared(100, 500, 18, 450, 12);110 MemPage *pPage = helperCreateMemPage(pBt, 4);111 int rc = test_decodeFlags(pPage, PTF_ZERODATA); /* 0x02 */112 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);113 TEST_ASSERT_EQUAL_UINT8(0, pPage->leaf);114 TEST_ASSERT_EQUAL_UINT8(4, pPage->childPtrSize);115 TEST_ASSERT_EQUAL_UINT8(0, pPage->intKeyLeaf);116 TEST_ASSERT_EQUAL_UINT8(0, pPage->intKey);117 TEST_ASSERT_NOT_NULL(pPage->xCellSize);118 TEST_ASSERT_NOT_NULL(pPage->xParseCell);119 TEST_ASSERT_EQUAL_UINT16(pBt->maxLocal, pPage->maxLocal);120 TEST_ASSERT_EQUAL_UINT16(pBt->minLocal, pPage->minLocal);121 TEST_ASSERT_EQUAL_UINT8(pBt->max1bytePayload, pPage->max1bytePayload);122 helperDestroyMemPage(pPage);123 helperDestroyBtShared(pBt);124}125 126/* Valid: Table internal node (0x05) */127void test_decodeFlags_table_internal_ok(void){128 BtShared *pBt = helperCreateBtShared(110, 550, 22, 480, 14);129 MemPage *pPage = helperCreateMemPage(pBt, 5);130 int rc = test_decodeFlags(pPage, PTF_LEAFDATA | PTF_INTKEY); /* 0x05 */131 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);132 TEST_ASSERT_EQUAL_UINT8(0, pPage->leaf);133 TEST_ASSERT_EQUAL_UINT8(4, pPage->childPtrSize);134 TEST_ASSERT_EQUAL_UINT8(0, pPage->intKeyLeaf);135 TEST_ASSERT_EQUAL_UINT8(1, pPage->intKey);136 TEST_ASSERT_NOT_NULL(pPage->xCellSize);137 TEST_ASSERT_NOT_NULL(pPage->xParseCell);138 TEST_ASSERT_EQUAL_UINT16(pBt->maxLeaf, pPage->maxLocal);139 TEST_ASSERT_EQUAL_UINT16(pBt->minLeaf, pPage->minLocal);140 TEST_ASSERT_EQUAL_UINT8(pBt->max1bytePayload, pPage->max1bytePayload);141 helperDestroyMemPage(pPage);142 helperDestroyBtShared(pBt);143}144 145/* Invalid: leaf missing INTKEY (0x09) should return corruption */146void test_decodeFlags_invalid_leaf_combination(void){147 BtShared *pBt = helperCreateBtShared(90, 300, 10, 280, 8);148 MemPage *pPage = helperCreateMemPage(pBt, 6);149 int rc = test_decodeFlags(pPage, PTF_LEAFDATA | PTF_LEAF); /* 0x09 */150 TEST_ASSERT_NOT_EQUAL(SQLITE_OK, rc);151 /* Fields set prior to returning error: leaf branch assigns leaf=1, childPtrSize=0,152 and sets index-leaf parsing funcs and maxLocal/minLocal. */153 TEST_ASSERT_EQUAL_UINT8(1, pPage->leaf);154 TEST_ASSERT_EQUAL_UINT8(0, pPage->childPtrSize);155 TEST_ASSERT_EQUAL_UINT16(pBt->maxLocal, pPage->maxLocal);156 TEST_ASSERT_EQUAL_UINT16(pBt->minLocal, pPage->minLocal);157 helperDestroyMemPage(pPage);158 helperDestroyBtShared(pBt);159}160 161/* Invalid: interior page with PTF_LEAF only (0x08) should return corruption */162void test_decodeFlags_invalid_interior_combination(void){163 BtShared *pBt = helperCreateBtShared(80, 260, 9, 200, 7);164 MemPage *pPage = helperCreateMemPage(pBt, 7);165 int rc = test_decodeFlags(pPage, PTF_LEAF); /* 0x08 */166 TEST_ASSERT_NOT_EQUAL(SQLITE_OK, rc);167 /* Non-leaf branch sets childPtrSize=4 and leaf=0 before returning error */168 TEST_ASSERT_EQUAL_UINT8(0, pPage->leaf);169 TEST_ASSERT_EQUAL_UINT8(4, pPage->childPtrSize);170 TEST_ASSERT_EQUAL_UINT16(pBt->maxLocal, pPage->maxLocal);171 TEST_ASSERT_EQUAL_UINT16(pBt->minLocal, pPage->minLocal);172 helperDestroyMemPage(pPage);173 helperDestroyBtShared(pBt);174}175 176/* Ensure the hdrOffset assertion is satisfied for pgno==1 paths too */177void test_decodeFlags_pgno1_hdrOffset_100_ok(void){178 BtShared *pBt = helperCreateBtShared(127, 900, 30, 800, 25);179 MemPage *pPage = helperCreateMemPage(pBt, 1);180 /* hdrOffset should be 100 already per helper */181 TEST_ASSERT_EQUAL_INT(100, pPage->hdrOffset);182 int rc = test_decodeFlags(pPage, PTF_ZERODATA); /* 0x02 */183 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);184 helperDestroyMemPage(pPage);185 helperDestroyBtShared(pBt);186}187 188int main(void) {189 UNITY_BEGIN();190 RUN_TEST(test_decodeFlags_table_leaf_ok);191 RUN_TEST(test_decodeFlags_index_leaf_ok);192 RUN_TEST(test_decodeFlags_index_internal_ok);193 RUN_TEST(test_decodeFlags_table_internal_ok);194 RUN_TEST(test_decodeFlags_invalid_leaf_combination);195 RUN_TEST(test_decodeFlags_invalid_interior_combination);196 RUN_TEST(test_decodeFlags_pgno1_hdrOffset_100_ok);197 return UNITY_END();198}