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 | |