vlib/json2/decode_storage_test.v
Rama master · réplica de lectura del repositorio original.
module json2
fn test_decode_scratch_storage_spills_and_releases_on_errors() {
for count in [0, 1, 7, 8, 9, 31, 32, 33, 1024] {
values := []string{len: count, init: '"entry"'}
source := '[' + values.join(',') + ']'
decoded := decode[[]string](source)!
assert decoded == []string{len: count, init: 'entry'}
invalid := source[..source.len - 1] + ',]'
if _ := decode[[]string](invalid) {
assert false, invalid
}
assert decode[string]('"after error"')! == 'after error'
}
}
fn test_flat_metadata_survives_growth_and_tracks_nested_spans() {
document := '{"name":"entry","items":[true,false,null]}'
documents := []string{len: 2048, init: document}
source := '[' + documents.join(',') + ']'
mut decoder := Decoder{ json: source }
decoder.check_json_format()!
assert decoder.values_info.len == 1 + 8 * documents.len
assert decoder.values_info[0].length == source.len
assert decoder.values_info[1].length == document.len
assert decoder.next_value(1) == 9
assert decoder.next_value(5) == 9
assert decoder.next_value(0) == decoder.values_info.len
expected := [
ValueKind.array,
.object,
.string,
.string,
.string,
.array,
.boolean,
.boolean,
.null,
]
for index, kind in expected {
assert decoder.values_info[index].value_kind == kind
}
for value in decoder.values_info {
assert value.length > 0
assert value.position + value.length <= source.len
}
decoded := decode[Any](source)!
// Encoding sorts object names lexically; metadata still follows input order.
canonical := []string{len: documents.len, init: '{"items":[true,false,null],"name":"entry"}'}
assert encode(decoded) == '[' + canonical.join(',') + ']'
}
fn test_flat_metadata_discriminator_skips_nested_values() {
source := '{"nested":{"_type":"Wrong"},"_type":"Right"}'
mut decoder := Decoder{ json: source }
decoder.check_json_format()!
index := decoder.get_sumtype_type_field_idx(0)
assert index < decoder.values_info.len
assert decoder.decode_string_value(decoder.values_info[index])! == 'Right'
decoder.skip_current_value()
assert decoder.current_idx == decoder.values_info.len
}
fn test_decoded_values_own_borrowed_input_fragments() {
mut source := '{"key":42,"escaped\\tkey":"a\\tb","plain":"text"}'.clone()
decoded := decode[map[string]Any](source)!
unsafe { source.free() }
assert (decoded['key'] or { panic('missing key') }) == Any(f64(42))
assert (decoded['escaped\tkey'] or { panic('missing key') }) == Any('a\tb')
assert (decoded['plain'] or { panic('missing key') }) == Any('text')
}
fn test_escaped_strings_survive_scratch_release() {
inputs := ['"plain"', '"line\\nend"', '"\\u4e16\\u754c"', '"\\uD83D\\uDE00"']
expected := ['plain', 'line\nend', '世界', '😀']
mut actual := []string{}
for input in inputs {
mut source := input.clone()
actual << decode[string](source)!
unsafe { source.free() }
}
for _ in 0 .. 100 {
assert decode[string]('"replacement\\ntext"')! == 'replacement\ntext'
}
assert actual == expected
}
fn test_encoded_output_survives_builder_release_and_reuse() {
item := 'text\n世界'.repeat(1024)
values := [item, item, item]
first := encode(values)
second := encode(['other'.repeat(8192)])
assert decode[[]string](first)! == values
assert decode[[]string](second)! == ['other'.repeat(8192)]
}
fn test_integer_encoding_preserves_signed_and_unsigned_limits() {
signed := [i64(-9223372036854775807) - 1, -1, 0, 9223372036854775807]
unsigned := [u64(0), 9223372036854775808, 18446744073709551615]
expected_signed := '[-9223372036854775808,-1,0,9223372036854775807]'
expected_unsigned := '[0,9223372036854775808,18446744073709551615]'
assert encode(signed) == expected_signed
assert encode(unsigned) == expected_unsigned
assert decode[[]i64](expected_signed)! == signed
assert decode[[]u64](expected_unsigned)! == unsigned
}
fn test_decoded_array_supports_slices_after_growth() {
source := '[' + []string{len: 4096, init: '42'}.join(',') + ']'
mut decoded := decode[[]Any](source)!
prefix := unsafe { decoded[..2] }
assert prefix.data == decoded.data
for _ in 0 .. 8192 {
decoded << Any('later')
}
assert prefix == [Any(f64(42)), Any(f64(42))]
assert decoded.len == 12288
assert decoded.last() == Any('later')
}
struct ArrayDefault {
mut:
value int = 42
name string = 'default'
items []int = [1]
table map[string]int = {
'count': 1
}
}
fn test_array_storage_preserves_element_defaults() {
mut values := decode[[]ArrayDefault]('[{}, {"value":7}]')!
assert values == [ArrayDefault{}, ArrayDefault{ value: 7 }]
values[0].items << 2
values[0].table['count'] = 2
assert values[1].items == [1]
assert values[1].table['count'] == 1
assert decode[[][]int]('[[],[1,2],[],[3]]')! == [[], [1, 2], [], [3]]
assert decode[[]?int]('[null,7,null]')! == [?int(none), ?int(7), ?int(none)]
assert decode[[]Any]('[]')!.len == 0
}
fn test_container_counts_and_skips_match_nested_boundaries() {
source := '[{},[],{"a":[1,{"b":[]}]},true,null,"[}"]'
mut decoder := Decoder{ json: source }
decoder.check_json_format()!
expected := [1, 2, 3, 10, 11, 12]
mut next := 1
for index in expected {
assert next == index
next = decoder.next_value(next)
}
assert next == decoder.values_info.len
assert decoder.container_len(0) == 6
assert decoder.container_len(1) == 0
assert decoder.container_len(2) == 0
assert decoder.container_len(3) == 1
assert decoder.container_len(5) == 2
assert decoder.next_value(0) == decoder.values_info.len
}
fn test_reserved_maps_keep_duplicates_and_allow_later_mutation() {
mut values := decode[map[string]Any]('{"a":1,"a":2,"b":[3]}')!
assert values.len == 2
assert (values['a'] or { panic('missing key') }) == Any(f64(2))
for key in ['c', 'd', 'e', 'f', 'g', 'h', 'i'] {
values[key] = key
}
values.delete('a')
values['j'] = 'j'
assert values.len == 9
assert (values['j'] or { panic('missing key') }) == Any('j')
assert (values['b'] or { panic('missing key') }) == Any([Any(f64(3))])
}
type StorageIntegerKey = int
type StorageStringKey = string
fn test_decoded_map_keys_follow_the_declared_type() {
integers := decode[map[int]string]('{"42":"answer","-7":"negative"}')!
assert integers[42] == 'answer'
assert integers[-7] == 'negative'
unsigned := decode[map[u64]int]('{"18446744073709551615":7}')!
assert unsigned[u64(18446744073709551615)] == 7
aliases := decode[map[StorageIntegerKey]int]('{"3":5}')!
assert aliases[StorageIntegerKey(3)] == 5
strings := decode[map[StorageStringKey]int]('{"name":9}')!
assert strings[StorageStringKey('name')] == 9
runes := decode[map[rune]int]('{"a":11,"世":13,"🙂":17,"1":19}')!
assert runes[`a`] == 11
assert runes[`世`] == 13
assert runes[`🙂`] == 17
assert runes[`1`] == 19
assert decode[map[rune]int](encode(runes))! == runes
values := decode[map[int]?int]('{"2":null,"3":4}')!
assert values[2] == none
assert values[3] == ?int(4)
}
fn test_decoded_map_keys_reject_out_of_range_and_multiple_runes() {
if _ := decode[map[u8]int]('{"256":1}') {
assert false
}
if _ := decode[map[rune]int]('{"ab":1}') {
assert false
}
}