summaryrefslogtreecommitdiff
path: root/encoding/json/+test/test_load.ha
blob: bf53777427fd69b30786a7b49c82fe7a7219c83d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
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);
};