AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS7/* Externs for the functions under test and helpers in mutex.c */8extern const sqlite3_mutex_methods *multiThreadedCheckMutex(void);9extern void test_checkMutexFree(sqlite3_mutex *p);10#endif11 12static const sqlite3_mutex_methods *gMethods = NULL;13 14void setUp(void) {15#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS16 /* Ensure SQLite core is initialized so memory allocators, etc. are ready. */17 int rc = sqlite3_initialize();18 (void)rc; /* ignore return here; Unity assertions below */19 TEST_ASSERT_TRUE_MESSAGE(rc==SQLITE_OK || rc==SQLITE_MISUSE, "sqlite3_initialize failed");20 21 gMethods = multiThreadedCheckMutex();22 TEST_ASSERT_NOT_NULL(gMethods);23 TEST_ASSERT_NOT_NULL(gMethods->xMutexInit);24 TEST_ASSERT_NOT_NULL(gMethods->xMutexAlloc);25 TEST_ASSERT_NOT_NULL(gMethods->xMutexEnter);26 TEST_ASSERT_NOT_NULL(gMethods->xMutexLeave);27 TEST_ASSERT_NOT_NULL(gMethods->xMutexFree);28 29 /* Initialize the multithreaded-check mutex wrapper implementation */30 TEST_ASSERT_EQUAL_INT(SQLITE_OK, gMethods->xMutexInit());31#else32 (void)gMethods;33#endif34}35 36void tearDown(void) {37#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS38 if (gMethods && gMethods->xMutexEnd) {39 (void)gMethods->xMutexEnd();40 }41 gMethods = NULL;42#endif43}44 45#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS46static void allocate_use_and_free_mutex(int iType){47 sqlite3_mutex *p = NULL;48 49 /* Allocate a dynamic mutex using the wrapper methods */50 p = gMethods->xMutexAlloc(iType);51 TEST_ASSERT_NOT_NULL(p);52 53 /* Basic sanity: enter/leave should work prior to free */54 gMethods->xMutexEnter(p);55 gMethods->xMutexLeave(p);56 57 /* Free via the function under test (wrapper to static checkMutexFree) */58 test_checkMutexFree(p);59}60 61void test_checkMutexFree_frees_dynamic_fast_mutex(void) {62 allocate_use_and_free_mutex(SQLITE_MUTEX_FAST);63 64 /* Ensure we can still allocate another one after freeing the previous */65 sqlite3_mutex *p2 = gMethods->xMutexAlloc(SQLITE_MUTEX_FAST);66 TEST_ASSERT_NOT_NULL(p2);67 test_checkMutexFree(p2);68}69 70void test_checkMutexFree_frees_dynamic_recursive_mutex(void) {71 sqlite3_mutex *p = gMethods->xMutexAlloc(SQLITE_MUTEX_RECURSIVE);72 TEST_ASSERT_NOT_NULL(p);73 74 /* Recursive enter/leave should work before free */75 gMethods->xMutexEnter(p);76 gMethods->xMutexEnter(p);77 gMethods->xMutexLeave(p);78 gMethods->xMutexLeave(p);79 80 test_checkMutexFree(p);81}82 83void test_checkMutexFree_many_alloc_free_cycles(void) {84 /* Stress a bit to catch potential state issues */85 for (int i = 0; i < 100; i++) {86 sqlite3_mutex *pFast = gMethods->xMutexAlloc(SQLITE_MUTEX_FAST);87 TEST_ASSERT_NOT_NULL(pFast);88 test_checkMutexFree(pFast);89 90 sqlite3_mutex *pRec = gMethods->xMutexAlloc(SQLITE_MUTEX_RECURSIVE);91 TEST_ASSERT_NOT_NULL(pRec);92 test_checkMutexFree(pRec);93 }94}95#else96/* If SQLITE_ENABLE_MULTITHREADED_CHECKS is not enabled, provide a trivial test97 so the file still compiles and runs. */98void test_checkMutexFree_noop_build_config(void) {99 TEST_PASS_MESSAGE("SQLITE_ENABLE_MULTITHREADED_CHECKS not defined; checkMutexFree not available.");100}101#endif102 103int main(void) {104 UNITY_BEGIN();105#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS106 RUN_TEST(test_checkMutexFree_frees_dynamic_fast_mutex);107 RUN_TEST(test_checkMutexFree_frees_dynamic_recursive_mutex);108 RUN_TEST(test_checkMutexFree_many_alloc_free_cycles);109#else110 RUN_TEST(test_checkMutexFree_noop_build_config);111#endif112 return UNITY_END();113}