Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_json_jsonTranslateBlobToText.c345 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5#include <stdint.h>6 7/* Prototype of the global test wrapper provided in the module */8u32 test_jsonTranslateBlobToText(const JsonParse *pParse, u32 i, JsonString *pOut);9 10/* Helpers to build headers */11#define HDR(sz,type)   (unsigned char)(((unsigned int)(sz)<<4) | ((type)&0x0f))12 13/* Initialize a JsonString equivalent to jsonStringZero/init without calling static funcs */14static void js_init(JsonString *p){15    memset(p, 0, sizeof(*p));16    p->zBuf = p->zSpace;17    p->nAlloc = (u32)sizeof(p->zSpace);18    p->nUsed = 0;19    p->bStatic = 1;20    p->eErr = 0;21    p->pCtx = NULL;22}23 24/* Initialize a JsonParse with a given blob */25static void jp_init(JsonParse *p, const unsigned char *aBlob, u32 nBlob){26    memset(p, 0, sizeof(*p));27    p->aBlob = aBlob;28    p->nBlob = nBlob;29    p->delta = 0;30}31 32/* Add C-string terminator for comparisons */33static void js_terminate(JsonString *p){34    /* Ensure there's room; the buffer implementations always keep capacity >= nUsed.35       Our test outputs are small and fit in the default zSpace. */36    if( p->nUsed < p->nAlloc ){37        p->zBuf[p->nUsed] = 0;38    }else if( p->nAlloc > 0 ){39        /* Fallback: overwrite last byte (should not happen with small outputs) */40        p->zBuf[p->nAlloc-1] = 0;41    }42}43 44void setUp(void) {45    /* No global setup needed */46}47void tearDown(void) {48    /* No global teardown needed */49}50 51/* Test NULL, TRUE, FALSE primitives */52void test_jsonTranslateBlobToText_primitives(void){53    unsigned char blob_null[]  = { HDR(0, JSONB_NULL) };54    unsigned char blob_true[]  = { HDR(0, JSONB_TRUE) };55    unsigned char blob_false[] = { HDR(0, JSONB_FALSE) };56 57    JsonParse p; JsonString out; u32 r;58 59    /* NULL */60    jp_init(&p, blob_null, sizeof(blob_null)); js_init(&out);61    r = test_jsonTranslateBlobToText(&p, 0, &out);62    js_terminate(&out);63    TEST_ASSERT_EQUAL_UINT32(1, r);64    TEST_ASSERT_EQUAL_STRING("null", out.zBuf);65    TEST_ASSERT_EQUAL_UINT32(0, out.eErr);66 67    /* TRUE */68    jp_init(&p, blob_true, sizeof(blob_true)); js_init(&out);69    r = test_jsonTranslateBlobToText(&p, 0, &out);70    js_terminate(&out);71    TEST_ASSERT_EQUAL_UINT32(1, r);72    TEST_ASSERT_EQUAL_STRING("true", out.zBuf);73    TEST_ASSERT_EQUAL_UINT32(0, out.eErr);74 75    /* FALSE */76    jp_init(&p, blob_false, sizeof(blob_false)); js_init(&out);77    r = test_jsonTranslateBlobToText(&p, 0, &out);78    js_terminate(&out);79    TEST_ASSERT_EQUAL_UINT32(1, r);80    TEST_ASSERT_EQUAL_STRING("false", out.zBuf);81    TEST_ASSERT_EQUAL_UINT32(0, out.eErr);82}83 84/* Test INT and FLOAT payloads */85void test_jsonTranslateBlobToText_int_and_float(void){86    /* INT "123" => header size 3, type INT(3) => 0x33, payload '123' */87    unsigned char blob_int[] = { HDR(3, JSONB_INT), '1','2','3' };88    /* FLOAT "3.14" => header size 4, type FLOAT(5) => 0x45, payload '3.14' */89    unsigned char blob_float[] = { HDR(4, JSONB_FLOAT), '3','.','1','4' };90 91    JsonParse p; JsonString out; u32 r;92 93    jp_init(&p, blob_int, sizeof(blob_int)); js_init(&out);94    r = test_jsonTranslateBlobToText(&p, 0, &out);95    js_terminate(&out);96    TEST_ASSERT_EQUAL_UINT32(sizeof(blob_int), r);97    TEST_ASSERT_EQUAL_STRING("123", out.zBuf);98    TEST_ASSERT_EQUAL_UINT32(0, out.eErr);99 100    jp_init(&p, blob_float, sizeof(blob_float)); js_init(&out);101    r = test_jsonTranslateBlobToText(&p, 0, &out);102    js_terminate(&out);103    TEST_ASSERT_EQUAL_UINT32(sizeof(blob_float), r);104    TEST_ASSERT_EQUAL_STRING("3.14", out.zBuf);105    TEST_ASSERT_EQUAL_UINT32(0, out.eErr);106}107 108/* Test INT5 hex with sign and overflow behavior */109void test_jsonTranslateBlobToText_int5_and_overflow(void){110    /* INT5 "-0x1f" => -31 */111    unsigned char blob_hex_neg[] = { HDR(5, JSONB_INT5), '-', '0','x','1','f' };112 113    /* INT5 "0x100000000000000000" (18 hex digits beyond 64-bit) => overflow -> 9.0e999114       We'll use 0x10000000000000000 (17 hex digits after 0x) */115    const char *hex_over = "0x10000000000000000";116    unsigned sz = (unsigned)strlen(hex_over);117    unsigned char blob_hex_over[1 + 32] = {0};118    blob_hex_over[0] = HDR(sz, JSONB_INT5);119    memcpy(&blob_hex_over[1], hex_over, sz);120 121    JsonParse p; JsonString out; u32 r;122 123    /* Negative hex */124    jp_init(&p, blob_hex_neg, sizeof(blob_hex_neg)); js_init(&out);125    r = test_jsonTranslateBlobToText(&p, 0, &out);126    js_terminate(&out);127    TEST_ASSERT_EQUAL_UINT32(sizeof(blob_hex_neg), r);128    TEST_ASSERT_EQUAL_STRING("-31", out.zBuf);129    TEST_ASSERT_EQUAL_UINT32(0, out.eErr);130 131    /* Overflow hex */132    jp_init(&p, blob_hex_over, 1+sz); js_init(&out);133    r = test_jsonTranslateBlobToText(&p, 0, &out);134    js_terminate(&out);135    TEST_ASSERT_EQUAL_UINT32(1+sz, r);136    TEST_ASSERT_EQUAL_STRING("9.0e999", out.zBuf);137    TEST_ASSERT_EQUAL_UINT32(0, out.eErr);138}139 140/* Test FLOAT5 normalization */141void test_jsonTranslateBlobToText_float5(void){142    /* FLOAT5 "-.5" => "-0.5" */143    unsigned char blob_f5a[] = { HDR(3, JSONB_FLOAT5), '-', '.','5' };144    /* FLOAT5 "." => "0.0" */145    unsigned char blob_f5b[] = { HDR(1, JSONB_FLOAT5), '.' };146 147    JsonParse p; JsonString out; u32 r;148 149    jp_init(&p, blob_f5a, sizeof(blob_f5a)); js_init(&out);150    r = test_jsonTranslateBlobToText(&p, 0, &out);151    js_terminate(&out);152    TEST_ASSERT_EQUAL_STRING("-0.5", out.zBuf);153    TEST_ASSERT_EQUAL_UINT32(sizeof(blob_f5a), r);154    TEST_ASSERT_EQUAL_UINT32(0, out.eErr);155 156    jp_init(&p, blob_f5b, sizeof(blob_f5b)); js_init(&out);157    r = test_jsonTranslateBlobToText(&p, 0, &out);158    js_terminate(&out);159    TEST_ASSERT_EQUAL_STRING("0.0", out.zBuf);160    TEST_ASSERT_EQUAL_UINT32(sizeof(blob_f5b), r);161    TEST_ASSERT_EQUAL_UINT32(0, out.eErr);162}163 164/* Test TEXT and TEXTJ simple quoting */165void test_jsonTranslateBlobToText_text_and_textj(void){166    /* TEXT "abc" => output "abc" (with quotes) */167    unsigned char blob_text[]  = { HDR(3, JSONB_TEXT),  'a','b','c' };168    /* TEXTJ with backslash n should remain as two chars in output (JSON escaping) */169    unsigned char blob_textj[] = { HDR(3, JSONB_TEXTJ), 'a','\\','n' };170 171    JsonParse p; JsonString out; u32 r;172 173    jp_init(&p, blob_text, sizeof(blob_text)); js_init(&out);174    r = test_jsonTranslateBlobToText(&p, 0, &out);175    js_terminate(&out);176    TEST_ASSERT_EQUAL_STRING("\"abc\"", out.zBuf);177    TEST_ASSERT_EQUAL_UINT32(sizeof(blob_text), r);178    TEST_ASSERT_EQUAL_UINT32(0, out.eErr);179 180    jp_init(&p, blob_textj, sizeof(blob_textj)); js_init(&out);181    r = test_jsonTranslateBlobToText(&p, 0, &out);182    js_terminate(&out);183    TEST_ASSERT_EQUAL_STRING("\"a\\n\"", out.zBuf);184    TEST_ASSERT_EQUAL_UINT32(sizeof(blob_textj), r);185    TEST_ASSERT_EQUAL_UINT32(0, out.eErr);186}187 188/* Test TEXT5 with various escapes */189void test_jsonTranslateBlobToText_text5_escapes(void){190    /* Payload: " then \x41 then \' then \v then \0191       Sequence: [ '"' , '\\','x','4','1' , '\\','\'' , '\\','v' , '\\','0' ]192       Expect inside quotes: \"\u0041'\u000b\u0000193     */194    unsigned char payload[] = { '"', '\\','x','4','1', '\\','\'', '\\','v', '\\','0' };195    unsigned char blob[1 + sizeof(payload)];196    blob[0] = HDR((u32)sizeof(payload), JSONB_TEXT5);197    memcpy(&blob[1], payload, sizeof(payload));198 199    JsonParse p; JsonString out; u32 r;200    jp_init(&p, blob, sizeof(blob)); js_init(&out);201    r = test_jsonTranslateBlobToText(&p, 0, &out);202    js_terminate(&out);203 204    TEST_ASSERT_EQUAL_UINT32(sizeof(blob), r);205    TEST_ASSERT_EQUAL_STRING("\"\\\"\\u0041'\\u000b\\u0000\"", out.zBuf);206    TEST_ASSERT_EQUAL_UINT32(0, out.eErr);207}208 209/* TEXTRAW should JSON-escape/quote via jsonAppendString */210void test_jsonTranslateBlobToText_textraw(void){211    /* Payload "a\nb" (actual newline byte 0x0a) should become "a\nb" with \n escaped in JSON text */212    unsigned char payload[] = { 'a', '\n', 'b' };213    unsigned char blob[1 + sizeof(payload)];214    blob[0] = HDR((u32)sizeof(payload), JSONB_TEXTRAW);215    memcpy(&blob[1], payload, sizeof(payload));216 217    JsonParse p; JsonString out; u32 r;218    jp_init(&p, blob, sizeof(blob)); js_init(&out);219    r = test_jsonTranslateBlobToText(&p, 0, &out);220    js_terminate(&out);221 222    TEST_ASSERT_EQUAL_UINT32(sizeof(blob), r);223    TEST_ASSERT_EQUAL_STRING("\"a\\nb\"", out.zBuf);224    TEST_ASSERT_EQUAL_UINT32(0, out.eErr);225}226 227/* Extended header size for TEXT (size nibble 12) with 12-byte payload */228void test_jsonTranslateBlobToText_extended_header_text(void){229    const char *twelve = "abcdefghijkl"; /* 12 chars */230    unsigned char blob[2 + 12];231    blob[0] = HDR(12, JSONB_TEXT); /* signals 1 extra size byte */232    blob[1] = 12;                  /* payload length */233    memcpy(&blob[2], twelve, 12);234 235    JsonParse p; JsonString out; u32 r;236    jp_init(&p, blob, sizeof(blob)); js_init(&out);237    r = test_jsonTranslateBlobToText(&p, 0, &out);238    js_terminate(&out);239 240    TEST_ASSERT_EQUAL_UINT32(sizeof(blob), r);241    TEST_ASSERT_EQUAL_STRING("\"abcdefghijkl\"", out.zBuf);242    TEST_ASSERT_EQUAL_UINT32(0, out.eErr);243}244 245/* Array and Object basic cases */246void test_jsonTranslateBlobToText_array_and_object(void){247    /* Array [true] => element TRUE (1 byte), array header: size 1, type ARRAY (11) => 0x1B */248    unsigned char arr1[] = { HDR(1, JSONB_ARRAY), HDR(0, JSONB_TRUE) };249 250    /* Array [null,false,true] */251    unsigned char arrN[] = {252        /* header: payload 3 bytes */253        HDR(3, JSONB_ARRAY),254        HDR(0, JSONB_NULL),255        HDR(0, JSONB_FALSE),256        HDR(0, JSONB_TRUE)257    };258 259    /* Object {"x":false}260       key: TEXT "x" => header 0x17, payload 'x'261       value: FALSE => 0x02262       object header: payload size 2+1=3, type OBJECT(12) => 0x3C263    */264    unsigned char obj1[] = { HDR(3, JSONB_OBJECT), HDR(1, JSONB_TEXT), 'x', HDR(0, JSONB_FALSE) };265 266    JsonParse p; JsonString out; u32 r;267 268    /* [true] */269    jp_init(&p, arr1, sizeof(arr1)); js_init(&out);270    r = test_jsonTranslateBlobToText(&p, 0, &out);271    js_terminate(&out);272    TEST_ASSERT_EQUAL_UINT32(sizeof(arr1), r);273    TEST_ASSERT_EQUAL_STRING("[true]", out.zBuf);274    TEST_ASSERT_EQUAL_UINT32(0, out.eErr);275 276    /* [null,false,true] */277    jp_init(&p, arrN, sizeof(arrN)); js_init(&out);278    r = test_jsonTranslateBlobToText(&p, 0, &out);279    js_terminate(&out);280    TEST_ASSERT_EQUAL_UINT32(sizeof(arrN), r);281    TEST_ASSERT_EQUAL_STRING("[null,false,true]", out.zBuf);282    TEST_ASSERT_EQUAL_UINT32(0, out.eErr);283 284    /* {"x":false} */285    jp_init(&p, obj1, sizeof(obj1)); js_init(&out);286    r = test_jsonTranslateBlobToText(&p, 0, &out);287    js_terminate(&out);288    TEST_ASSERT_EQUAL_UINT32(sizeof(obj1), r);289    TEST_ASSERT_EQUAL_STRING("{\"x\":false}", out.zBuf);290    TEST_ASSERT_EQUAL_UINT32(0, out.eErr);291}292 293/* Object with odd element count should set malformed error */294void test_jsonTranslateBlobToText_object_odd_count_error(void){295    /* Object with only one element (true), payload size 1 */296    unsigned char obj_bad[] = { HDR(1, JSONB_OBJECT), HDR(0, JSONB_TRUE) };297 298    JsonParse p; JsonString out; u32 r;299    jp_init(&p, obj_bad, sizeof(obj_bad)); js_init(&out);300    r = test_jsonTranslateBlobToText(&p, 0, &out);301    /* Output may be "{true}" (since trailing ':' trimmed). Validate error flag. */302    TEST_ASSERT_NOT_EQUAL(0u, out.eErr & JSTRING_MALFORMED);303}304 305/* Malformed header: claims extended size but truncated */306void test_jsonTranslateBlobToText_malformed_header_truncated(void){307    /* First byte indicates extended 1-byte size for INT (x==12), but missing size byte */308    unsigned char blob_bad[] = { HDR(12, JSONB_INT) /* no following size byte */ };309 310    JsonParse p; JsonString out; u32 r;311    jp_init(&p, blob_bad, sizeof(blob_bad)); js_init(&out);312    r = test_jsonTranslateBlobToText(&p, 0, &out);313 314    TEST_ASSERT_EQUAL_UINT32(p.nBlob + 1, r);315    TEST_ASSERT_NOT_EQUAL(0u, out.eErr & JSTRING_MALFORMED);316}317 318/* Malformed numeric: INT with zero-length payload should be flagged */319void test_jsonTranslateBlobToText_malformed_numeric_empty_payload(void){320    unsigned char blob_bad[] = { HDR(0, JSONB_INT) };321 322    JsonParse p; JsonString out; u32 r;323    jp_init(&p, blob_bad, sizeof(blob_bad)); js_init(&out);324    r = test_jsonTranslateBlobToText(&p, 0, &out);325 326    TEST_ASSERT_EQUAL_UINT32(1, r);327    TEST_ASSERT_NOT_EQUAL(0u, out.eErr & JSTRING_MALFORMED);328}329 330int main(void){331    UNITY_BEGIN();332    RUN_TEST(test_jsonTranslateBlobToText_primitives);333    RUN_TEST(test_jsonTranslateBlobToText_int_and_float);334    RUN_TEST(test_jsonTranslateBlobToText_int5_and_overflow);335    RUN_TEST(test_jsonTranslateBlobToText_float5);336    RUN_TEST(test_jsonTranslateBlobToText_text_and_textj);337    RUN_TEST(test_jsonTranslateBlobToText_text5_escapes);338    RUN_TEST(test_jsonTranslateBlobToText_textraw);339    RUN_TEST(test_jsonTranslateBlobToText_extended_header_text);340    RUN_TEST(test_jsonTranslateBlobToText_array_and_object);341    RUN_TEST(test_jsonTranslateBlobToText_object_odd_count_error);342    RUN_TEST(test_jsonTranslateBlobToText_malformed_header_truncated);343    RUN_TEST(test_jsonTranslateBlobToText_malformed_numeric_empty_payload);344    return UNITY_END();345}