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/* Backup of selected global configuration fields to restore in tearDown */8static sqlite3_mem_methods savedMethods;9static void *savedPPage = NULL;10static int savedSzPage = 0;11static int savedNPage = 0;12 13/* Test memory methods instrumentation */14static volatile int g_xInitCalled = 0;15static volatile int g_xInitRc = SQLITE_OK;16static void *g_lastAppData = NULL;17 18/* Simple wrapped allocator that tracks size in a header so xSize works */19typedef struct TestHdr {20 int n;21} TestHdr;22 23static void *test_xMalloc(int n){24 if( n<0 ) return NULL;25 TestHdr *h = (TestHdr*)malloc(sizeof(TestHdr) + (size_t)n);26 if( !h ) return NULL;27 h->n = n;28 return (void*)((char*)h + sizeof(TestHdr));29}30static void test_xFree(void *p){31 if( !p ) return;32 TestHdr *h = (TestHdr*)((char*)p - sizeof(TestHdr));33 free(h);34}35static void *test_xRealloc(void *p, int n){36 if( !p ) return test_xMalloc(n);37 if( n<=0 ){38 test_xFree(p);39 return NULL;40 }41 TestHdr *h = (TestHdr*)((char*)p - sizeof(TestHdr));42 h = (TestHdr*)realloc(h, sizeof(TestHdr) + (size_t)n);43 if( !h ) return NULL;44 h->n = n;45 return (void*)((char*)h + sizeof(TestHdr));46}47static int test_xSize(void *p){48 if( !p ) return 0;49 TestHdr *h = (TestHdr*)((char*)p - sizeof(TestHdr));50 return h->n;51}52static int test_xRoundup(int n){53 /* Simple identity roundup is fine for tests */54 return n;55}56static int test_xInit(void *pAppData){57 g_xInitCalled++;58 g_lastAppData = pAppData;59 return g_xInitRc;60}61static void test_xShutdown(void *pAppData){62 (void)pAppData;63}64 65/* Helper to install custom memory methods */66static void install_test_methods(void *appData){67 sqlite3_mem_methods mm;68 memset(&mm, 0, sizeof(mm));69 mm.xMalloc = test_xMalloc;70 mm.xFree = test_xFree;71 mm.xRealloc = test_xRealloc;72 mm.xSize = test_xSize;73 mm.xRoundup = test_xRoundup;74 mm.xInit = test_xInit;75 mm.xShutdown = test_xShutdown;76 mm.pAppData = appData;77 sqlite3GlobalConfig.m = mm;78}79 80/* Unity setup/teardown */81void setUp(void) {82 /* Save current configuration */83 savedMethods = sqlite3GlobalConfig.m;84 savedPPage = sqlite3GlobalConfig.pPage;85 savedSzPage = sqlite3GlobalConfig.szPage;86 savedNPage = sqlite3GlobalConfig.nPage;87 88 /* Reset internal mem0 state to a known baseline */89 sqlite3MallocEnd();90 91 /* Clear instrumentation */92 g_xInitCalled = 0;93 g_xInitRc = SQLITE_OK;94 g_lastAppData = NULL;95}96void tearDown(void) {97 /* Reset internal mem0 state */98 sqlite3MallocEnd();99 100 /* Restore configuration */101 sqlite3GlobalConfig.m = savedMethods;102 sqlite3GlobalConfig.pPage = savedPPage;103 sqlite3GlobalConfig.szPage = savedSzPage;104 sqlite3GlobalConfig.nPage = savedNPage;105 106 /* Do not force re-init here; leave environment as found */107}108 109/* Tests */110 111void test_sqlite3MallocInit_sets_default_when_xMalloc_null(void){112 /* Arrange: make xMalloc NULL to force sqlite3MemSetDefault() path */113 memset(&sqlite3GlobalConfig.m, 0, sizeof(sqlite3GlobalConfig.m));114 115 /* Provide invalid page-cache settings that should be sanitized */116 static unsigned char dummyPage[256];117 sqlite3GlobalConfig.pPage = dummyPage;118 sqlite3GlobalConfig.szPage = 256; /* < 512, invalid */119 sqlite3GlobalConfig.nPage = 10; /* > 0 */120 121 /* Act */122 int rc = sqlite3MallocInit();123 124 /* Assert */125 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);126 TEST_ASSERT_NOT_NULL(sqlite3GlobalConfig.m.xMalloc); /* default installed */127 TEST_ASSERT_NOT_NULL(sqlite3MallocMutex()); /* mem0.mutex set */128 TEST_ASSERT_NULL(sqlite3GlobalConfig.pPage); /* sanitized */129 TEST_ASSERT_EQUAL_INT(0, sqlite3GlobalConfig.szPage); /* sanitized */130}131 132void test_sqlite3MallocInit_keeps_valid_pagecache_and_calls_custom_xInit(void){133 /* Arrange: install custom methods and valid page-cache settings */134 unsigned char pagebuf[1024];135 void *appToken = (void*)0x1234abcd;136 install_test_methods(appToken);137 138 sqlite3GlobalConfig.pPage = pagebuf;139 sqlite3GlobalConfig.szPage = 512; /* valid (>=512) */140 sqlite3GlobalConfig.nPage = 1; /* valid (>0) */141 142 g_xInitRc = SQLITE_OK;143 g_xInitCalled = 0;144 g_lastAppData = NULL;145 146 /* Act */147 int rc = sqlite3MallocInit();148 149 /* Assert */150 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);151 TEST_ASSERT_EQUAL_INT(1, g_xInitCalled);152 TEST_ASSERT_EQUAL_PTR(appToken, g_lastAppData);153 TEST_ASSERT_NOT_NULL(sqlite3MallocMutex());154 TEST_ASSERT_EQUAL_PTR(pagebuf, sqlite3GlobalConfig.pPage); /* preserved */155 TEST_ASSERT_EQUAL_INT(512, sqlite3GlobalConfig.szPage); /* preserved */156}157 158void test_sqlite3MallocInit_when_xInit_fails_clears_mem0_and_returns_rc(void){159 /* Arrange: custom methods with failing xInit */160 install_test_methods((void*)0xDEADBEEF);161 g_xInitRc = SQLITE_ERROR;162 163 /* Act */164 int rc = sqlite3MallocInit();165 166 /* Assert */167 TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, rc);168 TEST_ASSERT_EQUAL_INT(1, g_xInitCalled);169 TEST_ASSERT_NULL(sqlite3MallocMutex()); /* mem0 zeroed on failure */170 TEST_ASSERT_EQUAL_INT(0, sqlite3HeapNearlyFull()); /* should be cleared */171}172 173void test_sqlite3MallocInit_sanitizes_when_pPage_null_but_sizes_set(void){174 /* Arrange: pPage==NULL should force szPage reset to 0 */175 install_test_methods((void*)0xBEEF);176 sqlite3GlobalConfig.pPage = NULL;177 sqlite3GlobalConfig.szPage = 8192;178 sqlite3GlobalConfig.nPage = 32;179 180 /* Act */181 int rc = sqlite3MallocInit();182 183 /* Assert */184 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);185 TEST_ASSERT_NULL(sqlite3GlobalConfig.pPage);186 TEST_ASSERT_EQUAL_INT(0, sqlite3GlobalConfig.szPage);187 TEST_ASSERT_NOT_NULL(sqlite3MallocMutex());188}189 190/* Unity main */191int main(void){192 UNITY_BEGIN();193 RUN_TEST(test_sqlite3MallocInit_sets_default_when_xMalloc_null);194 RUN_TEST(test_sqlite3MallocInit_keeps_valid_pagecache_and_calls_custom_xInit);195 RUN_TEST(test_sqlite3MallocInit_when_xInit_fails_clears_mem0_and_returns_rc);196 RUN_TEST(test_sqlite3MallocInit_sanitizes_when_pPage_null_but_sizes_set);197 return UNITY_END();198}