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