vlib/json2/json5_lifetime_test.v
Rama master · réplica de lectura del repositorio original.
module json2
import os
struct Json5BorrowedStrings {
name string
items []string
object_text string
raw string @[raw]
}
struct Json5RetainedStringHook {
mut:
text string
}
fn (mut value Json5RetainedStringHook) from_json_string(text string) ! {
value.text = text
}
struct Json5RetainedNumberHook {
mut:
text string
}
fn (mut value Json5RetainedNumberHook) from_json_number(text string) ! {
value.text = text
}
fn test_json5_returned_strings_survive_allocations_and_buffer_reuse() {
mut buffer := DecodeBuffer{}
root := decode[string]("'root string'", json5: true)!
fields := decode_reuse[Json5BorrowedStrings]("{name:'field string',items:['array string'],object_text:{key:'object string'},raw:{key:'raw string'}}",
mut buffer,
json5: true
)!
values := decode[map[string]string]("{'map key':'map value'}", json5: true)!
dynamic := decode[Any]("{bareKey:'dynamic string'}", json5: true)!
dynamic_root := decode[Any]("'dynamic root string'", json5: true)!
escaped := decode[string]("'escaped\\nstring'", json5: true)!
string_hook := decode[Json5RetainedStringHook]("'hook string'", json5: true)!
number_hook := decode[Json5RetainedNumberHook]('0x1234', json5: true)!
mut allocations := [][]u8{}
for i in 0 .. 256 {
// Occupy freed parser allocations of different sizes and repeatedly reuse tokens.
allocations << []u8{len: 16 + i, init: u8(i)}
next := decode_reuse[Json5BorrowedStrings]("{name:'replacement',items:['other'],object_text:{key:'other'},raw:{key:'other'}}",
mut buffer,
json5: true
)!
assert next.name == 'replacement'
}
assert allocations.len == 256
assert root == 'root string'
assert fields.name == 'field string'
assert fields.items == ['array string']
assert fields.object_text == '{"key":"object string"}'
assert fields.raw == '{"key":"raw string"}'
assert values.keys() == ['map key']
assert values['map key'] == 'map value'
assert dynamic.as_map().keys() == ['bareKey']
assert (dynamic.as_map()['bareKey'] or { panic('missing key') }).str() == 'dynamic string'
assert dynamic_root.str() == 'dynamic root string'
assert escaped == 'escaped\nstring'
assert string_hook.text == 'hook string'
assert number_hook.text == '0x1234'
}
@[manualfree]
fn test_file_decoding_returns_owned_strings_in_both_dialects() {
for json5 in [false, true] {
path := os.join_path(os.temp_dir(), 'json2_file_lifetime_${os.getpid()}_${json5}.json')
defer { os.rm(path) or {} }
os.write_file(path, '"root string"')!
root := decode_file[string](path, json5: json5)!
dynamic_root := parse_file(path, json5: json5)!
string_hook := decode_file[Json5RetainedStringHook](path, json5: json5)!
os.write_file(path, '{"name":"field string","items":["array string"],"object_text":{"key":"object string"},"raw":{"key":"raw string"}}')!
fields := decode_file[Json5BorrowedStrings](path, json5: json5)!
dynamic := parse_file(path, json5: json5)!
os.write_file(path, '{"map key":"map value"}')!
values := decode_file[map[string]string](path, json5: json5)!
os.write_file(path, '4660')!
number_hook := decode_file[Json5RetainedNumberHook](path, json5: json5)!
mut allocations := [][]u8{}
for i in 0 .. 256 {
allocations << []u8{len: 16 + i, init: u8(i)}
}
assert allocations.len == 256
assert root == 'root string'
assert dynamic_root.root.str() == 'root string'
assert string_hook.text == 'root string'
assert fields.name == 'field string'
assert fields.items == ['array string']
assert fields.object_text == '{"key":"object string"}'
assert fields.raw == '{"key":"raw string"}'
assert (dynamic.root.as_map()['name'] or { panic('missing name') }).str() == 'field string'
assert values.keys() == ['map key']
assert values['map key'] == 'map value'
assert number_hook.text == '4660'
}
}
@[manualfree]
fn test_file_decoding_returns_owned_scalar_strings_in_both_dialects() {
for json5 in [false, true] {
path := os.join_path(os.temp_dir(), 'json2_file_scalar_lifetime_${os.getpid()}_${json5}.json')
defer { os.rm(path) or {} }
os.write_file(path, '"root string"')!
root := decode_file[string](path, json5: json5)!
doc := parse_file(path, json5: json5)!
os.write_file(path, '"replacement"')!
for _ in 0 .. 256 {
other := decode_file[string](path, json5: json5)!
assert other == 'replacement'
unsafe { other.free() }
}
assert root == 'root string'
assert doc.root.str() == 'root string'
}
}