blob: 0ba9594409926febcb43f3a98cd49091ca4dc356 [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 Deymo509dd532015-06-10 14:11:05 -070011#include <chromeos/message_loops/fake_message_loop.h>
12#include <chromeos/message_loops/message_loop_utils.h>
Alex Deymo53556ec2014-03-17 10:05:57 -070013#include <gtest/gtest.h>
14
Alex Deymo41a75a72014-04-15 15:36:22 -070015#include "update_engine/fake_clock.h"
Alex Deymo63784a52014-05-28 10:46:14 -070016#include "update_engine/update_manager/fake_variable.h"
17#include "update_engine/update_manager/generic_variables.h"
18#include "update_engine/update_manager/mock_variable.h"
19#include "update_engine/update_manager/umtest_utils.h"
Alex Deymo23949d42014-02-05 15:20:59 -080020
Alex Deymo53556ec2014-03-17 10:05:57 -070021using base::Bind;
Gilad Arnoldfb794f42014-07-01 15:36:31 -070022using base::Closure;
Alex Deymo41a75a72014-04-15 15:36:22 -070023using base::Time;
Alex Deymo53556ec2014-03-17 10:05:57 -070024using base::TimeDelta;
Alex Deymo509dd532015-06-10 14:11:05 -070025using chromeos::MessageLoop;
26using chromeos::MessageLoopRunMaxIterations;
27using chromeos::MessageLoopRunUntil;
Alex Deymo41a75a72014-04-15 15:36:22 -070028using chromeos_update_engine::FakeClock;
Alex Deymo23949d42014-02-05 15:20:59 -080029using std::string;
Ben Chan02f7c1d2014-10-18 15:18:02 -070030using std::unique_ptr;
Alex Deymo41a75a72014-04-15 15:36:22 -070031using testing::Return;
32using testing::StrictMock;
33using testing::_;
Alex Deymo23949d42014-02-05 15:20:59 -080034
Gilad Arnoldfb794f42014-07-01 15:36:31 -070035namespace chromeos_update_manager {
36
Alex Deymo53556ec2014-03-17 10:05:57 -070037namespace {
38
39void DoNothing() {}
40
41// Sets the value of the passed pointer to true.
42void SetTrue(bool* value) {
43 *value = true;
44}
45
46bool GetBoolean(bool* value) {
47 return *value;
48}
49
Gilad Arnoldfb794f42014-07-01 15:36:31 -070050template<typename T>
51void ReadVar(scoped_refptr<EvaluationContext> ec, Variable<T>* var) {
52 ec->GetValue(var);
53}
Alex Deymo53556ec2014-03-17 10:05:57 -070054
Gilad Arnoldfb794f42014-07-01 15:36:31 -070055// Runs |evaluation|; if the value pointed by |count_p| is greater than zero,
56// decrement it and schedule a reevaluation; otherwise, writes true to |done_p|.
57void EvaluateRepeatedly(Closure evaluation, scoped_refptr<EvaluationContext> ec,
58 int* count_p, bool* done_p) {
59 evaluation.Run();
60
61 // Schedule reevaluation if needed.
62 if (*count_p > 0) {
63 Closure closure = Bind(EvaluateRepeatedly, evaluation, ec, count_p, done_p);
64 ASSERT_TRUE(ec->RunOnValueChangeOrTimeout(closure))
65 << "Failed to schedule reevaluation, count_p=" << *count_p;
66 (*count_p)--;
67 } else {
68 *done_p = true;
69 }
70}
71
72} // namespace
Alex Deymo23949d42014-02-05 15:20:59 -080073
Alex Deymo63784a52014-05-28 10:46:14 -070074class UmEvaluationContextTest : public ::testing::Test {
Alex Deymo23949d42014-02-05 15:20:59 -080075 protected:
Alex Deymo610277e2014-11-11 21:18:11 -080076 void SetUp() override {
Alex Deymo509dd532015-06-10 14:11:05 -070077 loop_.SetAsCurrent();
Gilad Arnolda65fced2014-07-23 09:01:31 -070078 // Apr 22, 2009 19:25:00 UTC (this is a random reference point).
79 fake_clock_.SetMonotonicTime(Time::FromTimeT(1240428300));
80 // Mar 2, 2006 1:23:45 UTC.
David Zeuthenc1490282014-04-29 16:25:03 -070081 fake_clock_.SetWallclockTime(Time::FromTimeT(1141262625));
Gilad Arnold83ffdda2014-08-08 13:30:31 -070082 eval_ctx_ = new EvaluationContext(
83 &fake_clock_, default_timeout_, default_timeout_,
Ben Chan02f7c1d2014-10-18 15:18:02 -070084 unique_ptr<base::Callback<void(EvaluationContext*)>>(nullptr));
Alex Deymo23949d42014-02-05 15:20:59 -080085 }
86
Alex Deymo610277e2014-11-11 21:18:11 -080087 void TearDown() override {
Gilad Arnoldfb794f42014-07-01 15:36:31 -070088 // Ensure that the evaluation context did not leak and is actually being
89 // destroyed.
90 if (eval_ctx_) {
91 base::WeakPtr<EvaluationContext> eval_ctx_weak_alias =
92 eval_ctx_->weak_ptr_factory_.GetWeakPtr();
Alex Vakulenko88b591f2014-08-28 16:48:57 -070093 ASSERT_NE(nullptr, eval_ctx_weak_alias.get());
Gilad Arnoldfb794f42014-07-01 15:36:31 -070094 eval_ctx_ = nullptr;
Alex Vakulenko88b591f2014-08-28 16:48:57 -070095 EXPECT_EQ(nullptr, eval_ctx_weak_alias.get())
Gilad Arnoldfb794f42014-07-01 15:36:31 -070096 << "The evaluation context was not destroyed! This is likely a bug "
97 "in how the test was written, look for leaking handles to the EC, "
98 "possibly through closure objects.";
99 }
100
Alex Deymo53556ec2014-03-17 10:05:57 -0700101 // Check that the evaluation context removed all the observers.
102 EXPECT_TRUE(fake_int_var_.observer_list_.empty());
103 EXPECT_TRUE(fake_async_var_.observer_list_.empty());
104 EXPECT_TRUE(fake_const_var_.observer_list_.empty());
105 EXPECT_TRUE(fake_poll_var_.observer_list_.empty());
Alex Deymo509dd532015-06-10 14:11:05 -0700106
107 EXPECT_FALSE(loop_.PendingTasks());
Alex Deymo53556ec2014-03-17 10:05:57 -0700108 }
109
Alex Deymof329b932014-10-30 01:37:48 -0700110 TimeDelta default_timeout_ = TimeDelta::FromSeconds(5);
Alex Deymo41a75a72014-04-15 15:36:22 -0700111
Alex Deymo509dd532015-06-10 14:11:05 -0700112 chromeos::FakeMessageLoop loop_{nullptr};
Alex Deymo41a75a72014-04-15 15:36:22 -0700113 FakeClock fake_clock_;
Alex Deymo7b948f02014-03-10 17:01:10 -0700114 scoped_refptr<EvaluationContext> eval_ctx_;
Alex Deymo53556ec2014-03-17 10:05:57 -0700115
116 // FakeVariables used for testing the EvaluationContext. These are required
117 // here to prevent them from going away *before* the EvaluationContext under
118 // test does, which keeps a reference to them.
David Zeuthenc1490282014-04-29 16:25:03 -0700119 FakeVariable<bool> fail_var_ = {"fail_var", kVariableModePoll};
Alex Deymo53556ec2014-03-17 10:05:57 -0700120 FakeVariable<int> fake_int_var_ = {"fake_int", kVariableModePoll};
121 FakeVariable<string> fake_async_var_ = {"fake_async", kVariableModeAsync};
122 FakeVariable<string> fake_const_var_ = {"fake_const", kVariableModeConst};
123 FakeVariable<string> fake_poll_var_ = {"fake_poll",
124 TimeDelta::FromSeconds(1)};
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700125 StrictMock<MockVariable<string>> mock_var_async_ {
126 "mock_var_async", kVariableModeAsync};
127 StrictMock<MockVariable<string>> mock_var_poll_ {
128 "mock_var_poll", kVariableModePoll};
Alex Deymo23949d42014-02-05 15:20:59 -0800129};
130
Alex Deymo63784a52014-05-28 10:46:14 -0700131TEST_F(UmEvaluationContextTest, GetValueFails) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700132 // FakeVariable is initialized as returning null.
133 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&fake_int_var_));
Alex Deymo23949d42014-02-05 15:20:59 -0800134}
135
Alex Deymo63784a52014-05-28 10:46:14 -0700136TEST_F(UmEvaluationContextTest, GetValueFailsWithInvalidVar) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700137 EXPECT_EQ(nullptr, eval_ctx_->GetValue(static_cast<Variable<int>*>(nullptr)));
Alex Deymo23949d42014-02-05 15:20:59 -0800138}
139
Alex Deymo63784a52014-05-28 10:46:14 -0700140TEST_F(UmEvaluationContextTest, GetValueReturns) {
Alex Deymo23949d42014-02-05 15:20:59 -0800141 const int* p_fake_int;
142
143 fake_int_var_.reset(new int(42));
144 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700145 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800146 EXPECT_EQ(42, *p_fake_int);
147}
148
Alex Deymo63784a52014-05-28 10:46:14 -0700149TEST_F(UmEvaluationContextTest, GetValueCached) {
Alex Deymo23949d42014-02-05 15:20:59 -0800150 const int* p_fake_int;
151
152 fake_int_var_.reset(new int(42));
153 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
154
155 // Check that if the variable changes, the EvaluationContext keeps returning
156 // the cached value.
157 fake_int_var_.reset(new int(5));
158
159 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700160 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800161 EXPECT_EQ(42, *p_fake_int);
162}
163
Alex Deymo63784a52014-05-28 10:46:14 -0700164TEST_F(UmEvaluationContextTest, GetValueCachesNull) {
Alex Deymo23949d42014-02-05 15:20:59 -0800165 const int* 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 fake_int_var_.reset(new int(42));
Alex Deymocc0e5cf2014-04-23 20:20:11 -0700169 // A second attempt to read the variable should not work because this
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700170 // EvaluationContext already got a null value.
Alex Deymo23949d42014-02-05 15:20:59 -0800171 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700172 EXPECT_EQ(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800173}
174
Alex Deymo63784a52014-05-28 10:46:14 -0700175TEST_F(UmEvaluationContextTest, GetValueMixedTypes) {
Alex Deymo23949d42014-02-05 15:20:59 -0800176 const int* p_fake_int;
177 const string* p_fake_string;
178
179 fake_int_var_.reset(new int(42));
Alex Deymo53556ec2014-03-17 10:05:57 -0700180 fake_poll_var_.reset(new string("Hello world!"));
Alex Deymo23949d42014-02-05 15:20:59 -0800181 // Check that the EvaluationContext can handle multiple Variable types. This
182 // is mostly a compile-time check due to the template nature of this method.
183 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Deymo53556ec2014-03-17 10:05:57 -0700184 p_fake_string = eval_ctx_->GetValue(&fake_poll_var_);
Alex Deymo23949d42014-02-05 15:20:59 -0800185
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700186 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800187 EXPECT_EQ(42, *p_fake_int);
188
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700189 ASSERT_NE(nullptr, p_fake_string);
Alex Deymo23949d42014-02-05 15:20:59 -0800190 EXPECT_EQ("Hello world!", *p_fake_string);
191}
192
Alex Deymo53556ec2014-03-17 10:05:57 -0700193// Test that we don't schedule an event if there's no variable to wait for.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700194TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutWithoutVariables) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700195 fake_const_var_.reset(new string("Hello world!"));
196 EXPECT_EQ(*eval_ctx_->GetValue(&fake_const_var_), "Hello world!");
197
198 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
199}
200
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700201// Test that reevaluation occurs when an async variable it depends on changes.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700202TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutWithVariables) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700203 fake_async_var_.reset(new string("Async value"));
204 eval_ctx_->GetValue(&fake_async_var_);
205
206 bool value = false;
207 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
208 // Check that the scheduled callback isn't run until we signal a ValueChaged.
Alex Deymo509dd532015-06-10 14:11:05 -0700209 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
Alex Deymo53556ec2014-03-17 10:05:57 -0700210 EXPECT_FALSE(value);
211
212 fake_async_var_.NotifyValueChanged();
213 EXPECT_FALSE(value);
214 // Ensure that the scheduled callback isn't run until we are back on the main
215 // loop.
Alex Deymo509dd532015-06-10 14:11:05 -0700216 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
Alex Deymo53556ec2014-03-17 10:05:57 -0700217 EXPECT_TRUE(value);
218}
219
220// Test that we don't re-schedule the events if we are attending one.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700221TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutCalledTwice) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700222 fake_async_var_.reset(new string("Async value"));
223 eval_ctx_->GetValue(&fake_async_var_);
224
225 bool value = false;
226 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
227 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
228
229 // The scheduled event should still work.
230 fake_async_var_.NotifyValueChanged();
Alex Deymo509dd532015-06-10 14:11:05 -0700231 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
Alex Deymo53556ec2014-03-17 10:05:57 -0700232 EXPECT_TRUE(value);
233}
234
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700235// Test that reevaluation occurs when a polling timeout fires.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700236TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutRunsFromTimeout) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700237 fake_poll_var_.reset(new string("Polled value"));
238 eval_ctx_->GetValue(&fake_poll_var_);
239
240 bool value = false;
241 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
242 // Check that the scheduled callback isn't run until the timeout occurs.
Alex Deymo509dd532015-06-10 14:11:05 -0700243 MessageLoopRunMaxIterations(MessageLoop::current(), 10);
Alex Deymo53556ec2014-03-17 10:05:57 -0700244 EXPECT_FALSE(value);
Alex Deymo509dd532015-06-10 14:11:05 -0700245 MessageLoopRunUntil(MessageLoop::current(),
246 TimeDelta::FromSeconds(10),
247 Bind(&GetBoolean, &value));
Alex Deymo53556ec2014-03-17 10:05:57 -0700248 EXPECT_TRUE(value);
249}
250
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700251// Test that callback is called when evaluation context expires, and that it
Gilad Arnoldfd45a732014-08-07 15:53:46 -0700252// cannot be used again unless the expiration deadline is reset.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700253TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutExpires) {
254 fake_async_var_.reset(new string("Async value"));
255 eval_ctx_->GetValue(&fake_async_var_);
256
257 bool value = false;
258 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
259 // Check that the scheduled callback isn't run until the timeout occurs.
Alex Deymo509dd532015-06-10 14:11:05 -0700260 MessageLoopRunMaxIterations(MessageLoop::current(), 10);
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700261 EXPECT_FALSE(value);
Alex Deymo509dd532015-06-10 14:11:05 -0700262 MessageLoopRunUntil(MessageLoop::current(),
263 TimeDelta::FromSeconds(10),
264 Bind(&GetBoolean, &value));
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700265 EXPECT_TRUE(value);
266
267 // Ensure that we cannot reschedule an evaluation.
268 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
Gilad Arnoldfd45a732014-08-07 15:53:46 -0700269
270 // Ensure that we can reschedule an evaluation after resetting expiration.
271 eval_ctx_->ResetExpiration();
272 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700273}
274
275// Test that we clear the events when destroying the EvaluationContext.
276TEST_F(UmEvaluationContextTest, RemoveObserversAndTimeoutTest) {
277 fake_async_var_.reset(new string("Async value"));
278 eval_ctx_->GetValue(&fake_async_var_);
279
280 bool value = false;
281 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
282 eval_ctx_ = nullptr;
283
284 // This should not trigger the callback since the EvaluationContext waiting
285 // for it is gone, and it should have remove all its observers.
286 fake_async_var_.NotifyValueChanged();
Alex Deymo509dd532015-06-10 14:11:05 -0700287 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700288 EXPECT_FALSE(value);
289}
290
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700291// Scheduling two reevaluations from the callback should succeed.
292TEST_F(UmEvaluationContextTest,
293 RunOnValueChangeOrTimeoutReevaluatesRepeatedly) {
294 fake_poll_var_.reset(new string("Polled value"));
295 Closure evaluation = Bind(ReadVar<string>, eval_ctx_, &fake_poll_var_);
296 int num_reevaluations = 2;
297 bool done = false;
298
299 // Run the evaluation once.
300 evaluation.Run();
301
302 // Schedule repeated reevaluations.
303 Closure closure = Bind(EvaluateRepeatedly, evaluation, eval_ctx_,
304 &num_reevaluations, &done);
305 ASSERT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(closure));
Alex Deymo509dd532015-06-10 14:11:05 -0700306 MessageLoopRunUntil(MessageLoop::current(),
307 TimeDelta::FromSeconds(10),
308 Bind(&GetBoolean, &done));
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700309 EXPECT_EQ(0, num_reevaluations);
310}
311
Alex Deymodb799532014-03-21 13:00:00 -0700312// Test that we can delete the EvaluationContext while having pending events.
Alex Deymo63784a52014-05-28 10:46:14 -0700313TEST_F(UmEvaluationContextTest, ObjectDeletedWithPendingEventsTest) {
Alex Deymodb799532014-03-21 13:00:00 -0700314 fake_async_var_.reset(new string("Async value"));
315 fake_poll_var_.reset(new string("Polled value"));
316 eval_ctx_->GetValue(&fake_async_var_);
317 eval_ctx_->GetValue(&fake_poll_var_);
318 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
319 // TearDown() checks for leaked observers on this async_variable, which means
320 // that our object is still alive after removing its reference.
321}
322
323// Test that timed events fired after removal of the EvaluationContext don't
324// crash.
Alex Deymo63784a52014-05-28 10:46:14 -0700325TEST_F(UmEvaluationContextTest, TimeoutEventAfterDeleteTest) {
Alex Deymodb799532014-03-21 13:00:00 -0700326 FakeVariable<string> fake_short_poll_var = {"fake_short_poll", TimeDelta()};
327 fake_short_poll_var.reset(new string("Polled value"));
328 eval_ctx_->GetValue(&fake_short_poll_var);
329 bool value = false;
330 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
331 // Remove the last reference to the EvaluationContext and run the loop for
332 // 1 second to give time to the main loop to trigger the timeout Event (of 0
333 // seconds). Our callback should not be called because the EvaluationContext
334 // was removed before the timeout event is attended.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700335 eval_ctx_ = nullptr;
Alex Deymo509dd532015-06-10 14:11:05 -0700336 MessageLoopRunUntil(MessageLoop::current(),
337 TimeDelta::FromSeconds(10),
338 Bind(&GetBoolean, &value));
Alex Deymodb799532014-03-21 13:00:00 -0700339 EXPECT_FALSE(value);
340}
341
Alex Deymo63784a52014-05-28 10:46:14 -0700342TEST_F(UmEvaluationContextTest, DefaultTimeout) {
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700343 // Test that the evaluation timeout calculation uses the default timeout on
344 // setup.
Alex Deymo41a75a72014-04-15 15:36:22 -0700345 EXPECT_CALL(mock_var_async_, GetValue(default_timeout_, _))
346 .WillOnce(Return(nullptr));
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700347 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&mock_var_async_));
Alex Deymo41a75a72014-04-15 15:36:22 -0700348}
349
Alex Deymo63784a52014-05-28 10:46:14 -0700350TEST_F(UmEvaluationContextTest, TimeoutUpdatesWithMonotonicTime) {
Alex Deymo41a75a72014-04-15 15:36:22 -0700351 fake_clock_.SetMonotonicTime(
352 fake_clock_.GetMonotonicTime() + TimeDelta::FromSeconds(1));
353
354 TimeDelta timeout = default_timeout_ - TimeDelta::FromSeconds(1);
355
356 EXPECT_CALL(mock_var_async_, GetValue(timeout, _))
357 .WillOnce(Return(nullptr));
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700358 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&mock_var_async_));
Alex Deymo41a75a72014-04-15 15:36:22 -0700359}
360
Gilad Arnolda65fced2014-07-23 09:01:31 -0700361TEST_F(UmEvaluationContextTest, ResetEvaluationResetsTimesWallclock) {
Alex Deymof329b932014-10-30 01:37:48 -0700362 Time cur_time = fake_clock_.GetWallclockTime();
Alex Deymo41a75a72014-04-15 15:36:22 -0700363 // Advance the time on the clock but don't call ResetEvaluation yet.
364 fake_clock_.SetWallclockTime(cur_time + TimeDelta::FromSeconds(4));
365
Gilad Arnolda65fced2014-07-23 09:01:31 -0700366 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
367 cur_time - TimeDelta::FromSeconds(1)));
368 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time));
369 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
370 cur_time + TimeDelta::FromSeconds(1)));
Alex Deymo41a75a72014-04-15 15:36:22 -0700371 // Call ResetEvaluation now, which should use the new evaluation time.
372 eval_ctx_->ResetEvaluation();
373
374 cur_time = fake_clock_.GetWallclockTime();
Gilad Arnolda65fced2014-07-23 09:01:31 -0700375 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
376 cur_time - TimeDelta::FromSeconds(1)));
377 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time));
378 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
379 cur_time + TimeDelta::FromSeconds(1)));
Alex Deymo41a75a72014-04-15 15:36:22 -0700380}
381
Gilad Arnolda65fced2014-07-23 09:01:31 -0700382TEST_F(UmEvaluationContextTest, ResetEvaluationResetsTimesMonotonic) {
Alex Deymof329b932014-10-30 01:37:48 -0700383 Time cur_time = fake_clock_.GetMonotonicTime();
Gilad Arnolda65fced2014-07-23 09:01:31 -0700384 // Advance the time on the clock but don't call ResetEvaluation yet.
385 fake_clock_.SetMonotonicTime(cur_time + TimeDelta::FromSeconds(4));
386
387 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
388 cur_time - TimeDelta::FromSeconds(1)));
389 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time));
390 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
391 cur_time + TimeDelta::FromSeconds(1)));
392 // Call ResetEvaluation now, which should use the new evaluation time.
393 eval_ctx_->ResetEvaluation();
394
395 cur_time = fake_clock_.GetMonotonicTime();
396 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
397 cur_time - TimeDelta::FromSeconds(1)));
398 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time));
399 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
400 cur_time + TimeDelta::FromSeconds(1)));
401}
402
403TEST_F(UmEvaluationContextTest,
404 IsWallclockTimeGreaterThanSignalsTriggerReevaluation) {
405 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
Alex Deymo41a75a72014-04-15 15:36:22 -0700406 fake_clock_.GetWallclockTime() + TimeDelta::FromSeconds(1)));
407
Gilad Arnolda65fced2014-07-23 09:01:31 -0700408 // The "false" from IsWallclockTimeGreaterThan means that's not that timestamp
409 // yet, so this should schedule a callback for when that happens.
Alex Deymo41a75a72014-04-15 15:36:22 -0700410 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
411}
412
Gilad Arnolda65fced2014-07-23 09:01:31 -0700413TEST_F(UmEvaluationContextTest,
414 IsMonotonicTimeGreaterThanSignalsTriggerReevaluation) {
415 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
416 fake_clock_.GetMonotonicTime() + TimeDelta::FromSeconds(1)));
417
418 // The "false" from IsMonotonicTimeGreaterThan means that's not that timestamp
419 // yet, so this should schedule a callback for when that happens.
420 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
421}
422
423TEST_F(UmEvaluationContextTest,
424 IsWallclockTimeGreaterThanDoesntRecordPastTimestamps) {
425 // IsWallclockTimeGreaterThan() should ignore timestamps on the past for
426 // reevaluation.
427 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
Alex Deymo41a75a72014-04-15 15:36:22 -0700428 fake_clock_.GetWallclockTime() - TimeDelta::FromSeconds(20)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700429 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
Alex Deymo41a75a72014-04-15 15:36:22 -0700430 fake_clock_.GetWallclockTime() - TimeDelta::FromSeconds(1)));
431
432 // Callback should not be scheduled.
433 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
434}
435
Gilad Arnolda65fced2014-07-23 09:01:31 -0700436TEST_F(UmEvaluationContextTest,
437 IsMonotonicTimeGreaterThanDoesntRecordPastTimestamps) {
438 // IsMonotonicTimeGreaterThan() should ignore timestamps on the past for
439 // reevaluation.
440 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
441 fake_clock_.GetMonotonicTime() - TimeDelta::FromSeconds(20)));
442 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
443 fake_clock_.GetMonotonicTime() - TimeDelta::FromSeconds(1)));
444
445 // Callback should not be scheduled.
446 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
447}
448
Alex Deymo63784a52014-05-28 10:46:14 -0700449TEST_F(UmEvaluationContextTest, DumpContext) {
David Zeuthenc1490282014-04-29 16:25:03 -0700450 // |fail_var_| yield "(no value)" since it is unset.
451 eval_ctx_->GetValue(&fail_var_);
452
453 // Check that this is included.
454 fake_int_var_.reset(new int(42));
455 eval_ctx_->GetValue(&fake_int_var_);
456
457 // Check that double-quotes are escaped properly.
458 fake_poll_var_.reset(new string("Hello \"world\"!"));
459 eval_ctx_->GetValue(&fake_poll_var_);
460
461 // Note that the variables are printed in alphabetical order. Also
Gilad Arnolda65fced2014-07-23 09:01:31 -0700462 // see UmEvaluationContextText::SetUp() where the values used for
463 // |evaluation_start_{monotonic,wallclock| are set.
David Zeuthenc1490282014-04-29 16:25:03 -0700464 EXPECT_EQ("{\n"
Gilad Arnolda65fced2014-07-23 09:01:31 -0700465 " \"evaluation_start_monotonic\": \"4/22/2009 19:25:00 GMT\",\n"
466 " \"evaluation_start_wallclock\": \"3/2/2006 1:23:45 GMT\",\n"
David Zeuthenc1490282014-04-29 16:25:03 -0700467 " \"variables\": {\n"
468 " \"fail_var\": \"(no value)\",\n"
469 " \"fake_int\": \"42\",\n"
470 " \"fake_poll\": \"Hello \\\"world\\\"!\"\n"
471 " }\n"
Gilad Arnold6e5ab5c2014-06-23 15:13:56 -0700472 "}",
David Zeuthenc1490282014-04-29 16:25:03 -0700473 eval_ctx_->DumpContext());
474}
475
Alex Deymo63784a52014-05-28 10:46:14 -0700476} // namespace chromeos_update_manager