@@ -25,6 +25,7 @@
#include <future>
#include <testsuite_hooks.h>
+#include <sys/time.h>
using namespace std;
@@ -94,11 +95,86 @@ void test03()
VERIFY( elapsed < std::chrono::seconds(20) );
}
+void perturb_system_clock(const std::chrono::seconds &seconds)
+{
+ struct timeval tv;
+ if (gettimeofday(&tv, NULL))
+ abort();
+
+ tv.tv_sec += seconds.count();
+ if (settimeofday(&tv, NULL))
+ abort();
+}
+
+void work04()
+{
+ std::this_thread::sleep_for(std::chrono::seconds(10));
+}
+
+// Ensure that advancing CLOCK_REALTIME doesn't make any difference
+// when we're waiting on std::chrono::steady_clock.
+void test04()
+{
+ auto const start = chrono::steady_clock::now();
+ future<void> f1 = async(launch::async, &work04);
+
+ perturb_system_clock(chrono::seconds(20));
+
+ std::future_status status;
+ status = f1.wait_for(std::chrono::seconds(4));
+ VERIFY( status == std::future_status::timeout );
+
+ status = f1.wait_until(start + std::chrono::seconds(6));
+ VERIFY( status == std::future_status::timeout );
+
+ status = f1.wait_until(start + std::chrono::seconds(12));
+ VERIFY( status == std::future_status::ready );
+
+ auto const elapsed = chrono::steady_clock::now() - start;
+ VERIFY( elapsed >= std::chrono::seconds(10) );
+ VERIFY( elapsed < std::chrono::seconds(15) );
+
+ perturb_system_clock(chrono::seconds(-20));
+}
+
+void work05()
+{
+ std::this_thread::sleep_for(std::chrono::seconds(5));
+ perturb_system_clock(chrono::seconds(60));
+ std::this_thread::sleep_for(std::chrono::seconds(5));
+}
+
+// Ensure that advancing CLOCK_REALTIME does make a difference when
+// we're waiting on std::chrono::system_clock.
+void test05()
+{
+ auto const start = chrono::system_clock::now();
+ auto const start_steady = chrono::steady_clock::now();
+
+ future<void> f1 = async(launch::async, &work05);
+ future_status status;
+ status = f1.wait_until(start + std::chrono::seconds(60));
+ VERIFY( status == std::future_status::timeout );
+
+ auto const elapsed_steady = chrono::steady_clock::now() - start_steady;
+ VERIFY( elapsed_steady >= std::chrono::seconds(5) );
+ VERIFY( elapsed_steady < std::chrono::seconds(10) );
+
+ status = f1.wait_until(start + std::chrono::seconds(75));
+ VERIFY( status == std::future_status::ready );
+
+ perturb_system_clock(chrono::seconds(-60));
+}
+
int main()
{
test01();
test02();
test03<std::chrono::system_clock>();
test03<std::chrono::steady_clock>();
+ if (geteuid() == 0) {
+ test04();
+ test05();
+ }
return 0;
}