AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3 4#include <stdlib.h>5#include <string.h>6 7/* Global counters for test extensions */8static int g_extA_calls = 0;9static int g_extB_calls = 0;10 11/* Test extension initializer functions.12 These match the sqlite3_loadext_entry signature and can be cast13 to void(*)(void) when registering/canceling with the API. */14static int test_extA_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi){15 (void)db;16 (void)pzErrMsg;17 (void)pApi;18 g_extA_calls++;19 return SQLITE_OK;20}21 22static int test_extB_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi){23 (void)db;24 (void)pzErrMsg;25 (void)pApi;26 g_extB_calls++;27 return SQLITE_OK;28}29 30void setUp(void) {31 /* Ensure SQLite is initialized and auto-ext list is empty for each test */32 sqlite3_initialize();33 sqlite3_reset_auto_extension();34 g_extA_calls = 0;35 g_extB_calls = 0;36}37 38void tearDown(void) {39 /* Clean up any registrations that might have been added during the test */40 sqlite3_reset_auto_extension();41}42 43/* Test that sqlite3_reset_auto_extension removes all registered entries */44void test_sqlite3_reset_auto_extension_removes_registered_entries(void) {45 int rc;46 47 rc = sqlite3_auto_extension((void(*)(void))test_extA_init);48 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);49 rc = sqlite3_auto_extension((void(*)(void))test_extB_init);50 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);51 52 /* Reset should clear both entries */53 sqlite3_reset_auto_extension();54 55 /* Now canceling either should return 0 (not found) */56 int removedA = sqlite3_cancel_auto_extension((void(*)(void))test_extA_init);57 int removedB = sqlite3_cancel_auto_extension((void(*)(void))test_extB_init);58 TEST_ASSERT_EQUAL_INT(0, removedA);59 TEST_ASSERT_EQUAL_INT(0, removedB);60}61 62/* Test that after reset, automatic extensions are not invoked */63void test_sqlite3_reset_prevents_future_auto_loads(void) {64 int rc;65 sqlite3 *db1 = NULL;66 sqlite3 *db2 = NULL;67 68 /* Register extension A and force a load on a connection */69 rc = sqlite3_auto_extension((void(*)(void))test_extA_init);70 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);71 72 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db1));73 /* Explicitly trigger auto-loading to observe calls deterministically */74 sqlite3AutoLoadExtensions(db1);75 int calls_after_first = g_extA_calls;76 /* Sanity: at least zero, but we don't assert a specific count here */77 78 sqlite3_close(db1);79 db1 = NULL;80 81 /* Reset and verify that no further calls happen on new connections */82 sqlite3_reset_auto_extension();83 84 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db2));85 sqlite3AutoLoadExtensions(db2);86 int calls_after_second = g_extA_calls;87 88 /* After reset, the list is empty, so explicit load should not increase calls */89 TEST_ASSERT_EQUAL_INT(calls_after_first, calls_after_second);90 91 sqlite3_close(db2);92 db2 = NULL;93}94 95/* Test that reset is idempotent and safe when list is empty or non-empty */96void test_sqlite3_reset_is_idempotent(void) {97 int rc;98 99 /* Call reset twice on an empty list */100 sqlite3_reset_auto_extension();101 sqlite3_reset_auto_extension();102 103 /* Register something, then reset twice again */104 rc = sqlite3_auto_extension((void(*)(void))test_extB_init);105 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);106 107 sqlite3_reset_auto_extension();108 sqlite3_reset_auto_extension();109 110 /* Cancel should report not found */111 int removedB = sqlite3_cancel_auto_extension((void(*)(void))test_extB_init);112 TEST_ASSERT_EQUAL_INT(0, removedB);113}114 115/* Test that after shutdown, calling reset still leaves system sane */116void test_sqlite3_reset_after_shutdown(void) {117 int rc;118 119 /* Force a full shutdown */120 sqlite3_shutdown();121 122 /* Now call reset before explicit re-initialize */123 sqlite3_reset_auto_extension();124 125 /* Should still be able to register/unregister extensions */126 rc = sqlite3_auto_extension((void(*)(void))test_extA_init);127 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);128 129 int removedA = sqlite3_cancel_auto_extension((void(*)(void))test_extA_init);130 TEST_ASSERT_EQUAL_INT(1, removedA);131 132 /* Final cleanup */133 sqlite3_reset_auto_extension();134}135 136int main(void) {137 UNITY_BEGIN();138 139 RUN_TEST(test_sqlite3_reset_auto_extension_removes_registered_entries);140 RUN_TEST(test_sqlite3_reset_prevents_future_auto_loads);141 RUN_TEST(test_sqlite3_reset_is_idempotent);142 RUN_TEST(test_sqlite3_reset_after_shutdown);143 144 return UNITY_END();145}