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 56 TEST_F(GlobPatternTest, BasicCharacterClass) { 57 Expected<GlobPattern> Pat1 = GlobPattern::create("[abc-fy-z]"); 58 EXPECT_TRUE((bool)Pat1); 59 EXPECT_TRUE(Pat1->match("a")); 60 EXPECT_TRUE(Pat1->match("b")); 61 EXPECT_TRUE(Pat1->match("c")); 62 EXPECT_TRUE(Pat1->match("d")); 63 EXPECT_TRUE(Pat1->match("e")); 64 EXPECT_TRUE(Pat1->match("f")); 65 EXPECT_TRUE(Pat1->match("y")); 66 EXPECT_TRUE(Pat1->match("z")); 67 EXPECT_FALSE(Pat1->match("g")); 68 EXPECT_FALSE(Pat1->match("")); 69 70 Expected<GlobPattern> Pat2 = GlobPattern::create("[ab]*[cd]?**[ef]"); 71 ASSERT_TRUE((bool)Pat2); 72 EXPECT_TRUE(Pat2->match("aecde")); 73 EXPECT_FALSE(Pat2->match("aecdg")); 74 } 75 76 TEST_F(GlobPatternTest, NegatedCharacterClass) { 77 Expected<GlobPattern> Pat1 = GlobPattern::create("[^abc-fy-z]"); 78 EXPECT_TRUE((bool)Pat1); 79 EXPECT_TRUE(Pat1->match("g")); 80 EXPECT_FALSE(Pat1->match("a")); 81 EXPECT_FALSE(Pat1->match("b")); 82 EXPECT_FALSE(Pat1->match("c")); 83 EXPECT_FALSE(Pat1->match("d")); 84 EXPECT_FALSE(Pat1->match("e")); 85 EXPECT_FALSE(Pat1->match("f")); 86 EXPECT_FALSE(Pat1->match("y")); 87 EXPECT_FALSE(Pat1->match("z")); 88 EXPECT_FALSE(Pat1->match("")); 89 90 Expected<GlobPattern> Pat2 = GlobPattern::create("[!abc-fy-z]"); 91 EXPECT_TRUE((bool)Pat2); 92 EXPECT_TRUE(Pat2->match("g")); 93 EXPECT_FALSE(Pat2->match("a")); 94 EXPECT_FALSE(Pat2->match("b")); 95 EXPECT_FALSE(Pat2->match("c")); 96 EXPECT_FALSE(Pat2->match("d")); 97 EXPECT_FALSE(Pat2->match("e")); 98 EXPECT_FALSE(Pat2->match("f")); 99 EXPECT_FALSE(Pat2->match("y")); 100 EXPECT_FALSE(Pat2->match("z")); 101 EXPECT_FALSE(Pat2->match("")); 102 } 103 104 TEST_F(GlobPatternTest, BracketFrontOfCharacterClass) { 105 Expected<GlobPattern> Pat1 = GlobPattern::create("[]a]x"); 106 EXPECT_TRUE((bool)Pat1); 107 EXPECT_TRUE(Pat1->match("]x")); 108 EXPECT_TRUE(Pat1->match("ax")); 109 EXPECT_FALSE(Pat1->match("a]x")); 110 EXPECT_FALSE(Pat1->match("")); 111 } 112 113 TEST_F(GlobPatternTest, SpecialCharsInCharacterClass) { 114 Expected<GlobPattern> Pat1 = GlobPattern::create("[*?^]"); 115 EXPECT_TRUE((bool)Pat1); 116 EXPECT_TRUE(Pat1->match("*")); 117 EXPECT_TRUE(Pat1->match("?")); 118 EXPECT_TRUE(Pat1->match("^")); 119 EXPECT_FALSE(Pat1->match("*?^")); 120 EXPECT_FALSE(Pat1->match("")); 121 } 122 123 TEST_F(GlobPatternTest, Invalid) { 124 Expected<GlobPattern> Pat1 = GlobPattern::create("["); 125 EXPECT_FALSE((bool)Pat1); 126 handleAllErrors(Pat1.takeError(), [&](ErrorInfoBase &EIB) {}); 127 128 Expected<GlobPattern> Pat2 = GlobPattern::create("[]"); 129 EXPECT_FALSE((bool)Pat2); 130 handleAllErrors(Pat2.takeError(), [&](ErrorInfoBase &EIB) {}); 131 } 132 133 TEST_F(GlobPatternTest, ExtSym) { 134 Expected<GlobPattern> Pat1 = GlobPattern::create("a*\xFF"); 135 EXPECT_TRUE((bool)Pat1); 136 EXPECT_TRUE(Pat1->match("axxx\xFF")); 137 Expected<GlobPattern> Pat2 = GlobPattern::create("[\xFF-\xFF]"); 138 EXPECT_TRUE((bool)Pat2); 139 EXPECT_TRUE(Pat2->match("\xFF")); 140 } 141 142 TEST_F(GlobPatternTest, IsTrivialMatchAll) { 143 Expected<GlobPattern> Pat1 = GlobPattern::create("*"); 144 EXPECT_TRUE((bool)Pat1); 145 EXPECT_TRUE(Pat1->isTrivialMatchAll()); 146 147 const char *NegativeCases[] = {"a*", "*a", "?*", "*?", "**", "\\*"}; 148 for (auto *P : NegativeCases) { 149 Expected<GlobPattern> Pat2 = GlobPattern::create(P); 150 EXPECT_TRUE((bool)Pat2); 151 EXPECT_FALSE(Pat2->isTrivialMatchAll()); 152 } 153 } 154 155 TEST_F(GlobPatternTest, NUL) { 156 for (char C : "?*{") { 157 std::string S(1, C); 158 Expected<GlobPattern> Pat = GlobPattern::create(S); 159 ASSERT_TRUE((bool)Pat); 160 EXPECT_TRUE(Pat->match(S)); 161 if (C == '*') { 162 EXPECT_TRUE(Pat->match(S + '\0')); 163 } else { 164 EXPECT_FALSE(Pat->match(S + '\0')); 165 handleAllErrors(Pat.takeError(), [&](ErrorInfoBase &) {}); 166 } 167 } 168 } 169 170 TEST_F(GlobPatternTest, Pathological) { 171 std::string P, S(4, 'a'); 172 for (int I = 0; I != 3; ++I) 173 P += I % 2 ? "a*" : "[ba]*"; 174 Expected<GlobPattern> Pat = GlobPattern::create(P); 175 ASSERT_TRUE((bool)Pat); 176 EXPECT_TRUE(Pat->match(S)); 177 P += 'b'; 178 Pat = GlobPattern::create(P); 179 ASSERT_TRUE((bool)Pat); 180 EXPECT_FALSE(Pat->match(S)); 181 EXPECT_TRUE(Pat->match(S + 'b')); 182 } 183 } 184