MultilibTest.cpp 11 KB

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