mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
92fa8af24d
Summary: ORCv1 is deprecated. The current aim is to remove it before the LLVM 10.0 release. This patch adds deprecation attributes to the ORCv1 layers and utilities to warn clients of the change. Reviewers: dblaikie, sgraenitz, AlexDenisov Subscribers: llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D64609 llvm-svn: 366344
589 lines
19 KiB
C++
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(AcknowledgeORCv1Deprecation,
|
|
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(
|
|
AcknowledgeORCv1Deprecation, 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(AcknowledgeORCv1Deprecation,
|
|
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(
|
|
AcknowledgeORCv1Deprecation, 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(AcknowledgeORCv1Deprecation,
|
|
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(
|
|
AcknowledgeORCv1Deprecation, 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(AcknowledgeORCv1Deprecation,
|
|
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(
|
|
AcknowledgeORCv1Deprecation, 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(AcknowledgeORCv1Deprecation,
|
|
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(
|
|
AcknowledgeORCv1Deprecation, 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(AcknowledgeORCv1Deprecation,
|
|
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(
|
|
AcknowledgeORCv1Deprecation, 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(AcknowledgeORCv1Deprecation,
|
|
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(
|
|
AcknowledgeORCv1Deprecation, 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(AcknowledgeORCv1Deprecation,
|
|
ClientEP, ReportError);
|
|
|
|
RPCEndpoint ServerEP(*Channels.second, true);
|
|
|
|
MockObjectLayer BaseLayer(
|
|
[](MockObjectLayer::ObjectPtr Obj,
|
|
MockObjectLayer::SymbolLookupTable &SymTab) {
|
|
return 1;
|
|
});
|
|
RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(
|
|
AcknowledgeORCv1Deprecation, 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();
|
|
}
|
|
|
|
}
|