1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00
llvm-mirror/unittests/ExecutionEngine/Orc/RemoteObjectLayerTest.cpp
Chandler Carruth ae65e281f3 Update the file headers across all of the LLVM projects in the monorepo
to reflect the new license.

We understand that people may be surprised that we're moving the header
entirely to discuss the new license. We checked this carefully with the
Foundation's lawyer and we believe this is the correct approach.

Essentially, all code in the project is now made available by the LLVM
project under our new license, so you will see that the license headers
include that license only. Some of our contributors have contributed
code under our old license, and accordingly, we have retained a copy of
our old license notice in the top-level files in each project and
repository.

llvm-svn: 351636
2019-01-19 08:50:56 +00:00

589 lines
19 KiB
C++

//===---------------------- RemoteObjectLayerTest.cpp ---------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/NullResolver.h"
#include "llvm/ExecutionEngine/Orc/RemoteObjectLayer.h"
#include "OrcTestCommon.h"
#include "QueueChannel.h"
#include "gtest/gtest.h"
using namespace llvm;
using namespace llvm::orc;
namespace {
class MockObjectLayer {
public:
using ObjHandleT = uint64_t;
using ObjectPtr = std::unique_ptr<MemoryBuffer>;
using LookupFn = std::function<JITSymbol(StringRef, bool)>;
using SymbolLookupTable = std::map<ObjHandleT, LookupFn>;
using AddObjectFtor =
std::function<Expected<ObjHandleT>(ObjectPtr, SymbolLookupTable&)>;
class ObjectNotFound : public remote::ResourceNotFound<ObjHandleT> {
public:
ObjectNotFound(ObjHandleT H) : ResourceNotFound(H, "Object handle") {}
};
MockObjectLayer(AddObjectFtor AddObject)
: AddObject(std::move(AddObject)) {}
Expected<ObjHandleT> addObject(ObjectPtr Obj,
std::shared_ptr<JITSymbolResolver> Resolver) {
return AddObject(std::move(Obj), SymTab);
}
Error removeObject(ObjHandleT H) {
if (SymTab.count(H))
return Error::success();
else
return make_error<ObjectNotFound>(H);
}
JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
for (auto KV : SymTab) {
if (auto Sym = KV.second(Name, ExportedSymbolsOnly))
return Sym;
else if (auto Err = Sym.takeError())
return std::move(Err);
}
return JITSymbol(nullptr);
}
JITSymbol findSymbolIn(ObjHandleT H, StringRef Name,
bool ExportedSymbolsOnly) {
auto LI = SymTab.find(H);
if (LI != SymTab.end())
return LI->second(Name, ExportedSymbolsOnly);
else
return make_error<ObjectNotFound>(H);
}
Error emitAndFinalize(ObjHandleT H) {
if (SymTab.count(H))
return Error::success();
else
return make_error<ObjectNotFound>(H);
}
private:
AddObjectFtor AddObject;
SymbolLookupTable SymTab;
};
using RPCEndpoint = rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>;
MockObjectLayer::ObjectPtr createTestObject() {
OrcNativeTarget::initialize();
auto TM = std::unique_ptr<TargetMachine>(EngineBuilder().selectTarget());
if (!TM)
return nullptr;
LLVMContext Ctx;
ModuleBuilder MB(Ctx, TM->getTargetTriple().str(), "TestModule");
MB.getModule()->setDataLayout(TM->createDataLayout());
auto *Main = MB.createFunctionDecl(
FunctionType::get(Type::getInt32Ty(Ctx),
{Type::getInt32Ty(Ctx),
Type::getInt8PtrTy(Ctx)->getPointerTo()},
false),
"main");
Main->getBasicBlockList().push_back(BasicBlock::Create(Ctx));
IRBuilder<> B(&Main->back());
B.CreateRet(ConstantInt::getSigned(Type::getInt32Ty(Ctx), 42));
SimpleCompiler IRCompiler(*TM);
return IRCompiler(*MB.getModule());
}
TEST(RemoteObjectLayer, AddObject) {
llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
auto TestObject = createTestObject();
if (!TestObject)
return;
auto Channels = createPairedQueueChannels();
auto ReportError = [](Error Err) {
logAllUnhandledErrors(std::move(Err), llvm::errs());
};
// Copy the bytes out of the test object: the copy will be used to verify
// that the original is correctly transmitted over RPC to the mock layer.
StringRef ObjBytes = TestObject->getBuffer();
std::vector<char> ObjContents(ObjBytes.size());
std::copy(ObjBytes.begin(), ObjBytes.end(), ObjContents.begin());
RPCEndpoint ClientEP(*Channels.first, true);
RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);
RPCEndpoint ServerEP(*Channels.second, true);
MockObjectLayer BaseLayer(
[&ObjContents](MockObjectLayer::ObjectPtr Obj,
MockObjectLayer::SymbolLookupTable &SymTab) {
// Check that the received object file content matches the original.
StringRef RPCObjContents = Obj->getBuffer();
EXPECT_EQ(RPCObjContents.size(), ObjContents.size())
<< "RPC'd object file has incorrect size";
EXPECT_TRUE(std::equal(RPCObjContents.begin(), RPCObjContents.end(),
ObjContents.begin()))
<< "RPC'd object file content does not match original content";
return 1;
});
RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,
ServerEP,
ReportError);
bool Finished = false;
ServerEP.addHandler<remote::utils::TerminateSession>(
[&]() { Finished = true; }
);
auto ServerThread =
std::thread([&]() {
while (!Finished)
cantFail(ServerEP.handleOne());
});
cantFail(Client.addObject(std::move(TestObject),
std::make_shared<NullLegacyResolver>()));
cantFail(ClientEP.callB<remote::utils::TerminateSession>());
ServerThread.join();
}
TEST(RemoteObjectLayer, AddObjectFailure) {
llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
auto TestObject = createTestObject();
if (!TestObject)
return;
auto Channels = createPairedQueueChannels();
auto ReportError =
[](Error Err) {
auto ErrMsg = toString(std::move(Err));
EXPECT_EQ(ErrMsg, "AddObjectFailure - Test Message")
<< "Expected error string to be \"AddObjectFailure - Test Message\"";
};
RPCEndpoint ClientEP(*Channels.first, true);
RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);
RPCEndpoint ServerEP(*Channels.second, true);
MockObjectLayer BaseLayer(
[](MockObjectLayer::ObjectPtr Obj,
MockObjectLayer::SymbolLookupTable &SymTab)
-> Expected<MockObjectLayer::ObjHandleT> {
return make_error<StringError>("AddObjectFailure - Test Message",
inconvertibleErrorCode());
});
RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,
ServerEP,
ReportError);
bool Finished = false;
ServerEP.addHandler<remote::utils::TerminateSession>(
[&]() { Finished = true; }
);
auto ServerThread =
std::thread([&]() {
while (!Finished)
cantFail(ServerEP.handleOne());
});
auto HandleOrErr = Client.addObject(std::move(TestObject),
std::make_shared<NullLegacyResolver>());
EXPECT_FALSE(HandleOrErr) << "Expected error from addObject";
auto ErrMsg = toString(HandleOrErr.takeError());
EXPECT_EQ(ErrMsg, "AddObjectFailure - Test Message")
<< "Expected error string to be \"AddObjectFailure - Test Message\"";
cantFail(ClientEP.callB<remote::utils::TerminateSession>());
ServerThread.join();
}
TEST(RemoteObjectLayer, RemoveObject) {
llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
auto TestObject = createTestObject();
if (!TestObject)
return;
auto Channels = createPairedQueueChannels();
auto ReportError = [](Error Err) {
logAllUnhandledErrors(std::move(Err), llvm::errs());
};
RPCEndpoint ClientEP(*Channels.first, true);
RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);
RPCEndpoint ServerEP(*Channels.second, true);
MockObjectLayer BaseLayer(
[](MockObjectLayer::ObjectPtr Obj,
MockObjectLayer::SymbolLookupTable &SymTab) {
SymTab[1] = MockObjectLayer::LookupFn();
return 1;
});
RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,
ServerEP,
ReportError);
bool Finished = false;
ServerEP.addHandler<remote::utils::TerminateSession>(
[&]() { Finished = true; }
);
auto ServerThread =
std::thread([&]() {
while (!Finished)
cantFail(ServerEP.handleOne());
});
auto H = cantFail(Client.addObject(std::move(TestObject),
std::make_shared<NullLegacyResolver>()));
cantFail(Client.removeObject(H));
cantFail(ClientEP.callB<remote::utils::TerminateSession>());
ServerThread.join();
}
TEST(RemoteObjectLayer, RemoveObjectFailure) {
llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
auto TestObject = createTestObject();
if (!TestObject)
return;
auto Channels = createPairedQueueChannels();
auto ReportError =
[](Error Err) {
auto ErrMsg = toString(std::move(Err));
EXPECT_EQ(ErrMsg, "Object handle 42 not found")
<< "Expected error string to be \"Object handle 42 not found\"";
};
RPCEndpoint ClientEP(*Channels.first, true);
RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);
RPCEndpoint ServerEP(*Channels.second, true);
// AddObject lambda does not update symbol table, so removeObject will treat
// this as a bad object handle.
MockObjectLayer BaseLayer(
[](MockObjectLayer::ObjectPtr Obj,
MockObjectLayer::SymbolLookupTable &SymTab) {
return 42;
});
RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,
ServerEP,
ReportError);
bool Finished = false;
ServerEP.addHandler<remote::utils::TerminateSession>(
[&]() { Finished = true; }
);
auto ServerThread =
std::thread([&]() {
while (!Finished)
cantFail(ServerEP.handleOne());
});
auto H = cantFail(Client.addObject(std::move(TestObject),
std::make_shared<NullLegacyResolver>()));
auto Err = Client.removeObject(H);
EXPECT_TRUE(!!Err) << "Expected error from removeObject";
auto ErrMsg = toString(std::move(Err));
EXPECT_EQ(ErrMsg, "Object handle 42 not found")
<< "Expected error string to be \"Object handle 42 not found\"";
cantFail(ClientEP.callB<remote::utils::TerminateSession>());
ServerThread.join();
}
TEST(RemoteObjectLayer, FindSymbol) {
llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
auto TestObject = createTestObject();
if (!TestObject)
return;
auto Channels = createPairedQueueChannels();
auto ReportError =
[](Error Err) {
auto ErrMsg = toString(std::move(Err));
EXPECT_EQ(ErrMsg, "Could not find symbol 'badsymbol'")
<< "Expected error string to be \"Object handle 42 not found\"";
};
RPCEndpoint ClientEP(*Channels.first, true);
RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);
RPCEndpoint ServerEP(*Channels.second, true);
// AddObject lambda does not update symbol table, so removeObject will treat
// this as a bad object handle.
MockObjectLayer BaseLayer(
[](MockObjectLayer::ObjectPtr Obj,
MockObjectLayer::SymbolLookupTable &SymTab) {
SymTab[42] =
[](StringRef Name, bool ExportedSymbolsOnly) -> JITSymbol {
if (Name == "foobar")
return JITSymbol(0x12348765, JITSymbolFlags::Exported);
if (Name == "badsymbol")
return make_error<JITSymbolNotFound>(Name);
return nullptr;
};
return 42;
});
RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,
ServerEP,
ReportError);
bool Finished = false;
ServerEP.addHandler<remote::utils::TerminateSession>(
[&]() { Finished = true; }
);
auto ServerThread =
std::thread([&]() {
while (!Finished)
cantFail(ServerEP.handleOne());
});
cantFail(Client.addObject(std::move(TestObject),
std::make_shared<NullLegacyResolver>()));
// Check that we can find and materialize a valid symbol.
auto Sym1 = Client.findSymbol("foobar", true);
EXPECT_TRUE(!!Sym1) << "Symbol 'foobar' should be findable";
EXPECT_EQ(cantFail(Sym1.getAddress()), 0x12348765ULL)
<< "Symbol 'foobar' does not return the correct address";
{
// Check that we can return a symbol containing an error.
auto Sym2 = Client.findSymbol("badsymbol", true);
EXPECT_FALSE(!!Sym2) << "Symbol 'badsymbol' should not be findable";
auto Err = Sym2.takeError();
EXPECT_TRUE(!!Err) << "Sym2 should contain an error value";
auto ErrMsg = toString(std::move(Err));
EXPECT_EQ(ErrMsg, "Could not find symbol 'badsymbol'")
<< "Expected symbol-not-found error for Sym2";
}
{
// Check that we can return a 'null' symbol.
auto Sym3 = Client.findSymbol("baz", true);
EXPECT_FALSE(!!Sym3) << "Symbol 'baz' should convert to false";
auto Err = Sym3.takeError();
EXPECT_FALSE(!!Err) << "Symbol 'baz' should not contain an error";
}
cantFail(ClientEP.callB<remote::utils::TerminateSession>());
ServerThread.join();
}
TEST(RemoteObjectLayer, FindSymbolIn) {
llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
auto TestObject = createTestObject();
if (!TestObject)
return;
auto Channels = createPairedQueueChannels();
auto ReportError =
[](Error Err) {
auto ErrMsg = toString(std::move(Err));
EXPECT_EQ(ErrMsg, "Could not find symbol 'barbaz'")
<< "Expected error string to be \"Object handle 42 not found\"";
};
RPCEndpoint ClientEP(*Channels.first, true);
RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);
RPCEndpoint ServerEP(*Channels.second, true);
// AddObject lambda does not update symbol table, so removeObject will treat
// this as a bad object handle.
MockObjectLayer BaseLayer(
[](MockObjectLayer::ObjectPtr Obj,
MockObjectLayer::SymbolLookupTable &SymTab) {
SymTab[42] =
[](StringRef Name, bool ExportedSymbolsOnly) -> JITSymbol {
if (Name == "foobar")
return JITSymbol(0x12348765, JITSymbolFlags::Exported);
return make_error<JITSymbolNotFound>(Name);
};
// Dummy symbol table entry - this should not be visible to
// findSymbolIn.
SymTab[43] =
[](StringRef Name, bool ExportedSymbolsOnly) -> JITSymbol {
if (Name == "barbaz")
return JITSymbol(0xdeadbeef, JITSymbolFlags::Exported);
return make_error<JITSymbolNotFound>(Name);
};
return 42;
});
RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,
ServerEP,
ReportError);
bool Finished = false;
ServerEP.addHandler<remote::utils::TerminateSession>(
[&]() { Finished = true; }
);
auto ServerThread =
std::thread([&]() {
while (!Finished)
cantFail(ServerEP.handleOne());
});
auto H = cantFail(Client.addObject(std::move(TestObject),
std::make_shared<NullLegacyResolver>()));
auto Sym1 = Client.findSymbolIn(H, "foobar", true);
EXPECT_TRUE(!!Sym1) << "Symbol 'foobar' should be findable";
EXPECT_EQ(cantFail(Sym1.getAddress()), 0x12348765ULL)
<< "Symbol 'foobar' does not return the correct address";
auto Sym2 = Client.findSymbolIn(H, "barbaz", true);
EXPECT_FALSE(!!Sym2) << "Symbol 'barbaz' should not be findable";
auto Err = Sym2.takeError();
EXPECT_TRUE(!!Err) << "Sym2 should contain an error value";
auto ErrMsg = toString(std::move(Err));
EXPECT_EQ(ErrMsg, "Could not find symbol 'barbaz'")
<< "Expected symbol-not-found error for Sym2";
cantFail(ClientEP.callB<remote::utils::TerminateSession>());
ServerThread.join();
}
TEST(RemoteObjectLayer, EmitAndFinalize) {
llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
auto TestObject = createTestObject();
if (!TestObject)
return;
auto Channels = createPairedQueueChannels();
auto ReportError = [](Error Err) {
logAllUnhandledErrors(std::move(Err), llvm::errs());
};
RPCEndpoint ClientEP(*Channels.first, true);
RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);
RPCEndpoint ServerEP(*Channels.second, true);
MockObjectLayer BaseLayer(
[](MockObjectLayer::ObjectPtr Obj,
MockObjectLayer::SymbolLookupTable &SymTab) {
SymTab[1] = MockObjectLayer::LookupFn();
return 1;
});
RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,
ServerEP,
ReportError);
bool Finished = false;
ServerEP.addHandler<remote::utils::TerminateSession>(
[&]() { Finished = true; }
);
auto ServerThread =
std::thread([&]() {
while (!Finished)
cantFail(ServerEP.handleOne());
});
auto H = cantFail(Client.addObject(std::move(TestObject),
std::make_shared<NullLegacyResolver>()));
auto Err = Client.emitAndFinalize(H);
EXPECT_FALSE(!!Err) << "emitAndFinalize should work";
cantFail(ClientEP.callB<remote::utils::TerminateSession>());
ServerThread.join();
}
TEST(RemoteObjectLayer, EmitAndFinalizeFailure) {
llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
auto TestObject = createTestObject();
if (!TestObject)
return;
auto Channels = createPairedQueueChannels();
auto ReportError =
[](Error Err) {
auto ErrMsg = toString(std::move(Err));
EXPECT_EQ(ErrMsg, "Object handle 1 not found")
<< "Expected bad handle error";
};
RPCEndpoint ClientEP(*Channels.first, true);
RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);
RPCEndpoint ServerEP(*Channels.second, true);
MockObjectLayer BaseLayer(
[](MockObjectLayer::ObjectPtr Obj,
MockObjectLayer::SymbolLookupTable &SymTab) {
return 1;
});
RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,
ServerEP,
ReportError);
bool Finished = false;
ServerEP.addHandler<remote::utils::TerminateSession>(
[&]() { Finished = true; }
);
auto ServerThread =
std::thread([&]() {
while (!Finished)
cantFail(ServerEP.handleOne());
});
auto H = cantFail(Client.addObject(std::move(TestObject),
std::make_shared<NullLegacyResolver>()));
auto Err = Client.emitAndFinalize(H);
EXPECT_TRUE(!!Err) << "emitAndFinalize should work";
auto ErrMsg = toString(std::move(Err));
EXPECT_EQ(ErrMsg, "Object handle 1 not found")
<< "emitAndFinalize returned incorrect error";
cantFail(ClientEP.callB<remote::utils::TerminateSession>());
ServerThread.join();
}
}