AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Prototype for the auto-generated wrapper to the static function */7void test_versionFunc(sqlite3_context *context, int NotUsed, sqlite3_value **NotUsed2);8 9/* Unity setup/teardown */10void setUp(void) {11 /* No global setup needed */12}13void tearDown(void) {14 /* No global teardown needed */15}16 17/* Helper: Register a SQL function that forwards to test_versionFunc */18static int register_call_version(sqlite3 *db, int nArg, int enc){19 /* Forwarder that passes the VM-provided context/args directly to versionFunc wrapper */20 void xFunc(sqlite3_context *ctx, int argc, sqlite3_value **argv){21 /* The underlying versionFunc ignores argc/argv; pass them anyway. */22 test_versionFunc(ctx, argc, argv);23 }24 return sqlite3_create_function_v2(db, "call_version", nArg, enc, NULL,25 xFunc, NULL, NULL, NULL);26}27 28/* Helper: Prepare, step once, and finalize a simple scalar SELECT */29static void prepare_step_finalize(sqlite3 *db, const char *zSql, sqlite3_stmt **ppStmt){30 int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, NULL);31 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_prepare_v2 failed");32 rc = sqlite3_step(*ppStmt);33 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_ROW, rc, "sqlite3_step did not return SQLITE_ROW");34}35 36/* Test 1: Basic behavior — returns sqlite3_libversion() */37void test_versionFunc_basic_returns_libversion(void){38 sqlite3 *db = NULL;39 int rc = sqlite3_open(":memory:", &db);40 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);41 42 rc = register_call_version(db, 0, SQLITE_UTF8);43 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);44 45 sqlite3_stmt *stmt = NULL;46 prepare_step_finalize(db, "SELECT call_version()", &stmt);47 48 const unsigned char *txt = sqlite3_column_text(stmt, 0);49 int tlen = sqlite3_column_bytes(stmt, 0);50 const char *libv = sqlite3_libversion();51 TEST_ASSERT_NOT_NULL(txt);52 TEST_ASSERT_EQUAL_INT((int)strlen(libv), tlen);53 TEST_ASSERT_EQUAL_STRING((const char*)libv, (const char*)txt);54 TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, sqlite3_column_type(stmt, 0));55 56 rc = sqlite3_finalize(stmt);57 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);58 rc = sqlite3_close(db);59 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);60}61 62/* Test 2: Consistency across multiple calls in the same row */63void test_versionFunc_consistent_multiple_calls(void){64 sqlite3 *db = NULL;65 int rc = sqlite3_open(":memory:", &db);66 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);67 68 rc = register_call_version(db, 0, SQLITE_UTF8);69 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);70 71 sqlite3_stmt *stmt = NULL;72 prepare_step_finalize(db, "SELECT call_version(), call_version()", &stmt);73 74 const unsigned char *t0 = sqlite3_column_text(stmt, 0);75 const unsigned char *t1 = sqlite3_column_text(stmt, 1);76 TEST_ASSERT_NOT_NULL(t0);77 TEST_ASSERT_NOT_NULL(t1);78 79 const char *libv = sqlite3_libversion();80 TEST_ASSERT_EQUAL_STRING((const char*)libv, (const char*)t0);81 TEST_ASSERT_EQUAL_STRING((const char*)libv, (const char*)t1);82 83 rc = sqlite3_finalize(stmt);84 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);85 rc = sqlite3_close(db);86 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);87}88 89/* Test 3: Function ignores arguments when present */90void test_versionFunc_ignores_arguments_when_present(void){91 sqlite3 *db = NULL;92 int rc = sqlite3_open(":memory:", &db);93 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);94 95 /* Register variadic so we can call it with arbitrary arguments */96 rc = register_call_version(db, -1, SQLITE_UTF8);97 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);98 99 sqlite3_stmt *stmt = NULL;100 prepare_step_finalize(db, "SELECT call_version(1, 'x', 3.14)", &stmt);101 102 const unsigned char *txt = sqlite3_column_text(stmt, 0);103 TEST_ASSERT_NOT_NULL(txt);104 TEST_ASSERT_EQUAL_STRING(sqlite3_libversion(), (const char*)txt);105 106 rc = sqlite3_finalize(stmt);107 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);108 rc = sqlite3_close(db);109 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);110}111 112/* Test 4: Registration with UTF-16 encoding still yields the same value */113void test_versionFunc_registration_utf16(void){114 sqlite3 *db = NULL;115 int rc = sqlite3_open(":memory:", &db);116 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);117 118 /* Register in UTF-16LE; engine will handle any conversions */119 rc = register_call_version(db, 0, SQLITE_UTF16LE);120 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);121 122 sqlite3_stmt *stmt = NULL;123 prepare_step_finalize(db, "SELECT call_version()", &stmt);124 125 const unsigned char *txt = sqlite3_column_text(stmt, 0); /* Retrieve as UTF-8 */126 TEST_ASSERT_NOT_NULL(txt);127 TEST_ASSERT_EQUAL_STRING(sqlite3_libversion(), (const char*)txt);128 129 rc = sqlite3_finalize(stmt);130 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);131 rc = sqlite3_close(db);132 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);133}134 135/* Main runner */136int main(void){137 UNITY_BEGIN();138 RUN_TEST(test_versionFunc_basic_returns_libversion);139 RUN_TEST(test_versionFunc_consistent_multiple_calls);140 RUN_TEST(test_versionFunc_ignores_arguments_when_present);141 RUN_TEST(test_versionFunc_registration_utf16);142 return UNITY_END();143}