xref: /llvm-project/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp (revision 08c1a6b3e181c3af019b18489139bfe4b03d9d08)
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/ADT/ScopeExit.h"
11 #include "llvm/Config/llvm-config.h"
12 #include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
13 #include "llvm/ExecutionEngine/Orc/Core.h"
14 #include "llvm/ExecutionEngine/Orc/Shared/OrcError.h"
15 #include "llvm/Testing/Support/Error.h"
16 
17 #include <deque>
18 #include <set>
19 #include <thread>
20 
21 using namespace llvm;
22 using namespace llvm::orc;
23 
24 class CoreAPIsStandardTest : public CoreAPIsBasedStandardTest {};
25 
26 namespace {
27 
28 class CustomError : public ErrorInfo<CustomError> {
29 public:
30   static char ID;
31   void log(raw_ostream &OS) const override { OS << "CustomError"; }
32   std::error_code convertToErrorCode() const override { return {}; }
33 };
34 char CustomError::ID = 0;
35 
36 TEST_F(CoreAPIsStandardTest, ErrorReporter) {
37   // Check that errors reported via ExecutionSession::reportError are sent to
38   // the registered error reporter, and that the error reporter can hold
39   // uniquely owned state.
40 
41   Error ReportedError = Error::success();
42 
43   ES.setErrorReporter(
44       // Make sure error reporter can capture uniquely-owned state.
45       [&, State = std::make_unique<int>(42)](Error Err) {
46         ReportedError = joinErrors(std::move(Err), std::move(ReportedError));
47       });
48 
49   ES.reportError(make_error<CustomError>());
50 
51   EXPECT_THAT_ERROR(std::move(ReportedError), Failed<CustomError>());
52 }
53 
54 TEST_F(CoreAPIsStandardTest, JITDylibAddToLinkOrder) {
55   // Check that the JITDylib::addToLinkOrder methods behave as expected.
56   auto &JD2 = ES.createBareJITDylib("JD2");
57   auto &JD3 = ES.createBareJITDylib("JD3");
58 
59   JD.addToLinkOrder(JD2);
60   JD.withLinkOrderDo([&](const JITDylibSearchOrder &SO) {
61     EXPECT_EQ(SO.size(), 2U);
62     EXPECT_EQ(SO[0].first, &JD);
63     EXPECT_EQ(SO[1].first, &JD2);
64   });
65 
66   JD.addToLinkOrder(makeJITDylibSearchOrder({&JD2, &JD3}));
67   JD.withLinkOrderDo([&](const JITDylibSearchOrder &SO) {
68     // JD2 was already in the search order, so we expect just one extra item
69     // here.
70     EXPECT_EQ(SO.size(), 3U);
71     EXPECT_EQ(SO[0].first, &JD);
72     EXPECT_EQ(SO[1].first, &JD2);
73     EXPECT_EQ(SO[2].first, &JD3);
74   });
75 }
76 
77 TEST_F(CoreAPIsStandardTest, BasicSuccessfulLookup) {
78   bool OnCompletionRun = false;
79 
80   auto OnCompletion = [&](Expected<SymbolMap> Result) {
81     EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error";
82     auto &Resolved = *Result;
83     auto I = Resolved.find(Foo);
84     EXPECT_NE(I, Resolved.end()) << "Could not find symbol definition";
85     EXPECT_EQ(I->second.getAddress(), FooAddr)
86         << "Resolution returned incorrect result";
87     OnCompletionRun = true;
88   };
89 
90   std::unique_ptr<MaterializationResponsibility> FooMR;
91 
92   cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
93       SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
94       [&](std::unique_ptr<MaterializationResponsibility> R) {
95         FooMR = std::move(R);
96       })));
97 
98   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
99             SymbolLookupSet(Foo), SymbolState::Ready, OnCompletion,
100             NoDependenciesToRegister);
101 
102   EXPECT_FALSE(OnCompletionRun) << "Should not have been resolved yet";
103 
104   cantFail(FooMR->notifyResolved({{Foo, FooSym}}));
105 
106   EXPECT_FALSE(OnCompletionRun) << "Should not be ready yet";
107 
108   cantFail(FooMR->notifyEmitted({}));
109 
110   EXPECT_TRUE(OnCompletionRun) << "Should have been marked ready";
111 }
112 
113 TEST_F(CoreAPIsStandardTest, EmptyLookup) {
114   bool OnCompletionRun = false;
115 
116   auto OnCompletion = [&](Expected<SymbolMap> Result) {
117     cantFail(std::move(Result));
118     OnCompletionRun = true;
119   };
120 
121   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(),
122             SymbolState::Ready, OnCompletion, NoDependenciesToRegister);
123 
124   EXPECT_TRUE(OnCompletionRun) << "OnCompletion was not run for empty query";
125 }
126 
127 TEST_F(CoreAPIsStandardTest, ResolveUnrequestedSymbol) {
128   // Test that all symbols in a MaterializationUnit materialize corretly when
129   // only a subset of symbols is looked up.
130   // The aim here is to ensure that we're not relying on the query to set up
131   // state needed to materialize the unrequested symbols.
132 
133   cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
134       SymbolFlagsMap({{Foo, FooSym.getFlags()}, {Bar, BarSym.getFlags()}}),
135       [this](std::unique_ptr<MaterializationResponsibility> R) {
136         cantFail(R->notifyResolved({{Foo, FooSym}, {Bar, BarSym}}));
137         cantFail(R->notifyEmitted({}));
138       })));
139 
140   auto Result =
141       cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet({Foo})));
142   EXPECT_EQ(Result.size(), 1U) << "Unexpected number of results";
143   EXPECT_TRUE(Result.count(Foo)) << "Expected result for \"Foo\"";
144 }
145 
146 TEST_F(CoreAPIsStandardTest, MaterializationSideEffctsOnlyBasic) {
147   // Test that basic materialization-side-effects-only symbols work as expected:
148   // that they can be emitted without being resolved, that queries for them
149   // don't return until they're emitted, and that they don't appear in query
150   // results.
151 
152   std::unique_ptr<MaterializationResponsibility> FooR;
153   std::optional<SymbolMap> Result;
154 
155   cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
156       SymbolFlagsMap(
157           {{Foo, JITSymbolFlags::Exported |
158                      JITSymbolFlags::MaterializationSideEffectsOnly}}),
159       [&](std::unique_ptr<MaterializationResponsibility> R) {
160         FooR = std::move(R);
161       })));
162 
163   ES.lookup(
164       LookupKind::Static, makeJITDylibSearchOrder(&JD),
165       SymbolLookupSet(Foo, SymbolLookupFlags::WeaklyReferencedSymbol),
166       SymbolState::Ready,
167       [&](Expected<SymbolMap> LookupResult) {
168         if (LookupResult)
169           Result = std::move(*LookupResult);
170         else
171           ADD_FAILURE() << "Unexpected lookup error: "
172                         << toString(LookupResult.takeError());
173       },
174       NoDependenciesToRegister);
175 
176   EXPECT_FALSE(Result) << "Lookup returned unexpectedly";
177   EXPECT_TRUE(FooR) << "Lookup failed to trigger materialization";
178   EXPECT_THAT_ERROR(FooR->notifyEmitted({}), Succeeded())
179       << "Emission of materialization-side-effects-only symbol failed";
180 
181   EXPECT_TRUE(Result) << "Lookup failed to return";
182   EXPECT_TRUE(Result->empty()) << "Lookup result contained unexpected value";
183 }
184 
185 TEST_F(CoreAPIsStandardTest, MaterializationSideEffectsOnlyFailuresPersist) {
186   // Test that when a MaterializationSideEffectsOnly symbol is failed it
187   // remains in the failure state rather than vanishing.
188 
189   cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
190       SymbolFlagsMap(
191           {{Foo, JITSymbolFlags::Exported |
192                      JITSymbolFlags::MaterializationSideEffectsOnly}}),
193       [&](std::unique_ptr<MaterializationResponsibility> R) {
194         R->failMaterialization();
195       })));
196 
197   EXPECT_THAT_EXPECTED(
198       ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet({Foo})),
199       Failed());
200   EXPECT_THAT_EXPECTED(
201       ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet({Foo})),
202       Failed());
203 }
204 
205 TEST_F(CoreAPIsStandardTest, RemoveSymbolsTest) {
206   // Test that:
207   // (1) Missing symbols generate a SymbolsNotFound error.
208   // (2) Materializing symbols generate a SymbolCouldNotBeRemoved error.
209   // (3) Removal of unmaterialized symbols triggers discard on the
210   //     materialization unit.
211   // (4) Removal of symbols destroys empty materialization units.
212   // (5) Removal of materialized symbols works.
213 
214   // Foo will be fully materialized.
215   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
216 
217   // Bar will be unmaterialized.
218   bool BarDiscarded = false;
219   bool BarMaterializerDestructed = false;
220   cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
221       SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
222       [this](std::unique_ptr<MaterializationResponsibility> R) {
223         ADD_FAILURE() << "Unexpected materialization of \"Bar\"";
224         cantFail(R->notifyResolved({{Bar, BarSym}}));
225         cantFail(R->notifyEmitted({}));
226       },
227       nullptr,
228       [&](const JITDylib &JD, const SymbolStringPtr &Name) {
229         EXPECT_EQ(Name, Bar) << "Expected \"Bar\" to be discarded";
230         if (Name == Bar)
231           BarDiscarded = true;
232       },
233       [&]() { BarMaterializerDestructed = true; })));
234 
235   // Baz will be in the materializing state initially, then
236   // materialized for the final removal attempt.
237   std::unique_ptr<MaterializationResponsibility> BazR;
238   cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
239       SymbolFlagsMap({{Baz, BazSym.getFlags()}}),
240       [&](std::unique_ptr<MaterializationResponsibility> R) {
241         BazR = std::move(R);
242       },
243       nullptr,
244       [](const JITDylib &JD, const SymbolStringPtr &Name) {
245         ADD_FAILURE() << "\"Baz\" discarded unexpectedly";
246       })));
247 
248   bool OnCompletionRun = false;
249   ES.lookup(
250       LookupKind::Static, makeJITDylibSearchOrder(&JD),
251       SymbolLookupSet({Foo, Baz}), SymbolState::Ready,
252       [&](Expected<SymbolMap> Result) {
253         cantFail(Result.takeError());
254         OnCompletionRun = true;
255       },
256       NoDependenciesToRegister);
257 
258   {
259     // Attempt 1: Search for a missing symbol, Qux.
260     auto Err = JD.remove({Foo, Bar, Baz, Qux});
261     EXPECT_TRUE(!!Err) << "Expected failure";
262     EXPECT_TRUE(Err.isA<SymbolsNotFound>())
263         << "Expected a SymbolsNotFound error";
264     consumeError(std::move(Err));
265   }
266 
267   {
268     // Attempt 2: Search for a symbol that is still materializing, Baz.
269     auto Err = JD.remove({Foo, Bar, Baz});
270     EXPECT_TRUE(!!Err) << "Expected failure";
271     EXPECT_TRUE(Err.isA<SymbolsCouldNotBeRemoved>())
272         << "Expected a SymbolsNotFound error";
273     consumeError(std::move(Err));
274   }
275 
276   cantFail(BazR->notifyResolved({{Baz, BazSym}}));
277   cantFail(BazR->notifyEmitted({}));
278   {
279     // Attempt 3: Search now that all symbols are fully materialized
280     // (Foo, Baz), or not yet materialized (Bar).
281     auto Err = JD.remove({Foo, Bar, Baz});
282     EXPECT_FALSE(!!Err) << "Expected success";
283   }
284 
285   EXPECT_TRUE(BarDiscarded) << "\"Bar\" should have been discarded";
286   EXPECT_TRUE(BarMaterializerDestructed)
287       << "\"Bar\"'s materializer should have been destructed";
288   EXPECT_TRUE(OnCompletionRun) << "OnCompletion should have been run";
289 }
290 
291 TEST_F(CoreAPIsStandardTest, DiscardInitSymbol) {
292   SymbolStringPtr ForwardedDiscardSym = nullptr;
293 
294   auto MU = std::make_unique<SimpleMaterializationUnit>(
295       SymbolFlagsMap({{Foo, FooSym.getFlags()}, {Bar, BarSym.getFlags()}}),
296       [](std::unique_ptr<MaterializationResponsibility> R) {
297         llvm_unreachable("Materialize called unexpectedly?");
298       },
299       Foo,
300       [&](const JITDylib &, SymbolStringPtr Sym) {
301         ForwardedDiscardSym = std::move(Sym);
302       });
303 
304   MU->doDiscard(JD, Foo);
305 
306   EXPECT_EQ(ForwardedDiscardSym, Foo);
307   EXPECT_EQ(MU->getSymbols().size(), 1U);
308   EXPECT_TRUE(MU->getSymbols().count(Bar));
309   EXPECT_EQ(MU->getInitializerSymbol(), nullptr);
310 }
311 
312 TEST_F(CoreAPIsStandardTest, LookupWithHiddenSymbols) {
313   auto BarHiddenFlags = BarSym.getFlags() & ~JITSymbolFlags::Exported;
314   auto BarHiddenSym = ExecutorSymbolDef(BarSym.getAddress(), BarHiddenFlags);
315 
316   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarHiddenSym}})));
317 
318   auto &JD2 = ES.createBareJITDylib("JD2");
319   cantFail(JD2.define(absoluteSymbols({{Bar, QuxSym}})));
320 
321   /// Try a blocking lookup.
322   auto Result = cantFail(ES.lookup(makeJITDylibSearchOrder({&JD, &JD2}),
323                                    SymbolLookupSet({Foo, Bar})));
324 
325   EXPECT_EQ(Result.size(), 2U) << "Unexpected number of results";
326   EXPECT_EQ(Result.count(Foo), 1U) << "Missing result for \"Foo\"";
327   EXPECT_EQ(Result.count(Bar), 1U) << "Missing result for \"Bar\"";
328   EXPECT_EQ(Result[Bar].getAddress(), QuxSym.getAddress())
329       << "Wrong result for \"Bar\"";
330 }
331 
332 TEST_F(CoreAPIsStandardTest, LookupFlagsTest) {
333   // Test that lookupFlags works on a predefined symbol, and does not trigger
334   // materialization of a lazy symbol. Make the lazy symbol weak to test that
335   // the weak flag is propagated correctly.
336 
337   BarSym.setFlags(static_cast<JITSymbolFlags::FlagNames>(
338       JITSymbolFlags::Exported | JITSymbolFlags::Weak));
339   auto MU = std::make_unique<SimpleMaterializationUnit>(
340       SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
341       [](std::unique_ptr<MaterializationResponsibility> R) {
342         llvm_unreachable("Symbol materialized on flags lookup");
343       });
344 
345   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
346   cantFail(JD.define(std::move(MU)));
347 
348   auto SymbolFlags = cantFail(ES.lookupFlags(
349       LookupKind::Static,
350       {{&JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
351       SymbolLookupSet({Foo, Bar, Baz},
352                       SymbolLookupFlags::WeaklyReferencedSymbol)));
353 
354   EXPECT_EQ(SymbolFlags.size(), 2U)
355       << "Returned symbol flags contains unexpected results";
356   EXPECT_EQ(SymbolFlags.count(Foo), 1U) << "Missing lookupFlags result for Foo";
357   EXPECT_EQ(SymbolFlags[Foo], FooSym.getFlags())
358       << "Incorrect flags returned for Foo";
359   EXPECT_EQ(SymbolFlags.count(Bar), 1U)
360       << "Missing  lookupFlags result for Bar";
361   EXPECT_EQ(SymbolFlags[Bar], BarSym.getFlags())
362       << "Incorrect flags returned for Bar";
363 }
364 
365 TEST_F(CoreAPIsStandardTest, LookupWithGeneratorFailure) {
366 
367   class BadGenerator : public DefinitionGenerator {
368   public:
369     Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &,
370                         JITDylibLookupFlags, const SymbolLookupSet &) override {
371       return make_error<StringError>("BadGenerator", inconvertibleErrorCode());
372     }
373   };
374 
375   JD.addGenerator(std::make_unique<BadGenerator>());
376 
377   EXPECT_THAT_ERROR(
378       ES.lookupFlags(LookupKind::Static,
379                      {{&JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
380                      SymbolLookupSet(Foo))
381           .takeError(),
382       Failed<StringError>())
383       << "Generator failure did not propagate through lookupFlags";
384 
385   EXPECT_THAT_ERROR(
386       ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo)).takeError(),
387       Failed<StringError>())
388       << "Generator failure did not propagate through lookup";
389 }
390 
391 TEST_F(CoreAPIsStandardTest, TestBasicAliases) {
392   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarSym}})));
393   cantFail(JD.define(symbolAliases({{Baz, {Foo, JITSymbolFlags::Exported}},
394                                     {Qux, {Bar, JITSymbolFlags::Weak}}})));
395   cantFail(JD.define(absoluteSymbols({{Qux, QuxSym}})));
396 
397   auto Result =
398       ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet({Baz, Qux}));
399   EXPECT_TRUE(!!Result) << "Unexpected lookup failure";
400   EXPECT_EQ(Result->count(Baz), 1U) << "No result for \"baz\"";
401   EXPECT_EQ(Result->count(Qux), 1U) << "No result for \"qux\"";
402   EXPECT_EQ((*Result)[Baz].getAddress(), FooSym.getAddress())
403       << "\"Baz\"'s address should match \"Foo\"'s";
404   EXPECT_EQ((*Result)[Qux].getAddress(), QuxSym.getAddress())
405       << "The \"Qux\" alias should have been overriden";
406 }
407 
408 TEST_F(CoreAPIsStandardTest, TestChainedAliases) {
409   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
410   cantFail(JD.define(symbolAliases(
411       {{Baz, {Bar, BazSym.getFlags()}}, {Bar, {Foo, BarSym.getFlags()}}})));
412 
413   auto Result =
414       ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet({Bar, Baz}));
415   EXPECT_TRUE(!!Result) << "Unexpected lookup failure";
416   EXPECT_EQ(Result->count(Bar), 1U) << "No result for \"bar\"";
417   EXPECT_EQ(Result->count(Baz), 1U) << "No result for \"baz\"";
418   EXPECT_EQ((*Result)[Bar].getAddress(), FooSym.getAddress())
419       << "\"Bar\"'s address should match \"Foo\"'s";
420   EXPECT_EQ((*Result)[Baz].getAddress(), FooSym.getAddress())
421       << "\"Baz\"'s address should match \"Foo\"'s";
422 }
423 
424 TEST_F(CoreAPIsStandardTest, TestBasicReExports) {
425   // Test that the basic use case of re-exporting a single symbol from another
426   // JITDylib works.
427   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
428 
429   auto &JD2 = ES.createBareJITDylib("JD2");
430 
431   cantFail(JD2.define(reexports(JD, {{Bar, {Foo, BarSym.getFlags()}}})));
432 
433   auto Result = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD2), Bar));
434   EXPECT_EQ(Result.getAddress(), FooSym.getAddress())
435       << "Re-export Bar for symbol Foo should match FooSym's address";
436 }
437 
438 TEST_F(CoreAPIsStandardTest, TestThatReExportsDontUnnecessarilyMaterialize) {
439   // Test that re-exports do not materialize symbols that have not been queried
440   // for.
441   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
442 
443   bool BarMaterialized = false;
444   auto BarMU = std::make_unique<SimpleMaterializationUnit>(
445       SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
446       [&](std::unique_ptr<MaterializationResponsibility> R) {
447         BarMaterialized = true;
448         cantFail(R->notifyResolved({{Bar, BarSym}}));
449         cantFail(R->notifyEmitted({}));
450       });
451 
452   cantFail(JD.define(BarMU));
453 
454   auto &JD2 = ES.createBareJITDylib("JD2");
455 
456   cantFail(JD2.define(reexports(
457       JD, {{Baz, {Foo, BazSym.getFlags()}}, {Qux, {Bar, QuxSym.getFlags()}}})));
458 
459   auto Result = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD2), Baz));
460   EXPECT_EQ(Result.getAddress(), FooSym.getAddress())
461       << "Re-export Baz for symbol Foo should match FooSym's address";
462 
463   EXPECT_FALSE(BarMaterialized) << "Bar should not have been materialized";
464 }
465 
466 TEST_F(CoreAPIsStandardTest, TestReexportsGenerator) {
467   // Test that a re-exports generator can dynamically generate reexports.
468 
469   auto &JD2 = ES.createBareJITDylib("JD2");
470   cantFail(JD2.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarSym}})));
471 
472   auto Filter = [this](SymbolStringPtr Name) { return Name != Bar; };
473 
474   JD.addGenerator(std::make_unique<ReexportsGenerator>(
475       JD2, JITDylibLookupFlags::MatchExportedSymbolsOnly, Filter));
476 
477   auto Flags = cantFail(ES.lookupFlags(
478       LookupKind::Static,
479       {{&JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
480       SymbolLookupSet({Foo, Bar, Baz},
481                       SymbolLookupFlags::WeaklyReferencedSymbol)));
482   EXPECT_EQ(Flags.size(), 1U) << "Unexpected number of results";
483   EXPECT_EQ(Flags[Foo], FooSym.getFlags()) << "Unexpected flags for Foo";
484 
485   auto Result = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), Foo));
486 
487   EXPECT_EQ(Result.getAddress(), FooSym.getAddress())
488       << "Incorrect reexported symbol address";
489 }
490 
491 TEST_F(CoreAPIsStandardTest, TestTrivialCircularDependency) {
492   std::unique_ptr<MaterializationResponsibility> FooR;
493   auto FooMU = std::make_unique<SimpleMaterializationUnit>(
494       SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
495       [&](std::unique_ptr<MaterializationResponsibility> R) {
496         FooR = std::move(R);
497       });
498 
499   cantFail(JD.define(FooMU));
500 
501   bool FooReady = false;
502   auto OnCompletion = [&](Expected<SymbolMap> Result) {
503     cantFail(std::move(Result));
504     FooReady = true;
505   };
506 
507   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
508             SymbolLookupSet({Foo}), SymbolState::Ready, OnCompletion,
509             NoDependenciesToRegister);
510 
511   EXPECT_THAT_ERROR(FooR->notifyResolved({{Foo, FooSym}}), Succeeded())
512       << "No symbols marked failed, but Foo failed to resolve";
513   SymbolDependenceGroup SDG({{Foo}, {{&JD, SymbolNameSet({Foo})}}});
514   EXPECT_THAT_ERROR(FooR->notifyEmitted(SDG), Succeeded())
515       << "No symbols marked failed, but Foo failed to emit";
516 
517   EXPECT_TRUE(FooReady)
518     << "Self-dependency prevented symbol from being marked ready";
519 }
520 
521 TEST_F(CoreAPIsStandardTest, TestCircularDependenceInOneJITDylib) {
522   // Test that a circular symbol dependency between three symbols in a JITDylib
523   // does not prevent any symbol from becoming 'ready' once all symbols are
524   // emitted.
525 
526   std::unique_ptr<MaterializationResponsibility> FooR;
527   std::unique_ptr<MaterializationResponsibility> BarR;
528   std::unique_ptr<MaterializationResponsibility> BazR;
529 
530   // Create a MaterializationUnit for each symbol that moves the
531   // MaterializationResponsibility into one of the locals above.
532   auto FooMU = std::make_unique<SimpleMaterializationUnit>(
533       SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
534       [&](std::unique_ptr<MaterializationResponsibility> R) {
535         FooR = std::move(R);
536       });
537 
538   auto BarMU = std::make_unique<SimpleMaterializationUnit>(
539       SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
540       [&](std::unique_ptr<MaterializationResponsibility> R) {
541         BarR = std::move(R);
542       });
543 
544   auto BazMU = std::make_unique<SimpleMaterializationUnit>(
545       SymbolFlagsMap({{Baz, BazSym.getFlags()}}),
546       [&](std::unique_ptr<MaterializationResponsibility> R) {
547         BazR = std::move(R);
548       });
549 
550   // Define the symbols.
551   cantFail(JD.define(FooMU));
552   cantFail(JD.define(BarMU));
553   cantFail(JD.define(BazMU));
554 
555   // Query each of the symbols to trigger materialization.
556   bool FooResolved = false;
557   bool FooReady = false;
558 
559   auto OnFooResolution = [&](Expected<SymbolMap> Result) {
560     cantFail(std::move(Result));
561     FooResolved = true;
562   };
563 
564   auto OnFooReady = [&](Expected<SymbolMap> Result) {
565     cantFail(std::move(Result));
566     FooReady = true;
567   };
568 
569   // Issue lookups for Foo. Use NoDependenciesToRegister: We're going to add
570   // the dependencies manually below.
571   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
572             SymbolLookupSet(Foo), SymbolState::Resolved,
573             std::move(OnFooResolution), NoDependenciesToRegister);
574 
575   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
576             SymbolLookupSet(Foo), SymbolState::Ready, std::move(OnFooReady),
577             NoDependenciesToRegister);
578 
579   bool BarResolved = false;
580   bool BarReady = false;
581   auto OnBarResolution = [&](Expected<SymbolMap> Result) {
582     cantFail(std::move(Result));
583     BarResolved = true;
584   };
585 
586   auto OnBarReady = [&](Expected<SymbolMap> Result) {
587     cantFail(std::move(Result));
588     BarReady = true;
589   };
590 
591   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
592             SymbolLookupSet(Bar), SymbolState::Resolved,
593             std::move(OnBarResolution), NoDependenciesToRegister);
594 
595   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
596             SymbolLookupSet(Bar), SymbolState::Ready, std::move(OnBarReady),
597             NoDependenciesToRegister);
598 
599   bool BazResolved = false;
600   bool BazReady = false;
601 
602   auto OnBazResolution = [&](Expected<SymbolMap> Result) {
603     cantFail(std::move(Result));
604     BazResolved = true;
605   };
606 
607   auto OnBazReady = [&](Expected<SymbolMap> Result) {
608     cantFail(std::move(Result));
609     BazReady = true;
610   };
611 
612   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
613             SymbolLookupSet(Baz), SymbolState::Resolved,
614             std::move(OnBazResolution), NoDependenciesToRegister);
615 
616   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
617             SymbolLookupSet(Baz), SymbolState::Ready, std::move(OnBazReady),
618             NoDependenciesToRegister);
619 
620   // Check that nothing has been resolved yet.
621   EXPECT_FALSE(FooResolved) << "\"Foo\" should not be resolved yet";
622   EXPECT_FALSE(BarResolved) << "\"Bar\" should not be resolved yet";
623   EXPECT_FALSE(BazResolved) << "\"Baz\" should not be resolved yet";
624 
625   // Resolve the symbols (but do not emit them).
626   EXPECT_THAT_ERROR(FooR->notifyResolved({{Foo, FooSym}}), Succeeded())
627       << "No symbols failed, but Foo failed to resolve";
628   EXPECT_THAT_ERROR(BarR->notifyResolved({{Bar, BarSym}}), Succeeded())
629       << "No symbols failed, but Bar failed to resolve";
630   EXPECT_THAT_ERROR(BazR->notifyResolved({{Baz, BazSym}}), Succeeded())
631       << "No symbols failed, but Baz failed to resolve";
632 
633   // Verify that the symbols have been resolved, but are not ready yet.
634   EXPECT_TRUE(FooResolved) << "\"Foo\" should be resolved now";
635   EXPECT_TRUE(BarResolved) << "\"Bar\" should be resolved now";
636   EXPECT_TRUE(BazResolved) << "\"Baz\" should be resolved now";
637 
638   EXPECT_FALSE(FooReady) << "\"Foo\" should not be ready yet";
639   EXPECT_FALSE(BarReady) << "\"Bar\" should not be ready yet";
640   EXPECT_FALSE(BazReady) << "\"Baz\" should not be ready yet";
641 
642   // Emit two of the symbols.
643   {
644     SymbolDependenceGroup FooDeps({{Foo}, {{&JD, {Foo, Bar}}}});
645     EXPECT_THAT_ERROR(FooR->notifyEmitted(FooDeps), Succeeded())
646         << "No symbols failed, but Foo failed to emit";
647 
648     SymbolDependenceGroup BarDeps({{Bar}, {{&JD, {Bar, Baz}}}});
649     EXPECT_THAT_ERROR(BarR->notifyEmitted(BarDeps), Succeeded())
650         << "No symbols failed, but Bar failed to emit";
651   }
652 
653   // Verify that nothing is ready until the circular dependence is resolved.
654   EXPECT_FALSE(FooReady) << "\"Foo\" still should not be ready";
655   EXPECT_FALSE(BarReady) << "\"Bar\" still should not be ready";
656   EXPECT_FALSE(BazReady) << "\"Baz\" still should not be ready";
657 
658   // Emit the last symbol.
659   {
660     SymbolDependenceGroup BazDeps({{Baz}, {{&JD, {Baz, Foo}}}});
661     EXPECT_THAT_ERROR(BazR->notifyEmitted(BazDeps), Succeeded())
662         << "No symbols failed, but Baz failed to emit";
663   }
664 
665   // Verify that everything becomes ready once the circular dependence resolved.
666   EXPECT_TRUE(FooReady) << "\"Foo\" should be ready now";
667   EXPECT_TRUE(BarReady) << "\"Bar\" should be ready now";
668   EXPECT_TRUE(BazReady) << "\"Baz\" should be ready now";
669 }
670 
671 TEST_F(CoreAPIsStandardTest, FailureInDependency) {
672   std::unique_ptr<MaterializationResponsibility> FooR;
673   std::unique_ptr<MaterializationResponsibility> BarR;
674 
675   // Create a MaterializationUnit for each symbol that moves the
676   // MaterializationResponsibility into one of the locals above.
677   auto FooMU = std::make_unique<SimpleMaterializationUnit>(
678       SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
679       [&](std::unique_ptr<MaterializationResponsibility> R) {
680         FooR = std::move(R);
681       });
682 
683   auto BarMU = std::make_unique<SimpleMaterializationUnit>(
684       SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
685       [&](std::unique_ptr<MaterializationResponsibility> R) {
686         BarR = std::move(R);
687       });
688 
689   // Define the symbols.
690   cantFail(JD.define(FooMU));
691   cantFail(JD.define(BarMU));
692 
693   bool OnFooReadyRun = false;
694   auto OnFooReady = [&](Expected<SymbolMap> Result) {
695     EXPECT_THAT_EXPECTED(std::move(Result), Failed());
696     OnFooReadyRun = true;
697   };
698 
699   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
700             SymbolLookupSet(Foo), SymbolState::Ready, std::move(OnFooReady),
701             NoDependenciesToRegister);
702 
703   bool OnBarReadyRun = false;
704   auto OnBarReady = [&](Expected<SymbolMap> Result) {
705     EXPECT_THAT_EXPECTED(std::move(Result), Failed());
706     OnBarReadyRun = true;
707   };
708 
709   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
710             SymbolLookupSet(Bar), SymbolState::Ready, std::move(OnBarReady),
711             NoDependenciesToRegister);
712 
713   // Fail bar.
714   BarR->failMaterialization();
715 
716   // Verify that queries on Bar failed, but queries on Foo have not yet.
717   EXPECT_TRUE(OnBarReadyRun) << "Query for \"Bar\" was not run";
718   EXPECT_FALSE(OnFooReadyRun) << "Query for \"Foo\" was run unexpectedly";
719 
720   // Check that we can still resolve Foo (even though it has been failed).
721   EXPECT_THAT_ERROR(FooR->notifyResolved({{Foo, FooSym}}), Succeeded())
722       << "Expected resolution for \"Foo\" to succeed despite error state.";
723 
724   FooR->failMaterialization();
725 
726   // Verify that queries on Foo have now failed.
727   EXPECT_TRUE(OnFooReadyRun) << "Query for \"Foo\" was not run";
728 
729   // Verify that subsequent lookups on Bar and Foo fail.
730   EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Bar}), Failed())
731       << "Lookup on failed symbol should fail";
732 
733   EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Foo}), Failed())
734       << "Lookup on failed symbol should fail";
735 }
736 
737 TEST_F(CoreAPIsStandardTest, AddDependencyOnFailedSymbol) {
738   std::unique_ptr<MaterializationResponsibility> FooR;
739   std::unique_ptr<MaterializationResponsibility> BarR;
740 
741   // Create a MaterializationUnit for each symbol that moves the
742   // MaterializationResponsibility into one of the locals above.
743   auto FooMU = std::make_unique<SimpleMaterializationUnit>(
744       SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
745       [&](std::unique_ptr<MaterializationResponsibility> R) {
746         FooR = std::move(R);
747       });
748 
749   auto BarMU = std::make_unique<SimpleMaterializationUnit>(
750       SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
751       [&](std::unique_ptr<MaterializationResponsibility> R) {
752         BarR = std::move(R);
753       });
754 
755   // Define the symbols.
756   cantFail(JD.define(FooMU));
757   cantFail(JD.define(BarMU));
758 
759   bool OnFooReadyRun = false;
760   auto OnFooReady = [&](Expected<SymbolMap> Result) {
761     EXPECT_THAT_EXPECTED(std::move(Result), Failed());
762     OnFooReadyRun = true;
763   };
764 
765   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
766             SymbolLookupSet(Foo), SymbolState::Ready, std::move(OnFooReady),
767             NoDependenciesToRegister);
768 
769   bool OnBarReadyRun = false;
770   auto OnBarReady = [&](Expected<SymbolMap> Result) {
771     EXPECT_THAT_EXPECTED(std::move(Result), Failed());
772     OnBarReadyRun = true;
773   };
774 
775   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
776             SymbolLookupSet(Bar), SymbolState::Ready, std::move(OnBarReady),
777             NoDependenciesToRegister);
778 
779   // Fail bar.
780   BarR->failMaterialization();
781 
782   // We expect Bar's query to fail immediately, but Foo's query not to have run
783   // yet.
784   EXPECT_TRUE(OnBarReadyRun) << "Query for \"Bar\" was not run";
785   EXPECT_FALSE(OnFooReadyRun) << "Query for \"Foo\" should not have run yet";
786 
787   EXPECT_THAT_ERROR(FooR->notifyResolved({{Foo, FooSym}}), Succeeded())
788       << "Expected resolution for \"Foo\" to succeed.";
789 
790   // Check that emission of Foo fails.
791   {
792     SymbolDependenceGroup FooDeps({{Foo}, {{&JD, {Bar}}}});
793     EXPECT_THAT_ERROR(FooR->notifyEmitted(FooDeps), Failed());
794   }
795 
796   FooR->failMaterialization();
797 
798   // Foo's query should have failed before we return from addDependencies.
799   EXPECT_TRUE(OnFooReadyRun) << "Query for \"Foo\" was not run";
800 
801   // Verify that subsequent lookups on Bar and Foo fail.
802   EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Bar}), Failed())
803       << "Lookup on failed symbol should fail";
804 
805   EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Foo}), Failed())
806       << "Lookup on failed symbol should fail";
807 }
808 
809 TEST_F(CoreAPIsStandardTest, FailAfterMaterialization) {
810   std::unique_ptr<MaterializationResponsibility> FooR;
811   std::unique_ptr<MaterializationResponsibility> BarR;
812 
813   // Create a MaterializationUnit for each symbol that moves the
814   // MaterializationResponsibility into one of the locals above.
815   auto FooMU = std::make_unique<SimpleMaterializationUnit>(
816       SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
817       [&](std::unique_ptr<MaterializationResponsibility> R) {
818         FooR = std::move(R);
819       });
820 
821   auto BarMU = std::make_unique<SimpleMaterializationUnit>(
822       SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
823       [&](std::unique_ptr<MaterializationResponsibility> R) {
824         BarR = std::move(R);
825       });
826 
827   // Define the symbols.
828   cantFail(JD.define(FooMU));
829   cantFail(JD.define(BarMU));
830 
831   bool OnFooReadyRun = false;
832   auto OnFooReady = [&](Expected<SymbolMap> Result) {
833     EXPECT_THAT_EXPECTED(std::move(Result), Failed());
834     OnFooReadyRun = true;
835   };
836 
837   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
838             SymbolLookupSet(Foo), SymbolState::Ready, std::move(OnFooReady),
839             NoDependenciesToRegister);
840 
841   bool OnBarReadyRun = false;
842   auto OnBarReady = [&](Expected<SymbolMap> Result) {
843     EXPECT_THAT_EXPECTED(std::move(Result), Failed());
844     OnBarReadyRun = true;
845   };
846 
847   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
848             SymbolLookupSet(Bar), SymbolState::Ready, std::move(OnBarReady),
849             NoDependenciesToRegister);
850 
851   // Materialize Foo.
852   EXPECT_THAT_ERROR(FooR->notifyResolved({{Foo, FooSym}}), Succeeded())
853       << "Expected resolution for \"Foo\" to succeed.";
854   {
855     SymbolDependenceGroup FooDeps({{Foo}, {{&JD, {Bar}}}});
856     EXPECT_THAT_ERROR(FooR->notifyEmitted(FooDeps), Succeeded())
857         << "Expected emission for \"Foo\" to succeed.";
858   }
859 
860   // Fail bar.
861   BarR->failMaterialization();
862 
863   // Verify that both queries failed.
864   EXPECT_TRUE(OnFooReadyRun) << "Query for Foo did not run";
865   EXPECT_TRUE(OnBarReadyRun) << "Query for Bar did not run";
866 }
867 
868 TEST_F(CoreAPIsStandardTest, FailMaterializerWithUnqueriedSymbols) {
869   // Make sure that symbols with no queries aganist them still
870   // fail correctly.
871 
872   bool MaterializerRun = false;
873   auto MU = std::make_unique<SimpleMaterializationUnit>(
874       SymbolFlagsMap(
875           {{Foo, JITSymbolFlags::Exported}, {Bar, JITSymbolFlags::Exported}}),
876       [&](std::unique_ptr<MaterializationResponsibility> R) {
877         MaterializerRun = true;
878         R->failMaterialization();
879       });
880 
881   cantFail(JD.define(std::move(MU)));
882 
883   // Issue a query for Foo, but not bar.
884   EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Foo}), Failed())
885       << "Expected lookup to fail.";
886 
887   // Check that the materializer (and therefore failMaterialization) ran.
888   EXPECT_TRUE(MaterializerRun) << "Expected materializer to have run by now";
889 
890   // Check that subsequent queries against both symbols fail.
891   EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Foo}), Failed())
892       << "Expected lookup for Foo to fail.";
893   EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Bar}), Failed())
894       << "Expected lookup for Bar to fail.";
895 }
896 
897 TEST_F(CoreAPIsStandardTest, DropMaterializerWhenEmpty) {
898   bool DestructorRun = false;
899 
900   JITSymbolFlags WeakExported(JITSymbolFlags::Exported);
901   WeakExported |= JITSymbolFlags::Weak;
902 
903   auto MU = std::make_unique<SimpleMaterializationUnit>(
904       SymbolFlagsMap({{Foo, WeakExported}, {Bar, WeakExported}}),
905       [](std::unique_ptr<MaterializationResponsibility> R) {
906         llvm_unreachable("Unexpected call to materialize");
907       },
908       nullptr,
909       [&](const JITDylib &JD, SymbolStringPtr Name) {
910         EXPECT_TRUE(Name == Foo || Name == Bar)
911             << "Discard of unexpected symbol?";
912       },
913       [&]() { DestructorRun = true; });
914 
915   cantFail(JD.define(MU));
916 
917   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
918 
919   EXPECT_FALSE(DestructorRun)
920       << "MaterializationUnit should not have been destroyed yet";
921 
922   cantFail(JD.define(absoluteSymbols({{Bar, BarSym}})));
923 
924   EXPECT_TRUE(DestructorRun)
925       << "MaterializationUnit should have been destroyed";
926 }
927 
928 TEST_F(CoreAPIsStandardTest, AddAndMaterializeLazySymbol) {
929   bool FooMaterialized = false;
930   bool BarDiscarded = false;
931 
932   JITSymbolFlags WeakExported(JITSymbolFlags::Exported);
933   WeakExported |= JITSymbolFlags::Weak;
934 
935   auto MU = std::make_unique<SimpleMaterializationUnit>(
936       SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}, {Bar, WeakExported}}),
937       [&](std::unique_ptr<MaterializationResponsibility> R) {
938         assert(BarDiscarded && "Bar should have been discarded by this point");
939         cantFail(R->notifyResolved(SymbolMap({{Foo, FooSym}})));
940         cantFail(R->notifyEmitted({}));
941         FooMaterialized = true;
942       },
943       nullptr,
944       [&](const JITDylib &JD, SymbolStringPtr Name) {
945         EXPECT_EQ(Name, Bar) << "Expected Name to be Bar";
946         BarDiscarded = true;
947       });
948 
949   cantFail(JD.define(MU));
950   cantFail(JD.define(absoluteSymbols({{Bar, BarSym}})));
951 
952   bool OnCompletionRun = false;
953 
954   auto OnCompletion = [&](Expected<SymbolMap> Result) {
955     EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error";
956     auto I = Result->find(Foo);
957     EXPECT_NE(I, Result->end()) << "Could not find symbol definition";
958     EXPECT_EQ(I->second.getAddress(), FooSym.getAddress())
959         << "Resolution returned incorrect result";
960     OnCompletionRun = true;
961   };
962 
963   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
964             SymbolLookupSet(Foo), SymbolState::Ready, std::move(OnCompletion),
965             NoDependenciesToRegister);
966 
967   EXPECT_TRUE(FooMaterialized) << "Foo was not materialized";
968   EXPECT_TRUE(BarDiscarded) << "Bar was not discarded";
969   EXPECT_TRUE(OnCompletionRun) << "OnResolutionCallback was not run";
970 }
971 
972 TEST_F(CoreAPIsStandardTest, TestBasicWeakSymbolMaterialization) {
973   // Test that weak symbols are materialized correctly when we look them up.
974   BarSym.setFlags(BarSym.getFlags() | JITSymbolFlags::Weak);
975 
976   bool BarMaterialized = false;
977   auto MU1 = std::make_unique<SimpleMaterializationUnit>(
978       SymbolFlagsMap({{Foo, FooSym.getFlags()}, {Bar, BarSym.getFlags()}}),
979       [&](std::unique_ptr<MaterializationResponsibility> R) {
980         cantFail(R->notifyResolved(SymbolMap({{Foo, FooSym}, {Bar, BarSym}})));
981         cantFail(R->notifyEmitted({}));
982         BarMaterialized = true;
983       });
984 
985   bool DuplicateBarDiscarded = false;
986   auto MU2 = std::make_unique<SimpleMaterializationUnit>(
987       SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
988       [&](std::unique_ptr<MaterializationResponsibility> R) {
989         ADD_FAILURE() << "Attempt to materialize Bar from the wrong unit";
990         R->failMaterialization();
991       },
992       nullptr,
993       [&](const JITDylib &JD, SymbolStringPtr Name) {
994         EXPECT_EQ(Name, Bar) << "Expected \"Bar\" to be discarded";
995         DuplicateBarDiscarded = true;
996       });
997 
998   cantFail(JD.define(MU1));
999   cantFail(JD.define(MU2));
1000 
1001   bool OnCompletionRun = false;
1002 
1003   auto OnCompletion = [&](Expected<SymbolMap> Result) {
1004     cantFail(std::move(Result));
1005     OnCompletionRun = true;
1006   };
1007 
1008   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
1009             SymbolLookupSet(Bar), SymbolState::Ready, std::move(OnCompletion),
1010             NoDependenciesToRegister);
1011 
1012   EXPECT_TRUE(OnCompletionRun) << "OnCompletion not run";
1013   EXPECT_TRUE(BarMaterialized) << "Bar was not materialized at all";
1014   EXPECT_TRUE(DuplicateBarDiscarded)
1015       << "Duplicate bar definition not discarded";
1016 }
1017 
1018 TEST_F(CoreAPIsStandardTest, RedefineBoundWeakSymbol) {
1019   // Check that redefinition of a bound weak symbol fails.
1020 
1021   JITSymbolFlags WeakExported(JITSymbolFlags::Exported);
1022   WeakExported |= JITSymbolFlags::Weak;
1023 
1024   // Define "Foo" as weak, force materialization.
1025   cantFail(JD.define(absoluteSymbols({{Foo, {FooAddr, WeakExported}}})));
1026   cantFail(ES.lookup({&JD}, Foo));
1027 
1028   // Attempt to redefine "Foo". Expect failure, despite "Foo" being weak,
1029   // since it has already been bound.
1030   EXPECT_THAT_ERROR(JD.define(absoluteSymbols({{Foo, FooSym}})), Failed());
1031 }
1032 
1033 TEST_F(CoreAPIsStandardTest, DefineMaterializingSymbol) {
1034   bool ExpectNoMoreMaterialization = false;
1035   DispatchOverride = [&](std::unique_ptr<Task> T) {
1036     if (ExpectNoMoreMaterialization && isa<MaterializationTask>(*T))
1037       ADD_FAILURE() << "Unexpected materialization";
1038     T->run();
1039   };
1040 
1041   auto MU = std::make_unique<SimpleMaterializationUnit>(
1042       SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
1043       [&](std::unique_ptr<MaterializationResponsibility> R) {
1044         cantFail(
1045             R->defineMaterializing(SymbolFlagsMap({{Bar, BarSym.getFlags()}})));
1046         cantFail(R->notifyResolved(SymbolMap({{Foo, FooSym}, {Bar, BarSym}})));
1047         cantFail(R->notifyEmitted({}));
1048       });
1049 
1050   cantFail(JD.define(MU));
1051   cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), Foo));
1052 
1053   // Assert that materialization is complete by now.
1054   ExpectNoMoreMaterialization = true;
1055 
1056   // Look up bar to verify that no further materialization happens.
1057   auto BarResult = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), Bar));
1058   EXPECT_EQ(BarResult.getAddress(), BarSym.getAddress())
1059       << "Expected Bar == BarSym";
1060 }
1061 
1062 TEST_F(CoreAPIsStandardTest, GeneratorTest) {
1063   ExecutorSymbolDef BazHiddenSym(BazSym.getAddress(),
1064                                  BazSym.getFlags() & ~JITSymbolFlags::Exported);
1065   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}, {Baz, BazHiddenSym}})));
1066 
1067   class TestGenerator : public DefinitionGenerator {
1068   public:
1069     TestGenerator(SymbolMap Symbols) : Symbols(std::move(Symbols)) {}
1070     Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
1071                         JITDylibLookupFlags JDLookupFlags,
1072                         const SymbolLookupSet &Names) override {
1073       SymbolMap NewDefs;
1074 
1075       for (const auto &KV : Names) {
1076         const auto &Name = KV.first;
1077         if (Symbols.count(Name))
1078           NewDefs[Name] = Symbols[Name];
1079       }
1080 
1081       cantFail(JD.define(absoluteSymbols(std::move(NewDefs))));
1082       return Error::success();
1083     };
1084 
1085   private:
1086     SymbolMap Symbols;
1087   };
1088 
1089   JD.addGenerator(std::make_unique<TestGenerator>(
1090       SymbolMap({{Bar, BarSym}, {Baz, BazSym}})));
1091 
1092   auto Result = cantFail(
1093       ES.lookup(makeJITDylibSearchOrder(&JD),
1094                 SymbolLookupSet({Foo, Bar})
1095                     .add(Baz, SymbolLookupFlags::WeaklyReferencedSymbol)));
1096 
1097   EXPECT_EQ(Result.count(Bar), 1U) << "Expected to find fallback def for 'bar'";
1098   EXPECT_EQ(Result[Bar].getAddress(), BarSym.getAddress())
1099       << "Expected fallback def for Bar to be equal to BarSym";
1100 }
1101 
1102 /// By default appends LookupStates to a queue.
1103 /// Behavior can be overridden by setting TryToGenerateOverride.
1104 class SimpleAsyncGenerator : public DefinitionGenerator {
1105 public:
1106   struct SuspendedLookupInfo {
1107     LookupState LS;
1108     LookupKind K;
1109     JITDylibSP JD;
1110     JITDylibLookupFlags JDLookupFlags;
1111     SymbolLookupSet Names;
1112   };
1113 
1114   unique_function<Error(LookupState &, LookupKind, JITDylib &,
1115                         JITDylibLookupFlags, const SymbolLookupSet &)>
1116       TryToGenerateOverride;
1117 
1118   Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
1119                       JITDylibLookupFlags JDLookupFlags,
1120                       const SymbolLookupSet &Names) override {
1121     if (TryToGenerateOverride)
1122       return TryToGenerateOverride(LS, K, JD, JDLookupFlags, Names);
1123     Lookup = SuspendedLookupInfo{std::move(LS), K, &JD, JDLookupFlags, Names};
1124     return Error::success();
1125   }
1126 
1127   SuspendedLookupInfo takeLookup() {
1128     std::optional<SuspendedLookupInfo> Tmp;
1129     std::swap(Tmp, Lookup);
1130     return std::move(*Tmp);
1131   }
1132 
1133   std::optional<SuspendedLookupInfo> Lookup;
1134 };
1135 
1136 TEST_F(CoreAPIsStandardTest, SimpleAsynchronousGeneratorTest) {
1137 
1138   auto &G = JD.addGenerator(std::make_unique<SimpleAsyncGenerator>());
1139 
1140   bool LookupCompleted = false;
1141 
1142   ES.lookup(
1143       LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo),
1144       SymbolState::Ready,
1145       [&](Expected<SymbolMap> Result) {
1146         LookupCompleted = true;
1147         EXPECT_THAT_EXPECTED(Result, Succeeded());
1148         if (Result) {
1149           EXPECT_EQ(*Result, SymbolMap({{Foo, FooSym}}));
1150         }
1151       },
1152       NoDependenciesToRegister);
1153 
1154   EXPECT_FALSE(LookupCompleted);
1155 
1156   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
1157   G.takeLookup().LS.continueLookup(Error::success());
1158 
1159   EXPECT_TRUE(LookupCompleted);
1160 }
1161 
1162 TEST_F(CoreAPIsStandardTest, ErrorFromSuspendedAsynchronousGeneratorTest) {
1163 
1164   auto &G = JD.addGenerator(std::make_unique<SimpleAsyncGenerator>());
1165 
1166   bool LookupCompleted = false;
1167 
1168   ES.lookup(
1169       LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo),
1170       SymbolState::Ready,
1171       [&](Expected<SymbolMap> Result) {
1172         LookupCompleted = true;
1173         EXPECT_THAT_EXPECTED(Result, Failed());
1174       },
1175       NoDependenciesToRegister);
1176 
1177   EXPECT_FALSE(LookupCompleted);
1178 
1179   G.takeLookup().LS.continueLookup(
1180       make_error<StringError>("boom", inconvertibleErrorCode()));
1181 
1182   EXPECT_TRUE(LookupCompleted);
1183 }
1184 
1185 TEST_F(CoreAPIsStandardTest, ErrorFromAutoSuspendedAsynchronousGeneratorTest) {
1186 
1187   auto &G = JD.addGenerator(std::make_unique<SimpleAsyncGenerator>());
1188 
1189   std::atomic_size_t LookupsCompleted = 0;
1190 
1191   ES.lookup(
1192       LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo),
1193       SymbolState::Ready,
1194       [&](Expected<SymbolMap> Result) {
1195         ++LookupsCompleted;
1196         EXPECT_THAT_EXPECTED(Result, Failed());
1197       },
1198       NoDependenciesToRegister);
1199 
1200   EXPECT_EQ(LookupsCompleted, 0U);
1201 
1202   // Suspend the first lookup.
1203   auto LS1 = std::move(G.takeLookup().LS);
1204 
1205   // Start a second lookup that should be auto-suspended.
1206   ES.lookup(
1207       LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo),
1208       SymbolState::Ready,
1209       [&](Expected<SymbolMap> Result) {
1210         ++LookupsCompleted;
1211         EXPECT_THAT_EXPECTED(Result, Failed());
1212       },
1213       NoDependenciesToRegister);
1214 
1215   EXPECT_EQ(LookupsCompleted, 0U);
1216 
1217   // Unsuspend the first lookup.
1218   LS1.continueLookup(make_error<StringError>("boom", inconvertibleErrorCode()));
1219 
1220   // Unsuspend the second.
1221   G.takeLookup().LS.continueLookup(
1222       make_error<StringError>("boom", inconvertibleErrorCode()));
1223 
1224   EXPECT_EQ(LookupsCompleted, 2U);
1225 }
1226 
1227 TEST_F(CoreAPIsStandardTest, BlockedGeneratorAutoSuspensionTest) {
1228   // Test that repeated lookups while a generator is in use cause automatic
1229   // lookup suspension / resumption.
1230 
1231   auto &G = JD.addGenerator(std::make_unique<SimpleAsyncGenerator>());
1232 
1233   bool Lookup1Completed = false;
1234   bool Lookup2Completed = false;
1235   bool Lookup3Completed = false;
1236   bool Lookup4Completed = false;
1237 
1238   // Add lookup 1.
1239   //
1240   // Tests that tryToGenerate-suspended lookups resume auto-suspended lookups
1241   // when the tryToGenerate-suspended lookup continues (i.e. the call to
1242   // OL_resumeLookupAfterGeneration at the top of OL_applyQueryPhase1).
1243   ES.lookup(
1244       LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo),
1245       SymbolState::Ready,
1246       [&](Expected<SymbolMap> Result) {
1247         Lookup1Completed = true;
1248         EXPECT_THAT_EXPECTED(Result, Succeeded());
1249         if (Result) {
1250           EXPECT_EQ(*Result, SymbolMap({{Foo, FooSym}}));
1251         }
1252       },
1253       NoDependenciesToRegister);
1254 
1255   // The generator should immediately see the first lookup.
1256   EXPECT_NE(G.Lookup, std::nullopt);
1257 
1258   // Add lookup 2.
1259   //
1260   // Tests that lookups that pass through tryToGenerate without being captured
1261   // resume auto-suspended lookups. We set a one-shot TryToGenerateOverride to
1262   // prevent capture of lookup 2 by tryToGenerate. This tests the call to
1263   // OL_resumeLookupAfterGeneration inside the generator loop.
1264   G.TryToGenerateOverride = [&](LookupState &LS, LookupKind K, JITDylib &JD,
1265                                 JITDylibLookupFlags JDLookupFlags,
1266                                 const SymbolLookupSet &Names) -> Error {
1267     cantFail(JD.define(absoluteSymbols({{Bar, BarSym}})));
1268     G.TryToGenerateOverride = nullptr;
1269     return Error::success();
1270   };
1271 
1272   ES.lookup(
1273       LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Bar),
1274       SymbolState::Ready,
1275       [&](Expected<SymbolMap> Result) {
1276         Lookup2Completed = true;
1277         EXPECT_THAT_EXPECTED(Result, Succeeded());
1278         if (Result) {
1279           EXPECT_EQ(*Result, SymbolMap({{Bar, BarSym}}));
1280         }
1281       },
1282       NoDependenciesToRegister);
1283 
1284   // Add lookup 3.
1285   //
1286   // Test that if a lookup's symbols have already been generated (and it
1287   // consequently skips the generator loop entirely) it still resumes the next
1288   // suspended lookup. This tests the call to OL_resumeLookupAfterGeneration
1289   // just above the generator loop.
1290   ES.lookup(
1291       LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Bar),
1292       SymbolState::Ready,
1293       [&](Expected<SymbolMap> Result) {
1294         Lookup3Completed = true;
1295         EXPECT_THAT_EXPECTED(Result, Succeeded());
1296         if (Result) {
1297           EXPECT_EQ(*Result, SymbolMap({{Bar, BarSym}}));
1298         }
1299       },
1300       NoDependenciesToRegister);
1301 
1302   // Add lookup 4.
1303   //
1304   // This is just used to verify that lookup 3 triggered resumption of the next
1305   // lookup as expected.
1306   ES.lookup(
1307       LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Baz),
1308       SymbolState::Ready,
1309       [&](Expected<SymbolMap> Result) {
1310         Lookup4Completed = true;
1311         EXPECT_THAT_EXPECTED(Result, Succeeded());
1312         if (Result) {
1313           EXPECT_EQ(*Result, SymbolMap({{Baz, BazSym}}));
1314         }
1315       },
1316       NoDependenciesToRegister);
1317 
1318   // All lookups have been started, but none should have been completed yet.
1319   EXPECT_FALSE(Lookup1Completed);
1320   EXPECT_FALSE(Lookup2Completed);
1321   EXPECT_FALSE(Lookup3Completed);
1322   EXPECT_FALSE(Lookup4Completed);
1323 
1324   // Start continuing lookups.
1325 
1326   // First Define foo and continue lookup 1. We expect this to complete lookups
1327   // 1, 2 and 3: the TryToGenerateOverride set above will define bar, which will
1328   // allow both 2 and 3 to complete.
1329   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
1330   G.takeLookup().LS.continueLookup(Error::success());
1331 
1332   EXPECT_TRUE(Lookup1Completed);
1333   EXPECT_TRUE(Lookup2Completed);
1334   EXPECT_TRUE(Lookup3Completed);
1335   EXPECT_FALSE(Lookup4Completed);
1336   EXPECT_NE(G.Lookup, std::nullopt);
1337 
1338   // Check that the most recently captured lookup is lookup 4 (for baz).
1339   if (G.Lookup) {
1340     EXPECT_EQ(G.Lookup->Names.begin()->first, Baz);
1341   }
1342 
1343   cantFail(JD.define(absoluteSymbols({{Baz, BazSym}})));
1344   G.takeLookup().LS.continueLookup(Error::success());
1345 
1346   EXPECT_TRUE(Lookup4Completed);
1347 }
1348 
1349 TEST_F(CoreAPIsStandardTest, FailResolution) {
1350   auto MU = std::make_unique<SimpleMaterializationUnit>(
1351       SymbolFlagsMap({{Foo, JITSymbolFlags::Exported | JITSymbolFlags::Weak},
1352                       {Bar, JITSymbolFlags::Exported | JITSymbolFlags::Weak}}),
1353       [&](std::unique_ptr<MaterializationResponsibility> R) {
1354         R->failMaterialization();
1355       });
1356 
1357   cantFail(JD.define(MU));
1358 
1359   SymbolNameSet Names({Foo, Bar});
1360   auto Result = ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet(Names));
1361 
1362   EXPECT_FALSE(!!Result) << "Expected failure";
1363   if (!Result) {
1364     handleAllErrors(
1365         Result.takeError(),
1366         [&](FailedToMaterialize &F) {
1367           EXPECT_TRUE(F.getSymbols().count(&JD))
1368               << "Expected to fail on JITDylib JD";
1369           EXPECT_EQ(F.getSymbols().find(&JD)->second, Names)
1370               << "Expected to fail on symbols in Names";
1371         },
1372         [](ErrorInfoBase &EIB) {
1373           std::string ErrMsg;
1374           {
1375             raw_string_ostream ErrOut(ErrMsg);
1376             EIB.log(ErrOut);
1377           }
1378           ADD_FAILURE() << "Expected a FailedToResolve error. Got:\n" << ErrMsg;
1379         });
1380   }
1381 }
1382 
1383 TEST_F(CoreAPIsStandardTest, FailEmissionAfterResolution) {
1384 
1385   cantFail(JD.define(absoluteSymbols({{Baz, BazSym}})));
1386 
1387   auto MU = std::make_unique<SimpleMaterializationUnit>(
1388       SymbolFlagsMap({{Foo, FooSym.getFlags()}, {Bar, BarSym.getFlags()}}),
1389       [&](std::unique_ptr<MaterializationResponsibility> R) {
1390         cantFail(R->notifyResolved(SymbolMap({{Foo, FooSym}, {Bar, BarSym}})));
1391         ES.lookup(
1392             LookupKind::Static, makeJITDylibSearchOrder(&JD),
1393             SymbolLookupSet({Baz}), SymbolState::Resolved,
1394             [&](Expected<SymbolMap> Result) {
1395               // Called when "baz" is resolved. We don't actually depend
1396               // on or care about baz, but use it to trigger failure of
1397               // this materialization before Baz has been finalized in
1398               // order to test that error propagation is correct in this
1399               // scenario.
1400               cantFail(std::move(Result));
1401               R->failMaterialization();
1402             },
1403             NoDependenciesToRegister);
1404       });
1405 
1406   cantFail(JD.define(MU));
1407 
1408   auto Result =
1409       ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet({Foo, Bar}));
1410 
1411   EXPECT_THAT_EXPECTED(std::move(Result), Failed())
1412       << "Unexpected success while trying to test error propagation";
1413 }
1414 
1415 TEST_F(CoreAPIsStandardTest, FailAfterPartialResolution) {
1416 
1417   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
1418 
1419   // Fail materialization of bar.
1420   auto BarMU = std::make_unique<SimpleMaterializationUnit>(
1421       SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
1422       [&](std::unique_ptr<MaterializationResponsibility> R) {
1423         R->failMaterialization();
1424       });
1425 
1426   cantFail(JD.define(std::move(BarMU)));
1427 
1428   bool QueryHandlerRun = false;
1429   ES.lookup(
1430       LookupKind::Static, makeJITDylibSearchOrder(&JD),
1431       SymbolLookupSet({Foo, Bar}), SymbolState::Resolved,
1432       [&](Expected<SymbolMap> Result) {
1433         EXPECT_THAT_EXPECTED(std::move(Result), Failed())
1434             << "Expected query to fail";
1435         QueryHandlerRun = true;
1436       },
1437       NoDependenciesToRegister);
1438   EXPECT_TRUE(QueryHandlerRun) << "Query handler never ran";
1439 }
1440 
1441 TEST_F(CoreAPIsStandardTest, FailDefineMaterializingDueToDefunctTracker) {
1442   // Check that a defunct resource tracker causes defineMaterializing to error
1443   // immediately.
1444 
1445   std::unique_ptr<MaterializationResponsibility> FooMR;
1446   auto MU = std::make_unique<SimpleMaterializationUnit>(
1447       SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
1448       [&](std::unique_ptr<MaterializationResponsibility> R) {
1449         FooMR = std::move(R);
1450       });
1451 
1452   auto RT = JD.createResourceTracker();
1453   cantFail(JD.define(std::move(MU), RT));
1454 
1455   bool OnCompletionRan = false;
1456   auto OnCompletion = [&](Expected<SymbolMap> Result) {
1457     EXPECT_THAT_EXPECTED(Result, Failed());
1458     OnCompletionRan = true;
1459   };
1460 
1461   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
1462             SymbolLookupSet(Foo), SymbolState::Ready, OnCompletion,
1463             NoDependenciesToRegister);
1464 
1465   cantFail(RT->remove());
1466 
1467   EXPECT_THAT_ERROR(FooMR->defineMaterializing(SymbolFlagsMap()), Failed())
1468       << "defineMaterializing should have failed due to a defunct tracker";
1469 
1470   FooMR->failMaterialization();
1471 
1472   EXPECT_TRUE(OnCompletionRan) << "OnCompletion handler did not run.";
1473 }
1474 
1475 TEST_F(CoreAPIsStandardTest, TestLookupWithUnthreadedMaterialization) {
1476   auto MU = std::make_unique<SimpleMaterializationUnit>(
1477       SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}),
1478       [&](std::unique_ptr<MaterializationResponsibility> R) {
1479         cantFail(R->notifyResolved({{Foo, FooSym}}));
1480         cantFail(R->notifyEmitted({}));
1481       });
1482 
1483   cantFail(JD.define(MU));
1484 
1485   auto FooLookupResult = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), Foo));
1486 
1487   EXPECT_EQ(FooLookupResult.getAddress(), FooSym.getAddress())
1488       << "lookup returned an incorrect address";
1489   EXPECT_EQ(FooLookupResult.getFlags(), FooSym.getFlags())
1490       << "lookup returned incorrect flags";
1491 }
1492 
1493 TEST_F(CoreAPIsStandardTest, TestLookupWithThreadedMaterialization) {
1494 #if LLVM_ENABLE_THREADS
1495 
1496   std::mutex WorkThreadsMutex;
1497   std::vector<std::thread> WorkThreads;
1498   DispatchOverride = [&](std::unique_ptr<Task> T) {
1499     std::promise<void> WaitP;
1500     std::lock_guard<std::mutex> Lock(WorkThreadsMutex);
1501     WorkThreads.push_back(
1502         std::thread([T = std::move(T), WaitF = WaitP.get_future()]() mutable {
1503           WaitF.get();
1504           T->run();
1505         }));
1506     WaitP.set_value();
1507   };
1508 
1509   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
1510 
1511   auto FooLookupResult = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), Foo));
1512 
1513   EXPECT_EQ(FooLookupResult.getAddress(), FooSym.getAddress())
1514       << "lookup returned an incorrect address";
1515   EXPECT_EQ(FooLookupResult.getFlags(), FooSym.getFlags())
1516       << "lookup returned incorrect flags";
1517 
1518   for (auto &WT : WorkThreads)
1519     WT.join();
1520 #endif
1521 }
1522 
1523 TEST_F(CoreAPIsStandardTest, TestGetRequestedSymbolsAndReplace) {
1524   // Test that GetRequestedSymbols returns the set of symbols that currently
1525   // have pending queries, and test that MaterializationResponsibility's
1526   // replace method can be used to return definitions to the JITDylib in a new
1527   // MaterializationUnit.
1528   SymbolNameSet Names({Foo, Bar});
1529 
1530   bool FooMaterialized = false;
1531   bool BarMaterialized = false;
1532 
1533   auto MU = std::make_unique<SimpleMaterializationUnit>(
1534       SymbolFlagsMap({{Foo, FooSym.getFlags()}, {Bar, BarSym.getFlags()}}),
1535       [&](std::unique_ptr<MaterializationResponsibility> R) {
1536         auto Requested = R->getRequestedSymbols();
1537         EXPECT_EQ(Requested.size(), 1U) << "Expected one symbol requested";
1538         EXPECT_EQ(*Requested.begin(), Foo) << "Expected \"Foo\" requested";
1539 
1540         auto NewMU = std::make_unique<SimpleMaterializationUnit>(
1541             SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
1542             [&](std::unique_ptr<MaterializationResponsibility> R2) {
1543               cantFail(R2->notifyResolved(SymbolMap({{Bar, BarSym}})));
1544               cantFail(R2->notifyEmitted({}));
1545               BarMaterialized = true;
1546             });
1547 
1548         cantFail(R->replace(std::move(NewMU)));
1549 
1550         cantFail(R->notifyResolved(SymbolMap({{Foo, FooSym}})));
1551         cantFail(R->notifyEmitted({}));
1552 
1553         FooMaterialized = true;
1554       });
1555 
1556   cantFail(JD.define(MU));
1557 
1558   EXPECT_FALSE(FooMaterialized) << "Foo should not be materialized yet";
1559   EXPECT_FALSE(BarMaterialized) << "Bar should not be materialized yet";
1560 
1561   auto FooSymResult = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), Foo));
1562   EXPECT_EQ(FooSymResult.getAddress(), FooSym.getAddress())
1563       << "Address mismatch for Foo";
1564 
1565   EXPECT_TRUE(FooMaterialized) << "Foo should be materialized now";
1566   EXPECT_FALSE(BarMaterialized) << "Bar still should not be materialized";
1567 
1568   auto BarSymResult = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), Bar));
1569   EXPECT_EQ(BarSymResult.getAddress(), BarSym.getAddress())
1570       << "Address mismatch for Bar";
1571   EXPECT_TRUE(BarMaterialized) << "Bar should be materialized now";
1572 }
1573 
1574 TEST_F(CoreAPIsStandardTest, TestMaterializationResponsibilityDelegation) {
1575   auto MU = std::make_unique<SimpleMaterializationUnit>(
1576       SymbolFlagsMap({{Foo, FooSym.getFlags()}, {Bar, BarSym.getFlags()}}),
1577       [&](std::unique_ptr<MaterializationResponsibility> R) {
1578         auto R2 = cantFail(R->delegate({Bar}));
1579 
1580         cantFail(R->notifyResolved({{Foo, FooSym}}));
1581         cantFail(R->notifyEmitted({}));
1582         cantFail(R2->notifyResolved({{Bar, BarSym}}));
1583         cantFail(R2->notifyEmitted({}));
1584       });
1585 
1586   cantFail(JD.define(MU));
1587 
1588   auto Result =
1589       ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet({Foo, Bar}));
1590 
1591   EXPECT_TRUE(!!Result) << "Result should be a success value";
1592   EXPECT_EQ(Result->count(Foo), 1U) << "\"Foo\" entry missing";
1593   EXPECT_EQ(Result->count(Bar), 1U) << "\"Bar\" entry missing";
1594   EXPECT_EQ((*Result)[Foo].getAddress(), FooSym.getAddress())
1595       << "Address mismatch for \"Foo\"";
1596   EXPECT_EQ((*Result)[Bar].getAddress(), BarSym.getAddress())
1597       << "Address mismatch for \"Bar\"";
1598 }
1599 
1600 TEST_F(CoreAPIsStandardTest, TestMaterializeWeakSymbol) {
1601   // Confirm that once a weak definition is selected for materialization it is
1602   // treated as strong.
1603   JITSymbolFlags WeakExported = JITSymbolFlags::Exported;
1604   WeakExported &= JITSymbolFlags::Weak;
1605 
1606   std::unique_ptr<MaterializationResponsibility> FooR;
1607   auto MU = std::make_unique<SimpleMaterializationUnit>(
1608       SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
1609       [&](std::unique_ptr<MaterializationResponsibility> R) {
1610         FooR = std::move(R);
1611       });
1612 
1613   cantFail(JD.define(MU));
1614   auto OnCompletion = [](Expected<SymbolMap> Result) {
1615     cantFail(std::move(Result));
1616   };
1617 
1618   ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
1619             SymbolLookupSet({Foo}), SymbolState::Ready, std::move(OnCompletion),
1620             NoDependenciesToRegister);
1621 
1622   auto MU2 = std::make_unique<SimpleMaterializationUnit>(
1623       SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}),
1624       [](std::unique_ptr<MaterializationResponsibility> R) {
1625         llvm_unreachable("This unit should never be materialized");
1626       });
1627 
1628   auto Err = JD.define(MU2);
1629   EXPECT_TRUE(!!Err) << "Expected failure value";
1630   EXPECT_TRUE(Err.isA<DuplicateDefinition>())
1631       << "Expected a duplicate definition error";
1632   consumeError(std::move(Err));
1633 
1634   // No dependencies registered, can't fail:
1635   cantFail(FooR->notifyResolved(SymbolMap({{Foo, FooSym}})));
1636   cantFail(FooR->notifyEmitted({}));
1637 }
1638 
1639 static bool linkOrdersEqual(const std::vector<JITDylibSP> &LHS,
1640                             ArrayRef<JITDylib *> RHS) {
1641   if (LHS.size() != RHS.size())
1642     return false;
1643   auto *RHSE = RHS.begin();
1644   for (auto &LHSE : LHS)
1645     if (LHSE.get() != *RHSE)
1646       return false;
1647     else
1648       ++RHSE;
1649   return true;
1650 }
1651 
1652 TEST(JITDylibTest, GetDFSLinkOrderTree) {
1653   // Test that DFS ordering behaves as expected when the linkage relationships
1654   // form a tree.
1655 
1656   ExecutionSession ES{std::make_unique<UnsupportedExecutorProcessControl>()};
1657   auto _ = make_scope_exit([&]() { cantFail(ES.endSession()); });
1658 
1659   auto &LibA = ES.createBareJITDylib("A");
1660   auto &LibB = ES.createBareJITDylib("B");
1661   auto &LibC = ES.createBareJITDylib("C");
1662   auto &LibD = ES.createBareJITDylib("D");
1663   auto &LibE = ES.createBareJITDylib("E");
1664   auto &LibF = ES.createBareJITDylib("F");
1665 
1666   // Linkage relationships:
1667   // A --- B -- D
1668   //  \      \- E
1669   //    \- C -- F
1670   LibA.setLinkOrder(makeJITDylibSearchOrder({&LibB, &LibC}));
1671   LibB.setLinkOrder(makeJITDylibSearchOrder({&LibD, &LibE}));
1672   LibC.setLinkOrder(makeJITDylibSearchOrder({&LibF}));
1673 
1674   auto DFSOrderFromB = cantFail(JITDylib::getDFSLinkOrder({&LibB}));
1675   EXPECT_TRUE(linkOrdersEqual(DFSOrderFromB, {&LibB, &LibD, &LibE}))
1676       << "Incorrect DFS link order for LibB";
1677 
1678   auto DFSOrderFromA = cantFail(JITDylib::getDFSLinkOrder({&LibA}));
1679   EXPECT_TRUE(linkOrdersEqual(DFSOrderFromA,
1680                               {&LibA, &LibB, &LibD, &LibE, &LibC, &LibF}))
1681       << "Incorrect DFS link order for libA";
1682 
1683   auto DFSOrderFromAB = cantFail(JITDylib::getDFSLinkOrder({&LibA, &LibB}));
1684   EXPECT_TRUE(linkOrdersEqual(DFSOrderFromAB,
1685                               {&LibA, &LibB, &LibD, &LibE, &LibC, &LibF}))
1686       << "Incorrect DFS link order for { libA, libB }";
1687 
1688   auto DFSOrderFromBA = cantFail(JITDylib::getDFSLinkOrder({&LibB, &LibA}));
1689   EXPECT_TRUE(linkOrdersEqual(DFSOrderFromBA,
1690                               {&LibB, &LibD, &LibE, &LibA, &LibC, &LibF}))
1691       << "Incorrect DFS link order for { libB, libA }";
1692 }
1693 
1694 TEST(JITDylibTest, GetDFSLinkOrderDiamond) {
1695   // Test that DFS ordering behaves as expected when the linkage relationships
1696   // contain a diamond.
1697 
1698   ExecutionSession ES{std::make_unique<UnsupportedExecutorProcessControl>()};
1699   auto _ = make_scope_exit([&]() { cantFail(ES.endSession()); });
1700 
1701   auto &LibA = ES.createBareJITDylib("A");
1702   auto &LibB = ES.createBareJITDylib("B");
1703   auto &LibC = ES.createBareJITDylib("C");
1704   auto &LibD = ES.createBareJITDylib("D");
1705 
1706   // Linkage relationships:
1707   // A -- B --- D
1708   //  \-- C --/
1709   LibA.setLinkOrder(makeJITDylibSearchOrder({&LibB, &LibC}));
1710   LibB.setLinkOrder(makeJITDylibSearchOrder({&LibD}));
1711   LibC.setLinkOrder(makeJITDylibSearchOrder({&LibD}));
1712 
1713   auto DFSOrderFromA = cantFail(JITDylib::getDFSLinkOrder({&LibA}));
1714   EXPECT_TRUE(linkOrdersEqual(DFSOrderFromA, {&LibA, &LibB, &LibD, &LibC}))
1715       << "Incorrect DFS link order for libA";
1716 }
1717 
1718 TEST(JITDylibTest, GetDFSLinkOrderCycle) {
1719   // Test that DFS ordering behaves as expected when the linkage relationships
1720   // contain a cycle.
1721 
1722   ExecutionSession ES{std::make_unique<UnsupportedExecutorProcessControl>()};
1723   auto _ = make_scope_exit([&]() { cantFail(ES.endSession()); });
1724 
1725   auto &LibA = ES.createBareJITDylib("A");
1726   auto &LibB = ES.createBareJITDylib("B");
1727   auto &LibC = ES.createBareJITDylib("C");
1728 
1729   // Linkage relationships:
1730   // A -- B --- C -- A
1731   LibA.setLinkOrder(makeJITDylibSearchOrder({&LibB}));
1732   LibB.setLinkOrder(makeJITDylibSearchOrder({&LibC}));
1733   LibC.setLinkOrder(makeJITDylibSearchOrder({&LibA}));
1734 
1735   auto DFSOrderFromA = cantFail(JITDylib::getDFSLinkOrder({&LibA}));
1736   EXPECT_TRUE(linkOrdersEqual(DFSOrderFromA, {&LibA, &LibB, &LibC}))
1737       << "Incorrect DFS link order for libA";
1738 
1739   auto DFSOrderFromB = cantFail(JITDylib::getDFSLinkOrder({&LibB}));
1740   EXPECT_TRUE(linkOrdersEqual(DFSOrderFromB, {&LibB, &LibC, &LibA}))
1741       << "Incorrect DFS link order for libB";
1742 
1743   auto DFSOrderFromC = cantFail(JITDylib::getDFSLinkOrder({&LibC}));
1744   EXPECT_TRUE(linkOrdersEqual(DFSOrderFromC, {&LibC, &LibA, &LibB}))
1745       << "Incorrect DFS link order for libC";
1746 }
1747 
1748 TEST_F(CoreAPIsStandardTest, RemoveJITDylibs) {
1749   // Foo will be fully materialized.
1750   cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
1751 
1752   // Bar should not be materialized at all.
1753   bool BarMaterializerDestroyed = false;
1754   cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
1755       SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
1756       [&](std::unique_ptr<MaterializationResponsibility> MR) {
1757         llvm_unreachable("Unexpected call to materialize");
1758       },
1759       nullptr,
1760       [](const JITDylib &, SymbolStringPtr Name) {
1761         llvm_unreachable("Unexpected call to discard");
1762       },
1763       [&]() { BarMaterializerDestroyed = true; })));
1764 
1765   // Baz will be in the materializing state.
1766   std::unique_ptr<MaterializationResponsibility> BazMR;
1767   cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
1768       SymbolFlagsMap({{Baz, BazSym.getFlags()}}),
1769       [&](std::unique_ptr<MaterializationResponsibility> MR) {
1770         BazMR = std::move(MR);
1771       })));
1772 
1773   // Lookup to force materialization of Foo.
1774   cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet({Foo})));
1775 
1776   // Start a lookup to force materialization of Baz.
1777   bool BazLookupFailed = false;
1778   ES.lookup(
1779       LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet({Baz}),
1780       SymbolState::Ready,
1781       [&](Expected<SymbolMap> Result) {
1782         if (!Result) {
1783           BazLookupFailed = true;
1784           consumeError(Result.takeError());
1785         }
1786       },
1787       NoDependenciesToRegister);
1788 
1789   // Remove the JITDylib.
1790   auto Err = ES.removeJITDylib(JD);
1791   EXPECT_THAT_ERROR(std::move(Err), Succeeded());
1792 
1793   EXPECT_TRUE(BarMaterializerDestroyed);
1794   EXPECT_TRUE(BazLookupFailed);
1795 
1796   EXPECT_THAT_ERROR(BazMR->notifyResolved({{Baz, BazSym}}), Failed());
1797 
1798   EXPECT_THAT_EXPECTED(JD.getDFSLinkOrder(), Failed());
1799 
1800   BazMR->failMaterialization();
1801 }
1802 
1803 TEST(CoreAPIsExtraTest, SessionTeardownByFailedToMaterialize) {
1804 
1805   auto RunTestCase = []() -> Error {
1806     ExecutionSession ES{std::make_unique<UnsupportedExecutorProcessControl>(
1807         std::make_shared<SymbolStringPool>())};
1808     auto Foo = ES.intern("foo");
1809     auto FooFlags = JITSymbolFlags::Exported;
1810 
1811     auto &JD = ES.createBareJITDylib("Foo");
1812     cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
1813         SymbolFlagsMap({{Foo, FooFlags}}),
1814         [&](std::unique_ptr<MaterializationResponsibility> R) {
1815           R->failMaterialization();
1816         })));
1817 
1818     auto Sym = ES.lookup({&JD}, Foo);
1819     assert(!Sym && "Query should have failed");
1820     cantFail(ES.endSession());
1821     return Sym.takeError();
1822   };
1823 
1824   auto Err = RunTestCase();
1825   EXPECT_TRUE(!!Err); // Expect that error occurred.
1826   EXPECT_TRUE(
1827       Err.isA<FailedToMaterialize>()); // Expect FailedToMaterialize error.
1828 
1829   // Make sure that we can log errors, even though the session has been
1830   // destroyed.
1831   logAllUnhandledErrors(std::move(Err), nulls(), "");
1832 }
1833 
1834 } // namespace
1835