1214152Sed//===-- sanitizer_suppressions_test.cc ------------------------------------===//
2214152Sed//
3214152Sed//                     The LLVM Compiler Infrastructure
4214152Sed//
5214152Sed// This file is distributed under the University of Illinois Open Source
6214152Sed// License. See LICENSE.TXT for details.
7214152Sed//
8214152Sed//===----------------------------------------------------------------------===//
9214152Sed//
10214152Sed// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
11214152Sed//
12214152Sed//===----------------------------------------------------------------------===//
13214152Sed#include "sanitizer_common/sanitizer_suppressions.h"
14214152Sed#include "gtest/gtest.h"
15214152Sed
16214152Sed#include <string.h>
17214152Sed
18214152Sednamespace __sanitizer {
19214152Sed
20214152Sedstatic bool MyMatch(const char *templ, const char *func) {
21214152Sed  char tmp[1024];
22214152Sed  strcpy(tmp, templ);  // NOLINT
23214152Sed  return TemplateMatch(tmp, func);
24214152Sed}
25214152Sed
26214152SedTEST(Suppressions, Match) {
27214152Sed  EXPECT_TRUE(MyMatch("foobar$", "foobar"));
28214152Sed
29214152Sed  EXPECT_TRUE(MyMatch("foobar", "foobar"));
30214152Sed  EXPECT_TRUE(MyMatch("*foobar*", "foobar"));
31214152Sed  EXPECT_TRUE(MyMatch("foobar", "prefix_foobar_postfix"));
32214152Sed  EXPECT_TRUE(MyMatch("*foobar*", "prefix_foobar_postfix"));
33214152Sed  EXPECT_TRUE(MyMatch("foo*bar", "foo_middle_bar"));
34214152Sed  EXPECT_TRUE(MyMatch("foo*bar", "foobar"));
35214152Sed  EXPECT_TRUE(MyMatch("foo*bar*baz", "foo_middle_bar_another_baz"));
36214152Sed  EXPECT_TRUE(MyMatch("foo*bar*baz", "foo_middle_barbaz"));
37214152Sed  EXPECT_TRUE(MyMatch("^foobar", "foobar"));
38214152Sed  EXPECT_TRUE(MyMatch("^foobar", "foobar_postfix"));
39214152Sed  EXPECT_TRUE(MyMatch("^*foobar", "foobar"));
40214152Sed  EXPECT_TRUE(MyMatch("^*foobar", "prefix_foobar"));
41214152Sed  EXPECT_TRUE(MyMatch("foobar$", "foobar"));
42214152Sed  EXPECT_TRUE(MyMatch("foobar$", "prefix_foobar"));
43214152Sed  EXPECT_TRUE(MyMatch("*foobar*$", "foobar"));
44214152Sed  EXPECT_TRUE(MyMatch("*foobar*$", "foobar_postfix"));
45214152Sed  EXPECT_TRUE(MyMatch("^foobar$", "foobar"));
46214152Sed
47214152Sed  EXPECT_FALSE(MyMatch("foo", "baz"));
48214152Sed  EXPECT_FALSE(MyMatch("foobarbaz", "foobar"));
49214152Sed  EXPECT_FALSE(MyMatch("foobarbaz", "barbaz"));
50214152Sed  EXPECT_FALSE(MyMatch("foo*bar", "foobaz"));
51214152Sed  EXPECT_FALSE(MyMatch("foo*bar", "foo_baz"));
52214152Sed  EXPECT_FALSE(MyMatch("^foobar", "prefix_foobar"));
53214152Sed  EXPECT_FALSE(MyMatch("foobar$", "foobar_postfix"));
54214152Sed  EXPECT_FALSE(MyMatch("^foobar$", "prefix_foobar"));
55214152Sed  EXPECT_FALSE(MyMatch("^foobar$", "foobar_postfix"));
56214152Sed  EXPECT_FALSE(MyMatch("foo^bar", "foobar"));
57214152Sed  EXPECT_FALSE(MyMatch("foo$bar", "foobar"));
58  EXPECT_FALSE(MyMatch("foo$^bar", "foobar"));
59}
60
61static const char *kTestSuppressionTypes[] = {"race", "thread", "mutex",
62                                              "signal"};
63
64class SuppressionContextTest : public ::testing::Test {
65 public:
66  SuppressionContextTest()
67      : ctx_(kTestSuppressionTypes, ARRAY_SIZE(kTestSuppressionTypes)) {}
68
69 protected:
70  SuppressionContext ctx_;
71
72  void CheckSuppressions(unsigned count, std::vector<const char *> types,
73                         std::vector<const char *> templs) const {
74    EXPECT_EQ(count, ctx_.SuppressionCount());
75    for (unsigned i = 0; i < count; i++) {
76      const Suppression *s = ctx_.SuppressionAt(i);
77      EXPECT_STREQ(types[i], s->type);
78      EXPECT_STREQ(templs[i], s->templ);
79    }
80  }
81};
82
83TEST_F(SuppressionContextTest, Parse) {
84  ctx_.Parse("race:foo\n"
85             " 	race:bar\n"  // NOLINT
86             "race:baz	 \n" // NOLINT
87             "# a comment\n"
88             "race:quz\n"); // NOLINT
89  CheckSuppressions(4, {"race", "race", "race", "race"},
90                    {"foo", "bar", "baz", "quz"});
91}
92
93TEST_F(SuppressionContextTest, Parse2) {
94  ctx_.Parse(
95    "  	# first line comment\n"  // NOLINT
96    " 	race:bar 	\n"  // NOLINT
97    "race:baz* *baz\n"
98    "# a comment\n"
99    "# last line comment\n"
100  );  // NOLINT
101  CheckSuppressions(2, {"race", "race"}, {"bar", "baz* *baz"});
102}
103
104TEST_F(SuppressionContextTest, Parse3) {
105  ctx_.Parse(
106    "# last suppression w/o line-feed\n"
107    "race:foo\n"
108    "race:bar\r\n"
109    "race:baz"
110  );  // NOLINT
111  CheckSuppressions(3, {"race", "race", "race"}, {"foo", "bar", "baz"});
112}
113
114TEST_F(SuppressionContextTest, ParseType) {
115  ctx_.Parse(
116    "race:foo\n"
117    "thread:bar\n"
118    "mutex:baz\n"
119    "signal:quz\n"
120  );  // NOLINT
121  CheckSuppressions(4, {"race", "thread", "mutex", "signal"},
122                    {"foo", "bar", "baz", "quz"});
123}
124
125TEST_F(SuppressionContextTest, HasSuppressionType) {
126  ctx_.Parse(
127    "race:foo\n"
128    "thread:bar\n");
129  EXPECT_TRUE(ctx_.HasSuppressionType("race"));
130  EXPECT_TRUE(ctx_.HasSuppressionType("thread"));
131  EXPECT_FALSE(ctx_.HasSuppressionType("mutex"));
132  EXPECT_FALSE(ctx_.HasSuppressionType("signal"));
133}
134
135}  // namespace __sanitizer
136