OLD | NEW |
| (Empty) |
1 // Copyright 2006 The RE2 Authors. All Rights Reserved. | |
2 // Use of this source code is governed by a BSD-style | |
3 // license that can be found in the LICENSE file. | |
4 | |
5 // Test character class manipulations. | |
6 | |
7 #include "util/test.h" | |
8 #include "re2/regexp.h" | |
9 | |
10 namespace re2 { | |
11 | |
12 struct CCTest { | |
13 struct { | |
14 Rune lo; | |
15 Rune hi; | |
16 } add[10]; | |
17 int remove; | |
18 struct { | |
19 Rune lo; | |
20 Rune hi; | |
21 } final[10]; | |
22 }; | |
23 | |
24 static CCTest tests[] = { | |
25 { { { 10, 20 }, {-1} }, -1, | |
26 { { 10, 20 }, {-1} } }, | |
27 | |
28 { { { 10, 20 }, { 20, 30 }, {-1} }, -1, | |
29 { { 10, 30 }, {-1} } }, | |
30 | |
31 { { { 10, 20 }, { 30, 40 }, { 20, 30 }, {-1} }, -1, | |
32 { { 10, 40 }, {-1} } }, | |
33 | |
34 { { { 0, 50 }, { 20, 30 }, {-1} }, -1, | |
35 { { 0, 50 }, {-1} } }, | |
36 | |
37 { { { 10, 11 }, { 13, 14 }, { 16, 17 }, { 19, 20 }, { 22, 23 }, {-1} }, -1, | |
38 { { 10, 11 }, { 13, 14 }, { 16, 17 }, { 19, 20 }, { 22, 23 }, {-1} } }, | |
39 | |
40 { { { 13, 14 }, { 10, 11 }, { 22, 23 }, { 19, 20 }, { 16, 17 }, {-1} }, -1, | |
41 { { 10, 11 }, { 13, 14 }, { 16, 17 }, { 19, 20 }, { 22, 23 }, {-1} } }, | |
42 | |
43 { { { 13, 14 }, { 10, 11 }, { 22, 23 }, { 19, 20 }, { 16, 17 }, {-1} }, -1, | |
44 { { 10, 11 }, { 13, 14 }, { 16, 17 }, { 19, 20 }, { 22, 23 }, {-1} } }, | |
45 | |
46 { { { 13, 14 }, { 10, 11 }, { 22, 23 }, { 19, 20 }, { 16, 17 }, { 5, 25 }, {-1
} }, -1, | |
47 { { 5, 25 }, {-1} } }, | |
48 | |
49 { { { 13, 14 }, { 10, 11 }, { 22, 23 }, { 19, 20 }, { 16, 17 }, { 12, 21 }, {-
1} }, -1, | |
50 { { 10, 23 }, {-1} } }, | |
51 | |
52 // These check boundary cases during negation. | |
53 { { { 0, Runemax }, {-1} }, -1, | |
54 { { 0, Runemax }, {-1} } }, | |
55 | |
56 { { { 0, 50 }, {-1} }, -1, | |
57 { { 0, 50 }, {-1} } }, | |
58 | |
59 { { { 50, Runemax }, {-1} }, -1, | |
60 { { 50, Runemax }, {-1} } }, | |
61 | |
62 // Check RemoveAbove. | |
63 { { { 50, Runemax }, {-1} }, 255, | |
64 { { 50, 255 }, {-1} } }, | |
65 | |
66 { { { 50, Runemax }, {-1} }, 65535, | |
67 { { 50, 65535 }, {-1} } }, | |
68 | |
69 { { { 50, Runemax }, {-1} }, Runemax, | |
70 { { 50, Runemax }, {-1} } }, | |
71 | |
72 { { { 50, 60 }, { 250, 260 }, { 350, 360 }, {-1} }, 255, | |
73 { { 50, 60 }, { 250, 255 }, {-1} } }, | |
74 | |
75 { { { 50, 60 }, {-1} }, 255, | |
76 { { 50, 60 }, {-1} } }, | |
77 | |
78 { { { 350, 360 }, {-1} }, 255, | |
79 { {-1} } }, | |
80 | |
81 { { {-1} }, 255, | |
82 { {-1} } }, | |
83 }; | |
84 | |
85 template<class CharClass> | |
86 static void Broke(const char *desc, const CCTest* t, CharClass* cc) { | |
87 if (t == NULL) { | |
88 printf("\t%s:", desc); | |
89 } else { | |
90 printf("\n"); | |
91 printf("CharClass added: [%s]", desc); | |
92 for (int k = 0; t->add[k].lo >= 0; k++) | |
93 printf(" %d-%d", t->add[k].lo, t->add[k].hi); | |
94 printf("\n"); | |
95 if (t->remove >= 0) | |
96 printf("Removed > %d\n", t->remove); | |
97 printf("\twant:"); | |
98 for (int k = 0; t->final[k].lo >= 0; k++) | |
99 printf(" %d-%d", t->final[k].lo, t->final[k].hi); | |
100 printf("\n"); | |
101 printf("\thave:"); | |
102 } | |
103 | |
104 for (typename CharClass::iterator it = cc->begin(); it != cc->end(); ++it) | |
105 printf(" %d-%d", it->lo, it->hi); | |
106 printf("\n"); | |
107 } | |
108 | |
109 bool ShouldContain(CCTest *t, int x) { | |
110 for (int j = 0; t->final[j].lo >= 0; j++) | |
111 if (t->final[j].lo <= x && x <= t->final[j].hi) | |
112 return true; | |
113 return false; | |
114 } | |
115 | |
116 // Helpers to make templated CorrectCC work with both CharClass and CharClassBui
lder. | |
117 | |
118 CharClass* Negate(CharClass *cc) { | |
119 return cc->Negate(); | |
120 } | |
121 | |
122 void Delete(CharClass* cc) { | |
123 cc->Delete(); | |
124 } | |
125 | |
126 CharClassBuilder* Negate(CharClassBuilder* cc) { | |
127 CharClassBuilder* ncc = cc->Copy(); | |
128 ncc->Negate(); | |
129 return ncc; | |
130 } | |
131 | |
132 void Delete(CharClassBuilder* cc) { | |
133 delete cc; | |
134 } | |
135 | |
136 template<class CharClass> | |
137 bool CorrectCC(CharClass *cc, CCTest *t, const char *desc) { | |
138 typename CharClass::iterator it = cc->begin(); | |
139 int size = 0; | |
140 for (int j = 0; t->final[j].lo >= 0; j++, ++it) { | |
141 if (it == cc->end() || | |
142 it->lo != t->final[j].lo || | |
143 it->hi != t->final[j].hi) { | |
144 Broke(desc, t, cc); | |
145 return false; | |
146 } | |
147 size += it->hi - it->lo + 1; | |
148 } | |
149 if (it != cc->end()) { | |
150 Broke(desc, t, cc); | |
151 return false; | |
152 } | |
153 if (cc->size() != size) { | |
154 Broke(desc, t, cc); | |
155 printf("wrong size: want %d have %d\n", size, cc->size()); | |
156 return false; | |
157 } | |
158 | |
159 for (int j = 0; j < 101; j++) { | |
160 if (j == 100) | |
161 j = Runemax; | |
162 if (ShouldContain(t, j) != cc->Contains(j)) { | |
163 Broke(desc, t, cc); | |
164 printf("want contains(%d)=%d, got %d\n", | |
165 j, ShouldContain(t, j), cc->Contains(j)); | |
166 return false; | |
167 } | |
168 } | |
169 | |
170 CharClass* ncc = Negate(cc); | |
171 for (int j = 0; j < 101; j++) { | |
172 if (j == 100) | |
173 j = Runemax; | |
174 if (ShouldContain(t, j) == ncc->Contains(j)) { | |
175 Broke(desc, t, cc); | |
176 Broke("ncc", NULL, ncc); | |
177 printf("want ncc contains(%d)!=%d, got %d\n", | |
178 j, ShouldContain(t, j), ncc->Contains(j)); | |
179 Delete(ncc); | |
180 return false; | |
181 } | |
182 if (ncc->size() != Runemax+1 - cc->size()) { | |
183 Broke(desc, t, cc); | |
184 Broke("ncc", NULL, ncc); | |
185 printf("ncc size should be %d is %d\n", | |
186 Runemax+1 - cc->size(), ncc->size()); | |
187 Delete(ncc); | |
188 return false; | |
189 } | |
190 } | |
191 Delete(ncc); | |
192 return true; | |
193 } | |
194 | |
195 TEST(TestCharClassBuilder, Adds) { | |
196 int nfail = 0; | |
197 for (int i = 0; i < arraysize(tests); i++) { | |
198 CharClassBuilder ccb; | |
199 CCTest* t = &tests[i]; | |
200 for (int j = 0; t->add[j].lo >= 0; j++) | |
201 ccb.AddRange(t->add[j].lo, t->add[j].hi); | |
202 if (t->remove >= 0) | |
203 ccb.RemoveAbove(t->remove); | |
204 if (!CorrectCC(&ccb, t, "before copy (CharClassBuilder)")) | |
205 nfail++; | |
206 CharClass* cc = ccb.GetCharClass(); | |
207 if (!CorrectCC(cc, t, "before copy (CharClass)")) | |
208 nfail++; | |
209 cc->Delete(); | |
210 | |
211 CharClassBuilder *ccb1 = ccb.Copy(); | |
212 if (!CorrectCC(ccb1, t, "after copy (CharClassBuilder)")) | |
213 nfail++; | |
214 cc = ccb.GetCharClass(); | |
215 if (!CorrectCC(cc, t, "after copy (CharClass)")) | |
216 nfail++; | |
217 cc->Delete(); | |
218 delete ccb1; | |
219 } | |
220 EXPECT_EQ(nfail, 0); | |
221 } | |
222 | |
223 } // namespace re2 | |
OLD | NEW |