Line data Source code
1 : // Copyright (c) 2021-2022 Made to Order Software Corporation
2 : //
3 : // https://snapwebsites.org/project/libutf8
4 : // contact@m2osw.com
5 : //
6 : // This program is free software; you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation; either version 2 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License along
17 : // with this program; if not, write to the Free Software Foundation, Inc.,
18 : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 :
20 : // unit test
21 : //
22 : #include "catch_main.h"
23 :
24 :
25 : // libutf8 lib
26 : //
27 : #include "libutf8/json_tokens.h"
28 : #include "libutf8/libutf8.h"
29 :
30 :
31 : // last include
32 : //
33 : #include <snapdev/file_contents.h>
34 :
35 :
36 : // C++ lib
37 : //
38 : #include <cctype>
39 : #include <iomanip>
40 : #include <iostream>
41 :
42 :
43 : // last include
44 : //
45 : #include <snapdev/poison.h>
46 :
47 :
48 :
49 : #pragma GCC diagnostic push
50 : #pragma GCC diagnostic ignored "-Wfloat-equal"
51 6 : CATCH_TEST_CASE("json_tokens", "[json][iterator]")
52 : {
53 8 : CATCH_START_SECTION("valid JSON tokens")
54 : {
55 1 : std::string valid_json(
56 : "{\n"
57 : "\"array-of-numbers\": [\n"
58 : "\t1,\r\n"
59 : "\t1.0,\r"
60 : "\t-0.1\r\n"
61 : "] , \n"
62 : "\"color\" :true ,\n"
63 : "\"temporary\" :false, \r"
64 : "\"flowers\":null\r\n"
65 : "}"
66 2 : );
67 :
68 : #if 0
69 : snap::file_contents f("test.json");
70 : f.contents(valid_json);
71 : f.write_all();
72 : #endif
73 :
74 2 : libutf8::json_tokens jt(valid_json);
75 1 : CATCH_REQUIRE(jt.line() == 0);
76 1 : CATCH_REQUIRE(jt.column() == 0);
77 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_OPEN_OBJECT);
78 1 : CATCH_REQUIRE(jt.line() == 1);
79 1 : CATCH_REQUIRE(jt.column() == 1);
80 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
81 1 : CATCH_REQUIRE(jt.string() == "array-of-numbers");
82 1 : CATCH_REQUIRE(jt.line() == 2);
83 1 : CATCH_REQUIRE(jt.column() == 1);
84 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COLON);
85 1 : CATCH_REQUIRE(jt.line() == 2);
86 1 : CATCH_REQUIRE(jt.column() == 19);
87 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_OPEN_ARRAY);
88 1 : CATCH_REQUIRE(jt.line() == 2);
89 1 : CATCH_REQUIRE(jt.column() == 21);
90 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_NUMBER);
91 1 : CATCH_REQUIRE(jt.number() == 1.0_a);
92 1 : CATCH_REQUIRE(jt.line() == 3);
93 1 : CATCH_REQUIRE(jt.column() == 2);
94 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COMMA);
95 1 : CATCH_REQUIRE(jt.line() == 3);
96 1 : CATCH_REQUIRE(jt.column() == 3 + 1); // error due to the unget
97 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_NUMBER);
98 1 : CATCH_REQUIRE(jt.number() == 1.0_a);
99 1 : CATCH_REQUIRE(jt.line() == 4);
100 1 : CATCH_REQUIRE(jt.column() == 2);
101 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COMMA);
102 1 : CATCH_REQUIRE(jt.line() == 4);
103 1 : CATCH_REQUIRE(jt.column() == 5 + 1); // error due to the unget
104 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_NUMBER);
105 1 : CATCH_REQUIRE(jt.number() == -0.1_a);
106 1 : CATCH_REQUIRE(jt.line() == 5);
107 1 : CATCH_REQUIRE(jt.column() == 2);
108 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_CLOSE_ARRAY);
109 1 : CATCH_REQUIRE(jt.line() == 6);
110 1 : CATCH_REQUIRE(jt.column() == 1);
111 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COMMA);
112 1 : CATCH_REQUIRE(jt.line() == 6);
113 1 : CATCH_REQUIRE(jt.column() == 5);
114 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
115 1 : CATCH_REQUIRE(jt.string() == "color");
116 1 : CATCH_REQUIRE(jt.line() == 7);
117 1 : CATCH_REQUIRE(jt.column() == 1);
118 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COLON);
119 1 : CATCH_REQUIRE(jt.line() == 7);
120 1 : CATCH_REQUIRE(jt.column() == 14);
121 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_TRUE);
122 1 : CATCH_REQUIRE(jt.line() == 7);
123 1 : CATCH_REQUIRE(jt.column() == 15);
124 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COMMA);
125 1 : CATCH_REQUIRE(jt.line() == 7);
126 1 : CATCH_REQUIRE(jt.column() == 21);
127 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
128 1 : CATCH_REQUIRE(jt.string() == "temporary");
129 1 : CATCH_REQUIRE(jt.line() == 8);
130 1 : CATCH_REQUIRE(jt.column() == 1);
131 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COLON);
132 1 : CATCH_REQUIRE(jt.line() == 8);
133 1 : CATCH_REQUIRE(jt.column() == 14);
134 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_FALSE);
135 1 : CATCH_REQUIRE(jt.line() == 8);
136 1 : CATCH_REQUIRE(jt.column() == 15);
137 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COMMA);
138 1 : CATCH_REQUIRE(jt.line() == 8);
139 1 : CATCH_REQUIRE(jt.column() == 20);
140 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
141 1 : CATCH_REQUIRE(jt.string() == "flowers");
142 1 : CATCH_REQUIRE(jt.line() == 9);
143 1 : CATCH_REQUIRE(jt.column() == 1);
144 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COLON);
145 1 : CATCH_REQUIRE(jt.line() == 9);
146 1 : CATCH_REQUIRE(jt.column() == 10);
147 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_NULL);
148 1 : CATCH_REQUIRE(jt.line() == 9);
149 1 : CATCH_REQUIRE(jt.column() == 11);
150 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_CLOSE_OBJECT);
151 1 : CATCH_REQUIRE(jt.line() == 10);
152 1 : CATCH_REQUIRE(jt.column() == 1);
153 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_END);
154 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_END);
155 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_END);
156 : }
157 : CATCH_END_SECTION()
158 :
159 8 : CATCH_START_SECTION("valid JSON numbers")
160 : {
161 1 : std::string valid_json(
162 : "["
163 : "733,"
164 : "-1892,"
165 : "-1.892,"
166 : "-9.892e33,"
167 : "101.302e+3,"
168 : "5031.70232e-13"
169 : "]"
170 2 : );
171 :
172 2 : libutf8::json_tokens jt(valid_json);
173 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_OPEN_ARRAY);
174 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_NUMBER);
175 1 : CATCH_REQUIRE_FLOATING_POINT(jt.number(), 733.0);
176 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COMMA);
177 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_NUMBER);
178 1 : CATCH_REQUIRE_FLOATING_POINT(jt.number(), -1892.0);
179 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COMMA);
180 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_NUMBER);
181 1 : CATCH_REQUIRE_FLOATING_POINT(jt.number(), -1.892);
182 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COMMA);
183 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_NUMBER);
184 1 : CATCH_REQUIRE_FLOATING_POINT(jt.number(), -9.892e33);
185 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COMMA);
186 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_NUMBER);
187 1 : CATCH_REQUIRE_FLOATING_POINT(jt.number(), 101.302e3);
188 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COMMA);
189 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_NUMBER);
190 1 : CATCH_REQUIRE_FLOATING_POINT(jt.number(), 5031.70232e-13);
191 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_CLOSE_ARRAY);
192 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_END);
193 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_END);
194 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_END);
195 : }
196 : CATCH_END_SECTION()
197 :
198 8 : CATCH_START_SECTION("valid JSON special escaped characters")
199 : {
200 1 : std::string valid_json(
201 : "{"
202 : "\"backslash\":\"\\\\\","
203 : "\"quote\":\"\\\"\","
204 : "\"slash\":\"\\/\","
205 : "\"backspace\":\"\\b\","
206 : "\"formfeed\":\"\\f\","
207 : "\"newline\":\"\\n\","
208 : "\"carriage-return\":\"\\r\","
209 : "\"tab\":\"\\t\""
210 : "}"
211 2 : );
212 :
213 2 : libutf8::json_tokens jt(valid_json);
214 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_OPEN_OBJECT);
215 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
216 1 : CATCH_REQUIRE(jt.string() == "backslash");
217 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COLON);
218 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
219 1 : CATCH_REQUIRE(jt.string() == "\\");
220 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COMMA);
221 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
222 1 : CATCH_REQUIRE(jt.string() == "quote");
223 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COLON);
224 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
225 1 : CATCH_REQUIRE(jt.string() == "\"");
226 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COMMA);
227 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
228 1 : CATCH_REQUIRE(jt.string() == "slash");
229 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COLON);
230 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
231 1 : CATCH_REQUIRE(jt.string() == "/");
232 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COMMA);
233 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
234 1 : CATCH_REQUIRE(jt.string() == "backspace");
235 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COLON);
236 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
237 1 : CATCH_REQUIRE(jt.string() == "\b");
238 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COMMA);
239 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
240 1 : CATCH_REQUIRE(jt.string() == "formfeed");
241 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COLON);
242 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
243 1 : CATCH_REQUIRE(jt.string() == "\f");
244 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COMMA);
245 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
246 1 : CATCH_REQUIRE(jt.string() == "newline");
247 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COLON);
248 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
249 1 : CATCH_REQUIRE(jt.string() == "\n");
250 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COMMA);
251 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
252 1 : CATCH_REQUIRE(jt.string() == "carriage-return");
253 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COLON);
254 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
255 1 : CATCH_REQUIRE(jt.string() == "\r");
256 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COMMA);
257 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
258 1 : CATCH_REQUIRE(jt.string() == "tab");
259 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COLON);
260 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
261 1 : CATCH_REQUIRE(jt.string() == "\t");
262 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_CLOSE_OBJECT);
263 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_END);
264 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_END);
265 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_END);
266 : }
267 : CATCH_END_SECTION()
268 :
269 8 : CATCH_START_SECTION("valid JSON unicode escaped characters")
270 : {
271 1114112 : for(char32_t c(1); c < 0x110000; ++c)
272 : {
273 1114111 : if(c >= 0xD800 && c <= 0xDFFF)
274 : {
275 2048 : continue;
276 : }
277 :
278 2224126 : std::stringstream ss;
279 2224126 : std::string valid_json;
280 1112063 : valid_json += "{\"unicode\":\"\\u";
281 1112063 : if(c > 0xFFFF)
282 : {
283 1048576 : int s(c - 0x10000);
284 1048576 : ss << std::hex << std::setw(4) << std::setfill('0') << ((s >> 10) | 0xD800)
285 1048576 : << "\\u" << std::setw(4) << std::setfill('0') << ((s & 0x3FF) | 0xDC00);
286 : }
287 : else
288 : {
289 63487 : ss << std::hex << std::setw(4) << std::setfill('0') << static_cast<int>(c);
290 : }
291 1112063 : valid_json += ss.str();
292 1112063 : valid_json += "\"}";
293 :
294 2224126 : libutf8::json_tokens jt(valid_json);
295 1112063 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_OPEN_OBJECT);
296 1112063 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
297 1112063 : CATCH_REQUIRE(jt.string() == "unicode");
298 1112063 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COLON);
299 1112063 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
300 2224126 : std::string expected(libutf8::to_u8string(c));
301 1112063 : CATCH_REQUIRE_LONG_STRING(jt.string(), expected);
302 1112063 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_CLOSE_OBJECT);
303 1112063 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_END);
304 1112063 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_END);
305 1112063 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_END);
306 : }
307 : }
308 : CATCH_END_SECTION()
309 4 : }
310 : #pragma GCC diagnostic pop
311 :
312 :
313 22 : CATCH_TEST_CASE("json_tokens_invalid", "[json][iterator][invalid]")
314 : {
315 40 : CATCH_START_SECTION("invalid JSON negative number")
316 : {
317 1 : std::string valid_json(
318 : "-a"
319 2 : );
320 :
321 2 : libutf8::json_tokens jt(valid_json);
322 1 : CATCH_REQUIRE(jt.line() == 0);
323 1 : CATCH_REQUIRE(jt.column() == 0);
324 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
325 1 : CATCH_REQUIRE(jt.line() == 1);
326 1 : CATCH_REQUIRE(jt.column() == 1);
327 1 : CATCH_REQUIRE(jt.error() == "found unexpected character: '-'");
328 : }
329 : CATCH_END_SECTION()
330 :
331 40 : CATCH_START_SECTION("invalid JSON number with fraction")
332 : {
333 1 : std::string valid_json(
334 : "-3., 2."
335 2 : );
336 :
337 2 : libutf8::json_tokens jt(valid_json);
338 1 : CATCH_REQUIRE(jt.line() == 0);
339 1 : CATCH_REQUIRE(jt.column() == 0);
340 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
341 1 : CATCH_REQUIRE(jt.line() == 1);
342 1 : CATCH_REQUIRE(jt.column() == 1);
343 1 : CATCH_REQUIRE(jt.error() == "number cannot end with a period (\"1.\" is not valid JSON)");
344 : }
345 : CATCH_END_SECTION()
346 :
347 40 : CATCH_START_SECTION("invalid JSON number exponent")
348 : {
349 1 : std::string valid_json(
350 : "-3.0e+a, 2.1"
351 2 : );
352 :
353 2 : libutf8::json_tokens jt(valid_json);
354 1 : CATCH_REQUIRE(jt.line() == 0);
355 1 : CATCH_REQUIRE(jt.column() == 0);
356 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
357 1 : CATCH_REQUIRE(jt.line() == 1);
358 1 : CATCH_REQUIRE(jt.column() == 1);
359 1 : CATCH_REQUIRE(jt.error() == "number exponent must include at least one digit");
360 : }
361 : CATCH_END_SECTION()
362 :
363 40 : CATCH_START_SECTION("invalid JSON number with fraction")
364 : {
365 1 : std::string valid_json(
366 : "\"back\\slash\""
367 2 : );
368 :
369 2 : libutf8::json_tokens jt(valid_json);
370 1 : CATCH_REQUIRE(jt.line() == 0);
371 1 : CATCH_REQUIRE(jt.column() == 0);
372 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
373 1 : CATCH_REQUIRE(jt.line() == 1);
374 1 : CATCH_REQUIRE(jt.column() == 1);
375 1 : CATCH_REQUIRE(jt.error() == "unexpected escape character: 's'");
376 : }
377 : CATCH_END_SECTION()
378 :
379 40 : CATCH_START_SECTION("unsupported JSON backslash character")
380 : {
381 : {
382 1 : std::string valid_json(
383 : "\"back\\slash\""
384 2 : );
385 :
386 2 : libutf8::json_tokens jt(valid_json);
387 1 : CATCH_REQUIRE(jt.line() == 0);
388 1 : CATCH_REQUIRE(jt.column() == 0);
389 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
390 1 : CATCH_REQUIRE(jt.line() == 1);
391 1 : CATCH_REQUIRE(jt.column() == 1);
392 1 : CATCH_REQUIRE(jt.error() == "unexpected escape character: 's'");
393 : }
394 :
395 : }
396 : CATCH_END_SECTION()
397 :
398 40 : CATCH_START_SECTION("invalid JSON unicode: too short")
399 : {
400 : {
401 1 : std::string valid_json(
402 : "\"\\u0"
403 2 : );
404 :
405 2 : libutf8::json_tokens jt(valid_json);
406 1 : CATCH_REQUIRE(jt.line() == 0);
407 1 : CATCH_REQUIRE(jt.column() == 0);
408 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
409 1 : CATCH_REQUIRE(jt.line() == 1);
410 1 : CATCH_REQUIRE(jt.column() == 1);
411 1 : CATCH_REQUIRE(jt.error() == "invalid unicode character: 'EOS'");
412 : }
413 :
414 : {
415 1 : std::string valid_json(
416 : "\"\\u20"
417 2 : );
418 :
419 2 : libutf8::json_tokens jt(valid_json);
420 1 : CATCH_REQUIRE(jt.line() == 0);
421 1 : CATCH_REQUIRE(jt.column() == 0);
422 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
423 1 : CATCH_REQUIRE(jt.line() == 1);
424 1 : CATCH_REQUIRE(jt.column() == 1);
425 1 : CATCH_REQUIRE(jt.error() == "invalid unicode character: 'EOS'");
426 : }
427 :
428 : {
429 1 : std::string valid_json(
430 : "\"\\u301"
431 2 : );
432 :
433 2 : libutf8::json_tokens jt(valid_json);
434 1 : CATCH_REQUIRE(jt.line() == 0);
435 1 : CATCH_REQUIRE(jt.column() == 0);
436 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
437 1 : CATCH_REQUIRE(jt.line() == 1);
438 1 : CATCH_REQUIRE(jt.column() == 1);
439 1 : CATCH_REQUIRE(jt.error() == "invalid unicode character: 'EOS'");
440 : }
441 :
442 : }
443 : CATCH_END_SECTION()
444 :
445 40 : CATCH_START_SECTION("invalid JSON unicode: low surrogate missing backslash")
446 : {
447 1 : std::string valid_json(
448 : "\"\\uD91Fmissing\""
449 2 : );
450 :
451 2 : libutf8::json_tokens jt(valid_json);
452 1 : CATCH_REQUIRE(jt.line() == 0);
453 1 : CATCH_REQUIRE(jt.column() == 0);
454 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
455 1 : CATCH_REQUIRE(jt.line() == 1);
456 1 : CATCH_REQUIRE(jt.column() == 1);
457 1 : CATCH_REQUIRE(jt.error() == "expected a low surrogate right after a high surrogate, backslash (\\) mising");
458 : }
459 : CATCH_END_SECTION()
460 :
461 40 : CATCH_START_SECTION("invalid JSON unicode: low surrogate missing 'u'")
462 : {
463 1 : std::string valid_json(
464 : "\"\\uD91F\\missing\""
465 2 : );
466 :
467 2 : libutf8::json_tokens jt(valid_json);
468 1 : CATCH_REQUIRE(jt.line() == 0);
469 1 : CATCH_REQUIRE(jt.column() == 0);
470 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
471 1 : CATCH_REQUIRE(jt.line() == 1);
472 1 : CATCH_REQUIRE(jt.column() == 1);
473 1 : CATCH_REQUIRE(jt.error() == "expected a low surrogate right after a high surrogate, 'u' missing");
474 : }
475 : CATCH_END_SECTION()
476 :
477 40 : CATCH_START_SECTION("invalid JSON unicode: low surrogate expected")
478 : {
479 : {
480 1 : std::string valid_json(
481 : "\"\\uD91F\\u0010\""
482 2 : );
483 :
484 2 : libutf8::json_tokens jt(valid_json);
485 1 : CATCH_REQUIRE(jt.line() == 0);
486 1 : CATCH_REQUIRE(jt.column() == 0);
487 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
488 1 : CATCH_REQUIRE(jt.line() == 1);
489 1 : CATCH_REQUIRE(jt.column() == 1);
490 1 : CATCH_REQUIRE(jt.error() == "expected a low surrogate right after a high surrogate");
491 : }
492 :
493 : {
494 1 : std::string valid_json(
495 : "\"\\uD91F\\uDBFF\""
496 2 : );
497 :
498 2 : libutf8::json_tokens jt(valid_json);
499 1 : CATCH_REQUIRE(jt.line() == 0);
500 1 : CATCH_REQUIRE(jt.column() == 0);
501 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
502 1 : CATCH_REQUIRE(jt.line() == 1);
503 1 : CATCH_REQUIRE(jt.column() == 1);
504 1 : CATCH_REQUIRE(jt.error() == "expected a low surrogate right after a high surrogate");
505 : }
506 :
507 : {
508 1 : std::string valid_json(
509 : "\"\\uD91F\\uE030"
510 2 : );
511 :
512 2 : libutf8::json_tokens jt(valid_json);
513 1 : CATCH_REQUIRE(jt.line() == 0);
514 1 : CATCH_REQUIRE(jt.column() == 0);
515 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
516 1 : CATCH_REQUIRE(jt.line() == 1);
517 1 : CATCH_REQUIRE(jt.column() == 1);
518 1 : CATCH_REQUIRE(jt.error() == "expected a low surrogate right after a high surrogate");
519 : }
520 : }
521 : CATCH_END_SECTION()
522 :
523 40 : CATCH_START_SECTION("invalid JSON unicode: low surrogate too short")
524 : {
525 : {
526 1 : std::string valid_json(
527 : "\"\\uD91F\\u0"
528 2 : );
529 :
530 2 : libutf8::json_tokens jt(valid_json);
531 1 : CATCH_REQUIRE(jt.line() == 0);
532 1 : CATCH_REQUIRE(jt.column() == 0);
533 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
534 1 : CATCH_REQUIRE(jt.line() == 1);
535 1 : CATCH_REQUIRE(jt.column() == 1);
536 1 : CATCH_REQUIRE(jt.error() == "invalid unicode character: 'EOS'");
537 : }
538 :
539 : {
540 1 : std::string valid_json(
541 : "\"\\uD91F\\u0f"
542 2 : );
543 :
544 2 : libutf8::json_tokens jt(valid_json);
545 1 : CATCH_REQUIRE(jt.line() == 0);
546 1 : CATCH_REQUIRE(jt.column() == 0);
547 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
548 1 : CATCH_REQUIRE(jt.line() == 1);
549 1 : CATCH_REQUIRE(jt.column() == 1);
550 1 : CATCH_REQUIRE(jt.error() == "invalid unicode character: 'EOS'");
551 : }
552 :
553 : {
554 1 : std::string valid_json(
555 : "\"\\uD91F\\u0fa"
556 2 : );
557 :
558 2 : libutf8::json_tokens jt(valid_json);
559 1 : CATCH_REQUIRE(jt.line() == 0);
560 1 : CATCH_REQUIRE(jt.column() == 0);
561 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
562 1 : CATCH_REQUIRE(jt.line() == 1);
563 1 : CATCH_REQUIRE(jt.column() == 1);
564 1 : CATCH_REQUIRE(jt.error() == "invalid unicode character: 'EOS'");
565 : }
566 : }
567 : CATCH_END_SECTION()
568 :
569 40 : CATCH_START_SECTION("invalid JSON unicode: invalid hexadecimal digit (low surrogate)")
570 : {
571 : {
572 1 : std::string valid_json(
573 : "\"\\udb31\\u0t\""
574 2 : );
575 :
576 2 : libutf8::json_tokens jt(valid_json);
577 1 : CATCH_REQUIRE(jt.line() == 0);
578 1 : CATCH_REQUIRE(jt.column() == 0);
579 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
580 1 : CATCH_REQUIRE(jt.line() == 1);
581 1 : CATCH_REQUIRE(jt.column() == 1);
582 1 : CATCH_REQUIRE(jt.error() == "invalid unicode character: 't'");
583 : }
584 :
585 : {
586 1 : std::string valid_json(
587 : "\"\\udb31\\u3eg\""
588 2 : );
589 :
590 2 : libutf8::json_tokens jt(valid_json);
591 1 : CATCH_REQUIRE(jt.line() == 0);
592 1 : CATCH_REQUIRE(jt.column() == 0);
593 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
594 1 : CATCH_REQUIRE(jt.line() == 1);
595 1 : CATCH_REQUIRE(jt.column() == 1);
596 1 : CATCH_REQUIRE(jt.error() == "invalid unicode character: 'g'");
597 : }
598 :
599 : {
600 1 : std::string valid_json(
601 : "\"\\udb31\\ua3e!\""
602 2 : );
603 :
604 2 : libutf8::json_tokens jt(valid_json);
605 1 : CATCH_REQUIRE(jt.line() == 0);
606 1 : CATCH_REQUIRE(jt.column() == 0);
607 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
608 1 : CATCH_REQUIRE(jt.line() == 1);
609 1 : CATCH_REQUIRE(jt.column() == 1);
610 1 : CATCH_REQUIRE(jt.error() == "invalid unicode character: '!'");
611 : }
612 : }
613 : CATCH_END_SECTION()
614 :
615 40 : CATCH_START_SECTION("invalid JSON unicode: low surrogate first")
616 : {
617 1025 : for(char32_t c(0xDC00); c <= 0xDFFF; ++c)
618 : {
619 2048 : std::stringstream ss;
620 1024 : ss << "\\u" << std::hex << std::setw(4)
621 1024 : << std::setfill('0') << static_cast<int>(c);
622 :
623 2048 : libutf8::json_tokens jt("\"" + ss.str() + "\"");
624 1024 : CATCH_REQUIRE(jt.line() == 0);
625 1024 : CATCH_REQUIRE(jt.column() == 0);
626 1024 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
627 1024 : CATCH_REQUIRE(jt.line() == 1);
628 1024 : CATCH_REQUIRE(jt.column() == 1);
629 3072 : std::string const msg("low surrogate " + ss.str()
630 3072 : + " found before a high surrogate");
631 1024 : CATCH_REQUIRE(jt.error() == msg);
632 : }
633 :
634 : }
635 : CATCH_END_SECTION()
636 :
637 40 : CATCH_START_SECTION("invalid JSON unicode: invalid hexadecimal digit")
638 : {
639 : {
640 1 : std::string valid_json(
641 : "\"\\u5z"
642 2 : );
643 :
644 2 : libutf8::json_tokens jt(valid_json);
645 1 : CATCH_REQUIRE(jt.line() == 0);
646 1 : CATCH_REQUIRE(jt.column() == 0);
647 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
648 1 : CATCH_REQUIRE(jt.line() == 1);
649 1 : CATCH_REQUIRE(jt.column() == 1);
650 1 : CATCH_REQUIRE(jt.error() == "invalid unicode character: 'z'");
651 : }
652 :
653 : {
654 1 : std::string valid_json(
655 : "\"\\uaa$"
656 2 : );
657 :
658 2 : libutf8::json_tokens jt(valid_json);
659 1 : CATCH_REQUIRE(jt.line() == 0);
660 1 : CATCH_REQUIRE(jt.column() == 0);
661 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
662 1 : CATCH_REQUIRE(jt.line() == 1);
663 1 : CATCH_REQUIRE(jt.column() == 1);
664 1 : CATCH_REQUIRE(jt.error() == "invalid unicode character: '$'");
665 : }
666 :
667 : {
668 1 : std::string valid_json(
669 : "\"\\ua9a\001"
670 2 : );
671 :
672 2 : libutf8::json_tokens jt(valid_json);
673 1 : CATCH_REQUIRE(jt.line() == 0);
674 1 : CATCH_REQUIRE(jt.column() == 0);
675 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
676 1 : CATCH_REQUIRE(jt.line() == 1);
677 1 : CATCH_REQUIRE(jt.column() == 1);
678 1 : CATCH_REQUIRE(jt.error() == "invalid unicode character: '^A'");
679 : }
680 : }
681 : CATCH_END_SECTION()
682 :
683 40 : CATCH_START_SECTION("unterminated JSON string")
684 : {
685 2 : libutf8::json_tokens jt("\"unterminated");
686 1 : CATCH_REQUIRE(jt.line() == 0);
687 1 : CATCH_REQUIRE(jt.column() == 0);
688 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
689 1 : CATCH_REQUIRE(jt.line() == 1);
690 1 : CATCH_REQUIRE(jt.column() == 1);
691 1 : CATCH_REQUIRE(jt.error() == "unclosed string");
692 :
693 : }
694 : CATCH_END_SECTION()
695 :
696 40 : CATCH_START_SECTION("JSON true with missing characters")
697 : {
698 : {
699 2 : libutf8::json_tokens jt("{\"bad-true\":tru}");
700 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_OPEN_OBJECT);
701 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
702 1 : CATCH_REQUIRE(jt.string() == "bad-true");
703 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COLON);
704 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
705 1 : CATCH_REQUIRE(jt.error() == "found unexpected character: 't'");
706 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
707 1 : CATCH_REQUIRE(jt.error() == "found unexpected character: 'r'");
708 : }
709 :
710 : {
711 2 : libutf8::json_tokens jt("{\"bad-true\":tr}");
712 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_OPEN_OBJECT);
713 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
714 1 : CATCH_REQUIRE(jt.string() == "bad-true");
715 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COLON);
716 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
717 1 : CATCH_REQUIRE(jt.error() == "found unexpected character: 't'");
718 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
719 1 : CATCH_REQUIRE(jt.error() == "found unexpected character: 'r'");
720 : }
721 :
722 : {
723 2 : libutf8::json_tokens jt("{\"bad-true\":t}");
724 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_OPEN_OBJECT);
725 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
726 1 : CATCH_REQUIRE(jt.string() == "bad-true");
727 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COLON);
728 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
729 1 : CATCH_REQUIRE(jt.error() == "found unexpected character: 't'");
730 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_CLOSE_OBJECT);
731 : }
732 : }
733 : CATCH_END_SECTION()
734 :
735 40 : CATCH_START_SECTION("JSON false with missing characters")
736 : {
737 : {
738 2 : libutf8::json_tokens jt("{\"bad-false\":fals}");
739 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_OPEN_OBJECT);
740 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
741 1 : CATCH_REQUIRE(jt.string() == "bad-false");
742 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COLON);
743 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
744 1 : CATCH_REQUIRE(jt.error() == "found unexpected character: 'f'");
745 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
746 1 : CATCH_REQUIRE(jt.error() == "found unexpected character: 'a'");
747 : }
748 :
749 : {
750 2 : libutf8::json_tokens jt("{\"bad-false\":fal}");
751 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_OPEN_OBJECT);
752 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
753 1 : CATCH_REQUIRE(jt.string() == "bad-false");
754 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COLON);
755 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
756 1 : CATCH_REQUIRE(jt.error() == "found unexpected character: 'f'");
757 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
758 1 : CATCH_REQUIRE(jt.error() == "found unexpected character: 'a'");
759 : }
760 :
761 : {
762 2 : libutf8::json_tokens jt("{\"bad-false\":fa}");
763 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_OPEN_OBJECT);
764 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
765 1 : CATCH_REQUIRE(jt.string() == "bad-false");
766 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COLON);
767 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
768 1 : CATCH_REQUIRE(jt.error() == "found unexpected character: 'f'");
769 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
770 1 : CATCH_REQUIRE(jt.error() == "found unexpected character: 'a'");
771 : }
772 :
773 : {
774 2 : libutf8::json_tokens jt("{\"bad-false\":f}");
775 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_OPEN_OBJECT);
776 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
777 1 : CATCH_REQUIRE(jt.string() == "bad-false");
778 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COLON);
779 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
780 1 : CATCH_REQUIRE(jt.error() == "found unexpected character: 'f'");
781 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_CLOSE_OBJECT);
782 : }
783 : }
784 : CATCH_END_SECTION()
785 :
786 40 : CATCH_START_SECTION("JSON null with missing characters")
787 : {
788 : {
789 2 : libutf8::json_tokens jt("{\"bad-null\":nul}");
790 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_OPEN_OBJECT);
791 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
792 1 : CATCH_REQUIRE(jt.string() == "bad-null");
793 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COLON);
794 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
795 1 : CATCH_REQUIRE(jt.error() == "found unexpected character: 'n'");
796 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
797 1 : CATCH_REQUIRE(jt.error() == "found unexpected character: 'u'");
798 : }
799 :
800 : {
801 2 : libutf8::json_tokens jt("{\"bad-null\":nu}");
802 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_OPEN_OBJECT);
803 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
804 1 : CATCH_REQUIRE(jt.string() == "bad-null");
805 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COLON);
806 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
807 1 : CATCH_REQUIRE(jt.error() == "found unexpected character: 'n'");
808 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
809 1 : CATCH_REQUIRE(jt.error() == "found unexpected character: 'u'");
810 : }
811 :
812 : {
813 2 : libutf8::json_tokens jt("{\"bad-null\":n}");
814 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_OPEN_OBJECT);
815 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_STRING);
816 1 : CATCH_REQUIRE(jt.string() == "bad-null");
817 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_COLON);
818 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
819 1 : CATCH_REQUIRE(jt.error() == "found unexpected character: 'n'");
820 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_CLOSE_OBJECT);
821 : }
822 : }
823 : CATCH_END_SECTION()
824 :
825 40 : CATCH_START_SECTION("unexpected JSON characters")
826 : {
827 1114112 : for(char32_t c(1); c < 0x110000; ++c)
828 : {
829 1114111 : if(c >= 0xD800 && c <= 0xDFFF)
830 : {
831 2048 : continue;
832 : }
833 1112087 : switch(c)
834 : {
835 24 : case '"':
836 : case '{':
837 : case '}':
838 : case '[':
839 : case ']':
840 : case '0':
841 : case '1':
842 : case '2':
843 : case '3':
844 : case '4':
845 : case '5':
846 : case '6':
847 : case '7':
848 : case '8':
849 : case '9':
850 : case ' ':
851 : case '\t':
852 : case '\r':
853 : case '\n':
854 : case 'n':
855 : case 't':
856 : case 'f':
857 : case ',':
858 : case ':':
859 24 : continue;
860 :
861 : }
862 :
863 2224078 : std::string invalid_json(libutf8::to_u8string(c));
864 2224078 : libutf8::json_tokens jt(invalid_json);
865 :
866 1112039 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
867 1112039 : if(c < 0x20)
868 : {
869 28 : CATCH_REQUIRE(jt.error() == "found unexpected character: '^" + libutf8::to_u8string(static_cast<char32_t>(c + 0x40)) + "'");
870 : }
871 1112011 : else if(c >= 0x80 && c < 0xA0)
872 : {
873 32 : CATCH_REQUIRE(jt.error() == "found unexpected character: '@" + libutf8::to_u8string(static_cast<char32_t>(c - 0x40)) + "'");
874 : }
875 : else
876 : {
877 1111979 : CATCH_REQUIRE(jt.error() == "found unexpected character: '" + libutf8::to_u8string(c) + "'");
878 : }
879 : }
880 : }
881 : CATCH_END_SECTION()
882 :
883 40 : CATCH_START_SECTION("unexpected '\\0' in JSON")
884 : {
885 2 : std::string invalid_json;
886 1 : invalid_json += '\0';
887 2 : libutf8::json_tokens jt(invalid_json);
888 :
889 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
890 1 : CATCH_REQUIRE(jt.error() == "found unexpected NULL character");
891 : }
892 : CATCH_END_SECTION()
893 :
894 40 : CATCH_START_SECTION("unexpected '\\0' in JSON string")
895 : {
896 2 : std::string invalid_json("\"string");
897 1 : invalid_json += '\0';
898 1 : invalid_json += "with null\"";
899 2 : libutf8::json_tokens jt(invalid_json);
900 :
901 1 : CATCH_REQUIRE(jt.next_token() == libutf8::token_t::TOKEN_ERROR);
902 1 : CATCH_REQUIRE(jt.error() == "unexpected NULL character in string");
903 : }
904 : CATCH_END_SECTION()
905 26 : }
906 :
907 :
908 :
909 : // vim: ts=4 sw=4 et
|