275 lines · cpp
1//===- llvm/unittest/ADT/StringSwitchTest.cpp - StringSwitch unit tests ---===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ADT/StringSwitch.h"10#include "gtest/gtest.h"11 12using namespace llvm;13 14TEST(StringSwitchTest, Case) {15 auto Translate = [](StringRef S) {16 return llvm::StringSwitch<int>(S)17 .Case("0", 0)18 .Case("1", 1)19 .Case("2", 2)20 .Case("3", 3)21 .Case("4", 4)22 .Case("5", 5)23 .Case("6", 6)24 .Case("7", 7)25 .Case("8", 8)26 .Case("9", 9)27 .Case("A", 10)28 .Case("B", 11)29 .Case("C", 12)30 .Case("D", 13)31 .Case("E", 14)32 .Case("F", 15)33 .Default(-1);34 };35 EXPECT_EQ(1, Translate("1"));36 EXPECT_EQ(2, Translate("2"));37 EXPECT_EQ(11, Translate("B"));38 EXPECT_EQ(-1, Translate("b"));39 EXPECT_EQ(-1, Translate(""));40 EXPECT_EQ(-1, Translate("Test"));41}42 43TEST(StringSwitchTest, CaseLower) {44 auto Translate = [](StringRef S) {45 return llvm::StringSwitch<int>(S)46 .Case("0", 0)47 .Case("1", 1)48 .Case("2", 2)49 .Case("3", 3)50 .Case("4", 4)51 .Case("5", 5)52 .Case("6", 6)53 .Case("7", 7)54 .Case("8", 8)55 .Case("9", 9)56 .CaseLower("A", 10)57 .CaseLower("B", 11)58 .CaseLower("C", 12)59 .CaseLower("D", 13)60 .CaseLower("E", 14)61 .CaseLower("F", 15)62 .Default(-1);63 };64 EXPECT_EQ(1, Translate("1"));65 EXPECT_EQ(2, Translate("2"));66 EXPECT_EQ(11, Translate("B"));67 EXPECT_EQ(11, Translate("b"));68 69 EXPECT_EQ(-1, Translate(""));70 EXPECT_EQ(-1, Translate("Test"));71}72 73TEST(StringSwitchTest, StartsWith) {74 auto Translate = [](StringRef S) {75 return llvm::StringSwitch<std::function<int(int, int)>>(S)76 .StartsWith("add", [](int X, int Y) { return X + Y; })77 .StartsWith("sub", [](int X, int Y) { return X - Y; })78 .StartsWith("mul", [](int X, int Y) { return X * Y; })79 .StartsWith("div", [](int X, int Y) { return X / Y; })80 .Default([](int X, int Y) { return 0; });81 };82 83 EXPECT_EQ(15, Translate("adder")(10, 5));84 EXPECT_EQ(5, Translate("subtracter")(10, 5));85 EXPECT_EQ(50, Translate("multiplier")(10, 5));86 EXPECT_EQ(2, Translate("divider")(10, 5));87 88 EXPECT_EQ(0, Translate("nothing")(10, 5));89 EXPECT_EQ(0, Translate("ADDER")(10, 5));90}91 92TEST(StringSwitchTest, StartsWithLower) {93 auto Translate = [](StringRef S) {94 return llvm::StringSwitch<std::function<int(int, int)>>(S)95 .StartsWithLower("add", [](int X, int Y) { return X + Y; })96 .StartsWithLower("sub", [](int X, int Y) { return X - Y; })97 .StartsWithLower("mul", [](int X, int Y) { return X * Y; })98 .StartsWithLower("div", [](int X, int Y) { return X / Y; })99 .Default([](int X, int Y) { return 0; });100 };101 102 EXPECT_EQ(15, Translate("adder")(10, 5));103 EXPECT_EQ(5, Translate("subtracter")(10, 5));104 EXPECT_EQ(50, Translate("multiplier")(10, 5));105 EXPECT_EQ(2, Translate("divider")(10, 5));106 107 EXPECT_EQ(15, Translate("AdDeR")(10, 5));108 EXPECT_EQ(5, Translate("SuBtRaCtEr")(10, 5));109 EXPECT_EQ(50, Translate("MuLtIpLiEr")(10, 5));110 EXPECT_EQ(2, Translate("DiViDeR")(10, 5));111 112 EXPECT_EQ(0, Translate("nothing")(10, 5));113}114 115TEST(StringSwitchTest, EndsWith) {116 enum class Suffix { Possible, PastTense, Process, InProgressAction, Unknown };117 118 auto Translate = [](StringRef S) {119 return llvm::StringSwitch<Suffix>(S)120 .EndsWith("able", Suffix::Possible)121 .EndsWith("ed", Suffix::PastTense)122 .EndsWith("ation", Suffix::Process)123 .EndsWith("ing", Suffix::InProgressAction)124 .Default(Suffix::Unknown);125 };126 127 EXPECT_EQ(Suffix::Possible, Translate("optimizable"));128 EXPECT_EQ(Suffix::PastTense, Translate("optimized"));129 EXPECT_EQ(Suffix::Process, Translate("optimization"));130 EXPECT_EQ(Suffix::InProgressAction, Translate("optimizing"));131 EXPECT_EQ(Suffix::Unknown, Translate("optimizer"));132 EXPECT_EQ(Suffix::Unknown, Translate("OPTIMIZABLE"));133}134 135TEST(StringSwitchTest, EndsWithLower) {136 enum class Suffix { Possible, PastTense, Process, InProgressAction, Unknown };137 138 auto Translate = [](StringRef S) {139 return llvm::StringSwitch<Suffix>(S)140 .EndsWithLower("able", Suffix::Possible)141 .EndsWithLower("ed", Suffix::PastTense)142 .EndsWithLower("ation", Suffix::Process)143 .EndsWithLower("ing", Suffix::InProgressAction)144 .Default(Suffix::Unknown);145 };146 147 EXPECT_EQ(Suffix::Possible, Translate("optimizable"));148 EXPECT_EQ(Suffix::Possible, Translate("OPTIMIZABLE"));149 EXPECT_EQ(Suffix::PastTense, Translate("optimized"));150 EXPECT_EQ(Suffix::Process, Translate("optimization"));151 EXPECT_EQ(Suffix::InProgressAction, Translate("optimizing"));152 EXPECT_EQ(Suffix::Unknown, Translate("optimizer"));153}154 155TEST(StringSwitchTest, Cases) {156 enum class OSType { Windows, Linux, MacOS, Unknown };157 158 auto Translate = [](StringRef S) {159 return llvm::StringSwitch<OSType>(S)160 .Cases({StringLiteral::withInnerNUL("wind\0ws"), "win32", "winnt"},161 OSType::Windows)162 .Cases({"linux", "unix", "*nix", "posix"}, OSType::Linux)163 .Cases({"macos", "osx"}, OSType::MacOS)164 .Default(OSType::Unknown);165 };166 167 EXPECT_EQ(OSType::Windows, Translate(llvm::StringRef("wind\0ws", 7)));168 EXPECT_EQ(OSType::Windows, Translate("win32"));169 EXPECT_EQ(OSType::Windows, Translate("winnt"));170 171 EXPECT_EQ(OSType::Linux, Translate("linux"));172 EXPECT_EQ(OSType::Linux, Translate("unix"));173 EXPECT_EQ(OSType::Linux, Translate("*nix"));174 EXPECT_EQ(OSType::Linux, Translate("posix"));175 176 EXPECT_EQ(OSType::MacOS, Translate("macos"));177 EXPECT_EQ(OSType::MacOS, Translate("osx"));178 179 // Note that the whole null-terminator embedded string is required for the180 // case to match.181 EXPECT_EQ(OSType::Unknown, Translate("wind"));182 EXPECT_EQ(OSType::Unknown, Translate("Windows"));183 EXPECT_EQ(OSType::Unknown, Translate("MacOS"));184 EXPECT_EQ(OSType::Unknown, Translate(""));185}186 187TEST(StringSwitchTest, CasesLower) {188 enum class OSType { Windows, Linux, MacOS, Unknown };189 190 auto Translate = [](StringRef S) {191 return llvm::StringSwitch<OSType>(S)192 .CasesLower({StringLiteral::withInnerNUL("wind\0ws"), "win32", "winnt"},193 OSType::Windows)194 .CasesLower({"linux", "unix", "*nix", "posix"}, OSType::Linux)195 .CasesLower({"macos", "osx"}, OSType::MacOS)196 .Default(OSType::Unknown);197 };198 199 EXPECT_EQ(OSType::Windows, Translate(llvm::StringRef("WIND\0WS", 7)));200 EXPECT_EQ(OSType::Windows, Translate("WIN32"));201 EXPECT_EQ(OSType::Windows, Translate("WINNT"));202 203 EXPECT_EQ(OSType::Linux, Translate("LINUX"));204 EXPECT_EQ(OSType::Linux, Translate("UNIX"));205 EXPECT_EQ(OSType::Linux, Translate("*NIX"));206 EXPECT_EQ(OSType::Linux, Translate("POSIX"));207 208 EXPECT_EQ(OSType::Windows, Translate(llvm::StringRef("wind\0ws", 7)));209 EXPECT_EQ(OSType::Linux, Translate("linux"));210 211 EXPECT_EQ(OSType::MacOS, Translate("macOS"));212 EXPECT_EQ(OSType::MacOS, Translate("OSX"));213 214 EXPECT_EQ(OSType::Unknown, Translate("wind"));215 EXPECT_EQ(OSType::Unknown, Translate(""));216}217 218TEST(StringSwitchTest, CasesCopies) {219 struct Copyable {220 unsigned &NumCopies;221 Copyable(unsigned &Value) : NumCopies(Value) {}222 Copyable(const Copyable &Other) : NumCopies(Other.NumCopies) {223 ++NumCopies;224 }225 Copyable &operator=(const Copyable &Other) {226 ++NumCopies;227 return *this;228 }229 };230 231 // Check that evaluating multiple cases does not cause unnecessary copies.232 unsigned NumCopies = 0;233 llvm::StringSwitch<Copyable, void>("baz").Cases({"foo", "bar", "baz", "qux"},234 Copyable{NumCopies});235 EXPECT_EQ(NumCopies, 1u);236 237 NumCopies = 0;238 llvm::StringSwitch<Copyable, void>("baz").CasesLower(239 {"Foo", "Bar", "Baz", "Qux"}, Copyable{NumCopies});240 EXPECT_EQ(NumCopies, 1u);241}242 243TEST(StringSwitchTest, StringSwitchMultipleMatches) {244 auto Translate = [](StringRef S) {245 return llvm::StringSwitch<int>(S)246 .CaseLower("A", 0)247 .Case("b", 1)248 .Case("a", 2)249 .CasesLower({"a", "b"}, 3)250 .DefaultUnreachable();251 };252 253 // Check that the value of the first match is returned.254 EXPECT_EQ(0, Translate("A"));255 EXPECT_EQ(0, Translate("a"));256 EXPECT_EQ(3, Translate("B"));257 EXPECT_EQ(1, Translate("b"));258}259 260TEST(StringSwitchTest, DefaultUnreachable) {261 auto Translate = [](StringRef S) {262 return llvm::StringSwitch<int>(S)263 .Case("A", 0)264 .Case("B", 1)265 .DefaultUnreachable("Unhandled case");266 };267 268 EXPECT_EQ(0, Translate("A"));269 EXPECT_EQ(1, Translate("B"));270 271#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)272 EXPECT_DEATH((void)Translate("C"), "Unhandled case");273#endif274}275