AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5#include <stdio.h>6 7/* Wrapper provided in the module for the static function */8extern void test_jsonAppendPathName(JsonEachCursor *p);9 10/* Unity hooks */11void setUp(void) {12 /* no-op */13}14void tearDown(void) {15 /* no-op */16}17 18/* Helper: Initialize a JsonString to hold an initial value */19static void initPath(JsonString *p, const char *initial){20 memset(p, 0, sizeof(*p));21 p->zBuf = p->zSpace;22 p->nAlloc = (u32)sizeof(p->zSpace);23 p->nUsed = 0;24 p->bStatic = 1;25 if( initial ){26 size_t n = strlen(initial);27 if( n >= sizeof(p->zSpace) ){28 n = sizeof(p->zSpace) - 1;29 }30 memcpy(p->zBuf, initial, n);31 p->zBuf[n] = '\0';32 p->nUsed = (u32)n;33 }else{34 p->zBuf[0] = '\0';35 p->nUsed = 0;36 }37}38 39/* Helper: Setup a JsonEachCursor for OBJECT path with a crafted JSONB label.40 headerForm:41 0 -> single-byte header (size in high nibble)42 1 -> form-12 header (1 size byte)43 2 -> form-13 header (2 size bytes)44*/45static void setupObjectWithLabel(JsonEachCursor *c,46 unsigned char *blob,47 unsigned int headerForm,48 const char *label){49 size_t len = label ? strlen(label) : 0;50 unsigned int n = 0;51 52 /* Build JSONB header + payload for a TEXT element (type code 7) */53 if( headerForm == 0 ){54 /* Single-byte header. Ensure len fits high-nibble (<= 11). */55 TEST_ASSERT(len <= 11);56 blob[0] = (unsigned char)((((unsigned int)len) << 4) | 0x07);57 if( len ) memcpy(blob+1, label, len);58 n = 1 + (unsigned int)len;59 }else if( headerForm == 1 ){60 /* Form 12: 1 size byte */61 TEST_ASSERT(len <= 255);62 blob[0] = (unsigned char)((12 << 4) | 0x07);63 blob[1] = (unsigned char)(len & 0xFF);64 if( len ) memcpy(blob+2, label, len);65 n = 2 + (unsigned int)len;66 }else{67 /* Form 13: 2 size bytes */68 TEST_ASSERT(len <= 65535);69 blob[0] = (unsigned char)((13 << 4) | 0x07);70 blob[1] = (unsigned char)((((unsigned int)len) >> 8) & 0xFF);71 blob[2] = (unsigned char)(((unsigned int)len) & 0xFF);72 if( len ) memcpy(blob+3, label, len);73 n = 3 + (unsigned int)len;74 }75 76 memset(c, 0, sizeof(*c));77 c->nParent = 1; /* assert requires > 0 */78 c->eType = JSONB_OBJECT; /* test OBJECT branch */79 c->i = 0; /* payload starts at index 0 */80 c->sParse.aBlob = blob;81 c->sParse.nBlob = n;82 c->sParse.delta = 0;83 initPath(&c->path, "");84}85 86/* Case: Alphanumeric label, starts with alpha -> no quotes */87static void test_jsonAppendPathName_object_simple_unquoted(void){88 JsonEachCursor c;89 unsigned char blob[64];90 setupObjectWithLabel(&c, blob, 0, "abc123");91 test_jsonAppendPathName(&c);92 TEST_ASSERT_EQUAL_STRING(".abc123", c.path.zBuf);93}94 95/* Case: starts with digit -> quoted */96static void test_jsonAppendPathName_object_starts_with_digit_quoted(void){97 JsonEachCursor c;98 unsigned char blob[64];99 setupObjectWithLabel(&c, blob, 0, "1abc");100 /* Preload path to verify append behavior */101 initPath(&c.path, "$");102 test_jsonAppendPathName(&c);103 TEST_ASSERT_EQUAL_STRING("$.\"1abc\"", c.path.zBuf);104}105 106/* Case: contains non-alnum (dash) -> quoted */107static void test_jsonAppendPathName_object_contains_dash_quoted(void){108 JsonEachCursor c;109 unsigned char blob[64];110 setupObjectWithLabel(&c, blob, 0, "ab-cd");111 test_jsonAppendPathName(&c);112 TEST_ASSERT_EQUAL_STRING(".\"ab-cd\"", c.path.zBuf);113}114 115/* Case: zero-length label -> quoted as ."" */116static void test_jsonAppendPathName_object_zero_length_label(void){117 JsonEachCursor c;118 unsigned char blob[2];119 /* Single-byte header with size 0, TEXT type (7) */120 blob[0] = (unsigned char)((0 << 4) | 0x07);121 memset(&c, 0, sizeof(c));122 c.nParent = 1;123 c.eType = JSONB_OBJECT;124 c.i = 0;125 c.sParse.aBlob = blob;126 c.sParse.nBlob = 1;127 c.sParse.delta = 0;128 initPath(&c.path, "");129 test_jsonAppendPathName(&c);130 TEST_ASSERT_EQUAL_STRING(".\"\"", c.path.zBuf);131}132 133/* Case: non-minimal header form (12) with longer label -> ensure parsing works */134static void test_jsonAppendPathName_object_form12_header_unquoted(void){135 JsonEachCursor c;136 unsigned char blob[64];137 setupObjectWithLabel(&c, blob, 1, "abcdefghijklmnopqrst"); /* 20 chars */138 test_jsonAppendPathName(&c);139 TEST_ASSERT_EQUAL_STRING(".abcdefghijklmnopqrst", c.path.zBuf);140}141 142/* Case: starts with underscore -> quoted (not alpha) */143static void test_jsonAppendPathName_object_starts_with_underscore_quoted(void){144 JsonEachCursor c;145 unsigned char blob[64];146 setupObjectWithLabel(&c, blob, 0, "_abc");147 test_jsonAppendPathName(&c);148 TEST_ASSERT_EQUAL_STRING(".\"_abc\"", c.path.zBuf);149}150 151int main(void){152 UNITY_BEGIN();153 RUN_TEST(test_jsonAppendPathName_object_simple_unquoted);154 RUN_TEST(test_jsonAppendPathName_object_starts_with_digit_quoted);155 RUN_TEST(test_jsonAppendPathName_object_contains_dash_quoted);156 RUN_TEST(test_jsonAppendPathName_object_zero_length_label);157 RUN_TEST(test_jsonAppendPathName_object_form12_header_unquoted);158 RUN_TEST(test_jsonAppendPathName_object_starts_with_underscore_quoted);159 return UNITY_END();160}