AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5#include <stdio.h>6 7void test_jsonAfterEditSizeAdjust(JsonParse *pParse, u32 iRoot);8 9/* Helpers to inspect/construct JSONB headers in tests */10 11static u8 extra_len_from_first(u8 first){12 u8 x = first >> 4;13 if( x <= 11 ) return 0;14 if( x == 12 ) return 1;15 if( x == 13 ) return 2;16 if( x == 14 ) return 4;17 /* x == 15 would be 8, but we will not generate that in tests */18 return 8;19}20 21static u8 sizefield_needed_for_payload(u32 sz){22 if( sz <= 11 ) return 0;23 if( sz <= 0xff ) return 1;24 if( sz <= 0xffff ) return 2;25 return 4;26}27 28static u32 header_size_for_payload(u32 sz){29 return 1 + sizefield_needed_for_payload(sz);30}31 32static void write_header(u8 *a, u8 eType, u32 payloadSz){33 if( payloadSz <= 11 ){34 a[0] = eType | (payloadSz<<4);35 }else if( payloadSz <= 0xff ){36 a[0] = eType | 0xC0;37 a[1] = (u8)(payloadSz & 0xff);38 }else if( payloadSz <= 0xffff ){39 a[0] = eType | 0xD0;40 a[1] = (u8)((payloadSz >> 8) & 0xff);41 a[2] = (u8)(payloadSz & 0xff);42 }else{43 a[0] = eType | 0xE0;44 a[1] = (u8)((payloadSz >> 24) & 0xff);45 a[2] = (u8)((payloadSz >> 16) & 0xff);46 a[3] = (u8)((payloadSz >> 8) & 0xff);47 a[4] = (u8)(payloadSz & 0xff);48 }49}50 51static u32 read_payload_size_from_header(const u8 *a){52 u8 x = a[0] >> 4;53 if( x <= 11 ){54 return x;55 }else if( x == 12 ){56 return (u32)a[1];57 }else if( x == 13 ){58 return ((u32)a[1] << 8) | (u32)a[2];59 }else if( x == 14 ){60 return ((u32)a[1] << 24) | ((u32)a[2] << 16) | ((u32)a[3] << 8) | (u32)a[4];61 }else{62 /* We won't construct this in tests */63 return 0;64 }65}66 67/* Build a single JSONB element at offset 0 with given payload size and capacity */68static void make_single_node(JsonParse *p, u8 eType, u32 payloadSz, u32 extraCapacity){69 memset(p, 0, sizeof(*p));70 u32 hdr = header_size_for_payload(payloadSz);71 u32 used = hdr + payloadSz;72 u32 cap = used + extraCapacity;73 74 p->aBlob = (u8*)sqlite3_malloc(cap);75 TEST_ASSERT_NOT_NULL(p->aBlob);76 memset(p->aBlob, 0, cap);77 78 write_header(p->aBlob, eType, payloadSz);79 /* Fill payload with a pattern so memmove has something to move */80 memset(p->aBlob + hdr, 0xAA, payloadSz);81 82 p->nBlob = used;83 p->nBlobAlloc = cap;84 p->oom = 0;85 p->bReadOnly = 0;86}87 88/* Unity hooks */89void setUp(void) { }90void tearDown(void) { }91 92/* Tests */93 94void test_jsonAfterEditSizeAdjust_grow_inline_to_1byte(void){95 JsonParse p;96 const u8 eType = 0x07; /* TEXT-like type code */97 const u32 initialSz = 11;98 const int initialDelta = 1; /* 11 -> 12 */99 make_single_node(&p, eType, initialSz, 32);100 101 u8 beforeFirst = p.aBlob[0];102 u8 beforeExtra = extra_len_from_first(beforeFirst);103 TEST_ASSERT_EQUAL_UINT8(0, beforeExtra);104 105 p.delta = initialDelta;106 test_jsonAfterEditSizeAdjust(&p, 0);107 108 /* New size should be 12, header grows by +1 */109 u32 newSz = read_payload_size_from_header(p.aBlob);110 TEST_ASSERT_EQUAL_UINT32(initialSz + initialDelta, newSz);111 112 u8 afterFirst = p.aBlob[0];113 TEST_ASSERT_EQUAL_UINT8(eType, afterFirst & 0x0F); /* type preserved */114 u8 afterExtra = extra_len_from_first(afterFirst);115 TEST_ASSERT_EQUAL_UINT8(1, afterExtra);116 117 /* nBlob increased by header delta, delta updated accordingly */118 TEST_ASSERT_EQUAL_UINT32(header_size_for_payload(initialSz) + initialSz + 1, p.nBlob);119 TEST_ASSERT_EQUAL_INT(initialDelta + (int)(afterExtra - beforeExtra), p.delta);120 121 sqlite3_free(p.aBlob);122}123 124void test_jsonAfterEditSizeAdjust_grow_1byte_to_2byte(void){125 JsonParse p;126 const u8 eType = 0x07;127 const u32 initialSz = 255;128 const int initialDelta = 1; /* 255 -> 256 */129 make_single_node(&p, eType, initialSz, 64);130 131 u8 beforeExtra = extra_len_from_first(p.aBlob[0]);132 TEST_ASSERT_EQUAL_UINT8(1, beforeExtra);133 134 p.delta = initialDelta;135 test_jsonAfterEditSizeAdjust(&p, 0);136 137 u32 newSz = read_payload_size_from_header(p.aBlob);138 TEST_ASSERT_EQUAL_UINT32(256, newSz);139 140 u8 afterFirst = p.aBlob[0];141 TEST_ASSERT_EQUAL_UINT8(eType, afterFirst & 0x0F);142 u8 afterExtra = extra_len_from_first(afterFirst);143 TEST_ASSERT_EQUAL_UINT8(2, afterExtra);144 145 TEST_ASSERT_EQUAL_UINT32(header_size_for_payload(initialSz) + initialSz + (afterExtra - beforeExtra), p.nBlob);146 TEST_ASSERT_EQUAL_INT(initialDelta + (int)(afterExtra - beforeExtra), p.delta);147 148 sqlite3_free(p.aBlob);149}150 151void test_jsonAfterEditSizeAdjust_grow_2byte_to_4byte(void){152 JsonParse p;153 const u8 eType = 0x07;154 const u32 initialSz = 65535;155 const int initialDelta = 1; /* 65535 -> 65536 */156 make_single_node(&p, eType, initialSz, 64);157 158 u8 beforeExtra = extra_len_from_first(p.aBlob[0]);159 TEST_ASSERT_EQUAL_UINT8(2, beforeExtra);160 161 p.delta = initialDelta;162 test_jsonAfterEditSizeAdjust(&p, 0);163 164 u32 newSz = read_payload_size_from_header(p.aBlob);165 TEST_ASSERT_EQUAL_UINT32(65536, newSz);166 167 u8 afterFirst = p.aBlob[0];168 TEST_ASSERT_EQUAL_UINT8(eType, afterFirst & 0x0F);169 u8 afterExtra = extra_len_from_first(afterFirst);170 TEST_ASSERT_EQUAL_UINT8(4, afterExtra);171 172 TEST_ASSERT_EQUAL_UINT32(header_size_for_payload(initialSz) + initialSz + (afterExtra - beforeExtra), p.nBlob);173 TEST_ASSERT_EQUAL_INT(initialDelta + (int)(afterExtra - beforeExtra), p.delta);174 175 sqlite3_free(p.aBlob);176}177 178void test_jsonAfterEditSizeAdjust_shrink_1byte_to_inline(void){179 JsonParse p;180 const u8 eType = 0x07;181 const u32 initialSz = 12;182 const int initialDelta = -1; /* 12 -> 11 */183 make_single_node(&p, eType, initialSz, 32);184 185 u8 beforeExtra = extra_len_from_first(p.aBlob[0]);186 TEST_ASSERT_EQUAL_UINT8(1, beforeExtra);187 188 p.delta = initialDelta;189 test_jsonAfterEditSizeAdjust(&p, 0);190 191 u32 newSz = read_payload_size_from_header(p.aBlob);192 TEST_ASSERT_EQUAL_UINT32(11, newSz);193 194 u8 afterFirst = p.aBlob[0];195 TEST_ASSERT_EQUAL_UINT8(eType, (afterFirst & 0x0F));196 u8 afterExtra = extra_len_from_first(afterFirst);197 TEST_ASSERT_EQUAL_UINT8(0, afterExtra);198 199 TEST_ASSERT_EQUAL_UINT32(header_size_for_payload(initialSz) + initialSz + (afterExtra - beforeExtra), p.nBlob);200 TEST_ASSERT_EQUAL_INT(initialDelta + (int)(afterExtra - beforeExtra), p.delta);201 202 sqlite3_free(p.aBlob);203}204 205void test_jsonAfterEditSizeAdjust_shrink_2byte_to_1byte(void){206 JsonParse p;207 const u8 eType = 0x07;208 const u32 initialSz = 256;209 const int initialDelta = -1; /* 256 -> 255 */210 make_single_node(&p, eType, initialSz, 32);211 212 u8 beforeExtra = extra_len_from_first(p.aBlob[0]);213 TEST_ASSERT_EQUAL_UINT8(2, beforeExtra);214 215 p.delta = initialDelta;216 test_jsonAfterEditSizeAdjust(&p, 0);217 218 u32 newSz = read_payload_size_from_header(p.aBlob);219 TEST_ASSERT_EQUAL_UINT32(255, newSz);220 221 u8 afterFirst = p.aBlob[0];222 TEST_ASSERT_EQUAL_UINT8(eType, (afterFirst & 0x0F));223 u8 afterExtra = extra_len_from_first(afterFirst);224 TEST_ASSERT_EQUAL_UINT8(1, afterExtra);225 226 TEST_ASSERT_EQUAL_UINT32(header_size_for_payload(initialSz) + initialSz + (afterExtra - beforeExtra), p.nBlob);227 TEST_ASSERT_EQUAL_INT(initialDelta + (int)(afterExtra - beforeExtra), p.delta);228 229 sqlite3_free(p.aBlob);230}231 232void test_jsonAfterEditSizeAdjust_no_header_change(void){233 JsonParse p;234 const u8 eType = 0x07;235 const u32 initialSz = 100;236 const int initialDelta = 5; /* 100 -> 105 (both 1-byte sizes) */237 make_single_node(&p, eType, initialSz, 32);238 239 u8 beforeFirst = p.aBlob[0];240 u8 beforeExtra = extra_len_from_first(beforeFirst);241 TEST_ASSERT_EQUAL_UINT8(1, beforeExtra);242 243 u32 beforeBlob = p.nBlob;244 245 p.delta = initialDelta;246 test_jsonAfterEditSizeAdjust(&p, 0);247 248 u32 newSz = read_payload_size_from_header(p.aBlob);249 TEST_ASSERT_EQUAL_UINT32(105, newSz);250 251 u8 afterFirst = p.aBlob[0];252 TEST_ASSERT_EQUAL_UINT8(eType, (afterFirst & 0x0F));253 u8 afterExtra = extra_len_from_first(afterFirst);254 TEST_ASSERT_EQUAL_UINT8(beforeExtra, afterExtra);255 256 TEST_ASSERT_EQUAL_UINT32(beforeBlob, p.nBlob); /* no header size change */257 TEST_ASSERT_EQUAL_INT(initialDelta, p.delta); /* delta unchanged by header */258 259 sqlite3_free(p.aBlob);260}261 262/* main */263int main(void){264 UNITY_BEGIN();265 RUN_TEST(test_jsonAfterEditSizeAdjust_grow_inline_to_1byte);266 RUN_TEST(test_jsonAfterEditSizeAdjust_grow_1byte_to_2byte);267 RUN_TEST(test_jsonAfterEditSizeAdjust_grow_2byte_to_4byte);268 RUN_TEST(test_jsonAfterEditSizeAdjust_shrink_1byte_to_inline);269 RUN_TEST(test_jsonAfterEditSizeAdjust_shrink_2byte_to_1byte);270 RUN_TEST(test_jsonAfterEditSizeAdjust_no_header_change);271 return UNITY_END();272}