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