xref: /third_party/skia/tests/JSONTest.cpp (revision cb93a386)
1/*
2 * Copyright 2018 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "tests/Test.h"
9
10#include "include/core/SkStream.h"
11#include "include/core/SkString.h"
12#include "src/core/SkArenaAlloc.h"
13#include "src/utils/SkJSON.h"
14
15using namespace skjson;
16
17DEF_TEST(JSON_Parse, reporter) {
18    static constexpr struct {
19        const char* in;
20        const char* out;
21    } g_tests[] = {
22        { ""     , nullptr },
23        { "["    , nullptr },
24        { "]"    , nullptr },
25        { "[[]"  , nullptr },
26        { "[]]"  , nullptr },
27        { "[]f"  , nullptr },
28        { "{"    , nullptr },
29        { "}"    , nullptr },
30        { "{{}"  , nullptr },
31        { "{}}"  , nullptr },
32        { "{}f"  , nullptr },
33        { "{]"   , nullptr },
34        { "[}"   , nullptr },
35        { "{\"}" , nullptr },
36        { "[\"]" , nullptr },
37        { "1"    , nullptr },
38        { "true" , nullptr },
39        { "false", nullptr },
40        { "null" , nullptr },
41
42        { "[nulll]" , nullptr },
43        { "[false2]", nullptr },
44        { "[true:]" , nullptr },
45
46        { "[1 2]"   , nullptr },
47        { "[1,,2]"  , nullptr },
48        { "[1,2,]"  , nullptr },
49        { "[,1,2]"  , nullptr },
50
51        { "[ \"foo"       , nullptr },
52        { "[ \"fo\0o\" ]" , nullptr },
53
54        { "{\"\":{}"                  , nullptr },
55        { "{ null }"                  , nullptr },
56        { "{ \"k\" : }"               , nullptr },
57        { "{ : null }"                , nullptr },
58        { "{ \"k\" : : null }"        , nullptr },
59        { "{ \"k\" : null , }"        , nullptr },
60        { "{ \"k\" : null \"k\" : 1 }", nullptr },
61
62        {R"zzz(["\)zzz"      , nullptr},
63        {R"zzz(["\])zzz"     , nullptr},
64        {R"zzz(["\"])zzz"    , nullptr},
65        {R"zzz(["\z"])zzz"   , nullptr},
66        {R"zzz(["\u"])zzz"   , nullptr},
67        {R"zzz(["\u0"])zzz"  , nullptr},
68        {R"zzz(["\u00"])zzz" , nullptr},
69        {R"zzz(["\u000"])zzz", nullptr},
70
71        { "[]"                           , "[]" },
72        { " \n\r\t [ \n\r\t ] \n\r\t "   , "[]" },
73        { "[[]]"                         , "[[]]" },
74        { "[ null ]"                     , "[null]" },
75        { "[ true ]"                     , "[true]" },
76        { "[ false ]"                    , "[false]" },
77        { "[ 0 ]"                        , "[0]" },
78        { "[ 1 ]"                        , "[1]" },
79        { "[ 1.248 ]"                    , "[1.248]" },
80        { "[ \"\" ]"                     , "[\"\"]" },
81        { "[ \"foo{bar}baz\" ]"          , "[\"foo{bar}baz\"]" },
82        { "[ \" f o o \" ]"              , "[\" f o o \"]" },
83        { "[ \"123456\" ]"               , "[\"123456\"]" },
84        { "[ \"1234567\" ]"              , "[\"1234567\"]" },
85        { "[ \"12345678\" ]"             , "[\"12345678\"]" },
86        { "[ \"123456789\" ]"            , "[\"123456789\"]" },
87        { "[ null , true, false,0,12.8 ]", "[null,true,false,0,12.8]" },
88
89        { "{}"                          , "{}" },
90        { " \n\r\t { \n\r\t } \n\r\t "  , "{}" },
91        { "{ \"k\" : null }"            , "{\"k\":null}" },
92        { "{ \"foo{\" : \"bar}baz\" }"  , "{\"foo{\":\"bar}baz\"}" },
93        { "{ \"k1\" : null, \"k2 \":0 }", "{\"k1\":null,\"k2 \":0}" },
94        { "{ \"k1\" : null, \"k1\":0 }" , "{\"k1\":null,\"k1\":0}" },
95
96        { "{ \"k1\" : null,                   \n\
97             \"k2\" : 0,                      \n\
98             \"k3\" : [                       \n\
99                        true,                 \r\n\
100                        { \"kk1\" : \"foo\" , \n\
101                          \"kk2\" : \"bar\" , \n\
102                          \"kk3\" : 1.28 ,    \n\
103                          \"kk4\" : [ 42 ]    \n\
104                        } ,                   \n\
105                        \"boo\" ,             \n\
106                        null                  \n\
107                      ]                       \n\
108           }",
109          "{\"k1\":null,\"k2\":0,\"k3\":[true,"
110              "{\"kk1\":\"foo\",\"kk2\":\"bar\",\"kk3\":1.28,\"kk4\":[42]},\"boo\",null]}" },
111
112        {R"zzz(["\""])zzz"    , "[\"\"\"]"},
113        {R"zzz(["\\"])zzz"    , "[\"\\\"]"},
114        {R"zzz(["\/"])zzz"    , "[\"/\"]" },
115        {R"zzz(["\b"])zzz"    , "[\"\b\"]"},
116        {R"zzz(["\f"])zzz"    , "[\"\f\"]"},
117        {R"zzz(["\n"])zzz"    , "[\"\n\"]"},
118        {R"zzz(["\r"])zzz"    , "[\"\r\"]"},
119        {R"zzz(["\t"])zzz"    , "[\"\t\"]"},
120        {R"zzz(["\u1234"])zzz", "[\"\u1234\"]"},
121
122        {R"zzz(["foo\"bar"])zzz"    , "[\"foo\"bar\"]"},
123        {R"zzz(["foo\\bar"])zzz"    , "[\"foo\\bar\"]"},
124        {R"zzz(["foo\/bar"])zzz"    , "[\"foo/bar\"]" },
125        {R"zzz(["foo\bbar"])zzz"    , "[\"foo\bbar\"]"},
126        {R"zzz(["foo\fbar"])zzz"    , "[\"foo\fbar\"]"},
127        {R"zzz(["foo\nbar"])zzz"    , "[\"foo\nbar\"]"},
128        {R"zzz(["foo\rbar"])zzz"    , "[\"foo\rbar\"]"},
129        {R"zzz(["foo\tbar"])zzz"    , "[\"foo\tbar\"]"},
130        {R"zzz(["foo\u1234bar"])zzz", "[\"foo\u1234bar\"]"},
131    };
132
133    for (const auto& tst : g_tests) {
134        DOM dom(tst.in, strlen(tst.in));
135        const auto success = !dom.root().is<NullValue>();
136        REPORTER_ASSERT(reporter, success == (tst.out != nullptr));
137        if (!success) continue;
138
139        SkDynamicMemoryWStream str;
140        dom.write(&str);
141        str.write8('\0');
142
143        auto data = str.detachAsData();
144        REPORTER_ASSERT(reporter, !strcmp(tst.out, static_cast<const char*>(data->data())));
145    }
146
147}
148
149template <typename T, typename VT>
150static void check_primitive(skiatest::Reporter* reporter, const Value& v, T pv,
151                            bool is_type) {
152
153    REPORTER_ASSERT(reporter,  v.is<VT>() == is_type);
154    const VT* cast_t = v;
155    REPORTER_ASSERT(reporter, (cast_t != nullptr) == is_type);
156
157    if (is_type) {
158        REPORTER_ASSERT(reporter, &v.as<VT>() == cast_t);
159        REPORTER_ASSERT(reporter, *v.as<VT>() == pv);
160    }
161}
162
163template <typename T>
164static void check_vector(skiatest::Reporter* reporter, const Value& v, size_t expected_size,
165                         bool is_vector) {
166    REPORTER_ASSERT(reporter, v.is<T>() == is_vector);
167    const T* cast_t = v;
168    REPORTER_ASSERT(reporter, (cast_t != nullptr) == is_vector);
169
170    if (is_vector) {
171        const auto& vec = v.as<T>();
172        REPORTER_ASSERT(reporter, &vec == cast_t);
173        REPORTER_ASSERT(reporter, vec.size()  == expected_size);
174        REPORTER_ASSERT(reporter, vec.begin() != nullptr);
175        REPORTER_ASSERT(reporter, vec.end()   == vec.begin() + expected_size);
176    }
177}
178
179static void check_string(skiatest::Reporter* reporter, const Value& v, const char* s) {
180    check_vector<StringValue>(reporter, v, s ? strlen(s) : 0, !!s);
181    if (s) {
182        REPORTER_ASSERT(reporter, !strcmp(v.as<StringValue>().begin(), s));
183    }
184}
185
186DEF_TEST(JSON_DOM_visit, reporter) {
187    static constexpr char json[] = "{ \n\
188        \"k1\": null,                \n\
189        \"k2\": false,               \n\
190        \"k3\": true,                \n\
191        \"k4\": 42,                  \n\
192        \"k5\": .75,                 \n\
193        \"k6\": \"foo\",             \n\
194        \"k7\": [ 1, true, \"bar\" ], \n\
195        \"k8\": { \"kk1\": 2, \"kk2\": false, \"kk1\": \"baz\" } \n\
196    }";
197
198    DOM dom(json, strlen(json));
199
200    const auto& jroot = dom.root().as<ObjectValue>();
201    REPORTER_ASSERT(reporter, jroot.is<ObjectValue>());
202
203    {
204        const auto& v = jroot["k1"];
205        REPORTER_ASSERT(reporter,  v.is<NullValue>());
206
207        check_primitive<bool, BoolValue>(reporter, v, false, false);
208        check_primitive<float, NumberValue>(reporter, v, 0, false);
209
210        check_string(reporter, v, nullptr);
211        check_vector<ArrayValue >(reporter, v, 0, false);
212        check_vector<ObjectValue>(reporter, v, 0, false);
213    }
214
215    {
216        const auto& v = jroot["k2"];
217        REPORTER_ASSERT(reporter, !v.is<NullValue>());
218
219        check_primitive<bool, BoolValue>(reporter, v, false, true);
220        check_primitive<float, NumberValue>(reporter, v, 0, false);
221
222        check_string(reporter, v, nullptr);
223        check_vector<ArrayValue >(reporter, v, 0, false);
224        check_vector<ObjectValue>(reporter, v, 0, false);
225    }
226
227    {
228        const auto& v = jroot["k3"];
229        REPORTER_ASSERT(reporter, !v.is<NullValue>());
230
231        check_primitive<bool, BoolValue>(reporter, v, true, true);
232        check_primitive<float, NumberValue>(reporter, v, 0, false);
233
234        check_string(reporter, v, nullptr);
235        check_vector<ArrayValue >(reporter, v, 0, false);
236        check_vector<ObjectValue>(reporter, v, 0, false);
237    }
238
239    {
240        const auto& v = jroot["k4"];
241        REPORTER_ASSERT(reporter, !v.is<NullValue>());
242
243        check_primitive<bool, BoolValue>(reporter, v, false, false);
244        check_primitive<float, NumberValue>(reporter, v, 42, true);
245
246        check_string(reporter, v, nullptr);
247        check_vector<ArrayValue >(reporter, v, 0, false);
248        check_vector<ObjectValue>(reporter, v, 0, false);
249    }
250
251    {
252        const auto& v = jroot["k5"];
253        REPORTER_ASSERT(reporter, !v.is<NullValue>());
254
255        check_primitive<bool, BoolValue>(reporter, v, false, false);
256        check_primitive<float, NumberValue>(reporter, v, .75f, true);
257
258        check_string(reporter, v, nullptr);
259        check_vector<ArrayValue >(reporter, v, 0, false);
260        check_vector<ObjectValue>(reporter, v, 0, false);
261    }
262
263    {
264        const auto& v = jroot["k6"];
265        REPORTER_ASSERT(reporter, !v.is<NullValue>());
266
267        check_primitive<bool, BoolValue>(reporter, v, false, false);
268        check_primitive<float, NumberValue>(reporter, v, 0, false);
269
270        check_string(reporter, v, "foo");
271        check_vector<ArrayValue >(reporter, v, 0, false);
272        check_vector<ObjectValue>(reporter, v, 0, false);
273    }
274
275    {
276        const auto& v = jroot["k7"];
277        REPORTER_ASSERT(reporter, !v.is<NullValue>());
278
279        check_primitive<bool, BoolValue>(reporter, v, false, false);
280        check_primitive<float, NumberValue>(reporter, v, 0, false);
281
282        check_string(reporter, v, nullptr);
283        check_vector<ObjectValue>(reporter, v, 0, false);
284
285        check_vector<ArrayValue >(reporter, v, 3, true);
286        check_primitive<float, NumberValue>(reporter, v.as<ArrayValue>()[0], 1, true);
287        check_primitive<bool, BoolValue>(reporter, v.as<ArrayValue>()[1], true, true);
288        check_vector<StringValue>(reporter, v.as<ArrayValue>()[2], 3, true);
289    }
290
291    {
292        const auto& v = jroot["k8"];
293        REPORTER_ASSERT(reporter, !v.is<NullValue>());
294
295        check_primitive<bool, BoolValue>(reporter, v, false, false);
296        check_primitive<float, NumberValue>(reporter, v, 0, false);
297
298        check_string(reporter, v, nullptr);
299        check_vector<ArrayValue >(reporter, v, 0, false);
300
301        check_vector<ObjectValue>(reporter, v, 3, true);
302
303        const auto& m0 = v.as<ObjectValue>().begin()[0];
304        check_string(reporter, m0.fKey, "kk1");
305        check_primitive<float, NumberValue>(reporter, m0.fValue, 2, true);
306
307        const auto& m1 = v.as<ObjectValue>().begin()[1];
308        check_string(reporter, m1.fKey, "kk2");
309        check_primitive<bool, BoolValue>(reporter, m1.fValue, false, true);
310
311        const auto& m2 = v.as<ObjectValue>().begin()[2];
312        check_string(reporter, m2.fKey, "kk1");
313        check_string(reporter, m2.fValue, "baz");
314
315        REPORTER_ASSERT(reporter, v.as<ObjectValue>()[""].is<NullValue>());
316        REPORTER_ASSERT(reporter, v.as<ObjectValue>()["nosuchkey"].is<NullValue>());
317        check_string(reporter, v.as<ObjectValue>()["kk1"], "baz");
318        check_primitive<bool, BoolValue>(reporter, v.as<ObjectValue>()["kk2"], false, true);
319    }
320}
321
322template <typename T>
323void check_value(skiatest::Reporter* reporter, const Value& v, const char* expected_string) {
324    REPORTER_ASSERT(reporter, v.is<T>());
325
326    const T* cast_t = v;
327    REPORTER_ASSERT(reporter, cast_t == &v.as<T>());
328
329    const auto vstr = v.toString();
330    REPORTER_ASSERT(reporter, 0 == strcmp(expected_string, vstr.c_str()));
331}
332
333DEF_TEST(JSON_DOM_build, reporter) {
334    SkArenaAlloc alloc(4096);
335
336    const auto v0  = NullValue();
337    check_value<NullValue>(reporter, v0, "null");
338
339    const auto v1  = BoolValue(true);
340    check_value<BoolValue>(reporter, v1, "true");
341
342    const auto v2  = BoolValue(false);
343    check_value<BoolValue>(reporter, v2, "false");
344
345    const auto v3  = NumberValue(0);
346    check_value<NumberValue>(reporter, v3, "0");
347
348    const auto v4  = NumberValue(42);
349    check_value<NumberValue>(reporter, v4, "42");
350
351    const auto v5  = NumberValue(42.75f);
352    check_value<NumberValue>(reporter, v5, "42.75");
353
354    const auto v6  = StringValue(nullptr, 0, alloc);
355    check_value<StringValue>(reporter, v6, "\"\"");
356
357    const auto v7  = StringValue(" foo ", 5, alloc);
358    check_value<StringValue>(reporter, v7, "\" foo \"");
359
360    const auto v8  = StringValue(" foo bar baz ", 13, alloc);
361    check_value<StringValue>(reporter, v8, "\" foo bar baz \"");
362
363    const auto v9  = ArrayValue(nullptr, 0, alloc);
364    check_value<ArrayValue>(reporter, v9, "[]");
365
366    const Value values0[] = { v0, v3, v9 };
367    const auto v10 = ArrayValue(values0, SK_ARRAY_COUNT(values0), alloc);
368    check_value<ArrayValue>(reporter, v10, "[null,0,[]]");
369
370    const auto v11 = ObjectValue(nullptr, 0, alloc);
371    check_value<ObjectValue>(reporter, v11, "{}");
372
373    const Member members0[] = {
374        { StringValue("key_0", 5, alloc), v1  },
375        { StringValue("key_1", 5, alloc), v4  },
376        { StringValue("key_2", 5, alloc), v11 },
377    };
378    const auto v12 = ObjectValue(members0, SK_ARRAY_COUNT(members0), alloc);
379    check_value<ObjectValue>(reporter, v12, "{"
380                                                "\"key_0\":true,"
381                                                "\"key_1\":42,"
382                                                "\"key_2\":{}"
383                                            "}");
384
385    const Value values1[] = { v2, v6, v12 };
386    const auto v13 = ArrayValue(values1, SK_ARRAY_COUNT(values1), alloc);
387    check_value<ArrayValue>(reporter, v13, "["
388                                               "false,"
389                                               "\"\","
390                                               "{"
391                                                   "\"key_0\":true,"
392                                                   "\"key_1\":42,"
393                                                   "\"key_2\":{}"
394                                               "}"
395                                           "]");
396
397    const Member members1[] = {
398        { StringValue("key_00", 6, alloc), v5  },
399        { StringValue("key_01", 6, alloc), v7  },
400        { StringValue("key_02", 6, alloc), v13 },
401    };
402    const auto v14 = ObjectValue(members1, SK_ARRAY_COUNT(members1), alloc);
403    check_value<ObjectValue>(reporter, v14, "{"
404                                                "\"key_00\":42.75,"
405                                                "\"key_01\":\" foo \","
406                                                "\"key_02\":["
407                                                                "false,"
408                                                                "\"\","
409                                                                "{"
410                                                                    "\"key_0\":true,"
411                                                                    "\"key_1\":42,"
412                                                                    "\"key_2\":{}"
413                                                                "}"
414                                                            "]"
415                                            "}");
416}
417
418DEF_TEST(JSON_ParseNumber, reporter) {
419    static constexpr struct {
420        const char* string;
421        SkScalar    value,
422                    tolerance;
423    } gTests[] = {
424        { "0", 0, 0 },
425        { "1", 1, 0 },
426
427        { "00000000", 0, 0 },
428        { "00000001", 1, 0 },
429
430        { "0.001", 0.001f, 0 },
431        { "1.001", 1.001f, 0 },
432
433        { "0.000001"   ,    0.000001f, 0 },
434        { "1.000001"   ,    1.000001f, 0 },
435        { "1000.000001", 1000.000001f, 0 },
436
437        { "0.0000000001"   ,    0.0000000001f, 0 },
438        { "1.0000000001"   ,    1.0000000001f, 0 },
439        { "1000.0000000001", 1000.0000000001f, 0 },
440
441        { "20.001111814444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444473",
442          20.001f, 0.001f },
443    };
444
445    for (const auto& test : gTests) {
446        const auto json = SkStringPrintf("{ \"key\": %s }", test.string);
447        const DOM dom(json.c_str(), json.size());
448        const ObjectValue* jroot = dom.root();
449
450        REPORTER_ASSERT(reporter, jroot);
451
452        const NumberValue* jnumber = (*jroot)["key"];
453        REPORTER_ASSERT(reporter, jnumber);
454        REPORTER_ASSERT(reporter, SkScalarNearlyEqual(**jnumber, test.value, test.tolerance));
455    }
456}
457