Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_json_jsonInsertIntoBlob.c237 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3 4#include <stdio.h>5#include <stdlib.h>6#include <string.h>7 8/* Forward declarations of the wrapper provided in the module */9void test_jsonInsertIntoBlob(sqlite3_context *ctx, int argc, sqlite3_value **argv, int eEdit);10 11/* Global database handle for tests */12static sqlite3 *gDb = NULL;13 14/* Helper: create SQL scalar functions that wrap test_jsonInsertIntoBlob */15static void t_json_insert_func(sqlite3_context *ctx, int argc, sqlite3_value **argv){16  test_jsonInsertIntoBlob(ctx, argc, argv, JEDIT_INS);17}18static void t_json_replace_func(sqlite3_context *ctx, int argc, sqlite3_value **argv){19  test_jsonInsertIntoBlob(ctx, argc, argv, JEDIT_REPL);20}21static void t_json_set_func(sqlite3_context *ctx, int argc, sqlite3_value **argv){22  test_jsonInsertIntoBlob(ctx, argc, argv, JEDIT_SET);23}24 25/* Register wrappers with the current database connection. */26static void register_json_edit_wrappers(sqlite3 *db){27  int rc;28  rc = sqlite3_create_function(db, "t_json_insert", -1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0,29                               t_json_insert_func, 0, 0);30  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "Failed to create t_json_insert");31  rc = sqlite3_create_function(db, "t_json_replace", -1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0,32                               t_json_replace_func, 0, 0);33  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "Failed to create t_json_replace");34  rc = sqlite3_create_function(db, "t_json_set", -1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0,35                               t_json_set_func, 0, 0);36  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "Failed to create t_json_set");37}38 39/* Helper: evaluate a scalar SQL and return a newly-allocated copy of column text */40static char *eval_scalar_text(sqlite3 *db, const char *sql){41  sqlite3_stmt *pStmt = NULL;42  int rc = sqlite3_prepare_v2(db, sql, -1, &pStmt, 0);43  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "prepare failed");44  rc = sqlite3_step(pStmt);45  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_ROW, rc, "expected one row");46  const unsigned char *z = sqlite3_column_text(pStmt, 0);47  char *ret = sqlite3_mprintf("%s", z ? (const char*)z : "");48  sqlite3_finalize(pStmt);49  return ret;50}51 52/* Helper: execute a scalar SQL expected to error; return a copy of the error message */53static char *eval_expect_error(sqlite3 *db, const char *sql){54  sqlite3_stmt *pStmt = NULL;55  int rc = sqlite3_prepare_v2(db, sql, -1, &pStmt, 0);56  if( rc==SQLITE_OK ){57    rc = sqlite3_step(pStmt);58    /* Expecting SQLITE_ERROR */59    TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_ERROR, rc, "expected SQLITE_ERROR");60    sqlite3_finalize(pStmt);61  }else{62    /* Prepare-time error is also acceptable for some malformed cases */63  }64  const char *zErr = sqlite3_errmsg(db);65  return sqlite3_mprintf("%s", zErr ? zErr : "");66}67 68void setUp(void) {69  int rc = sqlite3_open(":memory:", &gDb);70  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_open failed");71  register_json_edit_wrappers(gDb);72}73 74void tearDown(void) {75  if( gDb ){76    sqlite3_close(gDb);77    gDb = NULL;78  }79}80 81/* Tests */82 83/* Root-level insert on "$" is a no-op */84void test_jsonInsertIntoBlob_root_insert_noop(void){85  const char *sql = "SELECT t_json_insert(jsonb('[1]'), '$', 77)";86  char *z = eval_scalar_text(gDb, sql);87  TEST_ASSERT_NOT_NULL(z);88  TEST_ASSERT_EQUAL_STRING("[1]", z);89  sqlite3_free(z);90}91 92/* Root-level replace on "$" replaces entire document */93void test_jsonInsertIntoBlob_root_replace(void){94  const char *sql = "SELECT t_json_replace(jsonb('[1,2,3]'), '$', 99)";95  char *z = eval_scalar_text(gDb, sql);96  TEST_ASSERT_NOT_NULL(z);97  TEST_ASSERT_EQUAL_STRING("99", z);98  sqlite3_free(z);99}100 101/* Insert object key when missing */102void test_jsonInsertIntoBlob_object_insert_key(void){103  const char *sql = "SELECT t_json_insert(jsonb('{}'), '$.a', 1)";104  char *z = eval_scalar_text(gDb, sql);105  TEST_ASSERT_NOT_NULL(z);106  TEST_ASSERT_EQUAL_STRING("{\"a\":1}", z);107  sqlite3_free(z);108}109 110/* Set object key when missing (create it) */111void test_jsonInsertIntoBlob_object_set_inserts_when_missing(void){112  const char *sql = "SELECT t_json_set(jsonb('{}'), '$.a', 1)";113  char *z = eval_scalar_text(gDb, sql);114  TEST_ASSERT_NOT_NULL(z);115  TEST_ASSERT_EQUAL_STRING("{\"a\":1}", z);116  sqlite3_free(z);117}118 119/* Replace on missing key does nothing */120void test_jsonInsertIntoBlob_object_replace_missing_noop(void){121  const char *sql = "SELECT t_json_replace(jsonb('{}'), '$.a', 1)";122  char *z = eval_scalar_text(gDb, sql);123  TEST_ASSERT_NOT_NULL(z);124  TEST_ASSERT_EQUAL_STRING("{}", z);125  sqlite3_free(z);126}127 128/* Replace on existing key updates value */129void test_jsonInsertIntoBlob_object_replace_existing(void){130  const char *sql = "SELECT t_json_replace(jsonb('{\"a\":1}'), '$.a', 2)";131  char *z = eval_scalar_text(gDb, sql);132  TEST_ASSERT_NOT_NULL(z);133  TEST_ASSERT_EQUAL_STRING("{\"a\":2}", z);134  sqlite3_free(z);135}136 137/* Insert into array at index 0 on empty array */138void test_jsonInsertIntoBlob_array_insert_index0(void){139  const char *sql = "SELECT t_json_insert(jsonb('[]'), '$[0]', 5)";140  char *z = eval_scalar_text(gDb, sql);141  TEST_ASSERT_NOT_NULL(z);142  TEST_ASSERT_EQUAL_STRING("[5]", z);143  sqlite3_free(z);144}145 146/* Set into array at index 1 appends */147void test_jsonInsertIntoBlob_array_set_appends(void){148  const char *sql = "SELECT t_json_set(jsonb('[0]'), '$[1]', 9)";149  char *z = eval_scalar_text(gDb, sql);150  TEST_ASSERT_NOT_NULL(z);151  TEST_ASSERT_EQUAL_STRING("[0,9]", z);152  sqlite3_free(z);153}154 155/* Multiple path/value edits in one call */156void test_jsonInsertIntoBlob_multiple_pairs(void){157  const char *sql = "SELECT t_json_set(jsonb('{}'), '$.a', 1, '$.b', 2)";158  char *z = eval_scalar_text(gDb, sql);159  TEST_ASSERT_NOT_NULL(z);160  /* Expect insertion order a then b */161  TEST_ASSERT_EQUAL_STRING("{\"a\":1,\"b\":2}", z);162  sqlite3_free(z);163}164 165/* NULL path arguments are ignored */166void test_jsonInsertIntoBlob_null_path_is_ignored(void){167  const char *sql = "SELECT t_json_set(jsonb('{}'), NULL, 99, '$.x', 1)";168  char *z = eval_scalar_text(gDb, sql);169  TEST_ASSERT_NOT_NULL(z);170  TEST_ASSERT_EQUAL_STRING("{\"x\":1}", z);171  sqlite3_free(z);172}173 174/* Malformed path (e.g., '$.') yields bad JSON path error */175void test_jsonInsertIntoBlob_malformed_path_error(void){176  const char *sql = "SELECT t_json_set(jsonb('{}'), '$.', 1)";177  char *zErr = eval_expect_error(gDb, sql);178  TEST_ASSERT_NOT_NULL(zErr);179  TEST_ASSERT_EQUAL_STRING("bad JSON path: $.", zErr);180  sqlite3_free(zErr);181}182 183/* Path not starting with '$' yields bad JSON path error */184void test_jsonInsertIntoBlob_path_missing_dollar_error(void){185  const char *sql = "SELECT t_json_set(jsonb('{}'), 'a', 1)";186  char *zErr = eval_expect_error(gDb, sql);187  TEST_ASSERT_NOT_NULL(zErr);188  TEST_ASSERT_EQUAL_STRING("bad JSON path: a", zErr);189  sqlite3_free(zErr);190}191 192/* Content as non-JSONB BLOB is rejected */193void test_jsonInsertIntoBlob_blob_content_error(void){194  const char *sql = "SELECT t_json_set(jsonb('{}'), '$.a', x'1234')";195  char *zErr = eval_expect_error(gDb, sql);196  TEST_ASSERT_NOT_NULL(zErr);197  TEST_ASSERT_EQUAL_STRING("JSON cannot hold BLOB values", zErr);198  sqlite3_free(zErr);199}200 201/* Single-argument call returns original unchanged */202void test_jsonInsertIntoBlob_single_arg_passthrough(void){203  const char *sql = "SELECT t_json_set(jsonb('{\"a\":1}'))";204  char *z = eval_scalar_text(gDb, sql);205  TEST_ASSERT_NOT_NULL(z);206  TEST_ASSERT_EQUAL_STRING("{\"a\":1}", z);207  sqlite3_free(z);208}209 210/* Nested path creation with json_set */211void test_jsonInsertIntoBlob_nested_set_creates_structure(void){212  const char *sql = "SELECT t_json_set(jsonb('{}'), '$.a.b', 1)";213  char *z = eval_scalar_text(gDb, sql);214  TEST_ASSERT_NOT_NULL(z);215  TEST_ASSERT_EQUAL_STRING("{\"a\":{\"b\":1}}", z);216  sqlite3_free(z);217}218 219int main(void){220  UNITY_BEGIN();221  RUN_TEST(test_jsonInsertIntoBlob_root_insert_noop);222  RUN_TEST(test_jsonInsertIntoBlob_root_replace);223  RUN_TEST(test_jsonInsertIntoBlob_object_insert_key);224  RUN_TEST(test_jsonInsertIntoBlob_object_set_inserts_when_missing);225  RUN_TEST(test_jsonInsertIntoBlob_object_replace_missing_noop);226  RUN_TEST(test_jsonInsertIntoBlob_object_replace_existing);227  RUN_TEST(test_jsonInsertIntoBlob_array_insert_index0);228  RUN_TEST(test_jsonInsertIntoBlob_array_set_appends);229  RUN_TEST(test_jsonInsertIntoBlob_multiple_pairs);230  RUN_TEST(test_jsonInsertIntoBlob_null_path_is_ignored);231  RUN_TEST(test_jsonInsertIntoBlob_malformed_path_error);232  RUN_TEST(test_jsonInsertIntoBlob_path_missing_dollar_error);233  RUN_TEST(test_jsonInsertIntoBlob_blob_content_error);234  RUN_TEST(test_jsonInsertIntoBlob_single_arg_passthrough);235  RUN_TEST(test_jsonInsertIntoBlob_nested_set_creates_structure);236  return UNITY_END();237}