AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5#include <stdint.h>6 7/* Local helper to compute the same page hash as pager_datahash */8static u32 test_datahash(int nByte, const unsigned char *pData){9 u32 hash = 0;10 for(int i = 0; i < nByte; i++){11 hash = (hash * 1039) + pData[i];12 }13 return hash;14}15 16/* Create a deterministic data buffer of given size */17static void fill_buffer(unsigned char *p, int n){18 for(int i = 0; i < n; i++){19 p[i] = (unsigned char)(i & 0xFF);20 }21}22 23/* Minimal pager/file objects to satisfy PAGERTRACE/PAGERID access safely */24static sqlite3_file gDummyFile; /* Its pMethods may be NULL, which is fine */25static Pager make_pager(int pageSize, int tempFile, int nSavepoint){26 Pager p;27 memset(&p, 0, sizeof(p));28 p.pageSize = (u32)pageSize;29 p.tempFile = (u8)tempFile;30 p.nSavepoint = nSavepoint;31 p.fd = &gDummyFile; /* ensure non-NULL to satisfy PAGERID macro dereference of fd */32 return p;33}34 35/* Unity fixtures */36void setUp(void) {37 memset(&gDummyFile, 0, sizeof(gDummyFile));38}39void tearDown(void) {40 /* No dynamic global resources */41}42 43/* Test 1: Happy path — non-temp, dirty, no savepoint: flags updated and pageHash set */44void test_sqlite3PagerDontWrite_basic_updates_flags_and_hash(void){45 const int pageSize = 1024;46 unsigned char *buf = (unsigned char*)sqlite3_malloc(pageSize);47 TEST_ASSERT_NOT_NULL(buf);48 fill_buffer(buf, pageSize);49 50 Pager pager = make_pager(pageSize, 0, 0);51 52 PgHdr pg;53 memset(&pg, 0, sizeof(pg));54 pg.pPager = &pager;55 pg.pgno = 5;56 pg.pData = buf;57 pg.flags = PGHDR_DIRTY | PGHDR_WRITEABLE | PGHDR_NEED_SYNC; /* Include NEED_SYNC to ensure it persists */58 pg.pageHash = 0xDEADBEEF;59 60 u32 expectedHash = test_datahash(pageSize, buf);61 62 sqlite3PagerDontWrite(&pg);63 64 /* Flags: DONT_WRITE set, WRITEABLE cleared, DIRTY and NEED_SYNC preserved */65 TEST_ASSERT_TRUE((pg.flags & PGHDR_DONT_WRITE) != 0);66 TEST_ASSERT_TRUE((pg.flags & PGHDR_WRITEABLE) == 0);67 TEST_ASSERT_TRUE((pg.flags & PGHDR_DIRTY) != 0);68 TEST_ASSERT_TRUE((pg.flags & PGHDR_NEED_SYNC) != 0);69 70 /* Hash updated */71 TEST_ASSERT_EQUAL_UINT32(expectedHash, pg.pageHash);72 73 sqlite3_free(buf);74}75 76/* Test 2: tempFile true — no changes should occur */77void test_sqlite3PagerDontWrite_noop_when_tempfile(void){78 const int pageSize = 512;79 unsigned char *buf = (unsigned char*)sqlite3_malloc(pageSize);80 TEST_ASSERT_NOT_NULL(buf);81 fill_buffer(buf, pageSize);82 83 Pager pager = make_pager(pageSize, 1, 0); /* tempFile = 1 */84 85 PgHdr pg;86 memset(&pg, 0, sizeof(pg));87 pg.pPager = &pager;88 pg.pgno = 17;89 pg.pData = buf;90 pg.flags = PGHDR_DIRTY | PGHDR_WRITEABLE;91 pg.pageHash = 123456789u;92 93 sqlite3PagerDontWrite(&pg);94 95 /* No changes expected */96 TEST_ASSERT_TRUE((pg.flags & PGHDR_DONT_WRITE) == 0);97 TEST_ASSERT_TRUE((pg.flags & PGHDR_WRITEABLE) != 0);98 TEST_ASSERT_TRUE((pg.flags & PGHDR_DIRTY) != 0);99 TEST_ASSERT_EQUAL_UINT32(123456789u, pg.pageHash);100 101 sqlite3_free(buf);102}103 104/* Test 3: nSavepoint > 0 — no changes should occur */105void test_sqlite3PagerDontWrite_noop_when_savepoint_active(void){106 const int pageSize = 2048;107 unsigned char *buf = (unsigned char*)sqlite3_malloc(pageSize);108 TEST_ASSERT_NOT_NULL(buf);109 fill_buffer(buf, pageSize);110 111 Pager pager = make_pager(pageSize, 0, 2); /* nSavepoint = 2 */112 113 PgHdr pg;114 memset(&pg, 0, sizeof(pg));115 pg.pPager = &pager;116 pg.pgno = 42;117 pg.pData = buf;118 pg.flags = PGHDR_DIRTY | PGHDR_WRITEABLE;119 pg.pageHash = 0xABCDEF01u;120 121 sqlite3PagerDontWrite(&pg);122 123 /* No changes expected */124 TEST_ASSERT_TRUE((pg.flags & PGHDR_DONT_WRITE) == 0);125 TEST_ASSERT_TRUE((pg.flags & PGHDR_WRITEABLE) != 0);126 TEST_ASSERT_TRUE((pg.flags & PGHDR_DIRTY) != 0);127 TEST_ASSERT_EQUAL_UINT32(0xABCDEF01u, pg.pageHash);128 129 sqlite3_free(buf);130}131 132/* Test 4: Not dirty — no changes should occur */133void test_sqlite3PagerDontWrite_noop_when_not_dirty(void){134 const int pageSize = 1024;135 unsigned char *buf = (unsigned char*)sqlite3_malloc(pageSize);136 TEST_ASSERT_NOT_NULL(buf);137 fill_buffer(buf, pageSize);138 139 Pager pager = make_pager(pageSize, 0, 0); /* eligible, but page not dirty */140 141 PgHdr pg;142 memset(&pg, 0, sizeof(pg));143 pg.pPager = &pager;144 pg.pgno = 3;145 pg.pData = buf;146 pg.flags = PGHDR_WRITEABLE; /* Not dirty */147 pg.pageHash = 0x22222222u;148 149 sqlite3PagerDontWrite(&pg);150 151 /* No changes expected */152 TEST_ASSERT_TRUE((pg.flags & PGHDR_DONT_WRITE) == 0);153 TEST_ASSERT_TRUE((pg.flags & PGHDR_WRITEABLE) != 0);154 TEST_ASSERT_TRUE((pg.flags & PGHDR_DIRTY) == 0);155 TEST_ASSERT_EQUAL_UINT32(0x22222222u, pg.pageHash);156 157 sqlite3_free(buf);158}159 160/* Test 5: If already not writeable, still sets DONT_WRITE and preserves other flags */161void test_sqlite3PagerDontWrite_sets_dont_write_even_if_not_writeable(void){162 const int pageSize = 4096;163 unsigned char *buf = (unsigned char*)sqlite3_malloc(pageSize);164 TEST_ASSERT_NOT_NULL(buf);165 fill_buffer(buf, pageSize);166 167 Pager pager = make_pager(pageSize, 0, 0);168 169 PgHdr pg;170 memset(&pg, 0, sizeof(pg));171 pg.pPager = &pager;172 pg.pgno = 9;173 pg.pData = buf;174 pg.flags = PGHDR_DIRTY; /* Not writeable initially */175 pg.pageHash = 0;176 177 u32 expectedHash = test_datahash(pageSize, buf);178 179 sqlite3PagerDontWrite(&pg);180 181 TEST_ASSERT_TRUE((pg.flags & PGHDR_DONT_WRITE) != 0);182 TEST_ASSERT_TRUE((pg.flags & PGHDR_WRITEABLE) == 0);183 TEST_ASSERT_TRUE((pg.flags & PGHDR_DIRTY) != 0);184 TEST_ASSERT_EQUAL_UINT32(expectedHash, pg.pageHash);185 186 sqlite3_free(buf);187}188 189int main(void){190 UNITY_BEGIN();191 RUN_TEST(test_sqlite3PagerDontWrite_basic_updates_flags_and_hash);192 RUN_TEST(test_sqlite3PagerDontWrite_noop_when_tempfile);193 RUN_TEST(test_sqlite3PagerDontWrite_noop_when_savepoint_active);194 RUN_TEST(test_sqlite3PagerDontWrite_noop_when_not_dirty);195 RUN_TEST(test_sqlite3PagerDontWrite_sets_dont_write_even_if_not_writeable);196 return UNITY_END();197}