1 //===----------- CoreAPIsTest.cpp - Unit tests for Core ORC APIs ----------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "OrcTestCommon.h"
10 #include "llvm/Config/llvm-config.h"
11 #include "llvm/ExecutionEngine/Orc/Core.h"
12 #include "llvm/ExecutionEngine/Orc/OrcError.h"
13 #include "llvm/Testing/Support/Error.h"
14 
15 #include <set>
16 #include <thread>
17 
18 using namespace llvm;
19 using namespace llvm::orc;
20 
21 class CoreAPIsStandardTest : public CoreAPIsBasedStandardTest {};
22 
23 namespace {
24 
25 TEST_F(CoreAPIsStandardTest, BasicSuccessfulLookup) {
26   bool OnCompletionRun = false;
27 
28   auto OnCompletion = [&](Expected<SymbolMap> Result) {
29     EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error";
30     auto &Resolved = *Result;
31     auto I = Resolved.find(Foo);
32     EXPECT_NE(I, Resolved.end()) << "Could not find symbol definition";
33     EXPECT_EQ(I->second.getAddress(), FooAddr)
34         << "Resolution returned incorrect result";
35     OnCompletionRun = true;
36   };
37 
38   std::shared_ptr<MaterializationResponsibility> FooMR;
39 
40   cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
41       SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
42       [&](MaterializationResponsibility R) {
43         FooMR = std::make_shared<MaterializationResponsibility>(std::move(R));
44       })));
45 
46   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
47             SymbolLookupSet(Foo), SymbolState::Ready, OnCompletion,
48             NoDependenciesToRegister);
49 
50   EXPECT_FALSE(OnCompletionRun) << "Should not have been resolved yet";
51 
52   cantFail(FooMR->notifyResolved({{Foo, FooSym}}));
53 
54   EXPECT_FALSE(OnCompletionRun) << "Should not be ready yet";
55 
56   cantFail(FooMR->notifyEmitted());
57 
58   EXPECT_TRUE(OnCompletionRun) << "Should have been marked ready";
59 }
60 
61 TEST_F(CoreAPIsStandardTest, ExecutionSessionFailQuery) {
62   bool OnCompletionRun = false;
63 
64   auto OnCompletion = [&](Expected<SymbolMap> Result) {
65     EXPECT_FALSE(!!Result) << "Resolution unexpectedly returned success";
66     auto Msg = toString(Result.takeError());
67     EXPECT_EQ(Msg, "xyz") << "Resolution returned incorrect result";
68     OnCompletionRun = true;
69   };
70 
71   AsynchronousSymbolQuery Q(SymbolLookupSet(Foo), SymbolState::Ready,
72                             OnCompletion);
73 
74   ES.legacyFailQuery(Q,
75                      make_error<StringError>("xyz", inconvertibleErrorCode()));
76 
77   EXPECT_TRUE(OnCompletionRun) << "OnCompletionCallback was not run";
78 }
79 
80 TEST_F(CoreAPIsStandardTest, EmptyLookup) {
81   bool OnCompletionRun = false;
82 
83   auto OnCompletion = [&](Expected<SymbolMap> Result) {
84     cantFail(std::move(Result));
85     OnCompletionRun = true;
86   };
87 
88   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(),
89             SymbolState::Ready, OnCompletion, NoDependenciesToRegister);
90 
91   EXPECT_TRUE(OnCompletionRun) << "OnCompletion was not run for empty query";
92 }
93 
94 TEST_F(CoreAPIsStandardTest, ResolveUnrequestedSymbol) {
95   // Test that all symbols in a MaterializationUnit materialize corretly when
96   // only a subset of symbols is looked up.
97   // The aim here is to ensure that we're not relying on the query to set up
98   // state needed to materialize the unrequested symbols.
99 
100   cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
101       SymbolFlagsMap({{Foo, FooSym.getFlags()}, {Bar, BarSym.getFlags()}}),
102       [this](MaterializationResponsibility R) {
103         cantFail(R.notifyResolved({{Foo, FooSym}, {Bar, BarSym}}));
104         cantFail(R.notifyEmitted());
105       })));
106 
107   auto Result =
108       cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet({Foo})));
109   EXPECT_EQ(Result.size(), 1U) << "Unexpected number of results";
110   EXPECT_TRUE(Result.count(Foo)) << "Expected result for \"Foo\"";
111 }
112 
113 TEST_F(CoreAPIsStandardTest, MaterializationSideEffctsOnlyBasic) {
114   // Test that basic materialization-side-effects-only symbols work as expected:
115   // that they can be emitted without being resolved, that queries for them
116   // don't return until they're emitted, and that they don't appear in query
117   // results.
118 
119   Optional<MaterializationResponsibility> FooR;
120   Optional<SymbolMap> Result;
121 
122   cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
123       SymbolFlagsMap(
124           {{Foo, JITSymbolFlags::Exported |
125                      JITSymbolFlags::MaterializationSideEffectsOnly}}),
126       [&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); })));
127 
128   ES.lookup(
129       LookupKind::Static, makeJITDylibSearchOrder(&JD),
130       SymbolLookupSet({Foo}, SymbolLookupFlags::WeaklyReferencedSymbol),
131       SymbolState::Ready,
132       [&](Expected<SymbolMap> LookupResult) {
133         if (LookupResult)
134           Result = std::move(*LookupResult);
135         else
136           ADD_FAILURE() << "Unexpected lookup error: "
137                         << toString(LookupResult.takeError());
138       },
139       NoDependenciesToRegister);
140 
141   EXPECT_FALSE(Result) << "Lookup returned unexpectedly";
142   EXPECT_TRUE(FooR) << "Lookup failed to trigger materialization";
143   EXPECT_THAT_ERROR(FooR->notifyEmitted(), Succeeded())
144       << "Emission of materialization-side-effects-only symbol failed";
145 
146   EXPECT_TRUE(Result) << "Lookup failed to return";
147   EXPECT_TRUE(Result->empty()) << "Lookup result contained unexpected value";
148 }
149 
150 TEST_F(CoreAPIsStandardTest, MaterializationSideEffectsOnlyFailuresPersist) {
151   // Test that when a MaterializationSideEffectsOnly symbol is failed it
152   // remains in the failure state rather than vanishing.
153 
154   cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
155       SymbolFlagsMap(
156           {{Foo, JITSymbolFlags::Exported |
157                      JITSymbolFlags::MaterializationSideEffectsOnly}}),
158       [&](MaterializationResponsibility R) { R.failMaterialization(); })));
159 
160   EXPECT_THAT_EXPECTED(
161       ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet({Foo})),
162       Failed());
163   EXPECT_THAT_EXPECTED(
164       ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet({Foo})),
165       Failed());
166 }
167 
168 TEST_F(CoreAPIsStandardTest, RemoveSymbolsTest) {
169   // Test that:
170   // (1) Missing symbols generate a SymbolsNotFound error.
171   // (2) Materializing symbols generate a SymbolCouldNotBeRemoved error.
172   // (3) Removal of unmaterialized symbols triggers discard on the
173   //     materialization unit.
174   // (4) Removal of symbols destroys empty materialization units.
175   // (5) Removal of materialized symbols works.
176 
177   // Foo will be fully materialized.
178   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
179 
180   // Bar will be unmaterialized.
181   bool BarDiscarded = false;
182   bool BarMaterializerDestructed = false;
183   cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
184       SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
185       [this](MaterializationResponsibility R) {
186         ADD_FAILURE() << "Unexpected materialization of \"Bar\"";
187         cantFail(R.notifyResolved({{Bar, BarSym}}));
188         cantFail(R.notifyEmitted());
189       },
190       nullptr,
191       [&](const JITDylib &JD, const SymbolStringPtr &Name) {
192         EXPECT_EQ(Name, Bar) << "Expected \"Bar\" to be discarded";
193         if (Name == Bar)
194           BarDiscarded = true;
195       },
196       [&]() { BarMaterializerDestructed = true; })));
197 
198   // Baz will be in the materializing state initially, then
199   // materialized for the final removal attempt.
200   Optional<MaterializationResponsibility> BazR;
201   cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
202       SymbolFlagsMap({{Baz, BazSym.getFlags()}}),
203       [&](MaterializationResponsibility R) { BazR.emplace(std::move(R)); },
204       nullptr,
205       [](const JITDylib &JD, const SymbolStringPtr &Name) {
206         ADD_FAILURE() << "\"Baz\" discarded unexpectedly";
207       })));
208 
209   bool OnCompletionRun = false;
210   ES.lookup(
211       LookupKind::Static, makeJITDylibSearchOrder(&JD),
212       SymbolLookupSet({Foo, Baz}), SymbolState::Ready,
213       [&](Expected<SymbolMap> Result) {
214         cantFail(Result.takeError());
215         OnCompletionRun = true;
216       },
217       NoDependenciesToRegister);
218 
219   {
220     // Attempt 1: Search for a missing symbol, Qux.
221     auto Err = JD.remove({Foo, Bar, Baz, Qux});
222     EXPECT_TRUE(!!Err) << "Expected failure";
223     EXPECT_TRUE(Err.isA<SymbolsNotFound>())
224         << "Expected a SymbolsNotFound error";
225     consumeError(std::move(Err));
226   }
227 
228   {
229     // Attempt 2: Search for a symbol that is still materializing, Baz.
230     auto Err = JD.remove({Foo, Bar, Baz});
231     EXPECT_TRUE(!!Err) << "Expected failure";
232     EXPECT_TRUE(Err.isA<SymbolsCouldNotBeRemoved>())
233         << "Expected a SymbolsNotFound error";
234     consumeError(std::move(Err));
235   }
236 
237   cantFail(BazR->notifyResolved({{Baz, BazSym}}));
238   cantFail(BazR->notifyEmitted());
239   {
240     // Attempt 3: Search now that all symbols are fully materialized
241     // (Foo, Baz), or not yet materialized (Bar).
242     auto Err = JD.remove({Foo, Bar, Baz});
243     EXPECT_FALSE(!!Err) << "Expected success";
244   }
245 
246   EXPECT_TRUE(BarDiscarded) << "\"Bar\" should have been discarded";
247   EXPECT_TRUE(BarMaterializerDestructed)
248       << "\"Bar\"'s materializer should have been destructed";
249   EXPECT_TRUE(OnCompletionRun) << "OnCompletion should have been run";
250 }
251 
252 TEST_F(CoreAPIsStandardTest, ChainedJITDylibLookup) {
253   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
254 
255   auto &JD2 = ES.createBareJITDylib("JD2");
256 
257   bool OnCompletionRun = false;
258 
259   auto Q = std::make_shared<AsynchronousSymbolQuery>(
260       SymbolLookupSet({Foo}), SymbolState::Ready,
261       [&](Expected<SymbolMap> Result) {
262         cantFail(std::move(Result));
263         OnCompletionRun = true;
264       });
265 
266   cantFail(JD2.legacyLookup(Q, cantFail(JD.legacyLookup(Q, {Foo}))));
267 
268   EXPECT_TRUE(OnCompletionRun) << "OnCompletion was not run for empty query";
269 }
270 
271 TEST_F(CoreAPIsStandardTest, LookupWithHiddenSymbols) {
272   auto BarHiddenFlags = BarSym.getFlags() & ~JITSymbolFlags::Exported;
273   auto BarHiddenSym = JITEvaluatedSymbol(BarSym.getAddress(), BarHiddenFlags);
274 
275   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarHiddenSym}})));
276 
277   auto &JD2 = ES.createBareJITDylib("JD2");
278   cantFail(JD2.define(absoluteSymbols({{Bar, QuxSym}})));
279 
280   /// Try a blocking lookup.
281   auto Result = cantFail(ES.lookup(makeJITDylibSearchOrder({&JD, &JD2}),
282                                    SymbolLookupSet({Foo, Bar})));
283 
284   EXPECT_EQ(Result.size(), 2U) << "Unexpected number of results";
285   EXPECT_EQ(Result.count(Foo), 1U) << "Missing result for \"Foo\"";
286   EXPECT_EQ(Result.count(Bar), 1U) << "Missing result for \"Bar\"";
287   EXPECT_EQ(Result[Bar].getAddress(), QuxSym.getAddress())
288       << "Wrong result for \"Bar\"";
289 }
290 
291 TEST_F(CoreAPIsStandardTest, LookupFlagsTest) {
292   // Test that lookupFlags works on a predefined symbol, and does not trigger
293   // materialization of a lazy symbol. Make the lazy symbol weak to test that
294   // the weak flag is propagated correctly.
295 
296   BarSym.setFlags(static_cast<JITSymbolFlags::FlagNames>(
297       JITSymbolFlags::Exported | JITSymbolFlags::Weak));
298   auto MU = std::make_unique<SimpleMaterializationUnit>(
299       SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
300       [](MaterializationResponsibility R) {
301         llvm_unreachable("Symbol materialized on flags lookup");
302       });
303 
304   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
305   cantFail(JD.define(std::move(MU)));
306 
307   auto SymbolFlags = cantFail(JD.lookupFlags(
308       LookupKind::Static, JITDylibLookupFlags::MatchExportedSymbolsOnly,
309       SymbolLookupSet({Foo, Bar, Baz})));
310 
311   EXPECT_EQ(SymbolFlags.size(), 2U)
312       << "Returned symbol flags contains unexpected results";
313   EXPECT_EQ(SymbolFlags.count(Foo), 1U) << "Missing lookupFlags result for Foo";
314   EXPECT_EQ(SymbolFlags[Foo], FooSym.getFlags())
315       << "Incorrect flags returned for Foo";
316   EXPECT_EQ(SymbolFlags.count(Bar), 1U)
317       << "Missing  lookupFlags result for Bar";
318   EXPECT_EQ(SymbolFlags[Bar], BarSym.getFlags())
319       << "Incorrect flags returned for Bar";
320 }
321 
322 TEST_F(CoreAPIsStandardTest, LookupWithGeneratorFailure) {
323 
324   class BadGenerator : public JITDylib::DefinitionGenerator {
325   public:
326     Error tryToGenerate(LookupKind K, JITDylib &, JITDylibLookupFlags,
327                         const SymbolLookupSet &) override {
328       return make_error<StringError>("BadGenerator", inconvertibleErrorCode());
329     }
330   };
331 
332   JD.addGenerator(std::make_unique<BadGenerator>());
333 
334   EXPECT_THAT_ERROR(
335       JD.lookupFlags(LookupKind::Static,
336                      JITDylibLookupFlags::MatchExportedSymbolsOnly,
337                      SymbolLookupSet(Foo))
338           .takeError(),
339       Failed<StringError>())
340       << "Generator failure did not propagate through lookupFlags";
341 
342   EXPECT_THAT_ERROR(
343       ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo)).takeError(),
344       Failed<StringError>())
345       << "Generator failure did not propagate through lookup";
346 }
347 
348 TEST_F(CoreAPIsStandardTest, TestBasicAliases) {
349   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarSym}})));
350   cantFail(JD.define(symbolAliases({{Baz, {Foo, JITSymbolFlags::Exported}},
351                                     {Qux, {Bar, JITSymbolFlags::Weak}}})));
352   cantFail(JD.define(absoluteSymbols({{Qux, QuxSym}})));
353 
354   auto Result =
355       ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet({Baz, Qux}));
356   EXPECT_TRUE(!!Result) << "Unexpected lookup failure";
357   EXPECT_EQ(Result->count(Baz), 1U) << "No result for \"baz\"";
358   EXPECT_EQ(Result->count(Qux), 1U) << "No result for \"qux\"";
359   EXPECT_EQ((*Result)[Baz].getAddress(), FooSym.getAddress())
360       << "\"Baz\"'s address should match \"Foo\"'s";
361   EXPECT_EQ((*Result)[Qux].getAddress(), QuxSym.getAddress())
362       << "The \"Qux\" alias should have been overriden";
363 }
364 
365 TEST_F(CoreAPIsStandardTest, TestChainedAliases) {
366   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
367   cantFail(JD.define(symbolAliases(
368       {{Baz, {Bar, BazSym.getFlags()}}, {Bar, {Foo, BarSym.getFlags()}}})));
369 
370   auto Result =
371       ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet({Bar, Baz}));
372   EXPECT_TRUE(!!Result) << "Unexpected lookup failure";
373   EXPECT_EQ(Result->count(Bar), 1U) << "No result for \"bar\"";
374   EXPECT_EQ(Result->count(Baz), 1U) << "No result for \"baz\"";
375   EXPECT_EQ((*Result)[Bar].getAddress(), FooSym.getAddress())
376       << "\"Bar\"'s address should match \"Foo\"'s";
377   EXPECT_EQ((*Result)[Baz].getAddress(), FooSym.getAddress())
378       << "\"Baz\"'s address should match \"Foo\"'s";
379 }
380 
381 TEST_F(CoreAPIsStandardTest, TestBasicReExports) {
382   // Test that the basic use case of re-exporting a single symbol from another
383   // JITDylib works.
384   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
385 
386   auto &JD2 = ES.createBareJITDylib("JD2");
387 
388   cantFail(JD2.define(reexports(JD, {{Bar, {Foo, BarSym.getFlags()}}})));
389 
390   auto Result = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD2), Bar));
391   EXPECT_EQ(Result.getAddress(), FooSym.getAddress())
392       << "Re-export Bar for symbol Foo should match FooSym's address";
393 }
394 
395 TEST_F(CoreAPIsStandardTest, TestThatReExportsDontUnnecessarilyMaterialize) {
396   // Test that re-exports do not materialize symbols that have not been queried
397   // for.
398   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
399 
400   bool BarMaterialized = false;
401   auto BarMU = std::make_unique<SimpleMaterializationUnit>(
402       SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
403       [&](MaterializationResponsibility R) {
404         BarMaterialized = true;
405         cantFail(R.notifyResolved({{Bar, BarSym}}));
406         cantFail(R.notifyEmitted());
407       });
408 
409   cantFail(JD.define(BarMU));
410 
411   auto &JD2 = ES.createBareJITDylib("JD2");
412 
413   cantFail(JD2.define(reexports(
414       JD, {{Baz, {Foo, BazSym.getFlags()}}, {Qux, {Bar, QuxSym.getFlags()}}})));
415 
416   auto Result = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD2), Baz));
417   EXPECT_EQ(Result.getAddress(), FooSym.getAddress())
418       << "Re-export Baz for symbol Foo should match FooSym's address";
419 
420   EXPECT_FALSE(BarMaterialized) << "Bar should not have been materialized";
421 }
422 
423 TEST_F(CoreAPIsStandardTest, TestReexportsGenerator) {
424   // Test that a re-exports generator can dynamically generate reexports.
425 
426   auto &JD2 = ES.createBareJITDylib("JD2");
427   cantFail(JD2.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarSym}})));
428 
429   auto Filter = [this](SymbolStringPtr Name) { return Name != Bar; };
430 
431   JD.addGenerator(std::make_unique<ReexportsGenerator>(
432       JD2, JITDylibLookupFlags::MatchExportedSymbolsOnly, Filter));
433 
434   auto Flags = cantFail(JD.lookupFlags(
435       LookupKind::Static, JITDylibLookupFlags::MatchExportedSymbolsOnly,
436       SymbolLookupSet({Foo, Bar, Baz})));
437   EXPECT_EQ(Flags.size(), 1U) << "Unexpected number of results";
438   EXPECT_EQ(Flags[Foo], FooSym.getFlags()) << "Unexpected flags for Foo";
439 
440   auto Result = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), Foo));
441 
442   EXPECT_EQ(Result.getAddress(), FooSym.getAddress())
443       << "Incorrect reexported symbol address";
444 }
445 
446 TEST_F(CoreAPIsStandardTest, TestTrivialCircularDependency) {
447   Optional<MaterializationResponsibility> FooR;
448   auto FooMU = std::make_unique<SimpleMaterializationUnit>(
449       SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
450       [&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); });
451 
452   cantFail(JD.define(FooMU));
453 
454   bool FooReady = false;
455   auto OnCompletion = [&](Expected<SymbolMap> Result) {
456     cantFail(std::move(Result));
457     FooReady = true;
458   };
459 
460   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
461             SymbolLookupSet({Foo}), SymbolState::Ready, OnCompletion,
462             NoDependenciesToRegister);
463 
464   FooR->addDependenciesForAll({{&JD, SymbolNameSet({Foo})}});
465   EXPECT_THAT_ERROR(FooR->notifyResolved({{Foo, FooSym}}), Succeeded())
466       << "No symbols marked failed, but Foo failed to resolve";
467   EXPECT_THAT_ERROR(FooR->notifyEmitted(), Succeeded())
468       << "No symbols marked failed, but Foo failed to emit";
469 
470   EXPECT_TRUE(FooReady)
471     << "Self-dependency prevented symbol from being marked ready";
472 }
473 
474 TEST_F(CoreAPIsStandardTest, TestCircularDependenceInOneJITDylib) {
475   // Test that a circular symbol dependency between three symbols in a JITDylib
476   // does not prevent any symbol from becoming 'ready' once all symbols are
477   // emitted.
478 
479   // Create three MaterializationResponsibility objects: one for each of Foo,
480   // Bar and Baz. These are optional because MaterializationResponsibility
481   // does not have a default constructor).
482   Optional<MaterializationResponsibility> FooR;
483   Optional<MaterializationResponsibility> BarR;
484   Optional<MaterializationResponsibility> BazR;
485 
486   // Create a MaterializationUnit for each symbol that moves the
487   // MaterializationResponsibility into one of the locals above.
488   auto FooMU = std::make_unique<SimpleMaterializationUnit>(
489       SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
490       [&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); });
491 
492   auto BarMU = std::make_unique<SimpleMaterializationUnit>(
493       SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
494       [&](MaterializationResponsibility R) { BarR.emplace(std::move(R)); });
495 
496   auto BazMU = std::make_unique<SimpleMaterializationUnit>(
497       SymbolFlagsMap({{Baz, BazSym.getFlags()}}),
498       [&](MaterializationResponsibility R) { BazR.emplace(std::move(R)); });
499 
500   // Define the symbols.
501   cantFail(JD.define(FooMU));
502   cantFail(JD.define(BarMU));
503   cantFail(JD.define(BazMU));
504 
505   // Query each of the symbols to trigger materialization.
506   bool FooResolved = false;
507   bool FooReady = false;
508 
509   auto OnFooResolution = [&](Expected<SymbolMap> Result) {
510     cantFail(std::move(Result));
511     FooResolved = true;
512   };
513 
514   auto OnFooReady = [&](Expected<SymbolMap> Result) {
515     cantFail(std::move(Result));
516     FooReady = true;
517   };
518 
519   // Issue lookups for Foo. Use NoDependenciesToRegister: We're going to add
520   // the dependencies manually below.
521   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
522             SymbolLookupSet(Foo), SymbolState::Resolved,
523             std::move(OnFooResolution), NoDependenciesToRegister);
524 
525   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
526             SymbolLookupSet(Foo), SymbolState::Ready, std::move(OnFooReady),
527             NoDependenciesToRegister);
528 
529   bool BarResolved = false;
530   bool BarReady = false;
531   auto OnBarResolution = [&](Expected<SymbolMap> Result) {
532     cantFail(std::move(Result));
533     BarResolved = true;
534   };
535 
536   auto OnBarReady = [&](Expected<SymbolMap> Result) {
537     cantFail(std::move(Result));
538     BarReady = true;
539   };
540 
541   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
542             SymbolLookupSet(Bar), SymbolState::Resolved,
543             std::move(OnBarResolution), NoDependenciesToRegister);
544 
545   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
546             SymbolLookupSet(Bar), SymbolState::Ready, std::move(OnBarReady),
547             NoDependenciesToRegister);
548 
549   bool BazResolved = false;
550   bool BazReady = false;
551 
552   auto OnBazResolution = [&](Expected<SymbolMap> Result) {
553     cantFail(std::move(Result));
554     BazResolved = true;
555   };
556 
557   auto OnBazReady = [&](Expected<SymbolMap> Result) {
558     cantFail(std::move(Result));
559     BazReady = true;
560   };
561 
562   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
563             SymbolLookupSet(Baz), SymbolState::Resolved,
564             std::move(OnBazResolution), NoDependenciesToRegister);
565 
566   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
567             SymbolLookupSet(Baz), SymbolState::Ready, std::move(OnBazReady),
568             NoDependenciesToRegister);
569 
570   // Add a circular dependency: Foo -> Bar, Bar -> Baz, Baz -> Foo.
571   FooR->addDependenciesForAll({{&JD, SymbolNameSet({Bar})}});
572   BarR->addDependenciesForAll({{&JD, SymbolNameSet({Baz})}});
573   BazR->addDependenciesForAll({{&JD, SymbolNameSet({Foo})}});
574 
575   // Add self-dependencies for good measure. This tests that the implementation
576   // of addDependencies filters these out.
577   FooR->addDependenciesForAll({{&JD, SymbolNameSet({Foo})}});
578   BarR->addDependenciesForAll({{&JD, SymbolNameSet({Bar})}});
579   BazR->addDependenciesForAll({{&JD, SymbolNameSet({Baz})}});
580 
581   // Check that nothing has been resolved yet.
582   EXPECT_FALSE(FooResolved) << "\"Foo\" should not be resolved yet";
583   EXPECT_FALSE(BarResolved) << "\"Bar\" should not be resolved yet";
584   EXPECT_FALSE(BazResolved) << "\"Baz\" should not be resolved yet";
585 
586   // Resolve the symbols (but do not emit them).
587   EXPECT_THAT_ERROR(FooR->notifyResolved({{Foo, FooSym}}), Succeeded())
588       << "No symbols failed, but Foo failed to resolve";
589   EXPECT_THAT_ERROR(BarR->notifyResolved({{Bar, BarSym}}), Succeeded())
590       << "No symbols failed, but Bar failed to resolve";
591   EXPECT_THAT_ERROR(BazR->notifyResolved({{Baz, BazSym}}), Succeeded())
592       << "No symbols failed, but Baz failed to resolve";
593 
594   // Verify that the symbols have been resolved, but are not ready yet.
595   EXPECT_TRUE(FooResolved) << "\"Foo\" should be resolved now";
596   EXPECT_TRUE(BarResolved) << "\"Bar\" should be resolved now";
597   EXPECT_TRUE(BazResolved) << "\"Baz\" should be resolved now";
598 
599   EXPECT_FALSE(FooReady) << "\"Foo\" should not be ready yet";
600   EXPECT_FALSE(BarReady) << "\"Bar\" should not be ready yet";
601   EXPECT_FALSE(BazReady) << "\"Baz\" should not be ready yet";
602 
603   // Emit two of the symbols.
604   EXPECT_THAT_ERROR(FooR->notifyEmitted(), Succeeded())
605       << "No symbols failed, but Foo failed to emit";
606   EXPECT_THAT_ERROR(BarR->notifyEmitted(), Succeeded())
607       << "No symbols failed, but Bar failed to emit";
608 
609   // Verify that nothing is ready until the circular dependence is resolved.
610   EXPECT_FALSE(FooReady) << "\"Foo\" still should not be ready";
611   EXPECT_FALSE(BarReady) << "\"Bar\" still should not be ready";
612   EXPECT_FALSE(BazReady) << "\"Baz\" still should not be ready";
613 
614   // Emit the last symbol.
615   EXPECT_THAT_ERROR(BazR->notifyEmitted(), Succeeded())
616       << "No symbols failed, but Baz failed to emit";
617 
618   // Verify that everything becomes ready once the circular dependence resolved.
619   EXPECT_TRUE(FooReady) << "\"Foo\" should be ready now";
620   EXPECT_TRUE(BarReady) << "\"Bar\" should be ready now";
621   EXPECT_TRUE(BazReady) << "\"Baz\" should be ready now";
622 }
623 
624 TEST_F(CoreAPIsStandardTest, FailureInDependency) {
625   Optional<MaterializationResponsibility> FooR;
626   Optional<MaterializationResponsibility> BarR;
627 
628   // Create a MaterializationUnit for each symbol that moves the
629   // MaterializationResponsibility into one of the locals above.
630   auto FooMU = std::make_unique<SimpleMaterializationUnit>(
631       SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
632       [&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); });
633 
634   auto BarMU = std::make_unique<SimpleMaterializationUnit>(
635       SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
636       [&](MaterializationResponsibility R) { BarR.emplace(std::move(R)); });
637 
638   // Define the symbols.
639   cantFail(JD.define(FooMU));
640   cantFail(JD.define(BarMU));
641 
642   bool OnFooReadyRun = false;
643   auto OnFooReady = [&](Expected<SymbolMap> Result) {
644     EXPECT_THAT_EXPECTED(std::move(Result), Failed());
645     OnFooReadyRun = true;
646   };
647 
648   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
649             SymbolLookupSet(Foo), SymbolState::Ready, std::move(OnFooReady),
650             NoDependenciesToRegister);
651 
652   bool OnBarReadyRun = false;
653   auto OnBarReady = [&](Expected<SymbolMap> Result) {
654     EXPECT_THAT_EXPECTED(std::move(Result), Failed());
655     OnBarReadyRun = true;
656   };
657 
658   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
659             SymbolLookupSet(Bar), SymbolState::Ready, std::move(OnBarReady),
660             NoDependenciesToRegister);
661 
662   // Add a dependency by Foo on Bar.
663   FooR->addDependenciesForAll({{&JD, SymbolNameSet({Bar})}});
664 
665   // Fail bar.
666   BarR->failMaterialization();
667 
668   // Verify that queries on Bar failed, but queries on Foo have not yet.
669   EXPECT_TRUE(OnBarReadyRun) << "Query for \"Bar\" was not run";
670   EXPECT_FALSE(OnFooReadyRun) << "Query for \"Foo\" was run unexpectedly";
671 
672   // Check that we can still resolve Foo (even though it has been failed).
673   EXPECT_THAT_ERROR(FooR->notifyResolved({{Foo, FooSym}}), Failed())
674       << "Expected resolution for \"Foo\" to fail.";
675 
676   FooR->failMaterialization();
677 
678   // Verify that queries on Foo have now failed.
679   EXPECT_TRUE(OnFooReadyRun) << "Query for \"Foo\" was not run";
680 
681   // Verify that subsequent lookups on Bar and Foo fail.
682   EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Bar}), Failed())
683       << "Lookup on failed symbol should fail";
684 
685   EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Foo}), Failed())
686       << "Lookup on failed symbol should fail";
687 }
688 
689 TEST_F(CoreAPIsStandardTest, FailureInCircularDependency) {
690   Optional<MaterializationResponsibility> FooR;
691   Optional<MaterializationResponsibility> BarR;
692 
693   // Create a MaterializationUnit for each symbol that moves the
694   // MaterializationResponsibility into one of the locals above.
695   auto FooMU = std::make_unique<SimpleMaterializationUnit>(
696       SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
697       [&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); });
698 
699   auto BarMU = std::make_unique<SimpleMaterializationUnit>(
700       SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
701       [&](MaterializationResponsibility R) { BarR.emplace(std::move(R)); });
702 
703   // Define the symbols.
704   cantFail(JD.define(FooMU));
705   cantFail(JD.define(BarMU));
706 
707   bool OnFooReadyRun = false;
708   auto OnFooReady = [&](Expected<SymbolMap> Result) {
709     EXPECT_THAT_EXPECTED(std::move(Result), Failed());
710     OnFooReadyRun = true;
711   };
712 
713   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
714             SymbolLookupSet(Foo), SymbolState::Ready, std::move(OnFooReady),
715             NoDependenciesToRegister);
716 
717   bool OnBarReadyRun = false;
718   auto OnBarReady = [&](Expected<SymbolMap> Result) {
719     EXPECT_THAT_EXPECTED(std::move(Result), Failed());
720     OnBarReadyRun = true;
721   };
722 
723   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
724             SymbolLookupSet(Bar), SymbolState::Ready, std::move(OnBarReady),
725             NoDependenciesToRegister);
726 
727   // Add a dependency by Foo on Bar and vice-versa.
728   FooR->addDependenciesForAll({{&JD, SymbolNameSet({Bar})}});
729   BarR->addDependenciesForAll({{&JD, SymbolNameSet({Foo})}});
730 
731   // Fail bar.
732   BarR->failMaterialization();
733 
734   // Verify that queries on Bar failed, but queries on Foo have not yet.
735   EXPECT_TRUE(OnBarReadyRun) << "Query for \"Bar\" was not run";
736   EXPECT_FALSE(OnFooReadyRun) << "Query for \"Foo\" was run unexpectedly";
737 
738   // Verify that trying to resolve Foo fails.
739   EXPECT_THAT_ERROR(FooR->notifyResolved({{Foo, FooSym}}), Failed())
740       << "Expected resolution for \"Foo\" to fail.";
741 
742   FooR->failMaterialization();
743 
744   // Verify that queries on Foo have now failed.
745   EXPECT_TRUE(OnFooReadyRun) << "Query for \"Foo\" was not run";
746 
747   // Verify that subsequent lookups on Bar and Foo fail.
748   EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Bar}), Failed())
749       << "Lookup on failed symbol should fail";
750 
751   EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Foo}), Failed())
752       << "Lookup on failed symbol should fail";
753 }
754 
755 TEST_F(CoreAPIsStandardTest, AddDependencyOnFailedSymbol) {
756   Optional<MaterializationResponsibility> FooR;
757   Optional<MaterializationResponsibility> BarR;
758 
759   // Create a MaterializationUnit for each symbol that moves the
760   // MaterializationResponsibility into one of the locals above.
761   auto FooMU = std::make_unique<SimpleMaterializationUnit>(
762       SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
763       [&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); });
764 
765   auto BarMU = std::make_unique<SimpleMaterializationUnit>(
766       SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
767       [&](MaterializationResponsibility R) { BarR.emplace(std::move(R)); });
768 
769   // Define the symbols.
770   cantFail(JD.define(FooMU));
771   cantFail(JD.define(BarMU));
772 
773   bool OnFooReadyRun = false;
774   auto OnFooReady = [&](Expected<SymbolMap> Result) {
775     EXPECT_THAT_EXPECTED(std::move(Result), Failed());
776     OnFooReadyRun = true;
777   };
778 
779   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
780             SymbolLookupSet(Foo), SymbolState::Ready, std::move(OnFooReady),
781             NoDependenciesToRegister);
782 
783   bool OnBarReadyRun = false;
784   auto OnBarReady = [&](Expected<SymbolMap> Result) {
785     EXPECT_THAT_EXPECTED(std::move(Result), Failed());
786     OnBarReadyRun = true;
787   };
788 
789   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
790             SymbolLookupSet(Bar), SymbolState::Ready, std::move(OnBarReady),
791             NoDependenciesToRegister);
792 
793   // Fail bar.
794   BarR->failMaterialization();
795 
796   // We expect Bar's query to fail immediately, but Foo's query not to have run
797   // yet.
798   EXPECT_TRUE(OnBarReadyRun) << "Query for \"Bar\" was not run";
799   EXPECT_FALSE(OnFooReadyRun) << "Query for \"Foo\" should not have run yet";
800 
801   // Add dependency of Foo on Bar.
802   FooR->addDependenciesForAll({{&JD, SymbolNameSet({Bar})}});
803 
804   // Check that we can still resolve Foo (even though it has been failed).
805   EXPECT_THAT_ERROR(FooR->notifyResolved({{Foo, FooSym}}), Failed())
806       << "Expected resolution for \"Foo\" to fail.";
807 
808   FooR->failMaterialization();
809 
810   // Foo's query should have failed before we return from addDependencies.
811   EXPECT_TRUE(OnFooReadyRun) << "Query for \"Foo\" was not run";
812 
813   // Verify that subsequent lookups on Bar and Foo fail.
814   EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Bar}), Failed())
815       << "Lookup on failed symbol should fail";
816 
817   EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Foo}), Failed())
818       << "Lookup on failed symbol should fail";
819 }
820 
821 TEST_F(CoreAPIsStandardTest, FailAfterMaterialization) {
822   Optional<MaterializationResponsibility> FooR;
823   Optional<MaterializationResponsibility> BarR;
824 
825   // Create a MaterializationUnit for each symbol that moves the
826   // MaterializationResponsibility into one of the locals above.
827   auto FooMU = std::make_unique<SimpleMaterializationUnit>(
828       SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
829       [&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); });
830 
831   auto BarMU = std::make_unique<SimpleMaterializationUnit>(
832       SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
833       [&](MaterializationResponsibility R) { BarR.emplace(std::move(R)); });
834 
835   // Define the symbols.
836   cantFail(JD.define(FooMU));
837   cantFail(JD.define(BarMU));
838 
839   bool OnFooReadyRun = false;
840   auto OnFooReady = [&](Expected<SymbolMap> Result) {
841     EXPECT_THAT_EXPECTED(std::move(Result), Failed());
842     OnFooReadyRun = true;
843   };
844 
845   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
846             SymbolLookupSet(Foo), SymbolState::Ready, std::move(OnFooReady),
847             NoDependenciesToRegister);
848 
849   bool OnBarReadyRun = false;
850   auto OnBarReady = [&](Expected<SymbolMap> Result) {
851     EXPECT_THAT_EXPECTED(std::move(Result), Failed());
852     OnBarReadyRun = true;
853   };
854 
855   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
856             SymbolLookupSet(Bar), SymbolState::Ready, std::move(OnBarReady),
857             NoDependenciesToRegister);
858 
859   // Add a dependency by Foo on Bar and vice-versa.
860   FooR->addDependenciesForAll({{&JD, SymbolNameSet({Bar})}});
861   BarR->addDependenciesForAll({{&JD, SymbolNameSet({Foo})}});
862 
863   // Materialize Foo.
864   EXPECT_THAT_ERROR(FooR->notifyResolved({{Foo, FooSym}}), Succeeded())
865       << "Expected resolution for \"Foo\" to succeed.";
866   EXPECT_THAT_ERROR(FooR->notifyEmitted(), Succeeded())
867       << "Expected emission for \"Foo\" to succeed.";
868 
869   // Fail bar.
870   BarR->failMaterialization();
871 
872   // Verify that both queries failed.
873   EXPECT_TRUE(OnFooReadyRun) << "Query for Foo did not run";
874   EXPECT_TRUE(OnBarReadyRun) << "Query for Bar did not run";
875 }
876 
877 TEST_F(CoreAPIsStandardTest, FailMaterializerWithUnqueriedSymbols) {
878   // Make sure that symbols with no queries aganist them still
879   // fail correctly.
880 
881   bool MaterializerRun = false;
882   auto MU = std::make_unique<SimpleMaterializationUnit>(
883       SymbolFlagsMap(
884           {{Foo, JITSymbolFlags::Exported}, {Bar, JITSymbolFlags::Exported}}),
885       [&](MaterializationResponsibility R) {
886         MaterializerRun = true;
887         R.failMaterialization();
888       });
889 
890   cantFail(JD.define(std::move(MU)));
891 
892   // Issue a query for Foo, but not bar.
893   EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Foo}), Failed())
894       << "Expected lookup to fail.";
895 
896   // Check that the materializer (and therefore failMaterialization) ran.
897   EXPECT_TRUE(MaterializerRun) << "Expected materializer to have run by now";
898 
899   // Check that subsequent queries against both symbols fail.
900   EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Foo}), Failed())
901       << "Expected lookup for Foo to fail.";
902   EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Bar}), Failed())
903       << "Expected lookup for Bar to fail.";
904 }
905 
906 TEST_F(CoreAPIsStandardTest, DropMaterializerWhenEmpty) {
907   bool DestructorRun = false;
908 
909   JITSymbolFlags WeakExported(JITSymbolFlags::Exported);
910   WeakExported |= JITSymbolFlags::Weak;
911 
912   auto MU = std::make_unique<SimpleMaterializationUnit>(
913       SymbolFlagsMap({{Foo, WeakExported}, {Bar, WeakExported}}),
914       [](MaterializationResponsibility R) {
915         llvm_unreachable("Unexpected call to materialize");
916       },
917       nullptr,
918       [&](const JITDylib &JD, SymbolStringPtr Name) {
919         EXPECT_TRUE(Name == Foo || Name == Bar)
920             << "Discard of unexpected symbol?";
921       },
922       [&]() { DestructorRun = true; });
923 
924   cantFail(JD.define(MU));
925 
926   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
927 
928   EXPECT_FALSE(DestructorRun)
929       << "MaterializationUnit should not have been destroyed yet";
930 
931   cantFail(JD.define(absoluteSymbols({{Bar, BarSym}})));
932 
933   EXPECT_TRUE(DestructorRun)
934       << "MaterializationUnit should have been destroyed";
935 }
936 
937 TEST_F(CoreAPIsStandardTest, AddAndMaterializeLazySymbol) {
938   bool FooMaterialized = false;
939   bool BarDiscarded = false;
940 
941   JITSymbolFlags WeakExported(JITSymbolFlags::Exported);
942   WeakExported |= JITSymbolFlags::Weak;
943 
944   auto MU = std::make_unique<SimpleMaterializationUnit>(
945       SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}, {Bar, WeakExported}}),
946       [&](MaterializationResponsibility R) {
947         assert(BarDiscarded && "Bar should have been discarded by this point");
948         cantFail(R.notifyResolved(SymbolMap({{Foo, FooSym}})));
949         cantFail(R.notifyEmitted());
950         FooMaterialized = true;
951       },
952       nullptr,
953       [&](const JITDylib &JD, SymbolStringPtr Name) {
954         EXPECT_EQ(Name, Bar) << "Expected Name to be Bar";
955         BarDiscarded = true;
956       });
957 
958   cantFail(JD.define(MU));
959   cantFail(JD.define(absoluteSymbols({{Bar, BarSym}})));
960 
961   bool OnCompletionRun = false;
962 
963   auto OnCompletion = [&](Expected<SymbolMap> Result) {
964     EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error";
965     auto I = Result->find(Foo);
966     EXPECT_NE(I, Result->end()) << "Could not find symbol definition";
967     EXPECT_EQ(I->second.getAddress(), FooSym.getAddress())
968         << "Resolution returned incorrect result";
969     OnCompletionRun = true;
970   };
971 
972   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
973             SymbolLookupSet(Foo), SymbolState::Ready, std::move(OnCompletion),
974             NoDependenciesToRegister);
975 
976   EXPECT_TRUE(FooMaterialized) << "Foo was not materialized";
977   EXPECT_TRUE(BarDiscarded) << "Bar was not discarded";
978   EXPECT_TRUE(OnCompletionRun) << "OnResolutionCallback was not run";
979 }
980 
981 TEST_F(CoreAPIsStandardTest, TestBasicWeakSymbolMaterialization) {
982   // Test that weak symbols are materialized correctly when we look them up.
983   BarSym.setFlags(BarSym.getFlags() | JITSymbolFlags::Weak);
984 
985   bool BarMaterialized = false;
986   auto MU1 = std::make_unique<SimpleMaterializationUnit>(
987       SymbolFlagsMap({{Foo, FooSym.getFlags()}, {Bar, BarSym.getFlags()}}),
988       [&](MaterializationResponsibility R) {
989         cantFail(R.notifyResolved(SymbolMap({{Foo, FooSym}, {Bar, BarSym}})));
990         cantFail(R.notifyEmitted());
991         BarMaterialized = true;
992       });
993 
994   bool DuplicateBarDiscarded = false;
995   auto MU2 = std::make_unique<SimpleMaterializationUnit>(
996       SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
997       [&](MaterializationResponsibility R) {
998         ADD_FAILURE() << "Attempt to materialize Bar from the wrong unit";
999         R.failMaterialization();
1000       },
1001       nullptr,
1002       [&](const JITDylib &JD, SymbolStringPtr Name) {
1003         EXPECT_EQ(Name, Bar) << "Expected \"Bar\" to be discarded";
1004         DuplicateBarDiscarded = true;
1005       });
1006 
1007   cantFail(JD.define(MU1));
1008   cantFail(JD.define(MU2));
1009 
1010   bool OnCompletionRun = false;
1011 
1012   auto OnCompletion = [&](Expected<SymbolMap> Result) {
1013     cantFail(std::move(Result));
1014     OnCompletionRun = true;
1015   };
1016 
1017   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
1018             SymbolLookupSet(Bar), SymbolState::Ready, std::move(OnCompletion),
1019             NoDependenciesToRegister);
1020 
1021   EXPECT_TRUE(OnCompletionRun) << "OnCompletion not run";
1022   EXPECT_TRUE(BarMaterialized) << "Bar was not materialized at all";
1023   EXPECT_TRUE(DuplicateBarDiscarded)
1024       << "Duplicate bar definition not discarded";
1025 }
1026 
1027 TEST_F(CoreAPIsStandardTest, DefineMaterializingSymbol) {
1028   bool ExpectNoMoreMaterialization = false;
1029   ES.setDispatchMaterialization([&](std::unique_ptr<MaterializationUnit> MU,
1030                                     MaterializationResponsibility MR) {
1031     if (ExpectNoMoreMaterialization)
1032       ADD_FAILURE() << "Unexpected materialization";
1033     MU->materialize(std::move(MR));
1034   });
1035 
1036   auto MU = std::make_unique<SimpleMaterializationUnit>(
1037       SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
1038       [&](MaterializationResponsibility R) {
1039         cantFail(
1040             R.defineMaterializing(SymbolFlagsMap({{Bar, BarSym.getFlags()}})));
1041         cantFail(R.notifyResolved(SymbolMap({{Foo, FooSym}, {Bar, BarSym}})));
1042         cantFail(R.notifyEmitted());
1043       });
1044 
1045   cantFail(JD.define(MU));
1046   cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), Foo));
1047 
1048   // Assert that materialization is complete by now.
1049   ExpectNoMoreMaterialization = true;
1050 
1051   // Look up bar to verify that no further materialization happens.
1052   auto BarResult = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), Bar));
1053   EXPECT_EQ(BarResult.getAddress(), BarSym.getAddress())
1054       << "Expected Bar == BarSym";
1055 }
1056 
1057 TEST_F(CoreAPIsStandardTest, GeneratorTest) {
1058   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
1059 
1060   class TestGenerator : public JITDylib::DefinitionGenerator {
1061   public:
1062     TestGenerator(SymbolMap Symbols) : Symbols(std::move(Symbols)) {}
1063     Error tryToGenerate(LookupKind K, JITDylib &JD,
1064                         JITDylibLookupFlags JDLookupFlags,
1065                         const SymbolLookupSet &Names) override {
1066       SymbolMap NewDefs;
1067 
1068       for (const auto &KV : Names) {
1069         const auto &Name = KV.first;
1070         if (Symbols.count(Name))
1071           NewDefs[Name] = Symbols[Name];
1072       }
1073 
1074       cantFail(JD.define(absoluteSymbols(std::move(NewDefs))));
1075       return Error::success();
1076     };
1077 
1078   private:
1079     SymbolMap Symbols;
1080   };
1081 
1082   JD.addGenerator(std::make_unique<TestGenerator>(SymbolMap({{Bar, BarSym}})));
1083 
1084   auto Result = cantFail(
1085       ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet({Foo, Bar})));
1086 
1087   EXPECT_EQ(Result.count(Bar), 1U) << "Expected to find fallback def for 'bar'";
1088   EXPECT_EQ(Result[Bar].getAddress(), BarSym.getAddress())
1089       << "Expected fallback def for Bar to be equal to BarSym";
1090 }
1091 
1092 TEST_F(CoreAPIsStandardTest, FailResolution) {
1093   auto MU = std::make_unique<SimpleMaterializationUnit>(
1094       SymbolFlagsMap({{Foo, JITSymbolFlags::Exported | JITSymbolFlags::Weak},
1095                       {Bar, JITSymbolFlags::Exported | JITSymbolFlags::Weak}}),
1096       [&](MaterializationResponsibility R) {
1097         R.failMaterialization();
1098       });
1099 
1100   cantFail(JD.define(MU));
1101 
1102   SymbolNameSet Names({Foo, Bar});
1103   auto Result = ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet(Names));
1104 
1105   EXPECT_FALSE(!!Result) << "Expected failure";
1106   if (!Result) {
1107     handleAllErrors(
1108         Result.takeError(),
1109         [&](FailedToMaterialize &F) {
1110           EXPECT_TRUE(F.getSymbols().count(&JD))
1111               << "Expected to fail on JITDylib JD";
1112           EXPECT_EQ(F.getSymbols().find(&JD)->second, Names)
1113               << "Expected to fail on symbols in Names";
1114         },
1115         [](ErrorInfoBase &EIB) {
1116           std::string ErrMsg;
1117           {
1118             raw_string_ostream ErrOut(ErrMsg);
1119             EIB.log(ErrOut);
1120           }
1121           ADD_FAILURE() << "Expected a FailedToResolve error. Got:\n" << ErrMsg;
1122         });
1123   }
1124 }
1125 
1126 TEST_F(CoreAPIsStandardTest, FailEmissionAfterResolution) {
1127 
1128   cantFail(JD.define(absoluteSymbols({{Baz, BazSym}})));
1129 
1130   auto MU = std::make_unique<SimpleMaterializationUnit>(
1131       SymbolFlagsMap({{Foo, FooSym.getFlags()}, {Bar, BarSym.getFlags()}}),
1132       [&](MaterializationResponsibility R) {
1133         cantFail(R.notifyResolved(SymbolMap({{Foo, FooSym}, {Bar, BarSym}})));
1134 
1135         ES.lookup(
1136             LookupKind::Static, makeJITDylibSearchOrder(&JD),
1137             SymbolLookupSet({Baz}), SymbolState::Resolved,
1138             [&R](Expected<SymbolMap> Result) {
1139               // Called when "baz" is resolved. We don't actually depend
1140               // on or care about baz, but use it to trigger failure of
1141               // this materialization before Baz has been finalized in
1142               // order to test that error propagation is correct in this
1143               // scenario.
1144               cantFail(std::move(Result));
1145               R.failMaterialization();
1146             },
1147             [&](const SymbolDependenceMap &Deps) {
1148               R.addDependenciesForAll(Deps);
1149             });
1150       });
1151 
1152   cantFail(JD.define(MU));
1153 
1154   auto Result =
1155       ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet({Foo, Bar}));
1156 
1157   EXPECT_THAT_EXPECTED(std::move(Result), Failed())
1158       << "Unexpected success while trying to test error propagation";
1159 }
1160 
1161 TEST_F(CoreAPIsStandardTest, FailAfterPartialResolution) {
1162 
1163   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
1164 
1165   // Fail materialization of bar.
1166   auto BarMU = std::make_unique<SimpleMaterializationUnit>(
1167       SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
1168       [&](MaterializationResponsibility R) { R.failMaterialization(); });
1169 
1170   cantFail(JD.define(std::move(BarMU)));
1171 
1172   bool QueryHandlerRun = false;
1173   ES.lookup(
1174       LookupKind::Static, makeJITDylibSearchOrder(&JD),
1175       SymbolLookupSet({Foo, Bar}), SymbolState::Resolved,
1176       [&](Expected<SymbolMap> Result) {
1177         EXPECT_THAT_EXPECTED(std::move(Result), Failed())
1178             << "Expected query to fail";
1179         QueryHandlerRun = true;
1180       },
1181       NoDependenciesToRegister);
1182   EXPECT_TRUE(QueryHandlerRun) << "Query handler never ran";
1183 }
1184 
1185 TEST_F(CoreAPIsStandardTest, TestLookupWithUnthreadedMaterialization) {
1186   auto MU = std::make_unique<SimpleMaterializationUnit>(
1187       SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}),
1188       [&](MaterializationResponsibility R) {
1189         cantFail(R.notifyResolved({{Foo, FooSym}}));
1190         cantFail(R.notifyEmitted());
1191       });
1192 
1193   cantFail(JD.define(MU));
1194 
1195   auto FooLookupResult = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), Foo));
1196 
1197   EXPECT_EQ(FooLookupResult.getAddress(), FooSym.getAddress())
1198       << "lookup returned an incorrect address";
1199   EXPECT_EQ(FooLookupResult.getFlags(), FooSym.getFlags())
1200       << "lookup returned incorrect flags";
1201 }
1202 
1203 TEST_F(CoreAPIsStandardTest, TestLookupWithThreadedMaterialization) {
1204 #if LLVM_ENABLE_THREADS
1205 
1206   std::thread MaterializationThread;
1207   ES.setDispatchMaterialization([&](std::unique_ptr<MaterializationUnit> MU,
1208                                     MaterializationResponsibility MR) {
1209     auto SharedMR =
1210         std::make_shared<MaterializationResponsibility>(std::move(MR));
1211     MaterializationThread =
1212         std::thread([MU = std::move(MU), MR = std::move(SharedMR)] {
1213           MU->materialize(std::move(*MR));
1214         });
1215   });
1216 
1217   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
1218 
1219   auto FooLookupResult = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), Foo));
1220 
1221   EXPECT_EQ(FooLookupResult.getAddress(), FooSym.getAddress())
1222       << "lookup returned an incorrect address";
1223   EXPECT_EQ(FooLookupResult.getFlags(), FooSym.getFlags())
1224       << "lookup returned incorrect flags";
1225   MaterializationThread.join();
1226 #endif
1227 }
1228 
1229 TEST_F(CoreAPIsStandardTest, TestGetRequestedSymbolsAndReplace) {
1230   // Test that GetRequestedSymbols returns the set of symbols that currently
1231   // have pending queries, and test that MaterializationResponsibility's
1232   // replace method can be used to return definitions to the JITDylib in a new
1233   // MaterializationUnit.
1234   SymbolNameSet Names({Foo, Bar});
1235 
1236   bool FooMaterialized = false;
1237   bool BarMaterialized = false;
1238 
1239   auto MU = std::make_unique<SimpleMaterializationUnit>(
1240       SymbolFlagsMap({{Foo, FooSym.getFlags()}, {Bar, BarSym.getFlags()}}),
1241       [&](MaterializationResponsibility R) {
1242         auto Requested = R.getRequestedSymbols();
1243         EXPECT_EQ(Requested.size(), 1U) << "Expected one symbol requested";
1244         EXPECT_EQ(*Requested.begin(), Foo) << "Expected \"Foo\" requested";
1245 
1246         auto NewMU = std::make_unique<SimpleMaterializationUnit>(
1247             SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
1248             [&](MaterializationResponsibility R2) {
1249               cantFail(R2.notifyResolved(SymbolMap({{Bar, BarSym}})));
1250               cantFail(R2.notifyEmitted());
1251               BarMaterialized = true;
1252             });
1253 
1254         R.replace(std::move(NewMU));
1255 
1256         cantFail(R.notifyResolved(SymbolMap({{Foo, FooSym}})));
1257         cantFail(R.notifyEmitted());
1258 
1259         FooMaterialized = true;
1260       });
1261 
1262   cantFail(JD.define(MU));
1263 
1264   EXPECT_FALSE(FooMaterialized) << "Foo should not be materialized yet";
1265   EXPECT_FALSE(BarMaterialized) << "Bar should not be materialized yet";
1266 
1267   auto FooSymResult = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), Foo));
1268   EXPECT_EQ(FooSymResult.getAddress(), FooSym.getAddress())
1269       << "Address mismatch for Foo";
1270 
1271   EXPECT_TRUE(FooMaterialized) << "Foo should be materialized now";
1272   EXPECT_FALSE(BarMaterialized) << "Bar still should not be materialized";
1273 
1274   auto BarSymResult = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), Bar));
1275   EXPECT_EQ(BarSymResult.getAddress(), BarSym.getAddress())
1276       << "Address mismatch for Bar";
1277   EXPECT_TRUE(BarMaterialized) << "Bar should be materialized now";
1278 }
1279 
1280 TEST_F(CoreAPIsStandardTest, TestMaterializationResponsibilityDelegation) {
1281   auto MU = std::make_unique<SimpleMaterializationUnit>(
1282       SymbolFlagsMap({{Foo, FooSym.getFlags()}, {Bar, BarSym.getFlags()}}),
1283       [&](MaterializationResponsibility R) {
1284         auto R2 = R.delegate({Bar});
1285 
1286         cantFail(R.notifyResolved({{Foo, FooSym}}));
1287         cantFail(R.notifyEmitted());
1288         cantFail(R2.notifyResolved({{Bar, BarSym}}));
1289         cantFail(R2.notifyEmitted());
1290       });
1291 
1292   cantFail(JD.define(MU));
1293 
1294   auto Result =
1295       ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet({Foo, Bar}));
1296 
1297   EXPECT_TRUE(!!Result) << "Result should be a success value";
1298   EXPECT_EQ(Result->count(Foo), 1U) << "\"Foo\" entry missing";
1299   EXPECT_EQ(Result->count(Bar), 1U) << "\"Bar\" entry missing";
1300   EXPECT_EQ((*Result)[Foo].getAddress(), FooSym.getAddress())
1301       << "Address mismatch for \"Foo\"";
1302   EXPECT_EQ((*Result)[Bar].getAddress(), BarSym.getAddress())
1303       << "Address mismatch for \"Bar\"";
1304 }
1305 
1306 TEST_F(CoreAPIsStandardTest, TestMaterializeWeakSymbol) {
1307   // Confirm that once a weak definition is selected for materialization it is
1308   // treated as strong.
1309   JITSymbolFlags WeakExported = JITSymbolFlags::Exported;
1310   WeakExported &= JITSymbolFlags::Weak;
1311 
1312   std::unique_ptr<MaterializationResponsibility> FooResponsibility;
1313   auto MU = std::make_unique<SimpleMaterializationUnit>(
1314       SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
1315       [&](MaterializationResponsibility R) {
1316         FooResponsibility =
1317             std::make_unique<MaterializationResponsibility>(std::move(R));
1318       });
1319 
1320   cantFail(JD.define(MU));
1321   auto OnCompletion = [](Expected<SymbolMap> Result) {
1322     cantFail(std::move(Result));
1323   };
1324 
1325   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
1326             SymbolLookupSet({Foo}), SymbolState::Ready, std::move(OnCompletion),
1327             NoDependenciesToRegister);
1328 
1329   auto MU2 = std::make_unique<SimpleMaterializationUnit>(
1330       SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}),
1331       [](MaterializationResponsibility R) {
1332         llvm_unreachable("This unit should never be materialized");
1333       });
1334 
1335   auto Err = JD.define(MU2);
1336   EXPECT_TRUE(!!Err) << "Expected failure value";
1337   EXPECT_TRUE(Err.isA<DuplicateDefinition>())
1338       << "Expected a duplicate definition error";
1339   consumeError(std::move(Err));
1340 
1341   // No dependencies registered, can't fail:
1342   cantFail(FooResponsibility->notifyResolved(SymbolMap({{Foo, FooSym}})));
1343   cantFail(FooResponsibility->notifyEmitted());
1344 }
1345 
1346 static bool linkOrdersEqual(const std::vector<std::shared_ptr<JITDylib>> &LHS,
1347                             ArrayRef<JITDylib *> RHS) {
1348   if (LHS.size() != RHS.size())
1349     return false;
1350   auto *RHSE = RHS.begin();
1351   for (auto &LHSE : LHS)
1352     if (LHSE.get() != *RHSE)
1353       return false;
1354     else
1355       ++RHSE;
1356   return true;
1357 }
1358 
1359 TEST(JITDylibTest, GetDFSLinkOrderTree) {
1360   // Test that DFS ordering behaves as expected when the linkage relationships
1361   // form a tree.
1362 
1363   ExecutionSession ES;
1364 
1365   auto &LibA = ES.createBareJITDylib("A");
1366   auto &LibB = ES.createBareJITDylib("B");
1367   auto &LibC = ES.createBareJITDylib("C");
1368   auto &LibD = ES.createBareJITDylib("D");
1369   auto &LibE = ES.createBareJITDylib("E");
1370   auto &LibF = ES.createBareJITDylib("F");
1371 
1372   // Linkage relationships:
1373   // A --- B -- D
1374   //  \      \- E
1375   //    \- C -- F
1376   LibA.setLinkOrder(makeJITDylibSearchOrder({&LibB, &LibC}));
1377   LibB.setLinkOrder(makeJITDylibSearchOrder({&LibD, &LibE}));
1378   LibC.setLinkOrder(makeJITDylibSearchOrder({&LibF}));
1379 
1380   auto DFSOrderFromB = JITDylib::getDFSLinkOrder({LibB.shared_from_this()});
1381   EXPECT_TRUE(linkOrdersEqual(DFSOrderFromB, {&LibB, &LibD, &LibE}))
1382       << "Incorrect DFS link order for LibB";
1383 
1384   auto DFSOrderFromA = JITDylib::getDFSLinkOrder({LibA.shared_from_this()});
1385   EXPECT_TRUE(linkOrdersEqual(DFSOrderFromA,
1386                               {&LibA, &LibB, &LibD, &LibE, &LibC, &LibF}))
1387       << "Incorrect DFS link order for libA";
1388 
1389   auto DFSOrderFromAB = JITDylib::getDFSLinkOrder(
1390       {LibA.shared_from_this(), LibB.shared_from_this()});
1391   EXPECT_TRUE(linkOrdersEqual(DFSOrderFromAB,
1392                               {&LibA, &LibB, &LibD, &LibE, &LibC, &LibF}))
1393       << "Incorrect DFS link order for { libA, libB }";
1394 
1395   auto DFSOrderFromBA = JITDylib::getDFSLinkOrder(
1396       {LibB.shared_from_this(), LibA.shared_from_this()});
1397   EXPECT_TRUE(linkOrdersEqual(DFSOrderFromBA,
1398                               {&LibB, &LibD, &LibE, &LibA, &LibC, &LibF}))
1399       << "Incorrect DFS link order for { libB, libA }";
1400 }
1401 
1402 TEST(JITDylibTest, GetDFSLinkOrderDiamond) {
1403   // Test that DFS ordering behaves as expected when the linkage relationships
1404   // contain a diamond.
1405 
1406   ExecutionSession ES;
1407   auto &LibA = ES.createBareJITDylib("A");
1408   auto &LibB = ES.createBareJITDylib("B");
1409   auto &LibC = ES.createBareJITDylib("C");
1410   auto &LibD = ES.createBareJITDylib("D");
1411 
1412   // Linkage relationships:
1413   // A -- B --- D
1414   //  \-- C --/
1415   LibA.setLinkOrder(makeJITDylibSearchOrder({&LibB, &LibC}));
1416   LibB.setLinkOrder(makeJITDylibSearchOrder({&LibD}));
1417   LibC.setLinkOrder(makeJITDylibSearchOrder({&LibD}));
1418 
1419   auto DFSOrderFromA = JITDylib::getDFSLinkOrder({LibA.shared_from_this()});
1420   EXPECT_TRUE(linkOrdersEqual(DFSOrderFromA, {&LibA, &LibB, &LibD, &LibC}))
1421       << "Incorrect DFS link order for libA";
1422 }
1423 
1424 TEST(JITDylibTest, GetDFSLinkOrderCycle) {
1425   // Test that DFS ordering behaves as expected when the linkage relationships
1426   // contain a cycle.
1427 
1428   ExecutionSession ES;
1429   auto &LibA = ES.createBareJITDylib("A");
1430   auto &LibB = ES.createBareJITDylib("B");
1431   auto &LibC = ES.createBareJITDylib("C");
1432 
1433   // Linkage relationships:
1434   // A -- B --- C -- A
1435   LibA.setLinkOrder(makeJITDylibSearchOrder({&LibB}));
1436   LibB.setLinkOrder(makeJITDylibSearchOrder({&LibC}));
1437   LibC.setLinkOrder(makeJITDylibSearchOrder({&LibA}));
1438 
1439   auto DFSOrderFromA = JITDylib::getDFSLinkOrder({LibA.shared_from_this()});
1440   EXPECT_TRUE(linkOrdersEqual(DFSOrderFromA, {&LibA, &LibB, &LibC}))
1441       << "Incorrect DFS link order for libA";
1442 
1443   auto DFSOrderFromB = JITDylib::getDFSLinkOrder({LibB.shared_from_this()});
1444   EXPECT_TRUE(linkOrdersEqual(DFSOrderFromB, {&LibB, &LibC, &LibA}))
1445       << "Incorrect DFS link order for libB";
1446 
1447   auto DFSOrderFromC = JITDylib::getDFSLinkOrder({LibC.shared_from_this()});
1448   EXPECT_TRUE(linkOrdersEqual(DFSOrderFromC, {&LibC, &LibA, &LibB}))
1449       << "Incorrect DFS link order for libC";
1450 }
1451 
1452 } // namespace
1453