bool await(const process::Future<T>& future, const Duration& duration) { if (!process::Clock::paused()) { return future.await(duration); } // If the clock is paused, no new timers will expire. // Future::await(duration) may hang forever because it depends on // a timer to expire after 'duration'. We instead ensure all // expired timers are flushed and check if the future is satisfied. Stopwatch stopwatch; stopwatch.start(); // Settle to make sure all expired timers are executed (not // necessarily finished, see below). process::Clock::settle(); while (future.isPending() && stopwatch.elapsed() < duration) { // Synchronous operations and asynchronous process::Process // operations should finish when the above 'settle()' returns. // Other types of async operations such as io::write() may not. // Therefore we wait the specified duration for it to complete. // Note that nothing prevents the operations to schedule more // timeouts for some time in the future. These timeouts will // never be executed due to the paused process::Clock. In this // case we return after the stopwatch (system clock) runs out. os::sleep(Milliseconds(10)); } return !future.isPending(); }
inline ::testing::AssertionResult AwaitAssertResponseBodyEq( const char* expectedExpr, const char* actualExpr, const char* durationExpr, const std::string& expected, const process::Future<process::http::Response>& actual, const Duration& duration) { const ::testing::AssertionResult result = AwaitAssertReady(actualExpr, durationExpr, actual, duration); if (result) { if (expected == actual.get().body) { return ::testing::AssertionSuccess(); } else { return ::testing::AssertionFailure() << "Value of: (" << actualExpr << ").get().body\n" << " Actual: " << ::testing::PrintToString(actual.get().body) << "\n" << "Expected: " << expectedExpr << "\n" << "Which is: " << ::testing::PrintToString(expected); } } return result; }
Future<Nothing> _destroy( const ContainerID& containerId, process::Future<bool> destroyed) { if (destroyed.isFailed()) { LOG(ERROR) << "Failed to destroy freezer cgroup for '" << containerId << "': " << destroyed.failure(); return Failure("Failed to destroy launcher: " + destroyed.failure()); } return Nothing(); }
Future<Nothing> _destroy( const ContainerID& containerId, const process::Future<Nothing>& destroyed) { if (!destroyed.isReady()) { return Failure("Failed to destroy launcher: " + (destroyed.isFailed() ? destroyed.failure() : "discarded")); } return Nothing(); }
Option<Error> _check_failed(const process::Future<T>& f) { if (f.isPending()) { return Some("is PENDING"); } else if (f.isReady()) { return Some("is READY"); } else if (f.isDiscarded()) { return Some("is DISCARDED"); } else { CHECK(f.isFailed()); return None(); } }
Option<Error> _check_discarded(const process::Future<T>& f) { if (f.isPending()) { return Error("is PENDING"); } else if (f.isReady()) { return Error("is READY"); } else if (f.isFailed()) { return Error("is FAILED: " + f.failure()); } else { CHECK(f.isDiscarded()); return None(); } }
inline ::testing::AssertionResult AwaitAssertResponseHeaderEq( const char* expectedExpr, const char* keyExpr, const char* actualExpr, const char* durationExpr, const std::string& expected, const std::string& key, const process::Future<process::http::Response>& actual, const Duration& duration) { const ::testing::AssertionResult result = AwaitAssertReady(actualExpr, durationExpr, actual, duration); if (result) { const Option<std::string> value = actual.get().headers.get(key); if (value.isNone()) { return ::testing::AssertionFailure() << "Response does not contain header '" << key << "'"; } else if (expected == value.get()) { return ::testing::AssertionSuccess(); } else { return ::testing::AssertionFailure() << "Value of: (" << actualExpr << ").get().headers[" << keyExpr << "]\n" << " Actual: " << ::testing::PrintToString(value.get()) << "\n" << "Expected: " << expectedExpr << "\n" << "Which is: " << ::testing::PrintToString(expected); } } return result; }
::testing::AssertionResult AwaitAssertAbandoned( const char* expr, const char*, // Unused string representation of 'duration'. const process::Future<T>& actual, const Duration& duration) { process::Owned<process::Latch> latch(new process::Latch()); actual.onAny([=]() { latch->trigger(); }); actual.onAbandoned([=]() { latch->trigger(); }); if (!latch->await(duration)) { return ::testing::AssertionFailure() << "Failed to wait " << duration << " for " << expr; } else if (actual.isDiscarded()) { return ::testing::AssertionFailure() << expr << " was discarded"; } else if (actual.isReady()) { return ::testing::AssertionFailure() << expr << " is ready (" << ::testing::PrintToString(actual.get()) << ")"; } else if (actual.isFailed()) { return ::testing::AssertionFailure() << "(" << expr << ").failure(): " << actual.failure(); } CHECK_ABANDONED(actual); return ::testing::AssertionSuccess(); }
::testing::AssertionResult AwaitAssertDiscarded( const char* expr, const char*, // Unused string representation of 'duration'. const process::Future<T>& actual, const Duration& duration) { if (!process::internal::await(actual, duration)) { return ::testing::AssertionFailure() << "Failed to wait " << duration << " for " << expr; } else if (actual.isFailed()) { return ::testing::AssertionFailure() << "(" << expr << ").failure(): " << actual.failure(); } else if (actual.isReady()) { return ::testing::AssertionFailure() << expr << " is ready (" << ::testing::PrintToString(actual.get()) << ")"; } return ::testing::AssertionSuccess(); }
inline ::testing::AssertionResult AwaitAssertTermSigNe( const char* expectedExpr, const char* actualExpr, const char* durationExpr, const int expected, const process::Future<Option<int>>& actual, const Duration& duration) { const ::testing::AssertionResult result = AwaitAssertSignaled(actualExpr, durationExpr, actual, duration); if (result) { CHECK_READY(actual); CHECK_SOME(actual.get()); return AssertTermSigNe( expectedExpr, strings::join("(", actualExpr, ")->get()").c_str(), expected, actual->get()); } return result; }
inline ::testing::AssertionResult AwaitAssertSignaled( const char* actualExpr, const char* durationExpr, const process::Future<Option<int>>& actual, const Duration& duration) { const ::testing::AssertionResult result = AwaitAssertReady(actualExpr, durationExpr, actual, duration); if (result) { CHECK_READY(actual); if (actual->isNone()) { return ::testing::AssertionFailure() << "(" << actualExpr << ")->isNone() is true"; } return AssertSignaled( strings::join("(", actualExpr, ")->get()").c_str(), actual->get()); } return result; }