Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_json_jsonArrayFunc.c147 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3 4#include <stdlib.h>5#include <string.h>6#include <stdio.h>7 8/* The wrapper symbol provided in the module under test */9extern void test_jsonArrayFunc(sqlite3_context *ctx, int argc, sqlite3_value **argv);10 11static sqlite3 *gDb = NULL;12 13/* SQL function trampoline that invokes the target wrapper */14static void xTestJsonArrayFunc(sqlite3_context *ctx, int argc, sqlite3_value **argv){15  test_jsonArrayFunc(ctx, argc, argv);16}17 18/* Helper: register the SQL function that calls the target wrapper */19static void register_test_function(sqlite3 *db){20  /* Deterministic is fine. No user-data flags so results are text, not JSONB */21  int rc = sqlite3_create_function(db, "test_jsonArrayFunc", -1, SQLITE_UTF8 | SQLITE_DETERMINISTIC,22                                   0, xTestJsonArrayFunc, 0, 0);23  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);24}25 26/* Helper: prepare, step once, assert row, return stmt for caller to inspect */27static sqlite3_stmt* prepare_and_step(const char *sql){28  sqlite3_stmt *stmt = NULL;29  int rc = sqlite3_prepare_v2(gDb, sql, -1, &stmt, 0);30  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "prepare failed");31  rc = sqlite3_step(stmt);32  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_ROW, rc, "expected a single row result");33  return stmt;34}35 36/* Helper: execute expecting SQLITE_ERROR with an error message containing a substring */37static void expect_sql_error_contains(const char *sql, const char *needle){38  sqlite3_stmt *stmt = NULL;39  int rc = sqlite3_prepare_v2(gDb, sql, -1, &stmt, 0);40  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "prepare failed");41  rc = sqlite3_step(stmt);42  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_ERROR, rc, "expected SQLITE_ERROR from step");43  const char *emsg = sqlite3_errmsg(gDb);44  TEST_ASSERT_NOT_NULL(emsg);45  TEST_ASSERT_NOT_NULL(needle);46  TEST_ASSERT_NOT_EQUAL(-1, (int)(strstr(emsg, needle) - emsg >= 0 ? strstr(emsg, needle) - emsg : -1));47  sqlite3_finalize(stmt);48}49 50/* Helper: check single TEXT result equals expected and subtype is JSON_SUBTYPE */51static void expect_single_text_and_json_subtype(const char *sql, const char *expected){52  sqlite3_stmt *stmt = prepare_and_step(sql);53  const unsigned char *txt = sqlite3_column_text(stmt, 0);54  int subtype = sqlite3_column_subtype(stmt, 0);55  TEST_ASSERT_NOT_NULL(txt);56  TEST_ASSERT_EQUAL_STRING(expected, (const char*)txt);57  TEST_ASSERT_EQUAL_INT(JSON_SUBTYPE, subtype);58  sqlite3_finalize(stmt);59}60 61void setUp(void) {62  int rc = sqlite3_open(":memory:", &gDb);63  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);64  register_test_function(gDb);65}66 67void tearDown(void) {68  if( gDb ){69    sqlite3_close(gDb);70    gDb = NULL;71  }72}73 74/* Test: no arguments -> [] with JSON subtype */75void test_jsonArrayFunc_empty(void){76  expect_single_text_and_json_subtype("SELECT test_jsonArrayFunc()", "[]");77}78 79/* Test: NULL handling -> [null,null] */80void test_jsonArrayFunc_nulls(void){81  expect_single_text_and_json_subtype("SELECT test_jsonArrayFunc(NULL,NULL)", "[null,null]");82}83 84/* Test: mixed types: INTEGER, FLOAT, TEXT */85void test_jsonArrayFunc_mixed_types(void){86  /* '1' (TEXT) should be quoted, float formatting should be 3.5 */87  expect_single_text_and_json_subtype(88    "SELECT test_jsonArrayFunc(1, -2, 3.5, 'x', '1')",89    "[1,-2,3.5,\"x\",\"1\"]"90  );91}92 93/* Test: string quoting and escaping of quotes */94void test_jsonArrayFunc_string_escaping(void){95  /* input: a"b -> JSON string should be \" escaped */96  expect_single_text_and_json_subtype(97    "SELECT test_jsonArrayFunc('a\"b')",98    "[\"a\\\"b\"]"99  );100}101 102/* Test: passthrough for JSON-typed text (subtype JSON_SUBTYPE) using json() */103void test_jsonArrayFunc_json_subtype_passthrough(void){104  /* json('{"x":1}') yields JSON-subtype text; it should be inserted raw, not quoted */105  expect_single_text_and_json_subtype(106    "SELECT test_jsonArrayFunc(json('{\"x\":1}'), 'y')",107    "[{\"x\":1},\"y\"]"108  );109}110 111/* Test: BLOB argument should raise an error: "JSON cannot hold BLOB values" */112void test_jsonArrayFunc_blob_error(void){113  expect_sql_error_contains("SELECT test_jsonArrayFunc(x'313233')", "BLOB");114}115 116/* Test: buffer growth by using many arguments; verify length is as expected */117void test_jsonArrayFunc_many_args_growth(void){118  /* Build a SELECT with 200 'a' literals */119  char sql[8192];120  strcpy(sql, "SELECT test_jsonArrayFunc(");121  for(int i=0; i<200; i++){122    strcat(sql, "'a'");123    if( i!=199 ) strcat(sql, ",");124  }125  strcat(sql, ")");126  sqlite3_stmt *stmt = prepare_and_step(sql);127  const unsigned char *txt = sqlite3_column_text(stmt, 0);128  int subtype = sqlite3_column_subtype(stmt, 0);129  TEST_ASSERT_NOT_NULL(txt);130  TEST_ASSERT_EQUAL_INT(JSON_SUBTYPE, subtype);131  int n = sqlite3_column_bytes(stmt, 0);132  /* Each 'a' becomes "a" (3 chars), 199 commas, and 2 brackets: 200*3 + 199 + 2 = 801 */133  TEST_ASSERT_EQUAL_INT(801, n);134  sqlite3_finalize(stmt);135}136 137int main(void){138  UNITY_BEGIN();139  RUN_TEST(test_jsonArrayFunc_empty);140  RUN_TEST(test_jsonArrayFunc_nulls);141  RUN_TEST(test_jsonArrayFunc_mixed_types);142  RUN_TEST(test_jsonArrayFunc_string_escaping);143  RUN_TEST(test_jsonArrayFunc_json_subtype_passthrough);144  RUN_TEST(test_jsonArrayFunc_blob_error);145  RUN_TEST(test_jsonArrayFunc_many_args_growth);146  return UNITY_END();147}