• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2     __ _____ _____ _____
3  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
4 |  |  |__   |  |  | | | |  version 3.7.3
5 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
6 
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 SPDX-License-Identifier: MIT
9 Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
10 
11 Permission is hereby  granted, free of charge, to any  person obtaining a copy
12 of this software and associated  documentation files (the "Software"), to deal
13 in the Software  without restriction, including without  limitation the rights
14 to  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell
15 copies  of  the Software,  and  to  permit persons  to  whom  the Software  is
16 furnished to do so, subject to the following conditions:
17 
18 The above copyright notice and this permission notice shall be included in all
19 copies or substantial portions of the Software.
20 
21 THE SOFTWARE  IS PROVIDED "AS  IS", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR
22 IMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,
23 FITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE
24 AUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER
25 LIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 OUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE
27 SOFTWARE.
28 */
29 
30 #include "doctest_compatibility.h"
31 
32 #include <nlohmann/json.hpp>
33 using nlohmann::json;
34 
35 #include <iostream>
36 #include <sstream>
37 #include <valarray>
38 
39 namespace
40 {
41 struct SaxEventLogger : public nlohmann::json_sax<json>
42 {
null__anon147df8ed0111::SaxEventLogger43     bool null() override
44     {
45         events.push_back("null()");
46         return true;
47     }
48 
boolean__anon147df8ed0111::SaxEventLogger49     bool boolean(bool val) override
50     {
51         events.push_back(val ? "boolean(true)" : "boolean(false)");
52         return true;
53     }
54 
number_integer__anon147df8ed0111::SaxEventLogger55     bool number_integer(json::number_integer_t val) override
56     {
57         events.push_back("number_integer(" + std::to_string(val) + ")");
58         return true;
59     }
60 
number_unsigned__anon147df8ed0111::SaxEventLogger61     bool number_unsigned(json::number_unsigned_t val) override
62     {
63         events.push_back("number_unsigned(" + std::to_string(val) + ")");
64         return true;
65     }
66 
number_float__anon147df8ed0111::SaxEventLogger67     bool number_float(json::number_float_t, const std::string& s) override
68     {
69         events.push_back("number_float(" + s + ")");
70         return true;
71     }
72 
string__anon147df8ed0111::SaxEventLogger73     bool string(std::string& val) override
74     {
75         events.push_back("string(" + val + ")");
76         return true;
77     }
78 
start_object__anon147df8ed0111::SaxEventLogger79     bool start_object(std::size_t elements) override
80     {
81         if (elements == std::size_t(-1))
82         {
83             events.push_back("start_object()");
84         }
85         else
86         {
87             events.push_back("start_object(" + std::to_string(elements) + ")");
88         }
89         return true;
90     }
91 
key__anon147df8ed0111::SaxEventLogger92     bool key(std::string& val) override
93     {
94         events.push_back("key(" + val + ")");
95         return true;
96     }
97 
end_object__anon147df8ed0111::SaxEventLogger98     bool end_object() override
99     {
100         events.push_back("end_object()");
101         return true;
102     }
103 
start_array__anon147df8ed0111::SaxEventLogger104     bool start_array(std::size_t elements) override
105     {
106         if (elements == std::size_t(-1))
107         {
108             events.push_back("start_array()");
109         }
110         else
111         {
112             events.push_back("start_array(" + std::to_string(elements) + ")");
113         }
114         return true;
115     }
116 
end_array__anon147df8ed0111::SaxEventLogger117     bool end_array() override
118     {
119         events.push_back("end_array()");
120         return true;
121     }
122 
parse_error__anon147df8ed0111::SaxEventLogger123     bool parse_error(std::size_t position, const std::string&, const json::exception&) override
124     {
125         events.push_back("parse_error(" + std::to_string(position) + ")");
126         return false;
127     }
128 
129     std::vector<std::string> events {};
130 };
131 
132 struct SaxEventLoggerExitAfterStartObject : public SaxEventLogger
133 {
start_object__anon147df8ed0111::SaxEventLoggerExitAfterStartObject134     bool start_object(std::size_t elements) override
135     {
136         if (elements == std::size_t(-1))
137         {
138             events.push_back("start_object()");
139         }
140         else
141         {
142             events.push_back("start_object(" + std::to_string(elements) + ")");
143         }
144         return false;
145     }
146 };
147 
148 struct SaxEventLoggerExitAfterKey : public SaxEventLogger
149 {
key__anon147df8ed0111::SaxEventLoggerExitAfterKey150     bool key(std::string& val) override
151     {
152         events.push_back("key(" + val + ")");
153         return false;
154     }
155 };
156 
157 struct SaxEventLoggerExitAfterStartArray : public SaxEventLogger
158 {
start_array__anon147df8ed0111::SaxEventLoggerExitAfterStartArray159     bool start_array(std::size_t elements) override
160     {
161         if (elements == std::size_t(-1))
162         {
163             events.push_back("start_array()");
164         }
165         else
166         {
167             events.push_back("start_array(" + std::to_string(elements) + ")");
168         }
169         return false;
170     }
171 };
172 }
173 
174 TEST_CASE("deserialization")
175 {
176     SECTION("successful deserialization")
177     {
178         SECTION("stream")
179         {
180             std::stringstream ss1, ss2, ss3;
181             ss1 << "[\"foo\",1,2,3,false,{\"one\":1}]";
182             ss2 << "[\"foo\",1,2,3,false,{\"one\":1}]";
183             ss3 << "[\"foo\",1,2,3,false,{\"one\":1}]";
184             json j = json::parse(ss1);
185             CHECK(json::accept(ss2));
186             CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
187 
188             SaxEventLogger l;
189             CHECK(json::sax_parse(ss3, &l));
190             CHECK(l.events.size() == 11);
191             CHECK(l.events == std::vector<std::string>(
192             {
193                 "start_array()", "string(foo)", "number_unsigned(1)",
194                 "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
195                 "start_object()", "key(one)", "number_unsigned(1)",
196                 "end_object()", "end_array()"
197             }));
198         }
199 
200         SECTION("string literal")
201         {
202             auto s = "[\"foo\",1,2,3,false,{\"one\":1}]";
203             json j = json::parse(s);
204             CHECK(json::accept(s));
205             CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
206 
207             SaxEventLogger l;
208             CHECK(json::sax_parse(s, &l));
209             CHECK(l.events.size() == 11);
210             CHECK(l.events == std::vector<std::string>(
211             {
212                 "start_array()", "string(foo)", "number_unsigned(1)",
213                 "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
214                 "start_object()", "key(one)", "number_unsigned(1)",
215                 "end_object()", "end_array()"
216             }));
217         }
218 
219         SECTION("string_t")
220         {
221             json::string_t s = "[\"foo\",1,2,3,false,{\"one\":1}]";
222             json j = json::parse(s);
223             CHECK(json::accept(s));
224             CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
225 
226             SaxEventLogger l;
227             CHECK(json::sax_parse(s, &l));
228             CHECK(l.events.size() == 11);
229             CHECK(l.events == std::vector<std::string>(
230             {
231                 "start_array()", "string(foo)", "number_unsigned(1)",
232                 "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
233                 "start_object()", "key(one)", "number_unsigned(1)",
234                 "end_object()", "end_array()"
235             }));
236         }
237 
238         SECTION("operator<<")
239         {
240             std::stringstream ss;
241             ss << "[\"foo\",1,2,3,false,{\"one\":1}]";
242             json j;
243             j << ss;
244             CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
245         }
246 
247         SECTION("operator>>")
248         {
249             std::stringstream ss;
250             ss << "[\"foo\",1,2,3,false,{\"one\":1}]";
251             json j;
252             ss >> j;
253             CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
254         }
255 
256         SECTION("user-defined string literal")
257         {
258             CHECK("[\"foo\",1,2,3,false,{\"one\":1}]"_json == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
259         }
260     }
261 
262     SECTION("unsuccessful deserialization")
263     {
264         SECTION("stream")
265         {
266             std::stringstream ss1, ss2, ss3, ss4, ss5;
267             ss1 << "[\"foo\",1,2,3,false,{\"one\":1}";
268             ss2 << "[\"foo\",1,2,3,false,{\"one\":1}";
269             ss3 << "[\"foo\",1,2,3,false,{\"one\":1}";
270             ss4 << "[\"foo\",1,2,3,false,{\"one\":1}";
271             ss5 << "[\"foo\",1,2,3,false,{\"one\":1}";
272 
273             json _;
274             CHECK_THROWS_AS(_ = json::parse(ss1), json::parse_error&);
275             CHECK_THROWS_WITH(_ = json::parse(ss2),
276                               "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'");
277             CHECK(not json::accept(ss3));
278 
279             json j_error;
280             CHECK_NOTHROW(j_error = json::parse(ss4, nullptr, false));
281             CHECK(j_error.is_discarded());
282 
283             SaxEventLogger l;
284             CHECK(not json::sax_parse(ss5, &l));
285             CHECK(l.events.size() == 11);
286             CHECK(l.events == std::vector<std::string>(
287             {
288                 "start_array()", "string(foo)", "number_unsigned(1)",
289                 "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
290                 "start_object()", "key(one)", "number_unsigned(1)",
291                 "end_object()", "parse_error(29)"
292             }));
293         }
294 
295         SECTION("string")
296         {
297             json::string_t s = "[\"foo\",1,2,3,false,{\"one\":1}";
298             json _;
299             CHECK_THROWS_AS(_ = json::parse(s), json::parse_error&);
300             CHECK_THROWS_WITH(_ = json::parse(s),
301                               "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'");
302             CHECK(not json::accept(s));
303 
304             json j_error;
305             CHECK_NOTHROW(j_error = json::parse(s, nullptr, false));
306             CHECK(j_error.is_discarded());
307 
308             SaxEventLogger l;
309             CHECK(not json::sax_parse(s, &l));
310             CHECK(l.events.size() == 11);
311             CHECK(l.events == std::vector<std::string>(
312             {
313                 "start_array()", "string(foo)", "number_unsigned(1)",
314                 "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
315                 "start_object()", "key(one)", "number_unsigned(1)",
316                 "end_object()", "parse_error(29)"
317             }));
318         }
319 
320         SECTION("operator<<")
321         {
322             std::stringstream ss1, ss2;
323             ss1 << "[\"foo\",1,2,3,false,{\"one\":1}";
324             ss2 << "[\"foo\",1,2,3,false,{\"one\":1}";
325             json j;
326             CHECK_THROWS_AS(j << ss1, json::parse_error&);
327             CHECK_THROWS_WITH(j << ss2,
328                               "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'");
329         }
330 
331         SECTION("operator>>")
332         {
333             std::stringstream ss1, ss2;
334             ss1 << "[\"foo\",1,2,3,false,{\"one\":1}";
335             ss2 << "[\"foo\",1,2,3,false,{\"one\":1}";
336             json j;
337             CHECK_THROWS_AS(ss1 >> j, json::parse_error&);
338             CHECK_THROWS_WITH(ss2 >> j,
339                               "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'");
340         }
341 
342         SECTION("user-defined string literal")
343         {
344             CHECK_THROWS_AS("[\"foo\",1,2,3,false,{\"one\":1}"_json, json::parse_error&);
345             CHECK_THROWS_WITH("[\"foo\",1,2,3,false,{\"one\":1}"_json,
346                               "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'");
347         }
348     }
349 
350     SECTION("contiguous containers")
351     {
352         SECTION("directly")
353         {
354             SECTION("from std::vector")
355             {
356                 std::vector<uint8_t> v = {'t', 'r', 'u', 'e'};
357                 CHECK(json::parse(v) == json(true));
358                 CHECK(json::accept(v));
359 
360                 SaxEventLogger l;
361                 CHECK(json::sax_parse(v, &l));
362                 CHECK(l.events.size() == 1);
363                 CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
364             }
365 
366             SECTION("from std::array")
367             {
368                 std::array<uint8_t, 5> v { {'t', 'r', 'u', 'e'} };
369                 CHECK(json::parse(v) == json(true));
370                 CHECK(json::accept(v));
371 
372                 SaxEventLogger l;
373                 CHECK(json::sax_parse(v, &l));
374                 CHECK(l.events.size() == 1);
375                 CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
376             }
377 
378             SECTION("from array")
379             {
380                 uint8_t v[] = {'t', 'r', 'u', 'e'};
381                 CHECK(json::parse(v) == json(true));
382                 CHECK(json::accept(v));
383 
384                 SaxEventLogger l;
385                 CHECK(json::sax_parse(v, &l));
386                 CHECK(l.events.size() == 1);
387                 CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
388             }
389 
390             SECTION("from chars")
391             {
392                 uint8_t* v = new uint8_t[5];
393                 v[0] = 't';
394                 v[1] = 'r';
395                 v[2] = 'u';
396                 v[3] = 'e';
397                 v[4] = '\0';
398                 CHECK(json::parse(v) == json(true));
399                 CHECK(json::accept(v));
400 
401                 SaxEventLogger l;
402                 CHECK(json::sax_parse(v, &l));
403                 CHECK(l.events.size() == 1);
404                 CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
405 
406                 delete[] v;
407             }
408 
409             SECTION("from std::string")
410             {
411                 std::string v = {'t', 'r', 'u', 'e'};
412                 CHECK(json::parse(v) == json(true));
413                 CHECK(json::accept(v));
414 
415                 SaxEventLogger l;
416                 CHECK(json::sax_parse(v, &l));
417                 CHECK(l.events.size() == 1);
418                 CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
419             }
420 
421             SECTION("from std::initializer_list")
422             {
423                 std::initializer_list<uint8_t> v = {'t', 'r', 'u', 'e'};
424                 CHECK(json::parse(v) == json(true));
425                 CHECK(json::accept(v));
426 
427                 SaxEventLogger l;
428                 CHECK(json::sax_parse(v, &l));
429                 CHECK(l.events.size() == 1);
430                 CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
431             }
432 
433             SECTION("empty container")
434             {
435                 std::vector<uint8_t> v;
436                 json _;
437                 CHECK_THROWS_AS(_ = json::parse(v), json::parse_error&);
438                 CHECK(not json::accept(v));
439 
440                 SaxEventLogger l;
441                 CHECK(not json::sax_parse(v, &l));
442                 CHECK(l.events.size() == 1);
443                 CHECK(l.events == std::vector<std::string>({"parse_error(1)"}));
444             }
445         }
446 
447         SECTION("via iterator range")
448         {
449             SECTION("from std::vector")
450             {
451                 std::vector<uint8_t> v = {'t', 'r', 'u', 'e'};
452                 CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
453                 CHECK(json::accept(std::begin(v), std::end(v)));
454 
455                 SaxEventLogger l;
456                 CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
457                 CHECK(l.events.size() == 1);
458                 CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
459 
460             }
461 
462             SECTION("from std::array")
463             {
464                 std::array<uint8_t, 5> v { {'t', 'r', 'u', 'e'} };
465                 CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
466                 CHECK(json::accept(std::begin(v), std::end(v)));
467 
468                 SaxEventLogger l;
469                 CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
470                 CHECK(l.events.size() == 1);
471                 CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
472             }
473 
474             SECTION("from array")
475             {
476                 uint8_t v[] = {'t', 'r', 'u', 'e'};
477                 CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
478                 CHECK(json::accept(std::begin(v), std::end(v)));
479 
480                 SaxEventLogger l;
481                 CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
482                 CHECK(l.events.size() == 1);
483                 CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
484             }
485 
486             SECTION("from std::string")
487             {
488                 std::string v = {'t', 'r', 'u', 'e'};
489                 CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
490                 CHECK(json::accept(std::begin(v), std::end(v)));
491 
492                 SaxEventLogger l;
493                 CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
494                 CHECK(l.events.size() == 1);
495                 CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
496             }
497 
498             SECTION("from std::initializer_list")
499             {
500                 std::initializer_list<uint8_t> v = {'t', 'r', 'u', 'e'};
501                 CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
502                 CHECK(json::accept(std::begin(v), std::end(v)));
503 
504                 SaxEventLogger l;
505                 CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
506                 CHECK(l.events.size() == 1);
507                 CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
508             }
509 
510             SECTION("from std::valarray")
511             {
512                 std::valarray<uint8_t> v = {'t', 'r', 'u', 'e'};
513                 CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
514                 CHECK(json::accept(std::begin(v), std::end(v)));
515 
516                 SaxEventLogger l;
517                 CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
518                 CHECK(l.events.size() == 1);
519                 CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
520             }
521 
522             SECTION("with empty range")
523             {
524                 std::vector<uint8_t> v;
525                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
526                 CHECK(not json::accept(std::begin(v), std::end(v)));
527 
528                 SaxEventLogger l;
529                 CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
530                 CHECK(l.events.size() == 1);
531                 CHECK(l.events == std::vector<std::string>({"parse_error(1)"}));
532             }
533         }
534 
535         // these cases are required for 100% line coverage
536         SECTION("error cases")
537         {
538             SECTION("case 1")
539             {
540                 uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u'};
541                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
542                 CHECK(not json::accept(std::begin(v), std::end(v)));
543 
544                 json j_error;
545                 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
546                 CHECK(j_error.is_discarded());
547 
548                 SaxEventLogger l;
549                 CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
550                 CHECK(l.events.size() == 1);
551                 CHECK(l.events == std::vector<std::string>({"parse_error(10)"}));
552             }
553 
554             SECTION("case 2")
555             {
556                 uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1'};
557                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
558                 CHECK(not json::accept(std::begin(v), std::end(v)));
559 
560                 json j_error;
561                 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
562                 CHECK(j_error.is_discarded());
563 
564                 SaxEventLogger l;
565                 CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
566                 CHECK(l.events.size() == 1);
567                 CHECK(l.events == std::vector<std::string>({"parse_error(11)"}));
568             }
569 
570             SECTION("case 3")
571             {
572                 uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1', '1', '1', '1', '1', '1', '1', '1'};
573                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
574                 CHECK(not json::accept(std::begin(v), std::end(v)));
575 
576                 json j_error;
577                 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
578                 CHECK(j_error.is_discarded());
579 
580                 SaxEventLogger l;
581                 CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
582                 CHECK(l.events.size() == 1);
583                 CHECK(l.events == std::vector<std::string>({"parse_error(18)"}));
584             }
585 
586             SECTION("case 4")
587             {
588                 uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', 'u', '1', '1', '1', '1', '1', '1', '1', '1', '\\'};
589                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
590                 CHECK(not json::accept(std::begin(v), std::end(v)));
591 
592                 json j_error;
593                 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
594                 CHECK(j_error.is_discarded());
595 
596                 SaxEventLogger l;
597                 CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
598                 CHECK(l.events.size() == 1);
599                 CHECK(l.events == std::vector<std::string>({"parse_error(18)"}));
600             }
601 
602             SECTION("case 5")
603             {
604                 uint8_t v[] = {'\"', 0x7F, 0xC1};
605                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
606                 CHECK(not json::accept(std::begin(v), std::end(v)));
607 
608                 json j_error;
609                 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
610                 CHECK(j_error.is_discarded());
611 
612                 SaxEventLogger l;
613                 CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
614                 CHECK(l.events.size() == 1);
615                 CHECK(l.events == std::vector<std::string>({"parse_error(3)"}));
616             }
617 
618             SECTION("case 6")
619             {
620                 uint8_t v[] = {'\"', 0x7F, 0xDF, 0x7F};
621                 json _;
622                 CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
623                 CHECK_THROWS_WITH(_ = json::parse(std::begin(v), std::end(v)),
624                                   "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: ill-formed UTF-8 byte; last read: '\"\x7f\xdf\x7f'");
625                 CHECK(not json::accept(std::begin(v), std::end(v)));
626 
627                 json j_error;
628                 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
629                 CHECK(j_error.is_discarded());
630 
631                 SaxEventLogger l;
632                 CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
633                 CHECK(l.events.size() == 1);
634                 CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
635             }
636 
637             SECTION("case 7")
638             {
639                 uint8_t v[] = {'\"', 0x7F, 0xDF, 0xC0};
640                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
641                 CHECK(not json::accept(std::begin(v), std::end(v)));
642 
643                 json j_error;
644                 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
645                 CHECK(j_error.is_discarded());
646 
647                 SaxEventLogger l;
648                 CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
649                 CHECK(l.events.size() == 1);
650                 CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
651             }
652 
653             SECTION("case 8")
654             {
655                 uint8_t v[] = {'\"', 0x7F, 0xE0, 0x9F};
656                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
657                 CHECK(not json::accept(std::begin(v), std::end(v)));
658 
659                 json j_error;
660                 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
661                 CHECK(j_error.is_discarded());
662 
663                 SaxEventLogger l;
664                 CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
665                 CHECK(l.events.size() == 1);
666                 CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
667             }
668 
669             SECTION("case 9")
670             {
671                 uint8_t v[] = {'\"', 0x7F, 0xEF, 0xC0};
672                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
673                 CHECK(not json::accept(std::begin(v), std::end(v)));
674 
675                 json j_error;
676                 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
677                 CHECK(j_error.is_discarded());
678 
679                 SaxEventLogger l;
680                 CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
681                 CHECK(l.events.size() == 1);
682                 CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
683             }
684 
685             SECTION("case 10")
686             {
687                 uint8_t v[] = {'\"', 0x7F, 0xED, 0x7F};
688                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
689                 CHECK(not json::accept(std::begin(v), std::end(v)));
690 
691                 json j_error;
692                 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
693                 CHECK(j_error.is_discarded());
694 
695                 SaxEventLogger l;
696                 CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
697                 CHECK(l.events.size() == 1);
698                 CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
699             }
700 
701             SECTION("case 11")
702             {
703                 uint8_t v[] = {'\"', 0x7F, 0xF0, 0x8F};
704                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
705                 CHECK(not json::accept(std::begin(v), std::end(v)));
706 
707                 json j_error;
708                 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
709                 CHECK(j_error.is_discarded());
710 
711                 SaxEventLogger l;
712                 CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
713                 CHECK(l.events.size() == 1);
714                 CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
715             }
716 
717             SECTION("case 12")
718             {
719                 uint8_t v[] = {'\"', 0x7F, 0xF0, 0xC0};
720                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
721                 CHECK(not json::accept(std::begin(v), std::end(v)));
722 
723                 json j_error;
724                 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
725                 CHECK(j_error.is_discarded());
726 
727                 SaxEventLogger l;
728                 CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
729                 CHECK(l.events.size() == 1);
730                 CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
731             }
732 
733             SECTION("case 13")
734             {
735                 uint8_t v[] = {'\"', 0x7F, 0xF3, 0x7F};
736                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
737                 CHECK(not json::accept(std::begin(v), std::end(v)));
738 
739                 json j_error;
740                 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
741                 CHECK(j_error.is_discarded());
742 
743                 SaxEventLogger l;
744                 CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
745                 CHECK(l.events.size() == 1);
746                 CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
747             }
748 
749             SECTION("case 14")
750             {
751                 uint8_t v[] = {'\"', 0x7F, 0xF3, 0xC0};
752                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
753                 CHECK(not json::accept(std::begin(v), std::end(v)));
754 
755                 json j_error;
756                 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
757                 CHECK(j_error.is_discarded());
758 
759                 SaxEventLogger l;
760                 CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
761                 CHECK(l.events.size() == 1);
762                 CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
763             }
764 
765             SECTION("case 15")
766             {
767                 uint8_t v[] = {'\"', 0x7F, 0xF4, 0x7F};
768                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
769                 CHECK(not json::accept(std::begin(v), std::end(v)));
770 
771                 json j_error;
772                 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
773                 CHECK(j_error.is_discarded());
774 
775                 SaxEventLogger l;
776                 CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
777                 CHECK(l.events.size() == 1);
778                 CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
779             }
780 
781             SECTION("case 16")
782             {
783                 uint8_t v[] = {'{', '\"', '\"', ':', '1', '1'};
784                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
785                 CHECK(not json::accept(std::begin(v), std::end(v)));
786 
787                 json j_error;
788                 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
789                 CHECK(j_error.is_discarded());
790 
791                 SaxEventLogger l;
792                 CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
793                 CHECK(l.events.size() == 4);
794                 CHECK(l.events == std::vector<std::string>(
795                 {
796                     "start_object()", "key()", "number_unsigned(11)",
797                     "parse_error(7)"
798                 }));
799             }
800         }
801     }
802 
803     SECTION("ignoring byte-order marks")
804     {
805         std::string bom = "\xEF\xBB\xBF";
806 
807         SECTION("BOM only")
808         {
809             json _;
810             CHECK_THROWS_AS(_ = json::parse(bom), json::parse_error&);
811             CHECK_THROWS_WITH(_ = json::parse(bom),
812                               "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal");
813 
814             CHECK_THROWS_AS(_ = json::parse(std::istringstream(bom)), json::parse_error&);
815             CHECK_THROWS_WITH(_ = json::parse(std::istringstream(bom)),
816                               "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal");
817 
818             SaxEventLogger l;
819             CHECK(not json::sax_parse(bom, &l));
820             CHECK(l.events.size() == 1);
821             CHECK(l.events == std::vector<std::string>(
822             {
823                 "parse_error(4)"
824             }));
825         }
826 
827         SECTION("BOM and content")
828         {
829             CHECK(json::parse(bom + "1") == 1);
830             CHECK(json::parse(std::istringstream(bom + "1")) == 1);
831 
832             SaxEventLogger l1, l2;
833             CHECK(json::sax_parse(std::istringstream(bom + "1"), &l1));
834             CHECK(json::sax_parse(bom + "1", &l2));
835             CHECK(l1.events.size() == 1);
836             CHECK(l1.events == std::vector<std::string>(
837             {
838                 "number_unsigned(1)"
839             }));
840             CHECK(l2.events.size() == 1);
841             CHECK(l2.events == std::vector<std::string>(
842             {
843                 "number_unsigned(1)"
844             }));
845         }
846 
847         SECTION("2 byte of BOM")
848         {
849             json _;
850             CHECK_THROWS_AS(_ = json::parse(bom.substr(0, 2)), json::parse_error&);
851             CHECK_THROWS_WITH(_ = json::parse(bom.substr(0, 2)),
852                               "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF\xBB'");
853 
854             CHECK_THROWS_AS(_ = json::parse(std::istringstream(bom.substr(0, 2))), json::parse_error&);
855             CHECK_THROWS_WITH(_ = json::parse(std::istringstream(bom.substr(0, 2))),
856                               "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF\xBB'");
857 
858             SaxEventLogger l1, l2;
859             CHECK(not json::sax_parse(std::istringstream(bom.substr(0, 2)), &l1));
860             CHECK(not json::sax_parse(bom.substr(0, 2), &l2));
861             CHECK(l1.events.size() == 1);
862             CHECK(l1.events == std::vector<std::string>(
863             {
864                 "parse_error(3)"
865             }));
866             CHECK(l2.events.size() == 1);
867             CHECK(l2.events == std::vector<std::string>(
868             {
869                 "parse_error(3)"
870             }));
871         }
872 
873         SECTION("1 byte of BOM")
874         {
875             json _;
876             CHECK_THROWS_AS(_ = json::parse(bom.substr(0, 1)), json::parse_error&);
877             CHECK_THROWS_WITH(_ = json::parse(bom.substr(0, 1)),
878                               "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF'");
879 
880             CHECK_THROWS_AS(_ = json::parse(std::istringstream(bom.substr(0, 1))), json::parse_error&);
881             CHECK_THROWS_WITH(_ = json::parse(std::istringstream(bom.substr(0, 1))),
882                               "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF'");
883 
884             SaxEventLogger l1, l2;
885             CHECK(not json::sax_parse(std::istringstream(bom.substr(0, 1)), &l1));
886             CHECK(not json::sax_parse(bom.substr(0, 1), &l2));
887             CHECK(l1.events.size() == 1);
888             CHECK(l1.events == std::vector<std::string>(
889             {
890                 "parse_error(2)"
891             }));
892             CHECK(l2.events.size() == 1);
893             CHECK(l2.events == std::vector<std::string>(
894             {
895                 "parse_error(2)"
896             }));
897         }
898 
899         SECTION("variations")
900         {
901             // calculate variations of each byte of the BOM to make sure
902             // that the BOM and only the BOM is skipped
903             for (int i0 = -1; i0 < 2; ++i0)
904             {
905                 for (int i1 = -1; i1 < 2; ++i1)
906                 {
907                     for (int i2 = -1; i2 < 2; ++i2)
908                     {
909                         // debug output for the variations
910                         CAPTURE(i0)
911                         CAPTURE(i1)
912                         CAPTURE(i2)
913 
914                         std::string s = "";
915                         s.push_back(static_cast<char>(bom[0] + i0));
916                         s.push_back(static_cast<char>(bom[1] + i1));
917                         s.push_back(static_cast<char>(bom[2] + i2));
918 
919                         if (i0 == 0 and i1 == 0 and i2 == 0)
920                         {
921                             // without any variation, we skip the BOM
922                             CHECK(json::parse(s + "null") == json());
923                             CHECK(json::parse(std::istringstream(s + "null")) == json());
924 
925                             SaxEventLogger l;
926                             CHECK(json::sax_parse(s + "null", &l));
927                             CHECK(l.events.size() == 1);
928                             CHECK(l.events == std::vector<std::string>(
929                             {
930                                 "null()"
931                             }));
932                         }
933                         else
934                         {
935                             // any variation is an error
936                             json _;
937                             CHECK_THROWS_AS(_ = json::parse(s + "null"), json::parse_error&);
938                             CHECK_THROWS_AS(_ = json::parse(std::istringstream(s + "null")), json::parse_error&);
939 
940                             SaxEventLogger l;
941                             CHECK(not json::sax_parse(s + "null", &l));
942                             CHECK(l.events.size() == 1);
943 
944                             if (i0 != 0)
945                             {
946                                 CHECK(l.events == std::vector<std::string>(
947                                 {
948                                     "parse_error(1)"
949                                 }));
950                             }
951                             else if (i1 != 0)
952                             {
953                                 CHECK(l.events == std::vector<std::string>(
954                                 {
955                                     "parse_error(2)"
956                                 }));
957                             }
958                             else
959                             {
960                                 CHECK(l.events == std::vector<std::string>(
961                                 {
962                                     "parse_error(3)"
963                                 }));
964                             }
965                         }
966                     }
967                 }
968             }
969         }
970 
971         SECTION("preserve state after parsing")
972         {
973             std::istringstream s(bom + "123 456");
974             json j;
975             j << s;
976             CHECK(j == 123);
977             j << s;
978             CHECK(j == 456);
979         }
980     }
981 
982     SECTION("SAX and early abort")
983     {
984         std::string s = "[1, [\"string\", 43.12], null, {\"key1\": true, \"key2\": false}]";
985 
986         SaxEventLogger default_logger;
987         SaxEventLoggerExitAfterStartObject exit_after_start_object;
988         SaxEventLoggerExitAfterKey exit_after_key;
989         SaxEventLoggerExitAfterStartArray exit_after_start_array;
990 
991         json::sax_parse(s, &default_logger);
992         CHECK(default_logger.events.size() == 14);
993         CHECK(default_logger.events == std::vector<std::string>(
994         {
995             "start_array()", "number_unsigned(1)", "start_array()",
996             "string(string)", "number_float(43.12)", "end_array()", "null()",
997             "start_object()", "key(key1)", "boolean(true)", "key(key2)",
998             "boolean(false)", "end_object()", "end_array()"
999         }));
1000 
1001         json::sax_parse(s, &exit_after_start_object);
1002         CHECK(exit_after_start_object.events.size() == 8);
1003         CHECK(exit_after_start_object.events == std::vector<std::string>(
1004         {
1005             "start_array()", "number_unsigned(1)", "start_array()",
1006             "string(string)", "number_float(43.12)", "end_array()", "null()",
1007             "start_object()"
1008         }));
1009 
1010         json::sax_parse(s, &exit_after_key);
1011         CHECK(exit_after_key.events.size() == 9);
1012         CHECK(exit_after_key.events == std::vector<std::string>(
1013         {
1014             "start_array()", "number_unsigned(1)", "start_array()",
1015             "string(string)", "number_float(43.12)", "end_array()", "null()",
1016             "start_object()", "key(key1)"
1017         }));
1018 
1019         json::sax_parse(s, &exit_after_start_array);
1020         CHECK(exit_after_start_array.events.size() == 1);
1021         CHECK(exit_after_start_array.events == std::vector<std::string>(
1022         {
1023             "start_array()"
1024         }));
1025     }
1026 }
1027