Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_json_jsonFunctionArgToBlob.c298 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5#include <math.h>6 7/* Wrapper provided in module */8int test_jsonFunctionArgToBlob(sqlite3_context *ctx, sqlite3_value *pArg, JsonParse *pParse);9 10static sqlite3 *gDb = NULL;11 12static void init_context(sqlite3 *db, sqlite3_context *pCtx, Mem *pOut){13  memset(pCtx, 0, sizeof(*pCtx));14  sqlite3VdbeMemInit(pOut, db, 0);15  pCtx->pOut = pOut;16}17 18static void cleanup_context_out(Mem *pOut){19  sqlite3VdbeMemRelease(pOut);20  memset(pOut, 0, sizeof(*pOut));21}22 23void setUp(void) {24  if( gDb==NULL ){25    int rc = sqlite3_open(":memory:", &gDb);26    TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);27  }28}29void tearDown(void) {30  /* Keep db open across tests; close in main after Unity_END */31}32 33/* Helper to free JsonParse->aBlob if it was allocated */34static void free_parse_blob(JsonParse *p){35  if( p && p->nBlobAlloc>0 && p->aBlob ){36    sqlite3DbFree(p->db, p->aBlob);37    p->aBlob = NULL;38    p->nBlob = 0;39    p->nBlobAlloc = 0;40  }41}42 43/* Test: default branch (e.g., NULL argument) -> JSONB NULL single byte */44void test_jsonFunctionArgToBlob_null_input(void){45  sqlite3_context ctx;46  Mem out;47  init_context(gDb, &ctx, &out);48 49  sqlite3_value *v = sqlite3ValueNew(gDb);50  /* v is NULL by default, or explicitly: */51  sqlite3VdbeMemSetNull((Mem*)v);52 53  JsonParse p;54  int rc = test_jsonFunctionArgToBlob(&ctx, v, &p);55 56  TEST_ASSERT_EQUAL_INT(0, rc);57  TEST_ASSERT_EQUAL_PTR(gDb, p.db);58  TEST_ASSERT_EQUAL_UINT32(1u, p.nBlob);59  TEST_ASSERT_NOT_NULL(p.aBlob);60  /* JSONB NULL is type 0 with zero payload -> first byte is 0x00 */61  TEST_ASSERT_EQUAL_HEX8(0x00, p.aBlob[0]);62  TEST_ASSERT_EQUAL_UINT32(0u, p.nBlobAlloc); /* should not be allocated */63 64  sqlite3ValueFree(v);65  cleanup_context_out(&out);66}67 68/* Test: BLOB not JSONB -> error and return 1 */69void test_jsonFunctionArgToBlob_blob_not_jsonb_errors(void){70  sqlite3_context ctx;71  Mem out;72  init_context(gDb, &ctx, &out);73 74  static const char blobData[] = "abc";75  sqlite3_value *v = sqlite3ValueNew(gDb);76  sqlite3VdbeMemSetStr((Mem*)v, blobData, (int)sizeof(blobData)-1, 0 /*enc=0 => BLOB*/, SQLITE_STATIC);77 78  JsonParse p;79  int rc = test_jsonFunctionArgToBlob(&ctx, v, &p);80 81  TEST_ASSERT_EQUAL_INT(1, rc);82  TEST_ASSERT_NULL(p.aBlob);83  TEST_ASSERT_EQUAL_UINT32(0u, p.nBlob);84  /* Check error message */85  const unsigned char *zErr = sqlite3_value_text((sqlite3_value*)&out);86  TEST_ASSERT_NOT_NULL(zErr);87  TEST_ASSERT_NOT_EQUAL(-1, (int)sqlite3StrlikeCompare((const char*)zErr, "JSON cannot hold BLOB values", 0));88 89  sqlite3ValueFree(v);90  cleanup_context_out(&out);91}92 93/* Test: BLOB valid JSONB (single 0x00 byte) -> accepted, no copy */94void test_jsonFunctionArgToBlob_blob_jsonb_accepted(void){95  sqlite3_context ctx;96  Mem out;97  init_context(gDb, &ctx, &out);98 99  static const unsigned char jsonbNull[] = { 0x00 };100  sqlite3_value *v = sqlite3ValueNew(gDb);101  sqlite3VdbeMemSetStr((Mem*)v, jsonbNull, 1, 0 /*blob*/, SQLITE_STATIC);102 103  /* Capture pointer to underlying blob for later pointer equality check */104  const void *valBlobPtr = sqlite3_value_blob(v);105 106  JsonParse p;107  int rc = test_jsonFunctionArgToBlob(&ctx, v, &p);108 109  TEST_ASSERT_EQUAL_INT(0, rc);110  TEST_ASSERT_EQUAL_UINT32(1u, p.nBlob);111  TEST_ASSERT_EQUAL_PTR(valBlobPtr, (const void*)p.aBlob);112  TEST_ASSERT_EQUAL_HEX8(0x00, p.aBlob[0]);113  TEST_ASSERT_EQUAL_UINT32(0u, p.nBlobAlloc); /* borrowed memory */114 115  sqlite3ValueFree(v);116  cleanup_context_out(&out);117}118 119/* Test: TEXT without JSON subtype => TEXTRAW with payload */120void test_jsonFunctionArgToBlob_text_raw_textraw_encoding(void){121  sqlite3_context ctx;122  Mem out;123  init_context(gDb, &ctx, &out);124 125  const char *txt = "hello";126  const int n = (int)strlen(txt);127 128  sqlite3_value *v = sqlite3ValueNew(gDb);129  sqlite3VdbeMemSetStr((Mem*)v, txt, n, SQLITE_UTF8, SQLITE_STATIC);130 131  JsonParse p;132  int rc = test_jsonFunctionArgToBlob(&ctx, v, &p);133 134  TEST_ASSERT_EQUAL_INT(0, rc);135  TEST_ASSERT_NOT_NULL(p.aBlob);136  TEST_ASSERT_TRUE(p.nBlob >= 1u + (unsigned)n);137  /* First byte: type JSONB_TEXTRAW | (n<<4) if n<=11 */138  TEST_ASSERT_LESS_OR_EQUAL(11, n); /* ensure small payload path; n=5 OK */139  TEST_ASSERT_EQUAL_HEX8((JSONB_TEXTRAW | (n<<4)), p.aBlob[0]);140  TEST_ASSERT_EQUAL_UINT32((unsigned)(1 + n), p.nBlob);141  TEST_ASSERT_EQUAL_MEMORY(txt, p.aBlob+1, (size_t)n);142  TEST_ASSERT_TRUE(p.nBlobAlloc > 0);143 144  free_parse_blob(&p);145  sqlite3ValueFree(v);146  cleanup_context_out(&out);147}148 149/* Test: TEXT with JSON subtype "null" => JSONB NULL */150void test_jsonFunctionArgToBlob_text_jsonsubtype_valid_null(void){151  sqlite3_context ctx;152  Mem out;153  init_context(gDb, &ctx, &out);154 155  const char *txt = "null";156  sqlite3_value *v = sqlite3ValueNew(gDb);157  sqlite3VdbeMemSetStr((Mem*)v, txt, (int)strlen(txt), SQLITE_UTF8, SQLITE_STATIC);158  sqlite3VdbeMemSetSubtype((Mem*)v, JSON_SUBTYPE);159 160  JsonParse p;161  int rc = test_jsonFunctionArgToBlob(&ctx, v, &p);162 163  TEST_ASSERT_EQUAL_INT(0, rc);164  TEST_ASSERT_NOT_NULL(p.aBlob);165  TEST_ASSERT_EQUAL_UINT32(1u, p.nBlob);166  TEST_ASSERT_EQUAL_HEX8(0x00, p.aBlob[0]); /* JSONB NULL */167 168  free_parse_blob(&p);169  sqlite3ValueFree(v);170  cleanup_context_out(&out);171}172 173/* Test: TEXT with JSON subtype malformed => error */174void test_jsonFunctionArgToBlob_text_jsonsubtype_malformed_error(void){175  sqlite3_context ctx;176  Mem out;177  init_context(gDb, &ctx, &out);178 179  const char *txt = "x"; /* malformed JSON */180  sqlite3_value *v = sqlite3ValueNew(gDb);181  sqlite3VdbeMemSetStr((Mem*)v, txt, (int)strlen(txt), SQLITE_UTF8, SQLITE_STATIC);182  sqlite3VdbeMemSetSubtype((Mem*)v, JSON_SUBTYPE);183 184  JsonParse p;185  int rc = test_jsonFunctionArgToBlob(&ctx, v, &p);186 187  TEST_ASSERT_EQUAL_INT(1, rc);188  /* pParse reset to empty on error */189  TEST_ASSERT_NULL(p.aBlob);190  TEST_ASSERT_EQUAL_UINT32(0u, p.nBlob);191  /* confirm error message */192  const unsigned char *zErr = sqlite3_value_text((sqlite3_value*)&out);193  TEST_ASSERT_NOT_NULL(zErr);194  TEST_ASSERT_NOT_EQUAL(-1, (int)sqlite3StrlikeCompare((const char*)zErr, "malformed JSON", 0));195 196  sqlite3ValueFree(v);197  cleanup_context_out(&out);198}199 200/* Test: FLOAT finite => JSONB_FLOAT with textual payload */201void test_jsonFunctionArgToBlob_float_finite(void){202  sqlite3_context ctx;203  Mem out;204  init_context(gDb, &ctx, &out);205 206  sqlite3_value *v = sqlite3ValueNew(gDb);207  sqlite3VdbeMemSetDouble((Mem*)v, 1.25);208 209  /* Capture expected textual representation before calling */210  const unsigned char *zExp = sqlite3_value_text(v);211  int nExp = sqlite3_value_bytes(v);212  TEST_ASSERT_NOT_NULL(zExp);213  TEST_ASSERT_TRUE(nExp > 0 && nExp <= 11); /* ensure small-header path */214 215  JsonParse p;216  int rc = test_jsonFunctionArgToBlob(&ctx, v, &p);217 218  TEST_ASSERT_EQUAL_INT(0, rc);219  TEST_ASSERT_NOT_NULL(p.aBlob);220  TEST_ASSERT_EQUAL_UINT32((unsigned)(1 + nExp), p.nBlob);221  TEST_ASSERT_EQUAL_HEX8((JSONB_FLOAT | (nExp<<4)), p.aBlob[0]);222  TEST_ASSERT_EQUAL_MEMORY(zExp, p.aBlob+1, (size_t)nExp);223 224  free_parse_blob(&p);225  sqlite3ValueFree(v);226  cleanup_context_out(&out);227}228 229/* Test: FLOAT NaN => JSONB NULL */230void test_jsonFunctionArgToBlob_float_nan_becomes_null(void){231  sqlite3_context ctx;232  Mem out;233  init_context(gDb, &ctx, &out);234 235  sqlite3_value *v = sqlite3ValueNew(gDb);236  double x = NAN;237  sqlite3VdbeMemSetDouble((Mem*)v, x);238 239  JsonParse p;240  int rc = test_jsonFunctionArgToBlob(&ctx, v, &p);241 242  TEST_ASSERT_EQUAL_INT(0, rc);243  TEST_ASSERT_NOT_NULL(p.aBlob);244  TEST_ASSERT_EQUAL_UINT32(1u, p.nBlob);245  TEST_ASSERT_EQUAL_HEX8(0x00, p.aBlob[0]); /* JSONB NULL */246 247  free_parse_blob(&p);248  sqlite3ValueFree(v);249  cleanup_context_out(&out);250}251 252/* Test: INTEGER => JSONB_INT with textual payload */253void test_jsonFunctionArgToBlob_integer_basic(void){254  sqlite3_context ctx;255  Mem out;256  init_context(gDb, &ctx, &out);257 258  sqlite3_value *v = sqlite3ValueNew(gDb);259  sqlite3VdbeMemSetInt64((Mem*)v, 12345);260 261  /* Capture expected textual representation */262  const unsigned char *zExp = sqlite3_value_text(v);263  int nExp = sqlite3_value_bytes(v);264  TEST_ASSERT_NOT_NULL(zExp);265  TEST_ASSERT_TRUE(nExp > 0 && nExp <= 11);266 267  JsonParse p;268  int rc = test_jsonFunctionArgToBlob(&ctx, v, &p);269 270  TEST_ASSERT_EQUAL_INT(0, rc);271  TEST_ASSERT_NOT_NULL(p.aBlob);272  TEST_ASSERT_EQUAL_UINT32((unsigned)(1 + nExp), p.nBlob);273  TEST_ASSERT_EQUAL_HEX8((JSONB_INT | (nExp<<4)), p.aBlob[0]);274  TEST_ASSERT_EQUAL_MEMORY(zExp, p.aBlob+1, (size_t)nExp);275 276  free_parse_blob(&p);277  sqlite3ValueFree(v);278  cleanup_context_out(&out);279}280 281int main(void){282  UNITY_BEGIN();283  RUN_TEST(test_jsonFunctionArgToBlob_null_input);284  RUN_TEST(test_jsonFunctionArgToBlob_blob_not_jsonb_errors);285  RUN_TEST(test_jsonFunctionArgToBlob_blob_jsonb_accepted);286  RUN_TEST(test_jsonFunctionArgToBlob_text_raw_textraw_encoding);287  RUN_TEST(test_jsonFunctionArgToBlob_text_jsonsubtype_valid_null);288  RUN_TEST(test_jsonFunctionArgToBlob_text_jsonsubtype_malformed_error);289  RUN_TEST(test_jsonFunctionArgToBlob_float_finite);290  RUN_TEST(test_jsonFunctionArgToBlob_float_nan_becomes_null);291  RUN_TEST(test_jsonFunctionArgToBlob_integer_basic);292  int rc = UNITY_END();293  if( gDb ){294    sqlite3_close(gDb);295    gDb = NULL;296  }297  return rc;298}