1 //===----------- CoreAPIsTest.cpp - Unit tests for Core ORC APIs ----------===//
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
7 //===----------------------------------------------------------------------===//
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"
20 using namespace llvm::orc
;
22 class CoreAPIsStandardTest
: public CoreAPIsBasedStandardTest
{};
26 TEST_F(CoreAPIsStandardTest
, BasicSuccessfulLookup
) {
27 bool OnCompletionRun
= false;
29 auto OnCompletion
= [&](Expected
<SymbolMap
> Result
) {
30 EXPECT_TRUE(!!Result
) << "Resolution unexpectedly returned error";
31 auto &Resolved
= *Result
;
32 auto I
= Resolved
.find(Foo
);
33 EXPECT_NE(I
, Resolved
.end()) << "Could not find symbol definition";
34 EXPECT_EQ(I
->second
.getAddress(), FooAddr
)
35 << "Resolution returned incorrect result";
36 OnCompletionRun
= true;
39 std::unique_ptr
<MaterializationResponsibility
> FooMR
;
41 cantFail(JD
.define(std::make_unique
<SimpleMaterializationUnit
>(
42 SymbolFlagsMap({{Foo
, FooSym
.getFlags()}}),
43 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
47 ES
.lookup(LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
48 SymbolLookupSet(Foo
), SymbolState::Ready
, OnCompletion
,
49 NoDependenciesToRegister
);
51 EXPECT_FALSE(OnCompletionRun
) << "Should not have been resolved yet";
53 cantFail(FooMR
->notifyResolved({{Foo
, FooSym
}}));
55 EXPECT_FALSE(OnCompletionRun
) << "Should not be ready yet";
57 cantFail(FooMR
->notifyEmitted());
59 EXPECT_TRUE(OnCompletionRun
) << "Should have been marked ready";
62 TEST_F(CoreAPIsStandardTest
, EmptyLookup
) {
63 bool OnCompletionRun
= false;
65 auto OnCompletion
= [&](Expected
<SymbolMap
> Result
) {
66 cantFail(std::move(Result
));
67 OnCompletionRun
= true;
70 ES
.lookup(LookupKind::Static
, makeJITDylibSearchOrder(&JD
), SymbolLookupSet(),
71 SymbolState::Ready
, OnCompletion
, NoDependenciesToRegister
);
73 EXPECT_TRUE(OnCompletionRun
) << "OnCompletion was not run for empty query";
76 TEST_F(CoreAPIsStandardTest
, ResolveUnrequestedSymbol
) {
77 // Test that all symbols in a MaterializationUnit materialize corretly when
78 // only a subset of symbols is looked up.
79 // The aim here is to ensure that we're not relying on the query to set up
80 // state needed to materialize the unrequested symbols.
82 cantFail(JD
.define(std::make_unique
<SimpleMaterializationUnit
>(
83 SymbolFlagsMap({{Foo
, FooSym
.getFlags()}, {Bar
, BarSym
.getFlags()}}),
84 [this](std::unique_ptr
<MaterializationResponsibility
> R
) {
85 cantFail(R
->notifyResolved({{Foo
, FooSym
}, {Bar
, BarSym
}}));
86 cantFail(R
->notifyEmitted());
90 cantFail(ES
.lookup(makeJITDylibSearchOrder(&JD
), SymbolLookupSet({Foo
})));
91 EXPECT_EQ(Result
.size(), 1U) << "Unexpected number of results";
92 EXPECT_TRUE(Result
.count(Foo
)) << "Expected result for \"Foo\"";
95 TEST_F(CoreAPIsStandardTest
, MaterializationSideEffctsOnlyBasic
) {
96 // Test that basic materialization-side-effects-only symbols work as expected:
97 // that they can be emitted without being resolved, that queries for them
98 // don't return until they're emitted, and that they don't appear in query
101 std::unique_ptr
<MaterializationResponsibility
> FooR
;
102 Optional
<SymbolMap
> Result
;
104 cantFail(JD
.define(std::make_unique
<SimpleMaterializationUnit
>(
106 {{Foo
, JITSymbolFlags::Exported
|
107 JITSymbolFlags::MaterializationSideEffectsOnly
}}),
108 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
113 LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
114 SymbolLookupSet(Foo
, SymbolLookupFlags::WeaklyReferencedSymbol
),
116 [&](Expected
<SymbolMap
> LookupResult
) {
118 Result
= std::move(*LookupResult
);
120 ADD_FAILURE() << "Unexpected lookup error: "
121 << toString(LookupResult
.takeError());
123 NoDependenciesToRegister
);
125 EXPECT_FALSE(Result
) << "Lookup returned unexpectedly";
126 EXPECT_TRUE(FooR
) << "Lookup failed to trigger materialization";
127 EXPECT_THAT_ERROR(FooR
->notifyEmitted(), Succeeded())
128 << "Emission of materialization-side-effects-only symbol failed";
130 EXPECT_TRUE(Result
) << "Lookup failed to return";
131 EXPECT_TRUE(Result
->empty()) << "Lookup result contained unexpected value";
134 TEST_F(CoreAPIsStandardTest
, MaterializationSideEffectsOnlyFailuresPersist
) {
135 // Test that when a MaterializationSideEffectsOnly symbol is failed it
136 // remains in the failure state rather than vanishing.
138 cantFail(JD
.define(std::make_unique
<SimpleMaterializationUnit
>(
140 {{Foo
, JITSymbolFlags::Exported
|
141 JITSymbolFlags::MaterializationSideEffectsOnly
}}),
142 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
143 R
->failMaterialization();
146 EXPECT_THAT_EXPECTED(
147 ES
.lookup(makeJITDylibSearchOrder(&JD
), SymbolLookupSet({Foo
})),
149 EXPECT_THAT_EXPECTED(
150 ES
.lookup(makeJITDylibSearchOrder(&JD
), SymbolLookupSet({Foo
})),
154 TEST_F(CoreAPIsStandardTest
, RemoveSymbolsTest
) {
156 // (1) Missing symbols generate a SymbolsNotFound error.
157 // (2) Materializing symbols generate a SymbolCouldNotBeRemoved error.
158 // (3) Removal of unmaterialized symbols triggers discard on the
159 // materialization unit.
160 // (4) Removal of symbols destroys empty materialization units.
161 // (5) Removal of materialized symbols works.
163 // Foo will be fully materialized.
164 cantFail(JD
.define(absoluteSymbols({{Foo
, FooSym
}})));
166 // Bar will be unmaterialized.
167 bool BarDiscarded
= false;
168 bool BarMaterializerDestructed
= false;
169 cantFail(JD
.define(std::make_unique
<SimpleMaterializationUnit
>(
170 SymbolFlagsMap({{Bar
, BarSym
.getFlags()}}),
171 [this](std::unique_ptr
<MaterializationResponsibility
> R
) {
172 ADD_FAILURE() << "Unexpected materialization of \"Bar\"";
173 cantFail(R
->notifyResolved({{Bar
, BarSym
}}));
174 cantFail(R
->notifyEmitted());
177 [&](const JITDylib
&JD
, const SymbolStringPtr
&Name
) {
178 EXPECT_EQ(Name
, Bar
) << "Expected \"Bar\" to be discarded";
182 [&]() { BarMaterializerDestructed
= true; })));
184 // Baz will be in the materializing state initially, then
185 // materialized for the final removal attempt.
186 std::unique_ptr
<MaterializationResponsibility
> BazR
;
187 cantFail(JD
.define(std::make_unique
<SimpleMaterializationUnit
>(
188 SymbolFlagsMap({{Baz
, BazSym
.getFlags()}}),
189 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
193 [](const JITDylib
&JD
, const SymbolStringPtr
&Name
) {
194 ADD_FAILURE() << "\"Baz\" discarded unexpectedly";
197 bool OnCompletionRun
= false;
199 LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
200 SymbolLookupSet({Foo
, Baz
}), SymbolState::Ready
,
201 [&](Expected
<SymbolMap
> Result
) {
202 cantFail(Result
.takeError());
203 OnCompletionRun
= true;
205 NoDependenciesToRegister
);
208 // Attempt 1: Search for a missing symbol, Qux.
209 auto Err
= JD
.remove({Foo
, Bar
, Baz
, Qux
});
210 EXPECT_TRUE(!!Err
) << "Expected failure";
211 EXPECT_TRUE(Err
.isA
<SymbolsNotFound
>())
212 << "Expected a SymbolsNotFound error";
213 consumeError(std::move(Err
));
217 // Attempt 2: Search for a symbol that is still materializing, Baz.
218 auto Err
= JD
.remove({Foo
, Bar
, Baz
});
219 EXPECT_TRUE(!!Err
) << "Expected failure";
220 EXPECT_TRUE(Err
.isA
<SymbolsCouldNotBeRemoved
>())
221 << "Expected a SymbolsNotFound error";
222 consumeError(std::move(Err
));
225 cantFail(BazR
->notifyResolved({{Baz
, BazSym
}}));
226 cantFail(BazR
->notifyEmitted());
228 // Attempt 3: Search now that all symbols are fully materialized
229 // (Foo, Baz), or not yet materialized (Bar).
230 auto Err
= JD
.remove({Foo
, Bar
, Baz
});
231 EXPECT_FALSE(!!Err
) << "Expected success";
234 EXPECT_TRUE(BarDiscarded
) << "\"Bar\" should have been discarded";
235 EXPECT_TRUE(BarMaterializerDestructed
)
236 << "\"Bar\"'s materializer should have been destructed";
237 EXPECT_TRUE(OnCompletionRun
) << "OnCompletion should have been run";
240 TEST_F(CoreAPIsStandardTest
, LookupWithHiddenSymbols
) {
241 auto BarHiddenFlags
= BarSym
.getFlags() & ~JITSymbolFlags::Exported
;
242 auto BarHiddenSym
= JITEvaluatedSymbol(BarSym
.getAddress(), BarHiddenFlags
);
244 cantFail(JD
.define(absoluteSymbols({{Foo
, FooSym
}, {Bar
, BarHiddenSym
}})));
246 auto &JD2
= ES
.createBareJITDylib("JD2");
247 cantFail(JD2
.define(absoluteSymbols({{Bar
, QuxSym
}})));
249 /// Try a blocking lookup.
250 auto Result
= cantFail(ES
.lookup(makeJITDylibSearchOrder({&JD
, &JD2
}),
251 SymbolLookupSet({Foo
, Bar
})));
253 EXPECT_EQ(Result
.size(), 2U) << "Unexpected number of results";
254 EXPECT_EQ(Result
.count(Foo
), 1U) << "Missing result for \"Foo\"";
255 EXPECT_EQ(Result
.count(Bar
), 1U) << "Missing result for \"Bar\"";
256 EXPECT_EQ(Result
[Bar
].getAddress(), QuxSym
.getAddress())
257 << "Wrong result for \"Bar\"";
260 TEST_F(CoreAPIsStandardTest
, LookupFlagsTest
) {
261 // Test that lookupFlags works on a predefined symbol, and does not trigger
262 // materialization of a lazy symbol. Make the lazy symbol weak to test that
263 // the weak flag is propagated correctly.
265 BarSym
.setFlags(static_cast<JITSymbolFlags::FlagNames
>(
266 JITSymbolFlags::Exported
| JITSymbolFlags::Weak
));
267 auto MU
= std::make_unique
<SimpleMaterializationUnit
>(
268 SymbolFlagsMap({{Bar
, BarSym
.getFlags()}}),
269 [](std::unique_ptr
<MaterializationResponsibility
> R
) {
270 llvm_unreachable("Symbol materialized on flags lookup");
273 cantFail(JD
.define(absoluteSymbols({{Foo
, FooSym
}})));
274 cantFail(JD
.define(std::move(MU
)));
276 auto SymbolFlags
= cantFail(ES
.lookupFlags(
278 {{&JD
, JITDylibLookupFlags::MatchExportedSymbolsOnly
}},
279 SymbolLookupSet({Foo
, Bar
, Baz
},
280 SymbolLookupFlags::WeaklyReferencedSymbol
)));
282 EXPECT_EQ(SymbolFlags
.size(), 2U)
283 << "Returned symbol flags contains unexpected results";
284 EXPECT_EQ(SymbolFlags
.count(Foo
), 1U) << "Missing lookupFlags result for Foo";
285 EXPECT_EQ(SymbolFlags
[Foo
], FooSym
.getFlags())
286 << "Incorrect flags returned for Foo";
287 EXPECT_EQ(SymbolFlags
.count(Bar
), 1U)
288 << "Missing lookupFlags result for Bar";
289 EXPECT_EQ(SymbolFlags
[Bar
], BarSym
.getFlags())
290 << "Incorrect flags returned for Bar";
293 TEST_F(CoreAPIsStandardTest
, LookupWithGeneratorFailure
) {
295 class BadGenerator
: public DefinitionGenerator
{
297 Error
tryToGenerate(LookupState
&LS
, LookupKind K
, JITDylib
&,
298 JITDylibLookupFlags
, const SymbolLookupSet
&) override
{
299 return make_error
<StringError
>("BadGenerator", inconvertibleErrorCode());
303 JD
.addGenerator(std::make_unique
<BadGenerator
>());
306 ES
.lookupFlags(LookupKind::Static
,
307 {{&JD
, JITDylibLookupFlags::MatchExportedSymbolsOnly
}},
308 SymbolLookupSet(Foo
))
310 Failed
<StringError
>())
311 << "Generator failure did not propagate through lookupFlags";
314 ES
.lookup(makeJITDylibSearchOrder(&JD
), SymbolLookupSet(Foo
)).takeError(),
315 Failed
<StringError
>())
316 << "Generator failure did not propagate through lookup";
319 TEST_F(CoreAPIsStandardTest
, TestBasicAliases
) {
320 cantFail(JD
.define(absoluteSymbols({{Foo
, FooSym
}, {Bar
, BarSym
}})));
321 cantFail(JD
.define(symbolAliases({{Baz
, {Foo
, JITSymbolFlags::Exported
}},
322 {Qux
, {Bar
, JITSymbolFlags::Weak
}}})));
323 cantFail(JD
.define(absoluteSymbols({{Qux
, QuxSym
}})));
326 ES
.lookup(makeJITDylibSearchOrder(&JD
), SymbolLookupSet({Baz
, Qux
}));
327 EXPECT_TRUE(!!Result
) << "Unexpected lookup failure";
328 EXPECT_EQ(Result
->count(Baz
), 1U) << "No result for \"baz\"";
329 EXPECT_EQ(Result
->count(Qux
), 1U) << "No result for \"qux\"";
330 EXPECT_EQ((*Result
)[Baz
].getAddress(), FooSym
.getAddress())
331 << "\"Baz\"'s address should match \"Foo\"'s";
332 EXPECT_EQ((*Result
)[Qux
].getAddress(), QuxSym
.getAddress())
333 << "The \"Qux\" alias should have been overriden";
336 TEST_F(CoreAPIsStandardTest
, TestChainedAliases
) {
337 cantFail(JD
.define(absoluteSymbols({{Foo
, FooSym
}})));
338 cantFail(JD
.define(symbolAliases(
339 {{Baz
, {Bar
, BazSym
.getFlags()}}, {Bar
, {Foo
, BarSym
.getFlags()}}})));
342 ES
.lookup(makeJITDylibSearchOrder(&JD
), SymbolLookupSet({Bar
, Baz
}));
343 EXPECT_TRUE(!!Result
) << "Unexpected lookup failure";
344 EXPECT_EQ(Result
->count(Bar
), 1U) << "No result for \"bar\"";
345 EXPECT_EQ(Result
->count(Baz
), 1U) << "No result for \"baz\"";
346 EXPECT_EQ((*Result
)[Bar
].getAddress(), FooSym
.getAddress())
347 << "\"Bar\"'s address should match \"Foo\"'s";
348 EXPECT_EQ((*Result
)[Baz
].getAddress(), FooSym
.getAddress())
349 << "\"Baz\"'s address should match \"Foo\"'s";
352 TEST_F(CoreAPIsStandardTest
, TestBasicReExports
) {
353 // Test that the basic use case of re-exporting a single symbol from another
355 cantFail(JD
.define(absoluteSymbols({{Foo
, FooSym
}})));
357 auto &JD2
= ES
.createBareJITDylib("JD2");
359 cantFail(JD2
.define(reexports(JD
, {{Bar
, {Foo
, BarSym
.getFlags()}}})));
361 auto Result
= cantFail(ES
.lookup(makeJITDylibSearchOrder(&JD2
), Bar
));
362 EXPECT_EQ(Result
.getAddress(), FooSym
.getAddress())
363 << "Re-export Bar for symbol Foo should match FooSym's address";
366 TEST_F(CoreAPIsStandardTest
, TestThatReExportsDontUnnecessarilyMaterialize
) {
367 // Test that re-exports do not materialize symbols that have not been queried
369 cantFail(JD
.define(absoluteSymbols({{Foo
, FooSym
}})));
371 bool BarMaterialized
= false;
372 auto BarMU
= std::make_unique
<SimpleMaterializationUnit
>(
373 SymbolFlagsMap({{Bar
, BarSym
.getFlags()}}),
374 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
375 BarMaterialized
= true;
376 cantFail(R
->notifyResolved({{Bar
, BarSym
}}));
377 cantFail(R
->notifyEmitted());
380 cantFail(JD
.define(BarMU
));
382 auto &JD2
= ES
.createBareJITDylib("JD2");
384 cantFail(JD2
.define(reexports(
385 JD
, {{Baz
, {Foo
, BazSym
.getFlags()}}, {Qux
, {Bar
, QuxSym
.getFlags()}}})));
387 auto Result
= cantFail(ES
.lookup(makeJITDylibSearchOrder(&JD2
), Baz
));
388 EXPECT_EQ(Result
.getAddress(), FooSym
.getAddress())
389 << "Re-export Baz for symbol Foo should match FooSym's address";
391 EXPECT_FALSE(BarMaterialized
) << "Bar should not have been materialized";
394 TEST_F(CoreAPIsStandardTest
, TestReexportsGenerator
) {
395 // Test that a re-exports generator can dynamically generate reexports.
397 auto &JD2
= ES
.createBareJITDylib("JD2");
398 cantFail(JD2
.define(absoluteSymbols({{Foo
, FooSym
}, {Bar
, BarSym
}})));
400 auto Filter
= [this](SymbolStringPtr Name
) { return Name
!= Bar
; };
402 JD
.addGenerator(std::make_unique
<ReexportsGenerator
>(
403 JD2
, JITDylibLookupFlags::MatchExportedSymbolsOnly
, Filter
));
405 auto Flags
= cantFail(ES
.lookupFlags(
407 {{&JD
, JITDylibLookupFlags::MatchExportedSymbolsOnly
}},
408 SymbolLookupSet({Foo
, Bar
, Baz
},
409 SymbolLookupFlags::WeaklyReferencedSymbol
)));
410 EXPECT_EQ(Flags
.size(), 1U) << "Unexpected number of results";
411 EXPECT_EQ(Flags
[Foo
], FooSym
.getFlags()) << "Unexpected flags for Foo";
413 auto Result
= cantFail(ES
.lookup(makeJITDylibSearchOrder(&JD
), Foo
));
415 EXPECT_EQ(Result
.getAddress(), FooSym
.getAddress())
416 << "Incorrect reexported symbol address";
419 TEST_F(CoreAPIsStandardTest
, TestTrivialCircularDependency
) {
420 std::unique_ptr
<MaterializationResponsibility
> FooR
;
421 auto FooMU
= std::make_unique
<SimpleMaterializationUnit
>(
422 SymbolFlagsMap({{Foo
, FooSym
.getFlags()}}),
423 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
427 cantFail(JD
.define(FooMU
));
429 bool FooReady
= false;
430 auto OnCompletion
= [&](Expected
<SymbolMap
> Result
) {
431 cantFail(std::move(Result
));
435 ES
.lookup(LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
436 SymbolLookupSet({Foo
}), SymbolState::Ready
, OnCompletion
,
437 NoDependenciesToRegister
);
439 FooR
->addDependenciesForAll({{&JD
, SymbolNameSet({Foo
})}});
440 EXPECT_THAT_ERROR(FooR
->notifyResolved({{Foo
, FooSym
}}), Succeeded())
441 << "No symbols marked failed, but Foo failed to resolve";
442 EXPECT_THAT_ERROR(FooR
->notifyEmitted(), Succeeded())
443 << "No symbols marked failed, but Foo failed to emit";
445 EXPECT_TRUE(FooReady
)
446 << "Self-dependency prevented symbol from being marked ready";
449 TEST_F(CoreAPIsStandardTest
, TestCircularDependenceInOneJITDylib
) {
450 // Test that a circular symbol dependency between three symbols in a JITDylib
451 // does not prevent any symbol from becoming 'ready' once all symbols are
454 std::unique_ptr
<MaterializationResponsibility
> FooR
;
455 std::unique_ptr
<MaterializationResponsibility
> BarR
;
456 std::unique_ptr
<MaterializationResponsibility
> BazR
;
458 // Create a MaterializationUnit for each symbol that moves the
459 // MaterializationResponsibility into one of the locals above.
460 auto FooMU
= std::make_unique
<SimpleMaterializationUnit
>(
461 SymbolFlagsMap({{Foo
, FooSym
.getFlags()}}),
462 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
466 auto BarMU
= std::make_unique
<SimpleMaterializationUnit
>(
467 SymbolFlagsMap({{Bar
, BarSym
.getFlags()}}),
468 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
472 auto BazMU
= std::make_unique
<SimpleMaterializationUnit
>(
473 SymbolFlagsMap({{Baz
, BazSym
.getFlags()}}),
474 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
478 // Define the symbols.
479 cantFail(JD
.define(FooMU
));
480 cantFail(JD
.define(BarMU
));
481 cantFail(JD
.define(BazMU
));
483 // Query each of the symbols to trigger materialization.
484 bool FooResolved
= false;
485 bool FooReady
= false;
487 auto OnFooResolution
= [&](Expected
<SymbolMap
> Result
) {
488 cantFail(std::move(Result
));
492 auto OnFooReady
= [&](Expected
<SymbolMap
> Result
) {
493 cantFail(std::move(Result
));
497 // Issue lookups for Foo. Use NoDependenciesToRegister: We're going to add
498 // the dependencies manually below.
499 ES
.lookup(LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
500 SymbolLookupSet(Foo
), SymbolState::Resolved
,
501 std::move(OnFooResolution
), NoDependenciesToRegister
);
503 ES
.lookup(LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
504 SymbolLookupSet(Foo
), SymbolState::Ready
, std::move(OnFooReady
),
505 NoDependenciesToRegister
);
507 bool BarResolved
= false;
508 bool BarReady
= false;
509 auto OnBarResolution
= [&](Expected
<SymbolMap
> Result
) {
510 cantFail(std::move(Result
));
514 auto OnBarReady
= [&](Expected
<SymbolMap
> Result
) {
515 cantFail(std::move(Result
));
519 ES
.lookup(LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
520 SymbolLookupSet(Bar
), SymbolState::Resolved
,
521 std::move(OnBarResolution
), NoDependenciesToRegister
);
523 ES
.lookup(LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
524 SymbolLookupSet(Bar
), SymbolState::Ready
, std::move(OnBarReady
),
525 NoDependenciesToRegister
);
527 bool BazResolved
= false;
528 bool BazReady
= false;
530 auto OnBazResolution
= [&](Expected
<SymbolMap
> Result
) {
531 cantFail(std::move(Result
));
535 auto OnBazReady
= [&](Expected
<SymbolMap
> Result
) {
536 cantFail(std::move(Result
));
540 ES
.lookup(LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
541 SymbolLookupSet(Baz
), SymbolState::Resolved
,
542 std::move(OnBazResolution
), NoDependenciesToRegister
);
544 ES
.lookup(LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
545 SymbolLookupSet(Baz
), SymbolState::Ready
, std::move(OnBazReady
),
546 NoDependenciesToRegister
);
548 // Add a circular dependency: Foo -> Bar, Bar -> Baz, Baz -> Foo.
549 FooR
->addDependenciesForAll({{&JD
, SymbolNameSet({Bar
})}});
550 BarR
->addDependenciesForAll({{&JD
, SymbolNameSet({Baz
})}});
551 BazR
->addDependenciesForAll({{&JD
, SymbolNameSet({Foo
})}});
553 // Add self-dependencies for good measure. This tests that the implementation
554 // of addDependencies filters these out.
555 FooR
->addDependenciesForAll({{&JD
, SymbolNameSet({Foo
})}});
556 BarR
->addDependenciesForAll({{&JD
, SymbolNameSet({Bar
})}});
557 BazR
->addDependenciesForAll({{&JD
, SymbolNameSet({Baz
})}});
559 // Check that nothing has been resolved yet.
560 EXPECT_FALSE(FooResolved
) << "\"Foo\" should not be resolved yet";
561 EXPECT_FALSE(BarResolved
) << "\"Bar\" should not be resolved yet";
562 EXPECT_FALSE(BazResolved
) << "\"Baz\" should not be resolved yet";
564 // Resolve the symbols (but do not emit them).
565 EXPECT_THAT_ERROR(FooR
->notifyResolved({{Foo
, FooSym
}}), Succeeded())
566 << "No symbols failed, but Foo failed to resolve";
567 EXPECT_THAT_ERROR(BarR
->notifyResolved({{Bar
, BarSym
}}), Succeeded())
568 << "No symbols failed, but Bar failed to resolve";
569 EXPECT_THAT_ERROR(BazR
->notifyResolved({{Baz
, BazSym
}}), Succeeded())
570 << "No symbols failed, but Baz failed to resolve";
572 // Verify that the symbols have been resolved, but are not ready yet.
573 EXPECT_TRUE(FooResolved
) << "\"Foo\" should be resolved now";
574 EXPECT_TRUE(BarResolved
) << "\"Bar\" should be resolved now";
575 EXPECT_TRUE(BazResolved
) << "\"Baz\" should be resolved now";
577 EXPECT_FALSE(FooReady
) << "\"Foo\" should not be ready yet";
578 EXPECT_FALSE(BarReady
) << "\"Bar\" should not be ready yet";
579 EXPECT_FALSE(BazReady
) << "\"Baz\" should not be ready yet";
581 // Emit two of the symbols.
582 EXPECT_THAT_ERROR(FooR
->notifyEmitted(), Succeeded())
583 << "No symbols failed, but Foo failed to emit";
584 EXPECT_THAT_ERROR(BarR
->notifyEmitted(), Succeeded())
585 << "No symbols failed, but Bar failed to emit";
587 // Verify that nothing is ready until the circular dependence is resolved.
588 EXPECT_FALSE(FooReady
) << "\"Foo\" still should not be ready";
589 EXPECT_FALSE(BarReady
) << "\"Bar\" still should not be ready";
590 EXPECT_FALSE(BazReady
) << "\"Baz\" still should not be ready";
592 // Emit the last symbol.
593 EXPECT_THAT_ERROR(BazR
->notifyEmitted(), Succeeded())
594 << "No symbols failed, but Baz failed to emit";
596 // Verify that everything becomes ready once the circular dependence resolved.
597 EXPECT_TRUE(FooReady
) << "\"Foo\" should be ready now";
598 EXPECT_TRUE(BarReady
) << "\"Bar\" should be ready now";
599 EXPECT_TRUE(BazReady
) << "\"Baz\" should be ready now";
602 TEST_F(CoreAPIsStandardTest
, FailureInDependency
) {
603 std::unique_ptr
<MaterializationResponsibility
> FooR
;
604 std::unique_ptr
<MaterializationResponsibility
> BarR
;
606 // Create a MaterializationUnit for each symbol that moves the
607 // MaterializationResponsibility into one of the locals above.
608 auto FooMU
= std::make_unique
<SimpleMaterializationUnit
>(
609 SymbolFlagsMap({{Foo
, FooSym
.getFlags()}}),
610 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
614 auto BarMU
= std::make_unique
<SimpleMaterializationUnit
>(
615 SymbolFlagsMap({{Bar
, BarSym
.getFlags()}}),
616 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
620 // Define the symbols.
621 cantFail(JD
.define(FooMU
));
622 cantFail(JD
.define(BarMU
));
624 bool OnFooReadyRun
= false;
625 auto OnFooReady
= [&](Expected
<SymbolMap
> Result
) {
626 EXPECT_THAT_EXPECTED(std::move(Result
), Failed());
627 OnFooReadyRun
= true;
630 ES
.lookup(LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
631 SymbolLookupSet(Foo
), SymbolState::Ready
, std::move(OnFooReady
),
632 NoDependenciesToRegister
);
634 bool OnBarReadyRun
= false;
635 auto OnBarReady
= [&](Expected
<SymbolMap
> Result
) {
636 EXPECT_THAT_EXPECTED(std::move(Result
), Failed());
637 OnBarReadyRun
= true;
640 ES
.lookup(LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
641 SymbolLookupSet(Bar
), SymbolState::Ready
, std::move(OnBarReady
),
642 NoDependenciesToRegister
);
644 // Add a dependency by Foo on Bar.
645 FooR
->addDependenciesForAll({{&JD
, SymbolNameSet({Bar
})}});
648 BarR
->failMaterialization();
650 // Verify that queries on Bar failed, but queries on Foo have not yet.
651 EXPECT_TRUE(OnBarReadyRun
) << "Query for \"Bar\" was not run";
652 EXPECT_FALSE(OnFooReadyRun
) << "Query for \"Foo\" was run unexpectedly";
654 // Check that we can still resolve Foo (even though it has been failed).
655 EXPECT_THAT_ERROR(FooR
->notifyResolved({{Foo
, FooSym
}}), Failed())
656 << "Expected resolution for \"Foo\" to fail.";
658 FooR
->failMaterialization();
660 // Verify that queries on Foo have now failed.
661 EXPECT_TRUE(OnFooReadyRun
) << "Query for \"Foo\" was not run";
663 // Verify that subsequent lookups on Bar and Foo fail.
664 EXPECT_THAT_EXPECTED(ES
.lookup({&JD
}, {Bar
}), Failed())
665 << "Lookup on failed symbol should fail";
667 EXPECT_THAT_EXPECTED(ES
.lookup({&JD
}, {Foo
}), Failed())
668 << "Lookup on failed symbol should fail";
671 TEST_F(CoreAPIsStandardTest
, FailureInCircularDependency
) {
672 std::unique_ptr
<MaterializationResponsibility
> FooR
;
673 std::unique_ptr
<MaterializationResponsibility
> BarR
;
675 // Create a MaterializationUnit for each symbol that moves the
676 // MaterializationResponsibility into one of the locals above.
677 auto FooMU
= std::make_unique
<SimpleMaterializationUnit
>(
678 SymbolFlagsMap({{Foo
, FooSym
.getFlags()}}),
679 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
683 auto BarMU
= std::make_unique
<SimpleMaterializationUnit
>(
684 SymbolFlagsMap({{Bar
, BarSym
.getFlags()}}),
685 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
689 // Define the symbols.
690 cantFail(JD
.define(FooMU
));
691 cantFail(JD
.define(BarMU
));
693 bool OnFooReadyRun
= false;
694 auto OnFooReady
= [&](Expected
<SymbolMap
> Result
) {
695 EXPECT_THAT_EXPECTED(std::move(Result
), Failed());
696 OnFooReadyRun
= true;
699 ES
.lookup(LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
700 SymbolLookupSet(Foo
), SymbolState::Ready
, std::move(OnFooReady
),
701 NoDependenciesToRegister
);
703 bool OnBarReadyRun
= false;
704 auto OnBarReady
= [&](Expected
<SymbolMap
> Result
) {
705 EXPECT_THAT_EXPECTED(std::move(Result
), Failed());
706 OnBarReadyRun
= true;
709 ES
.lookup(LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
710 SymbolLookupSet(Bar
), SymbolState::Ready
, std::move(OnBarReady
),
711 NoDependenciesToRegister
);
713 // Add a dependency by Foo on Bar and vice-versa.
714 FooR
->addDependenciesForAll({{&JD
, SymbolNameSet({Bar
})}});
715 BarR
->addDependenciesForAll({{&JD
, SymbolNameSet({Foo
})}});
718 BarR
->failMaterialization();
720 // Verify that queries on Bar failed, but queries on Foo have not yet.
721 EXPECT_TRUE(OnBarReadyRun
) << "Query for \"Bar\" was not run";
722 EXPECT_FALSE(OnFooReadyRun
) << "Query for \"Foo\" was run unexpectedly";
724 // Verify that trying to resolve Foo fails.
725 EXPECT_THAT_ERROR(FooR
->notifyResolved({{Foo
, FooSym
}}), Failed())
726 << "Expected resolution for \"Foo\" to fail.";
728 FooR
->failMaterialization();
730 // Verify that queries on Foo have now failed.
731 EXPECT_TRUE(OnFooReadyRun
) << "Query for \"Foo\" was not run";
733 // Verify that subsequent lookups on Bar and Foo fail.
734 EXPECT_THAT_EXPECTED(ES
.lookup({&JD
}, {Bar
}), Failed())
735 << "Lookup on failed symbol should fail";
737 EXPECT_THAT_EXPECTED(ES
.lookup({&JD
}, {Foo
}), Failed())
738 << "Lookup on failed symbol should fail";
741 TEST_F(CoreAPIsStandardTest
, AddDependencyOnFailedSymbol
) {
742 std::unique_ptr
<MaterializationResponsibility
> FooR
;
743 std::unique_ptr
<MaterializationResponsibility
> BarR
;
745 // Create a MaterializationUnit for each symbol that moves the
746 // MaterializationResponsibility into one of the locals above.
747 auto FooMU
= std::make_unique
<SimpleMaterializationUnit
>(
748 SymbolFlagsMap({{Foo
, FooSym
.getFlags()}}),
749 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
753 auto BarMU
= std::make_unique
<SimpleMaterializationUnit
>(
754 SymbolFlagsMap({{Bar
, BarSym
.getFlags()}}),
755 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
759 // Define the symbols.
760 cantFail(JD
.define(FooMU
));
761 cantFail(JD
.define(BarMU
));
763 bool OnFooReadyRun
= false;
764 auto OnFooReady
= [&](Expected
<SymbolMap
> Result
) {
765 EXPECT_THAT_EXPECTED(std::move(Result
), Failed());
766 OnFooReadyRun
= true;
769 ES
.lookup(LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
770 SymbolLookupSet(Foo
), SymbolState::Ready
, std::move(OnFooReady
),
771 NoDependenciesToRegister
);
773 bool OnBarReadyRun
= false;
774 auto OnBarReady
= [&](Expected
<SymbolMap
> Result
) {
775 EXPECT_THAT_EXPECTED(std::move(Result
), Failed());
776 OnBarReadyRun
= true;
779 ES
.lookup(LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
780 SymbolLookupSet(Bar
), SymbolState::Ready
, std::move(OnBarReady
),
781 NoDependenciesToRegister
);
784 BarR
->failMaterialization();
786 // We expect Bar's query to fail immediately, but Foo's query not to have run
788 EXPECT_TRUE(OnBarReadyRun
) << "Query for \"Bar\" was not run";
789 EXPECT_FALSE(OnFooReadyRun
) << "Query for \"Foo\" should not have run yet";
791 // Add dependency of Foo on Bar.
792 FooR
->addDependenciesForAll({{&JD
, SymbolNameSet({Bar
})}});
794 // Check that we can still resolve Foo (even though it has been failed).
795 EXPECT_THAT_ERROR(FooR
->notifyResolved({{Foo
, FooSym
}}), Failed())
796 << "Expected resolution for \"Foo\" to fail.";
798 FooR
->failMaterialization();
800 // Foo's query should have failed before we return from addDependencies.
801 EXPECT_TRUE(OnFooReadyRun
) << "Query for \"Foo\" was not run";
803 // Verify that subsequent lookups on Bar and Foo fail.
804 EXPECT_THAT_EXPECTED(ES
.lookup({&JD
}, {Bar
}), Failed())
805 << "Lookup on failed symbol should fail";
807 EXPECT_THAT_EXPECTED(ES
.lookup({&JD
}, {Foo
}), Failed())
808 << "Lookup on failed symbol should fail";
811 TEST_F(CoreAPIsStandardTest
, FailAfterMaterialization
) {
812 std::unique_ptr
<MaterializationResponsibility
> FooR
;
813 std::unique_ptr
<MaterializationResponsibility
> BarR
;
815 // Create a MaterializationUnit for each symbol that moves the
816 // MaterializationResponsibility into one of the locals above.
817 auto FooMU
= std::make_unique
<SimpleMaterializationUnit
>(
818 SymbolFlagsMap({{Foo
, FooSym
.getFlags()}}),
819 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
823 auto BarMU
= std::make_unique
<SimpleMaterializationUnit
>(
824 SymbolFlagsMap({{Bar
, BarSym
.getFlags()}}),
825 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
829 // Define the symbols.
830 cantFail(JD
.define(FooMU
));
831 cantFail(JD
.define(BarMU
));
833 bool OnFooReadyRun
= false;
834 auto OnFooReady
= [&](Expected
<SymbolMap
> Result
) {
835 EXPECT_THAT_EXPECTED(std::move(Result
), Failed());
836 OnFooReadyRun
= true;
839 ES
.lookup(LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
840 SymbolLookupSet(Foo
), SymbolState::Ready
, std::move(OnFooReady
),
841 NoDependenciesToRegister
);
843 bool OnBarReadyRun
= false;
844 auto OnBarReady
= [&](Expected
<SymbolMap
> Result
) {
845 EXPECT_THAT_EXPECTED(std::move(Result
), Failed());
846 OnBarReadyRun
= true;
849 ES
.lookup(LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
850 SymbolLookupSet(Bar
), SymbolState::Ready
, std::move(OnBarReady
),
851 NoDependenciesToRegister
);
853 // Add a dependency by Foo on Bar and vice-versa.
854 FooR
->addDependenciesForAll({{&JD
, SymbolNameSet({Bar
})}});
855 BarR
->addDependenciesForAll({{&JD
, SymbolNameSet({Foo
})}});
858 EXPECT_THAT_ERROR(FooR
->notifyResolved({{Foo
, FooSym
}}), Succeeded())
859 << "Expected resolution for \"Foo\" to succeed.";
860 EXPECT_THAT_ERROR(FooR
->notifyEmitted(), Succeeded())
861 << "Expected emission for \"Foo\" to succeed.";
864 BarR
->failMaterialization();
866 // Verify that both queries failed.
867 EXPECT_TRUE(OnFooReadyRun
) << "Query for Foo did not run";
868 EXPECT_TRUE(OnBarReadyRun
) << "Query for Bar did not run";
871 TEST_F(CoreAPIsStandardTest
, FailMaterializerWithUnqueriedSymbols
) {
872 // Make sure that symbols with no queries aganist them still
875 bool MaterializerRun
= false;
876 auto MU
= std::make_unique
<SimpleMaterializationUnit
>(
878 {{Foo
, JITSymbolFlags::Exported
}, {Bar
, JITSymbolFlags::Exported
}}),
879 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
880 MaterializerRun
= true;
881 R
->failMaterialization();
884 cantFail(JD
.define(std::move(MU
)));
886 // Issue a query for Foo, but not bar.
887 EXPECT_THAT_EXPECTED(ES
.lookup({&JD
}, {Foo
}), Failed())
888 << "Expected lookup to fail.";
890 // Check that the materializer (and therefore failMaterialization) ran.
891 EXPECT_TRUE(MaterializerRun
) << "Expected materializer to have run by now";
893 // Check that subsequent queries against both symbols fail.
894 EXPECT_THAT_EXPECTED(ES
.lookup({&JD
}, {Foo
}), Failed())
895 << "Expected lookup for Foo to fail.";
896 EXPECT_THAT_EXPECTED(ES
.lookup({&JD
}, {Bar
}), Failed())
897 << "Expected lookup for Bar to fail.";
900 TEST_F(CoreAPIsStandardTest
, DropMaterializerWhenEmpty
) {
901 bool DestructorRun
= false;
903 JITSymbolFlags
WeakExported(JITSymbolFlags::Exported
);
904 WeakExported
|= JITSymbolFlags::Weak
;
906 auto MU
= std::make_unique
<SimpleMaterializationUnit
>(
907 SymbolFlagsMap({{Foo
, WeakExported
}, {Bar
, WeakExported
}}),
908 [](std::unique_ptr
<MaterializationResponsibility
> R
) {
909 llvm_unreachable("Unexpected call to materialize");
912 [&](const JITDylib
&JD
, SymbolStringPtr Name
) {
913 EXPECT_TRUE(Name
== Foo
|| Name
== Bar
)
914 << "Discard of unexpected symbol?";
916 [&]() { DestructorRun
= true; });
918 cantFail(JD
.define(MU
));
920 cantFail(JD
.define(absoluteSymbols({{Foo
, FooSym
}})));
922 EXPECT_FALSE(DestructorRun
)
923 << "MaterializationUnit should not have been destroyed yet";
925 cantFail(JD
.define(absoluteSymbols({{Bar
, BarSym
}})));
927 EXPECT_TRUE(DestructorRun
)
928 << "MaterializationUnit should have been destroyed";
931 TEST_F(CoreAPIsStandardTest
, AddAndMaterializeLazySymbol
) {
932 bool FooMaterialized
= false;
933 bool BarDiscarded
= false;
935 JITSymbolFlags
WeakExported(JITSymbolFlags::Exported
);
936 WeakExported
|= JITSymbolFlags::Weak
;
938 auto MU
= std::make_unique
<SimpleMaterializationUnit
>(
939 SymbolFlagsMap({{Foo
, JITSymbolFlags::Exported
}, {Bar
, WeakExported
}}),
940 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
941 assert(BarDiscarded
&& "Bar should have been discarded by this point");
942 cantFail(R
->notifyResolved(SymbolMap({{Foo
, FooSym
}})));
943 cantFail(R
->notifyEmitted());
944 FooMaterialized
= true;
947 [&](const JITDylib
&JD
, SymbolStringPtr Name
) {
948 EXPECT_EQ(Name
, Bar
) << "Expected Name to be Bar";
952 cantFail(JD
.define(MU
));
953 cantFail(JD
.define(absoluteSymbols({{Bar
, BarSym
}})));
955 bool OnCompletionRun
= false;
957 auto OnCompletion
= [&](Expected
<SymbolMap
> Result
) {
958 EXPECT_TRUE(!!Result
) << "Resolution unexpectedly returned error";
959 auto I
= Result
->find(Foo
);
960 EXPECT_NE(I
, Result
->end()) << "Could not find symbol definition";
961 EXPECT_EQ(I
->second
.getAddress(), FooSym
.getAddress())
962 << "Resolution returned incorrect result";
963 OnCompletionRun
= true;
966 ES
.lookup(LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
967 SymbolLookupSet(Foo
), SymbolState::Ready
, std::move(OnCompletion
),
968 NoDependenciesToRegister
);
970 EXPECT_TRUE(FooMaterialized
) << "Foo was not materialized";
971 EXPECT_TRUE(BarDiscarded
) << "Bar was not discarded";
972 EXPECT_TRUE(OnCompletionRun
) << "OnResolutionCallback was not run";
975 TEST_F(CoreAPIsStandardTest
, TestBasicWeakSymbolMaterialization
) {
976 // Test that weak symbols are materialized correctly when we look them up.
977 BarSym
.setFlags(BarSym
.getFlags() | JITSymbolFlags::Weak
);
979 bool BarMaterialized
= false;
980 auto MU1
= std::make_unique
<SimpleMaterializationUnit
>(
981 SymbolFlagsMap({{Foo
, FooSym
.getFlags()}, {Bar
, BarSym
.getFlags()}}),
982 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
983 cantFail(R
->notifyResolved(SymbolMap({{Foo
, FooSym
}, {Bar
, BarSym
}})));
984 cantFail(R
->notifyEmitted());
985 BarMaterialized
= true;
988 bool DuplicateBarDiscarded
= false;
989 auto MU2
= std::make_unique
<SimpleMaterializationUnit
>(
990 SymbolFlagsMap({{Bar
, BarSym
.getFlags()}}),
991 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
992 ADD_FAILURE() << "Attempt to materialize Bar from the wrong unit";
993 R
->failMaterialization();
996 [&](const JITDylib
&JD
, SymbolStringPtr Name
) {
997 EXPECT_EQ(Name
, Bar
) << "Expected \"Bar\" to be discarded";
998 DuplicateBarDiscarded
= true;
1001 cantFail(JD
.define(MU1
));
1002 cantFail(JD
.define(MU2
));
1004 bool OnCompletionRun
= false;
1006 auto OnCompletion
= [&](Expected
<SymbolMap
> Result
) {
1007 cantFail(std::move(Result
));
1008 OnCompletionRun
= true;
1011 ES
.lookup(LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
1012 SymbolLookupSet(Bar
), SymbolState::Ready
, std::move(OnCompletion
),
1013 NoDependenciesToRegister
);
1015 EXPECT_TRUE(OnCompletionRun
) << "OnCompletion not run";
1016 EXPECT_TRUE(BarMaterialized
) << "Bar was not materialized at all";
1017 EXPECT_TRUE(DuplicateBarDiscarded
)
1018 << "Duplicate bar definition not discarded";
1021 TEST_F(CoreAPIsStandardTest
, DefineMaterializingSymbol
) {
1022 bool ExpectNoMoreMaterialization
= false;
1023 ES
.setDispatchTask([&](std::unique_ptr
<Task
> T
) {
1024 if (ExpectNoMoreMaterialization
&& isa
<MaterializationTask
>(*T
))
1025 ADD_FAILURE() << "Unexpected materialization";
1029 auto MU
= std::make_unique
<SimpleMaterializationUnit
>(
1030 SymbolFlagsMap({{Foo
, FooSym
.getFlags()}}),
1031 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
1033 R
->defineMaterializing(SymbolFlagsMap({{Bar
, BarSym
.getFlags()}})));
1034 cantFail(R
->notifyResolved(SymbolMap({{Foo
, FooSym
}, {Bar
, BarSym
}})));
1035 cantFail(R
->notifyEmitted());
1038 cantFail(JD
.define(MU
));
1039 cantFail(ES
.lookup(makeJITDylibSearchOrder(&JD
), Foo
));
1041 // Assert that materialization is complete by now.
1042 ExpectNoMoreMaterialization
= true;
1044 // Look up bar to verify that no further materialization happens.
1045 auto BarResult
= cantFail(ES
.lookup(makeJITDylibSearchOrder(&JD
), Bar
));
1046 EXPECT_EQ(BarResult
.getAddress(), BarSym
.getAddress())
1047 << "Expected Bar == BarSym";
1050 TEST_F(CoreAPIsStandardTest
, GeneratorTest
) {
1051 JITEvaluatedSymbol
BazHiddenSym(
1052 BazSym
.getAddress(), BazSym
.getFlags() & ~JITSymbolFlags::Exported
);
1053 cantFail(JD
.define(absoluteSymbols({{Foo
, FooSym
}, {Baz
, BazHiddenSym
}})));
1055 class TestGenerator
: public DefinitionGenerator
{
1057 TestGenerator(SymbolMap Symbols
) : Symbols(std::move(Symbols
)) {}
1058 Error
tryToGenerate(LookupState
&LS
, LookupKind K
, JITDylib
&JD
,
1059 JITDylibLookupFlags JDLookupFlags
,
1060 const SymbolLookupSet
&Names
) override
{
1063 for (const auto &KV
: Names
) {
1064 const auto &Name
= KV
.first
;
1065 if (Symbols
.count(Name
))
1066 NewDefs
[Name
] = Symbols
[Name
];
1069 cantFail(JD
.define(absoluteSymbols(std::move(NewDefs
))));
1070 return Error::success();
1077 JD
.addGenerator(std::make_unique
<TestGenerator
>(
1078 SymbolMap({{Bar
, BarSym
}, {Baz
, BazSym
}})));
1080 auto Result
= cantFail(
1081 ES
.lookup(makeJITDylibSearchOrder(&JD
),
1082 SymbolLookupSet({Foo
, Bar
})
1083 .add(Baz
, SymbolLookupFlags::WeaklyReferencedSymbol
)));
1085 EXPECT_EQ(Result
.count(Bar
), 1U) << "Expected to find fallback def for 'bar'";
1086 EXPECT_EQ(Result
[Bar
].getAddress(), BarSym
.getAddress())
1087 << "Expected fallback def for Bar to be equal to BarSym";
1090 TEST_F(CoreAPIsStandardTest
, AsynchronousGeneratorTest
) {
1091 class TestGenerator
: public DefinitionGenerator
{
1093 TestGenerator(LookupState
&TLS
) : TLS(TLS
) {}
1094 Error
tryToGenerate(LookupState
&LS
, LookupKind K
, JITDylib
&JD
,
1095 JITDylibLookupFlags JDLookupFlags
,
1096 const SymbolLookupSet
&Name
) override
{
1097 TLS
= std::move(LS
);
1098 return Error::success();
1106 JD
.addGenerator(std::make_unique
<TestGenerator
>(LS
));
1108 bool LookupCompleted
= false;
1111 LookupKind::Static
, makeJITDylibSearchOrder(&JD
), SymbolLookupSet(Foo
),
1113 [&](Expected
<SymbolMap
> Result
) {
1114 LookupCompleted
= true;
1116 ADD_FAILURE() << "Lookup failed unexpected";
1117 logAllUnhandledErrors(Result
.takeError(), errs(), "");
1121 EXPECT_EQ(Result
->size(), 1U) << "Unexpected number of results";
1122 EXPECT_EQ(Result
->count(Foo
), 1U) << "Expected result for Foo";
1123 EXPECT_EQ((*Result
)[Foo
].getAddress(), FooSym
.getAddress())
1124 << "Bad result for Foo";
1126 NoDependenciesToRegister
);
1128 EXPECT_FALSE(LookupCompleted
);
1130 cantFail(JD
.define(absoluteSymbols({{Foo
, FooSym
}})));
1132 LS
.continueLookup(Error::success());
1134 EXPECT_TRUE(LookupCompleted
);
1137 TEST_F(CoreAPIsStandardTest
, FailResolution
) {
1138 auto MU
= std::make_unique
<SimpleMaterializationUnit
>(
1139 SymbolFlagsMap({{Foo
, JITSymbolFlags::Exported
| JITSymbolFlags::Weak
},
1140 {Bar
, JITSymbolFlags::Exported
| JITSymbolFlags::Weak
}}),
1141 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
1142 R
->failMaterialization();
1145 cantFail(JD
.define(MU
));
1147 SymbolNameSet
Names({Foo
, Bar
});
1148 auto Result
= ES
.lookup(makeJITDylibSearchOrder(&JD
), SymbolLookupSet(Names
));
1150 EXPECT_FALSE(!!Result
) << "Expected failure";
1154 [&](FailedToMaterialize
&F
) {
1155 EXPECT_TRUE(F
.getSymbols().count(&JD
))
1156 << "Expected to fail on JITDylib JD";
1157 EXPECT_EQ(F
.getSymbols().find(&JD
)->second
, Names
)
1158 << "Expected to fail on symbols in Names";
1160 [](ErrorInfoBase
&EIB
) {
1163 raw_string_ostream
ErrOut(ErrMsg
);
1166 ADD_FAILURE() << "Expected a FailedToResolve error. Got:\n" << ErrMsg
;
1171 TEST_F(CoreAPIsStandardTest
, FailEmissionAfterResolution
) {
1173 cantFail(JD
.define(absoluteSymbols({{Baz
, BazSym
}})));
1175 auto MU
= std::make_unique
<SimpleMaterializationUnit
>(
1176 SymbolFlagsMap({{Foo
, FooSym
.getFlags()}, {Bar
, BarSym
.getFlags()}}),
1177 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
1178 cantFail(R
->notifyResolved(SymbolMap({{Foo
, FooSym
}, {Bar
, BarSym
}})));
1181 LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
1182 SymbolLookupSet({Baz
}), SymbolState::Resolved
,
1183 [&](Expected
<SymbolMap
> Result
) {
1184 // Called when "baz" is resolved. We don't actually depend
1185 // on or care about baz, but use it to trigger failure of
1186 // this materialization before Baz has been finalized in
1187 // order to test that error propagation is correct in this
1189 cantFail(std::move(Result
));
1190 R
->failMaterialization();
1192 [&](const SymbolDependenceMap
&Deps
) {
1193 R
->addDependenciesForAll(Deps
);
1197 cantFail(JD
.define(MU
));
1200 ES
.lookup(makeJITDylibSearchOrder(&JD
), SymbolLookupSet({Foo
, Bar
}));
1202 EXPECT_THAT_EXPECTED(std::move(Result
), Failed())
1203 << "Unexpected success while trying to test error propagation";
1206 TEST_F(CoreAPIsStandardTest
, FailAfterPartialResolution
) {
1208 cantFail(JD
.define(absoluteSymbols({{Foo
, FooSym
}})));
1210 // Fail materialization of bar.
1211 auto BarMU
= std::make_unique
<SimpleMaterializationUnit
>(
1212 SymbolFlagsMap({{Bar
, BarSym
.getFlags()}}),
1213 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
1214 R
->failMaterialization();
1217 cantFail(JD
.define(std::move(BarMU
)));
1219 bool QueryHandlerRun
= false;
1221 LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
1222 SymbolLookupSet({Foo
, Bar
}), SymbolState::Resolved
,
1223 [&](Expected
<SymbolMap
> Result
) {
1224 EXPECT_THAT_EXPECTED(std::move(Result
), Failed())
1225 << "Expected query to fail";
1226 QueryHandlerRun
= true;
1228 NoDependenciesToRegister
);
1229 EXPECT_TRUE(QueryHandlerRun
) << "Query handler never ran";
1232 TEST_F(CoreAPIsStandardTest
, TestLookupWithUnthreadedMaterialization
) {
1233 auto MU
= std::make_unique
<SimpleMaterializationUnit
>(
1234 SymbolFlagsMap({{Foo
, JITSymbolFlags::Exported
}}),
1235 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
1236 cantFail(R
->notifyResolved({{Foo
, FooSym
}}));
1237 cantFail(R
->notifyEmitted());
1240 cantFail(JD
.define(MU
));
1242 auto FooLookupResult
= cantFail(ES
.lookup(makeJITDylibSearchOrder(&JD
), Foo
));
1244 EXPECT_EQ(FooLookupResult
.getAddress(), FooSym
.getAddress())
1245 << "lookup returned an incorrect address";
1246 EXPECT_EQ(FooLookupResult
.getFlags(), FooSym
.getFlags())
1247 << "lookup returned incorrect flags";
1250 TEST_F(CoreAPIsStandardTest
, TestLookupWithThreadedMaterialization
) {
1251 #if LLVM_ENABLE_THREADS
1253 std::mutex WorkThreadsMutex
;
1254 std::vector
<std::thread
> WorkThreads
;
1255 ES
.setDispatchTask([&](std::unique_ptr
<Task
> T
) {
1256 std::promise
<void> WaitP
;
1257 std::lock_guard
<std::mutex
> Lock(WorkThreadsMutex
);
1258 WorkThreads
.push_back(
1259 std::thread([T
= std::move(T
), WaitF
= WaitP
.get_future()]() mutable {
1266 cantFail(JD
.define(absoluteSymbols({{Foo
, FooSym
}})));
1268 auto FooLookupResult
= cantFail(ES
.lookup(makeJITDylibSearchOrder(&JD
), Foo
));
1270 EXPECT_EQ(FooLookupResult
.getAddress(), FooSym
.getAddress())
1271 << "lookup returned an incorrect address";
1272 EXPECT_EQ(FooLookupResult
.getFlags(), FooSym
.getFlags())
1273 << "lookup returned incorrect flags";
1275 for (auto &WT
: WorkThreads
)
1280 TEST_F(CoreAPIsStandardTest
, TestGetRequestedSymbolsAndReplace
) {
1281 // Test that GetRequestedSymbols returns the set of symbols that currently
1282 // have pending queries, and test that MaterializationResponsibility's
1283 // replace method can be used to return definitions to the JITDylib in a new
1284 // MaterializationUnit.
1285 SymbolNameSet
Names({Foo
, Bar
});
1287 bool FooMaterialized
= false;
1288 bool BarMaterialized
= false;
1290 auto MU
= std::make_unique
<SimpleMaterializationUnit
>(
1291 SymbolFlagsMap({{Foo
, FooSym
.getFlags()}, {Bar
, BarSym
.getFlags()}}),
1292 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
1293 auto Requested
= R
->getRequestedSymbols();
1294 EXPECT_EQ(Requested
.size(), 1U) << "Expected one symbol requested";
1295 EXPECT_EQ(*Requested
.begin(), Foo
) << "Expected \"Foo\" requested";
1297 auto NewMU
= std::make_unique
<SimpleMaterializationUnit
>(
1298 SymbolFlagsMap({{Bar
, BarSym
.getFlags()}}),
1299 [&](std::unique_ptr
<MaterializationResponsibility
> R2
) {
1300 cantFail(R2
->notifyResolved(SymbolMap({{Bar
, BarSym
}})));
1301 cantFail(R2
->notifyEmitted());
1302 BarMaterialized
= true;
1305 cantFail(R
->replace(std::move(NewMU
)));
1307 cantFail(R
->notifyResolved(SymbolMap({{Foo
, FooSym
}})));
1308 cantFail(R
->notifyEmitted());
1310 FooMaterialized
= true;
1313 cantFail(JD
.define(MU
));
1315 EXPECT_FALSE(FooMaterialized
) << "Foo should not be materialized yet";
1316 EXPECT_FALSE(BarMaterialized
) << "Bar should not be materialized yet";
1318 auto FooSymResult
= cantFail(ES
.lookup(makeJITDylibSearchOrder(&JD
), Foo
));
1319 EXPECT_EQ(FooSymResult
.getAddress(), FooSym
.getAddress())
1320 << "Address mismatch for Foo";
1322 EXPECT_TRUE(FooMaterialized
) << "Foo should be materialized now";
1323 EXPECT_FALSE(BarMaterialized
) << "Bar still should not be materialized";
1325 auto BarSymResult
= cantFail(ES
.lookup(makeJITDylibSearchOrder(&JD
), Bar
));
1326 EXPECT_EQ(BarSymResult
.getAddress(), BarSym
.getAddress())
1327 << "Address mismatch for Bar";
1328 EXPECT_TRUE(BarMaterialized
) << "Bar should be materialized now";
1331 TEST_F(CoreAPIsStandardTest
, TestMaterializationResponsibilityDelegation
) {
1332 auto MU
= std::make_unique
<SimpleMaterializationUnit
>(
1333 SymbolFlagsMap({{Foo
, FooSym
.getFlags()}, {Bar
, BarSym
.getFlags()}}),
1334 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
1335 auto R2
= cantFail(R
->delegate({Bar
}));
1337 cantFail(R
->notifyResolved({{Foo
, FooSym
}}));
1338 cantFail(R
->notifyEmitted());
1339 cantFail(R2
->notifyResolved({{Bar
, BarSym
}}));
1340 cantFail(R2
->notifyEmitted());
1343 cantFail(JD
.define(MU
));
1346 ES
.lookup(makeJITDylibSearchOrder(&JD
), SymbolLookupSet({Foo
, Bar
}));
1348 EXPECT_TRUE(!!Result
) << "Result should be a success value";
1349 EXPECT_EQ(Result
->count(Foo
), 1U) << "\"Foo\" entry missing";
1350 EXPECT_EQ(Result
->count(Bar
), 1U) << "\"Bar\" entry missing";
1351 EXPECT_EQ((*Result
)[Foo
].getAddress(), FooSym
.getAddress())
1352 << "Address mismatch for \"Foo\"";
1353 EXPECT_EQ((*Result
)[Bar
].getAddress(), BarSym
.getAddress())
1354 << "Address mismatch for \"Bar\"";
1357 TEST_F(CoreAPIsStandardTest
, TestMaterializeWeakSymbol
) {
1358 // Confirm that once a weak definition is selected for materialization it is
1359 // treated as strong.
1360 JITSymbolFlags WeakExported
= JITSymbolFlags::Exported
;
1361 WeakExported
&= JITSymbolFlags::Weak
;
1363 std::unique_ptr
<MaterializationResponsibility
> FooR
;
1364 auto MU
= std::make_unique
<SimpleMaterializationUnit
>(
1365 SymbolFlagsMap({{Foo
, FooSym
.getFlags()}}),
1366 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
1367 FooR
= std::move(R
);
1370 cantFail(JD
.define(MU
));
1371 auto OnCompletion
= [](Expected
<SymbolMap
> Result
) {
1372 cantFail(std::move(Result
));
1375 ES
.lookup(LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
1376 SymbolLookupSet({Foo
}), SymbolState::Ready
, std::move(OnCompletion
),
1377 NoDependenciesToRegister
);
1379 auto MU2
= std::make_unique
<SimpleMaterializationUnit
>(
1380 SymbolFlagsMap({{Foo
, JITSymbolFlags::Exported
}}),
1381 [](std::unique_ptr
<MaterializationResponsibility
> R
) {
1382 llvm_unreachable("This unit should never be materialized");
1385 auto Err
= JD
.define(MU2
);
1386 EXPECT_TRUE(!!Err
) << "Expected failure value";
1387 EXPECT_TRUE(Err
.isA
<DuplicateDefinition
>())
1388 << "Expected a duplicate definition error";
1389 consumeError(std::move(Err
));
1391 // No dependencies registered, can't fail:
1392 cantFail(FooR
->notifyResolved(SymbolMap({{Foo
, FooSym
}})));
1393 cantFail(FooR
->notifyEmitted());
1396 static bool linkOrdersEqual(const std::vector
<JITDylibSP
> &LHS
,
1397 ArrayRef
<JITDylib
*> RHS
) {
1398 if (LHS
.size() != RHS
.size())
1400 auto *RHSE
= RHS
.begin();
1401 for (auto &LHSE
: LHS
)
1402 if (LHSE
.get() != *RHSE
)
1409 TEST(JITDylibTest
, GetDFSLinkOrderTree
) {
1410 // Test that DFS ordering behaves as expected when the linkage relationships
1413 ExecutionSession ES
{std::make_unique
<UnsupportedExecutorProcessControl
>()};
1414 auto _
= make_scope_exit([&]() { cantFail(ES
.endSession()); });
1416 auto &LibA
= ES
.createBareJITDylib("A");
1417 auto &LibB
= ES
.createBareJITDylib("B");
1418 auto &LibC
= ES
.createBareJITDylib("C");
1419 auto &LibD
= ES
.createBareJITDylib("D");
1420 auto &LibE
= ES
.createBareJITDylib("E");
1421 auto &LibF
= ES
.createBareJITDylib("F");
1423 // Linkage relationships:
1427 LibA
.setLinkOrder(makeJITDylibSearchOrder({&LibB
, &LibC
}));
1428 LibB
.setLinkOrder(makeJITDylibSearchOrder({&LibD
, &LibE
}));
1429 LibC
.setLinkOrder(makeJITDylibSearchOrder({&LibF
}));
1431 auto DFSOrderFromB
= cantFail(JITDylib::getDFSLinkOrder({&LibB
}));
1432 EXPECT_TRUE(linkOrdersEqual(DFSOrderFromB
, {&LibB
, &LibD
, &LibE
}))
1433 << "Incorrect DFS link order for LibB";
1435 auto DFSOrderFromA
= cantFail(JITDylib::getDFSLinkOrder({&LibA
}));
1436 EXPECT_TRUE(linkOrdersEqual(DFSOrderFromA
,
1437 {&LibA
, &LibB
, &LibD
, &LibE
, &LibC
, &LibF
}))
1438 << "Incorrect DFS link order for libA";
1440 auto DFSOrderFromAB
= cantFail(JITDylib::getDFSLinkOrder({&LibA
, &LibB
}));
1441 EXPECT_TRUE(linkOrdersEqual(DFSOrderFromAB
,
1442 {&LibA
, &LibB
, &LibD
, &LibE
, &LibC
, &LibF
}))
1443 << "Incorrect DFS link order for { libA, libB }";
1445 auto DFSOrderFromBA
= cantFail(JITDylib::getDFSLinkOrder({&LibB
, &LibA
}));
1446 EXPECT_TRUE(linkOrdersEqual(DFSOrderFromBA
,
1447 {&LibB
, &LibD
, &LibE
, &LibA
, &LibC
, &LibF
}))
1448 << "Incorrect DFS link order for { libB, libA }";
1451 TEST(JITDylibTest
, GetDFSLinkOrderDiamond
) {
1452 // Test that DFS ordering behaves as expected when the linkage relationships
1453 // contain a diamond.
1455 ExecutionSession ES
{std::make_unique
<UnsupportedExecutorProcessControl
>()};
1456 auto _
= make_scope_exit([&]() { cantFail(ES
.endSession()); });
1458 auto &LibA
= ES
.createBareJITDylib("A");
1459 auto &LibB
= ES
.createBareJITDylib("B");
1460 auto &LibC
= ES
.createBareJITDylib("C");
1461 auto &LibD
= ES
.createBareJITDylib("D");
1463 // Linkage relationships:
1466 LibA
.setLinkOrder(makeJITDylibSearchOrder({&LibB
, &LibC
}));
1467 LibB
.setLinkOrder(makeJITDylibSearchOrder({&LibD
}));
1468 LibC
.setLinkOrder(makeJITDylibSearchOrder({&LibD
}));
1470 auto DFSOrderFromA
= cantFail(JITDylib::getDFSLinkOrder({&LibA
}));
1471 EXPECT_TRUE(linkOrdersEqual(DFSOrderFromA
, {&LibA
, &LibB
, &LibD
, &LibC
}))
1472 << "Incorrect DFS link order for libA";
1475 TEST(JITDylibTest
, GetDFSLinkOrderCycle
) {
1476 // Test that DFS ordering behaves as expected when the linkage relationships
1479 ExecutionSession ES
{std::make_unique
<UnsupportedExecutorProcessControl
>()};
1480 auto _
= make_scope_exit([&]() { cantFail(ES
.endSession()); });
1482 auto &LibA
= ES
.createBareJITDylib("A");
1483 auto &LibB
= ES
.createBareJITDylib("B");
1484 auto &LibC
= ES
.createBareJITDylib("C");
1486 // Linkage relationships:
1487 // A -- B --- C -- A
1488 LibA
.setLinkOrder(makeJITDylibSearchOrder({&LibB
}));
1489 LibB
.setLinkOrder(makeJITDylibSearchOrder({&LibC
}));
1490 LibC
.setLinkOrder(makeJITDylibSearchOrder({&LibA
}));
1492 auto DFSOrderFromA
= cantFail(JITDylib::getDFSLinkOrder({&LibA
}));
1493 EXPECT_TRUE(linkOrdersEqual(DFSOrderFromA
, {&LibA
, &LibB
, &LibC
}))
1494 << "Incorrect DFS link order for libA";
1496 auto DFSOrderFromB
= cantFail(JITDylib::getDFSLinkOrder({&LibB
}));
1497 EXPECT_TRUE(linkOrdersEqual(DFSOrderFromB
, {&LibB
, &LibC
, &LibA
}))
1498 << "Incorrect DFS link order for libB";
1500 auto DFSOrderFromC
= cantFail(JITDylib::getDFSLinkOrder({&LibC
}));
1501 EXPECT_TRUE(linkOrdersEqual(DFSOrderFromC
, {&LibC
, &LibA
, &LibB
}))
1502 << "Incorrect DFS link order for libC";
1505 TEST_F(CoreAPIsStandardTest
, RemoveJITDylibs
) {
1506 // Foo will be fully materialized.
1507 cantFail(JD
.define(absoluteSymbols({{Foo
, FooSym
}})));
1509 // Bar should not be materialized at all.
1510 bool BarMaterializerDestroyed
= false;
1511 cantFail(JD
.define(std::make_unique
<SimpleMaterializationUnit
>(
1512 SymbolFlagsMap({{Bar
, BarSym
.getFlags()}}),
1513 [&](std::unique_ptr
<MaterializationResponsibility
> MR
) {
1514 llvm_unreachable("Unexpected call to materialize");
1517 [](const JITDylib
&, SymbolStringPtr Name
) {
1518 llvm_unreachable("Unexpected call to discard");
1520 [&]() { BarMaterializerDestroyed
= true; })));
1522 // Baz will be in the materializing state.
1523 std::unique_ptr
<MaterializationResponsibility
> BazMR
;
1524 cantFail(JD
.define(std::make_unique
<SimpleMaterializationUnit
>(
1525 SymbolFlagsMap({{Baz
, BazSym
.getFlags()}}),
1526 [&](std::unique_ptr
<MaterializationResponsibility
> MR
) {
1527 BazMR
= std::move(MR
);
1530 // Lookup to force materialization of Foo.
1531 cantFail(ES
.lookup(makeJITDylibSearchOrder(&JD
), SymbolLookupSet({Foo
})));
1533 // Start a lookup to force materialization of Baz.
1534 bool BazLookupFailed
= false;
1536 LookupKind::Static
, makeJITDylibSearchOrder(&JD
), SymbolLookupSet({Baz
}),
1538 [&](Expected
<SymbolMap
> Result
) {
1540 BazLookupFailed
= true;
1541 consumeError(Result
.takeError());
1544 NoDependenciesToRegister
);
1546 // Remove the JITDylib.
1547 auto Err
= ES
.removeJITDylib(JD
);
1548 EXPECT_THAT_ERROR(std::move(Err
), Succeeded());
1550 EXPECT_TRUE(BarMaterializerDestroyed
);
1551 EXPECT_TRUE(BazLookupFailed
);
1553 EXPECT_THAT_ERROR(BazMR
->notifyResolved({{Baz
, BazSym
}}), Failed());
1555 EXPECT_THAT_EXPECTED(JD
.getDFSLinkOrder(), Failed());
1557 BazMR
->failMaterialization();
1560 TEST(CoreAPIsExtraTest
, SessionTeardownByFailedToMaterialize
) {
1562 auto RunTestCase
= []() -> Error
{
1563 ExecutionSession ES
{std::make_unique
<UnsupportedExecutorProcessControl
>(
1564 std::make_shared
<SymbolStringPool
>())};
1565 auto Foo
= ES
.intern("foo");
1566 auto FooFlags
= JITSymbolFlags::Exported
;
1568 auto &JD
= ES
.createBareJITDylib("Foo");
1569 cantFail(JD
.define(std::make_unique
<SimpleMaterializationUnit
>(
1570 SymbolFlagsMap({{Foo
, FooFlags
}}),
1571 [&](std::unique_ptr
<MaterializationResponsibility
> R
) {
1572 R
->failMaterialization();
1575 auto Sym
= ES
.lookup({&JD
}, Foo
);
1576 assert(!Sym
&& "Query should have failed");
1577 cantFail(ES
.endSession());
1578 return Sym
.takeError();
1581 auto Err
= RunTestCase();
1582 EXPECT_TRUE(!!Err
); // Expect that error occurred.
1584 Err
.isA
<FailedToMaterialize
>()); // Expect FailedToMaterialize error.
1586 // Make sure that we can log errors, even though the session has been
1588 logAllUnhandledErrors(std::move(Err
), nulls(), "");