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 134 TEST_F(GlobPatternTest, Invalid) { 135 Expected<GlobPattern> Pat1 = GlobPattern::create("["); 136 EXPECT_FALSE((bool)Pat1); 137 handleAllErrors(Pat1.takeError(), [&](ErrorInfoBase &EIB) {}); 138 139 Expected<GlobPattern> Pat2 = GlobPattern::create("[]"); 140 EXPECT_FALSE((bool)Pat2); 141 handleAllErrors(Pat2.takeError(), [&](ErrorInfoBase &EIB) {}); 142 } 143 144 TEST_F(GlobPatternTest, ExtSym) { 145 Expected<GlobPattern> Pat1 = GlobPattern::create("a*\xFF"); 146 EXPECT_TRUE((bool)Pat1); 147 EXPECT_TRUE(Pat1->match("axxx\xFF")); 148 Expected<GlobPattern> Pat2 = GlobPattern::create("[\xFF-\xFF]"); 149 EXPECT_TRUE((bool)Pat2); 150 EXPECT_TRUE(Pat2->match("\xFF")); 151 } 152 153 TEST_F(GlobPatternTest, IsTrivialMatchAll) { 154 Expected<GlobPattern> Pat1 = GlobPattern::create("*"); 155 EXPECT_TRUE((bool)Pat1); 156 EXPECT_TRUE(Pat1->isTrivialMatchAll()); 157 158 const char *NegativeCases[] = {"a*", "*a", "?*", "*?", "**", "\\*"}; 159 for (auto *P : NegativeCases) { 160 Expected<GlobPattern> Pat2 = GlobPattern::create(P); 161 EXPECT_TRUE((bool)Pat2); 162 EXPECT_FALSE(Pat2->isTrivialMatchAll()); 163 } 164 } 165 166 TEST_F(GlobPatternTest, NUL) { 167 for (char C : "?*{") { 168 std::string S(1, C); 169 Expected<GlobPattern> Pat = GlobPattern::create(S); 170 ASSERT_TRUE((bool)Pat); 171 EXPECT_TRUE(Pat->match(S)); 172 if (C == '*') { 173 EXPECT_TRUE(Pat->match(S + '\0')); 174 } else { 175 EXPECT_FALSE(Pat->match(S + '\0')); 176 handleAllErrors(Pat.takeError(), [&](ErrorInfoBase &) {}); 177 } 178 } 179 } 180 181 TEST_F(GlobPatternTest, Pathological) { 182 std::string P, S(40, 'a'); 183 for (int I = 0; I != 30; ++I) 184 P += I % 2 ? "a*" : "[ba]*"; 185 Expected<GlobPattern> Pat = GlobPattern::create(P); 186 ASSERT_TRUE((bool)Pat); 187 EXPECT_TRUE(Pat->match(S)); 188 P += 'b'; 189 Pat = GlobPattern::create(P); 190 ASSERT_TRUE((bool)Pat); 191 EXPECT_FALSE(Pat->match(S)); 192 EXPECT_TRUE(Pat->match(S + 'b')); 193 } 194 } 195