| /* Copyright (c) 2008-2010, Google Inc. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Neither the name of Google Inc. nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| // This file is part of ThreadSanitizer, a dynamic data race detector. |
| // Author: Evgeniy Stepanov. |
| |
| // This file contains tests for suppressions implementation. |
| |
| #include <gtest/gtest.h> |
| |
| #include "suppressions.h" |
| |
| #define VEC(arr) *(new vector<string>(arr, arr + sizeof(arr) / sizeof(*arr))) |
| |
| class BaseSuppressionsTest : public ::testing::Test { |
| protected: |
| bool IsSuppressed(string tool, string warning_type, const vector<string>& f_m, |
| const vector<string>& f_d, const vector<string>& o) { |
| string result; |
| return supp_.StackTraceSuppressed( |
| tool, warning_type, f_m, f_d, o, &result); |
| } |
| |
| bool IsSuppressed(const vector<string>& f_m, const vector<string>& f_d, |
| const vector<string>& o) { |
| return IsSuppressed("test_tool", "test_warning_type", f_m, f_d, o); |
| } |
| |
| Suppressions supp_; |
| }; |
| |
| class SuppressionsTest : public BaseSuppressionsTest { |
| protected: |
| virtual void SetUp() { |
| const string data = |
| "{\n" |
| " name\n" |
| " test_tool,tool2:test_warning_type\n" |
| " fun:function1\n" |
| " obj:object1\n" |
| " fun:function2\n" |
| "}"; |
| supp_.ReadFromString(data); |
| } |
| }; |
| |
| |
| TEST_F(SuppressionsTest, Simple) { |
| string m[] = {"aa", "bb", "cc"}; |
| string d[] = {"aaa", "bbb", "ccc"}; |
| string o[] = {"object1", "object2", "object3"}; |
| ASSERT_FALSE(IsSuppressed(VEC(m), VEC(d), VEC(o))); |
| } |
| |
| TEST_F(SuppressionsTest, Simple2) { |
| string m[] = {"function1", "bb", "function2"}; |
| string d[] = {"aaa", "bbb", "ccc"}; |
| string o[] = {"object2", "object1", "object3"}; |
| ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); |
| } |
| |
| // A long stack trace is ok. |
| TEST_F(SuppressionsTest, LongTrace) { |
| string m[] = {"function1", "bb", "function2", "zz"}; |
| string d[] = {"aaa", "bbb", "ccc", "zzz"}; |
| string o[] = {"object2", "object1", "object3", "o4"}; |
| ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); |
| } |
| |
| // A stack trace template only matches at the top of the stack. |
| TEST_F(SuppressionsTest, OnlyMatchesAtTheTop) { |
| string m[] = {"zz", "function1", "bb", "function2"}; |
| string d[] = {"zzz", "aaa", "bbb", "ccc"}; |
| string o[] = {"o0", "object2", "object1", "object3"}; |
| ASSERT_FALSE(IsSuppressed(VEC(m), VEC(d), VEC(o))); |
| } |
| |
| // A short stack trace is not. |
| TEST_F(SuppressionsTest, ShortTrace) { |
| string m[] = {"function1", "bb"}; |
| string d[] = {"aaa", "bbb"}; |
| string o[] = {"object2", "object1"}; |
| ASSERT_FALSE(IsSuppressed(VEC(m), VEC(d), VEC(o))); |
| } |
| |
| class SuppressionsWithWildcardsTest : public BaseSuppressionsTest { |
| protected: |
| virtual void SetUp() { |
| const string data = |
| "{\n" |
| " name\n" |
| " test_tool,tool2:test_warning_type\n" |
| " fun:fun*1\n" |
| " obj:obj*t1\n" |
| " ...\n" |
| " fun:f?n*2\n" |
| "}"; |
| supp_.ReadFromString(data); |
| } |
| }; |
| |
| TEST_F(SuppressionsWithWildcardsTest, Wildcards1) { |
| string m[] = {"function1", "bb", "function2"}; |
| string d[] = {"aaa", "bbb", "ccc"}; |
| string o[] = {"object2", "object1", "object3"}; |
| ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); |
| } |
| |
| TEST_F(SuppressionsWithWildcardsTest, Wildcards2) { |
| string m[] = {"some_other_function1", "bb", "function2"}; |
| string d[] = {"aaa", "bbb", "ccc"}; |
| string o[] = {"object2", "object1", "object3"}; |
| ASSERT_FALSE(IsSuppressed(VEC(m), VEC(d), VEC(o))); |
| } |
| |
| TEST_F(SuppressionsWithWildcardsTest, Wildcards3) { |
| string m[] = {"fun1", "bb", "fanction2"}; |
| string d[] = {"aaa", "bbb", "ccc"}; |
| string o[] = {"object2", "objt1", "object3"}; |
| ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); |
| } |
| |
| // Tests "..." wildcard. |
| TEST_F(SuppressionsWithWildcardsTest, VerticalWildcards1) { |
| string m[] = {"fun1", "bb", "qq", "fanction2"}; |
| string d[] = {"aaa", "bbb", "ddd", "ccc"}; |
| string o[] = {"object2", "objt1", "object3", "object4"}; |
| ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); |
| } |
| |
| |
| class MultipleStackTraceTest : public BaseSuppressionsTest { |
| protected: |
| virtual void SetUp() { |
| const string data = |
| "{\n" |
| " name\n" |
| " test_tool,tool2:test_warning_type\n" |
| " {\n" |
| " fun:fun*1\n" |
| " }\n" |
| " {\n" |
| " fun:fun*2\n" |
| " fun:fun*3\n" |
| " }\n" |
| " {\n" |
| " ...\n" |
| " fun:fun*4\n" |
| " obj:obj*5\n" |
| " }\n" |
| "}"; |
| supp_.ReadFromString(data); |
| } |
| }; |
| |
| TEST_F(MultipleStackTraceTest, Simple1) { |
| string m[] = {"fun1", "bb", "qq", "fun2"}; |
| string d[] = {"aaa", "bbb", "ddd", "ccc"}; |
| string o[] = {"object1", "object2", "object3", "object4"}; |
| ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); |
| } |
| |
| TEST_F(MultipleStackTraceTest, SecondTemplateMatches) { |
| string m[] = {"fun2", "fun3", "qq", "fun2"}; |
| string d[] = {"aaa", "bbb", "ddd", "ccc"}; |
| string o[] = {"object1", "object2", "object3", "object4"}; |
| ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); |
| } |
| |
| TEST_F(MultipleStackTraceTest, ThirdTemplateMatches) { |
| string m[] = {"fun4", "bb", "qq", "fun2"}; |
| string d[] = {"aaa", "bbb", "ddd", "ccc"}; |
| string o[] = {"object1", "object5", "object3", "object4"}; |
| ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); |
| } |
| |
| TEST_F(MultipleStackTraceTest, NothingMatches) { |
| string m[] = {"_fun1", "bb", "qq", "fun2"}; |
| string d[] = {"aaa", "bbb", "ddd", "ccc"}; |
| string o[] = {"object1", "object2", "object3", "object4"}; |
| ASSERT_FALSE(IsSuppressed(VEC(m), VEC(d), VEC(o))); |
| } |
| |
| TEST_F(MultipleStackTraceTest, TwoTemplatesMatch) { |
| string m[] = {"fun1", "bb", "fun4", "fun2"}; |
| string d[] = {"aaa", "bbb", "ddd", "ccc"}; |
| string o[] = {"object1", "object2", "object3", "object5"}; |
| ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); |
| } |
| |
| |
| TEST_F(BaseSuppressionsTest, StartsWithVerticalWildcard) { |
| const string data = |
| "{\n" |
| " name\n" |
| " test_tool:test_warning_type\n" |
| " ...\n" |
| " fun:qq\n" |
| "}"; |
| ASSERT_GT(supp_.ReadFromString(data), 0); |
| string m[] = {"fun1", "bb", "qq", "function2"}; |
| string d[] = {"aaa", "bbb", "ddd", "ccc"}; |
| string o[] = {"object2", "objt1", "object3", "object4"}; |
| ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); |
| } |
| |
| TEST_F(BaseSuppressionsTest, StartsWithVerticalWildcard2) { |
| const string data = |
| "{\n" |
| " name\n" |
| " test_tool:test_warning_type\n" |
| " ...\n" |
| " fun:fun1\n" |
| "}"; |
| ASSERT_GT(supp_.ReadFromString(data), 0); |
| string m[] = {"fun1", "bb", "qq", "function2"}; |
| string d[] = {"aaa", "bbb", "ddd", "ccc"}; |
| string o[] = {"object2", "objt1", "object3", "object4"}; |
| ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); |
| } |
| |
| TEST_F(BaseSuppressionsTest, EndsWithVerticalWildcard) { |
| const string data = |
| "{\n" |
| " name\n" |
| " test_tool:test_warning_type\n" |
| " fun:fun1\n" |
| " ...\n" |
| "}"; |
| ASSERT_GT(supp_.ReadFromString(data), 0); |
| string m[] = {"fun1", "bb", "qq", "function2"}; |
| string d[] = {"aaa", "bbb", "ddd", "ccc"}; |
| string o[] = {"object2", "objt1", "object3", "object4"}; |
| ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); |
| } |
| |
| TEST_F(BaseSuppressionsTest, EndsWithVerticalWildcard2) { |
| const string data = |
| "{\n" |
| " name\n" |
| " test_tool:test_warning_type\n" |
| " fun:qq\n" |
| " ...\n" |
| "}"; |
| ASSERT_GT(supp_.ReadFromString(data), 0); |
| string m[] = {"fun1", "bb", "qq", "function2"}; |
| string d[] = {"aaa", "bbb", "ddd", "ccc"}; |
| string o[] = {"object2", "objt1", "object3", "object4"}; |
| ASSERT_FALSE(IsSuppressed(VEC(m), VEC(d), VEC(o))); |
| } |
| |
| TEST_F(BaseSuppressionsTest, Complex) { |
| const string data = |
| "{\n" |
| " name\n" |
| " test_tool:test_warning_type\n" |
| " fun:qq\n" |
| " ...\n" |
| " obj:obj*3\n" |
| " ...\n" |
| " fun:function?\n" |
| "}"; |
| ASSERT_GT(supp_.ReadFromString(data), 0); |
| string m[] = {"fun1", "bb", "qq", "function2"}; |
| string d[] = {"aaa", "bbb", "ddd", "ccc"}; |
| string o[] = {"object2", "objt1", "object3", "object4"}; |
| ASSERT_FALSE(IsSuppressed(VEC(m), VEC(d), VEC(o))); |
| } |
| |
| TEST_F(BaseSuppressionsTest, DemangledNames) { |
| const string data = |
| "{\n" |
| " name\n" |
| " test_tool:test_warning_type\n" |
| " fun:bb*w?\n" |
| "}"; |
| ASSERT_GT(supp_.ReadFromString(data), 0); |
| string m[] = {"fun1", "bb", "qq", "function2"}; |
| string d[] = {"bbbxxwz", "aaa", "ddd", "ccc"}; |
| string o[] = {"object2", "objt1", "object3", "object4"}; |
| ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); |
| } |
| |
| TEST_F(BaseSuppressionsTest, TrailingWhitespace) { |
| const string data = |
| "{\n" |
| " name\n" |
| " test_tool:test_warning_type\n" |
| " fun:bb*w? \n" |
| "}"; |
| ASSERT_GT(supp_.ReadFromString(data), 0); |
| string m[] = {"fun1", "bb", "qq", "function2"}; |
| string d[] = {"bbbxxwz", "aaa", "ddd", "ccc"}; |
| string o[] = {"object2", "objt1", "object3", "object4"}; |
| ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); |
| } |
| |
| TEST_F(BaseSuppressionsTest, ObjectiveC) { |
| const string data = |
| "{\n" |
| " name\n" |
| " test_tool:test_warning_type\n" |
| " fun:-[NSObject(NSKeyValueCoding) setValue:forKeyPath:]\n" |
| "}"; |
| ASSERT_GT(supp_.ReadFromString(data), 0); |
| string m[] = {"-[NSObject(NSKeyValueCoding) setValue:forKeyPath:]", "function2"}; |
| string d[] = {"bbbxxwz", "aaa", "ddd", "ccc"}; |
| string o[] = {"object2", "objt1", "object3", "object4"}; |
| ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); |
| } |
| |
| TEST_F(BaseSuppressionsTest, ComparisonAndShiftOperators) { |
| const string data = |
| "{\n" |
| " name\n" |
| " test_tool:test_warning_type\n" |
| " fun:operator<\n" |
| " fun:operator>\n" |
| " fun:operator<=\n" |
| " fun:operator>=\n" |
| " fun:operator<<\n" |
| " fun:operator>>\n" |
| " fun:operator<<=\n" |
| " fun:operator>>=\n" |
| " fun:operator->\n" |
| " fun:operator->*\n" |
| "}"; |
| ASSERT_GT(supp_.ReadFromString(data), 0); |
| string m[] = {"operator<", "operator>", "operator<=", "operator>=", |
| "operator<<", "operator>>", "operator<<=", "operator>>=", |
| "operator->", "operator->*"}; |
| string d[] = {"bbbxxwz", "aaa", "ddd", "ccc"}; |
| string o[] = {"object2", "objt1", "object3", "object4"}; |
| ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); |
| } |
| |
| |
| class FailingSuppressionsTest : public ::testing::Test { |
| protected: |
| int ErrorLineNo(string data) { |
| int result = supp_.ReadFromString(data); |
| if (result >= 0) |
| return -1; |
| else |
| return supp_.GetErrorLineNo(); |
| } |
| |
| Suppressions supp_; |
| }; |
| |
| TEST_F(FailingSuppressionsTest, NoOpeningBrace) { |
| const string data = |
| " name\n" |
| " test_tool:test_warning_type\n" |
| " fun:bb*w? \n" |
| "}"; |
| ASSERT_EQ(1, ErrorLineNo(data)); |
| } |
| |
| TEST_F(FailingSuppressionsTest, Bad1) { |
| const string data = |
| "{\n" |
| " name\n" |
| " something_else\n" |
| " test_tool:test_warning_type\n" |
| " fun:bb*w? \n" |
| "}"; |
| ASSERT_EQ(3, ErrorLineNo(data)); |
| } |
| |
| TEST_F(FailingSuppressionsTest, Bad2) { |
| const string data = |
| "{\n" |
| " name\n" |
| " test_tool:test_warning_type\n" |
| " extra\n" |
| " fun:bb*w? \n" |
| "}"; |
| ASSERT_EQ(4, ErrorLineNo(data)); |
| } |
| |
| TEST_F(FailingSuppressionsTest, Bad3) { |
| const string data = |
| "{\n" |
| " name\n" |
| " test_tool:test_warning_type\n" |
| " fun:bb*w? \n" |
| " extra\n" |
| "}"; |
| ASSERT_EQ(5, ErrorLineNo(data)); |
| } |
| |
| TEST_F(FailingSuppressionsTest, SomeWeirdTextAfterASuppression) { |
| const string data = |
| "{\n" |
| " name\n" |
| " test_tool:test_warning_type\n" |
| " fun:bb*w? \n" |
| "}\n" |
| "some_weird_text\n" |
| "after_a_suppression\n"; |
| ASSERT_EQ(6, ErrorLineNo(data)); |
| } |
| |
| TEST_F(FailingSuppressionsTest, NoToolsLineInMultitraceSuppression) { |
| const string data = |
| "{\n" |
| " name\n" |
| " {\n" |
| " fun:fun*2\n" |
| " fun:fun*3\n" |
| " }\n" |
| " {\n" |
| " ...\n" |
| " fun:fun*4\n" |
| " obj:obj*5\n" |
| " }\n" |
| "}"; |
| ASSERT_EQ(3, ErrorLineNo(data)); |
| } |
| |
| TEST_F(FailingSuppressionsTest, BadStacktrace1) { |
| const string data = |
| "{\n" |
| " name\n" |
| " test_tool:test_warning_type\n" |
| " {\n" |
| " fun:fun*2\n" |
| " fun:fun*3\n" |
| " }\n" |
| " {\n" |
| " zzz\n" |
| " fun:fun*4\n" |
| " obj:obj*5\n" |
| " }\n" |
| "}"; |
| ASSERT_EQ(9, ErrorLineNo(data)); |
| } |
| |
| TEST_F(FailingSuppressionsTest, BadStacktrace2) { |
| const string data = |
| "{\n" |
| " name\n" |
| " test_tool:test_warning_type\n" |
| " {\n" |
| " fun:fun*2\n" |
| " fun:fun*3\n" |
| " }\n" |
| " {\n" |
| " {\n" |
| " fun:fun*4\n" |
| " obj:obj*5\n" |
| " }\n" |
| "}"; |
| ASSERT_EQ(9, ErrorLineNo(data)); |
| } |
| |
| TEST_F(FailingSuppressionsTest, BadStacktrace3) { |
| const string data = |
| "{\n" |
| " name\n" |
| " test_tool:test_warning_type\n" |
| " {\n" |
| " fun:fun*2\n" |
| " fun:fun*3\n" |
| " }\n" |
| " {\n" |
| " fun:fun*4\n" |
| " obj:obj*5\n" |
| " }\n" |
| " zzz\n" |
| "}"; |
| ASSERT_EQ(12, ErrorLineNo(data)); |
| } |
| |
| TEST_F(FailingSuppressionsTest, StacktraceWithParenthesis) { |
| const string data = |
| "{\n" |
| " name\n" |
| " test_tool:test_warning_type\n" |
| " {\n" |
| " fun:fun*2\n" |
| " fun:fun*3\n" |
| " }\n" |
| " {\n" |
| " fun:fun*4()\n" |
| " obj:obj*5\n" |
| " }\n" |
| "}"; |
| ASSERT_EQ(9, ErrorLineNo(data)); |
| } |
| |
| TEST_F(FailingSuppressionsTest, StacktraceWithAngleBraces) { |
| const string data = |
| "{\n" |
| " name\n" |
| " test_tool:test_warning_type\n" |
| " {\n" |
| " fun:fun*2\n" |
| " fun:fun*3\n" |
| " }\n" |
| " {\n" |
| " fun:fun<int>*4\n" |
| " obj:obj*5\n" |
| " }\n" |
| "}"; |
| ASSERT_EQ(9, ErrorLineNo(data)); |
| } |
| |
| |
| TEST(WildcardTest, Simple) { |
| EXPECT_TRUE(StringMatch("abc", "abc")); |
| EXPECT_FALSE(StringMatch("abcd", "abc")); |
| EXPECT_FALSE(StringMatch("dabc", "abc")); |
| EXPECT_FALSE(StringMatch("ab", "abc")); |
| EXPECT_FALSE(StringMatch("", "abc")); |
| EXPECT_FALSE(StringMatch("abc", "")); |
| EXPECT_TRUE(StringMatch("", "")); |
| } |
| |
| TEST(WildcardTest, SingleCharacterWildcard) { |
| EXPECT_TRUE(StringMatch("a?c", "abc")); |
| EXPECT_TRUE(StringMatch("?bc", "abc")); |
| EXPECT_TRUE(StringMatch("ab?", "abc")); |
| EXPECT_TRUE(StringMatch("a??", "abc")); |
| EXPECT_TRUE(StringMatch("???", "abc")); |
| EXPECT_TRUE(StringMatch("?", "a")); |
| EXPECT_FALSE(StringMatch("?zc", "abc")); |
| EXPECT_FALSE(StringMatch("?bz", "abc")); |
| EXPECT_FALSE(StringMatch("b?c", "abc")); |
| EXPECT_FALSE(StringMatch("az?", "abc")); |
| EXPECT_FALSE(StringMatch("abc?", "abc")); |
| EXPECT_FALSE(StringMatch("?abc", "abc")); |
| EXPECT_FALSE(StringMatch("?", "")); |
| EXPECT_FALSE(StringMatch("??", "")); |
| } |
| |
| TEST(WildcardTest, MultiCharacterWildcard) { |
| EXPECT_TRUE(StringMatch("*x", "x")); |
| EXPECT_TRUE(StringMatch("x*", "x")); |
| EXPECT_TRUE(StringMatch("*x*", "x")); |
| |
| EXPECT_TRUE(StringMatch("a*d", "abcd")); |
| EXPECT_TRUE(StringMatch("ab*d", "abcd")); |
| EXPECT_TRUE(StringMatch("*cd", "abcd")); |
| EXPECT_TRUE(StringMatch("*d", "abcd")); |
| EXPECT_TRUE(StringMatch("ab*", "abcd")); |
| EXPECT_TRUE(StringMatch("a*", "abcd")); |
| EXPECT_TRUE(StringMatch("*", "abcd")); |
| EXPECT_TRUE(StringMatch("ab*cd", "abcd")); |
| |
| EXPECT_TRUE(StringMatch("ab**", "abcd")); |
| EXPECT_TRUE(StringMatch("**", "abcd")); |
| EXPECT_TRUE(StringMatch("***", "abcd")); |
| EXPECT_TRUE(StringMatch("**d", "abcd")); |
| EXPECT_TRUE(StringMatch("*c*", "abcd")); |
| EXPECT_TRUE(StringMatch("a*c*d*f", "abcdef")); |
| EXPECT_TRUE(StringMatch("a*c*e*", "abcdef")); |
| EXPECT_TRUE(StringMatch("*a*b*f", "abcdef")); |
| EXPECT_TRUE(StringMatch("*b*d*", "abcdef")); |
| |
| EXPECT_FALSE(StringMatch("b*", "abcd")); |
| EXPECT_FALSE(StringMatch("*c", "abcd")); |
| EXPECT_FALSE(StringMatch("*a", "abcd")); |
| } |
| |
| TEST(WildcardTest, WildcardCharactersInText) { |
| EXPECT_TRUE(StringMatch("?", "?")); |
| EXPECT_FALSE(StringMatch("a", "?")); |
| EXPECT_FALSE(StringMatch("ab", "a?")); |
| EXPECT_FALSE(StringMatch("ab", "?b")); |
| EXPECT_TRUE(StringMatch("a?", "a?")); |
| EXPECT_TRUE(StringMatch("?b", "?b")); |
| |
| EXPECT_TRUE(StringMatch("*", "*")); |
| EXPECT_FALSE(StringMatch("a", "*")); |
| EXPECT_FALSE(StringMatch("ab", "a*")); |
| EXPECT_FALSE(StringMatch("ab", "*b")); |
| EXPECT_TRUE(StringMatch("a*", "a*")); |
| EXPECT_TRUE(StringMatch("*b", "*b")); |
| } |
| |
| int main(int argc, char **argv) { |
| testing::InitGoogleTest(&argc, argv); |
| |
| return RUN_ALL_TESTS(); |
| } |