165 lines
4.9 KiB
Hare
165 lines
4.9 KiB
Hare
|
use fmt;
|
||
|
|
||
|
fn roundtrip(input: str, expected: value) void = {
|
||
|
const val = loadstr(input)!;
|
||
|
defer finish(val);
|
||
|
assert(equal(val, expected));
|
||
|
const s = dumpstr(val);
|
||
|
defer free(s);
|
||
|
const val = loadstr(s)!;
|
||
|
defer finish(val);
|
||
|
assert(equal(val, expected));
|
||
|
};
|
||
|
|
||
|
fn errassert(input: str, expected_loc: (uint, uint)) void = {
|
||
|
const loc = loadstr(input) as invalid;
|
||
|
if (loc.0 != expected_loc.0 || loc.1 != expected_loc.1) {
|
||
|
fmt::errorfln("=== JSON:\n{}", input)!;
|
||
|
fmt::errorfln("=== expected error location:\n({}, {})",
|
||
|
expected_loc.0, expected_loc.1)!;
|
||
|
fmt::errorfln("=== actual error location:\n({}, {})",
|
||
|
loc.0, loc.1)!;
|
||
|
abort();
|
||
|
};
|
||
|
};
|
||
|
|
||
|
@test fn load() void = {
|
||
|
let obj = newobject();
|
||
|
defer finish(obj);
|
||
|
let obj2 = newobject();
|
||
|
defer finish(obj2);
|
||
|
|
||
|
roundtrip(`1234`, 1234.0);
|
||
|
roundtrip(`[]`, []);
|
||
|
roundtrip(`[1, 2, 3, null]`, [1.0, 2.0, 3.0, _null]);
|
||
|
roundtrip(`{}`, obj);
|
||
|
set(&obj, "hello", "world");
|
||
|
set(&obj, "answer", 42.0);
|
||
|
roundtrip(`{ "hello": "world", "answer": 42 }`, obj);
|
||
|
reset(&obj);
|
||
|
roundtrip(`[[] ]`, [[]]);
|
||
|
roundtrip(`[""]`, [""]);
|
||
|
roundtrip(`["a"]`, ["a"]);
|
||
|
roundtrip(`[false]`, [false]);
|
||
|
roundtrip(`[null, 1, "1", {}]`, [_null, 1.0, "1", obj]);
|
||
|
roundtrip(`[null]`, [_null]);
|
||
|
roundtrip("[1\n]", [1.0]);
|
||
|
roundtrip(`[1,null,null,null,2]`, [1.0, _null, _null, _null, 2.0]);
|
||
|
set(&obj, "", 0.0);
|
||
|
roundtrip(`{"":0}`, obj);
|
||
|
reset(&obj);
|
||
|
set(&obj, "foo\0bar", 42.0);
|
||
|
roundtrip(`{"foo\u0000bar": 42}`, obj);
|
||
|
reset(&obj);
|
||
|
set(&obj, "min", -1.0e+28);
|
||
|
set(&obj, "max", 1.0e+28);
|
||
|
roundtrip(`{"min": -1.0e+28, "max": 1.0e+28}`, obj);
|
||
|
reset(&obj);
|
||
|
set(&obj, "id", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
|
||
|
set(&obj2, "id", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
|
||
|
set(&obj, "x", [obj2]);
|
||
|
roundtrip(`{"x":[{"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}], "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}`, obj);
|
||
|
reset(&obj);
|
||
|
reset(&obj2);
|
||
|
set(&obj, "a", []);
|
||
|
roundtrip(`{"a":[]}`, obj);
|
||
|
roundtrip("{\n" `"a": []` "\n}", obj);
|
||
|
reset(&obj);
|
||
|
roundtrip(`"\u0060\u012a\u12AB"`, "\u0060\u012a\u12AB");
|
||
|
roundtrip(`"\"\\\/\b\f\n\r\t"`, "\"\\/\b\f\n\r\t");
|
||
|
roundtrip(`"\\u0000"`, `\u0000`);
|
||
|
roundtrip(`"\""`, `"`);
|
||
|
roundtrip(`"a/*b*/c/*d//e"`, "a/*b*/c/*d//e");
|
||
|
roundtrip(`"\\a"`, `\a`);
|
||
|
roundtrip(`"\\n"`, `\n`);
|
||
|
roundtrip(`"\u0012"`, "\u0012");
|
||
|
roundtrip(`[ "asd"]`, ["asd"]);
|
||
|
roundtrip(`"new\u000Aline"`, "new\nline");
|
||
|
roundtrip(`"\u0000"`, "\0");
|
||
|
roundtrip(`"\u002c"`, "\u002c");
|
||
|
roundtrip(`"asd "`, "asd ");
|
||
|
roundtrip(`" "`, " ");
|
||
|
roundtrip(`"\u0821"`, "\u0821");
|
||
|
roundtrip(`"\u0123"`, "\u0123");
|
||
|
roundtrip(`"\u0061\u30af\u30EA\u30b9"`, "\u0061\u30af\u30EA\u30b9");
|
||
|
roundtrip(`"\uA66D"`, "\uA66D");
|
||
|
roundtrip(`"\u005C"`, `\`);
|
||
|
roundtrip(`"\u0022"`, `"`);
|
||
|
roundtrip(`""`, "");
|
||
|
roundtrip(` [] `, []);
|
||
|
|
||
|
errassert(`[1,,]`, (1, 4));
|
||
|
errassert(`[1 true]`, (1, 7));
|
||
|
errassert(`["": 1]`, (1, 4));
|
||
|
errassert(`[,1]`, (1, 2));
|
||
|
errassert(`[1,,2]`, (1, 4));
|
||
|
errassert(`["",]`, (1, 5));
|
||
|
errassert(`["x"`, (1, 5));
|
||
|
errassert(`[x`, (1, 2));
|
||
|
errassert(`[3[4]]`, (1, 3));
|
||
|
errassert(`[1:2]`, (1, 3));
|
||
|
errassert(`[,]`, (1, 2));
|
||
|
errassert(`[-]`, (1, 3));
|
||
|
errassert(`[ , ""]`, (1, 5));
|
||
|
errassert("[\"a\",\n4\n,1,", (3, 4));
|
||
|
errassert(`[1,]`, (1, 4));
|
||
|
errassert("[\"\va\"\\f", (1, 3));
|
||
|
errassert(`[*]`, (1, 2));
|
||
|
errassert(`[1,`, (1, 4));
|
||
|
errassert("[1,\n1\n,1", (3, 3));
|
||
|
errassert(`[{}`, (1, 4));
|
||
|
errassert(`["x", truth]`, (1, 11));
|
||
|
errassert(`{[: "x"}`, (1, 2));
|
||
|
errassert(`{"x", null}`, (1, 5));
|
||
|
errassert(`{"x"::"b"}`, (1, 6));
|
||
|
errassert(`{"a":"a" 123}`, (1, 12));
|
||
|
errassert(`{"a" b}`, (1, 6));
|
||
|
errassert(`{:"b"}`, (1, 2));
|
||
|
errassert(`{"a" "b"}`, (1, 8));
|
||
|
errassert(`{"a":`, (1, 6));
|
||
|
errassert(`{"a"`, (1, 5));
|
||
|
errassert(`{1:1}`, (1, 2));
|
||
|
errassert(`{9999E9999:1}`, (1, 10));
|
||
|
errassert(`{null:null,null:null}`, (1, 5));
|
||
|
errassert(`{"id":0,,,,,}`, (1, 9));
|
||
|
errassert(`{'a':0}`, (1, 2));
|
||
|
errassert(`{"id":0,}`, (1, 9));
|
||
|
errassert(`{"a":"b",,"c":"d"}`, (1, 10));
|
||
|
errassert(`{true: false}`, (1, 5));
|
||
|
errassert(`{"a":"a`, (1, 8));
|
||
|
errassert(`{ "foo" : "bar", "a" }`, (1, 22));
|
||
|
errassert(` `, (1, 2));
|
||
|
errassert(`<null>`, (1, 1));
|
||
|
errassert(`["asd]`, (1, 7));
|
||
|
errassert(`True`, (1, 4));
|
||
|
errassert(`]`, (1, 1));
|
||
|
errassert(`}`, (1, 1));
|
||
|
errassert(`{"x": true,`, (1, 12));
|
||
|
errassert(`[`, (1, 2));
|
||
|
errassert(`{`, (1, 2));
|
||
|
errassert(``, (1, 1));
|
||
|
errassert("\0", (1, 1));
|
||
|
errassert(`{"":`, (1, 5));
|
||
|
errassert(`['`, (1, 2));
|
||
|
errassert(`["`, (1, 3));
|
||
|
errassert(`[,`, (1, 2));
|
||
|
errassert(`[{`, (1, 3));
|
||
|
errassert(`{[`, (1, 2));
|
||
|
errassert(`{]`, (1, 2));
|
||
|
errassert(`[}`, (1, 2));
|
||
|
errassert(`{'`, (1, 2));
|
||
|
errassert(`{"`, (1, 3));
|
||
|
errassert(`{,`, (1, 2));
|
||
|
errassert(`["\{["\{["\{["\{`, (1, 4));
|
||
|
errassert(`*`, (1, 1));
|
||
|
errassert(`\u000A""`, (1, 1));
|
||
|
errassert("\f", (1, 1));
|
||
|
};
|
||
|
|
||
|
@test fn nestlimit() void = {
|
||
|
const s = `{ "foo": [[[{"bar": ["baz"]}]]] }`;
|
||
|
const val = loadstr(s, 6: nestlimit)!;
|
||
|
finish(val);
|
||
|
assert(loadstr(s, 5: nestlimit) is limitreached);
|
||
|
};
|