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

common-test.c++ (13780B)


      1 // Copyright (c) 2013-2014 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 "common.h"
     23 #include "../string.h"
     24 #include <kj/compat/gtest.h>
     25 
     26 namespace kj {
     27 namespace parse {
     28 namespace {
     29 
     30 typedef IteratorInput<char, const char*> Input;
     31 
     32 TEST(CommonParsers, AnyParser) {
     33   StringPtr text = "foo";
     34   Input input(text.begin(), text.end());
     35   constexpr auto parser = any;
     36 
     37   Maybe<char> result = parser(input);
     38   KJ_IF_MAYBE(c, result) {
     39     EXPECT_EQ('f', *c);
     40   } else {
     41     ADD_FAILURE() << "Expected 'c', got null.";
     42   }
     43   EXPECT_FALSE(input.atEnd());
     44 
     45   result = parser(input);
     46   KJ_IF_MAYBE(c, result) {
     47     EXPECT_EQ('o', *c);
     48   } else {
     49     ADD_FAILURE() << "Expected 'o', got null.";
     50   }
     51   EXPECT_FALSE(input.atEnd());
     52 
     53   result = parser(input);
     54   KJ_IF_MAYBE(c, result) {
     55     EXPECT_EQ('o', *c);
     56   } else {
     57     ADD_FAILURE() << "Expected 'o', got null.";
     58   }
     59   EXPECT_TRUE(input.atEnd());
     60 
     61   result = parser(input);
     62   EXPECT_TRUE(result == nullptr);
     63   EXPECT_TRUE(input.atEnd());
     64 }
     65 
     66 TEST(CommonParsers, ExactElementParser) {
     67   StringPtr text = "foo";
     68   Input input(text.begin(), text.end());
     69 
     70   Maybe<Tuple<>> result = exactly('f')(input);
     71   EXPECT_TRUE(result != nullptr);
     72   EXPECT_FALSE(input.atEnd());
     73 
     74   result = exactly('o')(input);
     75   EXPECT_TRUE(result != nullptr);
     76   EXPECT_FALSE(input.atEnd());
     77 
     78   result = exactly('x')(input);
     79   EXPECT_TRUE(result == nullptr);
     80   EXPECT_FALSE(input.atEnd());
     81 
     82   auto parser = exactly('o');
     83   ParserRef<Input, Tuple<>> wrapped = ref<Input>(parser);
     84   result = wrapped(input);
     85   EXPECT_TRUE(result != nullptr);
     86   EXPECT_TRUE(input.atEnd());
     87 }
     88 
     89 TEST(CommonParsers, ExactlyConstParser) {
     90   StringPtr text = "foo";
     91   Input input(text.begin(), text.end());
     92 
     93   Maybe<Tuple<>> result = exactlyConst<char, 'f'>()(input);
     94   EXPECT_TRUE(result != nullptr);
     95   EXPECT_FALSE(input.atEnd());
     96 
     97   result = exactlyConst<char, 'o'>()(input);
     98   EXPECT_TRUE(result != nullptr);
     99   EXPECT_FALSE(input.atEnd());
    100 
    101   result = exactlyConst<char, 'x'>()(input);
    102   EXPECT_TRUE(result == nullptr);
    103   EXPECT_FALSE(input.atEnd());
    104 
    105   auto parser = exactlyConst<char, 'o'>();
    106   ParserRef<Input, Tuple<>> wrapped = ref<Input>(parser);
    107   result = wrapped(input);
    108   EXPECT_TRUE(result != nullptr);
    109   EXPECT_TRUE(input.atEnd());
    110 }
    111 
    112 TEST(CommonParsers, ConstResultParser) {
    113   auto parser = constResult(exactly('o'), 123);
    114 
    115   StringPtr text = "o";
    116   Input input(text.begin(), text.end());
    117   Maybe<int> result = parser(input);
    118   KJ_IF_MAYBE(i, result) {
    119     EXPECT_EQ(123, *i);
    120   } else {
    121     ADD_FAILURE() << "Expected 123, got null.";
    122   }
    123   EXPECT_TRUE(input.atEnd());
    124 }
    125 
    126 TEST(CommonParsers, DiscardParser) {
    127   auto parser = discard(any);
    128 
    129   StringPtr text = "o";
    130   Input input(text.begin(), text.end());
    131   Maybe<Tuple<>> result = parser(input);
    132   EXPECT_TRUE(result != nullptr);
    133   EXPECT_TRUE(input.atEnd());
    134 }
    135 
    136 TEST(CommonParsers, SequenceParser) {
    137   StringPtr text = "foo";
    138 
    139   {
    140     Input input(text.begin(), text.end());
    141     Maybe<Tuple<>> result = sequence(exactly('f'), exactly('o'), exactly('o'))(input);
    142     EXPECT_TRUE(result != nullptr);
    143     EXPECT_TRUE(input.atEnd());
    144   }
    145 
    146   {
    147     Input input(text.begin(), text.end());
    148     Maybe<Tuple<>> result = sequence(exactly('f'), exactly('o'))(input);
    149     EXPECT_TRUE(result != nullptr);
    150     EXPECT_FALSE(input.atEnd());
    151   }
    152 
    153   {
    154     Input input(text.begin(), text.end());
    155     Maybe<Tuple<>> result = sequence(exactly('x'), exactly('o'), exactly('o'))(input);
    156     EXPECT_TRUE(result == nullptr);
    157     EXPECT_FALSE(input.atEnd());
    158   }
    159 
    160   {
    161     Input input(text.begin(), text.end());
    162     Maybe<Tuple<>> result =
    163         sequence(sequence(exactly('f'), exactly('o')), exactly('o'))(input);
    164     EXPECT_TRUE(result != nullptr);
    165     EXPECT_TRUE(input.atEnd());
    166   }
    167 
    168   {
    169     Input input(text.begin(), text.end());
    170     Maybe<Tuple<>> result =
    171         sequence(sequence(exactly('f')), exactly('o'), exactly('o'))(input);
    172     EXPECT_TRUE(result != nullptr);
    173     EXPECT_TRUE(input.atEnd());
    174   }
    175 
    176   {
    177     Input input(text.begin(), text.end());
    178     Maybe<int> result = sequence(transform(exactly('f'), [](){return 123;}),
    179                                  exactly('o'), exactly('o'))(input);
    180     KJ_IF_MAYBE(i, result) {
    181       EXPECT_EQ(123, *i);
    182     } else {
    183       ADD_FAILURE() << "Expected 123, got null.";
    184     }
    185     EXPECT_TRUE(input.atEnd());
    186   }
    187 }
    188 
    189 TEST(CommonParsers, ManyParserCountOnly) {
    190   StringPtr text = "foooob";
    191 
    192   auto parser = sequence(exactly('f'), many(exactly('o')));
    193 
    194   {
    195     Input input(text.begin(), text.begin() + 3);
    196     Maybe<int> result = parser(input);
    197     KJ_IF_MAYBE(i, result) {
    198       EXPECT_EQ(2, *i);
    199     } else {
    200       ADD_FAILURE() << "Expected 2, got null.";
    201     }
    202     EXPECT_TRUE(input.atEnd());
    203   }
    204 
    205   {
    206     Input input(text.begin(), text.begin() + 5);
    207     Maybe<int> result = parser(input);
    208     KJ_IF_MAYBE(i, result) {
    209       EXPECT_EQ(4, *i);
    210     } else {
    211       ADD_FAILURE() << "Expected 4, got null.";
    212     }
    213     EXPECT_TRUE(input.atEnd());
    214   }
    215 
    216   {
    217     Input input(text.begin(), text.end());
    218     Maybe<int> result = parser(input);
    219     KJ_IF_MAYBE(i, result) {
    220       EXPECT_EQ(4, *i);
    221     } else {
    222       ADD_FAILURE() << "Expected 4, got null.";
    223     }
    224     EXPECT_FALSE(input.atEnd());
    225   }
    226 }
    227 
    228 TEST(CommonParsers, TimesParser) {
    229   StringPtr text = "foobar";
    230 
    231   auto parser = sequence(exactly('f'), times(any, 4));
    232 
    233   {
    234     Input input(text.begin(), text.begin() + 4);
    235     Maybe<Array<char>> result = parser(input);
    236     EXPECT_TRUE(result == nullptr);
    237     EXPECT_TRUE(input.atEnd());
    238   }
    239 
    240   {
    241     Input input(text.begin(), text.begin() + 5);
    242     Maybe<Array<char>> result = parser(input);
    243     KJ_IF_MAYBE(s, result) {
    244       EXPECT_EQ("ooba", heapString(*s));
    245     } else {
    246       ADD_FAILURE() << "Expected string, got null.";
    247     }
    248     EXPECT_TRUE(input.atEnd());
    249   }
    250 
    251   {
    252     Input input(text.begin(), text.end());
    253     Maybe<Array<char>> result = parser(input);
    254     KJ_IF_MAYBE(s, result) {
    255       EXPECT_EQ("ooba", heapString(*s));
    256     } else {
    257       ADD_FAILURE() << "Expected string, got null.";
    258     }
    259     EXPECT_FALSE(input.atEnd());
    260   }
    261 }
    262 
    263 TEST(CommonParsers, TimesParserCountOnly) {
    264   StringPtr text = "foooob";
    265 
    266   auto parser = sequence(exactly('f'), times(exactly('o'), 4));
    267 
    268   {
    269     Input input(text.begin(), text.begin() + 4);
    270     Maybe<Tuple<>> result = parser(input);
    271     EXPECT_TRUE(result == nullptr);
    272     EXPECT_TRUE(input.atEnd());
    273   }
    274 
    275   {
    276     Input input(text.begin(), text.begin() + 5);
    277     Maybe<Tuple<>> result = parser(input);
    278     EXPECT_TRUE(result != nullptr);
    279     EXPECT_TRUE(input.atEnd());
    280   }
    281 
    282   {
    283     Input input(text.begin(), text.end());
    284     Maybe<Tuple<>> result = parser(input);
    285     EXPECT_TRUE(result != nullptr);
    286     EXPECT_FALSE(input.atEnd());
    287   }
    288 
    289   text = "fooob";
    290 
    291   {
    292     Input input(text.begin(), text.end());
    293     Maybe<Tuple<>> result = parser(input);
    294     EXPECT_TRUE(result == nullptr);
    295     EXPECT_FALSE(input.atEnd());
    296   }
    297 }
    298 
    299 TEST(CommonParsers, ManyParserSubResult) {
    300   StringPtr text = "foooob";
    301 
    302   auto parser = many(any);
    303 
    304   {
    305     Input input(text.begin(), text.end());
    306     Maybe<Array<char>> result = parser(input);
    307     KJ_IF_MAYBE(chars, result) {
    308       EXPECT_EQ(text, heapString(*chars));
    309     } else {
    310       ADD_FAILURE() << "Expected char array, got null.";
    311     }
    312     EXPECT_TRUE(input.atEnd());
    313   }
    314 }
    315 
    316 TEST(CommonParsers, OptionalParser) {
    317   auto parser = sequence(
    318       transform(exactly('b'), []() -> uint { return 123; }),
    319       optional(transform(exactly('a'), []() -> uint { return 456; })),
    320       transform(exactly('r'), []() -> uint { return 789; }));
    321 
    322   {
    323     StringPtr text = "bar";
    324     Input input(text.begin(), text.end());
    325     Maybe<Tuple<uint, Maybe<uint>, uint>> result = parser(input);
    326     KJ_IF_MAYBE(value, result) {
    327       EXPECT_EQ(123u, get<0>(*value));
    328       KJ_IF_MAYBE(value2, get<1>(*value)) {
    329         EXPECT_EQ(456u, *value2);
    330       } else {
    331         ADD_FAILURE() << "Expected 456, got null.";
    332       }
    333       EXPECT_EQ(789u, get<2>(*value));
    334     } else {
    335       ADD_FAILURE() << "Expected result tuple, got null.";
    336     }
    337     EXPECT_TRUE(input.atEnd());
    338   }
    339 
    340   {
    341     StringPtr text = "br";
    342     Input input(text.begin(), text.end());
    343     Maybe<Tuple<uint, Maybe<uint>, uint>> result = parser(input);
    344     KJ_IF_MAYBE(value, result) {
    345       EXPECT_EQ(123u, get<0>(*value));
    346       EXPECT_TRUE(get<1>(*value) == nullptr);
    347       EXPECT_EQ(789u, get<2>(*value));
    348     } else {
    349       ADD_FAILURE() << "Expected result tuple, got null.";
    350     }
    351     EXPECT_TRUE(input.atEnd());
    352   }
    353 
    354   {
    355     StringPtr text = "bzr";
    356     Input input(text.begin(), text.end());
    357     Maybe<Tuple<uint, Maybe<uint>, uint>> result = parser(input);
    358     EXPECT_TRUE(result == nullptr);
    359   }
    360 }
    361 
    362 TEST(CommonParsers, OneOfParser) {
    363   auto parser = oneOf(
    364       transform(sequence(exactly('f'), exactly('o'), exactly('o')),
    365                 []() -> StringPtr { return "foo"; }),
    366       transform(sequence(exactly('b'), exactly('a'), exactly('r')),
    367                 []() -> StringPtr { return "bar"; }));
    368 
    369   {
    370     StringPtr text = "foo";
    371     Input input(text.begin(), text.end());
    372     Maybe<StringPtr> result = parser(input);
    373     KJ_IF_MAYBE(s, result) {
    374       EXPECT_EQ("foo", *s);
    375     } else {
    376       ADD_FAILURE() << "Expected 'foo', got null.";
    377     }
    378     EXPECT_TRUE(input.atEnd());
    379   }
    380 
    381   {
    382     StringPtr text = "bar";
    383     Input input(text.begin(), text.end());
    384     Maybe<StringPtr> result = parser(input);
    385     KJ_IF_MAYBE(s, result) {
    386       EXPECT_EQ("bar", *s);
    387     } else {
    388       ADD_FAILURE() << "Expected 'bar', got null.";
    389     }
    390     EXPECT_TRUE(input.atEnd());
    391   }
    392 }
    393 
    394 TEST(CommonParsers, TransformParser) {
    395   StringPtr text = "foo";
    396 
    397   auto parser = transformWithLocation(
    398       sequence(exactly('f'), exactly('o'), exactly('o')),
    399       [](Span<const char*> location) -> int {
    400         EXPECT_EQ("foo", StringPtr(location.begin(), location.end()));
    401         return 123;
    402       });
    403 
    404   {
    405     Input input(text.begin(), text.end());
    406     Maybe<int> result = parser(input);
    407     KJ_IF_MAYBE(i, result) {
    408       EXPECT_EQ(123, *i);
    409     } else {
    410       ADD_FAILURE() << "Expected 123, got null.";
    411     }
    412     EXPECT_TRUE(input.atEnd());
    413   }
    414 }
    415 
    416 TEST(CommonParsers, TransformOrRejectParser) {
    417   auto parser = transformOrReject(many(any),
    418       [](Array<char> chars) -> Maybe<int> {
    419         if (heapString(chars) == "foo") {
    420           return 123;
    421         } else {
    422           return nullptr;
    423         }
    424       });
    425 
    426   {
    427     StringPtr text = "foo";
    428     Input input(text.begin(), text.end());
    429     Maybe<int> result = parser(input);
    430     KJ_IF_MAYBE(i, result) {
    431       EXPECT_EQ(123, *i);
    432     } else {
    433       ADD_FAILURE() << "Expected 123, got null.";
    434     }
    435     EXPECT_TRUE(input.atEnd());
    436   }
    437 
    438   {
    439     StringPtr text = "bar";
    440     Input input(text.begin(), text.end());
    441     Maybe<int> result = parser(input);
    442     EXPECT_TRUE(result == nullptr);
    443     EXPECT_TRUE(input.atEnd());
    444   }
    445 }
    446 
    447 TEST(CommonParsers, References) {
    448   struct TransformFunc {
    449     int value;
    450 
    451     TransformFunc(int value): value(value) {}
    452 
    453     int operator()() const { return value; }
    454   };
    455 
    456   // Don't use auto for the parsers here in order to verify that the templates are properly choosing
    457   // whether to use references or copies.
    458 
    459   Transform_<Exactly_<char>, TransformFunc> parser1 =
    460       transform(exactly('f'), TransformFunc(12));
    461 
    462   auto otherParser = exactly('o');
    463   Transform_<Exactly_<char>&, TransformFunc> parser2 =
    464       transform(otherParser, TransformFunc(34));
    465 
    466   auto otherParser2 = exactly('b');
    467   Transform_<Exactly_<char>, TransformFunc> parser3 =
    468       transform(mv(otherParser2), TransformFunc(56));
    469 
    470   StringPtr text = "foob";
    471   auto parser = transform(
    472       sequence(parser1, parser2, exactly('o'), parser3),
    473       [](int i, int j, int k) { return i + j + k; });
    474 
    475   {
    476     Input input(text.begin(), text.end());
    477     Maybe<int> result = parser(input);
    478     KJ_IF_MAYBE(i, result) {
    479       EXPECT_EQ(12 + 34 + 56, *i);
    480     } else {
    481       ADD_FAILURE() << "Expected 12 + 34 + 56, got null.";
    482     }
    483     EXPECT_TRUE(input.atEnd());
    484   }
    485 }
    486 
    487 TEST(CommonParsers, NotLookingAt) {
    488   auto parser = notLookingAt(exactly('a'));
    489 
    490   {
    491     StringPtr text = "a";
    492     Input input(text.begin(), text.end());
    493     EXPECT_TRUE(parser(input) == nullptr);
    494     EXPECT_FALSE(input.atEnd());
    495   }
    496 
    497   {
    498     StringPtr text = "b";
    499     Input input(text.begin(), text.end());
    500     EXPECT_TRUE(parser(input) != nullptr);
    501     EXPECT_FALSE(input.atEnd());
    502   }
    503 }
    504 
    505 TEST(CommonParsers, EndOfInput) {
    506   auto parser = endOfInput;
    507 
    508   {
    509     StringPtr text = "a";
    510     Input input(text.begin(), text.end());
    511     EXPECT_TRUE(parser(input) == nullptr);
    512     EXPECT_TRUE(parser(input) == nullptr);
    513     input.next();
    514     EXPECT_FALSE(parser(input) == nullptr);
    515   }
    516 }
    517 
    518 }  // namespace
    519 }  // namespace parse
    520 }  // namespace kj