update_engine: UM: Add check for monotonic time elapsed.
This forks the former EvaluationStatus::IsTimeGreaterThan() into two
separate variants, checking either the wallclock or monotonic current
time against a corresponding timestamp. This is needed for policies that
require resilience against wallclock time volatility.
BUG=chromium:394778
TEST=Unit tests.
Change-Id: I9ecd20cc87a3a520e119f157e55ae4f54104a506
Reviewed-on: https://chromium-review.googlesource.com/209487
Commit-Queue: Gilad Arnold <garnold@chromium.org>
Tested-by: Gilad Arnold <garnold@chromium.org>
Reviewed-by: Gilad Arnold <garnold@chromium.org>
diff --git a/update_manager/evaluation_context_unittest.cc b/update_manager/evaluation_context_unittest.cc
index eafb219..52755fc 100644
--- a/update_manager/evaluation_context_unittest.cc
+++ b/update_manager/evaluation_context_unittest.cc
@@ -69,9 +69,9 @@
class UmEvaluationContextTest : public ::testing::Test {
protected:
virtual void SetUp() {
- // Set the clock to a fixed values.
- fake_clock_.SetMonotonicTime(Time::FromInternalValue(12345678L));
- // Mar 2, 2006 1:23:45 UTC is 1141262625 since the Unix Epoch.
+ // Apr 22, 2009 19:25:00 UTC (this is a random reference point).
+ fake_clock_.SetMonotonicTime(Time::FromTimeT(1240428300));
+ // Mar 2, 2006 1:23:45 UTC.
fake_clock_.SetWallclockTime(Time::FromTimeT(1141262625));
eval_ctx_ = new EvaluationContext(&fake_clock_, default_timeout_,
default_timeout_);
@@ -337,47 +337,94 @@
UMTEST_EXPECT_NULL(eval_ctx_->GetValue(&mock_var_async_));
}
-TEST_F(UmEvaluationContextTest, ResetEvaluationResetsTimes) {
+TEST_F(UmEvaluationContextTest, ResetEvaluationResetsTimesWallclock) {
base::Time cur_time = fake_clock_.GetWallclockTime();
// Advance the time on the clock but don't call ResetEvaluation yet.
fake_clock_.SetWallclockTime(cur_time + TimeDelta::FromSeconds(4));
- EXPECT_TRUE(eval_ctx_->IsTimeGreaterThan(cur_time -
- TimeDelta::FromSeconds(1)));
- EXPECT_FALSE(eval_ctx_->IsTimeGreaterThan(cur_time));
- EXPECT_FALSE(eval_ctx_->IsTimeGreaterThan(cur_time +
- TimeDelta::FromSeconds(1)));
+ EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
+ cur_time - TimeDelta::FromSeconds(1)));
+ EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time));
+ EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
+ cur_time + TimeDelta::FromSeconds(1)));
// Call ResetEvaluation now, which should use the new evaluation time.
eval_ctx_->ResetEvaluation();
cur_time = fake_clock_.GetWallclockTime();
- EXPECT_TRUE(eval_ctx_->IsTimeGreaterThan(cur_time -
- TimeDelta::FromSeconds(1)));
- EXPECT_FALSE(eval_ctx_->IsTimeGreaterThan(cur_time));
- EXPECT_FALSE(eval_ctx_->IsTimeGreaterThan(cur_time +
- TimeDelta::FromSeconds(1)));
+ EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
+ cur_time - TimeDelta::FromSeconds(1)));
+ EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time));
+ EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
+ cur_time + TimeDelta::FromSeconds(1)));
}
-TEST_F(UmEvaluationContextTest, IsTimeGreaterThanSignalsTriggerReevaluation) {
- EXPECT_FALSE(eval_ctx_->IsTimeGreaterThan(
+TEST_F(UmEvaluationContextTest, ResetEvaluationResetsTimesMonotonic) {
+ base::Time cur_time = fake_clock_.GetMonotonicTime();
+ // Advance the time on the clock but don't call ResetEvaluation yet.
+ fake_clock_.SetMonotonicTime(cur_time + TimeDelta::FromSeconds(4));
+
+ EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
+ cur_time - TimeDelta::FromSeconds(1)));
+ EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time));
+ EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
+ cur_time + TimeDelta::FromSeconds(1)));
+ // Call ResetEvaluation now, which should use the new evaluation time.
+ eval_ctx_->ResetEvaluation();
+
+ cur_time = fake_clock_.GetMonotonicTime();
+ EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
+ cur_time - TimeDelta::FromSeconds(1)));
+ EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time));
+ EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
+ cur_time + TimeDelta::FromSeconds(1)));
+}
+
+TEST_F(UmEvaluationContextTest,
+ IsWallclockTimeGreaterThanSignalsTriggerReevaluation) {
+ EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
fake_clock_.GetWallclockTime() + TimeDelta::FromSeconds(1)));
- // The "false" from IsTimeGreaterThan means that's not that timestamp yet, so
- // this should schedule a callback for when that happens.
+ // The "false" from IsWallclockTimeGreaterThan means that's not that timestamp
+ // yet, so this should schedule a callback for when that happens.
EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
}
-TEST_F(UmEvaluationContextTest, IsTimeGreaterThanDoesntRecordPastTimestamps) {
- // IsTimeGreaterThan() should ignore timestamps on the past for reevaluation.
- EXPECT_TRUE(eval_ctx_->IsTimeGreaterThan(
+TEST_F(UmEvaluationContextTest,
+ IsMonotonicTimeGreaterThanSignalsTriggerReevaluation) {
+ EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
+ fake_clock_.GetMonotonicTime() + TimeDelta::FromSeconds(1)));
+
+ // The "false" from IsMonotonicTimeGreaterThan means that's not that timestamp
+ // yet, so this should schedule a callback for when that happens.
+ EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
+}
+
+TEST_F(UmEvaluationContextTest,
+ IsWallclockTimeGreaterThanDoesntRecordPastTimestamps) {
+ // IsWallclockTimeGreaterThan() should ignore timestamps on the past for
+ // reevaluation.
+ EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
fake_clock_.GetWallclockTime() - TimeDelta::FromSeconds(20)));
- EXPECT_TRUE(eval_ctx_->IsTimeGreaterThan(
+ EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
fake_clock_.GetWallclockTime() - TimeDelta::FromSeconds(1)));
// Callback should not be scheduled.
EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
}
+TEST_F(UmEvaluationContextTest,
+ IsMonotonicTimeGreaterThanDoesntRecordPastTimestamps) {
+ // IsMonotonicTimeGreaterThan() should ignore timestamps on the past for
+ // reevaluation.
+ EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
+ fake_clock_.GetMonotonicTime() - TimeDelta::FromSeconds(20)));
+ EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
+ fake_clock_.GetMonotonicTime() - TimeDelta::FromSeconds(1)));
+
+ // Callback should not be scheduled.
+ EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
+}
+
TEST_F(UmEvaluationContextTest, DumpContext) {
// |fail_var_| yield "(no value)" since it is unset.
eval_ctx_->GetValue(&fail_var_);
@@ -391,10 +438,11 @@
eval_ctx_->GetValue(&fake_poll_var_);
// Note that the variables are printed in alphabetical order. Also
- // see UmEvaluationContextText::SetUp() where the value used for
- // |evaluation_start| is set.
+ // see UmEvaluationContextText::SetUp() where the values used for
+ // |evaluation_start_{monotonic,wallclock| are set.
EXPECT_EQ("{\n"
- " \"evaluation_start\": \"3/2/2006 1:23:45 GMT\",\n"
+ " \"evaluation_start_monotonic\": \"4/22/2009 19:25:00 GMT\",\n"
+ " \"evaluation_start_wallclock\": \"3/2/2006 1:23:45 GMT\",\n"
" \"variables\": {\n"
" \"fail_var\": \"(no value)\",\n"
" \"fake_int\": \"42\",\n"