AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Test stub extension init functions and state */7static int ext1_calls = 0;8static int ext2_calls = 0;9static int ext1_should_fail = 0;10static int ext2_should_fail = 0;11static int ext1_fail_rc = SQLITE_ERROR;12static int ext2_fail_rc = SQLITE_ERROR;13static int ext1_set_errmsg = 1;14static int ext2_set_errmsg = 1;15static const sqlite3_api_routines *ext1_last_pThunk = NULL;16static const sqlite3_api_routines *ext2_last_pThunk = NULL;17static sqlite3 *ext1_last_db = NULL;18static sqlite3 *ext2_last_db = NULL;19 20/* sqlite3_loadext_entry signature */21static int test_ext1(sqlite3 *db, char **pzErr, const sqlite3_api_routines *pThunk){22 ext1_calls++;23 ext1_last_db = db;24 ext1_last_pThunk = pThunk;25 if( ext1_should_fail ){26 if( pzErr && ext1_set_errmsg ){27 *pzErr = sqlite3_mprintf("ext1-failure");28 }29 return ext1_fail_rc;30 }31 return SQLITE_OK;32}33static int test_ext2(sqlite3 *db, char **pzErr, const sqlite3_api_routines *pThunk){34 ext2_calls++;35 ext2_last_db = db;36 ext2_last_pThunk = pThunk;37 if( ext2_should_fail ){38 if( pzErr && ext2_set_errmsg ){39 *pzErr = sqlite3_mprintf("ext2-failure");40 }41 return ext2_fail_rc;42 }43 return SQLITE_OK;44}45 46/* Unity fixtures */47void setUp(void) {48 /* Reset global auto-extension list and our local counters/flags */49 sqlite3_reset_auto_extension();50 ext1_calls = ext2_calls = 0;51 ext1_should_fail = ext2_should_fail = 0;52 ext1_fail_rc = ext2_fail_rc = SQLITE_ERROR;53 ext1_set_errmsg = ext2_set_errmsg = 1;54 ext1_last_pThunk = ext2_last_pThunk = NULL;55 ext1_last_db = ext2_last_db = NULL;56}57void tearDown(void) {58 sqlite3_reset_auto_extension();59}60 61/* Helper: open/close an in-memory database, returning db through out param */62static sqlite3* open_memory_db(void){63 sqlite3 *db = NULL;64 int rc = sqlite3_open(":memory:", &db);65 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);66 TEST_ASSERT_NOT_NULL(db);67 return db;68}69static void close_db(sqlite3 *db){70 if( db ){71 int rc = sqlite3_close(db);72 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);73 }74}75 76/* Tests */77 78void test_sqlite3AutoLoadExtensions_no_extensions_returns_immediately(void){79 sqlite3 *db = open_memory_db();80 81 /* No auto-extensions registered */82 sqlite3AutoLoadExtensions(db);83 84 /* No error set; counters unchanged */85 TEST_ASSERT_EQUAL_INT(0, ext1_calls);86 TEST_ASSERT_EQUAL_INT(0, ext2_calls);87 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_errcode(db));88 89 close_db(db);90}91 92void test_sqlite3AutoLoadExtensions_calls_single_extension(void){93 /* Register ext1 */94 int rc = sqlite3_auto_extension((void(*)(void))test_ext1);95 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);96 97 sqlite3 *db = open_memory_db();98 99 sqlite3AutoLoadExtensions(db);100 101 TEST_ASSERT_EQUAL_INT(1, ext1_calls);102 TEST_ASSERT_EQUAL_PTR(db, ext1_last_db);103 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_errcode(db));104 105 close_db(db);106}107 108void test_sqlite3AutoLoadExtensions_calls_multiple_extensions(void){109 int rc;110 rc = sqlite3_auto_extension((void(*)(void))test_ext1);111 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);112 rc = sqlite3_auto_extension((void(*)(void))test_ext2);113 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);114 115 sqlite3 *db = open_memory_db();116 117 sqlite3AutoLoadExtensions(db);118 119 TEST_ASSERT_EQUAL_INT(1, ext1_calls);120 TEST_ASSERT_EQUAL_INT(1, ext2_calls);121 TEST_ASSERT_EQUAL_PTR(db, ext1_last_db);122 TEST_ASSERT_EQUAL_PTR(db, ext2_last_db);123 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_errcode(db));124 125 close_db(db);126}127 128void test_sqlite3AutoLoadExtensions_duplicate_registration_only_calls_once(void){129 int rc;130 rc = sqlite3_auto_extension((void(*)(void))test_ext1);131 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);132 /* Attempt to add duplicate */133 rc = sqlite3_auto_extension((void(*)(void))test_ext1);134 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);135 136 sqlite3 *db = open_memory_db();137 138 sqlite3AutoLoadExtensions(db);139 140 TEST_ASSERT_EQUAL_INT(1, ext1_calls);141 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_errcode(db));142 143 close_db(db);144}145 146void test_sqlite3AutoLoadExtensions_cancel_extension(void){147 int rc;148 rc = sqlite3_auto_extension((void(*)(void))test_ext1);149 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);150 151 /* Cancel should return 1 as it was present */152 int removed = sqlite3_cancel_auto_extension((void(*)(void))test_ext1);153 TEST_ASSERT_EQUAL_INT(1, removed);154 /* Second cancel returns 0 */155 removed = sqlite3_cancel_auto_extension((void(*)(void))test_ext1);156 TEST_ASSERT_EQUAL_INT(0, removed);157 158 sqlite3 *db = open_memory_db();159 160 sqlite3AutoLoadExtensions(db);161 162 TEST_ASSERT_EQUAL_INT(0, ext1_calls);163 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_errcode(db));164 165 close_db(db);166}167 168void test_sqlite3AutoLoadExtensions_error_stops_and_sets_error(void){169 int rc;170 rc = sqlite3_auto_extension((void(*)(void))test_ext1);171 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);172 rc = sqlite3_auto_extension((void(*)(void))test_ext2);173 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);174 175 /* Configure ext1 to fail with an error message */176 ext1_should_fail = 1;177 ext1_fail_rc = SQLITE_ERROR;178 ext1_set_errmsg = 1;179 180 sqlite3 *db = open_memory_db();181 182 sqlite3AutoLoadExtensions(db);183 184 /* ext1 called once and failed; ext2 not called */185 TEST_ASSERT_EQUAL_INT(1, ext1_calls);186 TEST_ASSERT_EQUAL_INT(0, ext2_calls);187 188 /* Connection error set to ext1_fail_rc with message including our text */189 TEST_ASSERT_EQUAL_INT(ext1_fail_rc, sqlite3_errcode(db));190 const char *zErr = sqlite3_errmsg(db);191 TEST_ASSERT_NOT_NULL(zErr);192 TEST_ASSERT_NOT_NULL(strstr(zErr, "automatic extension loading failed"));193 TEST_ASSERT_NOT_NULL(strstr(zErr, "ext1-failure"));194 195 close_db(db);196}197 198void test_sqlite3AutoLoadExtensions_error_without_message(void){199 int rc;200 rc = sqlite3_auto_extension((void(*)(void))test_ext1);201 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);202 /* ext1 fails but does not provide an error message */203 ext1_should_fail = 1;204 ext1_fail_rc = SQLITE_ERROR;205 ext1_set_errmsg = 0;206 207 sqlite3 *db = open_memory_db();208 209 sqlite3AutoLoadExtensions(db);210 211 TEST_ASSERT_EQUAL_INT(1, ext1_calls);212 TEST_ASSERT_EQUAL_INT(ext1_fail_rc, sqlite3_errcode(db));213 const char *zErr = sqlite3_errmsg(db);214 TEST_ASSERT_NOT_NULL(zErr);215 /* Ensure the generic failure prefix is present */216 TEST_ASSERT_NOT_NULL(strstr(zErr, "automatic extension loading failed"));217 218 close_db(db);219}220 221int main(void) {222 UNITY_BEGIN();223 224 RUN_TEST(test_sqlite3AutoLoadExtensions_no_extensions_returns_immediately);225 RUN_TEST(test_sqlite3AutoLoadExtensions_calls_single_extension);226 RUN_TEST(test_sqlite3AutoLoadExtensions_calls_multiple_extensions);227 RUN_TEST(test_sqlite3AutoLoadExtensions_duplicate_registration_only_calls_once);228 RUN_TEST(test_sqlite3AutoLoadExtensions_cancel_extension);229 RUN_TEST(test_sqlite3AutoLoadExtensions_error_stops_and_sets_error);230 RUN_TEST(test_sqlite3AutoLoadExtensions_error_without_message);231 232 return UNITY_END();233}