charset_test.cc (6155B)
1 // Copyright 2020 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "absl/strings/charset.h" 16 17 #include <stdio.h> 18 #include <stdlib.h> 19 20 #include <string> 21 #include <vector> 22 23 #include "gtest/gtest.h" 24 #include "absl/strings/ascii.h" 25 #include "absl/strings/string_view.h" 26 27 namespace { 28 29 constexpr absl::CharSet everything_map = ~absl::CharSet(); 30 constexpr absl::CharSet nothing_map = absl::CharSet(); 31 32 TEST(Charmap, AllTests) { 33 const absl::CharSet also_nothing_map(""); 34 EXPECT_TRUE(everything_map.contains('\0')); 35 EXPECT_FALSE(nothing_map.contains('\0')); 36 EXPECT_FALSE(also_nothing_map.contains('\0')); 37 for (unsigned char ch = 1; ch != 0; ++ch) { 38 SCOPED_TRACE(ch); 39 EXPECT_TRUE(everything_map.contains(ch)); 40 EXPECT_FALSE(nothing_map.contains(ch)); 41 EXPECT_FALSE(also_nothing_map.contains(ch)); 42 } 43 44 const absl::CharSet symbols(absl::string_view("&@#@^!@?", 5)); 45 EXPECT_TRUE(symbols.contains('&')); 46 EXPECT_TRUE(symbols.contains('@')); 47 EXPECT_TRUE(symbols.contains('#')); 48 EXPECT_TRUE(symbols.contains('^')); 49 EXPECT_FALSE(symbols.contains('!')); 50 EXPECT_FALSE(symbols.contains('?')); 51 int cnt = 0; 52 for (unsigned char ch = 1; ch != 0; ++ch) cnt += symbols.contains(ch); 53 EXPECT_EQ(cnt, 4); 54 55 const absl::CharSet lets(absl::string_view("^abcde", 3)); 56 const absl::CharSet lets2(absl::string_view("fghij\0klmnop", 10)); 57 const absl::CharSet lets3("fghij\0klmnop"); 58 EXPECT_TRUE(lets2.contains('k')); 59 EXPECT_FALSE(lets3.contains('k')); 60 61 EXPECT_FALSE((symbols & lets).empty()); 62 EXPECT_TRUE((lets2 & lets).empty()); 63 EXPECT_FALSE((lets & symbols).empty()); 64 EXPECT_TRUE((lets & lets2).empty()); 65 66 EXPECT_TRUE(nothing_map.empty()); 67 EXPECT_FALSE(lets.empty()); 68 } 69 70 std::string Members(const absl::CharSet& m) { 71 std::string r; 72 for (size_t i = 0; i < 256; ++i) 73 if (m.contains(i)) r.push_back(i); 74 return r; 75 } 76 77 std::string ClosedRangeString(unsigned char lo, unsigned char hi) { 78 // Don't depend on lo<hi. Just increment until lo==hi. 79 std::string s; 80 while (true) { 81 s.push_back(lo); 82 if (lo == hi) break; 83 ++lo; 84 } 85 return s; 86 } 87 88 TEST(Charmap, Constexpr) { 89 constexpr absl::CharSet kEmpty = absl::CharSet(); 90 EXPECT_EQ(Members(kEmpty), ""); 91 constexpr absl::CharSet kA = absl::CharSet::Char('A'); 92 EXPECT_EQ(Members(kA), "A"); 93 constexpr absl::CharSet kAZ = absl::CharSet::Range('A', 'Z'); 94 EXPECT_EQ(Members(kAZ), "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 95 constexpr absl::CharSet kIdentifier = 96 absl::CharSet::Range('0', '9') | absl::CharSet::Range('A', 'Z') | 97 absl::CharSet::Range('a', 'z') | absl::CharSet::Char('_'); 98 EXPECT_EQ(Members(kIdentifier), 99 "0123456789" 100 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 101 "_" 102 "abcdefghijklmnopqrstuvwxyz"); 103 constexpr absl::CharSet kAll = ~absl::CharSet(); 104 for (size_t i = 0; i < 256; ++i) { 105 SCOPED_TRACE(i); 106 EXPECT_TRUE(kAll.contains(i)); 107 } 108 constexpr absl::CharSet kHello = absl::CharSet("Hello, world!"); 109 EXPECT_EQ(Members(kHello), " !,Hdelorw"); 110 111 // test negation and intersection 112 constexpr absl::CharSet kABC = 113 absl::CharSet::Range('A', 'Z') & ~absl::CharSet::Range('D', 'Z'); 114 EXPECT_EQ(Members(kABC), "ABC"); 115 116 // contains 117 constexpr bool kContainsA = absl::CharSet("abc").contains('a'); 118 EXPECT_TRUE(kContainsA); 119 constexpr bool kContainsD = absl::CharSet("abc").contains('d'); 120 EXPECT_FALSE(kContainsD); 121 122 // empty 123 constexpr bool kEmptyIsEmpty = absl::CharSet().empty(); 124 EXPECT_TRUE(kEmptyIsEmpty); 125 constexpr bool kNotEmptyIsEmpty = absl::CharSet("abc").empty(); 126 EXPECT_FALSE(kNotEmptyIsEmpty); 127 } 128 129 TEST(Charmap, Range) { 130 // Exhaustive testing takes too long, so test some of the boundaries that 131 // are perhaps going to cause trouble. 132 std::vector<size_t> poi = {0, 1, 2, 3, 4, 7, 8, 9, 15, 133 16, 17, 30, 31, 32, 33, 63, 64, 65, 134 127, 128, 129, 223, 224, 225, 254, 255}; 135 for (auto lo = poi.begin(); lo != poi.end(); ++lo) { 136 SCOPED_TRACE(*lo); 137 for (auto hi = lo; hi != poi.end(); ++hi) { 138 SCOPED_TRACE(*hi); 139 EXPECT_EQ(Members(absl::CharSet::Range(*lo, *hi)), 140 ClosedRangeString(*lo, *hi)); 141 } 142 } 143 } 144 145 TEST(Charmap, NullByteWithStringView) { 146 char characters[5] = {'a', 'b', '\0', 'd', 'x'}; 147 absl::string_view view(characters, 5); 148 absl::CharSet tester(view); 149 EXPECT_TRUE(tester.contains('a')); 150 EXPECT_TRUE(tester.contains('b')); 151 EXPECT_TRUE(tester.contains('\0')); 152 EXPECT_TRUE(tester.contains('d')); 153 EXPECT_TRUE(tester.contains('x')); 154 EXPECT_FALSE(tester.contains('c')); 155 } 156 157 TEST(CharmapCtype, Match) { 158 for (int c = 0; c < 256; ++c) { 159 SCOPED_TRACE(c); 160 SCOPED_TRACE(static_cast<char>(c)); 161 EXPECT_EQ(absl::ascii_isupper(c), 162 absl::CharSet::AsciiUppercase().contains(c)); 163 EXPECT_EQ(absl::ascii_islower(c), 164 absl::CharSet::AsciiLowercase().contains(c)); 165 EXPECT_EQ(absl::ascii_isdigit(c), absl::CharSet::AsciiDigits().contains(c)); 166 EXPECT_EQ(absl::ascii_isalpha(c), 167 absl::CharSet::AsciiAlphabet().contains(c)); 168 EXPECT_EQ(absl::ascii_isalnum(c), 169 absl::CharSet::AsciiAlphanumerics().contains(c)); 170 EXPECT_EQ(absl::ascii_isxdigit(c), 171 absl::CharSet::AsciiHexDigits().contains(c)); 172 EXPECT_EQ(absl::ascii_isprint(c), 173 absl::CharSet::AsciiPrintable().contains(c)); 174 EXPECT_EQ(absl::ascii_isspace(c), 175 absl::CharSet::AsciiWhitespace().contains(c)); 176 EXPECT_EQ(absl::ascii_ispunct(c), 177 absl::CharSet::AsciiPunctuation().contains(c)); 178 } 179 } 180 181 } // namespace