AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <stdint.h>5#include <string.h>6 7static void reinit_with_memstatus(int enable){8 /* Ensure clean state and configure memory status before initialization */9 sqlite3_shutdown();10 int rc = sqlite3_config(SQLITE_CONFIG_MEMSTATUS, enable);11 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_config(SQLITE_CONFIG_MEMSTATUS) failed");12 rc = sqlite3_initialize();13 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_initialize() failed");14}15 16static sqlite3_int64 memused(void){17 return sqlite3_memory_used();18}19 20void setUp(void) {21 /* Default all tests to memstatus enabled and a fresh memory subsystem. */22 reinit_with_memstatus(1);23}24 25void tearDown(void) {26 /* Clean up memory subsystem after each test */27 sqlite3_shutdown();28}29 30/* Helper to allocate a heap block with proper MEMTYPE_HEAP tagging. */31static void* heap_alloc_tagged(u64 n){32 /* Using sqlite3DbMallocRaw with db==NULL ensures MEMTYPE_HEAP tag for debug builds */33 void *p = sqlite3DbMallocRaw(0, n);34 return p;35}36 37/* Test 1: sqlite3_free(NULL) is a no-op and does not change memory accounting */38void test_sqlite3_free_null_noop(void){39 sqlite3_int64 m0 = memused();40 sqlite3_free(NULL);41 sqlite3_int64 m1 = memused();42 TEST_ASSERT_TRUE(m0 == m1);43}44 45/* Test 2: Single allocation then free should increase and then restore memory_used */46void test_sqlite3_free_releases_single_allocation(void){47 const u64 req = 12345;48 sqlite3_int64 m0 = memused();49 50 void *p = heap_alloc_tagged(req);51 TEST_ASSERT_NOT_NULL(p);52 53 sqlite3_uint64 sz = sqlite3_msize(p);54 TEST_ASSERT_TRUE(sz >= req); /* allocator may round up, but sqlite3_msize reports actual */55 56 sqlite3_int64 m1 = memused();57 TEST_ASSERT_TRUE(m1 - m0 == (sqlite3_int64)sz);58 59 sqlite3_free(p);60 61 sqlite3_int64 m2 = memused();62 TEST_ASSERT_TRUE(m2 == m0);63}64 65/* Test 3: Two allocations, free in parts tracks memory_used accordingly */66void test_sqlite3_free_releases_multiple_allocations_in_parts(void){67 const u64 a = 4096;68 const u64 b = 7777;69 70 sqlite3_int64 m0 = memused();71 72 void *p1 = heap_alloc_tagged(a);73 TEST_ASSERT_NOT_NULL(p1);74 sqlite3_uint64 s1 = sqlite3_msize(p1);75 76 void *p2 = heap_alloc_tagged(b);77 TEST_ASSERT_NOT_NULL(p2);78 sqlite3_uint64 s2 = sqlite3_msize(p2);79 80 sqlite3_int64 m1 = memused();81 TEST_ASSERT_TRUE(m1 - m0 == (sqlite3_int64)(s1 + s2));82 83 /* Free first allocation */84 sqlite3_free(p1);85 sqlite3_int64 m2 = memused();86 TEST_ASSERT_TRUE(m2 - m0 == (sqlite3_int64)s2);87 88 /* Free second allocation */89 sqlite3_free(p2);90 sqlite3_int64 m3 = memused();91 TEST_ASSERT_TRUE(m3 == m0);92}93 94/* Test 4: With memstatus disabled, sqlite3_free still works (no crash, counters unchanged) */95void test_sqlite3_free_with_memstatus_disabled(void){96 reinit_with_memstatus(0);97 98 sqlite3_int64 m0 = memused(); /* Likely 0 when memstatus is disabled */99 void *p = heap_alloc_tagged(5000);100 TEST_ASSERT_NOT_NULL(p);101 102 /* Not asserting on memused delta because memstatus is disabled. */103 sqlite3_free(p);104 105 sqlite3_int64 m1 = memused();106 TEST_ASSERT_TRUE(m0 == m1); /* Should remain unchanged when memstatus disabled */107}108 109/* Test 5: Stress test with many allocations, verify accounting sum */110void test_sqlite3_free_stress_many_allocations(void){111 enum { N = 50 };112 void *ptrs[N] = {0};113 sqlite3_uint64 sizes[N] = {0};114 115 sqlite3_int64 m0 = memused();116 117 for(int i=0; i<N; i++){118 u64 req = 64 + (u64)(i*37 % 3000); /* vary requested size */119 ptrs[i] = heap_alloc_tagged(req);120 TEST_ASSERT_NOT_NULL(ptrs[i]);121 sizes[i] = sqlite3_msize(ptrs[i]);122 TEST_ASSERT_TRUE(sizes[i] >= req);123 }124 125 sqlite3_uint64 sum = 0;126 for(int i=0; i<N; i++){127 sum += sizes[i];128 }129 130 sqlite3_int64 m1 = memused();131 TEST_ASSERT_TRUE(m1 - m0 == (sqlite3_int64)sum);132 133 /* Free them all */134 for(int i=0; i<N; i++){135 sqlite3_free(ptrs[i]);136 }137 138 sqlite3_int64 m2 = memused();139 TEST_ASSERT_TRUE(m2 == m0);140}141 142int main(void) {143 UNITY_BEGIN();144 RUN_TEST(test_sqlite3_free_null_noop);145 RUN_TEST(test_sqlite3_free_releases_single_allocation);146 RUN_TEST(test_sqlite3_free_releases_multiple_allocations_in_parts);147 RUN_TEST(test_sqlite3_free_with_memstatus_disabled);148 RUN_TEST(test_sqlite3_free_stress_many_allocations);149 return UNITY_END();150}