capnproto

FORK: Cap'n Proto serialization/RPC system - core tools and C++ library
git clone https://git.neptards.moe/neptards/capnproto.git
Log | Files | Refs | README | LICENSE

json-test.c++ (41034B)


      1 // Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors
      2 // Licensed under the MIT License:
      3 //
      4 // Permission is hereby granted, free of charge, to any person obtaining a copy
      5 // of this software and associated documentation files (the "Software"), to deal
      6 // in the Software without restriction, including without limitation the rights
      7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      8 // copies of the Software, and to permit persons to whom the Software is
      9 // furnished to do so, subject to the following conditions:
     10 //
     11 // The above copyright notice and this permission notice shall be included in
     12 // all copies or substantial portions of the Software.
     13 //
     14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     20 // THE SOFTWARE.
     21 
     22 #include "json.h"
     23 #include <capnp/test-util.h>
     24 #include <capnp/compat/json.capnp.h>
     25 #include <capnp/compat/json-test.capnp.h>
     26 #include <kj/debug.h>
     27 #include <kj/string.h>
     28 #include <kj/test.h>
     29 
     30 namespace capnp {
     31 namespace _ {  // private
     32 namespace {
     33 
     34 KJ_TEST("basic json encoding") {
     35   JsonCodec json;
     36 
     37   KJ_EXPECT(json.encode(VOID) == "null");
     38   KJ_EXPECT(json.encode(true) == "true");
     39   KJ_EXPECT(json.encode(false) == "false");
     40   KJ_EXPECT(json.encode(123) == "123");
     41   KJ_EXPECT(json.encode(-5.5) == "-5.5");
     42   KJ_EXPECT(json.encode(Text::Reader("foo")) == "\"foo\"");
     43   KJ_EXPECT(json.encode(Text::Reader("ab\"cd\\ef\x03")) == "\"ab\\\"cd\\\\ef\\u0003\"");
     44   KJ_EXPECT(json.encode(test::TestEnum::CORGE) == "\"corge\"");
     45 
     46   byte bytes[] = {12, 34, 56};
     47   KJ_EXPECT(json.encode(Data::Reader(bytes, 3)) == "[12,34,56]");
     48 
     49   json.setPrettyPrint(true);
     50   KJ_EXPECT(json.encode(Data::Reader(bytes, 3)) == "[12, 34, 56]");
     51 }
     52 
     53 const char ALL_TYPES_JSON[] =
     54     "{ \"voidField\": null,\n"
     55     "  \"boolField\": true,\n"
     56     "  \"int8Field\": -123,\n"
     57     "  \"int16Field\": -12345,\n"
     58     "  \"int32Field\": -12345678,\n"
     59     "  \"int64Field\": \"-123456789012345\",\n"
     60     "  \"uInt8Field\": 234,\n"
     61     "  \"uInt16Field\": 45678,\n"
     62     "  \"uInt32Field\": 3456789012,\n"
     63     "  \"uInt64Field\": \"12345678901234567890\",\n"
     64     "  \"float32Field\": 1234.5,\n"
     65     "  \"float64Field\": -1.23e47,\n"
     66     "  \"textField\": \"foo\",\n"
     67     "  \"dataField\": [98, 97, 114],\n"
     68     "  \"structField\": {\n"
     69     "    \"voidField\": null,\n"
     70     "    \"boolField\": true,\n"
     71     "    \"int8Field\": -12,\n"
     72     "    \"int16Field\": 3456,\n"
     73     "    \"int32Field\": -78901234,\n"
     74     "    \"int64Field\": \"56789012345678\",\n"
     75     "    \"uInt8Field\": 90,\n"
     76     "    \"uInt16Field\": 1234,\n"
     77     "    \"uInt32Field\": 56789012,\n"
     78     "    \"uInt64Field\": \"345678901234567890\",\n"
     79     "    \"float32Field\": -1.2499999646475857e-10,\n"
     80     "    \"float64Field\": 345,\n"
     81     "    \"textField\": \"baz\",\n"
     82     "    \"dataField\": [113, 117, 120],\n"
     83     "    \"structField\": {\n"
     84     "      \"voidField\": null,\n"
     85     "      \"boolField\": false,\n"
     86     "      \"int8Field\": 0,\n"
     87     "      \"int16Field\": 0,\n"
     88     "      \"int32Field\": 0,\n"
     89     "      \"int64Field\": \"0\",\n"
     90     "      \"uInt8Field\": 0,\n"
     91     "      \"uInt16Field\": 0,\n"
     92     "      \"uInt32Field\": 0,\n"
     93     "      \"uInt64Field\": \"0\",\n"
     94     "      \"float32Field\": 0,\n"
     95     "      \"float64Field\": 0,\n"
     96     "      \"textField\": \"nested\",\n"
     97     "      \"structField\": {\"voidField\": null, \"boolField\": false, \"int8Field\": 0, \"int16Field\": 0, \"int32Field\": 0, \"int64Field\": \"0\", \"uInt8Field\": 0, \"uInt16Field\": 0, \"uInt32Field\": 0, \"uInt64Field\": \"0\", \"float32Field\": 0, \"float64Field\": 0, \"textField\": \"really nested\", \"enumField\": \"foo\", \"interfaceField\": null},\n"
     98     "      \"enumField\": \"foo\",\n"
     99     "      \"interfaceField\": null },\n"
    100     "    \"enumField\": \"baz\",\n"
    101     "    \"interfaceField\": null,\n"
    102     "    \"voidList\": [null, null, null],\n"
    103     "    \"boolList\": [false, true, false, true, true],\n"
    104     "    \"int8List\": [12, -34, -128, 127],\n"
    105     "    \"int16List\": [1234, -5678, -32768, 32767],\n"
    106     "    \"int32List\": [12345678, -90123456, -2147483648, 2147483647],\n"
    107     "    \"int64List\": [\"123456789012345\", \"-678901234567890\", \"-9223372036854775808\", \"9223372036854775807\"],\n"
    108     "    \"uInt8List\": [12, 34, 0, 255],\n"
    109     "    \"uInt16List\": [1234, 5678, 0, 65535],\n"
    110     "    \"uInt32List\": [12345678, 90123456, 0, 4294967295],\n"
    111     "    \"uInt64List\": [\"123456789012345\", \"678901234567890\", \"0\", \"18446744073709551615\"],\n"
    112     "    \"float32List\": [0, 1234567, 9.9999999338158125e36, -9.9999999338158125e36, 9.99999991097579e-38, -9.99999991097579e-38],\n"
    113     "    \"float64List\": [0, 123456789012345, 1e306, -1e306, 1e-306, -1e-306],\n"
    114     "    \"textList\": [\"quux\", \"corge\", \"grault\"],\n"
    115     "    \"dataList\": [[103, 97, 114, 112, 108, 121], [119, 97, 108, 100, 111], [102, 114, 101, 100]],\n"
    116     "    \"structList\": [\n"
    117     "      {\"voidField\": null, \"boolField\": false, \"int8Field\": 0, \"int16Field\": 0, \"int32Field\": 0, \"int64Field\": \"0\", \"uInt8Field\": 0, \"uInt16Field\": 0, \"uInt32Field\": 0, \"uInt64Field\": \"0\", \"float32Field\": 0, \"float64Field\": 0, \"textField\": \"x structlist 1\", \"enumField\": \"foo\", \"interfaceField\": null},\n"
    118     "      {\"voidField\": null, \"boolField\": false, \"int8Field\": 0, \"int16Field\": 0, \"int32Field\": 0, \"int64Field\": \"0\", \"uInt8Field\": 0, \"uInt16Field\": 0, \"uInt32Field\": 0, \"uInt64Field\": \"0\", \"float32Field\": 0, \"float64Field\": 0, \"textField\": \"x structlist 2\", \"enumField\": \"foo\", \"interfaceField\": null},\n"
    119     "      {\"voidField\": null, \"boolField\": false, \"int8Field\": 0, \"int16Field\": 0, \"int32Field\": 0, \"int64Field\": \"0\", \"uInt8Field\": 0, \"uInt16Field\": 0, \"uInt32Field\": 0, \"uInt64Field\": \"0\", \"float32Field\": 0, \"float64Field\": 0, \"textField\": \"x structlist 3\", \"enumField\": \"foo\", \"interfaceField\": null} ],\n"
    120     "    \"enumList\": [\"qux\", \"bar\", \"grault\"] },\n"
    121     "  \"enumField\": \"corge\",\n"
    122     "  \"interfaceField\": null,\n"
    123     "  \"voidList\": [null, null, null, null, null, null],\n"
    124     "  \"boolList\": [true, false, false, true],\n"
    125     "  \"int8List\": [111, -111],\n"
    126     "  \"int16List\": [11111, -11111],\n"
    127     "  \"int32List\": [111111111, -111111111],\n"
    128     "  \"int64List\": [\"1111111111111111111\", \"-1111111111111111111\"],\n"
    129     "  \"uInt8List\": [111, 222],\n"
    130     "  \"uInt16List\": [33333, 44444],\n"
    131     "  \"uInt32List\": [3333333333],\n"
    132     "  \"uInt64List\": [\"11111111111111111111\"],\n"
    133     "  \"float32List\": [5555.5, \"Infinity\", \"-Infinity\", \"NaN\"],\n"
    134     "  \"float64List\": [7777.75, \"Infinity\", \"-Infinity\", \"NaN\"],\n"
    135     "  \"textList\": [\"plugh\", \"xyzzy\", \"thud\"],\n"
    136     "  \"dataList\": [[111, 111, 112, 115], [101, 120, 104, 97, 117, 115, 116, 101, 100], [114, 102, 99, 51, 48, 57, 50]],\n"
    137     "  \"structList\": [\n"
    138     "    {\"voidField\": null, \"boolField\": false, \"int8Field\": 0, \"int16Field\": 0, \"int32Field\": 0, \"int64Field\": \"0\", \"uInt8Field\": 0, \"uInt16Field\": 0, \"uInt32Field\": 0, \"uInt64Field\": \"0\", \"float32Field\": 0, \"float64Field\": 0, \"textField\": \"structlist 1\", \"enumField\": \"foo\", \"interfaceField\": null},\n"
    139     "    {\"voidField\": null, \"boolField\": false, \"int8Field\": 0, \"int16Field\": 0, \"int32Field\": 0, \"int64Field\": \"0\", \"uInt8Field\": 0, \"uInt16Field\": 0, \"uInt32Field\": 0, \"uInt64Field\": \"0\", \"float32Field\": 0, \"float64Field\": 0, \"textField\": \"structlist 2\", \"enumField\": \"foo\", \"interfaceField\": null},\n"
    140     "    {\"voidField\": null, \"boolField\": false, \"int8Field\": 0, \"int16Field\": 0, \"int32Field\": 0, \"int64Field\": \"0\", \"uInt8Field\": 0, \"uInt16Field\": 0, \"uInt32Field\": 0, \"uInt64Field\": \"0\", \"float32Field\": 0, \"float64Field\": 0, \"textField\": \"structlist 3\", \"enumField\": \"foo\", \"interfaceField\": null} ],\n"
    141     "  \"enumList\": [\"foo\", \"garply\"] }";
    142 
    143 KJ_TEST("encode all types") {
    144   MallocMessageBuilder message;
    145   auto root = message.getRoot<TestAllTypes>();
    146   initTestMessage(root);
    147 
    148   JsonCodec json;
    149   json.setPrettyPrint(true);
    150   KJ_EXPECT(json.encode(root) == ALL_TYPES_JSON);
    151 
    152   // Verify that if we strip out the non-string spaces, we get the non-pretty-print version.
    153   kj::Vector<char> chars;
    154   bool inQuotes = false;
    155   for (char c: ALL_TYPES_JSON) {
    156     if (c == '\"') inQuotes = !inQuotes;
    157 
    158     if ((c == '\n' || c == ' ') && !inQuotes) {
    159       // skip space
    160     } else {
    161       chars.add(c);
    162     }
    163   }
    164   kj::String nospaces(chars.releaseAsArray());
    165 
    166   json.setPrettyPrint(false);
    167   KJ_EXPECT(json.encode(root) == nospaces);
    168 }
    169 
    170 KJ_TEST("encode union") {
    171   MallocMessageBuilder message;
    172   auto root = message.getRoot<test::TestUnnamedUnion>();
    173 
    174   root.setBefore("a");
    175   root.setMiddle(44);
    176   root.setAfter("c");
    177 
    178   JsonCodec json;
    179 
    180   root.setFoo(123);
    181   KJ_EXPECT(json.encode(root) == "{\"before\":\"a\",\"foo\":123,\"middle\":44,\"after\":\"c\"}");
    182 
    183   root.setBar(321);
    184   KJ_EXPECT(json.encode(root) == "{\"before\":\"a\",\"middle\":44,\"bar\":321,\"after\":\"c\"}");
    185 }
    186 
    187 KJ_TEST("decode all types") {
    188   JsonCodec json;
    189   json.setHasMode(HasMode::NON_DEFAULT);
    190 
    191 #define CASE_MAYBE_ROUNDTRIP(s, f, roundtrip) \
    192   { \
    193     MallocMessageBuilder message; \
    194     auto root = message.initRoot<TestAllTypes>(); \
    195     kj::StringPtr input = s; \
    196     json.decode(input, root); \
    197     KJ_EXPECT((f), input, root); \
    198     auto reencoded = json.encode(root); \
    199     KJ_EXPECT(roundtrip == (input == reencoded), roundtrip, input, reencoded); \
    200   }
    201 #define CASE_NO_ROUNDTRIP(s, f) CASE_MAYBE_ROUNDTRIP(s, f, false)
    202 #define CASE(s, f) CASE_MAYBE_ROUNDTRIP(s, f, true)
    203 #define CASE_THROW(s, errorMessage) \
    204   { \
    205     MallocMessageBuilder message; \
    206     auto root = message.initRoot<TestAllTypes>(); \
    207     KJ_EXPECT_THROW_MESSAGE(errorMessage, json.decode(s, root)); \
    208   }
    209 #define CASE_THROW_RECOVERABLE(s, errorMessage) \
    210   { \
    211     MallocMessageBuilder message; \
    212     auto root = message.initRoot<TestAllTypes>(); \
    213     KJ_EXPECT_THROW_RECOVERABLE_MESSAGE(errorMessage, json.decode(s, root)); \
    214   }
    215 
    216   CASE(R"({})", root.getBoolField() == false);
    217   CASE_NO_ROUNDTRIP(R"({"unknownField":7})", root.getBoolField() == false);
    218   CASE(R"({"boolField":true})", root.getBoolField() == true);
    219   CASE(R"({"int8Field":-128})", root.getInt8Field() == -128);
    220   CASE_NO_ROUNDTRIP(R"({"int8Field":"127"})", root.getInt8Field() == 127);
    221   CASE_THROW_RECOVERABLE(R"({"int8Field":"-129"})", "Value out-of-range");
    222   CASE_THROW_RECOVERABLE(R"({"int8Field":128})", "Value out-of-range");
    223   CASE(R"({"int16Field":-32768})", root.getInt16Field() == -32768);
    224   CASE_NO_ROUNDTRIP(R"({"int16Field":"32767"})", root.getInt16Field() == 32767);
    225   CASE_THROW_RECOVERABLE(R"({"int16Field":"-32769"})", "Value out-of-range");
    226   CASE_THROW_RECOVERABLE(R"({"int16Field":32768})", "Value out-of-range");
    227   CASE(R"({"int32Field":-2147483648})", root.getInt32Field() == -2147483648);
    228   CASE_NO_ROUNDTRIP(R"({"int32Field":"2147483647"})", root.getInt32Field() == 2147483647);
    229   CASE_NO_ROUNDTRIP(R"({"int64Field":-9007199254740992})", root.getInt64Field() == -9007199254740992LL);
    230   CASE_NO_ROUNDTRIP(R"({"int64Field":9007199254740991})", root.getInt64Field() == 9007199254740991LL);
    231   CASE(R"({"int64Field":"-9223372036854775808"})", root.getInt64Field() == -9223372036854775808ULL);
    232   CASE(R"({"int64Field":"9223372036854775807"})", root.getInt64Field() == 9223372036854775807LL);
    233   CASE_THROW_RECOVERABLE(R"({"int64Field":"-9223372036854775809"})", "Value out-of-range");
    234   CASE_THROW_RECOVERABLE(R"({"int64Field":"9223372036854775808"})", "Value out-of-range");
    235   CASE(R"({"uInt8Field":255})", root.getUInt8Field() == 255);
    236   CASE_NO_ROUNDTRIP(R"({"uInt8Field":"0"})", root.getUInt8Field() == 0);
    237   CASE_THROW_RECOVERABLE(R"({"uInt8Field":"256"})", "Value out-of-range");
    238   CASE_THROW_RECOVERABLE(R"({"uInt8Field":-1})", "Value out-of-range");
    239   CASE(R"({"uInt16Field":65535})", root.getUInt16Field() == 65535);
    240   CASE_NO_ROUNDTRIP(R"({"uInt16Field":"0"})", root.getUInt16Field() == 0);
    241   CASE_THROW_RECOVERABLE(R"({"uInt16Field":"655356"})", "Value out-of-range");
    242   CASE_THROW_RECOVERABLE(R"({"uInt16Field":-1})", "Value out-of-range");
    243   CASE(R"({"uInt32Field":4294967295})", root.getUInt32Field() == 4294967295);
    244   CASE_NO_ROUNDTRIP(R"({"uInt32Field":"0"})", root.getUInt32Field() == 0);
    245   CASE_THROW_RECOVERABLE(R"({"uInt32Field":"42949672956"})", "Value out-of-range");
    246   CASE_THROW_RECOVERABLE(R"({"uInt32Field":-1})", "Value out-of-range");
    247   CASE_NO_ROUNDTRIP(R"({"uInt64Field":9007199254740991})", root.getUInt64Field() == 9007199254740991ULL);
    248   CASE(R"({"uInt64Field":"18446744073709551615"})", root.getUInt64Field() == 18446744073709551615ULL);
    249   CASE_NO_ROUNDTRIP(R"({"uInt64Field":"0"})", root.getUInt64Field() == 0);
    250   CASE_THROW_RECOVERABLE(R"({"uInt64Field":"18446744073709551616"})", "Value out-of-range");
    251   CASE_NO_ROUNDTRIP(R"({"float32Field":0})", root.getFloat32Field() == 0);
    252   CASE(R"({"float32Field":4.5})", root.getFloat32Field() == 4.5);
    253   CASE_NO_ROUNDTRIP(R"({"float32Field":null})", kj::isNaN(root.getFloat32Field()));
    254   CASE(R"({"float32Field":"NaN"})", kj::isNaN(root.getFloat32Field()));
    255   CASE_NO_ROUNDTRIP(R"({"float32Field":"nan"})", kj::isNaN(root.getFloat32Field()));
    256   CASE(R"({"float32Field":"Infinity"})", root.getFloat32Field() == kj::inf());
    257   CASE(R"({"float32Field":"-Infinity"})", root.getFloat32Field() == -kj::inf());
    258   CASE_NO_ROUNDTRIP(R"({"float32Field":"infinity"})", root.getFloat32Field() == kj::inf());
    259   CASE_NO_ROUNDTRIP(R"({"float32Field":"-infinity"})", root.getFloat32Field() == -kj::inf());
    260   CASE_NO_ROUNDTRIP(R"({"float32Field":"INF"})", root.getFloat32Field() == kj::inf());
    261   CASE_NO_ROUNDTRIP(R"({"float32Field":"-INF"})", root.getFloat32Field() == -kj::inf());
    262   CASE_NO_ROUNDTRIP(R"({"float32Field":1e39})", root.getFloat32Field() == kj::inf());
    263   CASE_NO_ROUNDTRIP(R"({"float32Field":-1e39})", root.getFloat32Field() == -kj::inf());
    264   CASE_NO_ROUNDTRIP(R"({"float64Field":0})", root.getFloat64Field() == 0);
    265   CASE(R"({"float64Field":4.5})", root.getFloat64Field() == 4.5);
    266   CASE_NO_ROUNDTRIP(R"({"float64Field":null})", kj::isNaN(root.getFloat64Field()));
    267   CASE(R"({"float64Field":"NaN"})", kj::isNaN(root.getFloat64Field()));
    268   CASE_NO_ROUNDTRIP(R"({"float64Field":"nan"})", kj::isNaN(root.getFloat64Field()));
    269   CASE(R"({"float64Field":"Infinity"})", root.getFloat64Field() == kj::inf());
    270   CASE_NO_ROUNDTRIP(R"({"float64Field":"infinity"})", root.getFloat64Field() == kj::inf());
    271   CASE_NO_ROUNDTRIP(R"({"float64Field":"-infinity"})", root.getFloat64Field() == -kj::inf());
    272   CASE_NO_ROUNDTRIP(R"({"float64Field":"INF"})", root.getFloat64Field() == kj::inf());
    273   CASE_NO_ROUNDTRIP(R"({"float64Field":"-INF"})", root.getFloat64Field() == -kj::inf());
    274   CASE_NO_ROUNDTRIP(R"({"float64Field":1e309})", root.getFloat64Field() == kj::inf());
    275   CASE_NO_ROUNDTRIP(R"({"float64Field":-1e309})", root.getFloat64Field() == -kj::inf());
    276   CASE(R"({"textField":"hello"})", kj::str("hello") == root.getTextField());
    277   CASE(R"({"dataField":[7,0,122]})",
    278       kj::heapArray<byte>({7,0,122}).asPtr() == root.getDataField());
    279   CASE(R"({"structField":{}})", root.hasStructField() == true);
    280   CASE(R"({"structField":{}})", root.getStructField().getBoolField() == false);
    281   CASE_NO_ROUNDTRIP(R"({"structField":{"boolField":false}})", root.getStructField().getBoolField() == false);
    282   CASE(R"({"structField":{"boolField":true}})", root.getStructField().getBoolField() == true);
    283   CASE(R"({"enumField":"bar"})", root.getEnumField() == TestEnum::BAR);
    284 
    285   CASE_NO_ROUNDTRIP(R"({"textField":"foo\u1234bar"})",
    286       kj::str(u8"foo\u1234bar") == root.getTextField());
    287 
    288   CASE_THROW_RECOVERABLE(R"({"structField":null})", "Expected object value");
    289   CASE_THROW_RECOVERABLE(R"({"structList":null})", "Expected list value");
    290   CASE_THROW_RECOVERABLE(R"({"boolList":null})", "Expected list value");
    291   CASE_THROW_RECOVERABLE(R"({"structList":[null]})", "Expected object value");
    292   CASE_THROW_RECOVERABLE(R"({"int64Field":"177a"})", "String does not contain valid");
    293   CASE_THROW_RECOVERABLE(R"({"uInt64Field":"177a"})", "String does not contain valid");
    294   CASE_THROW_RECOVERABLE(R"({"float64Field":"177a"})", "String does not contain valid");
    295 
    296   CASE(R"({})", root.hasBoolList() == false);
    297   CASE(R"({"boolList":[]})", root.hasBoolList() == true);
    298   CASE(R"({"boolList":[]})", root.getBoolList().size() == 0);
    299   CASE(R"({"boolList":[false]})", root.getBoolList().size() == 1);
    300   CASE(R"({"boolList":[false]})", root.getBoolList()[0] == false);
    301   CASE(R"({"boolList":[true]})", root.getBoolList()[0] == true);
    302   CASE(R"({"int8List":[7]})", root.getInt8List()[0] == 7);
    303   CASE_NO_ROUNDTRIP(R"({"int8List":["7"]})", root.getInt8List()[0] == 7);
    304   CASE(R"({"int16List":[7]})", root.getInt16List()[0] == 7);
    305   CASE_NO_ROUNDTRIP(R"({"int16List":["7"]})", root.getInt16List()[0] == 7);
    306   CASE(R"({"int32List":[7]})", root.getInt32List()[0] == 7);
    307   CASE_NO_ROUNDTRIP(R"({"int32List":["7"]})", root.getInt32List()[0] == 7);
    308   CASE_NO_ROUNDTRIP(R"({"int64List":[7]})", root.getInt64List()[0] == 7);
    309   CASE(R"({"int64List":["7"]})", root.getInt64List()[0] == 7);
    310   CASE(R"({"uInt8List":[7]})", root.getUInt8List()[0] == 7);
    311   CASE_NO_ROUNDTRIP(R"({"uInt8List":["7"]})", root.getUInt8List()[0] == 7);
    312   CASE(R"({"uInt16List":[7]})", root.getUInt16List()[0] == 7);
    313   CASE_NO_ROUNDTRIP(R"({"uInt16List":["7"]})", root.getUInt16List()[0] == 7);
    314   CASE(R"({"uInt32List":[7]})", root.getUInt32List()[0] == 7);
    315   CASE_NO_ROUNDTRIP(R"({"uInt32List":["7"]})", root.getUInt32List()[0] == 7);
    316   CASE_NO_ROUNDTRIP(R"({"uInt64List":[7]})", root.getUInt64List()[0] == 7);
    317   CASE(R"({"uInt64List":["7"]})", root.getUInt64List()[0] == 7);
    318   CASE(R"({"float32List":[4.5]})", root.getFloat32List()[0] == 4.5);
    319   CASE_NO_ROUNDTRIP(R"({"float32List":["4.5"]})", root.getFloat32List()[0] == 4.5);
    320   CASE_NO_ROUNDTRIP(R"({"float32List":[null]})", kj::isNaN(root.getFloat32List()[0]));
    321   CASE(R"({"float32List":["NaN"]})", kj::isNaN(root.getFloat32List()[0]));
    322   CASE(R"({"float32List":["Infinity"]})", root.getFloat32List()[0] == kj::inf());
    323   CASE(R"({"float32List":["-Infinity"]})", root.getFloat32List()[0] == -kj::inf());
    324   CASE(R"({"float64List":[4.5]})", root.getFloat64List()[0] == 4.5);
    325   CASE_NO_ROUNDTRIP(R"({"float64List":["4.5"]})", root.getFloat64List()[0] == 4.5);
    326   CASE_NO_ROUNDTRIP(R"({"float64List":[null]})", kj::isNaN(root.getFloat64List()[0]));
    327   CASE(R"({"float64List":["NaN"]})", kj::isNaN(root.getFloat64List()[0]));
    328   CASE(R"({"float64List":["Infinity"]})", root.getFloat64List()[0] == kj::inf());
    329   CASE(R"({"float64List":["-Infinity"]})", root.getFloat64List()[0] == -kj::inf());
    330   CASE(R"({"textList":["hello"]})", kj::str("hello") == root.getTextList()[0]);
    331   CASE(R"({"dataList":[[7,0,122]]})",
    332       kj::heapArray<byte>({7,0,122}).asPtr() == root.getDataList()[0]);
    333   CASE(R"({"structList":[{}]})", root.hasStructList() == true);
    334   CASE(R"({"structList":[{}]})", root.getStructList()[0].getBoolField() == false);
    335   CASE_NO_ROUNDTRIP(R"({"structList":[{"boolField":false}]})", root.getStructList()[0].getBoolField() == false);
    336   CASE(R"({"structList":[{"boolField":true}]})", root.getStructList()[0].getBoolField() == true);
    337   CASE(R"({"enumList":["bar"]})", root.getEnumList()[0] == TestEnum::BAR);
    338 #undef CASE_MAYBE_ROUNDTRIP
    339 #undef CASE_NO_ROUNDTRIP
    340 #undef CASE
    341 #undef CASE_THROW
    342 #undef CASE_THROW_RECOVERABLE
    343 }
    344 
    345 KJ_TEST("decode test message") {
    346   MallocMessageBuilder message;
    347   auto root = message.getRoot<TestAllTypes>();
    348   initTestMessage(root);
    349 
    350   JsonCodec json;
    351   auto encoded = json.encode(root);
    352 
    353   MallocMessageBuilder decodedMessage;
    354   auto decodedRoot = decodedMessage.initRoot<TestAllTypes>();
    355   json.decode(encoded, decodedRoot);
    356 
    357   KJ_EXPECT(root.toString().flatten() == decodedRoot.toString().flatten());
    358 }
    359 
    360 KJ_TEST("basic json decoding") {
    361   // TODO(cleanup): this test is a mess!
    362   JsonCodec json;
    363   {
    364     MallocMessageBuilder message;
    365     auto root = message.initRoot<JsonValue>();
    366     json.decodeRaw("null", root);
    367 
    368     KJ_EXPECT(root.which() == JsonValue::NULL_);
    369     KJ_EXPECT(root.getNull() == VOID);
    370   }
    371 
    372   {
    373     MallocMessageBuilder message;
    374     auto root = message.initRoot<JsonValue>();
    375 
    376     json.decodeRaw("false", root);
    377     KJ_EXPECT(root.which() == JsonValue::BOOLEAN);
    378     KJ_EXPECT(root.getBoolean() == false);
    379   }
    380 
    381   {
    382     MallocMessageBuilder message;
    383     auto root = message.initRoot<JsonValue>();
    384 
    385     json.decodeRaw("true", root);
    386     KJ_EXPECT(root.which() == JsonValue::BOOLEAN);
    387     KJ_EXPECT(root.getBoolean() == true);
    388   }
    389 
    390   {
    391     MallocMessageBuilder message;
    392     auto root = message.initRoot<JsonValue>();
    393 
    394     json.decodeRaw("\"foo\"", root);
    395     KJ_EXPECT(root.which() == JsonValue::STRING);
    396     KJ_EXPECT(kj::str("foo") == root.getString());
    397   }
    398 
    399   {
    400     MallocMessageBuilder message;
    401     auto root = message.initRoot<JsonValue>();
    402 
    403     json.decodeRaw(R"("\"")", root);
    404     KJ_EXPECT(root.which() == JsonValue::STRING);
    405     KJ_EXPECT(kj::str("\"") == root.getString());
    406   }
    407 
    408   {
    409     MallocMessageBuilder message;
    410     auto root = message.initRoot<JsonValue>();
    411 
    412     json.decodeRaw(R"("\\abc\"d\\e")", root);
    413     KJ_EXPECT(root.which() == JsonValue::STRING);
    414     KJ_EXPECT(kj::str("\\abc\"d\\e") == root.getString());
    415   }
    416 
    417   {
    418     MallocMessageBuilder message;
    419     auto root = message.initRoot<JsonValue>();
    420 
    421     json.decodeRaw(R"("\"\\\/\b\f\n\r\t\u0003abc\u0064\u0065f")", root);
    422     KJ_EXPECT(root.which() == JsonValue::STRING);
    423     KJ_EXPECT(kj::str("\"\\/\b\f\n\r\t\x03""abcdef") == root.getString(), root.getString());
    424   }
    425   {
    426     MallocMessageBuilder message;
    427     auto root = message.initRoot<JsonValue>();
    428 
    429     json.decodeRaw("[]", root);
    430     KJ_EXPECT(root.which() == JsonValue::ARRAY, (uint)root.which());
    431     KJ_EXPECT(root.getArray().size() == 0);
    432   }
    433 
    434   {
    435     MallocMessageBuilder message;
    436     auto root = message.initRoot<JsonValue>();
    437 
    438     json.decodeRaw("[true]", root);
    439     KJ_EXPECT(root.which() == JsonValue::ARRAY);
    440     auto array = root.getArray();
    441     KJ_EXPECT(array.size() == 1, array.size());
    442     KJ_EXPECT(root.getArray()[0].which() == JsonValue::BOOLEAN);
    443     KJ_EXPECT(root.getArray()[0].getBoolean() == true);
    444   }
    445 
    446   {
    447     MallocMessageBuilder message;
    448     auto root = message.initRoot<JsonValue>();
    449 
    450     json.decodeRaw("  [  true  , false\t\n , null]", root);
    451     KJ_EXPECT(root.which() == JsonValue::ARRAY);
    452     auto array = root.getArray();
    453     KJ_EXPECT(array.size() == 3);
    454     KJ_EXPECT(array[0].which() == JsonValue::BOOLEAN);
    455     KJ_EXPECT(array[0].getBoolean() == true);
    456     KJ_EXPECT(array[1].which() == JsonValue::BOOLEAN);
    457     KJ_EXPECT(array[1].getBoolean() == false);
    458     KJ_EXPECT(array[2].which() == JsonValue::NULL_);
    459     KJ_EXPECT(array[2].getNull() == VOID);
    460   }
    461 
    462   {
    463     MallocMessageBuilder message;
    464     auto root = message.initRoot<JsonValue>();
    465 
    466     json.decodeRaw("{}", root);
    467     KJ_EXPECT(root.which() == JsonValue::OBJECT, (uint)root.which());
    468     KJ_EXPECT(root.getObject().size() == 0);
    469   }
    470 
    471   {
    472     MallocMessageBuilder message;
    473     auto root = message.initRoot<JsonValue>();
    474 
    475     json.decodeRaw("\r\n\t {\r\n\t }\r\n\t ", root);
    476     KJ_EXPECT(root.which() == JsonValue::OBJECT, (uint)root.which());
    477     KJ_EXPECT(root.getObject().size() == 0);
    478   }
    479 
    480   {
    481     MallocMessageBuilder message;
    482     auto root = message.initRoot<JsonValue>();
    483 
    484     json.decodeRaw(R"({"some": null})", root);
    485     KJ_EXPECT(root.which() == JsonValue::OBJECT, (uint)root.which());
    486     auto object = root.getObject();
    487     KJ_EXPECT(object.size() == 1);
    488     KJ_EXPECT(kj::str("some") == object[0].getName());
    489     KJ_EXPECT(object[0].getValue().which() == JsonValue::NULL_);
    490   }
    491 
    492   {
    493     MallocMessageBuilder message;
    494     auto root = message.initRoot<JsonValue>();
    495 
    496     json.decodeRaw(R"({"foo\n\tbaz": "a val", "bar": ["a", -5.5e11,  { "z": {}}]})", root);
    497     KJ_EXPECT(root.which() == JsonValue::OBJECT, (uint)root.which());
    498     auto object = root.getObject();
    499     KJ_EXPECT(object.size() == 2);
    500     KJ_EXPECT(kj::str("foo\n\tbaz") == object[0].getName());
    501     KJ_EXPECT(object[0].getValue().which() == JsonValue::STRING);
    502     KJ_EXPECT(kj::str("a val") == object[0].getValue().getString());
    503 
    504     KJ_EXPECT(kj::str("bar") == object[1].getName());
    505     KJ_EXPECT(object[1].getValue().which() == JsonValue::ARRAY);
    506     auto array = object[1].getValue().getArray();
    507     KJ_EXPECT(array.size() == 3, array.size());
    508     KJ_EXPECT(array[0].which() == JsonValue::STRING);
    509     KJ_EXPECT(kj::str("a") == array[0].getString());
    510     KJ_EXPECT(array[1].which() == JsonValue::NUMBER);
    511     KJ_EXPECT(array[1].getNumber() == -5.5e11);
    512     KJ_EXPECT(array[2].which() == JsonValue::OBJECT);
    513     KJ_EXPECT(array[2].getObject().size() == 1);
    514     KJ_EXPECT(array[2].getObject()[0].getValue().which() == JsonValue::OBJECT);
    515     KJ_EXPECT(array[2].getObject()[0].getValue().getObject().size() == 0);
    516   }
    517 
    518   {
    519     MallocMessageBuilder message;
    520     auto root = message.initRoot<JsonValue>();
    521 
    522     json.decodeRaw("123", root);
    523     KJ_EXPECT(root.which() == JsonValue::NUMBER);
    524     KJ_EXPECT(root.getNumber() == 123);
    525   }
    526 
    527   {
    528     MallocMessageBuilder message;
    529     auto root = message.initRoot<JsonValue>();
    530 
    531     KJ_EXPECT_THROW_MESSAGE("input", json.decodeRaw("z", root));
    532   }
    533 
    534   {
    535     MallocMessageBuilder message;
    536     auto root = message.initRoot<JsonValue>();
    537 
    538     // Leading + not allowed in numbers.
    539     KJ_EXPECT_THROW_MESSAGE("Unexpected", json.decodeRaw("+123", root));
    540   }
    541 
    542   {
    543     MallocMessageBuilder message;
    544     auto root = message.initRoot<JsonValue>();
    545 
    546     KJ_EXPECT_THROW_MESSAGE("Unexpected", json.decodeRaw("[00]", root));
    547     KJ_EXPECT_THROW_MESSAGE("Unexpected", json.decodeRaw("[01]", root));
    548   }
    549 
    550   {
    551     MallocMessageBuilder message;
    552     auto root = message.initRoot<JsonValue>();
    553 
    554     KJ_EXPECT_THROW_MESSAGE("ends prematurely", json.decodeRaw("-", root));
    555   }
    556 
    557   {
    558     MallocMessageBuilder message;
    559     auto root = message.initRoot<JsonValue>();
    560 
    561     json.decodeRaw("-5", root);
    562     KJ_EXPECT(root.which() == JsonValue::NUMBER);
    563     KJ_EXPECT(root.getNumber() == -5);
    564   }
    565 
    566   {
    567     MallocMessageBuilder message;
    568     auto root = message.initRoot<JsonValue>();
    569 
    570     json.decodeRaw("-5.5", root);
    571     KJ_EXPECT(root.which() == JsonValue::NUMBER);
    572     KJ_EXPECT(root.getNumber() == -5.5);
    573   }
    574 
    575   {
    576     MallocMessageBuilder message;
    577     auto root = message.initRoot<JsonValue>();
    578 
    579     KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("a", root));
    580     KJ_EXPECT_THROW_MESSAGE("ends prematurely", json.decodeRaw("[", root));
    581     KJ_EXPECT_THROW_MESSAGE("ends prematurely", json.decodeRaw("{", root));
    582     KJ_EXPECT_THROW_MESSAGE("ends prematurely", json.decodeRaw("\"\\u\"", root));
    583     KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[}", root));
    584     KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("{]", root));
    585     KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[}]", root));
    586     KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[1, , ]", root));
    587     KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[,]", root));
    588     KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[true,]", root));
    589     KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[, 1]", root));
    590     KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[1\"\"]", root));
    591     KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[1,, \"\"]", root));
    592     KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("{\"a\"1: 0}", root));
    593     KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw(R"({"some": null,})", root));
    594     KJ_EXPECT_THROW_MESSAGE("Input remains", json.decodeRaw("11a", root));
    595     KJ_EXPECT_THROW_MESSAGE("Invalid escape", json.decodeRaw(R"("\z")", root));
    596     KJ_EXPECT_THROW_MESSAGE("Invalid escape", json.decodeRaw(R"("\z")", root));
    597     {
    598       // TODO(msvc):  This raw string literal currently confuses MSVC's preprocessor, so I hoisted
    599       // it outside the macro.
    600       auto f = [&] { json.decodeRaw(R"(["\n\", 3])", root); };
    601       KJ_EXPECT_THROW_MESSAGE("ends prematurely", f());
    602     }
    603     KJ_EXPECT_THROW_MESSAGE("Invalid hex", json.decodeRaw(R"("\u12zz")", root));
    604     KJ_EXPECT_THROW_MESSAGE("ends prematurely", json.decodeRaw("-", root));
    605     KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("--", root));
    606     KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("\f{}", root));
    607     KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("{\v}", root));
    608   }
    609 }
    610 
    611 KJ_TEST("maximum nesting depth") {
    612   JsonCodec json;
    613   auto input = kj::str(R"({"foo": "a", "bar": ["b", { "baz": [-5.5e11] }, [ [ 1 ], {  "z": 2 }]]})");
    614   // `input` has a maximum nesting depth of 4, reached 3 times.
    615 
    616   {
    617     MallocMessageBuilder message;
    618     auto root = message.initRoot<JsonValue>();
    619 
    620     json.decodeRaw(input, root);
    621   }
    622 
    623   {
    624     json.setMaxNestingDepth(0);
    625     MallocMessageBuilder message;
    626     auto root = message.initRoot<JsonValue>();
    627 
    628     KJ_EXPECT_THROW_MESSAGE("nest",
    629         json.decodeRaw(input, root));
    630   }
    631 
    632   {
    633     json.setMaxNestingDepth(3);
    634     MallocMessageBuilder message;
    635     auto root = message.initRoot<JsonValue>();
    636 
    637     KJ_EXPECT_THROW_MESSAGE("nest",
    638         json.decodeRaw(input, root));
    639   }
    640 
    641   {
    642     json.setMaxNestingDepth(4);
    643     MallocMessageBuilder message;
    644     auto root = message.initRoot<JsonValue>();
    645 
    646     json.decodeRaw(input, root);
    647   }
    648 }
    649 
    650 KJ_TEST("unknown fields") {
    651   JsonCodec json;
    652   MallocMessageBuilder message;
    653   auto root = message.initRoot<TestJsonAnnotations2>();
    654   auto valid = R"({"foo": "a"})"_kj;
    655   auto unknown = R"({"foo": "a", "unknown-field": "b"})"_kj;
    656   json.decode(valid, root);
    657   json.decode(unknown, root);
    658   json.setRejectUnknownFields(true);
    659   json.decode(valid, root);
    660   KJ_EXPECT_THROW_MESSAGE("Unknown field", json.decode(unknown, root));
    661 
    662   // Verify unknown field rejection still works when handling by annotation.
    663   json.handleByAnnotation<TestJsonAnnotations2>();
    664   KJ_EXPECT_THROW_MESSAGE("Unknown field", json.decode(unknown, root));
    665 }
    666 
    667 class TestCallHandler: public JsonCodec::Handler<Text> {
    668 public:
    669   void encode(const JsonCodec& codec, Text::Reader input,
    670               JsonValue::Builder output) const override {
    671     auto call = output.initCall();
    672     call.setFunction("Frob");
    673     auto params = call.initParams(2);
    674     params[0].setNumber(123);
    675     params[1].setString(input);
    676   }
    677 
    678   Orphan<Text> decode(const JsonCodec& codec, JsonValue::Reader input,
    679                       Orphanage orphanage) const override {
    680     KJ_UNIMPLEMENTED("TestHandler::decode");
    681   }
    682 };
    683 
    684 class TestDynamicStructHandler: public JsonCodec::Handler<DynamicStruct> {
    685 public:
    686   void encode(const JsonCodec& codec, DynamicStruct::Reader input,
    687               JsonValue::Builder output) const override {
    688     auto fields = input.getSchema().getFields();
    689     auto items = output.initArray(fields.size());
    690     for (auto field: fields) {
    691       KJ_REQUIRE(field.getIndex() < items.size());
    692       auto item = items[field.getIndex()];
    693       if (input.has(field)) {
    694         codec.encode(input.get(field), field.getType(), item);
    695       } else {
    696         item.setNull();
    697       }
    698     }
    699   }
    700 
    701   void decode(const JsonCodec& codec, JsonValue::Reader input,
    702               DynamicStruct::Builder output) const override {
    703     auto orphanage = Orphanage::getForMessageContaining(output);
    704     auto fields = output.getSchema().getFields();
    705     auto items = input.getArray();
    706     for (auto field: fields) {
    707       KJ_REQUIRE(field.getIndex() < items.size());
    708       auto item = items[field.getIndex()];
    709       if (!item.isNull()) {
    710         output.adopt(field, codec.decode(item, field.getType(), orphanage));
    711       }
    712     }
    713   }
    714 };
    715 
    716 class TestStructHandler: public JsonCodec::Handler<test::TestOldVersion> {
    717 public:
    718   void encode(const JsonCodec& codec, test::TestOldVersion::Reader input, JsonValue::Builder output) const override {
    719     dynamicHandler.encode(codec, input, output);
    720   }
    721 
    722   void decode(const JsonCodec& codec, JsonValue::Reader input, test::TestOldVersion::Builder output) const override {
    723     dynamicHandler.decode(codec, input, output);
    724   }
    725 
    726 private:
    727   TestDynamicStructHandler dynamicHandler;
    728 };
    729 
    730 KJ_TEST("register custom encoding handlers") {
    731   JsonCodec json;
    732 
    733   TestStructHandler structHandler;
    734   json.addTypeHandler(structHandler);
    735 
    736   // JSON decoder can't parse calls back, so test only encoder here
    737   TestCallHandler callHandler;
    738   json.addTypeHandler(callHandler);
    739 
    740   MallocMessageBuilder message;
    741   auto root = message.getRoot<test::TestOldVersion>();
    742   root.setOld1(123);
    743   root.setOld2("foo");
    744 
    745   KJ_EXPECT(json.encode(root) == "[\"123\",Frob(123,\"foo\"),null]");
    746 }
    747 
    748 KJ_TEST("register custom roundtrip handler") {
    749   for (auto i = 1; i <= 2; i++) {
    750     JsonCodec json;
    751     TestStructHandler staticHandler;
    752     TestDynamicStructHandler dynamicHandler;
    753     kj::String encoded;
    754 
    755     if (i == 1) {
    756       // first iteration: test with explicit struct handler
    757       json.addTypeHandler(staticHandler);
    758     } else {
    759       // second iteration: same checks, but with DynamicStruct handler
    760       json.addTypeHandler(StructSchema::from<test::TestOldVersion>(), dynamicHandler);
    761     }
    762 
    763     {
    764       MallocMessageBuilder message;
    765       auto root = message.getRoot<test::TestOldVersion>();
    766       root.setOld1(123);
    767       root.initOld3().setOld2("foo");
    768 
    769       encoded = json.encode(root);
    770 
    771       KJ_EXPECT(encoded == "[\"123\",null,[\"0\",\"foo\",null]]");
    772     }
    773 
    774     {
    775       MallocMessageBuilder message;
    776       auto root = message.getRoot<test::TestOldVersion>();
    777       json.decode(encoded, root);
    778 
    779       KJ_EXPECT(root.getOld1() == 123);
    780       KJ_EXPECT(!root.hasOld2());
    781       auto nested = root.getOld3();
    782       KJ_EXPECT(nested.getOld1() == 0);
    783       KJ_EXPECT("foo" == nested.getOld2());
    784       KJ_EXPECT(!nested.hasOld3());
    785     }
    786   }
    787 }
    788 
    789 KJ_TEST("register field handler") {
    790   TestStructHandler handler;
    791   JsonCodec json;
    792   json.addFieldHandler(StructSchema::from<test::TestOldVersion>().getFieldByName("old3"),
    793                        handler);
    794 
    795   kj::String encoded;
    796 
    797   {
    798     MallocMessageBuilder message;
    799     auto root = message.getRoot<test::TestOldVersion>();
    800     root.setOld1(123);
    801     root.setOld2("foo");
    802     auto nested = root.initOld3();
    803     nested.setOld2("bar");
    804 
    805     encoded = json.encode(root);
    806 
    807     KJ_EXPECT(encoded == "{\"old1\":\"123\",\"old2\":\"foo\",\"old3\":[\"0\",\"bar\",null]}")
    808   }
    809 
    810   {
    811     MallocMessageBuilder message;
    812     auto root = message.getRoot<test::TestOldVersion>();
    813     json.decode(encoded, root);
    814 
    815     KJ_EXPECT(root.getOld1() == 123);
    816     KJ_EXPECT("foo" == root.getOld2());
    817     auto nested = root.getOld3();
    818     KJ_EXPECT(nested.getOld1() == 0);
    819     KJ_EXPECT("bar" == nested.getOld2());
    820     KJ_EXPECT(!nested.hasOld3());
    821   }
    822 }
    823 
    824 class TestCapabilityHandler: public JsonCodec::Handler<test::TestInterface> {
    825 public:
    826   void encode(const JsonCodec& codec, test::TestInterface::Client input,
    827               JsonValue::Builder output) const override {
    828     KJ_UNIMPLEMENTED("TestCapabilityHandler::encode");
    829   }
    830 
    831   test::TestInterface::Client decode(
    832       const JsonCodec& codec, JsonValue::Reader input) const override {
    833     return nullptr;
    834   }
    835 };
    836 
    837 KJ_TEST("register capability handler") {
    838   // This test currently only checks that this compiles, which at one point wasn't the caes.
    839   // TODO(test): Actually run some code here.
    840 
    841   TestCapabilityHandler handler;
    842   JsonCodec json;
    843   json.addTypeHandler(handler);
    844 }
    845 
    846 static constexpr kj::StringPtr GOLDEN_ANNOTATED =
    847 R"({ "names-can_contain!anything Really": "foo",
    848   "flatFoo": 123,
    849   "flatBar": "abc",
    850   "renamed-flatBaz": {"hello": true},
    851   "flatQux": "cba",
    852   "pfx.foo": "this is a long string in order to force multi-line pretty printing",
    853   "pfx.renamed-bar": 321,
    854   "pfx.baz": {"hello": true},
    855   "pfx.xfp.qux": "fed",
    856   "union-type": "renamed-bar",
    857   "barMember": 789,
    858   "multiMember": "ghi",
    859   "dependency": {"renamed-foo": "corge"},
    860   "simpleGroup": {"renamed-grault": "garply"},
    861   "enums": ["qux", "renamed-bar", "foo", "renamed-baz"],
    862   "innerJson": [123, "hello", {"object": true}],
    863   "customFieldHandler": "add-prefix-waldo",
    864   "testBase64": "ZnJlZA==",
    865   "testHex": "706c756768",
    866   "bUnion": "renamed-bar",
    867   "bValue": 678,
    868   "externalUnion": {"type": "bar", "value": "cba"},
    869   "unionWithVoid": {"type": "voidValue"} })"_kj;
    870 
    871 static constexpr kj::StringPtr GOLDEN_ANNOTATED_REVERSE =
    872 R"({
    873   "unionWithVoid": {"type": "voidValue"},
    874   "externalUnion": {"type": "bar", "value": "cba"},
    875   "bValue": 678,
    876   "bUnion": "renamed-bar",
    877   "testHex": "706c756768",
    878   "testBase64": "ZnJlZA==",
    879   "customFieldHandler": "add-prefix-waldo",
    880   "innerJson": [123, "hello", {"object": true}],
    881   "enums": ["qux", "renamed-bar", "foo", "renamed-baz"],
    882   "simpleGroup": { "renamed-grault": "garply" },
    883   "dependency": { "renamed-foo": "corge" },
    884   "multiMember": "ghi",
    885   "barMember": 789,
    886   "union-type": "renamed-bar",
    887   "pfx.xfp.qux": "fed",
    888   "pfx.baz": {"hello": true},
    889   "pfx.renamed-bar": 321,
    890   "pfx.foo": "this is a long string in order to force multi-line pretty printing",
    891   "flatQux": "cba",
    892   "renamed-flatBaz": {"hello": true},
    893   "flatBar": "abc",
    894   "flatFoo": 123,
    895   "names-can_contain!anything Really": "foo"
    896 })"_kj;
    897 
    898 class PrefixAdder: public JsonCodec::Handler<capnp::Text> {
    899 public:
    900   void encode(const JsonCodec& codec, capnp::Text::Reader input, JsonValue::Builder output) const {
    901     output.setString(kj::str("add-prefix-", input));
    902   }
    903 
    904   Orphan<capnp::Text> decode(const JsonCodec& codec, JsonValue::Reader input,
    905                              Orphanage orphanage) const {
    906     return orphanage.newOrphanCopy(capnp::Text::Reader(input.getString().slice(11)));
    907   }
    908 };
    909 
    910 KJ_TEST("rename fields") {
    911   JsonCodec json;
    912   json.handleByAnnotation<TestJsonAnnotations>();
    913   json.setPrettyPrint(true);
    914 
    915   PrefixAdder customHandler;
    916   json.addFieldHandler(Schema::from<TestJsonAnnotations>().getFieldByName("customFieldHandler"),
    917                        customHandler);
    918 
    919   kj::String goldenText;
    920 
    921   {
    922     MallocMessageBuilder message;
    923     auto root = message.getRoot<TestJsonAnnotations>();
    924     root.setSomeField("foo");
    925 
    926     auto aGroup = root.getAGroup();
    927     aGroup.setFlatFoo(123);
    928     aGroup.setFlatBar("abc");
    929     aGroup.getFlatBaz().setHello(true);
    930     aGroup.getDoubleFlat().setFlatQux("cba");
    931 
    932     auto prefixedGroup = root.getPrefixedGroup();
    933     prefixedGroup.setFoo("this is a long string in order to force multi-line pretty printing");
    934     prefixedGroup.setBar(321);
    935     prefixedGroup.getBaz().setHello(true);
    936     prefixedGroup.getMorePrefix().setQux("fed");
    937 
    938     auto unionBar = root.getAUnion().initBar();
    939     unionBar.setBarMember(789);
    940     unionBar.setMultiMember("ghi");
    941 
    942     root.initDependency().setFoo("corge");
    943     root.initSimpleGroup().setGrault("garply");
    944 
    945     root.setEnums({
    946       TestJsonAnnotatedEnum::QUX,
    947       TestJsonAnnotatedEnum::BAR,
    948       TestJsonAnnotatedEnum::FOO,
    949       TestJsonAnnotatedEnum::BAZ
    950     });
    951 
    952     auto val = root.initInnerJson();
    953     auto arr = val.initArray(3);
    954     arr[0].setNumber(123);
    955     arr[1].setString("hello");
    956     auto field = arr[2].initObject(1)[0];
    957     field.setName("object");
    958     field.initValue().setBoolean(true);
    959 
    960     root.setCustomFieldHandler("waldo");
    961 
    962     root.setTestBase64("fred"_kj.asBytes());
    963     root.setTestHex("plugh"_kj.asBytes());
    964 
    965     root.getBUnion().setBar(678);
    966 
    967     root.initExternalUnion().initBar().setValue("cba");
    968 
    969     root.initUnionWithVoid().setVoidValue();
    970 
    971     auto encoded = json.encode(root.asReader());
    972     KJ_EXPECT(encoded == GOLDEN_ANNOTATED, encoded);
    973 
    974     goldenText = kj::str(root);
    975   }
    976 
    977   {
    978     MallocMessageBuilder message;
    979     auto root = message.getRoot<TestJsonAnnotations>();
    980     json.decode(GOLDEN_ANNOTATED, root);
    981 
    982     KJ_EXPECT(kj::str(root) == goldenText, root, goldenText);
    983   }
    984 
    985   {
    986     // Try parsing in reverse, mostly to test that union tags can come after content.
    987     MallocMessageBuilder message;
    988     auto root = message.getRoot<TestJsonAnnotations>();
    989     json.decode(GOLDEN_ANNOTATED_REVERSE, root);
    990 
    991     KJ_EXPECT(kj::str(root) == goldenText, root, goldenText);
    992   }
    993 }
    994 
    995 KJ_TEST("base64 union encoded correctly") {
    996   // At one point field handlers were not correctly applied when the field was a member of a union
    997   // in a type that was handled by annotation.
    998 
    999   JsonCodec json;
   1000   json.handleByAnnotation<TestBase64Union>();
   1001   json.setPrettyPrint(true);
   1002 
   1003   MallocMessageBuilder message;
   1004   auto root = message.getRoot<TestBase64Union>();
   1005   root.initFoo(5);
   1006 
   1007   KJ_EXPECT(json.encode(root) == "{\"foo\": \"AAAAAAA=\"}", json.encode(root));
   1008 }
   1009 
   1010 }  // namespace
   1011 }  // namespace _ (private)
   1012 }  // namespace capnp