From 2ca233e645016cfab5badc4d967bf46c68839701 Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Wed, 16 Nov 2016 17:31:09 +0000 Subject: [PATCH] [Orc] Re-enable the RPC unit test disabled in r286917. This unit test infinite-looped on s390x due to a thread_yield being optimized out. I've updated the QueueChannel class (where thread_yield was called) to use a condition variable instead. This should cause the unit test to behave correctly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@287121 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../ExecutionEngine/Orc/RPCUtilsTest.cpp | 331 +++++++++--------- 1 file changed, 163 insertions(+), 168 deletions(-) diff --git a/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp b/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp index d658780b036..6da8b63c0d4 100644 --- a/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp +++ b/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp @@ -19,10 +19,11 @@ using namespace llvm::orc::rpc; class Queue : public std::queue { public: - std::mutex &getLock() { return Lock; } - + std::mutex &getMutex() { return M; } + std::condition_variable &getCondVar() { return CV; } private: - std::mutex Lock; + std::mutex M; + std::condition_variable CV; }; class QueueChannel : public RawByteChannel { @@ -31,26 +32,22 @@ public: : InQueue(InQueue), OutQueue(OutQueue) {} Error readBytes(char *Dst, unsigned Size) override { - while (Size != 0) { - // If there's nothing to read then yield. + std::unique_lock Lock(InQueue.getMutex()); + while (Size) { while (InQueue.empty()) - std::this_thread::yield(); - - // Lock the channel and read what we can. - std::lock_guard Lock(InQueue.getLock()); - while (!InQueue.empty() && Size) { - *Dst++ = InQueue.front(); - --Size; - InQueue.pop(); - } + InQueue.getCondVar().wait(Lock); + *Dst++ = InQueue.front(); + --Size; + InQueue.pop(); } return Error::success(); } Error appendBytes(const char *Src, unsigned Size) override { - std::lock_guard Lock(OutQueue.getLock()); + std::unique_lock Lock(OutQueue.getMutex()); while (Size--) OutQueue.push(*Src++); + OutQueue.getCondVar().notify_one(); return Error::success(); } @@ -93,162 +90,160 @@ private: QueueChannel C; }; -// FIXME: Temporarily disabled while the infnite loop discovered in r286639 is -// fixed (see llvm commits list discussion for that commit). -// TEST(DummyRPC, TestAsyncVoidBool) { -// Queue Q1, Q2; -// DummyRPCEndpoint Client(Q1, Q2); -// DummyRPCEndpoint Server(Q2, Q1); - -// std::thread ServerThread([&]() { -// Server.addHandler( -// [](bool B) { -// EXPECT_EQ(B, true) -// << "Server void(bool) received unexpected result"; -// }); - -// { -// // Poke the server to handle the negotiate call. -// auto Err = Server.handleOne(); -// EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate"; -// } - -// { -// // Poke the server to handle the VoidBool call. -// auto Err = Server.handleOne(); -// EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)"; -// } -// }); - -// { -// // Make an async call. -// auto Err = Client.callAsync( -// [](Error Err) { -// EXPECT_FALSE(!!Err) << "Async void(bool) response handler failed"; -// return Error::success(); -// }, true); -// EXPECT_FALSE(!!Err) << "Client.callAsync failed for void(bool)"; -// } - -// { -// // Poke the client to process the result of the void(bool) call. -// auto Err = Client.handleOne(); -// EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)"; -// } - -// ServerThread.join(); -// } +TEST(DummyRPC, TestAsyncVoidBool) { + Queue Q1, Q2; + DummyRPCEndpoint Client(Q1, Q2); + DummyRPCEndpoint Server(Q2, Q1); -// TEST(DummyRPC, TestAsyncIntInt) { -// Queue Q1, Q2; -// DummyRPCEndpoint Client(Q1, Q2); -// DummyRPCEndpoint Server(Q2, Q1); - -// std::thread ServerThread([&]() { -// Server.addHandler( -// [](int X) -> int { -// EXPECT_EQ(X, 21) << "Server int(int) receieved unexpected result"; -// return 2 * X; -// }); - -// { -// // Poke the server to handle the negotiate call. -// auto Err = Server.handleOne(); -// EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate"; -// } - -// { -// // Poke the server to handle the int(int) call. -// auto Err = Server.handleOne(); -// EXPECT_FALSE(!!Err) << "Server failed to handle call to int(int)"; -// } -// }); - -// { -// auto Err = Client.callAsync( -// [](Expected Result) { -// EXPECT_TRUE(!!Result) << "Async int(int) response handler failed"; -// EXPECT_EQ(*Result, 42) -// << "Async int(int) response handler received incorrect result"; -// return Error::success(); -// }, 21); -// EXPECT_FALSE(!!Err) << "Client.callAsync failed for int(int)"; -// } - -// { -// // Poke the client to process the result. -// auto Err = Client.handleOne(); -// EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)"; -// } - -// ServerThread.join(); -// } + std::thread ServerThread([&]() { + Server.addHandler( + [](bool B) { + EXPECT_EQ(B, true) + << "Server void(bool) received unexpected result"; + }); -// TEST(DummyRPC, TestSerialization) { -// Queue Q1, Q2; -// DummyRPCEndpoint Client(Q1, Q2); -// DummyRPCEndpoint Server(Q2, Q1); - -// std::thread ServerThread([&]() { -// Server.addHandler( -// [&](int8_t S8, uint8_t U8, int16_t S16, uint16_t U16, -// int32_t S32, uint32_t U32, int64_t S64, uint64_t U64, -// bool B, std::string S, std::vector V) { - -// EXPECT_EQ(S8, -101) << "int8_t serialization broken"; -// EXPECT_EQ(U8, 250) << "uint8_t serialization broken"; -// EXPECT_EQ(S16, -10000) << "int16_t serialization broken"; -// EXPECT_EQ(U16, 10000) << "uint16_t serialization broken"; -// EXPECT_EQ(S32, -1000000000) << "int32_t serialization broken"; -// EXPECT_EQ(U32, 1000000000ULL) << "uint32_t serialization broken"; -// EXPECT_EQ(S64, -10000000000) << "int64_t serialization broken"; -// EXPECT_EQ(U64, 10000000000ULL) << "uint64_t serialization broken"; -// EXPECT_EQ(B, true) << "bool serialization broken"; -// EXPECT_EQ(S, "foo") << "std::string serialization broken"; -// EXPECT_EQ(V, std::vector({42, 7})) -// << "std::vector serialization broken"; -// return Error::success(); -// }); - -// { -// // Poke the server to handle the negotiate call. -// auto Err = Server.handleOne(); -// EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate"; -// } - -// { -// // Poke the server to handle the AllTheTypes call. -// auto Err = Server.handleOne(); -// EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)"; -// } -// }); - - -// { -// // Make an async call. -// std::vector v({42, 7}); -// auto Err = Client.callAsync( -// [](Error Err) { -// EXPECT_FALSE(!!Err) << "Async AllTheTypes response handler failed"; -// return Error::success(); -// }, -// static_cast(-101), static_cast(250), -// static_cast(-10000), static_cast(10000), -// static_cast(-1000000000), static_cast(1000000000), -// static_cast(-10000000000), static_cast(10000000000), -// true, std::string("foo"), v); -// EXPECT_FALSE(!!Err) << "Client.callAsync failed for AllTheTypes"; -// } - -// { -// // Poke the client to process the result of the AllTheTypes call. -// auto Err = Client.handleOne(); -// EXPECT_FALSE(!!Err) << "Client failed to handle response from AllTheTypes"; -// } - -// ServerThread.join(); -// } + { + // Poke the server to handle the negotiate call. + auto Err = Server.handleOne(); + EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate"; + } + + { + // Poke the server to handle the VoidBool call. + auto Err = Server.handleOne(); + EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)"; + } + }); + + { + // Make an async call. + auto Err = Client.callAsync( + [](Error Err) { + EXPECT_FALSE(!!Err) << "Async void(bool) response handler failed"; + return Error::success(); + }, true); + EXPECT_FALSE(!!Err) << "Client.callAsync failed for void(bool)"; + } + + { + // Poke the client to process the result of the void(bool) call. + auto Err = Client.handleOne(); + EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)"; + } + + ServerThread.join(); +} + +TEST(DummyRPC, TestAsyncIntInt) { + Queue Q1, Q2; + DummyRPCEndpoint Client(Q1, Q2); + DummyRPCEndpoint Server(Q2, Q1); + + std::thread ServerThread([&]() { + Server.addHandler( + [](int X) -> int { + EXPECT_EQ(X, 21) << "Server int(int) receieved unexpected result"; + return 2 * X; + }); + + { + // Poke the server to handle the negotiate call. + auto Err = Server.handleOne(); + EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate"; + } + + { + // Poke the server to handle the int(int) call. + auto Err = Server.handleOne(); + EXPECT_FALSE(!!Err) << "Server failed to handle call to int(int)"; + } + }); + + { + auto Err = Client.callAsync( + [](Expected Result) { + EXPECT_TRUE(!!Result) << "Async int(int) response handler failed"; + EXPECT_EQ(*Result, 42) + << "Async int(int) response handler received incorrect result"; + return Error::success(); + }, 21); + EXPECT_FALSE(!!Err) << "Client.callAsync failed for int(int)"; + } + + { + // Poke the client to process the result. + auto Err = Client.handleOne(); + EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)"; + } + + ServerThread.join(); +} + +TEST(DummyRPC, TestSerialization) { + Queue Q1, Q2; + DummyRPCEndpoint Client(Q1, Q2); + DummyRPCEndpoint Server(Q2, Q1); + + std::thread ServerThread([&]() { + Server.addHandler( + [&](int8_t S8, uint8_t U8, int16_t S16, uint16_t U16, + int32_t S32, uint32_t U32, int64_t S64, uint64_t U64, + bool B, std::string S, std::vector V) { + + EXPECT_EQ(S8, -101) << "int8_t serialization broken"; + EXPECT_EQ(U8, 250) << "uint8_t serialization broken"; + EXPECT_EQ(S16, -10000) << "int16_t serialization broken"; + EXPECT_EQ(U16, 10000) << "uint16_t serialization broken"; + EXPECT_EQ(S32, -1000000000) << "int32_t serialization broken"; + EXPECT_EQ(U32, 1000000000ULL) << "uint32_t serialization broken"; + EXPECT_EQ(S64, -10000000000) << "int64_t serialization broken"; + EXPECT_EQ(U64, 10000000000ULL) << "uint64_t serialization broken"; + EXPECT_EQ(B, true) << "bool serialization broken"; + EXPECT_EQ(S, "foo") << "std::string serialization broken"; + EXPECT_EQ(V, std::vector({42, 7})) + << "std::vector serialization broken"; + return Error::success(); + }); + + { + // Poke the server to handle the negotiate call. + auto Err = Server.handleOne(); + EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate"; + } + + { + // Poke the server to handle the AllTheTypes call. + auto Err = Server.handleOne(); + EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)"; + } + }); + + + { + // Make an async call. + std::vector v({42, 7}); + auto Err = Client.callAsync( + [](Error Err) { + EXPECT_FALSE(!!Err) << "Async AllTheTypes response handler failed"; + return Error::success(); + }, + static_cast(-101), static_cast(250), + static_cast(-10000), static_cast(10000), + static_cast(-1000000000), static_cast(1000000000), + static_cast(-10000000000), static_cast(10000000000), + true, std::string("foo"), v); + EXPECT_FALSE(!!Err) << "Client.callAsync failed for AllTheTypes"; + } + + { + // Poke the client to process the result of the AllTheTypes call. + auto Err = Client.handleOne(); + EXPECT_FALSE(!!Err) << "Client failed to handle response from AllTheTypes"; + } + + ServerThread.join(); +} // Test the synchronous call API. // TEST_F(DummyRPC, TestSynchronousCall) { -- 2.40.0