Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2016 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "Test.h"
      9 
     10 #if defined(SK_XML)
     11 #include "SkPEG.h"
     12 
     13 using namespace skpeg;
     14 
     15 namespace {
     16 
     17 struct Alpha {
     18     using V = char;
     19     using MatchT = MatchResult<V>;
     20 
     21     static MatchT Match(const char* in) {
     22         static constexpr unsigned kAlphaRange = 'z' - 'a';
     23         return static_cast<unsigned>(*in - 'a') <= kAlphaRange
     24             || static_cast<unsigned>(*in - 'A') <= kAlphaRange
     25             ? MatchT(in + 1, *in)
     26             : nullptr;
     27     }
     28 };
     29 
     30 struct Digit {
     31     using V = uint8_t;
     32     using MatchT = MatchResult<V>;
     33 
     34     static MatchT Match(const char* in) {
     35         static constexpr unsigned kDigitRange = '9' - '0';
     36         return static_cast<unsigned>(*in - '0') <= kDigitRange
     37             ? MatchT(in + 1, SkTo<uint8_t>(*in - '0'))
     38             : nullptr;
     39     }
     40 };
     41 
     42 void test_EOS(skiatest::Reporter* r) {
     43     static const struct {
     44         const char* fInput;
     45         bool        fMatch;
     46     } gTests[] = {
     47         { ""   , true  },
     48         { " "  , false },
     49         { "\0" , true  },
     50         { "foo", false },
     51     };
     52 
     53     for (size_t i = 0; i < SK_ARRAY_COUNT(gTests); ++i) {
     54         const auto match = EOS::Match(gTests[i].fInput);
     55         REPORTER_ASSERT(r, match == gTests[i].fMatch);
     56         REPORTER_ASSERT(r, match.fNext == (match ? gTests[i].fInput : nullptr));
     57     }
     58 }
     59 
     60 void test_LIT(skiatest::Reporter* r) {
     61     static const struct {
     62         const char* fInput;
     63         bool        fMatch;
     64     } gTests[] = {
     65         { ""  , false },
     66         { " " , false },
     67         { "x" , false },
     68         { "X" , true  },
     69         { "xX", false },
     70         { "Xx", true  },
     71     };
     72 
     73     for (size_t i = 0; i < SK_ARRAY_COUNT(gTests); ++i) {
     74         const auto match = LIT<'X'>::Match(gTests[i].fInput);
     75         REPORTER_ASSERT(r, match == gTests[i].fMatch);
     76         REPORTER_ASSERT(r, match.fNext == (match ? gTests[i].fInput + 1 : nullptr));
     77     }
     78 
     79     REPORTER_ASSERT(r, !(LIT<'F', 'o', 'o'>::Match("")));
     80     REPORTER_ASSERT(r, !(LIT<'F', 'o', 'o'>::Match("Fo")));
     81     REPORTER_ASSERT(r, !(LIT<'F', 'o', 'o'>::Match("FoO")));
     82     REPORTER_ASSERT(r,  (LIT<'F', 'o', 'o'>::Match("Foo")));
     83     REPORTER_ASSERT(r,  (LIT<'F', 'o', 'o'>::Match("Foobar")));
     84 }
     85 
     86 void test_Alpha(skiatest::Reporter* r) {
     87     static const struct {
     88         const char* fInput;
     89         bool        fMatch;
     90         char        fMatchValue;
     91     } gTests[] = {
     92         { ""  , false,  0  },
     93         { "\r", false,  0  },
     94         { "\n", false,  0  },
     95         { "\t", false,  0  },
     96         { "0" , false,  0  },
     97         { "9" , false,  0  },
     98         { "a" , true , 'a' },
     99         { "a" , true , 'a' },
    100         { "z" , true , 'z' },
    101         { "A" , true , 'A' },
    102         { "Z" , true , 'Z' },
    103         { "az", true , 'a' },
    104         { "a0", true , 'a' },
    105         { "0a", false,  0  },
    106     };
    107 
    108     for (size_t i = 0; i < SK_ARRAY_COUNT(gTests); ++i) {
    109         const auto match = Alpha::Match(gTests[i].fInput);
    110         REPORTER_ASSERT(r, match == gTests[i].fMatch);
    111         REPORTER_ASSERT(r, match.fNext == (match ? gTests[i].fInput + 1 : nullptr));
    112         if (match) {
    113             REPORTER_ASSERT(r, *match == gTests[i].fMatchValue);
    114         }
    115     }
    116 }
    117 
    118 void test_Digit(skiatest::Reporter* r) {
    119     static const struct {
    120         const char* fInput;
    121         bool        fMatch;
    122         uint8_t     fMatchValue;
    123     } gTests[] = {
    124         { ""   , false, 0 },
    125         { "/"  , false, 0 },
    126         { ":"  , false, 0 },
    127         { "x"  , false, 0 },
    128         { "x0" , false, 0 },
    129         { "0"  , true , 0 },
    130         { "1x" , true , 1 },
    131         { "9 a", true , 9 },
    132     };
    133 
    134     for (size_t i = 0; i < SK_ARRAY_COUNT(gTests); ++i) {
    135         const auto match = Digit::Match(gTests[i].fInput);
    136         REPORTER_ASSERT(r, match == gTests[i].fMatch);
    137         REPORTER_ASSERT(r, match.fNext == (match ? gTests[i].fInput + 1 : nullptr));
    138         if (match) {
    139             REPORTER_ASSERT(r, *match == gTests[i].fMatchValue);
    140         }
    141     }
    142 }
    143 
    144 void test_Opt(skiatest::Reporter* r) {
    145     static const struct {
    146         const char* fInput;
    147         bool        fMatch;
    148     } gTests[] = {
    149         { ""       , false },
    150         { "fo"     , false },
    151         { " foo"   , false },
    152         { "foo"    , true },
    153         { "foobar" , true },
    154     };
    155 
    156     for (size_t i = 0; i < SK_ARRAY_COUNT(gTests); ++i) {
    157         const auto m = Opt<LIT<'f', 'o', 'o'>>::Match(gTests[i].fInput);
    158         REPORTER_ASSERT(r, m);
    159         REPORTER_ASSERT(r, m->fValue.isValid() == gTests[i].fMatch);
    160     }
    161 }
    162 
    163 void test_Seq(skiatest::Reporter* r) {
    164     REPORTER_ASSERT(r,  (Seq<LIT<'X'>, EOS>::Match("X")));
    165     REPORTER_ASSERT(r, !(Seq<LIT<'X'>, EOS>::Match("x")));
    166     REPORTER_ASSERT(r, !(Seq<LIT<'X'>, EOS>::Match("xX")));
    167     REPORTER_ASSERT(r, !(Seq<LIT<'X'>, EOS>::Match("XX")));
    168     REPORTER_ASSERT(r,  (Seq<LIT<'X'>, Seq<LIT<'X'>, EOS>>::Match("XX")));
    169     REPORTER_ASSERT(r,  (Seq<LIT<'X'>, Seq<LIT<'X'>, EOS>>::Match("XX")));
    170 
    171     REPORTER_ASSERT(r, !(Seq<LIT<'F', 'o', 'o'>, EOS>::Match("FooBar")));
    172     REPORTER_ASSERT(r,  (Seq<LIT<'F', 'o', 'o'>, EOS>::Match("Foo")));
    173 
    174     {
    175         const auto m = Seq<LIT<'x'>, Digit>::Match("x5");
    176         REPORTER_ASSERT(r, m);
    177         REPORTER_ASSERT(r, m->get<1>() == 5);
    178     }
    179     {
    180         const auto m = Seq<Digit, Digit>::Match("42");
    181         REPORTER_ASSERT(r, m);
    182         REPORTER_ASSERT(r, m->get<0>() == 4);
    183         REPORTER_ASSERT(r, m->get<1>() == 2);
    184     }
    185 }
    186 
    187 void test_Choice(skiatest::Reporter* r) {
    188     REPORTER_ASSERT(r, !(Choice<Digit,Alpha>::Match("")));
    189     REPORTER_ASSERT(r, !(Choice<Digit,Alpha>::Match("\t")));
    190     REPORTER_ASSERT(r, !(Choice<Digit,Alpha>::Match(" ")));
    191     REPORTER_ASSERT(r,  (Choice<Digit,Alpha>::Match("a")));
    192     REPORTER_ASSERT(r,  (Choice<Digit,Alpha>::Match("3")));
    193     REPORTER_ASSERT(r,  (Choice<Digit,Alpha>::Match("a ")));
    194     REPORTER_ASSERT(r,  (Choice<Digit,Alpha>::Match("3 ")));
    195     REPORTER_ASSERT(r, !(Choice<Digit,Alpha>::Match(" a ")));
    196     REPORTER_ASSERT(r, !(Choice<Digit,Alpha>::Match(" 3 ")));
    197 
    198     {
    199         const auto m = Choice<Alpha, Digit>::Match("x");
    200         REPORTER_ASSERT(r,  m);
    201         REPORTER_ASSERT(r,  m->v1.isValid());
    202         REPORTER_ASSERT(r, !m->v2.isValid());
    203         REPORTER_ASSERT(r, *m->v1.get() == 'x');
    204     }
    205 
    206     {
    207         const auto m = Choice<Alpha, Digit>::Match("7");
    208         REPORTER_ASSERT(r,  m);
    209         REPORTER_ASSERT(r, !m->v1.isValid());
    210         REPORTER_ASSERT(r,  m->v2.isValid());
    211         REPORTER_ASSERT(r, *m->v2.get() == 7);
    212     }
    213 }
    214 
    215 void test_AnySome(skiatest::Reporter* r) {
    216     static const struct {
    217         const char* fInput;
    218         int         fCount;
    219     } gTests[] = {
    220         { ""      , 0 },
    221         { "fo"    , 0 },
    222         { "Foo"   , 0 },
    223         { "foo"   , 1 },
    224         { "foofoo", 2 },
    225     };
    226 
    227     for (size_t i = 0; i < SK_ARRAY_COUNT(gTests); ++i) {
    228         const auto matchAny = Any<LIT<'f', 'o', 'o'>>::Match(gTests[i].fInput);
    229         REPORTER_ASSERT(r, matchAny);
    230         REPORTER_ASSERT(r, matchAny->fValues.count() == gTests[i].fCount);
    231 
    232         const auto matchSome = Some<LIT<'f', 'o', 'o'>>::Match(gTests[i].fInput);
    233         REPORTER_ASSERT(r,  matchSome == (gTests[i].fCount > 0));
    234         REPORTER_ASSERT(r, !matchSome ||
    235                             matchSome->get<1>().fValues.count() == gTests[i].fCount - 1);
    236     }
    237 
    238     {
    239         const auto m = Any<Digit>::Match("0123456789foo");
    240         REPORTER_ASSERT(r, m);
    241         REPORTER_ASSERT(r, m->fValues.count() == 10);
    242         for (int i = 0; i < m->fValues.count(); ++i) {
    243             REPORTER_ASSERT(r, m->fValues[i] == i);
    244         }
    245     }
    246 }
    247 
    248 void test_Complex(skiatest::Reporter* r) {
    249     // [0-9]+(,[0-9]+)?$
    250     using P0 =
    251         Seq<
    252           Some<Digit>,
    253           Opt<Seq<
    254             LIT<','>,
    255             Some<Digit>>>,
    256           EOS>;
    257 
    258     REPORTER_ASSERT(r, !P0::Match(""));
    259     REPORTER_ASSERT(r, !P0::Match(","));
    260     REPORTER_ASSERT(r, !P0::Match("1,"));
    261     REPORTER_ASSERT(r, !P0::Match(",1"));
    262     REPORTER_ASSERT(r,  P0::Match("1"));
    263     REPORTER_ASSERT(r,  P0::Match("1,2"));
    264     REPORTER_ASSERT(r, !P0::Match("1,2 "));
    265     REPORTER_ASSERT(r,  P0::Match("123,456"));
    266 
    267     // [ ]*[Ff]oo([Bb]ar)+[Bb]az[ ]*$
    268     using P1 =
    269         Seq<
    270           Any<LIT<' '>>,
    271           Choice<LIT<'F'>, LIT<'f'>>,
    272           LIT<'o', 'o'>,
    273           Some<Seq<
    274             Choice<LIT<'B'>, LIT<'b'>>,
    275             LIT<'a', 'r'>>>,
    276           Choice<LIT<'B'>, LIT<'b'>>,
    277           LIT<'a', 'z'>,
    278           Any<LIT<' '>>,
    279           EOS>;
    280 
    281     REPORTER_ASSERT(r, !P1::Match(""));
    282     REPORTER_ASSERT(r, !P1::Match("FooBar"));
    283     REPORTER_ASSERT(r, !P1::Match("FooBaz"));
    284     REPORTER_ASSERT(r,  P1::Match("FooBarBaz"));
    285     REPORTER_ASSERT(r,  P1::Match("foobarbaz"));
    286     REPORTER_ASSERT(r,  P1::Match("  FooBarbaz     "));
    287     REPORTER_ASSERT(r,  P1::Match(" FooBarbarbarBaz "));
    288 }
    289 
    290 } // anonymous ns
    291 
    292 DEF_TEST(SkPEG, r) {
    293     test_EOS(r);
    294     test_LIT(r);
    295     test_Alpha(r);
    296     test_Digit(r);
    297     test_Opt(r);
    298     test_Seq(r);
    299     test_Choice(r);
    300     test_AnySome(r);
    301     test_Complex(r);
    302 }
    303 
    304 #endif // SK_XML
    305