Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_json_jsonArrayStep.c182 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5#include <stdio.h>6 7/* Global database handle for tests */8static sqlite3 *gDb = NULL;9 10/* Forward declaration of the wrapper provided in the module */11void test_jsonArrayStep(sqlite3_context *ctx, int argc, sqlite3_value **argv);12 13/* Aggregate step: delegate to the target function wrapper */14static void tja_step(sqlite3_context *ctx, int argc, sqlite3_value **argv){15  test_jsonArrayStep(ctx, argc, argv);16}17 18/* Finalizer that returns the raw accumulated buffer (without closing bracket) */19static void tja_final_raw(sqlite3_context *ctx){20  JsonString *pStr = (JsonString*)sqlite3_aggregate_context(ctx, (int)sizeof(JsonString));21  if( pStr==0 || pStr->zBuf==0 ){22    sqlite3_result_null(ctx);23    return;24  }25  if( pStr->eErr ){26    /* Preserve any prior error set by the step function */27    return;28  }29  /* Return exactly the accumulated bytes as text */30  sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);31}32 33/* Finalizer that appends a closing ']' and returns complete JSON text */34static void tja_final_json(sqlite3_context *ctx){35  JsonString *pStr = (JsonString*)sqlite3_aggregate_context(ctx, (int)sizeof(JsonString));36  if( pStr==0 || pStr->zBuf==0 ){37    sqlite3_result_null(ctx);38    return;39  }40  if( pStr->eErr ){41    /* Preserve any prior error set by the step function */42    return;43  }44  /* Build a copy with a closing bracket */45  size_t n = (size_t)pStr->nUsed;46  char *zOut = (char*)sqlite3_malloc64(n + 2);47  if( zOut==0 ){48    sqlite3_result_error_nomem(ctx);49    return;50  }51  memcpy(zOut, pStr->zBuf, n);52  zOut[n] = ']';53  zOut[n+1] = 0;54  sqlite3_result_text(ctx, zOut, -1, sqlite3_free);55}56 57/* Helpers to run scalar queries and fetch a single text result */58static void assert_query_text_eq(const char *sql, const char *expected){59  sqlite3_stmt *stmt = 0;60  int rc = sqlite3_prepare_v2(gDb, sql, -1, &stmt, 0);61  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);62  rc = sqlite3_step(stmt);63  TEST_ASSERT_EQUAL_INT(SQLITE_ROW, rc);64  int t = sqlite3_column_type(stmt, 0);65  TEST_ASSERT_NOT_EQUAL_MESSAGE(SQLITE_NULL, t, "Expected a text result, got NULL");66  const unsigned char *z = sqlite3_column_text(stmt, 0);67  TEST_ASSERT_NOT_NULL(z);68  TEST_ASSERT_EQUAL_STRING(expected, (const char*)z);69  rc = sqlite3_step(stmt);70  TEST_ASSERT_EQUAL_INT(SQLITE_DONE, rc);71  sqlite3_finalize(stmt);72}73 74static void assert_query_is_null(const char *sql){75  sqlite3_stmt *stmt = 0;76  int rc = sqlite3_prepare_v2(gDb, sql, -1, &stmt, 0);77  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);78  rc = sqlite3_step(stmt);79  TEST_ASSERT_EQUAL_INT(SQLITE_ROW, rc);80  TEST_ASSERT_EQUAL_INT(SQLITE_NULL, sqlite3_column_type(stmt, 0));81  rc = sqlite3_step(stmt);82  TEST_ASSERT_EQUAL_INT(SQLITE_DONE, rc);83  sqlite3_finalize(stmt);84}85 86static void assert_query_error_contains(const char *sql, const char *substr){87  sqlite3_stmt *stmt = 0;88  int rc = sqlite3_prepare_v2(gDb, sql, -1, &stmt, 0);89  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);90  rc = sqlite3_step(stmt);91  TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, rc);92  const char *zErr = sqlite3_errmsg(gDb);93  TEST_ASSERT_NOT_NULL(zErr);94  TEST_ASSERT_NOT_NULL_MESSAGE(strstr(zErr, substr), "Error message does not contain expected substring");95  sqlite3_finalize(stmt);96}97 98/* Unity setUp/tearDown */99void setUp(void) {100  int rc = sqlite3_open(":memory:", &gDb);101  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);102 103  /* Register our test aggregates */104  rc = sqlite3_create_function(gDb, "tja_raw", 1, SQLITE_UTF8, 0, 0, tja_step, tja_final_raw);105  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);106  rc = sqlite3_create_function(gDb, "tja_json", 1, SQLITE_UTF8, 0, 0, tja_step, tja_final_json);107  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);108}109void tearDown(void) {110  if( gDb ){111    sqlite3_close(gDb);112    gDb = NULL;113  }114}115 116/* Tests */117 118void test_jsonArrayStep_single_integer(void){119  /* First step should insert '[' then the integer text */120  assert_query_text_eq("SELECT tja_raw(x) FROM (VALUES(5)) AS t(x);", "[5");121}122 123void test_jsonArrayStep_two_integers_comma_inserted(void){124  /* After first element, subsequent steps should insert commas */125  assert_query_text_eq("SELECT tja_raw(x) FROM (VALUES(1),(2)) AS t(x);", "[1,2");126}127 128void test_jsonArrayStep_mixed_types_complete_json(void){129  /* Verify string quoting, null, and float formatting with closing bracket */130  assert_query_text_eq(131    "SELECT tja_json(x) FROM (VALUES(1),('a'),(NULL),(1.25)) AS t(x);",132    "[1,\"a\",null,1.25]"133  );134}135 136void test_jsonArrayStep_json_subtype_passthrough(void){137  /* json() returns text with JSON_SUBTYPE; it should be appended without extra quotes */138  assert_query_text_eq(139    "SELECT tja_json(x) FROM (SELECT json('{\"x\":1}') AS x);",140    "[{\"x\":1}]"141  );142}143 144void test_jsonArrayStep_jsonb_blob_supported(void){145  /* jsonb() returns a JSONB blob; it should be translated to text and appended */146  assert_query_text_eq(147    "SELECT tja_json(x) FROM (SELECT jsonb('[1,2]') AS x);",148    "[[1,2]]"149  );150}151 152void test_jsonArrayStep_blob_error_raises(void){153  /* Non-JSON blob should cause an error: "JSON cannot hold BLOB values" */154  assert_query_error_contains(155    "SELECT tja_json(x) FROM (VALUES(zeroblob(2))) AS t(x);",156    "JSON cannot hold BLOB values"157  );158}159 160void test_jsonArrayStep_empty_input_yields_null(void){161  /* Aggregating over zero rows should return NULL */162  assert_query_is_null("SELECT tja_json(x) FROM (SELECT 1 WHERE 0) AS t(x);");163}164 165void test_jsonArrayStep_single_null(void){166  /* Single NULL should produce [null] when closed */167  assert_query_text_eq("SELECT tja_json(x) FROM (VALUES(NULL)) AS t(x);", "[null]");168}169 170/* main runner */171int main(void){172  UNITY_BEGIN();173  RUN_TEST(test_jsonArrayStep_single_integer);174  RUN_TEST(test_jsonArrayStep_two_integers_comma_inserted);175  RUN_TEST(test_jsonArrayStep_mixed_types_complete_json);176  RUN_TEST(test_jsonArrayStep_json_subtype_passthrough);177  RUN_TEST(test_jsonArrayStep_jsonb_blob_supported);178  RUN_TEST(test_jsonArrayStep_blob_error_raises);179  RUN_TEST(test_jsonArrayStep_empty_input_yields_null);180  RUN_TEST(test_jsonArrayStep_single_null);181  return UNITY_END();182}