Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_json_jsonReturnStringAsBlob.c163 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6/* Forward declaration of the provided test wrapper for the static function */7extern void test_jsonReturnStringAsBlob(JsonString *pStr);8 9static sqlite3 *gDb = NULL;10 11/* UDF: make_blob(text) -> JSONB blob converted by jsonReturnStringAsBlob */12static void xMakeBlob(sqlite3_context *ctx, int argc, sqlite3_value **argv){13  (void)argc;14  JsonString js;15  memset(&js, 0, sizeof(js));16 17  const unsigned char *zArg = sqlite3_value_text(argv[0]);18  if( zArg==NULL ){19    /* Propagate SQL NULL to result NULL for completeness */20    sqlite3_result_null(ctx);21    return;22  }23 24  /* Use a sufficiently large stack buffer to avoid growth during termination */25  char buf[1024];26  size_t n = strlen((const char*)zArg);27  if( n >= sizeof(buf) ) n = sizeof(buf) - 1;28  memcpy(buf, zArg, n);29 30  js.zBuf = buf;31  js.nUsed = (u32)n;32  js.nAlloc = (u32)sizeof(buf);33  js.bStatic = 1;34  js.eErr = 0;35  js.pCtx = ctx;36 37  test_jsonReturnStringAsBlob(&js);38}39 40/* UDF: make_blob_err(text) -> forces eErr to simulate OOM/error precondition */41static void xMakeBlobErr(sqlite3_context *ctx, int argc, sqlite3_value **argv){42  (void)argc;43  (void)argv;44  JsonString js;45  memset(&js, 0, sizeof(js));46 47  char dummy[] = "null";48  js.zBuf = dummy;49  js.nUsed = (u32)strlen(dummy);50  js.nAlloc = (u32)sizeof(dummy);51  js.bStatic = 1;52  js.eErr = 1; /* Non-zero triggers sqlite3_result_error_nomem */53  js.pCtx = ctx;54 55  test_jsonReturnStringAsBlob(&js);56}57 58static void prepare_and_bind_text(sqlite3_stmt **ppStmt, const char *zSql, const char *zParam){59  int rc = sqlite3_prepare_v2(gDb, zSql, -1, ppStmt, NULL);60  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "prepare failed");61  rc = sqlite3_bind_text(*ppStmt, 1, zParam, -1, SQLITE_TRANSIENT);62  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "bind failed");63}64 65void setUp(void) {66  int rc = sqlite3_open(":memory:", &gDb);67  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_open failed");68 69  rc = sqlite3_create_function(gDb, "make_blob", 1, SQLITE_UTF8, NULL, xMakeBlob, NULL, NULL);70  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "create_function make_blob failed");71 72  rc = sqlite3_create_function(gDb, "make_blob_err", 1, SQLITE_UTF8, NULL, xMakeBlobErr, NULL, NULL);73  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "create_function make_blob_err failed");74}75 76void tearDown(void) {77  if( gDb ){78    int rc = sqlite3_close(gDb);79    TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_close failed");80    gDb = NULL;81  }82}83 84/* Helper to validate typeof, json_valid, and json canonicalization */85static void assert_roundtrip(const char *inJson, const char *expectedCanonical){86  sqlite3_stmt *pStmt = NULL;87  const char *zSql =88    "SELECT typeof(make_blob(?1)), json_valid(make_blob(?1)), json(make_blob(?1))";89  prepare_and_bind_text(&pStmt, zSql, inJson);90 91  int rc = sqlite3_step(pStmt);92  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_ROW, rc, "step failed");93 94  const unsigned char *zType = sqlite3_column_text(pStmt, 0);95  TEST_ASSERT_NOT_NULL(zType);96  TEST_ASSERT_EQUAL_STRING("blob", (const char*)zType);97 98  int isValid = sqlite3_column_int(pStmt, 1);99  TEST_ASSERT_EQUAL_INT(1, isValid);100 101  const unsigned char *zCanon = sqlite3_column_text(pStmt, 2);102  TEST_ASSERT_NOT_NULL(zCanon);103  TEST_ASSERT_EQUAL_STRING(expectedCanonical, (const char*)zCanon);104 105  rc = sqlite3_finalize(pStmt);106  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "finalize failed");107}108 109void test_jsonReturnStringAsBlob_roundtrip_null(void){110  assert_roundtrip("null", "null");111}112 113void test_jsonReturnStringAsBlob_roundtrip_object_array(void){114  const char *in = "{\"a\":1,\"b\":[2,3]}";115  const char *expected = "{\"a\":1,\"b\":[2,3]}";116  assert_roundtrip(in, expected);117}118 119void test_jsonReturnStringAsBlob_roundtrip_string_escapes(void){120  /* JSON string "a\nb" encoded with escape */121  assert_roundtrip("\"a\\nb\"", "\"a\\nb\"");122}123 124void test_jsonReturnStringAsBlob_accepts_JSON5_single_quotes(void){125  /* JSON5 input with single quotes should canonicalize to double-quoted JSON */126  assert_roundtrip("'abc'", "\"abc\"");127}128 129void test_jsonReturnStringAsBlob_accepts_JSON5_leading_decimal(void){130  /* JSON5 input .5 should canonicalize to 0.5 */131  assert_roundtrip(".5", "0.5");132}133 134void test_jsonReturnStringAsBlob_error_when_eErr_pre_set(void){135  sqlite3_stmt *pStmt = NULL;136  const char *zSql = "SELECT make_blob_err(?1)";137  prepare_and_bind_text(&pStmt, zSql, "{\"a\":1}");138 139  int rc = sqlite3_step(pStmt);140  /* Expect an error due to sqlite3_result_error_nomem inside the target function */141  TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, rc);142 143  int eec = sqlite3_extended_errcode(gDb);144  TEST_ASSERT_EQUAL_INT(SQLITE_NOMEM, eec);145 146  /* Optionally verify there is an error message */147  const char *zErr = sqlite3_errmsg(gDb);148  TEST_ASSERT_NOT_NULL(zErr);149 150  rc = sqlite3_finalize(pStmt);151  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);152}153 154int main(void) {155  UNITY_BEGIN();156  RUN_TEST(test_jsonReturnStringAsBlob_roundtrip_null);157  RUN_TEST(test_jsonReturnStringAsBlob_roundtrip_object_array);158  RUN_TEST(test_jsonReturnStringAsBlob_roundtrip_string_escapes);159  RUN_TEST(test_jsonReturnStringAsBlob_accepts_JSON5_single_quotes);160  RUN_TEST(test_jsonReturnStringAsBlob_accepts_JSON5_leading_decimal);161  RUN_TEST(test_jsonReturnStringAsBlob_error_when_eErr_pre_set);162  return UNITY_END();163}