// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers // // This file is part of Bytecoin. // // Bytecoin is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Bytecoin is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . #include #include #include #include #include #include #include using namespace System; class RemoteContextTests : public testing::Test { public: Dispatcher dispatcher; }; TEST_F(RemoteContextTests, getReturnsResult) { RemoteContext context(dispatcher, [&] { return 2; }); ASSERT_EQ(2, context.get()); } TEST_F(RemoteContextTests, getRethrowsException) { RemoteContext<> context(dispatcher, [&] { throw std::string("Hi there!"); }); ASSERT_THROW(context.get(), std::string); } TEST_F(RemoteContextTests, destructorIgnoresException) { ASSERT_NO_THROW(RemoteContext<>(dispatcher, [&] { throw std::string("Hi there!"); })); } TEST_F(RemoteContextTests, canBeUsedWithoutObject) { ASSERT_EQ(42, RemoteContext(dispatcher, [&] { return 42; }).get()); } TEST_F(RemoteContextTests, interruptIsInterruptingWait) { ContextGroup cg(dispatcher); cg.spawn([&] { RemoteContext<> context(dispatcher, [&] { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }); ASSERT_NO_THROW(context.wait()); ASSERT_TRUE(dispatcher.interrupted()); }); cg.interrupt(); cg.wait(); } TEST_F(RemoteContextTests, interruptIsInterruptingGet) { ContextGroup cg(dispatcher); cg.spawn([&] { RemoteContext<> context(dispatcher, [&] { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }); ASSERT_NO_THROW(context.wait()); ASSERT_TRUE(dispatcher.interrupted()); }); cg.interrupt(); cg.wait(); } TEST_F(RemoteContextTests, destructorIgnoresInterrupt) { ContextGroup cg(dispatcher); cg.spawn([&] { ASSERT_NO_THROW(RemoteContext<>(dispatcher, [&] { std::this_thread::sleep_for(std::chrono::milliseconds(10)); })); }); cg.interrupt(); cg.wait(); } TEST_F(RemoteContextTests, canExecuteOtherContextsWhileWaiting) { auto start = std::chrono::high_resolution_clock::now(); ContextGroup cg(dispatcher); cg.spawn([&] { RemoteContext<> context(dispatcher, [&] { std::this_thread::sleep_for(std::chrono::milliseconds(100)); }); }); cg.spawn([&] { System::Timer(dispatcher).sleep(std::chrono::milliseconds(50)); auto end = std::chrono::high_resolution_clock::now(); ASSERT_GE(std::chrono::duration_cast(end - start).count(), 50); ASSERT_LT(std::chrono::duration_cast(end - start).count(), 100); }); cg.wait(); } TEST_F(RemoteContextTests, waitMethodWaitsForContexCompletion) { auto start = std::chrono::high_resolution_clock::now(); ContextGroup cg(dispatcher); cg.spawn([&] { RemoteContext<> context(dispatcher, [&] { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }); }); cg.wait(); auto end = std::chrono::high_resolution_clock::now(); ASSERT_GE(std::chrono::duration_cast(end - start).count(), 10); } TEST_F(RemoteContextTests, waitMethodWaitsForContexCompletionOnInterrupt) { auto start = std::chrono::high_resolution_clock::now(); ContextGroup cg(dispatcher); cg.spawn([&] { RemoteContext<> context(dispatcher, [&] { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }); }); cg.interrupt(); cg.wait(); auto end = std::chrono::high_resolution_clock::now(); ASSERT_GE(std::chrono::duration_cast(end - start).count(), 10); }