1 //===- llvm/unittest/Support/GlobPatternTest.cpp --------------------------===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Support/GlobPattern.h" 10 #include "gtest/gtest.h" 11 12 using namespace llvm; 13 namespace { 14 15 class GlobPatternTest : public ::testing::Test {}; 16 17 TEST_F(GlobPatternTest, Empty) { 18 Expected<GlobPattern> Pat1 = GlobPattern::create(""); 19 EXPECT_TRUE((bool)Pat1); 20 EXPECT_TRUE(Pat1->match("")); 21 EXPECT_FALSE(Pat1->match("a")); 22 } 23 24 TEST_F(GlobPatternTest, Glob) { 25 Expected<GlobPattern> Pat1 = GlobPattern::create("ab*c*def"); 26 EXPECT_TRUE((bool)Pat1); 27 EXPECT_TRUE(Pat1->match("abcdef")); 28 EXPECT_TRUE(Pat1->match("abxcxdef")); 29 EXPECT_FALSE(Pat1->match("")); 30 EXPECT_FALSE(Pat1->match("xabcdef")); 31 EXPECT_FALSE(Pat1->match("abcdefx")); 32 } 33 34 TEST_F(GlobPatternTest, Wildcard) { 35 Expected<GlobPattern> Pat1 = GlobPattern::create("a??c"); 36 EXPECT_TRUE((bool)Pat1); 37 EXPECT_TRUE(Pat1->match("axxc")); 38 EXPECT_FALSE(Pat1->match("axxx")); 39 EXPECT_FALSE(Pat1->match("")); 40 } 41 42 TEST_F(GlobPatternTest, Escape) { 43 Expected<GlobPattern> Pat1 = GlobPattern::create("\\*"); 44 EXPECT_TRUE((bool)Pat1); 45 EXPECT_TRUE(Pat1->match("*")); 46 EXPECT_FALSE(Pat1->match("\\*")); 47 EXPECT_FALSE(Pat1->match("a")); 48 49 Expected<GlobPattern> Pat2 = GlobPattern::create("a?\\?c"); 50 EXPECT_TRUE((bool)Pat2); 51 EXPECT_TRUE(Pat2->match("ax?c")); 52 EXPECT_FALSE(Pat2->match("axxc")); 53 EXPECT_FALSE(Pat2->match("")); 54 55 for (size_t I = 0; I != 4; ++I) { 56 std::string S(I, '\\'); 57 Expected<GlobPattern> Pat = GlobPattern::create(S); 58 if (I % 2) { 59 EXPECT_FALSE((bool)Pat); 60 handleAllErrors(Pat.takeError(), [&](ErrorInfoBase &) {}); 61 } else { 62 EXPECT_TRUE((bool)Pat); 63 } 64 } 65 } 66 67 TEST_F(GlobPatternTest, BasicCharacterClass) { 68 Expected<GlobPattern> Pat1 = GlobPattern::create("[abc-fy-z]"); 69 EXPECT_TRUE((bool)Pat1); 70 EXPECT_TRUE(Pat1->match("a")); 71 EXPECT_TRUE(Pat1->match("b")); 72 EXPECT_TRUE(Pat1->match("c")); 73 EXPECT_TRUE(Pat1->match("d")); 74 EXPECT_TRUE(Pat1->match("e")); 75 EXPECT_TRUE(Pat1->match("f")); 76 EXPECT_TRUE(Pat1->match("y")); 77 EXPECT_TRUE(Pat1->match("z")); 78 EXPECT_FALSE(Pat1->match("g")); 79 EXPECT_FALSE(Pat1->match("")); 80 81 Expected<GlobPattern> Pat2 = GlobPattern::create("[ab]*[cd]?**[ef]"); 82 ASSERT_TRUE((bool)Pat2); 83 EXPECT_TRUE(Pat2->match("aecde")); 84 EXPECT_FALSE(Pat2->match("aecdg")); 85 } 86 87 TEST_F(GlobPatternTest, NegatedCharacterClass) { 88 Expected<GlobPattern> Pat1 = GlobPattern::create("[^abc-fy-z]"); 89 EXPECT_TRUE((bool)Pat1); 90 EXPECT_TRUE(Pat1->match("g")); 91 EXPECT_FALSE(Pat1->match("a")); 92 EXPECT_FALSE(Pat1->match("b")); 93 EXPECT_FALSE(Pat1->match("c")); 94 EXPECT_FALSE(Pat1->match("d")); 95 EXPECT_FALSE(Pat1->match("e")); 96 EXPECT_FALSE(Pat1->match("f")); 97 EXPECT_FALSE(Pat1->match("y")); 98 EXPECT_FALSE(Pat1->match("z")); 99 EXPECT_FALSE(Pat1->match("")); 100 101 Expected<GlobPattern> Pat2 = GlobPattern::create("[!abc-fy-z]"); 102 EXPECT_TRUE((bool)Pat2); 103 EXPECT_TRUE(Pat2->match("g")); 104 EXPECT_FALSE(Pat2->match("a")); 105 EXPECT_FALSE(Pat2->match("b")); 106 EXPECT_FALSE(Pat2->match("c")); 107 EXPECT_FALSE(Pat2->match("d")); 108 EXPECT_FALSE(Pat2->match("e")); 109 EXPECT_FALSE(Pat2->match("f")); 110 EXPECT_FALSE(Pat2->match("y")); 111 EXPECT_FALSE(Pat2->match("z")); 112 EXPECT_FALSE(Pat2->match("")); 113 } 114 115 TEST_F(GlobPatternTest, BracketFrontOfCharacterClass) { 116 Expected<GlobPattern> Pat1 = GlobPattern::create("[]a]x"); 117 EXPECT_TRUE((bool)Pat1); 118 EXPECT_TRUE(Pat1->match("]x")); 119 EXPECT_TRUE(Pat1->match("ax")); 120 EXPECT_FALSE(Pat1->match("a]x")); 121 EXPECT_FALSE(Pat1->match("")); 122 } 123 124 TEST_F(GlobPatternTest, SpecialCharsInCharacterClass) { 125 Expected<GlobPattern> Pat1 = GlobPattern::create("[*?^]"); 126 EXPECT_TRUE((bool)Pat1); 127 EXPECT_TRUE(Pat1->match("*")); 128 EXPECT_TRUE(Pat1->match("?")); 129 EXPECT_TRUE(Pat1->match("^")); 130 EXPECT_FALSE(Pat1->match("*?^")); 131 EXPECT_FALSE(Pat1->match("")); 132 133 Expected<GlobPattern> Pat2 = GlobPattern::create("[*]"); 134 ASSERT_TRUE((bool)Pat2); 135 EXPECT_TRUE(Pat2->match("*")); 136 EXPECT_FALSE(Pat2->match("]")); 137 } 138 139 TEST_F(GlobPatternTest, Invalid) { 140 Expected<GlobPattern> Pat1 = GlobPattern::create("["); 141 EXPECT_FALSE((bool)Pat1); 142 handleAllErrors(Pat1.takeError(), [&](ErrorInfoBase &EIB) {}); 143 144 Expected<GlobPattern> Pat2 = GlobPattern::create("[]"); 145 EXPECT_FALSE((bool)Pat2); 146 handleAllErrors(Pat2.takeError(), [&](ErrorInfoBase &EIB) {}); 147 } 148 149 TEST_F(GlobPatternTest, ExtSym) { 150 Expected<GlobPattern> Pat1 = GlobPattern::create("a*\xFF"); 151 EXPECT_TRUE((bool)Pat1); 152 EXPECT_TRUE(Pat1->match("axxx\xFF")); 153 Expected<GlobPattern> Pat2 = GlobPattern::create("[\xFF-\xFF]"); 154 EXPECT_TRUE((bool)Pat2); 155 EXPECT_TRUE(Pat2->match("\xFF")); 156 } 157 158 TEST_F(GlobPatternTest, IsTrivialMatchAll) { 159 Expected<GlobPattern> Pat1 = GlobPattern::create("*"); 160 EXPECT_TRUE((bool)Pat1); 161 EXPECT_TRUE(Pat1->isTrivialMatchAll()); 162 163 const char *NegativeCases[] = {"a*", "*a", "?*", "*?", "**", "\\*"}; 164 for (auto *P : NegativeCases) { 165 Expected<GlobPattern> Pat2 = GlobPattern::create(P); 166 EXPECT_TRUE((bool)Pat2); 167 EXPECT_FALSE(Pat2->isTrivialMatchAll()); 168 } 169 } 170 171 TEST_F(GlobPatternTest, NUL) { 172 for (char C : "?*{") { 173 std::string S(1, C); 174 Expected<GlobPattern> Pat = GlobPattern::create(S); 175 ASSERT_TRUE((bool)Pat); 176 EXPECT_TRUE(Pat->match(S)); 177 if (C == '*') { 178 EXPECT_TRUE(Pat->match(S + '\0')); 179 } else { 180 EXPECT_FALSE(Pat->match(S + '\0')); 181 handleAllErrors(Pat.takeError(), [&](ErrorInfoBase &) {}); 182 } 183 } 184 } 185 186 TEST_F(GlobPatternTest, Pathological) { 187 std::string P, S(40, 'a'); 188 for (int I = 0; I != 30; ++I) 189 P += I % 2 ? "a*" : "[ba]*"; 190 Expected<GlobPattern> Pat = GlobPattern::create(P); 191 ASSERT_TRUE((bool)Pat); 192 EXPECT_TRUE(Pat->match(S)); 193 P += 'b'; 194 Pat = GlobPattern::create(P); 195 ASSERT_TRUE((bool)Pat); 196 EXPECT_FALSE(Pat->match(S)); 197 EXPECT_TRUE(Pat->match(S + 'b')); 198 } 199 } 200