AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdio.h>5 6/* Wrapper provided in the module for the static function */7void test_jsonReturnTextJsonFromBlob(sqlite3_context *ctx, const u8 *aBlob, u32 nBlob);8 9/* Global database handle for tests */10static sqlite3 *gDb = NULL;11 12/* Our SQL function that bridges to the target function */13static void from_jsonb_func(sqlite3_context *ctx, int argc, sqlite3_value **argv){14 (void)argc;15 const void *pBlob = sqlite3_value_blob(argv[0]);16 int nBlob = sqlite3_value_bytes(argv[0]);17 test_jsonReturnTextJsonFromBlob(ctx, (const u8*)pBlob, (u32)nBlob);18}19 20/* Helper: register the SQL function that calls the target */21static void register_from_jsonb(sqlite3 *db){22 /* user data is 0; jsonReturnString will return text (not blob) */23 int rc = sqlite3_create_function_v2(24 db, "from_jsonb", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC,25 SQLITE_INT_TO_PTR(0), from_jsonb_func, 0, 0, 026 );27 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_create_function_v2 failed");28}29 30/* Helper: run "SELECT from_jsonb(jsonb(?1))" with a JSON/JSON5 text param and compare */31static void assert_jsonb_to_text_equals(const char *jsonIn, const char *expectOut){32 sqlite3_stmt *pStmt = NULL;33 const char *zSql = "SELECT from_jsonb(jsonb(?1))";34 int rc = sqlite3_prepare_v2(gDb, zSql, -1, &pStmt, 0);35 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "prepare failed");36 37 rc = sqlite3_bind_text(pStmt, 1, jsonIn, -1, SQLITE_STATIC);38 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "bind failed");39 40 rc = sqlite3_step(pStmt);41 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_ROW, rc, "step did not return a row");42 43 const unsigned char *zOut = sqlite3_column_text(pStmt, 0);44 TEST_ASSERT_NOT_NULL(zOut);45 TEST_ASSERT_EQUAL_STRING(expectOut, (const char*)zOut);46 47 sqlite3_finalize(pStmt);48}49 50/* Helper: run a statement expecting an error */51static void assert_from_jsonb_blob_error(const void *pBlob, int nBlob, const char *expectErrSubstr){52 sqlite3_stmt *pStmt = NULL;53 const char *zSql = "SELECT from_jsonb(?1)";54 int rc = sqlite3_prepare_v2(gDb, zSql, -1, &pStmt, 0);55 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "prepare failed (error test)");56 57 rc = sqlite3_bind_blob(pStmt, 1, pBlob, nBlob, SQLITE_STATIC);58 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "bind blob failed (error test)");59 60 rc = sqlite3_step(pStmt);61 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_ERROR, rc, "expected SQLITE_ERROR from malformed blob");62 63 const char *zErr = sqlite3_errmsg(gDb);64 TEST_ASSERT_NOT_NULL(zErr);65 TEST_ASSERT_NOT_EQUAL_INT(0, (int)strstr(zErr, expectErrSubstr) != NULL);66 67 sqlite3_finalize(pStmt);68}69 70void setUp(void) {71 int rc = sqlite3_open(":memory:", &gDb);72 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_open failed");73 register_from_jsonb(gDb);74}75 76void tearDown(void) {77 if( gDb ){78 sqlite3_close(gDb);79 gDb = NULL;80 }81}82 83/* Tests */84 85void test_jsonReturnTextJsonFromBlob_null_true_false(void){86 assert_jsonb_to_text_equals("null", "null");87 assert_jsonb_to_text_equals("true", "true");88 assert_jsonb_to_text_equals("false", "false");89}90 91void test_jsonReturnTextJsonFromBlob_numbers_plain(void){92 assert_jsonb_to_text_equals("123456", "123456");93 assert_jsonb_to_text_equals("-99", "-99");94 assert_jsonb_to_text_equals("3.14", "3.14");95 assert_jsonb_to_text_equals("-2.0", "-2.0");96}97 98void test_jsonReturnTextJsonFromBlob_json5_hex_and_overflow(void){99 /* JSON5 hex integers should render as decimal */100 assert_jsonb_to_text_equals("0x10", "16");101 assert_jsonb_to_text_equals("-0xA", "-10");102 assert_jsonb_to_text_equals("+0x1f", "31");103 104 /* Overflow beyond 64-bit -> "9.0e999" */105 assert_jsonb_to_text_equals("0x10000000000000000", "9.0e999"); /* 2^64 */106}107 108void test_jsonReturnTextJsonFromBlob_json5_float_missing_digits(void){109 assert_jsonb_to_text_equals(".5", "0.5");110 assert_jsonb_to_text_equals("2.", "2.0");111 assert_jsonb_to_text_equals("-.25", "-0.25");112}113 114void test_jsonReturnTextJsonFromBlob_text_and_escapes(void){115 /* Standard JSON escape -> should pass through */116 assert_jsonb_to_text_equals("\"a\\nb\"", "\"a\\nb\"");117 118 /* JSON5 single-quoted string with \xNN, \v, \0, embedded " and \' */119 const char *json5_in = "'A\\x42\\v\\0\"\\''";120 const char *expect_out = "\"A\\u0042\\u000b\\u0000\\\"'\"";121 assert_jsonb_to_text_equals(json5_in, expect_out);122}123 124void test_jsonReturnTextJsonFromBlob_array_object_nested(void){125 assert_jsonb_to_text_equals("[1,2,3]", "[1,2,3]");126 assert_jsonb_to_text_equals("{\"a\":1,\"b\":2}", "{\"a\":1,\"b\":2}");127 /* Nested */128 assert_jsonb_to_text_equals("[1,{\"a\":2},[3]]", "[1,{\"a\":2},[3]]");129}130 131void test_jsonReturnTextJsonFromBlob_malformed_empty_blob_error(void){132 /* Passing an empty blob should be detected as malformed JSONB */133 assert_from_jsonb_blob_error("", 0, "malformed JSON");134}135 136int main(void) {137 UNITY_BEGIN();138 RUN_TEST(test_jsonReturnTextJsonFromBlob_null_true_false);139 RUN_TEST(test_jsonReturnTextJsonFromBlob_numbers_plain);140 RUN_TEST(test_jsonReturnTextJsonFromBlob_json5_hex_and_overflow);141 RUN_TEST(test_jsonReturnTextJsonFromBlob_json5_float_missing_digits);142 RUN_TEST(test_jsonReturnTextJsonFromBlob_text_and_escapes);143 RUN_TEST(test_jsonReturnTextJsonFromBlob_array_object_nested);144 RUN_TEST(test_jsonReturnTextJsonFromBlob_malformed_empty_blob_error);145 return UNITY_END();146}