blob: 5c5a71b9bfd54e804576578364fe0df1bdc32331 [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
2// Copyright (C) 2014 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
Alex Deymo23949d42014-02-05 15:20:59 -080016
Alex Deymoaab50e32014-11-10 19:55:35 -080017#include "update_engine/update_manager/evaluation_context.h"
18
Ben Chan02f7c1d2014-10-18 15:18:02 -070019#include <memory>
Alex Deymo23949d42014-02-05 15:20:59 -080020#include <string>
21
Alex Deymo53556ec2014-03-17 10:05:57 -070022#include <base/bind.h>
Alex Deymo509dd532015-06-10 14:11:05 -070023#include <chromeos/message_loops/fake_message_loop.h>
24#include <chromeos/message_loops/message_loop_utils.h>
Alex Deymo53556ec2014-03-17 10:05:57 -070025#include <gtest/gtest.h>
26
Alex Deymo41a75a72014-04-15 15:36:22 -070027#include "update_engine/fake_clock.h"
Alex Deymo63784a52014-05-28 10:46:14 -070028#include "update_engine/update_manager/fake_variable.h"
29#include "update_engine/update_manager/generic_variables.h"
30#include "update_engine/update_manager/mock_variable.h"
31#include "update_engine/update_manager/umtest_utils.h"
Alex Deymo23949d42014-02-05 15:20:59 -080032
Alex Deymo53556ec2014-03-17 10:05:57 -070033using base::Bind;
Gilad Arnoldfb794f42014-07-01 15:36:31 -070034using base::Closure;
Alex Deymo41a75a72014-04-15 15:36:22 -070035using base::Time;
Alex Deymo53556ec2014-03-17 10:05:57 -070036using base::TimeDelta;
Alex Deymo509dd532015-06-10 14:11:05 -070037using chromeos::MessageLoop;
38using chromeos::MessageLoopRunMaxIterations;
39using chromeos::MessageLoopRunUntil;
Alex Deymo41a75a72014-04-15 15:36:22 -070040using chromeos_update_engine::FakeClock;
Alex Deymo23949d42014-02-05 15:20:59 -080041using std::string;
Ben Chan02f7c1d2014-10-18 15:18:02 -070042using std::unique_ptr;
Alex Deymo41a75a72014-04-15 15:36:22 -070043using testing::Return;
44using testing::StrictMock;
45using testing::_;
Alex Deymo23949d42014-02-05 15:20:59 -080046
Gilad Arnoldfb794f42014-07-01 15:36:31 -070047namespace chromeos_update_manager {
48
Alex Deymo53556ec2014-03-17 10:05:57 -070049namespace {
50
51void DoNothing() {}
52
53// Sets the value of the passed pointer to true.
54void SetTrue(bool* value) {
55 *value = true;
56}
57
58bool GetBoolean(bool* value) {
59 return *value;
60}
61
Gilad Arnoldfb794f42014-07-01 15:36:31 -070062template<typename T>
63void ReadVar(scoped_refptr<EvaluationContext> ec, Variable<T>* var) {
64 ec->GetValue(var);
65}
Alex Deymo53556ec2014-03-17 10:05:57 -070066
Gilad Arnoldfb794f42014-07-01 15:36:31 -070067// Runs |evaluation|; if the value pointed by |count_p| is greater than zero,
68// decrement it and schedule a reevaluation; otherwise, writes true to |done_p|.
69void EvaluateRepeatedly(Closure evaluation, scoped_refptr<EvaluationContext> ec,
70 int* count_p, bool* done_p) {
71 evaluation.Run();
72
73 // Schedule reevaluation if needed.
74 if (*count_p > 0) {
75 Closure closure = Bind(EvaluateRepeatedly, evaluation, ec, count_p, done_p);
76 ASSERT_TRUE(ec->RunOnValueChangeOrTimeout(closure))
77 << "Failed to schedule reevaluation, count_p=" << *count_p;
78 (*count_p)--;
79 } else {
80 *done_p = true;
81 }
82}
83
84} // namespace
Alex Deymo23949d42014-02-05 15:20:59 -080085
Alex Deymo63784a52014-05-28 10:46:14 -070086class UmEvaluationContextTest : public ::testing::Test {
Alex Deymo23949d42014-02-05 15:20:59 -080087 protected:
Alex Deymo610277e2014-11-11 21:18:11 -080088 void SetUp() override {
Alex Deymo509dd532015-06-10 14:11:05 -070089 loop_.SetAsCurrent();
Gilad Arnolda65fced2014-07-23 09:01:31 -070090 // Apr 22, 2009 19:25:00 UTC (this is a random reference point).
91 fake_clock_.SetMonotonicTime(Time::FromTimeT(1240428300));
92 // Mar 2, 2006 1:23:45 UTC.
David Zeuthenc1490282014-04-29 16:25:03 -070093 fake_clock_.SetWallclockTime(Time::FromTimeT(1141262625));
Gilad Arnold83ffdda2014-08-08 13:30:31 -070094 eval_ctx_ = new EvaluationContext(
95 &fake_clock_, default_timeout_, default_timeout_,
Ben Chan02f7c1d2014-10-18 15:18:02 -070096 unique_ptr<base::Callback<void(EvaluationContext*)>>(nullptr));
Alex Deymo23949d42014-02-05 15:20:59 -080097 }
98
Alex Deymo610277e2014-11-11 21:18:11 -080099 void TearDown() override {
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700100 // Ensure that the evaluation context did not leak and is actually being
101 // destroyed.
102 if (eval_ctx_) {
103 base::WeakPtr<EvaluationContext> eval_ctx_weak_alias =
104 eval_ctx_->weak_ptr_factory_.GetWeakPtr();
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700105 ASSERT_NE(nullptr, eval_ctx_weak_alias.get());
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700106 eval_ctx_ = nullptr;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700107 EXPECT_EQ(nullptr, eval_ctx_weak_alias.get())
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700108 << "The evaluation context was not destroyed! This is likely a bug "
109 "in how the test was written, look for leaking handles to the EC, "
110 "possibly through closure objects.";
111 }
112
Alex Deymo53556ec2014-03-17 10:05:57 -0700113 // Check that the evaluation context removed all the observers.
114 EXPECT_TRUE(fake_int_var_.observer_list_.empty());
115 EXPECT_TRUE(fake_async_var_.observer_list_.empty());
116 EXPECT_TRUE(fake_const_var_.observer_list_.empty());
117 EXPECT_TRUE(fake_poll_var_.observer_list_.empty());
Alex Deymo509dd532015-06-10 14:11:05 -0700118
119 EXPECT_FALSE(loop_.PendingTasks());
Alex Deymo53556ec2014-03-17 10:05:57 -0700120 }
121
Alex Deymof329b932014-10-30 01:37:48 -0700122 TimeDelta default_timeout_ = TimeDelta::FromSeconds(5);
Alex Deymo41a75a72014-04-15 15:36:22 -0700123
Alex Deymo509dd532015-06-10 14:11:05 -0700124 chromeos::FakeMessageLoop loop_{nullptr};
Alex Deymo41a75a72014-04-15 15:36:22 -0700125 FakeClock fake_clock_;
Alex Deymo7b948f02014-03-10 17:01:10 -0700126 scoped_refptr<EvaluationContext> eval_ctx_;
Alex Deymo53556ec2014-03-17 10:05:57 -0700127
128 // FakeVariables used for testing the EvaluationContext. These are required
129 // here to prevent them from going away *before* the EvaluationContext under
130 // test does, which keeps a reference to them.
David Zeuthenc1490282014-04-29 16:25:03 -0700131 FakeVariable<bool> fail_var_ = {"fail_var", kVariableModePoll};
Alex Deymo53556ec2014-03-17 10:05:57 -0700132 FakeVariable<int> fake_int_var_ = {"fake_int", kVariableModePoll};
133 FakeVariable<string> fake_async_var_ = {"fake_async", kVariableModeAsync};
134 FakeVariable<string> fake_const_var_ = {"fake_const", kVariableModeConst};
135 FakeVariable<string> fake_poll_var_ = {"fake_poll",
136 TimeDelta::FromSeconds(1)};
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700137 StrictMock<MockVariable<string>> mock_var_async_ {
138 "mock_var_async", kVariableModeAsync};
139 StrictMock<MockVariable<string>> mock_var_poll_ {
140 "mock_var_poll", kVariableModePoll};
Alex Deymo23949d42014-02-05 15:20:59 -0800141};
142
Alex Deymo63784a52014-05-28 10:46:14 -0700143TEST_F(UmEvaluationContextTest, GetValueFails) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700144 // FakeVariable is initialized as returning null.
145 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&fake_int_var_));
Alex Deymo23949d42014-02-05 15:20:59 -0800146}
147
Alex Deymo63784a52014-05-28 10:46:14 -0700148TEST_F(UmEvaluationContextTest, GetValueFailsWithInvalidVar) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700149 EXPECT_EQ(nullptr, eval_ctx_->GetValue(static_cast<Variable<int>*>(nullptr)));
Alex Deymo23949d42014-02-05 15:20:59 -0800150}
151
Alex Deymo63784a52014-05-28 10:46:14 -0700152TEST_F(UmEvaluationContextTest, GetValueReturns) {
Alex Deymo23949d42014-02-05 15:20:59 -0800153 const int* p_fake_int;
154
155 fake_int_var_.reset(new int(42));
156 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700157 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800158 EXPECT_EQ(42, *p_fake_int);
159}
160
Alex Deymo63784a52014-05-28 10:46:14 -0700161TEST_F(UmEvaluationContextTest, GetValueCached) {
Alex Deymo23949d42014-02-05 15:20:59 -0800162 const int* p_fake_int;
163
164 fake_int_var_.reset(new int(42));
165 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
166
167 // Check that if the variable changes, the EvaluationContext keeps returning
168 // the cached value.
169 fake_int_var_.reset(new int(5));
170
171 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700172 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800173 EXPECT_EQ(42, *p_fake_int);
174}
175
Alex Deymo63784a52014-05-28 10:46:14 -0700176TEST_F(UmEvaluationContextTest, GetValueCachesNull) {
Alex Deymo23949d42014-02-05 15:20:59 -0800177 const int* p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700178 EXPECT_EQ(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800179
180 fake_int_var_.reset(new int(42));
Alex Deymocc0e5cf2014-04-23 20:20:11 -0700181 // A second attempt to read the variable should not work because this
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700182 // EvaluationContext already got a null value.
Alex Deymo23949d42014-02-05 15:20:59 -0800183 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700184 EXPECT_EQ(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800185}
186
Alex Deymo63784a52014-05-28 10:46:14 -0700187TEST_F(UmEvaluationContextTest, GetValueMixedTypes) {
Alex Deymo23949d42014-02-05 15:20:59 -0800188 const int* p_fake_int;
189 const string* p_fake_string;
190
191 fake_int_var_.reset(new int(42));
Alex Deymo53556ec2014-03-17 10:05:57 -0700192 fake_poll_var_.reset(new string("Hello world!"));
Alex Deymo23949d42014-02-05 15:20:59 -0800193 // Check that the EvaluationContext can handle multiple Variable types. This
194 // is mostly a compile-time check due to the template nature of this method.
195 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Deymo53556ec2014-03-17 10:05:57 -0700196 p_fake_string = eval_ctx_->GetValue(&fake_poll_var_);
Alex Deymo23949d42014-02-05 15:20:59 -0800197
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700198 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800199 EXPECT_EQ(42, *p_fake_int);
200
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700201 ASSERT_NE(nullptr, p_fake_string);
Alex Deymo23949d42014-02-05 15:20:59 -0800202 EXPECT_EQ("Hello world!", *p_fake_string);
203}
204
Alex Deymo53556ec2014-03-17 10:05:57 -0700205// Test that we don't schedule an event if there's no variable to wait for.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700206TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutWithoutVariables) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700207 fake_const_var_.reset(new string("Hello world!"));
208 EXPECT_EQ(*eval_ctx_->GetValue(&fake_const_var_), "Hello world!");
209
210 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
211}
212
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700213// Test that reevaluation occurs when an async variable it depends on changes.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700214TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutWithVariables) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700215 fake_async_var_.reset(new string("Async value"));
216 eval_ctx_->GetValue(&fake_async_var_);
217
218 bool value = false;
219 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
220 // Check that the scheduled callback isn't run until we signal a ValueChaged.
Alex Deymo509dd532015-06-10 14:11:05 -0700221 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
Alex Deymo53556ec2014-03-17 10:05:57 -0700222 EXPECT_FALSE(value);
223
224 fake_async_var_.NotifyValueChanged();
225 EXPECT_FALSE(value);
226 // Ensure that the scheduled callback isn't run until we are back on the main
227 // loop.
Alex Deymo509dd532015-06-10 14:11:05 -0700228 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
Alex Deymo53556ec2014-03-17 10:05:57 -0700229 EXPECT_TRUE(value);
230}
231
232// Test that we don't re-schedule the events if we are attending one.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700233TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutCalledTwice) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700234 fake_async_var_.reset(new string("Async value"));
235 eval_ctx_->GetValue(&fake_async_var_);
236
237 bool value = false;
238 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
239 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
240
241 // The scheduled event should still work.
242 fake_async_var_.NotifyValueChanged();
Alex Deymo509dd532015-06-10 14:11:05 -0700243 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
Alex Deymo53556ec2014-03-17 10:05:57 -0700244 EXPECT_TRUE(value);
245}
246
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700247// Test that reevaluation occurs when a polling timeout fires.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700248TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutRunsFromTimeout) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700249 fake_poll_var_.reset(new string("Polled value"));
250 eval_ctx_->GetValue(&fake_poll_var_);
251
252 bool value = false;
253 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
254 // Check that the scheduled callback isn't run until the timeout occurs.
Alex Deymo509dd532015-06-10 14:11:05 -0700255 MessageLoopRunMaxIterations(MessageLoop::current(), 10);
Alex Deymo53556ec2014-03-17 10:05:57 -0700256 EXPECT_FALSE(value);
Alex Deymo509dd532015-06-10 14:11:05 -0700257 MessageLoopRunUntil(MessageLoop::current(),
258 TimeDelta::FromSeconds(10),
259 Bind(&GetBoolean, &value));
Alex Deymo53556ec2014-03-17 10:05:57 -0700260 EXPECT_TRUE(value);
261}
262
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700263// Test that callback is called when evaluation context expires, and that it
Gilad Arnoldfd45a732014-08-07 15:53:46 -0700264// cannot be used again unless the expiration deadline is reset.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700265TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutExpires) {
266 fake_async_var_.reset(new string("Async value"));
267 eval_ctx_->GetValue(&fake_async_var_);
268
269 bool value = false;
270 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
271 // Check that the scheduled callback isn't run until the timeout occurs.
Alex Deymo509dd532015-06-10 14:11:05 -0700272 MessageLoopRunMaxIterations(MessageLoop::current(), 10);
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700273 EXPECT_FALSE(value);
Alex Deymo509dd532015-06-10 14:11:05 -0700274 MessageLoopRunUntil(MessageLoop::current(),
275 TimeDelta::FromSeconds(10),
276 Bind(&GetBoolean, &value));
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700277 EXPECT_TRUE(value);
278
279 // Ensure that we cannot reschedule an evaluation.
280 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
Gilad Arnoldfd45a732014-08-07 15:53:46 -0700281
282 // Ensure that we can reschedule an evaluation after resetting expiration.
283 eval_ctx_->ResetExpiration();
284 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700285}
286
287// Test that we clear the events when destroying the EvaluationContext.
288TEST_F(UmEvaluationContextTest, RemoveObserversAndTimeoutTest) {
289 fake_async_var_.reset(new string("Async value"));
290 eval_ctx_->GetValue(&fake_async_var_);
291
292 bool value = false;
293 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
294 eval_ctx_ = nullptr;
295
296 // This should not trigger the callback since the EvaluationContext waiting
297 // for it is gone, and it should have remove all its observers.
298 fake_async_var_.NotifyValueChanged();
Alex Deymo509dd532015-06-10 14:11:05 -0700299 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700300 EXPECT_FALSE(value);
301}
302
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700303// Scheduling two reevaluations from the callback should succeed.
304TEST_F(UmEvaluationContextTest,
305 RunOnValueChangeOrTimeoutReevaluatesRepeatedly) {
306 fake_poll_var_.reset(new string("Polled value"));
307 Closure evaluation = Bind(ReadVar<string>, eval_ctx_, &fake_poll_var_);
308 int num_reevaluations = 2;
309 bool done = false;
310
311 // Run the evaluation once.
312 evaluation.Run();
313
314 // Schedule repeated reevaluations.
315 Closure closure = Bind(EvaluateRepeatedly, evaluation, eval_ctx_,
316 &num_reevaluations, &done);
317 ASSERT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(closure));
Alex Deymo509dd532015-06-10 14:11:05 -0700318 MessageLoopRunUntil(MessageLoop::current(),
319 TimeDelta::FromSeconds(10),
320 Bind(&GetBoolean, &done));
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700321 EXPECT_EQ(0, num_reevaluations);
322}
323
Alex Deymodb799532014-03-21 13:00:00 -0700324// Test that we can delete the EvaluationContext while having pending events.
Alex Deymo63784a52014-05-28 10:46:14 -0700325TEST_F(UmEvaluationContextTest, ObjectDeletedWithPendingEventsTest) {
Alex Deymodb799532014-03-21 13:00:00 -0700326 fake_async_var_.reset(new string("Async value"));
327 fake_poll_var_.reset(new string("Polled value"));
328 eval_ctx_->GetValue(&fake_async_var_);
329 eval_ctx_->GetValue(&fake_poll_var_);
330 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
331 // TearDown() checks for leaked observers on this async_variable, which means
332 // that our object is still alive after removing its reference.
333}
334
335// Test that timed events fired after removal of the EvaluationContext don't
336// crash.
Alex Deymo63784a52014-05-28 10:46:14 -0700337TEST_F(UmEvaluationContextTest, TimeoutEventAfterDeleteTest) {
Alex Deymo0bb23412015-06-19 00:04:46 -0700338 FakeVariable<string> fake_short_poll_var = {"fake_short_poll",
339 TimeDelta::FromSeconds(1)};
Alex Deymodb799532014-03-21 13:00:00 -0700340 fake_short_poll_var.reset(new string("Polled value"));
341 eval_ctx_->GetValue(&fake_short_poll_var);
342 bool value = false;
343 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
344 // Remove the last reference to the EvaluationContext and run the loop for
Alex Deymo0bb23412015-06-19 00:04:46 -0700345 // 10 seconds to give time to the main loop to trigger the timeout Event (of 1
346 // second). Our callback should not be called because the EvaluationContext
Alex Deymodb799532014-03-21 13:00:00 -0700347 // was removed before the timeout event is attended.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700348 eval_ctx_ = nullptr;
Alex Deymo509dd532015-06-10 14:11:05 -0700349 MessageLoopRunUntil(MessageLoop::current(),
350 TimeDelta::FromSeconds(10),
351 Bind(&GetBoolean, &value));
Alex Deymodb799532014-03-21 13:00:00 -0700352 EXPECT_FALSE(value);
353}
354
Alex Deymo63784a52014-05-28 10:46:14 -0700355TEST_F(UmEvaluationContextTest, DefaultTimeout) {
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700356 // Test that the evaluation timeout calculation uses the default timeout on
357 // setup.
Alex Deymo41a75a72014-04-15 15:36:22 -0700358 EXPECT_CALL(mock_var_async_, GetValue(default_timeout_, _))
359 .WillOnce(Return(nullptr));
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700360 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&mock_var_async_));
Alex Deymo41a75a72014-04-15 15:36:22 -0700361}
362
Alex Deymo63784a52014-05-28 10:46:14 -0700363TEST_F(UmEvaluationContextTest, TimeoutUpdatesWithMonotonicTime) {
Alex Deymo41a75a72014-04-15 15:36:22 -0700364 fake_clock_.SetMonotonicTime(
365 fake_clock_.GetMonotonicTime() + TimeDelta::FromSeconds(1));
366
367 TimeDelta timeout = default_timeout_ - TimeDelta::FromSeconds(1);
368
369 EXPECT_CALL(mock_var_async_, GetValue(timeout, _))
370 .WillOnce(Return(nullptr));
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700371 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&mock_var_async_));
Alex Deymo41a75a72014-04-15 15:36:22 -0700372}
373
Gilad Arnolda65fced2014-07-23 09:01:31 -0700374TEST_F(UmEvaluationContextTest, ResetEvaluationResetsTimesWallclock) {
Alex Deymof329b932014-10-30 01:37:48 -0700375 Time cur_time = fake_clock_.GetWallclockTime();
Alex Deymo41a75a72014-04-15 15:36:22 -0700376 // Advance the time on the clock but don't call ResetEvaluation yet.
377 fake_clock_.SetWallclockTime(cur_time + TimeDelta::FromSeconds(4));
378
Gilad Arnolda65fced2014-07-23 09:01:31 -0700379 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
380 cur_time - TimeDelta::FromSeconds(1)));
381 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time));
382 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
383 cur_time + TimeDelta::FromSeconds(1)));
Alex Deymo41a75a72014-04-15 15:36:22 -0700384 // Call ResetEvaluation now, which should use the new evaluation time.
385 eval_ctx_->ResetEvaluation();
386
387 cur_time = fake_clock_.GetWallclockTime();
Gilad Arnolda65fced2014-07-23 09:01:31 -0700388 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
389 cur_time - TimeDelta::FromSeconds(1)));
390 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time));
391 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
392 cur_time + TimeDelta::FromSeconds(1)));
Alex Deymo41a75a72014-04-15 15:36:22 -0700393}
394
Gilad Arnolda65fced2014-07-23 09:01:31 -0700395TEST_F(UmEvaluationContextTest, ResetEvaluationResetsTimesMonotonic) {
Alex Deymof329b932014-10-30 01:37:48 -0700396 Time cur_time = fake_clock_.GetMonotonicTime();
Gilad Arnolda65fced2014-07-23 09:01:31 -0700397 // Advance the time on the clock but don't call ResetEvaluation yet.
398 fake_clock_.SetMonotonicTime(cur_time + TimeDelta::FromSeconds(4));
399
400 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
401 cur_time - TimeDelta::FromSeconds(1)));
402 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time));
403 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
404 cur_time + TimeDelta::FromSeconds(1)));
405 // Call ResetEvaluation now, which should use the new evaluation time.
406 eval_ctx_->ResetEvaluation();
407
408 cur_time = fake_clock_.GetMonotonicTime();
409 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
410 cur_time - TimeDelta::FromSeconds(1)));
411 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time));
412 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
413 cur_time + TimeDelta::FromSeconds(1)));
414}
415
416TEST_F(UmEvaluationContextTest,
417 IsWallclockTimeGreaterThanSignalsTriggerReevaluation) {
418 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
Alex Deymo41a75a72014-04-15 15:36:22 -0700419 fake_clock_.GetWallclockTime() + TimeDelta::FromSeconds(1)));
420
Gilad Arnolda65fced2014-07-23 09:01:31 -0700421 // The "false" from IsWallclockTimeGreaterThan means that's not that timestamp
422 // yet, so this should schedule a callback for when that happens.
Alex Deymo41a75a72014-04-15 15:36:22 -0700423 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
424}
425
Gilad Arnolda65fced2014-07-23 09:01:31 -0700426TEST_F(UmEvaluationContextTest,
427 IsMonotonicTimeGreaterThanSignalsTriggerReevaluation) {
428 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
429 fake_clock_.GetMonotonicTime() + TimeDelta::FromSeconds(1)));
430
431 // The "false" from IsMonotonicTimeGreaterThan means that's not that timestamp
432 // yet, so this should schedule a callback for when that happens.
433 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
434}
435
436TEST_F(UmEvaluationContextTest,
437 IsWallclockTimeGreaterThanDoesntRecordPastTimestamps) {
438 // IsWallclockTimeGreaterThan() should ignore timestamps on the past for
439 // reevaluation.
440 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
Alex Deymo41a75a72014-04-15 15:36:22 -0700441 fake_clock_.GetWallclockTime() - TimeDelta::FromSeconds(20)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700442 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
Alex Deymo41a75a72014-04-15 15:36:22 -0700443 fake_clock_.GetWallclockTime() - TimeDelta::FromSeconds(1)));
444
445 // Callback should not be scheduled.
446 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
447}
448
Gilad Arnolda65fced2014-07-23 09:01:31 -0700449TEST_F(UmEvaluationContextTest,
450 IsMonotonicTimeGreaterThanDoesntRecordPastTimestamps) {
451 // IsMonotonicTimeGreaterThan() should ignore timestamps on the past for
452 // reevaluation.
453 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
454 fake_clock_.GetMonotonicTime() - TimeDelta::FromSeconds(20)));
455 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
456 fake_clock_.GetMonotonicTime() - TimeDelta::FromSeconds(1)));
457
458 // Callback should not be scheduled.
459 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
460}
461
Alex Deymo63784a52014-05-28 10:46:14 -0700462TEST_F(UmEvaluationContextTest, DumpContext) {
David Zeuthenc1490282014-04-29 16:25:03 -0700463 // |fail_var_| yield "(no value)" since it is unset.
464 eval_ctx_->GetValue(&fail_var_);
465
466 // Check that this is included.
467 fake_int_var_.reset(new int(42));
468 eval_ctx_->GetValue(&fake_int_var_);
469
470 // Check that double-quotes are escaped properly.
471 fake_poll_var_.reset(new string("Hello \"world\"!"));
472 eval_ctx_->GetValue(&fake_poll_var_);
473
474 // Note that the variables are printed in alphabetical order. Also
Gilad Arnolda65fced2014-07-23 09:01:31 -0700475 // see UmEvaluationContextText::SetUp() where the values used for
476 // |evaluation_start_{monotonic,wallclock| are set.
David Zeuthenc1490282014-04-29 16:25:03 -0700477 EXPECT_EQ("{\n"
Gilad Arnolda65fced2014-07-23 09:01:31 -0700478 " \"evaluation_start_monotonic\": \"4/22/2009 19:25:00 GMT\",\n"
479 " \"evaluation_start_wallclock\": \"3/2/2006 1:23:45 GMT\",\n"
David Zeuthenc1490282014-04-29 16:25:03 -0700480 " \"variables\": {\n"
481 " \"fail_var\": \"(no value)\",\n"
482 " \"fake_int\": \"42\",\n"
483 " \"fake_poll\": \"Hello \\\"world\\\"!\"\n"
484 " }\n"
Gilad Arnold6e5ab5c2014-06-23 15:13:56 -0700485 "}",
David Zeuthenc1490282014-04-29 16:25:03 -0700486 eval_ctx_->DumpContext());
487}
488
Alex Deymo63784a52014-05-28 10:46:14 -0700489} // namespace chromeos_update_manager