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