blob: c5cc88393f8295652b667a5c6bb040f6c759958d [file] [log] [blame]
Alex Deymo23949d42014-02-05 15:20:59 -08001// Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Alex Deymoaab50e32014-11-10 19:55:35 -08005#include "update_engine/update_manager/evaluation_context.h"
6
Ben Chan02f7c1d2014-10-18 15:18:02 -07007#include <memory>
Alex Deymo23949d42014-02-05 15:20:59 -08008#include <string>
9
Alex Deymo53556ec2014-03-17 10:05:57 -070010#include <base/bind.h>
Alex Deymo53556ec2014-03-17 10:05:57 -070011#include <gtest/gtest.h>
12
Alex Deymo41a75a72014-04-15 15:36:22 -070013#include "update_engine/fake_clock.h"
Alex Deymo53556ec2014-03-17 10:05:57 -070014#include "update_engine/test_utils.h"
Alex Deymo63784a52014-05-28 10:46:14 -070015#include "update_engine/update_manager/fake_variable.h"
16#include "update_engine/update_manager/generic_variables.h"
17#include "update_engine/update_manager/mock_variable.h"
18#include "update_engine/update_manager/umtest_utils.h"
Alex Deymo23949d42014-02-05 15:20:59 -080019
Alex Deymo53556ec2014-03-17 10:05:57 -070020using base::Bind;
Gilad Arnoldfb794f42014-07-01 15:36:31 -070021using base::Closure;
Alex Deymo41a75a72014-04-15 15:36:22 -070022using base::Time;
Alex Deymo53556ec2014-03-17 10:05:57 -070023using base::TimeDelta;
Alex Deymo41a75a72014-04-15 15:36:22 -070024using chromeos_update_engine::FakeClock;
Alex Deymo10875d92014-11-10 21:52:57 -080025using chromeos_update_engine::test_utils::RunGMainLoopMaxIterations;
26using chromeos_update_engine::test_utils::RunGMainLoopUntil;
Alex Deymo23949d42014-02-05 15:20:59 -080027using std::string;
Ben Chan02f7c1d2014-10-18 15:18:02 -070028using std::unique_ptr;
Alex Deymo41a75a72014-04-15 15:36:22 -070029using testing::Return;
30using testing::StrictMock;
31using testing::_;
Alex Deymo23949d42014-02-05 15:20:59 -080032
Gilad Arnoldfb794f42014-07-01 15:36:31 -070033namespace chromeos_update_manager {
34
Alex Deymo53556ec2014-03-17 10:05:57 -070035namespace {
36
37void DoNothing() {}
38
39// Sets the value of the passed pointer to true.
40void SetTrue(bool* value) {
41 *value = true;
42}
43
44bool GetBoolean(bool* value) {
45 return *value;
46}
47
Gilad Arnoldfb794f42014-07-01 15:36:31 -070048template<typename T>
49void ReadVar(scoped_refptr<EvaluationContext> ec, Variable<T>* var) {
50 ec->GetValue(var);
51}
Alex Deymo53556ec2014-03-17 10:05:57 -070052
Gilad Arnoldfb794f42014-07-01 15:36:31 -070053// Runs |evaluation|; if the value pointed by |count_p| is greater than zero,
54// decrement it and schedule a reevaluation; otherwise, writes true to |done_p|.
55void EvaluateRepeatedly(Closure evaluation, scoped_refptr<EvaluationContext> ec,
56 int* count_p, bool* done_p) {
57 evaluation.Run();
58
59 // Schedule reevaluation if needed.
60 if (*count_p > 0) {
61 Closure closure = Bind(EvaluateRepeatedly, evaluation, ec, count_p, done_p);
62 ASSERT_TRUE(ec->RunOnValueChangeOrTimeout(closure))
63 << "Failed to schedule reevaluation, count_p=" << *count_p;
64 (*count_p)--;
65 } else {
66 *done_p = true;
67 }
68}
69
70} // namespace
Alex Deymo23949d42014-02-05 15:20:59 -080071
Alex Deymo63784a52014-05-28 10:46:14 -070072class UmEvaluationContextTest : public ::testing::Test {
Alex Deymo23949d42014-02-05 15:20:59 -080073 protected:
74 virtual void SetUp() {
Gilad Arnolda65fced2014-07-23 09:01:31 -070075 // Apr 22, 2009 19:25:00 UTC (this is a random reference point).
76 fake_clock_.SetMonotonicTime(Time::FromTimeT(1240428300));
77 // Mar 2, 2006 1:23:45 UTC.
David Zeuthenc1490282014-04-29 16:25:03 -070078 fake_clock_.SetWallclockTime(Time::FromTimeT(1141262625));
Gilad Arnold83ffdda2014-08-08 13:30:31 -070079 eval_ctx_ = new EvaluationContext(
80 &fake_clock_, default_timeout_, default_timeout_,
Ben Chan02f7c1d2014-10-18 15:18:02 -070081 unique_ptr<base::Callback<void(EvaluationContext*)>>(nullptr));
Alex Deymo23949d42014-02-05 15:20:59 -080082 }
83
Alex Deymo53556ec2014-03-17 10:05:57 -070084 virtual void TearDown() {
Gilad Arnoldfb794f42014-07-01 15:36:31 -070085 // Ensure that the evaluation context did not leak and is actually being
86 // destroyed.
87 if (eval_ctx_) {
88 base::WeakPtr<EvaluationContext> eval_ctx_weak_alias =
89 eval_ctx_->weak_ptr_factory_.GetWeakPtr();
Alex Vakulenko88b591f2014-08-28 16:48:57 -070090 ASSERT_NE(nullptr, eval_ctx_weak_alias.get());
Gilad Arnoldfb794f42014-07-01 15:36:31 -070091 eval_ctx_ = nullptr;
Alex Vakulenko88b591f2014-08-28 16:48:57 -070092 EXPECT_EQ(nullptr, eval_ctx_weak_alias.get())
Gilad Arnoldfb794f42014-07-01 15:36:31 -070093 << "The evaluation context was not destroyed! This is likely a bug "
94 "in how the test was written, look for leaking handles to the EC, "
95 "possibly through closure objects.";
96 }
97
Alex Deymo53556ec2014-03-17 10:05:57 -070098 // Check that the evaluation context removed all the observers.
99 EXPECT_TRUE(fake_int_var_.observer_list_.empty());
100 EXPECT_TRUE(fake_async_var_.observer_list_.empty());
101 EXPECT_TRUE(fake_const_var_.observer_list_.empty());
102 EXPECT_TRUE(fake_poll_var_.observer_list_.empty());
103 }
104
Alex Deymof329b932014-10-30 01:37:48 -0700105 TimeDelta default_timeout_ = TimeDelta::FromSeconds(5);
Alex Deymo41a75a72014-04-15 15:36:22 -0700106
107 FakeClock fake_clock_;
Alex Deymo7b948f02014-03-10 17:01:10 -0700108 scoped_refptr<EvaluationContext> eval_ctx_;
Alex Deymo53556ec2014-03-17 10:05:57 -0700109
110 // FakeVariables used for testing the EvaluationContext. These are required
111 // here to prevent them from going away *before* the EvaluationContext under
112 // test does, which keeps a reference to them.
David Zeuthenc1490282014-04-29 16:25:03 -0700113 FakeVariable<bool> fail_var_ = {"fail_var", kVariableModePoll};
Alex Deymo53556ec2014-03-17 10:05:57 -0700114 FakeVariable<int> fake_int_var_ = {"fake_int", kVariableModePoll};
115 FakeVariable<string> fake_async_var_ = {"fake_async", kVariableModeAsync};
116 FakeVariable<string> fake_const_var_ = {"fake_const", kVariableModeConst};
117 FakeVariable<string> fake_poll_var_ = {"fake_poll",
118 TimeDelta::FromSeconds(1)};
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700119 StrictMock<MockVariable<string>> mock_var_async_ {
120 "mock_var_async", kVariableModeAsync};
121 StrictMock<MockVariable<string>> mock_var_poll_ {
122 "mock_var_poll", kVariableModePoll};
Alex Deymo23949d42014-02-05 15:20:59 -0800123};
124
Alex Deymo63784a52014-05-28 10:46:14 -0700125TEST_F(UmEvaluationContextTest, GetValueFails) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700126 // FakeVariable is initialized as returning null.
127 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&fake_int_var_));
Alex Deymo23949d42014-02-05 15:20:59 -0800128}
129
Alex Deymo63784a52014-05-28 10:46:14 -0700130TEST_F(UmEvaluationContextTest, GetValueFailsWithInvalidVar) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700131 EXPECT_EQ(nullptr, eval_ctx_->GetValue(static_cast<Variable<int>*>(nullptr)));
Alex Deymo23949d42014-02-05 15:20:59 -0800132}
133
Alex Deymo63784a52014-05-28 10:46:14 -0700134TEST_F(UmEvaluationContextTest, GetValueReturns) {
Alex Deymo23949d42014-02-05 15:20:59 -0800135 const int* p_fake_int;
136
137 fake_int_var_.reset(new int(42));
138 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700139 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800140 EXPECT_EQ(42, *p_fake_int);
141}
142
Alex Deymo63784a52014-05-28 10:46:14 -0700143TEST_F(UmEvaluationContextTest, GetValueCached) {
Alex Deymo23949d42014-02-05 15:20:59 -0800144 const int* p_fake_int;
145
146 fake_int_var_.reset(new int(42));
147 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
148
149 // Check that if the variable changes, the EvaluationContext keeps returning
150 // the cached value.
151 fake_int_var_.reset(new int(5));
152
153 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700154 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800155 EXPECT_EQ(42, *p_fake_int);
156}
157
Alex Deymo63784a52014-05-28 10:46:14 -0700158TEST_F(UmEvaluationContextTest, GetValueCachesNull) {
Alex Deymo23949d42014-02-05 15:20:59 -0800159 const int* p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700160 EXPECT_EQ(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800161
162 fake_int_var_.reset(new int(42));
Alex Deymocc0e5cf2014-04-23 20:20:11 -0700163 // A second attempt to read the variable should not work because this
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700164 // EvaluationContext already got a null value.
Alex Deymo23949d42014-02-05 15:20:59 -0800165 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700166 EXPECT_EQ(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800167}
168
Alex Deymo63784a52014-05-28 10:46:14 -0700169TEST_F(UmEvaluationContextTest, GetValueMixedTypes) {
Alex Deymo23949d42014-02-05 15:20:59 -0800170 const int* p_fake_int;
171 const string* p_fake_string;
172
173 fake_int_var_.reset(new int(42));
Alex Deymo53556ec2014-03-17 10:05:57 -0700174 fake_poll_var_.reset(new string("Hello world!"));
Alex Deymo23949d42014-02-05 15:20:59 -0800175 // Check that the EvaluationContext can handle multiple Variable types. This
176 // is mostly a compile-time check due to the template nature of this method.
177 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Deymo53556ec2014-03-17 10:05:57 -0700178 p_fake_string = eval_ctx_->GetValue(&fake_poll_var_);
Alex Deymo23949d42014-02-05 15:20:59 -0800179
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700180 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800181 EXPECT_EQ(42, *p_fake_int);
182
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700183 ASSERT_NE(nullptr, p_fake_string);
Alex Deymo23949d42014-02-05 15:20:59 -0800184 EXPECT_EQ("Hello world!", *p_fake_string);
185}
186
Alex Deymo53556ec2014-03-17 10:05:57 -0700187// Test that we don't schedule an event if there's no variable to wait for.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700188TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutWithoutVariables) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700189 fake_const_var_.reset(new string("Hello world!"));
190 EXPECT_EQ(*eval_ctx_->GetValue(&fake_const_var_), "Hello world!");
191
192 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
193}
194
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700195// Test that reevaluation occurs when an async variable it depends on changes.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700196TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutWithVariables) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700197 fake_async_var_.reset(new string("Async value"));
198 eval_ctx_->GetValue(&fake_async_var_);
199
200 bool value = false;
201 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
202 // Check that the scheduled callback isn't run until we signal a ValueChaged.
203 RunGMainLoopMaxIterations(100);
204 EXPECT_FALSE(value);
205
206 fake_async_var_.NotifyValueChanged();
207 EXPECT_FALSE(value);
208 // Ensure that the scheduled callback isn't run until we are back on the main
209 // loop.
210 RunGMainLoopMaxIterations(100);
211 EXPECT_TRUE(value);
212}
213
214// Test that we don't re-schedule the events if we are attending one.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700215TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutCalledTwice) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700216 fake_async_var_.reset(new string("Async value"));
217 eval_ctx_->GetValue(&fake_async_var_);
218
219 bool value = false;
220 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
221 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
222
223 // The scheduled event should still work.
224 fake_async_var_.NotifyValueChanged();
225 RunGMainLoopMaxIterations(100);
226 EXPECT_TRUE(value);
227}
228
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700229// Test that reevaluation occurs when a polling timeout fires.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700230TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutRunsFromTimeout) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700231 fake_poll_var_.reset(new string("Polled value"));
232 eval_ctx_->GetValue(&fake_poll_var_);
233
234 bool value = false;
235 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
236 // Check that the scheduled callback isn't run until the timeout occurs.
237 RunGMainLoopMaxIterations(10);
238 EXPECT_FALSE(value);
239 RunGMainLoopUntil(10000, Bind(&GetBoolean, &value));
240 EXPECT_TRUE(value);
241}
242
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700243// Test that callback is called when evaluation context expires, and that it
Gilad Arnoldfd45a732014-08-07 15:53:46 -0700244// cannot be used again unless the expiration deadline is reset.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700245TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutExpires) {
246 fake_async_var_.reset(new string("Async value"));
247 eval_ctx_->GetValue(&fake_async_var_);
248
249 bool value = false;
250 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
251 // Check that the scheduled callback isn't run until the timeout occurs.
252 RunGMainLoopMaxIterations(10);
253 EXPECT_FALSE(value);
254 RunGMainLoopUntil(10000, Bind(&GetBoolean, &value));
255 EXPECT_TRUE(value);
256
257 // Ensure that we cannot reschedule an evaluation.
258 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
Gilad Arnoldfd45a732014-08-07 15:53:46 -0700259
260 // Ensure that we can reschedule an evaluation after resetting expiration.
261 eval_ctx_->ResetExpiration();
262 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700263}
264
265// Test that we clear the events when destroying the EvaluationContext.
266TEST_F(UmEvaluationContextTest, RemoveObserversAndTimeoutTest) {
267 fake_async_var_.reset(new string("Async value"));
268 eval_ctx_->GetValue(&fake_async_var_);
269
270 bool value = false;
271 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
272 eval_ctx_ = nullptr;
273
274 // This should not trigger the callback since the EvaluationContext waiting
275 // for it is gone, and it should have remove all its observers.
276 fake_async_var_.NotifyValueChanged();
277 RunGMainLoopMaxIterations(100);
278 EXPECT_FALSE(value);
279}
280
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700281// Scheduling two reevaluations from the callback should succeed.
282TEST_F(UmEvaluationContextTest,
283 RunOnValueChangeOrTimeoutReevaluatesRepeatedly) {
284 fake_poll_var_.reset(new string("Polled value"));
285 Closure evaluation = Bind(ReadVar<string>, eval_ctx_, &fake_poll_var_);
286 int num_reevaluations = 2;
287 bool done = false;
288
289 // Run the evaluation once.
290 evaluation.Run();
291
292 // Schedule repeated reevaluations.
293 Closure closure = Bind(EvaluateRepeatedly, evaluation, eval_ctx_,
294 &num_reevaluations, &done);
295 ASSERT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(closure));
296 RunGMainLoopUntil(10000, Bind(&GetBoolean, &done));
297 EXPECT_EQ(0, num_reevaluations);
298}
299
Alex Deymodb799532014-03-21 13:00:00 -0700300// Test that we can delete the EvaluationContext while having pending events.
Alex Deymo63784a52014-05-28 10:46:14 -0700301TEST_F(UmEvaluationContextTest, ObjectDeletedWithPendingEventsTest) {
Alex Deymodb799532014-03-21 13:00:00 -0700302 fake_async_var_.reset(new string("Async value"));
303 fake_poll_var_.reset(new string("Polled value"));
304 eval_ctx_->GetValue(&fake_async_var_);
305 eval_ctx_->GetValue(&fake_poll_var_);
306 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
307 // TearDown() checks for leaked observers on this async_variable, which means
308 // that our object is still alive after removing its reference.
309}
310
311// Test that timed events fired after removal of the EvaluationContext don't
312// crash.
Alex Deymo63784a52014-05-28 10:46:14 -0700313TEST_F(UmEvaluationContextTest, TimeoutEventAfterDeleteTest) {
Alex Deymodb799532014-03-21 13:00:00 -0700314 FakeVariable<string> fake_short_poll_var = {"fake_short_poll", TimeDelta()};
315 fake_short_poll_var.reset(new string("Polled value"));
316 eval_ctx_->GetValue(&fake_short_poll_var);
317 bool value = false;
318 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
319 // Remove the last reference to the EvaluationContext and run the loop for
320 // 1 second to give time to the main loop to trigger the timeout Event (of 0
321 // seconds). Our callback should not be called because the EvaluationContext
322 // was removed before the timeout event is attended.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700323 eval_ctx_ = nullptr;
Alex Deymodb799532014-03-21 13:00:00 -0700324 RunGMainLoopUntil(1000, Bind(&GetBoolean, &value));
325 EXPECT_FALSE(value);
326}
327
Alex Deymo63784a52014-05-28 10:46:14 -0700328TEST_F(UmEvaluationContextTest, DefaultTimeout) {
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700329 // Test that the evaluation timeout calculation uses the default timeout on
330 // setup.
Alex Deymo41a75a72014-04-15 15:36:22 -0700331 EXPECT_CALL(mock_var_async_, GetValue(default_timeout_, _))
332 .WillOnce(Return(nullptr));
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700333 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&mock_var_async_));
Alex Deymo41a75a72014-04-15 15:36:22 -0700334}
335
Alex Deymo63784a52014-05-28 10:46:14 -0700336TEST_F(UmEvaluationContextTest, TimeoutUpdatesWithMonotonicTime) {
Alex Deymo41a75a72014-04-15 15:36:22 -0700337 fake_clock_.SetMonotonicTime(
338 fake_clock_.GetMonotonicTime() + TimeDelta::FromSeconds(1));
339
340 TimeDelta timeout = default_timeout_ - TimeDelta::FromSeconds(1);
341
342 EXPECT_CALL(mock_var_async_, GetValue(timeout, _))
343 .WillOnce(Return(nullptr));
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700344 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&mock_var_async_));
Alex Deymo41a75a72014-04-15 15:36:22 -0700345}
346
Gilad Arnolda65fced2014-07-23 09:01:31 -0700347TEST_F(UmEvaluationContextTest, ResetEvaluationResetsTimesWallclock) {
Alex Deymof329b932014-10-30 01:37:48 -0700348 Time cur_time = fake_clock_.GetWallclockTime();
Alex Deymo41a75a72014-04-15 15:36:22 -0700349 // Advance the time on the clock but don't call ResetEvaluation yet.
350 fake_clock_.SetWallclockTime(cur_time + TimeDelta::FromSeconds(4));
351
Gilad Arnolda65fced2014-07-23 09:01:31 -0700352 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
353 cur_time - TimeDelta::FromSeconds(1)));
354 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time));
355 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
356 cur_time + TimeDelta::FromSeconds(1)));
Alex Deymo41a75a72014-04-15 15:36:22 -0700357 // Call ResetEvaluation now, which should use the new evaluation time.
358 eval_ctx_->ResetEvaluation();
359
360 cur_time = fake_clock_.GetWallclockTime();
Gilad Arnolda65fced2014-07-23 09:01:31 -0700361 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
362 cur_time - TimeDelta::FromSeconds(1)));
363 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time));
364 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
365 cur_time + TimeDelta::FromSeconds(1)));
Alex Deymo41a75a72014-04-15 15:36:22 -0700366}
367
Gilad Arnolda65fced2014-07-23 09:01:31 -0700368TEST_F(UmEvaluationContextTest, ResetEvaluationResetsTimesMonotonic) {
Alex Deymof329b932014-10-30 01:37:48 -0700369 Time cur_time = fake_clock_.GetMonotonicTime();
Gilad Arnolda65fced2014-07-23 09:01:31 -0700370 // Advance the time on the clock but don't call ResetEvaluation yet.
371 fake_clock_.SetMonotonicTime(cur_time + TimeDelta::FromSeconds(4));
372
373 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
374 cur_time - TimeDelta::FromSeconds(1)));
375 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time));
376 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
377 cur_time + TimeDelta::FromSeconds(1)));
378 // Call ResetEvaluation now, which should use the new evaluation time.
379 eval_ctx_->ResetEvaluation();
380
381 cur_time = fake_clock_.GetMonotonicTime();
382 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
383 cur_time - TimeDelta::FromSeconds(1)));
384 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time));
385 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
386 cur_time + TimeDelta::FromSeconds(1)));
387}
388
389TEST_F(UmEvaluationContextTest,
390 IsWallclockTimeGreaterThanSignalsTriggerReevaluation) {
391 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
Alex Deymo41a75a72014-04-15 15:36:22 -0700392 fake_clock_.GetWallclockTime() + TimeDelta::FromSeconds(1)));
393
Gilad Arnolda65fced2014-07-23 09:01:31 -0700394 // The "false" from IsWallclockTimeGreaterThan means that's not that timestamp
395 // yet, so this should schedule a callback for when that happens.
Alex Deymo41a75a72014-04-15 15:36:22 -0700396 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
397}
398
Gilad Arnolda65fced2014-07-23 09:01:31 -0700399TEST_F(UmEvaluationContextTest,
400 IsMonotonicTimeGreaterThanSignalsTriggerReevaluation) {
401 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
402 fake_clock_.GetMonotonicTime() + TimeDelta::FromSeconds(1)));
403
404 // The "false" from IsMonotonicTimeGreaterThan means that's not that timestamp
405 // yet, so this should schedule a callback for when that happens.
406 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
407}
408
409TEST_F(UmEvaluationContextTest,
410 IsWallclockTimeGreaterThanDoesntRecordPastTimestamps) {
411 // IsWallclockTimeGreaterThan() should ignore timestamps on the past for
412 // reevaluation.
413 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
Alex Deymo41a75a72014-04-15 15:36:22 -0700414 fake_clock_.GetWallclockTime() - TimeDelta::FromSeconds(20)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700415 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
Alex Deymo41a75a72014-04-15 15:36:22 -0700416 fake_clock_.GetWallclockTime() - TimeDelta::FromSeconds(1)));
417
418 // Callback should not be scheduled.
419 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
420}
421
Gilad Arnolda65fced2014-07-23 09:01:31 -0700422TEST_F(UmEvaluationContextTest,
423 IsMonotonicTimeGreaterThanDoesntRecordPastTimestamps) {
424 // IsMonotonicTimeGreaterThan() should ignore timestamps on the past for
425 // reevaluation.
426 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
427 fake_clock_.GetMonotonicTime() - TimeDelta::FromSeconds(20)));
428 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
429 fake_clock_.GetMonotonicTime() - TimeDelta::FromSeconds(1)));
430
431 // Callback should not be scheduled.
432 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
433}
434
Alex Deymo63784a52014-05-28 10:46:14 -0700435TEST_F(UmEvaluationContextTest, DumpContext) {
David Zeuthenc1490282014-04-29 16:25:03 -0700436 // |fail_var_| yield "(no value)" since it is unset.
437 eval_ctx_->GetValue(&fail_var_);
438
439 // Check that this is included.
440 fake_int_var_.reset(new int(42));
441 eval_ctx_->GetValue(&fake_int_var_);
442
443 // Check that double-quotes are escaped properly.
444 fake_poll_var_.reset(new string("Hello \"world\"!"));
445 eval_ctx_->GetValue(&fake_poll_var_);
446
447 // Note that the variables are printed in alphabetical order. Also
Gilad Arnolda65fced2014-07-23 09:01:31 -0700448 // see UmEvaluationContextText::SetUp() where the values used for
449 // |evaluation_start_{monotonic,wallclock| are set.
David Zeuthenc1490282014-04-29 16:25:03 -0700450 EXPECT_EQ("{\n"
Gilad Arnolda65fced2014-07-23 09:01:31 -0700451 " \"evaluation_start_monotonic\": \"4/22/2009 19:25:00 GMT\",\n"
452 " \"evaluation_start_wallclock\": \"3/2/2006 1:23:45 GMT\",\n"
David Zeuthenc1490282014-04-29 16:25:03 -0700453 " \"variables\": {\n"
454 " \"fail_var\": \"(no value)\",\n"
455 " \"fake_int\": \"42\",\n"
456 " \"fake_poll\": \"Hello \\\"world\\\"!\"\n"
457 " }\n"
Gilad Arnold6e5ab5c2014-06-23 15:13:56 -0700458 "}",
David Zeuthenc1490282014-04-29 16:25:03 -0700459 eval_ctx_->DumpContext());
460}
461
Alex Deymo63784a52014-05-28 10:46:14 -0700462} // namespace chromeos_update_manager