| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | #include "clang/Driver/Multilib.h" |
| 14 | #include "clang/Basic/LLVM.h" |
| 15 | #include "llvm/ADT/StringRef.h" |
| 16 | #include "llvm/ADT/StringSwitch.h" |
| 17 | #include "gtest/gtest.h" |
| 18 | |
| 19 | using namespace clang::driver; |
| 20 | using namespace clang; |
| 21 | |
| 22 | TEST(MultilibTest, MultilibValidity) { |
| 23 | |
| 24 | ASSERT_TRUE(Multilib().isValid()) << "Empty multilib is not valid"; |
| 25 | |
| 26 | ASSERT_TRUE(Multilib().flag("+foo").isValid()) |
| 27 | << "Single indicative flag is not valid"; |
| 28 | |
| 29 | ASSERT_TRUE(Multilib().flag("-foo").isValid()) |
| 30 | << "Single contraindicative flag is not valid"; |
| 31 | |
| 32 | ASSERT_FALSE(Multilib().flag("+foo").flag("-foo").isValid()) |
| 33 | << "Conflicting flags should invalidate the Multilib"; |
| 34 | |
| 35 | ASSERT_TRUE(Multilib().flag("+foo").flag("+foo").isValid()) |
| 36 | << "Multilib should be valid even if it has the same flag twice"; |
| 37 | |
| 38 | ASSERT_TRUE(Multilib().flag("+foo").flag("-foobar").isValid()) |
| 39 | << "Seemingly conflicting prefixes shouldn't actually conflict"; |
| 40 | } |
| 41 | |
| 42 | TEST(MultilibTest, OpEqReflexivity1) { |
| 43 | Multilib M; |
| 44 | ASSERT_TRUE(M == M) << "Multilib::operator==() is not reflexive"; |
| 45 | } |
| 46 | |
| 47 | TEST(MultilibTest, OpEqReflexivity2) { |
| 48 | ASSERT_TRUE(Multilib() == Multilib()) |
| 49 | << "Separately constructed default multilibs are not equal"; |
| 50 | } |
| 51 | |
| 52 | TEST(MultilibTest, OpEqReflexivity3) { |
| 53 | Multilib M1, M2; |
| 54 | M1.flag("+foo"); |
| 55 | M2.flag("+foo"); |
| 56 | ASSERT_TRUE(M1 == M2) << "Multilibs with the same flag should be the same"; |
| 57 | } |
| 58 | |
| 59 | TEST(MultilibTest, OpEqInequivalence1) { |
| 60 | Multilib M1, M2; |
| 61 | M1.flag("+foo"); |
| 62 | M2.flag("-foo"); |
| 63 | ASSERT_FALSE(M1 == M2) << "Multilibs with conflicting flags are not the same"; |
| 64 | ASSERT_FALSE(M2 == M1) |
| 65 | << "Multilibs with conflicting flags are not the same (commuted)"; |
| 66 | } |
| 67 | |
| 68 | TEST(MultilibTest, OpEqInequivalence2) { |
| 69 | Multilib M1, M2; |
| 70 | M2.flag("+foo"); |
| 71 | ASSERT_FALSE(M1 == M2) << "Flags make Multilibs different"; |
| 72 | } |
| 73 | |
| 74 | TEST(MultilibTest, OpEqEquivalence1) { |
| 75 | Multilib M1, M2; |
| 76 | M1.flag("+foo"); |
| 77 | M2.flag("+foo").flag("+foo"); |
| 78 | ASSERT_TRUE(M1 == M2) << "Flag duplication shouldn't affect equivalence"; |
| 79 | ASSERT_TRUE(M2 == M1) |
| 80 | << "Flag duplication shouldn't affect equivalence (commuted)"; |
| 81 | } |
| 82 | |
| 83 | TEST(MultilibTest, OpEqEquivalence2) { |
| 84 | Multilib M1("64"); |
| 85 | Multilib M2; |
| 86 | M2.gccSuffix("/64"); |
| 87 | ASSERT_TRUE(M1 == M2) |
| 88 | << "Constructor argument must match Multilib::gccSuffix()"; |
| 89 | ASSERT_TRUE(M2 == M1) |
| 90 | << "Constructor argument must match Multilib::gccSuffix() (commuted)"; |
| 91 | } |
| 92 | |
| 93 | TEST(MultilibTest, OpEqEquivalence3) { |
| 94 | Multilib M1("", "32"); |
| 95 | Multilib M2; |
| 96 | M2.osSuffix("/32"); |
| 97 | ASSERT_TRUE(M1 == M2) |
| 98 | << "Constructor argument must match Multilib::osSuffix()"; |
| 99 | ASSERT_TRUE(M2 == M1) |
| 100 | << "Constructor argument must match Multilib::osSuffix() (commuted)"; |
| 101 | } |
| 102 | |
| 103 | TEST(MultilibTest, OpEqEquivalence4) { |
| 104 | Multilib M1("", "", "16"); |
| 105 | Multilib M2; |
| 106 | M2.includeSuffix("/16"); |
| 107 | ASSERT_TRUE(M1 == M2) |
| 108 | << "Constructor argument must match Multilib::includeSuffix()"; |
| 109 | ASSERT_TRUE(M2 == M1) |
| 110 | << "Constructor argument must match Multilib::includeSuffix() (commuted)"; |
| 111 | } |
| 112 | |
| 113 | TEST(MultilibTest, OpEqInequivalence3) { |
| 114 | Multilib M1("foo"); |
| 115 | Multilib M2("bar"); |
| 116 | ASSERT_FALSE(M1 == M2) << "Differing gccSuffixes should be different"; |
| 117 | ASSERT_FALSE(M2 == M1) |
| 118 | << "Differing gccSuffixes should be different (commuted)"; |
| 119 | } |
| 120 | |
| 121 | TEST(MultilibTest, OpEqInequivalence4) { |
| 122 | Multilib M1("", "foo"); |
| 123 | Multilib M2("", "bar"); |
| 124 | ASSERT_FALSE(M1 == M2) << "Differing osSuffixes should be different"; |
| 125 | ASSERT_FALSE(M2 == M1) |
| 126 | << "Differing osSuffixes should be different (commuted)"; |
| 127 | } |
| 128 | |
| 129 | TEST(MultilibTest, OpEqInequivalence5) { |
| 130 | Multilib M1("", "", "foo"); |
| 131 | Multilib M2("", "", "bar"); |
| 132 | ASSERT_FALSE(M1 == M2) << "Differing includeSuffixes should be different"; |
| 133 | ASSERT_FALSE(M2 == M1) |
| 134 | << "Differing includeSuffixes should be different (commuted)"; |
| 135 | } |
| 136 | |
| 137 | TEST(MultilibTest, Construction1) { |
| 138 | Multilib M("gcc64", "os64", "inc64"); |
| 139 | ASSERT_TRUE(M.gccSuffix() == "/gcc64"); |
| 140 | ASSERT_TRUE(M.osSuffix() == "/os64"); |
| 141 | ASSERT_TRUE(M.includeSuffix() == "/inc64"); |
| 142 | } |
| 143 | |
| 144 | TEST(MultilibTest, Construction2) { |
| 145 | Multilib M1; |
| 146 | Multilib M2(""); |
| 147 | Multilib M3("", ""); |
| 148 | Multilib M4("", "", ""); |
| 149 | ASSERT_TRUE(M1 == M2) |
| 150 | << "Default arguments to Multilib constructor broken (first argument)"; |
| 151 | ASSERT_TRUE(M1 == M3) |
| 152 | << "Default arguments to Multilib constructor broken (second argument)"; |
| 153 | ASSERT_TRUE(M1 == M4) |
| 154 | << "Default arguments to Multilib constructor broken (third argument)"; |
| 155 | } |
| 156 | |
| 157 | TEST(MultilibTest, Construction3) { |
| 158 | Multilib M = Multilib().flag("+f1").flag("+f2").flag("-f3"); |
| 159 | for (Multilib::flags_list::const_iterator I = M.flags().begin(), |
| 160 | E = M.flags().end(); |
| 161 | I != E; ++I) { |
| 162 | ASSERT_TRUE(llvm::StringSwitch<bool>(*I) |
| 163 | .Cases("+f1", "+f2", "-f3", true) |
| 164 | .Default(false)); |
| 165 | } |
| 166 | } |
| 167 | |
| 168 | static bool hasFlag(const Multilib &M, StringRef Flag) { |
| 169 | for (Multilib::flags_list::const_iterator I = M.flags().begin(), |
| 170 | E = M.flags().end(); |
| 171 | I != E; ++I) { |
| 172 | if (*I == Flag) |
| 173 | return true; |
| 174 | else if (StringRef(*I).substr(1) == Flag.substr(1)) |
| 175 | return false; |
| 176 | } |
| 177 | return false; |
| 178 | } |
| 179 | |
| 180 | TEST(MultilibTest, SetConstruction1) { |
| 181 | |
| 182 | MultilibSet MS; |
| 183 | ASSERT_TRUE(MS.size() == 0); |
| 184 | MS.Maybe(Multilib("64").flag("+m64")); |
| 185 | ASSERT_TRUE(MS.size() == 2); |
| 186 | for (MultilibSet::const_iterator I = MS.begin(), E = MS.end(); I != E; ++I) { |
| 187 | if (I->gccSuffix() == "/64") |
| 188 | ASSERT_TRUE(I->flags()[0] == "+m64"); |
| 189 | else if (I->gccSuffix() == "") |
| 190 | ASSERT_TRUE(I->flags()[0] == "-m64"); |
| 191 | else |
| 192 | FAIL() << "Unrecognized gccSufix: " << I->gccSuffix(); |
| 193 | } |
| 194 | } |
| 195 | |
| 196 | TEST(MultilibTest, SetConstruction2) { |
| 197 | |
| 198 | MultilibSet MS; |
| 199 | MS.Maybe(Multilib("sof").flag("+sof")); |
| 200 | MS.Maybe(Multilib("el").flag("+EL")); |
| 201 | ASSERT_TRUE(MS.size() == 4); |
| 202 | for (MultilibSet::const_iterator I = MS.begin(), E = MS.end(); I != E; ++I) { |
| 203 | ASSERT_TRUE(I->isValid()) << "Multilb " << *I << " should be valid"; |
| 204 | ASSERT_TRUE(llvm::StringSwitch<bool>(I->gccSuffix()) |
| 205 | .Cases("", "/sof", "/el", "/sof/el", true) |
| 206 | .Default(false)) |
| 207 | << "Multilib " << *I << " wasn't expected"; |
| 208 | ASSERT_TRUE(llvm::StringSwitch<bool>(I->gccSuffix()) |
| 209 | .Case("", hasFlag(*I, "-sof")) |
| 210 | .Case("/sof", hasFlag(*I, "+sof")) |
| 211 | .Case("/el", hasFlag(*I, "-sof")) |
| 212 | .Case("/sof/el", hasFlag(*I, "+sof")) |
| 213 | .Default(false)) |
| 214 | << "Multilib " << *I << " didn't have the appropriate {+,-}sof flag"; |
| 215 | ASSERT_TRUE(llvm::StringSwitch<bool>(I->gccSuffix()) |
| 216 | .Case("", hasFlag(*I, "-EL")) |
| 217 | .Case("/sof", hasFlag(*I, "-EL")) |
| 218 | .Case("/el", hasFlag(*I, "+EL")) |
| 219 | .Case("/sof/el", hasFlag(*I, "+EL")) |
| 220 | .Default(false)) |
| 221 | << "Multilib " << *I << " didn't have the appropriate {+,-}EL flag"; |
| 222 | } |
| 223 | } |
| 224 | |
| 225 | TEST(MultilibTest, SetPushback) { |
| 226 | MultilibSet MS; |
| 227 | MS.push_back(Multilib("one")); |
| 228 | MS.push_back(Multilib("two")); |
| 229 | ASSERT_TRUE(MS.size() == 2); |
| 230 | for (MultilibSet::const_iterator I = MS.begin(), E = MS.end(); I != E; ++I) { |
| 231 | ASSERT_TRUE(llvm::StringSwitch<bool>(I->gccSuffix()) |
| 232 | .Cases("/one", "/two", true) |
| 233 | .Default(false)); |
| 234 | } |
| 235 | MS.clear(); |
| 236 | ASSERT_TRUE(MS.size() == 0); |
| 237 | } |
| 238 | |
| 239 | TEST(MultilibTest, SetRegexFilter) { |
| 240 | MultilibSet MS; |
| 241 | MS.Maybe(Multilib("one")); |
| 242 | MS.Maybe(Multilib("two")); |
| 243 | MS.Maybe(Multilib("three")); |
| 244 | ASSERT_EQ(MS.size(), (unsigned)2 * 2 * 2) |
| 245 | << "Size before filter was incorrect. Contents:\n" << MS; |
| 246 | MS.FilterOut("/one/two/three"); |
| 247 | ASSERT_EQ(MS.size(), (unsigned)2 * 2 * 2 - 1) |
| 248 | << "Size after filter was incorrect. Contents:\n" << MS; |
| 249 | for (MultilibSet::const_iterator I = MS.begin(), E = MS.end(); I != E; ++I) { |
| 250 | ASSERT_TRUE(I->gccSuffix() != "/one/two/three") |
| 251 | << "The filter should have removed " << *I; |
| 252 | } |
| 253 | } |
| 254 | |
| 255 | TEST(MultilibTest, SetFilterObject) { |
| 256 | MultilibSet MS; |
| 257 | MS.Maybe(Multilib("orange")); |
| 258 | MS.Maybe(Multilib("pear")); |
| 259 | MS.Maybe(Multilib("plum")); |
| 260 | ASSERT_EQ((int)MS.size(), 1 + |
| 261 | 1 + |
| 262 | 1 + |
| 263 | 1 + |
| 264 | 1 + |
| 265 | 1 + |
| 266 | 1 + |
| 267 | 1 ) |
| 268 | << "Size before filter was incorrect. Contents:\n" << MS; |
| 269 | MS.FilterOut([](const Multilib &M) { |
| 270 | return StringRef(M.gccSuffix()).startswith("/p"); |
| 271 | }); |
| 272 | ASSERT_EQ((int)MS.size(), 1 + |
| 273 | 1 + |
| 274 | 1 + |
| 275 | 1 + |
| 276 | 1 ) |
| 277 | << "Size after filter was incorrect. Contents:\n" << MS; |
| 278 | for (MultilibSet::const_iterator I = MS.begin(), E = MS.end(); I != E; ++I) { |
| 279 | ASSERT_FALSE(StringRef(I->gccSuffix()).startswith("/p")) |
| 280 | << "The filter should have removed " << *I; |
| 281 | } |
| 282 | } |
| 283 | |
| 284 | TEST(MultilibTest, SetSelection1) { |
| 285 | MultilibSet MS1 = MultilibSet() |
| 286 | .Maybe(Multilib("64").flag("+m64")); |
| 287 | |
| 288 | Multilib::flags_list FlagM64; |
| 289 | FlagM64.push_back("+m64"); |
| 290 | Multilib SelectionM64; |
| 291 | ASSERT_TRUE(MS1.select(FlagM64, SelectionM64)) |
| 292 | << "Flag set was {\"+m64\"}, but selection not found"; |
| 293 | ASSERT_TRUE(SelectionM64.gccSuffix() == "/64") |
| 294 | << "Selection picked " << SelectionM64 << " which was not expected"; |
| 295 | |
| 296 | Multilib::flags_list FlagNoM64; |
| 297 | FlagNoM64.push_back("-m64"); |
| 298 | Multilib SelectionNoM64; |
| 299 | ASSERT_TRUE(MS1.select(FlagNoM64, SelectionNoM64)) |
| 300 | << "Flag set was {\"-m64\"}, but selection not found"; |
| 301 | ASSERT_TRUE(SelectionNoM64.gccSuffix() == "") |
| 302 | << "Selection picked " << SelectionNoM64 << " which was not expected"; |
| 303 | } |
| 304 | |
| 305 | TEST(MultilibTest, SetSelection2) { |
| 306 | MultilibSet MS2 = MultilibSet() |
| 307 | .Maybe(Multilib("el").flag("+EL")) |
| 308 | .Maybe(Multilib("sf").flag("+SF")); |
| 309 | |
| 310 | for (unsigned I = 0; I < 4; ++I) { |
| 311 | bool IsEL = I & 0x1; |
| 312 | bool IsSF = I & 0x2; |
| 313 | Multilib::flags_list Flags; |
| 314 | if (IsEL) |
| 315 | Flags.push_back("+EL"); |
| 316 | else |
| 317 | Flags.push_back("-EL"); |
| 318 | |
| 319 | if (IsSF) |
| 320 | Flags.push_back("+SF"); |
| 321 | else |
| 322 | Flags.push_back("-SF"); |
| 323 | |
| 324 | Multilib Selection; |
| 325 | ASSERT_TRUE(MS2.select(Flags, Selection)) << "Selection failed for " |
| 326 | << (IsEL ? "+EL" : "-EL") << " " |
| 327 | << (IsSF ? "+SF" : "-SF"); |
| 328 | |
| 329 | std::string Suffix; |
| 330 | if (IsEL) |
| 331 | Suffix += "/el"; |
| 332 | if (IsSF) |
| 333 | Suffix += "/sf"; |
| 334 | |
| 335 | ASSERT_EQ(Selection.gccSuffix(), Suffix) << "Selection picked " << Selection |
| 336 | << " which was not expected "; |
| 337 | } |
| 338 | } |
| 339 | |
| 340 | TEST(MultilibTest, SetCombineWith) { |
| 341 | MultilibSet Coffee; |
| 342 | Coffee.push_back(Multilib("coffee")); |
| 343 | MultilibSet Milk; |
| 344 | Milk.push_back(Multilib("milk")); |
| 345 | MultilibSet Latte; |
| 346 | ASSERT_EQ(Latte.size(), (unsigned)0); |
| 347 | Latte.combineWith(Coffee); |
| 348 | ASSERT_EQ(Latte.size(), (unsigned)1); |
| 349 | Latte.combineWith(Milk); |
| 350 | ASSERT_EQ(Latte.size(), (unsigned)2); |
| 351 | } |
| 352 | |