Inna Palant | ff3f07a | 2019-07-11 16:15:26 -0700 | [diff] [blame] | 1 | //===- SpecialCaseListTest.cpp - Unit tests for SpecialCaseList -----------===// |
| 2 | // |
Chih-Hung Hsieh | 0860053 | 2019-12-19 15:55:38 -0800 | [diff] [blame] | 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
Inna Palant | ff3f07a | 2019-07-11 16:15:26 -0700 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #include "llvm/Support/SpecialCaseList.h" |
| 10 | #include "llvm/Support/FileSystem.h" |
| 11 | #include "llvm/Support/MemoryBuffer.h" |
Jeff Vander Stoep | 247d86b | 2020-08-11 14:27:44 +0200 | [diff] [blame] | 12 | #include "llvm/Support/VirtualFileSystem.h" |
Inna Palant | ff3f07a | 2019-07-11 16:15:26 -0700 | [diff] [blame] | 13 | #include "gtest/gtest.h" |
| 14 | |
| 15 | using namespace llvm; |
| 16 | |
| 17 | namespace { |
| 18 | |
| 19 | class SpecialCaseListTest : public ::testing::Test { |
| 20 | protected: |
| 21 | std::unique_ptr<SpecialCaseList> makeSpecialCaseList(StringRef List, |
| 22 | std::string &Error) { |
| 23 | std::unique_ptr<MemoryBuffer> MB = MemoryBuffer::getMemBuffer(List); |
| 24 | return SpecialCaseList::create(MB.get(), Error); |
| 25 | } |
| 26 | |
| 27 | std::unique_ptr<SpecialCaseList> makeSpecialCaseList(StringRef List) { |
| 28 | std::string Error; |
| 29 | auto SCL = makeSpecialCaseList(List, Error); |
| 30 | assert(SCL); |
| 31 | assert(Error == ""); |
| 32 | return SCL; |
| 33 | } |
| 34 | |
| 35 | std::string makeSpecialCaseListFile(StringRef Contents) { |
| 36 | int FD; |
| 37 | SmallString<64> Path; |
| 38 | sys::fs::createTemporaryFile("SpecialCaseListTest", "temp", FD, Path); |
| 39 | raw_fd_ostream OF(FD, true, true); |
| 40 | OF << Contents; |
| 41 | OF.close(); |
ThiƩbaud Weksteen | e40e736 | 2020-10-28 15:03:00 +0100 | [diff] [blame] | 42 | return std::string(Path.str()); |
Inna Palant | ff3f07a | 2019-07-11 16:15:26 -0700 | [diff] [blame] | 43 | } |
| 44 | }; |
| 45 | |
| 46 | TEST_F(SpecialCaseListTest, Basic) { |
| 47 | std::unique_ptr<SpecialCaseList> SCL = |
| 48 | makeSpecialCaseList("# This is a comment.\n" |
| 49 | "\n" |
| 50 | "src:hello\n" |
| 51 | "src:bye\n" |
| 52 | "src:hi=category\n" |
| 53 | "src:z*=category\n"); |
| 54 | EXPECT_TRUE(SCL->inSection("", "src", "hello")); |
| 55 | EXPECT_TRUE(SCL->inSection("", "src", "bye")); |
| 56 | EXPECT_TRUE(SCL->inSection("", "src", "hi", "category")); |
| 57 | EXPECT_TRUE(SCL->inSection("", "src", "zzzz", "category")); |
| 58 | EXPECT_FALSE(SCL->inSection("", "src", "hi")); |
| 59 | EXPECT_FALSE(SCL->inSection("", "fun", "hello")); |
| 60 | EXPECT_FALSE(SCL->inSection("", "src", "hello", "category")); |
| 61 | |
| 62 | EXPECT_EQ(3u, SCL->inSectionBlame("", "src", "hello")); |
| 63 | EXPECT_EQ(4u, SCL->inSectionBlame("", "src", "bye")); |
| 64 | EXPECT_EQ(5u, SCL->inSectionBlame("", "src", "hi", "category")); |
| 65 | EXPECT_EQ(6u, SCL->inSectionBlame("", "src", "zzzz", "category")); |
| 66 | EXPECT_EQ(0u, SCL->inSectionBlame("", "src", "hi")); |
| 67 | EXPECT_EQ(0u, SCL->inSectionBlame("", "fun", "hello")); |
| 68 | EXPECT_EQ(0u, SCL->inSectionBlame("", "src", "hello", "category")); |
| 69 | } |
| 70 | |
| 71 | TEST_F(SpecialCaseListTest, CorrectErrorLineNumberWithBlankLine) { |
| 72 | std::string Error; |
| 73 | EXPECT_EQ(nullptr, makeSpecialCaseList("# This is a comment.\n" |
| 74 | "\n" |
| 75 | "[not valid\n", |
| 76 | Error)); |
| 77 | EXPECT_TRUE( |
| 78 | ((StringRef)Error).startswith("malformed section header on line 3:")); |
| 79 | |
| 80 | EXPECT_EQ(nullptr, makeSpecialCaseList("\n\n\n" |
| 81 | "[not valid\n", |
| 82 | Error)); |
| 83 | EXPECT_TRUE( |
| 84 | ((StringRef)Error).startswith("malformed section header on line 4:")); |
| 85 | } |
| 86 | |
| 87 | TEST_F(SpecialCaseListTest, SectionRegexErrorHandling) { |
| 88 | std::string Error; |
| 89 | EXPECT_EQ(makeSpecialCaseList("[address", Error), nullptr); |
| 90 | EXPECT_TRUE(((StringRef)Error).startswith("malformed section header ")); |
| 91 | |
| 92 | EXPECT_EQ(makeSpecialCaseList("[[]", Error), nullptr); |
| 93 | EXPECT_TRUE(((StringRef)Error).startswith("malformed regex for section [: ")); |
| 94 | |
| 95 | EXPECT_EQ(makeSpecialCaseList("src:=", Error), nullptr); |
| 96 | EXPECT_TRUE(((StringRef)Error).endswith("Supplied regexp was blank")); |
| 97 | } |
| 98 | |
| 99 | TEST_F(SpecialCaseListTest, Section) { |
| 100 | std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("src:global\n" |
| 101 | "[sect1|sect2]\n" |
| 102 | "src:test1\n" |
| 103 | "[sect3*]\n" |
| 104 | "src:test2\n"); |
| 105 | EXPECT_TRUE(SCL->inSection("arbitrary", "src", "global")); |
| 106 | EXPECT_TRUE(SCL->inSection("", "src", "global")); |
| 107 | EXPECT_TRUE(SCL->inSection("sect1", "src", "test1")); |
| 108 | EXPECT_FALSE(SCL->inSection("sect1-arbitrary", "src", "test1")); |
| 109 | EXPECT_FALSE(SCL->inSection("sect", "src", "test1")); |
| 110 | EXPECT_FALSE(SCL->inSection("sect1", "src", "test2")); |
| 111 | EXPECT_TRUE(SCL->inSection("sect2", "src", "test1")); |
| 112 | EXPECT_TRUE(SCL->inSection("sect3", "src", "test2")); |
| 113 | EXPECT_TRUE(SCL->inSection("sect3-arbitrary", "src", "test2")); |
| 114 | EXPECT_FALSE(SCL->inSection("", "src", "test1")); |
| 115 | EXPECT_FALSE(SCL->inSection("", "src", "test2")); |
| 116 | } |
| 117 | |
| 118 | TEST_F(SpecialCaseListTest, GlobalInit) { |
| 119 | std::unique_ptr<SpecialCaseList> SCL = |
| 120 | makeSpecialCaseList("global:foo=init\n"); |
| 121 | EXPECT_FALSE(SCL->inSection("", "global", "foo")); |
| 122 | EXPECT_FALSE(SCL->inSection("", "global", "bar")); |
| 123 | EXPECT_TRUE(SCL->inSection("", "global", "foo", "init")); |
| 124 | EXPECT_FALSE(SCL->inSection("", "global", "bar", "init")); |
| 125 | |
| 126 | SCL = makeSpecialCaseList("type:t2=init\n"); |
| 127 | EXPECT_FALSE(SCL->inSection("", "type", "t1")); |
| 128 | EXPECT_FALSE(SCL->inSection("", "type", "t2")); |
| 129 | EXPECT_FALSE(SCL->inSection("", "type", "t1", "init")); |
| 130 | EXPECT_TRUE(SCL->inSection("", "type", "t2", "init")); |
| 131 | |
| 132 | SCL = makeSpecialCaseList("src:hello=init\n"); |
| 133 | EXPECT_FALSE(SCL->inSection("", "src", "hello")); |
| 134 | EXPECT_FALSE(SCL->inSection("", "src", "bye")); |
| 135 | EXPECT_TRUE(SCL->inSection("", "src", "hello", "init")); |
| 136 | EXPECT_FALSE(SCL->inSection("", "src", "bye", "init")); |
| 137 | } |
| 138 | |
| 139 | TEST_F(SpecialCaseListTest, Substring) { |
| 140 | std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("src:hello\n" |
| 141 | "fun:foo\n" |
| 142 | "global:bar\n"); |
| 143 | EXPECT_FALSE(SCL->inSection("", "src", "othello")); |
| 144 | EXPECT_FALSE(SCL->inSection("", "fun", "tomfoolery")); |
| 145 | EXPECT_FALSE(SCL->inSection("", "global", "bartender")); |
| 146 | |
| 147 | SCL = makeSpecialCaseList("fun:*foo*\n"); |
| 148 | EXPECT_TRUE(SCL->inSection("", "fun", "tomfoolery")); |
| 149 | EXPECT_TRUE(SCL->inSection("", "fun", "foobar")); |
| 150 | } |
| 151 | |
| 152 | TEST_F(SpecialCaseListTest, InvalidSpecialCaseList) { |
| 153 | std::string Error; |
| 154 | EXPECT_EQ(nullptr, makeSpecialCaseList("badline", Error)); |
| 155 | EXPECT_EQ("malformed line 1: 'badline'", Error); |
| 156 | EXPECT_EQ(nullptr, makeSpecialCaseList("src:bad[a-", Error)); |
| 157 | EXPECT_EQ("malformed regex in line 1: 'bad[a-': invalid character range", |
| 158 | Error); |
| 159 | EXPECT_EQ(nullptr, makeSpecialCaseList("src:a.c\n" |
| 160 | "fun:fun(a\n", |
| 161 | Error)); |
| 162 | EXPECT_EQ("malformed regex in line 2: 'fun(a': parentheses not balanced", |
| 163 | Error); |
| 164 | std::vector<std::string> Files(1, "unexisting"); |
Jeff Vander Stoep | 247d86b | 2020-08-11 14:27:44 +0200 | [diff] [blame] | 165 | EXPECT_EQ(nullptr, |
| 166 | SpecialCaseList::create(Files, *vfs::getRealFileSystem(), Error)); |
Inna Palant | ff3f07a | 2019-07-11 16:15:26 -0700 | [diff] [blame] | 167 | EXPECT_EQ(0U, Error.find("can't open file 'unexisting':")); |
| 168 | } |
| 169 | |
| 170 | TEST_F(SpecialCaseListTest, EmptySpecialCaseList) { |
| 171 | std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList(""); |
| 172 | EXPECT_FALSE(SCL->inSection("", "foo", "bar")); |
| 173 | } |
| 174 | |
ThiƩbaud Weksteen | e40e736 | 2020-10-28 15:03:00 +0100 | [diff] [blame] | 175 | TEST_F(SpecialCaseListTest, MultipleExclusions) { |
Inna Palant | ff3f07a | 2019-07-11 16:15:26 -0700 | [diff] [blame] | 176 | std::vector<std::string> Files; |
| 177 | Files.push_back(makeSpecialCaseListFile("src:bar\n" |
| 178 | "src:*foo*\n" |
| 179 | "src:ban=init\n")); |
| 180 | Files.push_back(makeSpecialCaseListFile("src:baz\n" |
| 181 | "src:*fog*\n")); |
Jeff Vander Stoep | 247d86b | 2020-08-11 14:27:44 +0200 | [diff] [blame] | 182 | auto SCL = SpecialCaseList::createOrDie(Files, *vfs::getRealFileSystem()); |
Inna Palant | ff3f07a | 2019-07-11 16:15:26 -0700 | [diff] [blame] | 183 | EXPECT_TRUE(SCL->inSection("", "src", "bar")); |
| 184 | EXPECT_TRUE(SCL->inSection("", "src", "baz")); |
| 185 | EXPECT_FALSE(SCL->inSection("", "src", "ban")); |
| 186 | EXPECT_TRUE(SCL->inSection("", "src", "ban", "init")); |
| 187 | EXPECT_TRUE(SCL->inSection("", "src", "tomfoolery")); |
| 188 | EXPECT_TRUE(SCL->inSection("", "src", "tomfoglery")); |
| 189 | for (auto &Path : Files) |
| 190 | sys::fs::remove(Path); |
| 191 | } |
| 192 | |
| 193 | TEST_F(SpecialCaseListTest, NoTrigramsInRules) { |
| 194 | std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("fun:b.r\n" |
| 195 | "fun:za*az\n"); |
| 196 | EXPECT_TRUE(SCL->inSection("", "fun", "bar")); |
| 197 | EXPECT_FALSE(SCL->inSection("", "fun", "baz")); |
| 198 | EXPECT_TRUE(SCL->inSection("", "fun", "zakaz")); |
| 199 | EXPECT_FALSE(SCL->inSection("", "fun", "zaraza")); |
| 200 | } |
| 201 | |
| 202 | TEST_F(SpecialCaseListTest, NoTrigramsInARule) { |
| 203 | std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("fun:*bar*\n" |
| 204 | "fun:za*az\n"); |
| 205 | EXPECT_TRUE(SCL->inSection("", "fun", "abara")); |
| 206 | EXPECT_FALSE(SCL->inSection("", "fun", "bor")); |
| 207 | EXPECT_TRUE(SCL->inSection("", "fun", "zakaz")); |
| 208 | EXPECT_FALSE(SCL->inSection("", "fun", "zaraza")); |
| 209 | } |
| 210 | |
| 211 | TEST_F(SpecialCaseListTest, RepetitiveRule) { |
| 212 | std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("fun:*bar*bar*bar*bar*\n" |
| 213 | "fun:bar*\n"); |
| 214 | EXPECT_TRUE(SCL->inSection("", "fun", "bara")); |
| 215 | EXPECT_FALSE(SCL->inSection("", "fun", "abara")); |
| 216 | EXPECT_TRUE(SCL->inSection("", "fun", "barbarbarbar")); |
| 217 | EXPECT_TRUE(SCL->inSection("", "fun", "abarbarbarbar")); |
| 218 | EXPECT_FALSE(SCL->inSection("", "fun", "abarbarbar")); |
| 219 | } |
| 220 | |
| 221 | TEST_F(SpecialCaseListTest, SpecialSymbolRule) { |
| 222 | std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("src:*c\\+\\+abi*\n"); |
| 223 | EXPECT_TRUE(SCL->inSection("", "src", "c++abi")); |
| 224 | EXPECT_FALSE(SCL->inSection("", "src", "c\\+\\+abi")); |
| 225 | } |
| 226 | |
| 227 | TEST_F(SpecialCaseListTest, PopularTrigram) { |
| 228 | std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("fun:*aaaaaa*\n" |
| 229 | "fun:*aaaaa*\n" |
| 230 | "fun:*aaaa*\n" |
| 231 | "fun:*aaa*\n"); |
| 232 | EXPECT_TRUE(SCL->inSection("", "fun", "aaa")); |
| 233 | EXPECT_TRUE(SCL->inSection("", "fun", "aaaa")); |
| 234 | EXPECT_TRUE(SCL->inSection("", "fun", "aaaabbbaaa")); |
| 235 | } |
| 236 | |
| 237 | TEST_F(SpecialCaseListTest, EscapedSymbols) { |
| 238 | std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("src:*c\\+\\+abi*\n" |
| 239 | "src:*hello\\\\world*\n"); |
| 240 | EXPECT_TRUE(SCL->inSection("", "src", "dir/c++abi")); |
| 241 | EXPECT_FALSE(SCL->inSection("", "src", "dir/c\\+\\+abi")); |
| 242 | EXPECT_FALSE(SCL->inSection("", "src", "c\\+\\+abi")); |
| 243 | EXPECT_TRUE(SCL->inSection("", "src", "C:\\hello\\world")); |
| 244 | EXPECT_TRUE(SCL->inSection("", "src", "hello\\world")); |
| 245 | EXPECT_FALSE(SCL->inSection("", "src", "hello\\\\world")); |
| 246 | } |
| 247 | |
| 248 | } |