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