1 //===- unittests/Driver/MultilibTest.cpp --- Multilib tests ---------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Unit tests for Multilib and MultilibSet
12 //===----------------------------------------------------------------------===//
14 #include "clang/Driver/Multilib.h"
15 #include "clang/Basic/LLVM.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/ADT/StringSwitch.h"
18 #include "gtest/gtest.h"
20 using namespace clang::driver;
21 using namespace clang;
23 TEST(MultilibTest, MultilibValidity) {
25 ASSERT_TRUE(Multilib().isValid()) << "Empty multilib is not valid";
27 ASSERT_TRUE(Multilib().flag("+foo").isValid())
28 << "Single indicative flag is not valid";
30 ASSERT_TRUE(Multilib().flag("-foo").isValid())
31 << "Single contraindicative flag is not valid";
33 ASSERT_FALSE(Multilib().flag("+foo").flag("-foo").isValid())
34 << "Conflicting flags should invalidate the Multilib";
36 ASSERT_TRUE(Multilib().flag("+foo").flag("+foo").isValid())
37 << "Multilib should be valid even if it has the same flag twice";
39 ASSERT_TRUE(Multilib().flag("+foo").flag("-foobar").isValid())
40 << "Seemingly conflicting prefixes shouldn't actually conflict";
43 TEST(MultilibTest, OpEqReflexivity1) {
45 ASSERT_TRUE(M == M) << "Multilib::operator==() is not reflexive";
48 TEST(MultilibTest, OpEqReflexivity2) {
49 ASSERT_TRUE(Multilib() == Multilib())
50 << "Separately constructed default multilibs are not equal";
53 TEST(MultilibTest, OpEqReflexivity3) {
57 ASSERT_TRUE(M1 == M2) << "Multilibs with the same flag should be the same";
60 TEST(MultilibTest, OpEqInequivalence1) {
64 ASSERT_FALSE(M1 == M2) << "Multilibs with conflicting flags are not the same";
65 ASSERT_FALSE(M2 == M1)
66 << "Multilibs with conflicting flags are not the same (commuted)";
69 TEST(MultilibTest, OpEqInequivalence2) {
72 ASSERT_FALSE(M1 == M2) << "Flags make Multilibs different";
75 TEST(MultilibTest, OpEqEquivalence1) {
78 M2.flag("+foo").flag("+foo");
79 ASSERT_TRUE(M1 == M2) << "Flag duplication shouldn't affect equivalence";
81 << "Flag duplication shouldn't affect equivalence (commuted)";
84 TEST(MultilibTest, OpEqEquivalence2) {
89 << "Constructor argument must match Multilib::gccSuffix()";
91 << "Constructor argument must match Multilib::gccSuffix() (commuted)";
94 TEST(MultilibTest, OpEqEquivalence3) {
95 Multilib M1("", "32");
99 << "Constructor argument must match Multilib::osSuffix()";
100 ASSERT_TRUE(M2 == M1)
101 << "Constructor argument must match Multilib::osSuffix() (commuted)";
104 TEST(MultilibTest, OpEqEquivalence4) {
105 Multilib M1("", "", "16");
107 M2.includeSuffix("/16");
108 ASSERT_TRUE(M1 == M2)
109 << "Constructor argument must match Multilib::includeSuffix()";
110 ASSERT_TRUE(M2 == M1)
111 << "Constructor argument must match Multilib::includeSuffix() (commuted)";
114 TEST(MultilibTest, OpEqInequivalence3) {
117 ASSERT_FALSE(M1 == M2) << "Differing gccSuffixes should be different";
118 ASSERT_FALSE(M2 == M1)
119 << "Differing gccSuffixes should be different (commuted)";
122 TEST(MultilibTest, OpEqInequivalence4) {
123 Multilib M1("", "foo");
124 Multilib M2("", "bar");
125 ASSERT_FALSE(M1 == M2) << "Differing osSuffixes should be different";
126 ASSERT_FALSE(M2 == M1)
127 << "Differing osSuffixes should be different (commuted)";
130 TEST(MultilibTest, OpEqInequivalence5) {
131 Multilib M1("", "", "foo");
132 Multilib M2("", "", "bar");
133 ASSERT_FALSE(M1 == M2) << "Differing includeSuffixes should be different";
134 ASSERT_FALSE(M2 == M1)
135 << "Differing includeSuffixes should be different (commuted)";
138 TEST(MultilibTest, Construction1) {
139 Multilib M("gcc64", "os64", "inc64");
140 ASSERT_TRUE(M.gccSuffix() == "/gcc64");
141 ASSERT_TRUE(M.osSuffix() == "/os64");
142 ASSERT_TRUE(M.includeSuffix() == "/inc64");
145 TEST(MultilibTest, Construction2) {
149 Multilib M4("", "", "");
150 ASSERT_TRUE(M1 == M2)
151 << "Default arguments to Multilib constructor broken (first argument)";
152 ASSERT_TRUE(M1 == M3)
153 << "Default arguments to Multilib constructor broken (second argument)";
154 ASSERT_TRUE(M1 == M4)
155 << "Default arguments to Multilib constructor broken (third argument)";
158 TEST(MultilibTest, Construction3) {
159 Multilib M = Multilib().flag("+f1").flag("+f2").flag("-f3");
160 for (Multilib::flags_list::const_iterator I = M.flags().begin(),
163 ASSERT_TRUE(llvm::StringSwitch<bool>(*I)
164 .Cases("+f1", "+f2", "-f3", true)
169 static bool hasFlag(const Multilib &M, StringRef Flag) {
170 for (Multilib::flags_list::const_iterator I = M.flags().begin(),
175 else if (StringRef(*I).substr(1) == Flag.substr(1))
181 TEST(MultilibTest, SetConstruction1) {
184 ASSERT_TRUE(MS.size() == 0);
185 MS.Maybe(Multilib("64").flag("+m64"));
186 ASSERT_TRUE(MS.size() == 2);
187 for (MultilibSet::const_iterator I = MS.begin(), E = MS.end(); I != E; ++I) {
188 if (I->gccSuffix() == "/64")
189 ASSERT_TRUE(I->flags()[0] == "+m64");
190 else if (I->gccSuffix() == "")
191 ASSERT_TRUE(I->flags()[0] == "-m64");
193 FAIL() << "Unrecognized gccSufix: " << I->gccSuffix();
197 TEST(MultilibTest, SetConstruction2) {
200 MS.Maybe(Multilib("sof").flag("+sof"));
201 MS.Maybe(Multilib("el").flag("+EL"));
202 ASSERT_TRUE(MS.size() == 4);
203 for (MultilibSet::const_iterator I = MS.begin(), E = MS.end(); I != E; ++I) {
204 ASSERT_TRUE(I->isValid()) << "Multilb " << *I << " should be valid";
205 ASSERT_TRUE(llvm::StringSwitch<bool>(I->gccSuffix())
206 .Cases("", "/sof", "/el", "/sof/el", true)
208 << "Multilib " << *I << " wasn't expected";
209 ASSERT_TRUE(llvm::StringSwitch<bool>(I->gccSuffix())
210 .Case("", hasFlag(*I, "-sof"))
211 .Case("/sof", hasFlag(*I, "+sof"))
212 .Case("/el", hasFlag(*I, "-sof"))
213 .Case("/sof/el", hasFlag(*I, "+sof"))
215 << "Multilib " << *I << " didn't have the appropriate {+,-}sof flag";
216 ASSERT_TRUE(llvm::StringSwitch<bool>(I->gccSuffix())
217 .Case("", hasFlag(*I, "-EL"))
218 .Case("/sof", hasFlag(*I, "-EL"))
219 .Case("/el", hasFlag(*I, "+EL"))
220 .Case("/sof/el", hasFlag(*I, "+EL"))
222 << "Multilib " << *I << " didn't have the appropriate {+,-}EL flag";
226 TEST(MultilibTest, SetPushback) {
228 MS.push_back(Multilib("one"));
229 MS.push_back(Multilib("two"));
230 ASSERT_TRUE(MS.size() == 2);
231 for (MultilibSet::const_iterator I = MS.begin(), E = MS.end(); I != E; ++I) {
232 ASSERT_TRUE(llvm::StringSwitch<bool>(I->gccSuffix())
233 .Cases("/one", "/two", true)
237 ASSERT_TRUE(MS.size() == 0);
240 TEST(MultilibTest, SetRegexFilter) {
242 MS.Maybe(Multilib("one"));
243 MS.Maybe(Multilib("two"));
244 MS.Maybe(Multilib("three"));
245 ASSERT_EQ(MS.size(), (unsigned)2 * 2 * 2)
246 << "Size before filter was incorrect. Contents:\n" << MS;
247 MS.FilterOut("/one/two/three");
248 ASSERT_EQ(MS.size(), (unsigned)2 * 2 * 2 - 1)
249 << "Size after filter was incorrect. Contents:\n" << MS;
250 for (MultilibSet::const_iterator I = MS.begin(), E = MS.end(); I != E; ++I) {
251 ASSERT_TRUE(I->gccSuffix() != "/one/two/three")
252 << "The filter should have removed " << *I;
256 TEST(MultilibTest, SetFilterObject) {
258 MS.Maybe(Multilib("orange"));
259 MS.Maybe(Multilib("pear"));
260 MS.Maybe(Multilib("plum"));
261 ASSERT_EQ((int)MS.size(), 1 /* Default */ +
266 1 /* orange/pear */ +
267 1 /* orange/plum */ +
268 1 /* orange/pear/plum */ )
269 << "Size before filter was incorrect. Contents:\n" << MS;
270 MS.FilterOut([](const Multilib &M) {
271 return StringRef(M.gccSuffix()).startswith("/p");
273 ASSERT_EQ((int)MS.size(), 1 /* Default */ +
275 1 /* orange/pear */ +
276 1 /* orange/plum */ +
277 1 /* orange/pear/plum */ )
278 << "Size after filter was incorrect. Contents:\n" << MS;
279 for (MultilibSet::const_iterator I = MS.begin(), E = MS.end(); I != E; ++I) {
280 ASSERT_FALSE(StringRef(I->gccSuffix()).startswith("/p"))
281 << "The filter should have removed " << *I;
285 TEST(MultilibTest, SetSelection1) {
286 MultilibSet MS1 = MultilibSet()
287 .Maybe(Multilib("64").flag("+m64"));
289 Multilib::flags_list FlagM64;
290 FlagM64.push_back("+m64");
291 Multilib SelectionM64;
292 ASSERT_TRUE(MS1.select(FlagM64, SelectionM64))
293 << "Flag set was {\"+m64\"}, but selection not found";
294 ASSERT_TRUE(SelectionM64.gccSuffix() == "/64")
295 << "Selection picked " << SelectionM64 << " which was not expected";
297 Multilib::flags_list FlagNoM64;
298 FlagNoM64.push_back("-m64");
299 Multilib SelectionNoM64;
300 ASSERT_TRUE(MS1.select(FlagNoM64, SelectionNoM64))
301 << "Flag set was {\"-m64\"}, but selection not found";
302 ASSERT_TRUE(SelectionNoM64.gccSuffix() == "")
303 << "Selection picked " << SelectionNoM64 << " which was not expected";
306 TEST(MultilibTest, SetSelection2) {
307 MultilibSet MS2 = MultilibSet()
308 .Maybe(Multilib("el").flag("+EL"))
309 .Maybe(Multilib("sf").flag("+SF"));
311 for (unsigned I = 0; I < 4; ++I) {
314 Multilib::flags_list Flags;
316 Flags.push_back("+EL");
318 Flags.push_back("-EL");
321 Flags.push_back("+SF");
323 Flags.push_back("-SF");
326 ASSERT_TRUE(MS2.select(Flags, Selection)) << "Selection failed for "
327 << (IsEL ? "+EL" : "-EL") << " "
328 << (IsSF ? "+SF" : "-SF");
336 ASSERT_EQ(Selection.gccSuffix(), Suffix) << "Selection picked " << Selection
337 << " which was not expected ";
341 TEST(MultilibTest, SetCombineWith) {
343 Coffee.push_back(Multilib("coffee"));
345 Milk.push_back(Multilib("milk"));
347 ASSERT_EQ(Latte.size(), (unsigned)0);
348 Latte.combineWith(Coffee);
349 ASSERT_EQ(Latte.size(), (unsigned)1);
350 Latte.combineWith(Milk);
351 ASSERT_EQ(Latte.size(), (unsigned)2);