Update configs. IGNORE BROKEN CHANGESETS CLOSED TREE NO BUG a=release ba=release
[gecko.git] / mfbt / tests / TestJSONWriter.cpp
bloba90732396f284b25cad38ef10b9654968e8c22f9
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/Assertions.h"
8 #include "mozilla/JSONWriter.h"
9 #include "mozilla/UniquePtr.h"
10 #include <stdio.h>
11 #include <string>
12 #include <string.h>
14 using mozilla::JSONWriteFunc;
15 using mozilla::JSONWriter;
16 using mozilla::MakeStringSpan;
17 using mozilla::MakeUnique;
18 using mozilla::Span;
20 // This writes all the output into a big buffer.
21 struct StringWriteFunc final : public JSONWriteFunc {
22 std::string mString;
24 void Write(const mozilla::Span<const char>& aStr) final {
25 mString.append(aStr.data(), aStr.size());
29 void Check(JSONWriter& aWriter, const char* aExpected) {
30 JSONWriteFunc& func = aWriter.WriteFunc();
31 const std::string& actual = static_cast<StringWriteFunc&>(func).mString;
32 if (strcmp(aExpected, actual.c_str()) != 0) {
33 fprintf(stderr,
34 "---- EXPECTED ----\n<<<%s>>>\n"
35 "---- ACTUAL ----\n<<<%s>>>\n",
36 aExpected, actual.c_str());
37 MOZ_RELEASE_ASSERT(false, "expected and actual output don't match");
41 // Note: to convert actual output into |expected| strings that C++ can handle,
42 // apply the following substitutions, in order, to each line.
43 // - s/\\/\\\\/g # escapes backslashes
44 // - s/"/\\"/g # escapes quotes
45 // - s/$/\\n\\/ # adds a newline and string continuation char to each line
47 void TestBasicProperties() {
48 const char* expected =
50 {\n\
51 \"null\": null,\n\
52 \"bool1\": true,\n\
53 \"bool2\": false,\n\
54 \"int1\": 123,\n\
55 \"int2\": -123,\n\
56 \"int3\": -123456789000,\n\
57 \"double1\": 1.2345,\n\
58 \"double2\": -3,\n\
59 \"double3\": 1e-7,\n\
60 \"double4\": 1.1111111111111111e+21,\n\
61 \"string1\": \"\",\n\
62 \"string2\": \"1234\",\n\
63 \"string3\": \"hello\",\n\
64 \"string4\": \"\\\" \\\\ \\u0007 \\b \\t \\n \\u000b \\f \\r\",\n\
65 \"string5\": \"hello\",\n\
66 \"string6\": \"\\\" \\\\ \\u0007 \\b \\t \",\n\
67 \"span1\": \"buf1\",\n\
68 \"span2\": \"buf2\",\n\
69 \"span3\": \"buf3\",\n\
70 \"span4\": \"buf\\n4\",\n\
71 \"span5\": \"MakeStringSpan\",\n\
72 \"len 0 array, multi-line\": [\n\
73 ],\n\
74 \"len 0 array, single-line\": [],\n\
75 \"len 1 array\": [\n\
76 1\n\
77 ],\n\
78 \"len 5 array, multi-line\": [\n\
79 1,\n\
80 2,\n\
81 3,\n\
82 4,\n\
83 5\n\
84 ],\n\
85 \"len 3 array, single-line\": [1, [{}, 2, []], 3],\n\
86 \"len 0 object, multi-line\": {\n\
87 },\n\
88 \"len 0 object, single-line\": {},\n\
89 \"len 1 object\": {\n\
90 \"one\": 1\n\
91 },\n\
92 \"len 5 object\": {\n\
93 \"one\": 1,\n\
94 \"two\": 2,\n\
95 \"three\": 3,\n\
96 \"four\": 4,\n\
97 \"five\": 5\n\
98 },\n\
99 \"len 3 object, single-line\": {\"a\": 1, \"b\": [{}, 2, []], \"c\": 3}\n\
100 }\n\
103 JSONWriter w(MakeUnique<StringWriteFunc>());
105 w.Start();
107 w.NullProperty("null");
109 w.BoolProperty("bool1", true);
110 w.BoolProperty("bool2", false);
112 w.IntProperty("int1", 123);
113 w.IntProperty("int2", -0x7b);
114 w.IntProperty("int3", -123456789000ll);
116 w.DoubleProperty("double1", 1.2345);
117 w.DoubleProperty("double2", -3);
118 w.DoubleProperty("double3", 1e-7);
119 w.DoubleProperty("double4", 1.1111111111111111e+21);
121 w.StringProperty("string1", "");
122 w.StringProperty("string2", "1234");
123 w.StringProperty("string3", "hello");
124 w.StringProperty("string4", "\" \\ \a \b \t \n \v \f \r");
125 w.StringProperty("string5", "hello\0cut"); // '\0' marks the end.
126 w.StringProperty("string6", "\" \\ \a \b \t \0 \n \v \f \r");
128 const char buf1[] = {'b', 'u', 'f', '1'};
129 w.StringProperty("span1", buf1);
130 const char buf2[] = {'b', 'u', 'f', '2', '\0'};
131 w.StringProperty("span2", buf2);
132 const char buf3[] = {'b', 'u', 'f', '3', '\0', '?'};
133 w.StringProperty("span3", buf3);
134 const char buf4[] = {'b', 'u', 'f', '\n', '4', '\0', '?'};
135 w.StringProperty("span4", buf4);
136 w.StringProperty("span5", MakeStringSpan("MakeStringSpan"));
138 w.StartArrayProperty("len 0 array, multi-line", w.MultiLineStyle);
139 w.EndArray();
141 w.StartArrayProperty("len 0 array, single-line", w.SingleLineStyle);
142 w.EndArray();
144 w.StartArrayProperty("len 1 array");
145 { w.IntElement(1); }
146 w.EndArray();
148 w.StartArrayProperty("len 5 array, multi-line", w.MultiLineStyle);
150 w.IntElement(1);
151 w.IntElement(2);
152 w.IntElement(3);
153 w.IntElement(4);
154 w.IntElement(5);
156 w.EndArray();
158 w.StartArrayProperty("len 3 array, single-line", w.SingleLineStyle);
160 w.IntElement(1);
161 w.StartArrayElement();
163 w.StartObjectElement(w.SingleLineStyle);
164 w.EndObject();
166 w.IntElement(2);
168 w.StartArrayElement(w.MultiLineStyle); // style overridden from above
169 w.EndArray();
171 w.EndArray();
172 w.IntElement(3);
174 w.EndArray();
176 w.StartObjectProperty("len 0 object, multi-line");
177 w.EndObject();
179 w.StartObjectProperty("len 0 object, single-line", w.SingleLineStyle);
180 w.EndObject();
182 w.StartObjectProperty("len 1 object");
183 { w.IntProperty("one", 1); }
184 w.EndObject();
186 w.StartObjectProperty("len 5 object");
188 w.IntProperty("one", 1);
189 w.IntProperty("two", 2);
190 w.IntProperty("three", 3);
191 w.IntProperty("four", 4);
192 w.IntProperty("five", 5);
194 w.EndObject();
196 w.StartObjectProperty("len 3 object, single-line", w.SingleLineStyle);
198 w.IntProperty("a", 1);
199 w.StartArrayProperty("b");
201 w.StartObjectElement();
202 w.EndObject();
204 w.IntElement(2);
206 w.StartArrayElement(w.SingleLineStyle);
207 w.EndArray();
209 w.EndArray();
210 w.IntProperty("c", 3);
212 w.EndObject();
214 w.End();
216 Check(w, expected);
219 void TestBasicElements() {
220 const char* expected =
222 {\n\
223 \"array\": [\n\
224 null,\n\
225 true,\n\
226 false,\n\
227 123,\n\
228 -123,\n\
229 -123456789000,\n\
230 1.2345,\n\
231 -3,\n\
232 1e-7,\n\
233 1.1111111111111111e+21,\n\
234 \"\",\n\
235 \"1234\",\n\
236 \"hello\",\n\
237 \"\\\" \\\\ \\u0007 \\b \\t \\n \\u000b \\f \\r\",\n\
238 \"hello\",\n\
239 \"\\\" \\\\ \\u0007 \\b \\t \",\n\
240 \"buf1\",\n\
241 \"buf2\",\n\
242 \"buf3\",\n\
243 \"buf\\n4\",\n\
244 \"MakeStringSpan\",\n\
245 [\n\
246 ],\n\
247 [],\n\
248 [\n\
249 1\n\
250 ],\n\
251 [\n\
252 1,\n\
253 2,\n\
254 3,\n\
255 4,\n\
256 5\n\
257 ],\n\
258 [1, [{}, 2, []], 3],\n\
259 {\n\
260 },\n\
261 {},\n\
262 {\n\
263 \"one\": 1\n\
264 },\n\
265 {\n\
266 \"one\": 1,\n\
267 \"two\": 2,\n\
268 \"three\": 3,\n\
269 \"four\": 4,\n\
270 \"five\": 5\n\
271 },\n\
272 {\"a\": 1, \"b\": [{}, 2, []], \"c\": 3}\n\
273 ]\n\
274 }\n\
277 JSONWriter w(MakeUnique<StringWriteFunc>());
279 w.Start();
280 w.StartArrayProperty("array");
282 w.NullElement();
284 w.BoolElement(true);
285 w.BoolElement(false);
287 w.IntElement(123);
288 w.IntElement(-0x7b);
289 w.IntElement(-123456789000ll);
291 w.DoubleElement(1.2345);
292 w.DoubleElement(-3);
293 w.DoubleElement(1e-7);
294 w.DoubleElement(1.1111111111111111e+21);
296 w.StringElement("");
297 w.StringElement("1234");
298 w.StringElement("hello");
299 w.StringElement("\" \\ \a \b \t \n \v \f \r");
300 w.StringElement("hello\0cut"); // '\0' marks the end.
301 w.StringElement("\" \\ \a \b \t \0 \n \v \f \r");
303 const char buf1[] = {'b', 'u', 'f', '1'};
304 w.StringElement(buf1);
305 const char buf2[] = {'b', 'u', 'f', '2', '\0'};
306 w.StringElement(buf2);
307 const char buf3[] = {'b', 'u', 'f', '3', '\0', '?'};
308 w.StringElement(buf3);
309 const char buf4[] = {'b', 'u', 'f', '\n', '4', '\0', '?'};
310 w.StringElement(buf4);
311 w.StringElement(MakeStringSpan("MakeStringSpan"));
313 w.StartArrayElement();
314 w.EndArray();
316 w.StartArrayElement(w.SingleLineStyle);
317 w.EndArray();
319 w.StartArrayElement();
320 { w.IntElement(1); }
321 w.EndArray();
323 w.StartArrayElement();
325 w.IntElement(1);
326 w.IntElement(2);
327 w.IntElement(3);
328 w.IntElement(4);
329 w.IntElement(5);
331 w.EndArray();
333 w.StartArrayElement(w.SingleLineStyle);
335 w.IntElement(1);
336 w.StartArrayElement();
338 w.StartObjectElement(w.SingleLineStyle);
339 w.EndObject();
341 w.IntElement(2);
343 w.StartArrayElement(w.MultiLineStyle); // style overridden from above
344 w.EndArray();
346 w.EndArray();
347 w.IntElement(3);
349 w.EndArray();
351 w.StartObjectElement();
352 w.EndObject();
354 w.StartObjectElement(w.SingleLineStyle);
355 w.EndObject();
357 w.StartObjectElement();
358 { w.IntProperty("one", 1); }
359 w.EndObject();
361 w.StartObjectElement();
363 w.IntProperty("one", 1);
364 w.IntProperty("two", 2);
365 w.IntProperty("three", 3);
366 w.IntProperty("four", 4);
367 w.IntProperty("five", 5);
369 w.EndObject();
371 w.StartObjectElement(w.SingleLineStyle);
373 w.IntProperty("a", 1);
374 w.StartArrayProperty("b");
376 w.StartObjectElement();
377 w.EndObject();
379 w.IntElement(2);
381 w.StartArrayElement(w.SingleLineStyle);
382 w.EndArray();
384 w.EndArray();
385 w.IntProperty("c", 3);
387 w.EndObject();
389 w.EndArray();
390 w.End();
392 Check(w, expected);
395 void TestOneLineObject() {
396 const char* expected =
398 {\"i\": 1, \"array\": [null, [{}], {\"o\": {}}, \"s\"], \"d\": 3.33}\n\
401 JSONWriter w(MakeUnique<StringWriteFunc>());
403 w.Start(w.SingleLineStyle);
405 w.IntProperty("i", 1);
407 w.StartArrayProperty("array");
409 w.NullElement();
411 w.StartArrayElement(w.MultiLineStyle); // style overridden from above
413 w.StartObjectElement();
414 w.EndObject();
416 w.EndArray();
418 w.StartObjectElement();
420 w.StartObjectProperty("o");
421 w.EndObject();
423 w.EndObject();
425 w.StringElement("s");
427 w.EndArray();
429 w.DoubleProperty("d", 3.33);
431 w.End();
433 Check(w, expected);
436 void TestOneLineJson() {
437 const char* expected =
439 {\"i\":1,\"array\":[null,[{}],{\"o\":{}},\"s\"],\"d\":3.33}\
442 StringWriteFunc func;
443 JSONWriter w(func, JSONWriter::SingleLineStyle);
445 w.Start(w.MultiLineStyle); // style overridden from above
447 w.IntProperty("i", 1);
449 w.StartArrayProperty("array");
451 w.NullElement();
453 w.StartArrayElement(w.MultiLineStyle); // style overridden from above
455 w.StartObjectElement();
456 w.EndObject();
458 w.EndArray();
460 w.StartObjectElement();
462 w.StartObjectProperty("o");
463 w.EndObject();
465 w.EndObject();
467 w.StringElement("s");
469 w.EndArray();
471 w.DoubleProperty("d", 3.33);
473 w.End(); // No newline in this case.
475 Check(w, expected);
478 void TestStringEscaping() {
479 // This test uses hexadecimal character escapes because UTF8 literals cause
480 // problems for some compilers (see bug 1069726).
481 const char* expected =
483 {\n\
484 \"ascii\": \"\x7F~}|{zyxwvutsrqponmlkjihgfedcba`_^]\\\\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#\\\"! \\u001f\\u001e\\u001d\\u001c\\u001b\\u001a\\u0019\\u0018\\u0017\\u0016\\u0015\\u0014\\u0013\\u0012\\u0011\\u0010\\u000f\\u000e\\r\\f\\u000b\\n\\t\\b\\u0007\\u0006\\u0005\\u0004\\u0003\\u0002\\u0001\",\n\
485 \"\xD9\x85\xD8\xB1\xD8\xAD\xD8\xA8\xD8\xA7 \xD9\x87\xD9\x86\xD8\xA7\xD9\x83\": true,\n\
486 \"\xD5\xA2\xD5\xA1\xD6\x80\xD5\xA5\xD6\x82 \xD5\xB9\xD5\xAF\xD5\xA1\": -123,\n\
487 \"\xE4\xBD\xA0\xE5\xA5\xBD\": 1.234,\n\
488 \"\xCE\xB3\xCE\xB5\xCE\xB9\xCE\xB1 \xCE\xB5\xCE\xBA\xCE\xB5\xCE\xAF\": \"\xD8\xB3\xD9\x84\xD8\xA7\xD9\x85\",\n\
489 \"hall\xC3\xB3 \xC3\xBE"
490 "arna\": 4660,\n\
491 \"\xE3\x81\x93\xE3\x82\x93\xE3\x81\xAB\xE3\x81\xA1\xE3\x81\xAF\": {\n\
492 \"\xD0\xBF\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82\": [\n\
493 ]\n\
494 }\n\
495 }\n\
498 JSONWriter w(MakeUnique<StringWriteFunc>());
500 // Test the string escaping behaviour.
501 w.Start();
503 // Test all 127 ascii values. Do it in reverse order so that the 0
504 // at the end serves as the null char.
505 char buf[128];
506 for (int i = 0; i < 128; i++) {
507 buf[i] = 127 - i;
509 w.StringProperty("ascii", buf);
511 // Test lots of unicode stuff. Note that this file is encoded as UTF-8.
512 w.BoolProperty(
513 "\xD9\x85\xD8\xB1\xD8\xAD\xD8\xA8\xD8\xA7 "
514 "\xD9\x87\xD9\x86\xD8\xA7\xD9\x83",
515 true);
516 w.IntProperty(
517 "\xD5\xA2\xD5\xA1\xD6\x80\xD5\xA5\xD6\x82 \xD5\xB9\xD5\xAF\xD5\xA1",
518 -123);
519 w.DoubleProperty("\xE4\xBD\xA0\xE5\xA5\xBD", 1.234);
520 w.StringProperty(
521 "\xCE\xB3\xCE\xB5\xCE\xB9\xCE\xB1 \xCE\xB5\xCE\xBA\xCE\xB5\xCE\xAF",
522 "\xD8\xB3\xD9\x84\xD8\xA7\xD9\x85");
523 w.IntProperty(
524 "hall\xC3\xB3 \xC3\xBE"
525 "arna",
526 0x1234);
527 w.StartObjectProperty(
528 "\xE3\x81\x93\xE3\x82\x93\xE3\x81\xAB\xE3\x81\xA1\xE3\x81\xAF");
530 w.StartArrayProperty("\xD0\xBF\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82");
531 w.EndArray();
533 w.EndObject();
535 w.End();
537 Check(w, expected);
540 void TestDeepNesting() {
541 const char* expected =
543 {\n\
544 \"a\": [\n\
545 {\n\
546 \"a\": [\n\
547 {\n\
548 \"a\": [\n\
549 {\n\
550 \"a\": [\n\
551 {\n\
552 \"a\": [\n\
553 {\n\
554 \"a\": [\n\
555 {\n\
556 \"a\": [\n\
557 {\n\
558 \"a\": [\n\
559 {\n\
560 \"a\": [\n\
561 {\n\
562 \"a\": [\n\
563 {\n\
564 }\n\
565 ]\n\
566 }\n\
567 ]\n\
568 }\n\
569 ]\n\
570 }\n\
571 ]\n\
572 }\n\
573 ]\n\
574 }\n\
575 ]\n\
576 }\n\
577 ]\n\
578 }\n\
579 ]\n\
580 }\n\
581 ]\n\
582 }\n\
583 ]\n\
584 }\n\
587 JSONWriter w(MakeUnique<StringWriteFunc>());
589 w.Start();
591 static const int n = 10;
592 for (int i = 0; i < n; i++) {
593 w.StartArrayProperty("a");
594 w.StartObjectElement();
596 for (int i = 0; i < n; i++) {
597 w.EndObject();
598 w.EndArray();
601 w.End();
603 Check(w, expected);
606 void TestEscapedPropertyNames() {
607 const char* expected =
609 {\"i\\t\": 1, \"array\\t\": [null, [{}], {\"o\\t\": {}}, \"s\"], \"d\": 3.33}\n\
612 JSONWriter w(MakeUnique<StringWriteFunc>());
614 w.Start(w.SingleLineStyle);
616 w.IntProperty("i\t\0cut", 1); // '\0' marks the end.
618 w.StartArrayProperty("array\t");
620 w.NullElement();
622 w.StartArrayElement(w.MultiLineStyle); // style overridden from above
624 w.StartObjectElement();
625 w.EndObject();
627 w.EndArray();
629 w.StartObjectElement();
631 w.StartObjectProperty("o\t");
632 w.EndObject();
634 w.EndObject();
636 w.StringElement("s");
638 w.EndArray();
640 w.DoubleProperty("d\0\t", 3.33);
642 w.End();
644 Check(w, expected);
647 int main(void) {
648 TestBasicProperties();
649 TestBasicElements();
650 TestOneLineObject();
651 TestOneLineJson();
652 TestStringEscaping();
653 TestDeepNesting();
654 TestEscapedPropertyNames();
656 return 0;