summaryrefslogtreecommitdiff
path: root/gnu/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp')
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp275
1 files changed, 275 insertions, 0 deletions
diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp b/gnu/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp
new file mode 100644
index 00000000000..c88c94f17b1
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp
@@ -0,0 +1,275 @@
+//===- ObjectTransformLayerTest.cpp - Unit tests for ObjectTransformLayer -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "gtest/gtest.h"
+
+using namespace llvm::orc;
+
+namespace {
+
+// Stand-in for RuntimeDyld::MemoryManager
+typedef int MockMemoryManager;
+
+// Stand-in for RuntimeDyld::SymbolResolver
+typedef int MockSymbolResolver;
+
+// stand-in for object::ObjectFile
+typedef int MockObjectFile;
+
+// stand-in for llvm::MemoryBuffer set
+typedef int MockMemoryBufferSet;
+
+// Mock transform that operates on unique pointers to object files, and
+// allocates new object files rather than mutating the given ones.
+struct AllocatingTransform {
+ std::unique_ptr<MockObjectFile>
+ operator()(std::unique_ptr<MockObjectFile> Obj) const {
+ return llvm::make_unique<MockObjectFile>(*Obj + 1);
+ }
+};
+
+// Mock base layer for verifying behavior of transform layer.
+// Each method "T foo(args)" is accompanied by two auxiliary methods:
+// - "void expectFoo(args)", to be called before calling foo on the transform
+// layer; saves values of args, which mock layer foo then verifies against.
+// - "void verifyFoo(T)", to be called after foo, which verifies that the
+// transform layer called the base layer and forwarded any return value.
+class MockBaseLayer {
+public:
+ typedef int ObjSetHandleT;
+
+ MockBaseLayer() : MockSymbol(nullptr) { resetExpectations(); }
+
+ template <typename ObjSetT, typename MemoryManagerPtrT,
+ typename SymbolResolverPtrT>
+ ObjSetHandleT addObjectSet(ObjSetT &Objects, MemoryManagerPtrT MemMgr,
+ SymbolResolverPtrT Resolver) {
+ EXPECT_EQ(MockManager, *MemMgr) << "MM should pass through";
+ EXPECT_EQ(MockResolver, *Resolver) << "Resolver should pass through";
+ size_t I = 0;
+ for (auto &ObjPtr : Objects) {
+ EXPECT_EQ(MockObjects[I++] + 1, *ObjPtr) << "Transform should be applied";
+ }
+ EXPECT_EQ(MockObjects.size(), I) << "Number of objects should match";
+ LastCalled = "addObjectSet";
+ MockObjSetHandle = 111;
+ return MockObjSetHandle;
+ }
+ template <typename ObjSetT>
+ void expectAddObjectSet(ObjSetT &Objects, MockMemoryManager *MemMgr,
+ MockSymbolResolver *Resolver) {
+ MockManager = *MemMgr;
+ MockResolver = *Resolver;
+ for (auto &ObjPtr : Objects) {
+ MockObjects.push_back(*ObjPtr);
+ }
+ }
+ void verifyAddObjectSet(ObjSetHandleT Returned) {
+ EXPECT_EQ("addObjectSet", LastCalled);
+ EXPECT_EQ(MockObjSetHandle, Returned) << "Return should pass through";
+ resetExpectations();
+ }
+
+ void removeObjectSet(ObjSetHandleT H) {
+ EXPECT_EQ(MockObjSetHandle, H);
+ LastCalled = "removeObjectSet";
+ }
+ void expectRemoveObjectSet(ObjSetHandleT H) { MockObjSetHandle = H; }
+ void verifyRemoveObjectSet() {
+ EXPECT_EQ("removeObjectSet", LastCalled);
+ resetExpectations();
+ }
+
+ JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
+ EXPECT_EQ(MockName, Name) << "Name should pass through";
+ EXPECT_EQ(MockBool, ExportedSymbolsOnly) << "Flag should pass through";
+ LastCalled = "findSymbol";
+ MockSymbol = JITSymbol(122, llvm::JITSymbolFlags::None);
+ return MockSymbol;
+ }
+ void expectFindSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
+ MockName = Name;
+ MockBool = ExportedSymbolsOnly;
+ }
+ void verifyFindSymbol(llvm::orc::JITSymbol Returned) {
+ EXPECT_EQ("findSymbol", LastCalled);
+ EXPECT_EQ(MockSymbol.getAddress(), Returned.getAddress())
+ << "Return should pass through";
+ resetExpectations();
+ }
+
+ JITSymbol findSymbolIn(ObjSetHandleT H, const std::string &Name,
+ bool ExportedSymbolsOnly) {
+ EXPECT_EQ(MockObjSetHandle, H) << "Handle should pass through";
+ EXPECT_EQ(MockName, Name) << "Name should pass through";
+ EXPECT_EQ(MockBool, ExportedSymbolsOnly) << "Flag should pass through";
+ LastCalled = "findSymbolIn";
+ MockSymbol = JITSymbol(122, llvm::JITSymbolFlags::None);
+ return MockSymbol;
+ }
+ void expectFindSymbolIn(ObjSetHandleT H, const std::string &Name,
+ bool ExportedSymbolsOnly) {
+ MockObjSetHandle = H;
+ MockName = Name;
+ MockBool = ExportedSymbolsOnly;
+ }
+ void verifyFindSymbolIn(llvm::orc::JITSymbol Returned) {
+ EXPECT_EQ("findSymbolIn", LastCalled);
+ EXPECT_EQ(MockSymbol.getAddress(), Returned.getAddress())
+ << "Return should pass through";
+ resetExpectations();
+ }
+
+ void emitAndFinalize(ObjSetHandleT H) {
+ EXPECT_EQ(MockObjSetHandle, H) << "Handle should pass through";
+ LastCalled = "emitAndFinalize";
+ }
+ void expectEmitAndFinalize(ObjSetHandleT H) { MockObjSetHandle = H; }
+ void verifyEmitAndFinalize() {
+ EXPECT_EQ("emitAndFinalize", LastCalled);
+ resetExpectations();
+ }
+
+ void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
+ TargetAddress TargetAddr) {
+ EXPECT_EQ(MockObjSetHandle, H);
+ EXPECT_EQ(MockLocalAddress, LocalAddress);
+ EXPECT_EQ(MockTargetAddress, TargetAddr);
+ LastCalled = "mapSectionAddress";
+ }
+ void expectMapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
+ TargetAddress TargetAddr) {
+ MockObjSetHandle = H;
+ MockLocalAddress = LocalAddress;
+ MockTargetAddress = TargetAddr;
+ }
+ void verifyMapSectionAddress() {
+ EXPECT_EQ("mapSectionAddress", LastCalled);
+ resetExpectations();
+ }
+
+private:
+ // Backing fields for remembering parameter/return values
+ std::string LastCalled;
+ MockMemoryManager MockManager;
+ MockSymbolResolver MockResolver;
+ std::vector<MockObjectFile> MockObjects;
+ ObjSetHandleT MockObjSetHandle;
+ std::string MockName;
+ bool MockBool;
+ JITSymbol MockSymbol;
+ const void *MockLocalAddress;
+ TargetAddress MockTargetAddress;
+ MockMemoryBufferSet MockBufferSet;
+
+ // Clear remembered parameters between calls
+ void resetExpectations() {
+ LastCalled = "nothing";
+ MockManager = 0;
+ MockResolver = 0;
+ MockObjects.clear();
+ MockObjSetHandle = 0;
+ MockName = "bogus";
+ MockSymbol = JITSymbol(nullptr);
+ MockLocalAddress = nullptr;
+ MockTargetAddress = 0;
+ MockBufferSet = 0;
+ }
+};
+
+// Test each operation on ObjectTransformLayer.
+TEST(ObjectTransformLayerTest, Main) {
+ MockBaseLayer M;
+
+ // Create one object transform layer using a transform (as a functor)
+ // that allocates new objects, and deals in unique pointers.
+ ObjectTransformLayer<MockBaseLayer, AllocatingTransform> T1(M);
+
+ // Create a second object transform layer using a transform (as a lambda)
+ // that mutates objects in place, and deals in naked pointers
+ ObjectTransformLayer<MockBaseLayer,
+ std::function<MockObjectFile *(MockObjectFile *)>>
+ T2(M, [](MockObjectFile *Obj) {
+ ++(*Obj);
+ return Obj;
+ });
+
+ // Instantiate some mock objects to use below
+ MockObjectFile MockObject1 = 211;
+ MockObjectFile MockObject2 = 222;
+ MockMemoryManager MockManager = 233;
+ MockSymbolResolver MockResolver = 244;
+
+ // Test addObjectSet with T1 (allocating, unique pointers)
+ std::vector<std::unique_ptr<MockObjectFile>> Objs1;
+ Objs1.push_back(llvm::make_unique<MockObjectFile>(MockObject1));
+ Objs1.push_back(llvm::make_unique<MockObjectFile>(MockObject2));
+ auto MM = llvm::make_unique<MockMemoryManager>(MockManager);
+ auto SR = llvm::make_unique<MockSymbolResolver>(MockResolver);
+ M.expectAddObjectSet(Objs1, MM.get(), SR.get());
+ auto H = T1.addObjectSet(Objs1, std::move(MM), std::move(SR));
+ M.verifyAddObjectSet(H);
+
+ // Test addObjectSet with T2 (mutating, naked pointers)
+ llvm::SmallVector<MockObjectFile *, 2> Objs2;
+ Objs2.push_back(&MockObject1);
+ Objs2.push_back(&MockObject2);
+ M.expectAddObjectSet(Objs2, &MockManager, &MockResolver);
+ H = T2.addObjectSet(Objs2, &MockManager, &MockResolver);
+ M.verifyAddObjectSet(H);
+ EXPECT_EQ(212, MockObject1) << "Expected mutation";
+ EXPECT_EQ(223, MockObject2) << "Expected mutation";
+
+ // Test removeObjectSet
+ M.expectRemoveObjectSet(H);
+ T1.removeObjectSet(H);
+ M.verifyRemoveObjectSet();
+
+ // Test findSymbol
+ std::string Name = "foo";
+ bool ExportedOnly = true;
+ M.expectFindSymbol(Name, ExportedOnly);
+ JITSymbol Symbol = T2.findSymbol(Name, ExportedOnly);
+ M.verifyFindSymbol(Symbol);
+
+ // Test findSymbolIn
+ Name = "bar";
+ ExportedOnly = false;
+ M.expectFindSymbolIn(H, Name, ExportedOnly);
+ Symbol = T1.findSymbolIn(H, Name, ExportedOnly);
+ M.verifyFindSymbolIn(Symbol);
+
+ // Test emitAndFinalize
+ M.expectEmitAndFinalize(H);
+ T2.emitAndFinalize(H);
+ M.verifyEmitAndFinalize();
+
+ // Test mapSectionAddress
+ char Buffer[24];
+ TargetAddress MockAddress = 255;
+ M.expectMapSectionAddress(H, Buffer, MockAddress);
+ T1.mapSectionAddress(H, Buffer, MockAddress);
+ M.verifyMapSectionAddress();
+
+ // Verify transform getter (non-const)
+ MockObjectFile Mutatee = 277;
+ MockObjectFile *Out = T2.getTransform()(&Mutatee);
+ EXPECT_EQ(&Mutatee, Out) << "Expected in-place transform";
+ EXPECT_EQ(278, Mutatee) << "Expected incrementing transform";
+
+ // Verify transform getter (const)
+ auto OwnedObj = llvm::make_unique<MockObjectFile>(288);
+ const auto &T1C = T1;
+ OwnedObj = T1C.getTransform()(std::move(OwnedObj));
+ EXPECT_EQ(289, *OwnedObj) << "Expected incrementing transform";
+}
+}