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