1 /* Copyright (c) 2008-2010, Google Inc.
2 * All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Neither the name of Google Inc. nor the names of its
11 * contributors may be used to endorse or promote products derived from
12 * this software without specific prior written permission.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 // This file is part of ThreadSanitizer, a dynamic data race detector.
28 // Author: Evgeniy Stepanov.
29
30 // This file contains tests for suppressions implementation.
31
32 #include <gtest/gtest.h>
33
34 #include "suppressions.h"
35
36 #define VEC(arr) *(new vector<string>(arr, arr + sizeof(arr) / sizeof(*arr)))
37
38 class BaseSuppressionsTest : public ::testing::Test {
39 protected:
IsSuppressed(string tool,string warning_type,const vector<string> & f_m,const vector<string> & f_d,const vector<string> & o)40 bool IsSuppressed(string tool, string warning_type, const vector<string>& f_m,
41 const vector<string>& f_d, const vector<string>& o) {
42 string result;
43 return supp_.StackTraceSuppressed(
44 tool, warning_type, f_m, f_d, o, &result);
45 }
46
IsSuppressed(const vector<string> & f_m,const vector<string> & f_d,const vector<string> & o)47 bool IsSuppressed(const vector<string>& f_m, const vector<string>& f_d,
48 const vector<string>& o) {
49 return IsSuppressed("test_tool", "test_warning_type", f_m, f_d, o);
50 }
51
52 Suppressions supp_;
53 };
54
55 class SuppressionsTest : public BaseSuppressionsTest {
56 protected:
SetUp()57 virtual void SetUp() {
58 const string data =
59 "{\n"
60 " name\n"
61 " test_tool,tool2:test_warning_type\n"
62 " fun:function1\n"
63 " obj:object1\n"
64 " fun:function2\n"
65 "}";
66 supp_.ReadFromString(data);
67 }
68 };
69
70
TEST_F(SuppressionsTest,Simple)71 TEST_F(SuppressionsTest, Simple) {
72 string m[] = {"aa", "bb", "cc"};
73 string d[] = {"aaa", "bbb", "ccc"};
74 string o[] = {"object1", "object2", "object3"};
75 ASSERT_FALSE(IsSuppressed(VEC(m), VEC(d), VEC(o)));
76 }
77
TEST_F(SuppressionsTest,Simple2)78 TEST_F(SuppressionsTest, Simple2) {
79 string m[] = {"function1", "bb", "function2"};
80 string d[] = {"aaa", "bbb", "ccc"};
81 string o[] = {"object2", "object1", "object3"};
82 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o)));
83 }
84
85 // A long stack trace is ok.
TEST_F(SuppressionsTest,LongTrace)86 TEST_F(SuppressionsTest, LongTrace) {
87 string m[] = {"function1", "bb", "function2", "zz"};
88 string d[] = {"aaa", "bbb", "ccc", "zzz"};
89 string o[] = {"object2", "object1", "object3", "o4"};
90 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o)));
91 }
92
93 // A stack trace template only matches at the top of the stack.
TEST_F(SuppressionsTest,OnlyMatchesAtTheTop)94 TEST_F(SuppressionsTest, OnlyMatchesAtTheTop) {
95 string m[] = {"zz", "function1", "bb", "function2"};
96 string d[] = {"zzz", "aaa", "bbb", "ccc"};
97 string o[] = {"o0", "object2", "object1", "object3"};
98 ASSERT_FALSE(IsSuppressed(VEC(m), VEC(d), VEC(o)));
99 }
100
101 // A short stack trace is not.
TEST_F(SuppressionsTest,ShortTrace)102 TEST_F(SuppressionsTest, ShortTrace) {
103 string m[] = {"function1", "bb"};
104 string d[] = {"aaa", "bbb"};
105 string o[] = {"object2", "object1"};
106 ASSERT_FALSE(IsSuppressed(VEC(m), VEC(d), VEC(o)));
107 }
108
109 class SuppressionsWithWildcardsTest : public BaseSuppressionsTest {
110 protected:
SetUp()111 virtual void SetUp() {
112 const string data =
113 "{\n"
114 " name\n"
115 " test_tool,tool2:test_warning_type\n"
116 " fun:fun*1\n"
117 " obj:obj*t1\n"
118 " ...\n"
119 " fun:f?n*2\n"
120 "}";
121 supp_.ReadFromString(data);
122 }
123 };
124
TEST_F(SuppressionsWithWildcardsTest,Wildcards1)125 TEST_F(SuppressionsWithWildcardsTest, Wildcards1) {
126 string m[] = {"function1", "bb", "function2"};
127 string d[] = {"aaa", "bbb", "ccc"};
128 string o[] = {"object2", "object1", "object3"};
129 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o)));
130 }
131
TEST_F(SuppressionsWithWildcardsTest,Wildcards2)132 TEST_F(SuppressionsWithWildcardsTest, Wildcards2) {
133 string m[] = {"some_other_function1", "bb", "function2"};
134 string d[] = {"aaa", "bbb", "ccc"};
135 string o[] = {"object2", "object1", "object3"};
136 ASSERT_FALSE(IsSuppressed(VEC(m), VEC(d), VEC(o)));
137 }
138
TEST_F(SuppressionsWithWildcardsTest,Wildcards3)139 TEST_F(SuppressionsWithWildcardsTest, Wildcards3) {
140 string m[] = {"fun1", "bb", "fanction2"};
141 string d[] = {"aaa", "bbb", "ccc"};
142 string o[] = {"object2", "objt1", "object3"};
143 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o)));
144 }
145
146 // Tests "..." wildcard.
TEST_F(SuppressionsWithWildcardsTest,VerticalWildcards1)147 TEST_F(SuppressionsWithWildcardsTest, VerticalWildcards1) {
148 string m[] = {"fun1", "bb", "qq", "fanction2"};
149 string d[] = {"aaa", "bbb", "ddd", "ccc"};
150 string o[] = {"object2", "objt1", "object3", "object4"};
151 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o)));
152 }
153
154
155 class MultipleStackTraceTest : public BaseSuppressionsTest {
156 protected:
SetUp()157 virtual void SetUp() {
158 const string data =
159 "{\n"
160 " name\n"
161 " test_tool,tool2:test_warning_type\n"
162 " {\n"
163 " fun:fun*1\n"
164 " }\n"
165 " {\n"
166 " fun:fun*2\n"
167 " fun:fun*3\n"
168 " }\n"
169 " {\n"
170 " ...\n"
171 " fun:fun*4\n"
172 " obj:obj*5\n"
173 " }\n"
174 "}";
175 supp_.ReadFromString(data);
176 }
177 };
178
TEST_F(MultipleStackTraceTest,Simple1)179 TEST_F(MultipleStackTraceTest, Simple1) {
180 string m[] = {"fun1", "bb", "qq", "fun2"};
181 string d[] = {"aaa", "bbb", "ddd", "ccc"};
182 string o[] = {"object1", "object2", "object3", "object4"};
183 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o)));
184 }
185
TEST_F(MultipleStackTraceTest,SecondTemplateMatches)186 TEST_F(MultipleStackTraceTest, SecondTemplateMatches) {
187 string m[] = {"fun2", "fun3", "qq", "fun2"};
188 string d[] = {"aaa", "bbb", "ddd", "ccc"};
189 string o[] = {"object1", "object2", "object3", "object4"};
190 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o)));
191 }
192
TEST_F(MultipleStackTraceTest,ThirdTemplateMatches)193 TEST_F(MultipleStackTraceTest, ThirdTemplateMatches) {
194 string m[] = {"fun4", "bb", "qq", "fun2"};
195 string d[] = {"aaa", "bbb", "ddd", "ccc"};
196 string o[] = {"object1", "object5", "object3", "object4"};
197 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o)));
198 }
199
TEST_F(MultipleStackTraceTest,NothingMatches)200 TEST_F(MultipleStackTraceTest, NothingMatches) {
201 string m[] = {"_fun1", "bb", "qq", "fun2"};
202 string d[] = {"aaa", "bbb", "ddd", "ccc"};
203 string o[] = {"object1", "object2", "object3", "object4"};
204 ASSERT_FALSE(IsSuppressed(VEC(m), VEC(d), VEC(o)));
205 }
206
TEST_F(MultipleStackTraceTest,TwoTemplatesMatch)207 TEST_F(MultipleStackTraceTest, TwoTemplatesMatch) {
208 string m[] = {"fun1", "bb", "fun4", "fun2"};
209 string d[] = {"aaa", "bbb", "ddd", "ccc"};
210 string o[] = {"object1", "object2", "object3", "object5"};
211 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o)));
212 }
213
214
TEST_F(BaseSuppressionsTest,StartsWithVerticalWildcard)215 TEST_F(BaseSuppressionsTest, StartsWithVerticalWildcard) {
216 const string data =
217 "{\n"
218 " name\n"
219 " test_tool:test_warning_type\n"
220 " ...\n"
221 " fun:qq\n"
222 "}";
223 ASSERT_GT(supp_.ReadFromString(data), 0);
224 string m[] = {"fun1", "bb", "qq", "function2"};
225 string d[] = {"aaa", "bbb", "ddd", "ccc"};
226 string o[] = {"object2", "objt1", "object3", "object4"};
227 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o)));
228 }
229
TEST_F(BaseSuppressionsTest,StartsWithVerticalWildcard2)230 TEST_F(BaseSuppressionsTest, StartsWithVerticalWildcard2) {
231 const string data =
232 "{\n"
233 " name\n"
234 " test_tool:test_warning_type\n"
235 " ...\n"
236 " fun:fun1\n"
237 "}";
238 ASSERT_GT(supp_.ReadFromString(data), 0);
239 string m[] = {"fun1", "bb", "qq", "function2"};
240 string d[] = {"aaa", "bbb", "ddd", "ccc"};
241 string o[] = {"object2", "objt1", "object3", "object4"};
242 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o)));
243 }
244
TEST_F(BaseSuppressionsTest,EndsWithVerticalWildcard)245 TEST_F(BaseSuppressionsTest, EndsWithVerticalWildcard) {
246 const string data =
247 "{\n"
248 " name\n"
249 " test_tool:test_warning_type\n"
250 " fun:fun1\n"
251 " ...\n"
252 "}";
253 ASSERT_GT(supp_.ReadFromString(data), 0);
254 string m[] = {"fun1", "bb", "qq", "function2"};
255 string d[] = {"aaa", "bbb", "ddd", "ccc"};
256 string o[] = {"object2", "objt1", "object3", "object4"};
257 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o)));
258 }
259
TEST_F(BaseSuppressionsTest,EndsWithVerticalWildcard2)260 TEST_F(BaseSuppressionsTest, EndsWithVerticalWildcard2) {
261 const string data =
262 "{\n"
263 " name\n"
264 " test_tool:test_warning_type\n"
265 " fun:qq\n"
266 " ...\n"
267 "}";
268 ASSERT_GT(supp_.ReadFromString(data), 0);
269 string m[] = {"fun1", "bb", "qq", "function2"};
270 string d[] = {"aaa", "bbb", "ddd", "ccc"};
271 string o[] = {"object2", "objt1", "object3", "object4"};
272 ASSERT_FALSE(IsSuppressed(VEC(m), VEC(d), VEC(o)));
273 }
274
TEST_F(BaseSuppressionsTest,Complex)275 TEST_F(BaseSuppressionsTest, Complex) {
276 const string data =
277 "{\n"
278 " name\n"
279 " test_tool:test_warning_type\n"
280 " fun:qq\n"
281 " ...\n"
282 " obj:obj*3\n"
283 " ...\n"
284 " fun:function?\n"
285 "}";
286 ASSERT_GT(supp_.ReadFromString(data), 0);
287 string m[] = {"fun1", "bb", "qq", "function2"};
288 string d[] = {"aaa", "bbb", "ddd", "ccc"};
289 string o[] = {"object2", "objt1", "object3", "object4"};
290 ASSERT_FALSE(IsSuppressed(VEC(m), VEC(d), VEC(o)));
291 }
292
TEST_F(BaseSuppressionsTest,DemangledNames)293 TEST_F(BaseSuppressionsTest, DemangledNames) {
294 const string data =
295 "{\n"
296 " name\n"
297 " test_tool:test_warning_type\n"
298 " fun:bb*w?\n"
299 "}";
300 ASSERT_GT(supp_.ReadFromString(data), 0);
301 string m[] = {"fun1", "bb", "qq", "function2"};
302 string d[] = {"bbbxxwz", "aaa", "ddd", "ccc"};
303 string o[] = {"object2", "objt1", "object3", "object4"};
304 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o)));
305 }
306
TEST_F(BaseSuppressionsTest,TrailingWhitespace)307 TEST_F(BaseSuppressionsTest, TrailingWhitespace) {
308 const string data =
309 "{\n"
310 " name\n"
311 " test_tool:test_warning_type\n"
312 " fun:bb*w? \n"
313 "}";
314 ASSERT_GT(supp_.ReadFromString(data), 0);
315 string m[] = {"fun1", "bb", "qq", "function2"};
316 string d[] = {"bbbxxwz", "aaa", "ddd", "ccc"};
317 string o[] = {"object2", "objt1", "object3", "object4"};
318 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o)));
319 }
320
TEST_F(BaseSuppressionsTest,ObjectiveC)321 TEST_F(BaseSuppressionsTest, ObjectiveC) {
322 const string data =
323 "{\n"
324 " name\n"
325 " test_tool:test_warning_type\n"
326 " fun:-[NSObject(NSKeyValueCoding) setValue:forKeyPath:]\n"
327 "}";
328 ASSERT_GT(supp_.ReadFromString(data), 0);
329 string m[] = {"-[NSObject(NSKeyValueCoding) setValue:forKeyPath:]", "function2"};
330 string d[] = {"bbbxxwz", "aaa", "ddd", "ccc"};
331 string o[] = {"object2", "objt1", "object3", "object4"};
332 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o)));
333 }
334
TEST_F(BaseSuppressionsTest,ComparisonAndShiftOperators)335 TEST_F(BaseSuppressionsTest, ComparisonAndShiftOperators) {
336 const string data =
337 "{\n"
338 " name\n"
339 " test_tool:test_warning_type\n"
340 " fun:operator<\n"
341 " fun:operator>\n"
342 " fun:operator<=\n"
343 " fun:operator>=\n"
344 " fun:operator<<\n"
345 " fun:operator>>\n"
346 " fun:operator<<=\n"
347 " fun:operator>>=\n"
348 " fun:operator->\n"
349 " fun:operator->*\n"
350 "}";
351 ASSERT_GT(supp_.ReadFromString(data), 0);
352 string m[] = {"operator<", "operator>", "operator<=", "operator>=",
353 "operator<<", "operator>>", "operator<<=", "operator>>=",
354 "operator->", "operator->*"};
355 string d[] = {"bbbxxwz", "aaa", "ddd", "ccc"};
356 string o[] = {"object2", "objt1", "object3", "object4"};
357 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o)));
358 }
359
360
361 class FailingSuppressionsTest : public ::testing::Test {
362 protected:
ErrorLineNo(string data)363 int ErrorLineNo(string data) {
364 int result = supp_.ReadFromString(data);
365 if (result >= 0)
366 return -1;
367 else
368 return supp_.GetErrorLineNo();
369 }
370
371 Suppressions supp_;
372 };
373
TEST_F(FailingSuppressionsTest,NoOpeningBrace)374 TEST_F(FailingSuppressionsTest, NoOpeningBrace) {
375 const string data =
376 " name\n"
377 " test_tool:test_warning_type\n"
378 " fun:bb*w? \n"
379 "}";
380 ASSERT_EQ(1, ErrorLineNo(data));
381 }
382
TEST_F(FailingSuppressionsTest,Bad1)383 TEST_F(FailingSuppressionsTest, Bad1) {
384 const string data =
385 "{\n"
386 " name\n"
387 " something_else\n"
388 " test_tool:test_warning_type\n"
389 " fun:bb*w? \n"
390 "}";
391 ASSERT_EQ(3, ErrorLineNo(data));
392 }
393
TEST_F(FailingSuppressionsTest,Bad2)394 TEST_F(FailingSuppressionsTest, Bad2) {
395 const string data =
396 "{\n"
397 " name\n"
398 " test_tool:test_warning_type\n"
399 " extra\n"
400 " fun:bb*w? \n"
401 "}";
402 ASSERT_EQ(4, ErrorLineNo(data));
403 }
404
TEST_F(FailingSuppressionsTest,Bad3)405 TEST_F(FailingSuppressionsTest, Bad3) {
406 const string data =
407 "{\n"
408 " name\n"
409 " test_tool:test_warning_type\n"
410 " fun:bb*w? \n"
411 " extra\n"
412 "}";
413 ASSERT_EQ(5, ErrorLineNo(data));
414 }
415
TEST_F(FailingSuppressionsTest,SomeWeirdTextAfterASuppression)416 TEST_F(FailingSuppressionsTest, SomeWeirdTextAfterASuppression) {
417 const string data =
418 "{\n"
419 " name\n"
420 " test_tool:test_warning_type\n"
421 " fun:bb*w? \n"
422 "}\n"
423 "some_weird_text\n"
424 "after_a_suppression\n";
425 ASSERT_EQ(6, ErrorLineNo(data));
426 }
427
TEST_F(FailingSuppressionsTest,NoToolsLineInMultitraceSuppression)428 TEST_F(FailingSuppressionsTest, NoToolsLineInMultitraceSuppression) {
429 const string data =
430 "{\n"
431 " name\n"
432 " {\n"
433 " fun:fun*2\n"
434 " fun:fun*3\n"
435 " }\n"
436 " {\n"
437 " ...\n"
438 " fun:fun*4\n"
439 " obj:obj*5\n"
440 " }\n"
441 "}";
442 ASSERT_EQ(3, ErrorLineNo(data));
443 }
444
TEST_F(FailingSuppressionsTest,BadStacktrace1)445 TEST_F(FailingSuppressionsTest, BadStacktrace1) {
446 const string data =
447 "{\n"
448 " name\n"
449 " test_tool:test_warning_type\n"
450 " {\n"
451 " fun:fun*2\n"
452 " fun:fun*3\n"
453 " }\n"
454 " {\n"
455 " zzz\n"
456 " fun:fun*4\n"
457 " obj:obj*5\n"
458 " }\n"
459 "}";
460 ASSERT_EQ(9, ErrorLineNo(data));
461 }
462
TEST_F(FailingSuppressionsTest,BadStacktrace2)463 TEST_F(FailingSuppressionsTest, BadStacktrace2) {
464 const string data =
465 "{\n"
466 " name\n"
467 " test_tool:test_warning_type\n"
468 " {\n"
469 " fun:fun*2\n"
470 " fun:fun*3\n"
471 " }\n"
472 " {\n"
473 " {\n"
474 " fun:fun*4\n"
475 " obj:obj*5\n"
476 " }\n"
477 "}";
478 ASSERT_EQ(9, ErrorLineNo(data));
479 }
480
TEST_F(FailingSuppressionsTest,BadStacktrace3)481 TEST_F(FailingSuppressionsTest, BadStacktrace3) {
482 const string data =
483 "{\n"
484 " name\n"
485 " test_tool:test_warning_type\n"
486 " {\n"
487 " fun:fun*2\n"
488 " fun:fun*3\n"
489 " }\n"
490 " {\n"
491 " fun:fun*4\n"
492 " obj:obj*5\n"
493 " }\n"
494 " zzz\n"
495 "}";
496 ASSERT_EQ(12, ErrorLineNo(data));
497 }
498
TEST_F(FailingSuppressionsTest,StacktraceWithParenthesis)499 TEST_F(FailingSuppressionsTest, StacktraceWithParenthesis) {
500 const string data =
501 "{\n"
502 " name\n"
503 " test_tool:test_warning_type\n"
504 " {\n"
505 " fun:fun*2\n"
506 " fun:fun*3\n"
507 " }\n"
508 " {\n"
509 " fun:fun*4()\n"
510 " obj:obj*5\n"
511 " }\n"
512 "}";
513 ASSERT_EQ(9, ErrorLineNo(data));
514 }
515
TEST_F(FailingSuppressionsTest,StacktraceWithAngleBraces)516 TEST_F(FailingSuppressionsTest, StacktraceWithAngleBraces) {
517 const string data =
518 "{\n"
519 " name\n"
520 " test_tool:test_warning_type\n"
521 " {\n"
522 " fun:fun*2\n"
523 " fun:fun*3\n"
524 " }\n"
525 " {\n"
526 " fun:fun<int>*4\n"
527 " obj:obj*5\n"
528 " }\n"
529 "}";
530 ASSERT_EQ(9, ErrorLineNo(data));
531 }
532
533
TEST(WildcardTest,Simple)534 TEST(WildcardTest, Simple) {
535 EXPECT_TRUE(StringMatch("abc", "abc"));
536 EXPECT_FALSE(StringMatch("abcd", "abc"));
537 EXPECT_FALSE(StringMatch("dabc", "abc"));
538 EXPECT_FALSE(StringMatch("ab", "abc"));
539 EXPECT_FALSE(StringMatch("", "abc"));
540 EXPECT_FALSE(StringMatch("abc", ""));
541 EXPECT_TRUE(StringMatch("", ""));
542 }
543
TEST(WildcardTest,SingleCharacterWildcard)544 TEST(WildcardTest, SingleCharacterWildcard) {
545 EXPECT_TRUE(StringMatch("a?c", "abc"));
546 EXPECT_TRUE(StringMatch("?bc", "abc"));
547 EXPECT_TRUE(StringMatch("ab?", "abc"));
548 EXPECT_TRUE(StringMatch("a??", "abc"));
549 EXPECT_TRUE(StringMatch("???", "abc"));
550 EXPECT_TRUE(StringMatch("?", "a"));
551 EXPECT_FALSE(StringMatch("?zc", "abc"));
552 EXPECT_FALSE(StringMatch("?bz", "abc"));
553 EXPECT_FALSE(StringMatch("b?c", "abc"));
554 EXPECT_FALSE(StringMatch("az?", "abc"));
555 EXPECT_FALSE(StringMatch("abc?", "abc"));
556 EXPECT_FALSE(StringMatch("?abc", "abc"));
557 EXPECT_FALSE(StringMatch("?", ""));
558 EXPECT_FALSE(StringMatch("??", ""));
559 }
560
TEST(WildcardTest,MultiCharacterWildcard)561 TEST(WildcardTest, MultiCharacterWildcard) {
562 EXPECT_TRUE(StringMatch("*x", "x"));
563 EXPECT_TRUE(StringMatch("x*", "x"));
564 EXPECT_TRUE(StringMatch("*x*", "x"));
565
566 EXPECT_TRUE(StringMatch("a*d", "abcd"));
567 EXPECT_TRUE(StringMatch("ab*d", "abcd"));
568 EXPECT_TRUE(StringMatch("*cd", "abcd"));
569 EXPECT_TRUE(StringMatch("*d", "abcd"));
570 EXPECT_TRUE(StringMatch("ab*", "abcd"));
571 EXPECT_TRUE(StringMatch("a*", "abcd"));
572 EXPECT_TRUE(StringMatch("*", "abcd"));
573 EXPECT_TRUE(StringMatch("ab*cd", "abcd"));
574
575 EXPECT_TRUE(StringMatch("ab**", "abcd"));
576 EXPECT_TRUE(StringMatch("**", "abcd"));
577 EXPECT_TRUE(StringMatch("***", "abcd"));
578 EXPECT_TRUE(StringMatch("**d", "abcd"));
579 EXPECT_TRUE(StringMatch("*c*", "abcd"));
580 EXPECT_TRUE(StringMatch("a*c*d*f", "abcdef"));
581 EXPECT_TRUE(StringMatch("a*c*e*", "abcdef"));
582 EXPECT_TRUE(StringMatch("*a*b*f", "abcdef"));
583 EXPECT_TRUE(StringMatch("*b*d*", "abcdef"));
584
585 EXPECT_FALSE(StringMatch("b*", "abcd"));
586 EXPECT_FALSE(StringMatch("*c", "abcd"));
587 EXPECT_FALSE(StringMatch("*a", "abcd"));
588 }
589
TEST(WildcardTest,WildcardCharactersInText)590 TEST(WildcardTest, WildcardCharactersInText) {
591 EXPECT_TRUE(StringMatch("?", "?"));
592 EXPECT_FALSE(StringMatch("a", "?"));
593 EXPECT_FALSE(StringMatch("ab", "a?"));
594 EXPECT_FALSE(StringMatch("ab", "?b"));
595 EXPECT_TRUE(StringMatch("a?", "a?"));
596 EXPECT_TRUE(StringMatch("?b", "?b"));
597
598 EXPECT_TRUE(StringMatch("*", "*"));
599 EXPECT_FALSE(StringMatch("a", "*"));
600 EXPECT_FALSE(StringMatch("ab", "a*"));
601 EXPECT_FALSE(StringMatch("ab", "*b"));
602 EXPECT_TRUE(StringMatch("a*", "a*"));
603 EXPECT_TRUE(StringMatch("*b", "*b"));
604 }
605
main(int argc,char ** argv)606 int main(int argc, char **argv) {
607 testing::InitGoogleTest(&argc, argv);
608
609 return RUN_ALL_TESTS();
610 }
611