tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

testFrontendJSON.cpp (20567B)


      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
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "mozilla/Maybe.h"  // mozilla::Maybe
      8 
      9 #include <string>
     10 
     11 #include "js/AllocPolicy.h"  // js::SystemAllocPolicy
     12 #include "js/JSON.h"
     13 #include "js/Vector.h"  // js::Vector
     14 #include "jsapi-tests/tests.h"
     15 
     16 using namespace JS;
     17 
     18 BEGIN_FRONTEND_TEST(testIsValidJSONLatin1) {
     19  const char* source;
     20 
     21  source = "true";
     22  CHECK(IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
     23                    strlen(source)));
     24 
     25  source = "false";
     26  CHECK(IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
     27                    strlen(source)));
     28 
     29  source = "null";
     30  CHECK(IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
     31                    strlen(source)));
     32 
     33  source = "0";
     34  CHECK(IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
     35                    strlen(source)));
     36 
     37  source = "1";
     38  CHECK(IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
     39                    strlen(source)));
     40 
     41  source = "-1";
     42  CHECK(IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
     43                    strlen(source)));
     44 
     45  source = "1.75";
     46  CHECK(IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
     47                    strlen(source)));
     48 
     49  source = "9000000000";
     50  CHECK(IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
     51                    strlen(source)));
     52 
     53  source = "\"foo\"";
     54  CHECK(IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
     55                    strlen(source)));
     56 
     57  source = "[]";
     58  CHECK(IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
     59                    strlen(source)));
     60 
     61  source = "[1, true]";
     62  CHECK(IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
     63                    strlen(source)));
     64 
     65  source = "{}";
     66  CHECK(IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
     67                    strlen(source)));
     68 
     69  source = "{\"key\": 10}";
     70  CHECK(IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
     71                    strlen(source)));
     72 
     73  source = "{\"key\": 10, \"prop\": 20}";
     74  CHECK(IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
     75                    strlen(source)));
     76 
     77  source = "1 ";
     78  CHECK(IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
     79                    strlen(source)));
     80 
     81  // Invalid cases.
     82 
     83  source = "";
     84  CHECK(!IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
     85                     strlen(source)));
     86 
     87  source = "1 1";
     88  CHECK(!IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
     89                     strlen(source)));
     90 
     91  source = ".1";
     92  CHECK(!IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
     93                     strlen(source)));
     94 
     95  source = "undefined";
     96  CHECK(!IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
     97                     strlen(source)));
     98 
     99  source = "TRUE";
    100  CHECK(!IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
    101                     strlen(source)));
    102 
    103  source = "'foo'";
    104  CHECK(!IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
    105                     strlen(source)));
    106 
    107  source = "[";
    108  CHECK(!IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
    109                     strlen(source)));
    110 
    111  source = "{";
    112  CHECK(!IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
    113                     strlen(source)));
    114 
    115  source = "/a/";
    116  CHECK(!IsValidJSON(reinterpret_cast<const JS::Latin1Char*>(source),
    117                     strlen(source)));
    118 
    119  return true;
    120 }
    121 
    122 END_TEST(testIsValidJSONLatin1)
    123 
    124 BEGIN_FRONTEND_TEST(testIsValidJSONTwoBytes) {
    125  const char16_t* source;
    126 
    127  source = u"true";
    128  CHECK(IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    129 
    130  source = u"false";
    131  CHECK(IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    132 
    133  source = u"null";
    134  CHECK(IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    135 
    136  source = u"0";
    137  CHECK(IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    138 
    139  source = u"1";
    140  CHECK(IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    141 
    142  source = u"-1";
    143  CHECK(IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    144 
    145  source = u"1.75";
    146  CHECK(IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    147 
    148  source = u"9000000000";
    149  CHECK(IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    150 
    151  source = u"\"foo\"";
    152  CHECK(IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    153 
    154  source = u"[]";
    155  CHECK(IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    156 
    157  source = u"[1, true]";
    158  CHECK(IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    159 
    160  source = u"{}";
    161  CHECK(IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    162 
    163  source = u"{\"key\": 10}";
    164  CHECK(IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    165 
    166  source = u"{\"key\": 10, \"prop\": 20}";
    167  CHECK(IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    168 
    169  source = u"1 ";
    170  CHECK(IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    171 
    172  // Invalid cases.
    173 
    174  source = u"";
    175  CHECK(!IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    176 
    177  source = u"1 1";
    178  CHECK(!IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    179 
    180  source = u".1";
    181  CHECK(!IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    182 
    183  source = u"undefined";
    184  CHECK(!IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    185 
    186  source = u"TRUE";
    187  CHECK(!IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    188 
    189  source = u"'foo'";
    190  CHECK(!IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    191 
    192  source = u"[";
    193  CHECK(!IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    194 
    195  source = u"{";
    196  CHECK(!IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    197 
    198  source = u"/a/";
    199  CHECK(!IsValidJSON(source, std::char_traits<char16_t>::length(source)));
    200 
    201  return true;
    202 }
    203 
    204 END_TEST(testIsValidJSONTwoBytes)
    205 
    206 BEGIN_FRONTEND_TEST(testParseJSONWithHandler) {
    207  {
    208    MyHandler handler;
    209 
    210    const char* source =
    211        "{ \"prop1\": 10.5, \"prop\\uff12\": [true, false, null, \"Ascii\", "
    212        "\"\\u3042\\u3044\\u3046\", \"\\u0020\", \"\\u0080\"] }";
    213    CHECK(JS::ParseJSONWithHandler((const JS::Latin1Char*)source,
    214                                   std::char_traits<char>::length(source),
    215                                   &handler));
    216 
    217    size_t i = 0;
    218 
    219    CHECK(handler.events[i++] == MyHandler::Event::StartObject);
    220 
    221    // Non-escaped ASCII property name in Latin1 input should be passed with
    222    // Latin1.
    223    CHECK(handler.events[i++] == MyHandler::Event::Latin1Prop1);
    224 
    225    CHECK(handler.events[i++] == MyHandler::Event::Number);
    226 
    227    // Escaped non-Latin1 property name in Latin1 input should be passed with
    228    // TwoBytes.
    229    CHECK(handler.events[i++] == MyHandler::Event::TwoBytesProp2);
    230    CHECK(handler.events[i++] == MyHandler::Event::StartArray);
    231    CHECK(handler.events[i++] == MyHandler::Event::True);
    232    CHECK(handler.events[i++] == MyHandler::Event::False);
    233    CHECK(handler.events[i++] == MyHandler::Event::Null);
    234 
    235    // Non-escaped ASCII string in Latin1 input should be passed with Latin1.
    236    CHECK(handler.events[i++] == MyHandler::Event::Latin1Str1);
    237 
    238    // Escaped non-Latin1 string in Latin1 input should be passed with TwoBytes.
    239    CHECK(handler.events[i++] == MyHandler::Event::TwoBytesStr2);
    240 
    241    // Escaped ASCII-range string in Latin1 input should be passed with Latin1.
    242    CHECK(handler.events[i++] == MyHandler::Event::Latin1Str3);
    243 
    244    // Escaped Latin1-range string in Latin1 input should be passed with Latin1.
    245    CHECK(handler.events[i++] == MyHandler::Event::Latin1Str4);
    246 
    247    CHECK(handler.events[i++] == MyHandler::Event::EndArray);
    248    CHECK(handler.events[i++] == MyHandler::Event::EndObject);
    249    CHECK(handler.events.length() == i);
    250  }
    251  {
    252    MyHandler handler;
    253 
    254    const char* source = "{";
    255    CHECK(!JS::ParseJSONWithHandler((const JS::Latin1Char*)source,
    256                                    std::char_traits<char>::length(source),
    257                                    &handler));
    258 
    259    size_t i = 0;
    260 
    261    CHECK(handler.events[i++] == MyHandler::Event::StartObject);
    262    CHECK(handler.events[i++] == MyHandler::Event::Error);
    263    CHECK(handler.events.length() == i);
    264  }
    265 
    266  {
    267    MyHandler handler;
    268 
    269    const char16_t* source =
    270        u"{ \"prop1\": 10.5, \"prop\uff12\": [true, false, null, \"Ascii\", "
    271        u"\"\\u3042\\u3044\\u3046\", \"\\u0020\", \"\\u0080\"] }";
    272    CHECK(JS::ParseJSONWithHandler(
    273        source, std::char_traits<char16_t>::length(source), &handler));
    274 
    275    size_t i = 0;
    276 
    277    CHECK(handler.events[i++] == MyHandler::Event::StartObject);
    278 
    279    // Non-escaped ASCII property name in TwoBytes input should be passed with
    280    // TwoBytes.
    281    CHECK(handler.events[i++] == MyHandler::Event::TwoBytesProp1);
    282 
    283    CHECK(handler.events[i++] == MyHandler::Event::Number);
    284 
    285    // Escaped non-Latin1 property name in TwoBytes input should be passed with
    286    // TwoBytes.
    287    CHECK(handler.events[i++] == MyHandler::Event::TwoBytesProp2);
    288 
    289    CHECK(handler.events[i++] == MyHandler::Event::StartArray);
    290    CHECK(handler.events[i++] == MyHandler::Event::True);
    291    CHECK(handler.events[i++] == MyHandler::Event::False);
    292    CHECK(handler.events[i++] == MyHandler::Event::Null);
    293 
    294    // Non-escaped ASCII string in TwoBytes input should be passed with
    295    // TwoBytes.
    296    CHECK(handler.events[i++] == MyHandler::Event::TwoBytesStr1);
    297 
    298    // Escaped non-Latin1 string in TwoBytes input should be passed with
    299    // TwoBytes.
    300    CHECK(handler.events[i++] == MyHandler::Event::TwoBytesStr2);
    301 
    302    // Escaped ASCII-range string in TwoBytes input should be passed with
    303    // Latin1.
    304    CHECK(handler.events[i++] == MyHandler::Event::Latin1Str3);
    305 
    306    // Escaped Latin1-range string in TwoBytes input should be passed with
    307    // Latin1.
    308    CHECK(handler.events[i++] == MyHandler::Event::Latin1Str4);
    309 
    310    CHECK(handler.events[i++] == MyHandler::Event::EndArray);
    311    CHECK(handler.events[i++] == MyHandler::Event::EndObject);
    312    CHECK(handler.events.length() == i);
    313  }
    314 
    315  {
    316    MyHandler handler;
    317 
    318    const char16_t* source = u"{";
    319    CHECK(!JS::ParseJSONWithHandler(
    320        source, std::char_traits<char16_t>::length(source), &handler));
    321 
    322    size_t i = 0;
    323 
    324    CHECK(handler.events[i++] == MyHandler::Event::StartObject);
    325    CHECK(handler.events[i++] == MyHandler::Event::Error);
    326    CHECK(handler.events.length() == i);
    327  }
    328 
    329  // Verify the failure case is handled properly and no methods are called
    330  // after the failure.
    331 
    332  bool checkedLast = false;
    333  for (size_t failAt = 1; !checkedLast; failAt++) {
    334    MyHandler handler;
    335    handler.failAt.emplace(failAt);
    336 
    337    const char* source =
    338        "{ \"prop1\": 10.5, \"prop\\uff12\": [true, false, null, \"Ascii\", "
    339        "\"\\u3042\\u3044\\u3046\", \"\\u0020\", \"\\u0080\"] }";
    340    CHECK(!JS::ParseJSONWithHandler((const JS::Latin1Char*)source,
    341                                    std::char_traits<char>::length(source),
    342                                    &handler));
    343 
    344    CHECK(handler.events.length() == failAt);
    345 
    346    size_t i = 0;
    347 
    348    CHECK(handler.events[i++] == MyHandler::Event::StartObject);
    349    if (i >= failAt) {
    350      continue;
    351    }
    352    CHECK(handler.events[i++] == MyHandler::Event::Latin1Prop1);
    353    if (i >= failAt) {
    354      continue;
    355    }
    356    CHECK(handler.events[i++] == MyHandler::Event::Number);
    357    if (i >= failAt) {
    358      continue;
    359    }
    360    CHECK(handler.events[i++] == MyHandler::Event::TwoBytesProp2);
    361    if (i >= failAt) {
    362      continue;
    363    }
    364    CHECK(handler.events[i++] == MyHandler::Event::StartArray);
    365    if (i >= failAt) {
    366      continue;
    367    }
    368    CHECK(handler.events[i++] == MyHandler::Event::True);
    369    if (i >= failAt) {
    370      continue;
    371    }
    372    CHECK(handler.events[i++] == MyHandler::Event::False);
    373    if (i >= failAt) {
    374      continue;
    375    }
    376    CHECK(handler.events[i++] == MyHandler::Event::Null);
    377    if (i >= failAt) {
    378      continue;
    379    }
    380    CHECK(handler.events[i++] == MyHandler::Event::Latin1Str1);
    381    if (i >= failAt) {
    382      continue;
    383    }
    384    CHECK(handler.events[i++] == MyHandler::Event::TwoBytesStr2);
    385    if (i >= failAt) {
    386      continue;
    387    }
    388    CHECK(handler.events[i++] == MyHandler::Event::Latin1Str3);
    389    if (i >= failAt) {
    390      continue;
    391    }
    392    CHECK(handler.events[i++] == MyHandler::Event::Latin1Str4);
    393    if (i >= failAt) {
    394      continue;
    395    }
    396    CHECK(handler.events[i++] == MyHandler::Event::EndArray);
    397    if (i >= failAt) {
    398      continue;
    399    }
    400    CHECK(handler.events[i++] == MyHandler::Event::EndObject);
    401    checkedLast = true;
    402  }
    403 
    404  checkedLast = false;
    405  for (size_t failAt = 1; !checkedLast; failAt++) {
    406    MyHandler handler;
    407    handler.failAt.emplace(failAt);
    408 
    409    const char16_t* source =
    410        u"{ \"prop1\": 10.5, \"prop\uff12\": [true, false, null, \"Ascii\", "
    411        u"\"\\u3042\\u3044\\u3046\", \"\\u0020\", \"\\u0080\"] }";
    412    CHECK(!JS::ParseJSONWithHandler(
    413        source, std::char_traits<char16_t>::length(source), &handler));
    414 
    415    CHECK(handler.events.length() == failAt);
    416 
    417    size_t i = 0;
    418 
    419    CHECK(handler.events[i++] == MyHandler::Event::StartObject);
    420    if (i >= failAt) {
    421      continue;
    422    }
    423    CHECK(handler.events[i++] == MyHandler::Event::TwoBytesProp1);
    424    if (i >= failAt) {
    425      continue;
    426    }
    427    CHECK(handler.events[i++] == MyHandler::Event::Number);
    428    if (i >= failAt) {
    429      continue;
    430    }
    431    CHECK(handler.events[i++] == MyHandler::Event::TwoBytesProp2);
    432    if (i >= failAt) {
    433      continue;
    434    }
    435    CHECK(handler.events[i++] == MyHandler::Event::StartArray);
    436    if (i >= failAt) {
    437      continue;
    438    }
    439    CHECK(handler.events[i++] == MyHandler::Event::True);
    440    if (i >= failAt) {
    441      continue;
    442    }
    443    CHECK(handler.events[i++] == MyHandler::Event::False);
    444    if (i >= failAt) {
    445      continue;
    446    }
    447    CHECK(handler.events[i++] == MyHandler::Event::Null);
    448    if (i >= failAt) {
    449      continue;
    450    }
    451    CHECK(handler.events[i++] == MyHandler::Event::TwoBytesStr1);
    452    if (i >= failAt) {
    453      continue;
    454    }
    455    CHECK(handler.events[i++] == MyHandler::Event::TwoBytesStr2);
    456    if (i >= failAt) {
    457      continue;
    458    }
    459    CHECK(handler.events[i++] == MyHandler::Event::Latin1Str3);
    460    if (i >= failAt) {
    461      continue;
    462    }
    463    CHECK(handler.events[i++] == MyHandler::Event::Latin1Str4);
    464    if (i >= failAt) {
    465      continue;
    466    }
    467    CHECK(handler.events[i++] == MyHandler::Event::EndArray);
    468    if (i >= failAt) {
    469      continue;
    470    }
    471    CHECK(handler.events[i++] == MyHandler::Event::EndObject);
    472    checkedLast = true;
    473  }
    474 
    475  {
    476    const size_t failAt = 1;
    477    MyHandler handler;
    478    const char16_t* source;
    479 
    480 #define IMMEDIATE_FAIL(json)                                          \
    481  handler.failAt.emplace(failAt);                                     \
    482  source = json;                                                      \
    483  CHECK(!JS::ParseJSONWithHandler(                                    \
    484      source, std::char_traits<char16_t>::length(source), &handler)); \
    485  CHECK(handler.events.length() == failAt);                           \
    486  handler.events.clear();
    487 
    488    IMMEDIATE_FAIL(u"{");
    489    IMMEDIATE_FAIL(u"[");
    490    IMMEDIATE_FAIL(u"\"string\"");
    491    IMMEDIATE_FAIL(u"1");
    492    IMMEDIATE_FAIL(u"true");
    493    IMMEDIATE_FAIL(u"null");
    494 
    495 #undef IMMEDIATE_FAIL
    496  }
    497 
    498  return true;
    499 }
    500 
    501 class MyHandler : public JS::JSONParseHandler {
    502 public:
    503  enum class Event {
    504    Uninitialized = 0,
    505 
    506    StartObject,
    507    Latin1Prop1,
    508    TwoBytesProp1,
    509    Number,
    510    TwoBytesProp2,
    511    StartArray,
    512    True,
    513    False,
    514    Null,
    515    Latin1Str1,
    516    TwoBytesStr1,
    517    TwoBytesStr2,
    518    Latin1Str3,
    519    Latin1Str4,
    520    EndArray,
    521    EndObject,
    522    Error,
    523    UnexpectedNumber,
    524    UnexpectedLatin1Prop,
    525    UnexpectedTwoBytesProp,
    526    UnexpectedLatin1String,
    527    UnexpectedTwoBytesString,
    528  };
    529  js::Vector<Event, 0, js::SystemAllocPolicy> events;
    530  mozilla::Maybe<size_t> failAt;
    531 
    532  MyHandler() {}
    533  virtual ~MyHandler() {}
    534 
    535  bool startObject() override {
    536    MOZ_ALWAYS_TRUE(events.append(Event::StartObject));
    537    if (failAt.isSome() && events.length() == *failAt) {
    538      failAt.reset();
    539      return false;
    540    }
    541    return true;
    542  }
    543  bool propertyName(const JS::Latin1Char* name, size_t length) override {
    544    if (length == 5 && name[0] == 'p' && name[1] == 'r' && name[2] == 'o' &&
    545        name[3] == 'p' && name[4] == '1') {
    546      MOZ_ALWAYS_TRUE(events.append(Event::Latin1Prop1));
    547    } else {
    548      MOZ_ALWAYS_TRUE(events.append(Event::UnexpectedLatin1Prop));
    549    }
    550    if (failAt.isSome() && events.length() == *failAt) {
    551      failAt.reset();
    552      return false;
    553    }
    554    return true;
    555  }
    556  bool propertyName(const char16_t* name, size_t length) override {
    557    if (length == 5 && name[0] == 'p' && name[1] == 'r' && name[2] == 'o' &&
    558        name[3] == 'p' && name[4] == '1') {
    559      MOZ_ALWAYS_TRUE(events.append(Event::TwoBytesProp1));
    560    } else if (length == 5 && name[0] == 'p' && name[1] == 'r' &&
    561               name[2] == 'o' && name[3] == 'p' && name[4] == 0xff12) {
    562      MOZ_ALWAYS_TRUE(events.append(Event::TwoBytesProp2));
    563    } else {
    564      MOZ_ALWAYS_TRUE(events.append(Event::UnexpectedTwoBytesProp));
    565    }
    566    if (failAt.isSome() && events.length() == *failAt) {
    567      failAt.reset();
    568      return false;
    569    }
    570    return true;
    571  }
    572  bool endObject() override {
    573    MOZ_ALWAYS_TRUE(events.append(Event::EndObject));
    574    if (failAt.isSome() && events.length() == *failAt) {
    575      failAt.reset();
    576      return false;
    577    }
    578    return true;
    579  }
    580 
    581  bool startArray() override {
    582    MOZ_ALWAYS_TRUE(events.append(Event::StartArray));
    583    if (failAt.isSome() && events.length() == *failAt) {
    584      failAt.reset();
    585      return false;
    586    }
    587    return true;
    588  }
    589  bool endArray() override {
    590    MOZ_ALWAYS_TRUE(events.append(Event::EndArray));
    591    if (failAt.isSome() && events.length() == *failAt) {
    592      failAt.reset();
    593      return false;
    594    }
    595    return true;
    596  }
    597 
    598  bool stringValue(const JS::Latin1Char* name, size_t length) override {
    599    if (length == 5 && name[0] == 'A' && name[1] == 's' && name[2] == 'c' &&
    600        name[3] == 'i' && name[4] == 'i') {
    601      MOZ_ALWAYS_TRUE(events.append(Event::Latin1Str1));
    602    } else if (length == 1 && name[0] == ' ') {
    603      MOZ_ALWAYS_TRUE(events.append(Event::Latin1Str3));
    604    } else if (length == 1 && name[0] == 0x80) {
    605      MOZ_ALWAYS_TRUE(events.append(Event::Latin1Str4));
    606    } else {
    607      MOZ_ALWAYS_TRUE(events.append(Event::UnexpectedLatin1String));
    608    }
    609    if (failAt.isSome() && events.length() == *failAt) {
    610      failAt.reset();
    611      return false;
    612    }
    613    return true;
    614  }
    615  bool stringValue(const char16_t* name, size_t length) override {
    616    if (length == 5 && name[0] == 'A' && name[1] == 's' && name[2] == 'c' &&
    617        name[3] == 'i' && name[4] == 'i') {
    618      MOZ_ALWAYS_TRUE(events.append(Event::TwoBytesStr1));
    619    } else if (length == 3 && name[0] == 0x3042 && name[1] == 0x3044 &&
    620               name[2] == 0x3046) {
    621      MOZ_ALWAYS_TRUE(events.append(Event::TwoBytesStr2));
    622    } else {
    623      MOZ_ALWAYS_TRUE(events.append(Event::UnexpectedTwoBytesString));
    624    }
    625    if (failAt.isSome() && events.length() == *failAt) {
    626      failAt.reset();
    627      return false;
    628    }
    629    return true;
    630  }
    631  bool numberValue(double d) override {
    632    if (d == 10.5) {
    633      MOZ_ALWAYS_TRUE(events.append(Event::Number));
    634    } else {
    635      MOZ_ALWAYS_TRUE(events.append(Event::UnexpectedNumber));
    636    }
    637    if (failAt.isSome() && events.length() == *failAt) {
    638      failAt.reset();
    639      return false;
    640    }
    641    return true;
    642  }
    643  bool booleanValue(bool v) override {
    644    if (v) {
    645      MOZ_ALWAYS_TRUE(events.append(Event::True));
    646    } else {
    647      MOZ_ALWAYS_TRUE(events.append(Event::False));
    648    }
    649    if (failAt.isSome() && events.length() == *failAt) {
    650      failAt.reset();
    651      return false;
    652    }
    653    return true;
    654  }
    655  bool nullValue() override {
    656    MOZ_ALWAYS_TRUE(events.append(Event::Null));
    657    if (failAt.isSome() && events.length() == *failAt) {
    658      failAt.reset();
    659      return false;
    660    }
    661    return true;
    662  }
    663 
    664  void error(const char* msg, uint32_t line, uint32_t column) override {
    665    MOZ_ALWAYS_TRUE(events.append(Event::Error));
    666  }
    667 };
    668 
    669 END_TEST(testParseJSONWithHandler)