1b66b73beSStefan Gränitz //===------ ResourceTrackerTest.cpp - Unit tests ResourceTracker API ------===//
20aec49c8SLang Hames //
30aec49c8SLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40aec49c8SLang Hames // See https://llvm.org/LICENSE.txt for license information.
50aec49c8SLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60aec49c8SLang Hames //
70aec49c8SLang Hames //===----------------------------------------------------------------------===//
80aec49c8SLang Hames
90aec49c8SLang Hames #include "OrcTestCommon.h"
100aec49c8SLang Hames #include "llvm/ADT/FunctionExtras.h"
110aec49c8SLang Hames #include "llvm/Config/llvm-config.h"
120aec49c8SLang Hames #include "llvm/ExecutionEngine/Orc/Core.h"
1324672ddeSLang Hames #include "llvm/ExecutionEngine/Orc/Shared/OrcError.h"
140aec49c8SLang Hames #include "llvm/Testing/Support/Error.h"
150aec49c8SLang Hames
160aec49c8SLang Hames using namespace llvm;
170aec49c8SLang Hames using namespace llvm::orc;
180aec49c8SLang Hames
190aec49c8SLang Hames class ResourceTrackerStandardTest : public CoreAPIsBasedStandardTest {};
200aec49c8SLang Hames
210aec49c8SLang Hames namespace {
220aec49c8SLang Hames
230aec49c8SLang Hames template <typename ResourceT = unsigned>
240aec49c8SLang Hames class SimpleResourceManager : public ResourceManager {
250aec49c8SLang Hames public:
26bf6d7ca9SLang Hames using HandleRemoveFunction =
27bf6d7ca9SLang Hames unique_function<Error(JITDylib &JD, ResourceKey)>;
280aec49c8SLang Hames
290aec49c8SLang Hames using HandleTransferFunction =
30bf6d7ca9SLang Hames unique_function<void(JITDylib &JD, ResourceKey, ResourceKey)>;
310aec49c8SLang Hames
320aec49c8SLang Hames using RecordedResourcesMap = DenseMap<ResourceKey, ResourceT>;
330aec49c8SLang Hames
SimpleResourceManager(ExecutionSession & ES)34d54c4e38SLang Hames SimpleResourceManager(ExecutionSession &ES) : ES(ES) {
35bf6d7ca9SLang Hames HandleRemove = [&](JITDylib &JD, ResourceKey K) -> Error {
36bf6d7ca9SLang Hames ES.runSessionLocked([&] { removeResource(JD, K); });
370aec49c8SLang Hames return Error::success();
380aec49c8SLang Hames };
390aec49c8SLang Hames
40bf6d7ca9SLang Hames HandleTransfer = [this](JITDylib &JD, ResourceKey DstKey,
41bf6d7ca9SLang Hames ResourceKey SrcKey) {
42bf6d7ca9SLang Hames transferResources(JD, DstKey, SrcKey);
430aec49c8SLang Hames };
440aec49c8SLang Hames
450aec49c8SLang Hames ES.registerResourceManager(*this);
460aec49c8SLang Hames }
470aec49c8SLang Hames
480aec49c8SLang Hames SimpleResourceManager(const SimpleResourceManager &) = delete;
490aec49c8SLang Hames SimpleResourceManager &operator=(const SimpleResourceManager &) = delete;
500aec49c8SLang Hames SimpleResourceManager(SimpleResourceManager &&) = delete;
510aec49c8SLang Hames SimpleResourceManager &operator=(SimpleResourceManager &&) = delete;
520aec49c8SLang Hames
~SimpleResourceManager()530aec49c8SLang Hames ~SimpleResourceManager() { ES.deregisterResourceManager(*this); }
540aec49c8SLang Hames
55d54c4e38SLang Hames /// Set the HandleRemove function object.
setHandleRemove(HandleRemoveFunction HandleRemove)56d54c4e38SLang Hames void setHandleRemove(HandleRemoveFunction HandleRemove) {
57d54c4e38SLang Hames this->HandleRemove = std::move(HandleRemove);
58d54c4e38SLang Hames }
59d54c4e38SLang Hames
60d54c4e38SLang Hames /// Set the HandleTransfer function object.
setHandleTransfer(HandleTransferFunction HandleTransfer)61d54c4e38SLang Hames void setHandleTransfer(HandleTransferFunction HandleTransfer) {
62d54c4e38SLang Hames this->HandleTransfer = std::move(HandleTransfer);
63d54c4e38SLang Hames }
64d54c4e38SLang Hames
650aec49c8SLang Hames /// Create an association between the given key and resource.
660aec49c8SLang Hames template <typename MergeOp = std::plus<ResourceT>>
recordResource(ResourceKey K,ResourceT Val=ResourceT (),MergeOp Merge=MergeOp ())670aec49c8SLang Hames void recordResource(ResourceKey K, ResourceT Val = ResourceT(),
680aec49c8SLang Hames MergeOp Merge = MergeOp()) {
690aec49c8SLang Hames auto Tmp = std::move(Resources[K]);
700aec49c8SLang Hames Resources[K] = Merge(std::move(Tmp), std::move(Val));
710aec49c8SLang Hames }
720aec49c8SLang Hames
730aec49c8SLang Hames /// Remove the resource associated with K from the map if present.
removeResource(JITDylib & JD,ResourceKey K)74bf6d7ca9SLang Hames void removeResource(JITDylib &JD, ResourceKey K) { Resources.erase(K); }
750aec49c8SLang Hames
760aec49c8SLang Hames /// Transfer resources from DstKey to SrcKey.
770aec49c8SLang Hames template <typename MergeOp = std::plus<ResourceT>>
transferResources(JITDylib & JD,ResourceKey DstKey,ResourceKey SrcKey,MergeOp Merge=MergeOp ())78bf6d7ca9SLang Hames void transferResources(JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey,
790aec49c8SLang Hames MergeOp Merge = MergeOp()) {
800aec49c8SLang Hames auto &DstResourceRef = Resources[DstKey];
810aec49c8SLang Hames ResourceT DstResources;
820aec49c8SLang Hames std::swap(DstResourceRef, DstResources);
830aec49c8SLang Hames
840aec49c8SLang Hames auto SI = Resources.find(SrcKey);
850aec49c8SLang Hames assert(SI != Resources.end() && "No resource associated with SrcKey");
860aec49c8SLang Hames
870aec49c8SLang Hames DstResourceRef = Merge(std::move(DstResources), std::move(SI->second));
880aec49c8SLang Hames Resources.erase(SI);
890aec49c8SLang Hames }
900aec49c8SLang Hames
910aec49c8SLang Hames /// Return a reference to the Resources map.
getRecordedResources()920aec49c8SLang Hames RecordedResourcesMap &getRecordedResources() { return Resources; }
getRecordedResources() const930aec49c8SLang Hames const RecordedResourcesMap &getRecordedResources() const { return Resources; }
940aec49c8SLang Hames
handleRemoveResources(JITDylib & JD,ResourceKey K)95bf6d7ca9SLang Hames Error handleRemoveResources(JITDylib &JD, ResourceKey K) override {
96bf6d7ca9SLang Hames return HandleRemove(JD, K);
970aec49c8SLang Hames }
980aec49c8SLang Hames
handleTransferResources(JITDylib & JD,ResourceKey DstKey,ResourceKey SrcKey)99bf6d7ca9SLang Hames void handleTransferResources(JITDylib &JD, ResourceKey DstKey,
1000aec49c8SLang Hames ResourceKey SrcKey) override {
101bf6d7ca9SLang Hames HandleTransfer(JD, DstKey, SrcKey);
1020aec49c8SLang Hames }
1030aec49c8SLang Hames
transferNotAllowed(ResourceKey DstKey,ResourceKey SrcKey)1040aec49c8SLang Hames static void transferNotAllowed(ResourceKey DstKey, ResourceKey SrcKey) {
1050aec49c8SLang Hames llvm_unreachable("Resource transfer not allowed");
1060aec49c8SLang Hames }
1070aec49c8SLang Hames
1080aec49c8SLang Hames private:
1090aec49c8SLang Hames ExecutionSession &ES;
1100aec49c8SLang Hames HandleRemoveFunction HandleRemove;
1110aec49c8SLang Hames HandleTransferFunction HandleTransfer;
1120aec49c8SLang Hames RecordedResourcesMap Resources;
1130aec49c8SLang Hames };
1140aec49c8SLang Hames
TEST_F(ResourceTrackerStandardTest,BasicDefineAndRemoveAllBeforeMaterializing)1150aec49c8SLang Hames TEST_F(ResourceTrackerStandardTest,
1160aec49c8SLang Hames BasicDefineAndRemoveAllBeforeMaterializing) {
1170aec49c8SLang Hames
1180aec49c8SLang Hames bool ResourceManagerGotRemove = false;
119d54c4e38SLang Hames SimpleResourceManager<> SRM(ES);
120bf6d7ca9SLang Hames SRM.setHandleRemove([&](JITDylib &JD, ResourceKey K) -> Error {
1210aec49c8SLang Hames ResourceManagerGotRemove = true;
1220aec49c8SLang Hames EXPECT_EQ(SRM.getRecordedResources().size(), 0U)
1230aec49c8SLang Hames << "Unexpected resources recorded";
124bf6d7ca9SLang Hames SRM.removeResource(JD, K);
1250aec49c8SLang Hames return Error::success();
1260aec49c8SLang Hames });
1270aec49c8SLang Hames
1280aec49c8SLang Hames bool MaterializationUnitDestroyed = false;
1290aec49c8SLang Hames auto MU = std::make_unique<SimpleMaterializationUnit>(
1300aec49c8SLang Hames SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
1310aec49c8SLang Hames [&](std::unique_ptr<MaterializationResponsibility> R) {
1320aec49c8SLang Hames llvm_unreachable("Never called");
1330aec49c8SLang Hames },
1340aec49c8SLang Hames nullptr, SimpleMaterializationUnit::DiscardFunction(),
1350aec49c8SLang Hames [&]() { MaterializationUnitDestroyed = true; });
1360aec49c8SLang Hames
1370aec49c8SLang Hames auto RT = JD.createResourceTracker();
1380aec49c8SLang Hames cantFail(JD.define(std::move(MU), RT));
1390aec49c8SLang Hames cantFail(RT->remove());
140069919c9SLang Hames auto SymFlags = cantFail(ES.lookupFlags(
141069919c9SLang Hames LookupKind::Static,
142069919c9SLang Hames {{&JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
143069919c9SLang Hames SymbolLookupSet(Foo, SymbolLookupFlags::WeaklyReferencedSymbol)));
1440aec49c8SLang Hames
1450aec49c8SLang Hames EXPECT_EQ(SymFlags.size(), 0U)
1460aec49c8SLang Hames << "Symbols should have been removed from the symbol table";
1470aec49c8SLang Hames EXPECT_TRUE(ResourceManagerGotRemove)
1480aec49c8SLang Hames << "ResourceManager did not receive handleRemoveResources";
1490aec49c8SLang Hames EXPECT_TRUE(MaterializationUnitDestroyed)
1500aec49c8SLang Hames << "MaterializationUnit not destroyed in response to removal";
1510aec49c8SLang Hames }
1520aec49c8SLang Hames
TEST_F(ResourceTrackerStandardTest,BasicDefineAndRemoveAllAfterMaterializing)1530aec49c8SLang Hames TEST_F(ResourceTrackerStandardTest, BasicDefineAndRemoveAllAfterMaterializing) {
1540aec49c8SLang Hames
1550aec49c8SLang Hames bool ResourceManagerGotRemove = false;
156d54c4e38SLang Hames SimpleResourceManager<> SRM(ES);
157bf6d7ca9SLang Hames SRM.setHandleRemove([&](JITDylib &JD, ResourceKey K) -> Error {
1580aec49c8SLang Hames ResourceManagerGotRemove = true;
1590aec49c8SLang Hames EXPECT_EQ(SRM.getRecordedResources().size(), 1U)
1600aec49c8SLang Hames << "Unexpected number of resources recorded";
1610aec49c8SLang Hames EXPECT_EQ(SRM.getRecordedResources().count(K), 1U)
1620aec49c8SLang Hames << "Unexpected recorded resource";
163bf6d7ca9SLang Hames SRM.removeResource(JD, K);
1640aec49c8SLang Hames return Error::success();
1650aec49c8SLang Hames });
1660aec49c8SLang Hames
1670aec49c8SLang Hames auto MU = std::make_unique<SimpleMaterializationUnit>(
1680aec49c8SLang Hames SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
1690aec49c8SLang Hames [&](std::unique_ptr<MaterializationResponsibility> R) {
1700aec49c8SLang Hames cantFail(R->withResourceKeyDo(
1710aec49c8SLang Hames [&](ResourceKey K) { SRM.recordResource(K); }));
1720aec49c8SLang Hames cantFail(R->notifyResolved({{Foo, FooSym}}));
173*ebe8733aSlhames cantFail(R->notifyEmitted({}));
1740aec49c8SLang Hames });
1750aec49c8SLang Hames
1760aec49c8SLang Hames auto RT = JD.createResourceTracker();
1770aec49c8SLang Hames cantFail(JD.define(std::move(MU), RT));
1780aec49c8SLang Hames cantFail(ES.lookup({&JD}, Foo));
1790aec49c8SLang Hames cantFail(RT->remove());
180069919c9SLang Hames auto SymFlags = cantFail(ES.lookupFlags(
181069919c9SLang Hames LookupKind::Static,
182069919c9SLang Hames {{&JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
183069919c9SLang Hames SymbolLookupSet(Foo, SymbolLookupFlags::WeaklyReferencedSymbol)));
1840aec49c8SLang Hames
1850aec49c8SLang Hames EXPECT_EQ(SymFlags.size(), 0U)
1860aec49c8SLang Hames << "Symbols should have been removed from the symbol table";
1870aec49c8SLang Hames EXPECT_TRUE(ResourceManagerGotRemove)
1880aec49c8SLang Hames << "ResourceManager did not receive handleRemoveResources";
1890aec49c8SLang Hames }
1900aec49c8SLang Hames
TEST_F(ResourceTrackerStandardTest,BasicDefineAndRemoveAllWhileMaterializing)1910aec49c8SLang Hames TEST_F(ResourceTrackerStandardTest, BasicDefineAndRemoveAllWhileMaterializing) {
1920aec49c8SLang Hames
1930aec49c8SLang Hames bool ResourceManagerGotRemove = false;
194d54c4e38SLang Hames SimpleResourceManager<> SRM(ES);
195bf6d7ca9SLang Hames SRM.setHandleRemove([&](JITDylib &JD, ResourceKey K) -> Error {
1960aec49c8SLang Hames ResourceManagerGotRemove = true;
1970aec49c8SLang Hames EXPECT_EQ(SRM.getRecordedResources().size(), 0U)
1980aec49c8SLang Hames << "Unexpected resources recorded";
199bf6d7ca9SLang Hames SRM.removeResource(JD, K);
2000aec49c8SLang Hames return Error::success();
2010aec49c8SLang Hames });
2020aec49c8SLang Hames
2030aec49c8SLang Hames std::unique_ptr<MaterializationResponsibility> MR;
2040aec49c8SLang Hames auto MU = std::make_unique<SimpleMaterializationUnit>(
2050aec49c8SLang Hames SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
2060aec49c8SLang Hames [&](std::unique_ptr<MaterializationResponsibility> R) {
2070aec49c8SLang Hames MR = std::move(R);
2080aec49c8SLang Hames });
2090aec49c8SLang Hames
2100aec49c8SLang Hames auto RT = JD.createResourceTracker();
2110aec49c8SLang Hames cantFail(JD.define(std::move(MU), RT));
2120aec49c8SLang Hames
2130aec49c8SLang Hames ES.lookup(
2140aec49c8SLang Hames LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo),
2150aec49c8SLang Hames SymbolState::Ready,
2160aec49c8SLang Hames [](Expected<SymbolMap> Result) {
2170aec49c8SLang Hames EXPECT_THAT_EXPECTED(Result, Failed<FailedToMaterialize>())
2180aec49c8SLang Hames << "Lookup failed unexpectedly";
2190aec49c8SLang Hames },
2200aec49c8SLang Hames NoDependenciesToRegister);
2210aec49c8SLang Hames
2220aec49c8SLang Hames cantFail(RT->remove());
223069919c9SLang Hames auto SymFlags = cantFail(ES.lookupFlags(
224069919c9SLang Hames LookupKind::Static,
225069919c9SLang Hames {{&JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
226069919c9SLang Hames SymbolLookupSet(Foo, SymbolLookupFlags::WeaklyReferencedSymbol)));
2270aec49c8SLang Hames
2280aec49c8SLang Hames EXPECT_EQ(SymFlags.size(), 0U)
2290aec49c8SLang Hames << "Symbols should have been removed from the symbol table";
2300aec49c8SLang Hames EXPECT_TRUE(ResourceManagerGotRemove)
2310aec49c8SLang Hames << "ResourceManager did not receive handleRemoveResources";
2320aec49c8SLang Hames
2330aec49c8SLang Hames EXPECT_THAT_ERROR(MR->withResourceKeyDo([](ResourceKey K) {
2340aec49c8SLang Hames ADD_FAILURE() << "Should not reach withResourceKeyDo body for removed key";
2350aec49c8SLang Hames }),
2360aec49c8SLang Hames Failed<ResourceTrackerDefunct>())
2370aec49c8SLang Hames << "withResourceKeyDo on MR with removed tracker should have failed";
2380aec49c8SLang Hames EXPECT_THAT_ERROR(MR->notifyResolved({{Foo, FooSym}}),
2390aec49c8SLang Hames Failed<ResourceTrackerDefunct>())
2400aec49c8SLang Hames << "notifyResolved on MR with removed tracker should have failed";
2410aec49c8SLang Hames
2420aec49c8SLang Hames MR->failMaterialization();
2430aec49c8SLang Hames }
2440aec49c8SLang Hames
TEST_F(ResourceTrackerStandardTest,JITDylibClear)2450aec49c8SLang Hames TEST_F(ResourceTrackerStandardTest, JITDylibClear) {
2460aec49c8SLang Hames SimpleResourceManager<> SRM(ES);
2470aec49c8SLang Hames
2480aec49c8SLang Hames // Add materializer for Foo.
2490aec49c8SLang Hames cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
2500aec49c8SLang Hames SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
2510aec49c8SLang Hames [&](std::unique_ptr<MaterializationResponsibility> R) {
2520aec49c8SLang Hames cantFail(R->withResourceKeyDo(
2530aec49c8SLang Hames [&](ResourceKey K) { ++SRM.getRecordedResources()[K]; }));
2540aec49c8SLang Hames cantFail(R->notifyResolved({{Foo, FooSym}}));
255*ebe8733aSlhames cantFail(R->notifyEmitted({}));
2560aec49c8SLang Hames })));
2570aec49c8SLang Hames
2580aec49c8SLang Hames // Add materializer for Bar.
2590aec49c8SLang Hames cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
2600aec49c8SLang Hames SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
2610aec49c8SLang Hames [&](std::unique_ptr<MaterializationResponsibility> R) {
2620aec49c8SLang Hames cantFail(R->withResourceKeyDo(
2630aec49c8SLang Hames [&](ResourceKey K) { ++SRM.getRecordedResources()[K]; }));
2640aec49c8SLang Hames cantFail(R->notifyResolved({{Bar, BarSym}}));
265*ebe8733aSlhames cantFail(R->notifyEmitted({}));
2660aec49c8SLang Hames })));
2670aec49c8SLang Hames
2680aec49c8SLang Hames EXPECT_TRUE(SRM.getRecordedResources().empty())
2690aec49c8SLang Hames << "Expected no resources recorded yet.";
2700aec49c8SLang Hames
2710aec49c8SLang Hames cantFail(
2720aec49c8SLang Hames ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet({Foo, Bar})));
2730aec49c8SLang Hames
2740aec49c8SLang Hames auto JDResourceKey = JD.getDefaultResourceTracker()->getKeyUnsafe();
2750aec49c8SLang Hames EXPECT_EQ(SRM.getRecordedResources().size(), 1U)
2760aec49c8SLang Hames << "Expected exactly one entry (for JD's ResourceKey)";
2770aec49c8SLang Hames EXPECT_EQ(SRM.getRecordedResources().count(JDResourceKey), 1U)
2780aec49c8SLang Hames << "Expected an entry for JD's ResourceKey";
2790aec49c8SLang Hames EXPECT_EQ(SRM.getRecordedResources()[JDResourceKey], 2U)
2800aec49c8SLang Hames << "Expected value of 2 for JD's ResourceKey "
2810aec49c8SLang Hames "(+1 for each of Foo and Bar)";
2820aec49c8SLang Hames
2830aec49c8SLang Hames cantFail(JD.clear());
2840aec49c8SLang Hames
2850aec49c8SLang Hames EXPECT_TRUE(SRM.getRecordedResources().empty())
2860aec49c8SLang Hames << "Expected no resources recorded after clear";
2870aec49c8SLang Hames }
2880aec49c8SLang Hames
TEST_F(ResourceTrackerStandardTest,BasicDefineAndExplicitTransferBeforeMaterializing)2890aec49c8SLang Hames TEST_F(ResourceTrackerStandardTest,
2900aec49c8SLang Hames BasicDefineAndExplicitTransferBeforeMaterializing) {
2910aec49c8SLang Hames
2920aec49c8SLang Hames bool ResourceManagerGotTransfer = false;
293d54c4e38SLang Hames SimpleResourceManager<> SRM(ES);
294bf6d7ca9SLang Hames SRM.setHandleTransfer(
295bf6d7ca9SLang Hames [&](JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) {
2960aec49c8SLang Hames ResourceManagerGotTransfer = true;
2970aec49c8SLang Hames auto &RR = SRM.getRecordedResources();
2980aec49c8SLang Hames EXPECT_EQ(RR.size(), 0U) << "Expected no resources recorded yet";
2990aec49c8SLang Hames });
3000aec49c8SLang Hames
3018b1771bdSLang Hames auto MakeMU = [&](SymbolStringPtr Name, ExecutorSymbolDef Sym) {
3020aec49c8SLang Hames return std::make_unique<SimpleMaterializationUnit>(
3030aec49c8SLang Hames SymbolFlagsMap({{Name, Sym.getFlags()}}),
3040aec49c8SLang Hames [=, &SRM](std::unique_ptr<MaterializationResponsibility> R) {
3050aec49c8SLang Hames cantFail(R->withResourceKeyDo(
3060aec49c8SLang Hames [&](ResourceKey K) { SRM.recordResource(K); }));
3070aec49c8SLang Hames cantFail(R->notifyResolved({{Name, Sym}}));
308*ebe8733aSlhames cantFail(R->notifyEmitted({}));
3090aec49c8SLang Hames });
3100aec49c8SLang Hames };
3110aec49c8SLang Hames
3120aec49c8SLang Hames auto FooRT = JD.createResourceTracker();
3130aec49c8SLang Hames cantFail(JD.define(MakeMU(Foo, FooSym), FooRT));
3140aec49c8SLang Hames
3150aec49c8SLang Hames auto BarRT = JD.createResourceTracker();
3160aec49c8SLang Hames cantFail(JD.define(MakeMU(Bar, BarSym), BarRT));
3170aec49c8SLang Hames
3180aec49c8SLang Hames BarRT->transferTo(*FooRT);
3190aec49c8SLang Hames
3200aec49c8SLang Hames EXPECT_TRUE(ResourceManagerGotTransfer)
3210aec49c8SLang Hames << "ResourceManager did not receive transfer";
3220aec49c8SLang Hames EXPECT_TRUE(BarRT->isDefunct()) << "BarRT should now be defunct";
3230aec49c8SLang Hames
3240aec49c8SLang Hames cantFail(
3250aec49c8SLang Hames ES.lookup(makeJITDylibSearchOrder({&JD}), SymbolLookupSet({Foo, Bar})));
3260aec49c8SLang Hames
3270aec49c8SLang Hames EXPECT_EQ(SRM.getRecordedResources().size(), 1U)
3280aec49c8SLang Hames << "Expected exactly one entry (for FooRT's Key)";
3290aec49c8SLang Hames EXPECT_EQ(SRM.getRecordedResources().count(FooRT->getKeyUnsafe()), 1U)
3300aec49c8SLang Hames << "Expected an entry for FooRT's ResourceKey";
3310aec49c8SLang Hames EXPECT_EQ(SRM.getRecordedResources().count(BarRT->getKeyUnsafe()), 0U)
3320aec49c8SLang Hames << "Expected no entry for BarRT's ResourceKey";
3330aec49c8SLang Hames
3340aec49c8SLang Hames // We need to explicitly destroy FooRT or its resources will be implicitly
3350aec49c8SLang Hames // transferred to the default tracker triggering a second call to our
3360aec49c8SLang Hames // transfer function above (which expects only one call).
3370aec49c8SLang Hames cantFail(FooRT->remove());
3380aec49c8SLang Hames }
3390aec49c8SLang Hames
TEST_F(ResourceTrackerStandardTest,BasicDefineAndExplicitTransferAfterMaterializing)3400aec49c8SLang Hames TEST_F(ResourceTrackerStandardTest,
3410aec49c8SLang Hames BasicDefineAndExplicitTransferAfterMaterializing) {
3420aec49c8SLang Hames
3430aec49c8SLang Hames bool ResourceManagerGotTransfer = false;
344d54c4e38SLang Hames SimpleResourceManager<> SRM(ES);
345bf6d7ca9SLang Hames SRM.setHandleTransfer(
346bf6d7ca9SLang Hames [&](JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) {
3470aec49c8SLang Hames ResourceManagerGotTransfer = true;
348bf6d7ca9SLang Hames SRM.transferResources(JD, DstKey, SrcKey);
3490aec49c8SLang Hames });
3500aec49c8SLang Hames
3518b1771bdSLang Hames auto MakeMU = [&](SymbolStringPtr Name, ExecutorSymbolDef Sym) {
3520aec49c8SLang Hames return std::make_unique<SimpleMaterializationUnit>(
3530aec49c8SLang Hames SymbolFlagsMap({{Name, Sym.getFlags()}}),
3540aec49c8SLang Hames [=, &SRM](std::unique_ptr<MaterializationResponsibility> R) {
3550aec49c8SLang Hames cantFail(R->withResourceKeyDo(
3560aec49c8SLang Hames [&](ResourceKey K) { SRM.recordResource(K, 1); }));
3570aec49c8SLang Hames cantFail(R->notifyResolved({{Name, Sym}}));
358*ebe8733aSlhames cantFail(R->notifyEmitted({}));
3590aec49c8SLang Hames });
3600aec49c8SLang Hames };
3610aec49c8SLang Hames
3620aec49c8SLang Hames auto FooRT = JD.createResourceTracker();
3630aec49c8SLang Hames cantFail(JD.define(MakeMU(Foo, FooSym), FooRT));
3640aec49c8SLang Hames
3650aec49c8SLang Hames auto BarRT = JD.createResourceTracker();
3660aec49c8SLang Hames cantFail(JD.define(MakeMU(Bar, BarSym), BarRT));
3670aec49c8SLang Hames
3680aec49c8SLang Hames EXPECT_EQ(SRM.getRecordedResources().size(), 0U)
3690aec49c8SLang Hames << "Expected no recorded resources yet";
3700aec49c8SLang Hames
3710aec49c8SLang Hames cantFail(
3720aec49c8SLang Hames ES.lookup(makeJITDylibSearchOrder({&JD}), SymbolLookupSet({Foo, Bar})));
3730aec49c8SLang Hames
3740aec49c8SLang Hames EXPECT_EQ(SRM.getRecordedResources().size(), 2U)
3750aec49c8SLang Hames << "Expected recorded resources for both Foo and Bar";
3760aec49c8SLang Hames
3770aec49c8SLang Hames BarRT->transferTo(*FooRT);
3780aec49c8SLang Hames
3790aec49c8SLang Hames EXPECT_TRUE(ResourceManagerGotTransfer)
3800aec49c8SLang Hames << "ResourceManager did not receive transfer";
3810aec49c8SLang Hames EXPECT_TRUE(BarRT->isDefunct()) << "BarRT should now be defunct";
3820aec49c8SLang Hames
3830aec49c8SLang Hames EXPECT_EQ(SRM.getRecordedResources().size(), 1U)
3840aec49c8SLang Hames << "Expected recorded resources for Foo only";
3850aec49c8SLang Hames EXPECT_EQ(SRM.getRecordedResources().count(FooRT->getKeyUnsafe()), 1U)
3860aec49c8SLang Hames << "Expected recorded resources for Foo";
3870aec49c8SLang Hames EXPECT_EQ(SRM.getRecordedResources()[FooRT->getKeyUnsafe()], 2U)
3880aec49c8SLang Hames << "Expected resources value for for Foo to be '2'";
3890aec49c8SLang Hames }
3900aec49c8SLang Hames
TEST_F(ResourceTrackerStandardTest,BasicDefineAndExplicitTransferWhileMaterializing)3910aec49c8SLang Hames TEST_F(ResourceTrackerStandardTest,
3920aec49c8SLang Hames BasicDefineAndExplicitTransferWhileMaterializing) {
3930aec49c8SLang Hames
3940aec49c8SLang Hames bool ResourceManagerGotTransfer = false;
395d54c4e38SLang Hames SimpleResourceManager<> SRM(ES);
396bf6d7ca9SLang Hames SRM.setHandleTransfer(
397bf6d7ca9SLang Hames [&](JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) {
3980aec49c8SLang Hames ResourceManagerGotTransfer = true;
399bf6d7ca9SLang Hames SRM.transferResources(JD, DstKey, SrcKey);
4000aec49c8SLang Hames });
4010aec49c8SLang Hames
4020aec49c8SLang Hames auto FooRT = JD.createResourceTracker();
4030aec49c8SLang Hames std::unique_ptr<MaterializationResponsibility> FooMR;
4040aec49c8SLang Hames cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
4050aec49c8SLang Hames SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
4060aec49c8SLang Hames [&](std::unique_ptr<MaterializationResponsibility> R) {
4070aec49c8SLang Hames FooMR = std::move(R);
4080aec49c8SLang Hames }),
4090aec49c8SLang Hames FooRT));
4100aec49c8SLang Hames
4110aec49c8SLang Hames auto BarRT = JD.createResourceTracker();
4120aec49c8SLang Hames
4130aec49c8SLang Hames ES.lookup(
4140aec49c8SLang Hames LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo),
4150aec49c8SLang Hames SymbolState::Ready,
4160aec49c8SLang Hames [](Expected<SymbolMap> Result) { cantFail(Result.takeError()); },
4170aec49c8SLang Hames NoDependenciesToRegister);
4180aec49c8SLang Hames
4190aec49c8SLang Hames cantFail(FooMR->withResourceKeyDo([&](ResourceKey K) {
4200aec49c8SLang Hames EXPECT_EQ(FooRT->getKeyUnsafe(), K)
4210aec49c8SLang Hames << "Expected FooRT's ResourceKey for Foo here";
4220aec49c8SLang Hames SRM.recordResource(K, 1);
4230aec49c8SLang Hames }));
4240aec49c8SLang Hames
4250aec49c8SLang Hames EXPECT_EQ(SRM.getRecordedResources().size(), 1U)
4260aec49c8SLang Hames << "Expected one recorded resource here";
4270aec49c8SLang Hames EXPECT_EQ(SRM.getRecordedResources()[FooRT->getKeyUnsafe()], 1U)
4280aec49c8SLang Hames << "Expected Resource value for FooRT to be '1' here";
4290aec49c8SLang Hames
4300aec49c8SLang Hames FooRT->transferTo(*BarRT);
4310aec49c8SLang Hames
4320aec49c8SLang Hames EXPECT_TRUE(ResourceManagerGotTransfer)
4330aec49c8SLang Hames << "Expected resource manager to receive handleTransferResources call";
4340aec49c8SLang Hames
4350aec49c8SLang Hames cantFail(FooMR->withResourceKeyDo([&](ResourceKey K) {
4360aec49c8SLang Hames EXPECT_EQ(BarRT->getKeyUnsafe(), K)
4370aec49c8SLang Hames << "Expected BarRT's ResourceKey for Foo here";
4380aec49c8SLang Hames SRM.recordResource(K, 1);
4390aec49c8SLang Hames }));
4400aec49c8SLang Hames
4410aec49c8SLang Hames EXPECT_EQ(SRM.getRecordedResources().size(), 1U)
4420aec49c8SLang Hames << "Expected one recorded resource here";
4430aec49c8SLang Hames EXPECT_EQ(SRM.getRecordedResources().count(BarRT->getKeyUnsafe()), 1U)
4440aec49c8SLang Hames << "Expected RecordedResources to contain an entry for BarRT";
4450aec49c8SLang Hames EXPECT_EQ(SRM.getRecordedResources()[BarRT->getKeyUnsafe()], 2U)
4460aec49c8SLang Hames << "Expected Resource value for BarRT to be '2' here";
4470aec49c8SLang Hames
4480aec49c8SLang Hames cantFail(FooMR->notifyResolved({{Foo, FooSym}}));
449*ebe8733aSlhames cantFail(FooMR->notifyEmitted({}));
4500aec49c8SLang Hames }
4510aec49c8SLang Hames
4520aec49c8SLang Hames } // namespace
453