blob: d1728859b2ebbd4f6884f833d560a2664369af1e [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>
Jakub Pawlowski7e1dcf72018-07-26 00:29:42 -070023#include <base/bind_helpers.h>
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070024#include <brillo/message_loops/fake_message_loop.h>
25#include <brillo/message_loops/message_loop_utils.h>
Alex Deymo53556ec2014-03-17 10:05:57 -070026#include <gtest/gtest.h>
27
Alex Deymo39910dc2015-11-09 17:04:30 -080028#include "update_engine/common/fake_clock.h"
Alex Deymo63784a52014-05-28 10:46:14 -070029#include "update_engine/update_manager/fake_variable.h"
30#include "update_engine/update_manager/generic_variables.h"
31#include "update_engine/update_manager/mock_variable.h"
32#include "update_engine/update_manager/umtest_utils.h"
Alex Deymo23949d42014-02-05 15:20:59 -080033
Alex Deymo53556ec2014-03-17 10:05:57 -070034using base::Bind;
Gilad Arnoldfb794f42014-07-01 15:36:31 -070035using base::Closure;
Alex Deymo41a75a72014-04-15 15:36:22 -070036using base::Time;
Alex Deymo53556ec2014-03-17 10:05:57 -070037using base::TimeDelta;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070038using brillo::MessageLoop;
39using brillo::MessageLoopRunMaxIterations;
40using brillo::MessageLoopRunUntil;
Alex Deymo41a75a72014-04-15 15:36:22 -070041using chromeos_update_engine::FakeClock;
Alex Deymo23949d42014-02-05 15:20:59 -080042using std::string;
Ben Chan02f7c1d2014-10-18 15:18:02 -070043using std::unique_ptr;
Alex Deymo41a75a72014-04-15 15:36:22 -070044using testing::Return;
45using testing::StrictMock;
46using testing::_;
Alex Deymo23949d42014-02-05 15:20:59 -080047
Gilad Arnoldfb794f42014-07-01 15:36:31 -070048namespace chromeos_update_manager {
49
Alex Deymo53556ec2014-03-17 10:05:57 -070050namespace {
51
Alex Deymo53556ec2014-03-17 10:05:57 -070052// Sets the value of the passed pointer to true.
53void SetTrue(bool* value) {
54 *value = true;
55}
56
57bool GetBoolean(bool* value) {
58 return *value;
59}
60
Gilad Arnoldfb794f42014-07-01 15:36:31 -070061template<typename T>
62void ReadVar(scoped_refptr<EvaluationContext> ec, Variable<T>* var) {
63 ec->GetValue(var);
64}
Alex Deymo53556ec2014-03-17 10:05:57 -070065
Gilad Arnoldfb794f42014-07-01 15:36:31 -070066// Runs |evaluation|; if the value pointed by |count_p| is greater than zero,
67// decrement it and schedule a reevaluation; otherwise, writes true to |done_p|.
68void EvaluateRepeatedly(Closure evaluation, scoped_refptr<EvaluationContext> ec,
69 int* count_p, bool* done_p) {
70 evaluation.Run();
71
72 // Schedule reevaluation if needed.
73 if (*count_p > 0) {
74 Closure closure = Bind(EvaluateRepeatedly, evaluation, ec, count_p, done_p);
75 ASSERT_TRUE(ec->RunOnValueChangeOrTimeout(closure))
76 << "Failed to schedule reevaluation, count_p=" << *count_p;
77 (*count_p)--;
78 } else {
79 *done_p = true;
80 }
81}
82
83} // namespace
Alex Deymo23949d42014-02-05 15:20:59 -080084
Alex Deymo63784a52014-05-28 10:46:14 -070085class UmEvaluationContextTest : public ::testing::Test {
Alex Deymo23949d42014-02-05 15:20:59 -080086 protected:
Alex Deymo610277e2014-11-11 21:18:11 -080087 void SetUp() override {
Alex Deymo509dd532015-06-10 14:11:05 -070088 loop_.SetAsCurrent();
Gilad Arnolda65fced2014-07-23 09:01:31 -070089 // Apr 22, 2009 19:25:00 UTC (this is a random reference point).
90 fake_clock_.SetMonotonicTime(Time::FromTimeT(1240428300));
91 // Mar 2, 2006 1:23:45 UTC.
David Zeuthenc1490282014-04-29 16:25:03 -070092 fake_clock_.SetWallclockTime(Time::FromTimeT(1141262625));
Gilad Arnold83ffdda2014-08-08 13:30:31 -070093 eval_ctx_ = new EvaluationContext(
94 &fake_clock_, default_timeout_, default_timeout_,
Ben Chan02f7c1d2014-10-18 15:18:02 -070095 unique_ptr<base::Callback<void(EvaluationContext*)>>(nullptr));
Alex Deymo23949d42014-02-05 15:20:59 -080096 }
97
Alex Deymo610277e2014-11-11 21:18:11 -080098 void TearDown() override {
Gilad Arnoldfb794f42014-07-01 15:36:31 -070099 // Ensure that the evaluation context did not leak and is actually being
100 // destroyed.
101 if (eval_ctx_) {
102 base::WeakPtr<EvaluationContext> eval_ctx_weak_alias =
103 eval_ctx_->weak_ptr_factory_.GetWeakPtr();
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700104 ASSERT_NE(nullptr, eval_ctx_weak_alias.get());
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700105 eval_ctx_ = nullptr;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700106 EXPECT_EQ(nullptr, eval_ctx_weak_alias.get())
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700107 << "The evaluation context was not destroyed! This is likely a bug "
108 "in how the test was written, look for leaking handles to the EC, "
109 "possibly through closure objects.";
110 }
111
Alex Deymo53556ec2014-03-17 10:05:57 -0700112 // Check that the evaluation context removed all the observers.
113 EXPECT_TRUE(fake_int_var_.observer_list_.empty());
114 EXPECT_TRUE(fake_async_var_.observer_list_.empty());
115 EXPECT_TRUE(fake_const_var_.observer_list_.empty());
116 EXPECT_TRUE(fake_poll_var_.observer_list_.empty());
Alex Deymo509dd532015-06-10 14:11:05 -0700117
118 EXPECT_FALSE(loop_.PendingTasks());
Alex Deymo53556ec2014-03-17 10:05:57 -0700119 }
120
Alex Deymof329b932014-10-30 01:37:48 -0700121 TimeDelta default_timeout_ = TimeDelta::FromSeconds(5);
Alex Deymo41a75a72014-04-15 15:36:22 -0700122
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700123 brillo::FakeMessageLoop loop_{nullptr};
Alex Deymo41a75a72014-04-15 15:36:22 -0700124 FakeClock fake_clock_;
Alex Deymo7b948f02014-03-10 17:01:10 -0700125 scoped_refptr<EvaluationContext> eval_ctx_;
Alex Deymo53556ec2014-03-17 10:05:57 -0700126
127 // FakeVariables used for testing the EvaluationContext. These are required
128 // here to prevent them from going away *before* the EvaluationContext under
129 // test does, which keeps a reference to them.
David Zeuthenc1490282014-04-29 16:25:03 -0700130 FakeVariable<bool> fail_var_ = {"fail_var", kVariableModePoll};
Alex Deymo53556ec2014-03-17 10:05:57 -0700131 FakeVariable<int> fake_int_var_ = {"fake_int", kVariableModePoll};
132 FakeVariable<string> fake_async_var_ = {"fake_async", kVariableModeAsync};
133 FakeVariable<string> fake_const_var_ = {"fake_const", kVariableModeConst};
134 FakeVariable<string> fake_poll_var_ = {"fake_poll",
135 TimeDelta::FromSeconds(1)};
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700136 StrictMock<MockVariable<string>> mock_var_async_ {
137 "mock_var_async", kVariableModeAsync};
138 StrictMock<MockVariable<string>> mock_var_poll_ {
139 "mock_var_poll", kVariableModePoll};
Alex Deymo23949d42014-02-05 15:20:59 -0800140};
141
Alex Deymo63784a52014-05-28 10:46:14 -0700142TEST_F(UmEvaluationContextTest, GetValueFails) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700143 // FakeVariable is initialized as returning null.
144 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&fake_int_var_));
Alex Deymo23949d42014-02-05 15:20:59 -0800145}
146
Alex Deymo63784a52014-05-28 10:46:14 -0700147TEST_F(UmEvaluationContextTest, GetValueFailsWithInvalidVar) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700148 EXPECT_EQ(nullptr, eval_ctx_->GetValue(static_cast<Variable<int>*>(nullptr)));
Alex Deymo23949d42014-02-05 15:20:59 -0800149}
150
Alex Deymo63784a52014-05-28 10:46:14 -0700151TEST_F(UmEvaluationContextTest, GetValueReturns) {
Alex Deymo23949d42014-02-05 15:20:59 -0800152 const int* p_fake_int;
153
154 fake_int_var_.reset(new int(42));
155 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700156 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800157 EXPECT_EQ(42, *p_fake_int);
158}
159
Alex Deymo63784a52014-05-28 10:46:14 -0700160TEST_F(UmEvaluationContextTest, GetValueCached) {
Alex Deymo23949d42014-02-05 15:20:59 -0800161 const int* p_fake_int;
162
163 fake_int_var_.reset(new int(42));
164 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
165
166 // Check that if the variable changes, the EvaluationContext keeps returning
167 // the cached value.
168 fake_int_var_.reset(new int(5));
169
170 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700171 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800172 EXPECT_EQ(42, *p_fake_int);
173}
174
Alex Deymo63784a52014-05-28 10:46:14 -0700175TEST_F(UmEvaluationContextTest, GetValueCachesNull) {
Alex Deymo23949d42014-02-05 15:20:59 -0800176 const int* p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700177 EXPECT_EQ(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800178
179 fake_int_var_.reset(new int(42));
Alex Deymocc0e5cf2014-04-23 20:20:11 -0700180 // A second attempt to read the variable should not work because this
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700181 // EvaluationContext already got a null value.
Alex Deymo23949d42014-02-05 15:20:59 -0800182 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700183 EXPECT_EQ(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800184}
185
Alex Deymo63784a52014-05-28 10:46:14 -0700186TEST_F(UmEvaluationContextTest, GetValueMixedTypes) {
Alex Deymo23949d42014-02-05 15:20:59 -0800187 const int* p_fake_int;
188 const string* p_fake_string;
189
190 fake_int_var_.reset(new int(42));
Alex Deymo53556ec2014-03-17 10:05:57 -0700191 fake_poll_var_.reset(new string("Hello world!"));
Alex Deymo23949d42014-02-05 15:20:59 -0800192 // Check that the EvaluationContext can handle multiple Variable types. This
193 // is mostly a compile-time check due to the template nature of this method.
194 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Deymo53556ec2014-03-17 10:05:57 -0700195 p_fake_string = eval_ctx_->GetValue(&fake_poll_var_);
Alex Deymo23949d42014-02-05 15:20:59 -0800196
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700197 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800198 EXPECT_EQ(42, *p_fake_int);
199
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700200 ASSERT_NE(nullptr, p_fake_string);
Alex Deymo23949d42014-02-05 15:20:59 -0800201 EXPECT_EQ("Hello world!", *p_fake_string);
202}
203
Alex Deymo53556ec2014-03-17 10:05:57 -0700204// Test that we don't schedule an event if there's no variable to wait for.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700205TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutWithoutVariables) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700206 fake_const_var_.reset(new string("Hello world!"));
207 EXPECT_EQ(*eval_ctx_->GetValue(&fake_const_var_), "Hello world!");
208
Amin Hassani2e4eda52019-01-07 14:01:17 -0800209 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(
210#if BASE_VER < 576279
211 Bind(&base::DoNothing)
212#else
213 base::DoNothing()
214#endif
215 ));
Alex Deymo53556ec2014-03-17 10:05:57 -0700216}
217
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700218// Test that reevaluation occurs when an async variable it depends on changes.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700219TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutWithVariables) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700220 fake_async_var_.reset(new string("Async value"));
221 eval_ctx_->GetValue(&fake_async_var_);
222
223 bool value = false;
224 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
225 // Check that the scheduled callback isn't run until we signal a ValueChaged.
Alex Deymo509dd532015-06-10 14:11:05 -0700226 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
Alex Deymo53556ec2014-03-17 10:05:57 -0700227 EXPECT_FALSE(value);
228
229 fake_async_var_.NotifyValueChanged();
230 EXPECT_FALSE(value);
231 // Ensure that the scheduled callback isn't run until we are back on the main
232 // loop.
Alex Deymo509dd532015-06-10 14:11:05 -0700233 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
Alex Deymo53556ec2014-03-17 10:05:57 -0700234 EXPECT_TRUE(value);
235}
236
237// Test that we don't re-schedule the events if we are attending one.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700238TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutCalledTwice) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700239 fake_async_var_.reset(new string("Async value"));
240 eval_ctx_->GetValue(&fake_async_var_);
241
242 bool value = false;
243 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
244 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
245
246 // The scheduled event should still work.
247 fake_async_var_.NotifyValueChanged();
Alex Deymo509dd532015-06-10 14:11:05 -0700248 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
Alex Deymo53556ec2014-03-17 10:05:57 -0700249 EXPECT_TRUE(value);
250}
251
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700252// Test that reevaluation occurs when a polling timeout fires.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700253TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutRunsFromTimeout) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700254 fake_poll_var_.reset(new string("Polled value"));
255 eval_ctx_->GetValue(&fake_poll_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);
Alex Deymo53556ec2014-03-17 10:05:57 -0700261 EXPECT_FALSE(value);
Alex Deymo509dd532015-06-10 14:11:05 -0700262 MessageLoopRunUntil(MessageLoop::current(),
263 TimeDelta::FromSeconds(10),
264 Bind(&GetBoolean, &value));
Alex Deymo53556ec2014-03-17 10:05:57 -0700265 EXPECT_TRUE(value);
266}
267
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700268// Test that callback is called when evaluation context expires, and that it
Gilad Arnoldfd45a732014-08-07 15:53:46 -0700269// cannot be used again unless the expiration deadline is reset.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700270TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutExpires) {
271 fake_async_var_.reset(new string("Async value"));
272 eval_ctx_->GetValue(&fake_async_var_);
273
274 bool value = false;
275 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
276 // Check that the scheduled callback isn't run until the timeout occurs.
Alex Deymo509dd532015-06-10 14:11:05 -0700277 MessageLoopRunMaxIterations(MessageLoop::current(), 10);
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700278 EXPECT_FALSE(value);
Alex Deymo509dd532015-06-10 14:11:05 -0700279 MessageLoopRunUntil(MessageLoop::current(),
280 TimeDelta::FromSeconds(10),
281 Bind(&GetBoolean, &value));
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700282 EXPECT_TRUE(value);
283
284 // Ensure that we cannot reschedule an evaluation.
Amin Hassani2e4eda52019-01-07 14:01:17 -0800285 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(
286#if BASE_VER < 576279
287 Bind(&base::DoNothing)
288#else
289 base::DoNothing()
290#endif
291 ));
Gilad Arnoldfd45a732014-08-07 15:53:46 -0700292
293 // Ensure that we can reschedule an evaluation after resetting expiration.
294 eval_ctx_->ResetExpiration();
Amin Hassani2e4eda52019-01-07 14:01:17 -0800295 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(
296#if BASE_VER < 576279
297 Bind(&base::DoNothing)
298#else
299 base::DoNothing()
300#endif
301 ));
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700302}
303
304// Test that we clear the events when destroying the EvaluationContext.
305TEST_F(UmEvaluationContextTest, RemoveObserversAndTimeoutTest) {
306 fake_async_var_.reset(new string("Async value"));
307 eval_ctx_->GetValue(&fake_async_var_);
308
309 bool value = false;
310 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
311 eval_ctx_ = nullptr;
312
313 // This should not trigger the callback since the EvaluationContext waiting
314 // for it is gone, and it should have remove all its observers.
315 fake_async_var_.NotifyValueChanged();
Alex Deymo509dd532015-06-10 14:11:05 -0700316 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700317 EXPECT_FALSE(value);
318}
319
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700320// Scheduling two reevaluations from the callback should succeed.
321TEST_F(UmEvaluationContextTest,
322 RunOnValueChangeOrTimeoutReevaluatesRepeatedly) {
323 fake_poll_var_.reset(new string("Polled value"));
324 Closure evaluation = Bind(ReadVar<string>, eval_ctx_, &fake_poll_var_);
325 int num_reevaluations = 2;
326 bool done = false;
327
328 // Run the evaluation once.
329 evaluation.Run();
330
331 // Schedule repeated reevaluations.
332 Closure closure = Bind(EvaluateRepeatedly, evaluation, eval_ctx_,
333 &num_reevaluations, &done);
334 ASSERT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(closure));
Alex Deymo509dd532015-06-10 14:11:05 -0700335 MessageLoopRunUntil(MessageLoop::current(),
336 TimeDelta::FromSeconds(10),
337 Bind(&GetBoolean, &done));
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700338 EXPECT_EQ(0, num_reevaluations);
339}
340
Alex Deymodb799532014-03-21 13:00:00 -0700341// Test that we can delete the EvaluationContext while having pending events.
Alex Deymo63784a52014-05-28 10:46:14 -0700342TEST_F(UmEvaluationContextTest, ObjectDeletedWithPendingEventsTest) {
Alex Deymodb799532014-03-21 13:00:00 -0700343 fake_async_var_.reset(new string("Async value"));
344 fake_poll_var_.reset(new string("Polled value"));
345 eval_ctx_->GetValue(&fake_async_var_);
346 eval_ctx_->GetValue(&fake_poll_var_);
Amin Hassani2e4eda52019-01-07 14:01:17 -0800347 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(
348#if BASE_VER < 576279
349 Bind(&base::DoNothing)
350#else
351 base::DoNothing()
352#endif
353 ));
Alex Deymodb799532014-03-21 13:00:00 -0700354 // TearDown() checks for leaked observers on this async_variable, which means
355 // that our object is still alive after removing its reference.
356}
357
358// Test that timed events fired after removal of the EvaluationContext don't
359// crash.
Alex Deymo63784a52014-05-28 10:46:14 -0700360TEST_F(UmEvaluationContextTest, TimeoutEventAfterDeleteTest) {
Alex Deymo0bb23412015-06-19 00:04:46 -0700361 FakeVariable<string> fake_short_poll_var = {"fake_short_poll",
362 TimeDelta::FromSeconds(1)};
Alex Deymodb799532014-03-21 13:00:00 -0700363 fake_short_poll_var.reset(new string("Polled value"));
364 eval_ctx_->GetValue(&fake_short_poll_var);
365 bool value = false;
366 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
367 // Remove the last reference to the EvaluationContext and run the loop for
Alex Deymo0bb23412015-06-19 00:04:46 -0700368 // 10 seconds to give time to the main loop to trigger the timeout Event (of 1
369 // second). Our callback should not be called because the EvaluationContext
Alex Deymodb799532014-03-21 13:00:00 -0700370 // was removed before the timeout event is attended.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700371 eval_ctx_ = nullptr;
Alex Deymo509dd532015-06-10 14:11:05 -0700372 MessageLoopRunUntil(MessageLoop::current(),
373 TimeDelta::FromSeconds(10),
374 Bind(&GetBoolean, &value));
Alex Deymodb799532014-03-21 13:00:00 -0700375 EXPECT_FALSE(value);
376}
377
Alex Deymo63784a52014-05-28 10:46:14 -0700378TEST_F(UmEvaluationContextTest, DefaultTimeout) {
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700379 // Test that the evaluation timeout calculation uses the default timeout on
380 // setup.
Alex Deymo41a75a72014-04-15 15:36:22 -0700381 EXPECT_CALL(mock_var_async_, GetValue(default_timeout_, _))
382 .WillOnce(Return(nullptr));
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700383 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&mock_var_async_));
Alex Deymo41a75a72014-04-15 15:36:22 -0700384}
385
Alex Deymo63784a52014-05-28 10:46:14 -0700386TEST_F(UmEvaluationContextTest, TimeoutUpdatesWithMonotonicTime) {
Alex Deymo41a75a72014-04-15 15:36:22 -0700387 fake_clock_.SetMonotonicTime(
388 fake_clock_.GetMonotonicTime() + TimeDelta::FromSeconds(1));
389
390 TimeDelta timeout = default_timeout_ - TimeDelta::FromSeconds(1);
391
392 EXPECT_CALL(mock_var_async_, GetValue(timeout, _))
393 .WillOnce(Return(nullptr));
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700394 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&mock_var_async_));
Alex Deymo41a75a72014-04-15 15:36:22 -0700395}
396
Gilad Arnolda65fced2014-07-23 09:01:31 -0700397TEST_F(UmEvaluationContextTest, ResetEvaluationResetsTimesWallclock) {
Alex Deymof329b932014-10-30 01:37:48 -0700398 Time cur_time = fake_clock_.GetWallclockTime();
Alex Deymo41a75a72014-04-15 15:36:22 -0700399 // Advance the time on the clock but don't call ResetEvaluation yet.
400 fake_clock_.SetWallclockTime(cur_time + TimeDelta::FromSeconds(4));
401
Gilad Arnolda65fced2014-07-23 09:01:31 -0700402 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
403 cur_time - TimeDelta::FromSeconds(1)));
404 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time));
405 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
406 cur_time + TimeDelta::FromSeconds(1)));
Alex Deymo41a75a72014-04-15 15:36:22 -0700407 // Call ResetEvaluation now, which should use the new evaluation time.
408 eval_ctx_->ResetEvaluation();
409
410 cur_time = fake_clock_.GetWallclockTime();
Gilad Arnolda65fced2014-07-23 09:01:31 -0700411 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
412 cur_time - TimeDelta::FromSeconds(1)));
413 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time));
414 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
415 cur_time + TimeDelta::FromSeconds(1)));
Alex Deymo41a75a72014-04-15 15:36:22 -0700416}
417
Gilad Arnolda65fced2014-07-23 09:01:31 -0700418TEST_F(UmEvaluationContextTest, ResetEvaluationResetsTimesMonotonic) {
Alex Deymof329b932014-10-30 01:37:48 -0700419 Time cur_time = fake_clock_.GetMonotonicTime();
Gilad Arnolda65fced2014-07-23 09:01:31 -0700420 // Advance the time on the clock but don't call ResetEvaluation yet.
421 fake_clock_.SetMonotonicTime(cur_time + TimeDelta::FromSeconds(4));
422
423 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
424 cur_time - TimeDelta::FromSeconds(1)));
425 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time));
426 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
427 cur_time + TimeDelta::FromSeconds(1)));
428 // Call ResetEvaluation now, which should use the new evaluation time.
429 eval_ctx_->ResetEvaluation();
430
431 cur_time = fake_clock_.GetMonotonicTime();
432 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
433 cur_time - TimeDelta::FromSeconds(1)));
434 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time));
435 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
436 cur_time + TimeDelta::FromSeconds(1)));
437}
438
439TEST_F(UmEvaluationContextTest,
440 IsWallclockTimeGreaterThanSignalsTriggerReevaluation) {
441 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
Alex Deymo41a75a72014-04-15 15:36:22 -0700442 fake_clock_.GetWallclockTime() + TimeDelta::FromSeconds(1)));
443
Gilad Arnolda65fced2014-07-23 09:01:31 -0700444 // The "false" from IsWallclockTimeGreaterThan means that's not that timestamp
445 // yet, so this should schedule a callback for when that happens.
Amin Hassani2e4eda52019-01-07 14:01:17 -0800446 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(
447#if BASE_VER < 576279
448 Bind(&base::DoNothing)
449#else
450 base::DoNothing()
451#endif
452 ));
Alex Deymo41a75a72014-04-15 15:36:22 -0700453}
454
Gilad Arnolda65fced2014-07-23 09:01:31 -0700455TEST_F(UmEvaluationContextTest,
456 IsMonotonicTimeGreaterThanSignalsTriggerReevaluation) {
457 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
458 fake_clock_.GetMonotonicTime() + TimeDelta::FromSeconds(1)));
459
460 // The "false" from IsMonotonicTimeGreaterThan means that's not that timestamp
461 // yet, so this should schedule a callback for when that happens.
Amin Hassani2e4eda52019-01-07 14:01:17 -0800462 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(
463#if BASE_VER < 576279
464 Bind(&base::DoNothing)
465#else
466 base::DoNothing()
467#endif
468 ));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700469}
470
471TEST_F(UmEvaluationContextTest,
472 IsWallclockTimeGreaterThanDoesntRecordPastTimestamps) {
473 // IsWallclockTimeGreaterThan() should ignore timestamps on the past for
474 // reevaluation.
475 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
Alex Deymo41a75a72014-04-15 15:36:22 -0700476 fake_clock_.GetWallclockTime() - TimeDelta::FromSeconds(20)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700477 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
Alex Deymo41a75a72014-04-15 15:36:22 -0700478 fake_clock_.GetWallclockTime() - TimeDelta::FromSeconds(1)));
479
480 // Callback should not be scheduled.
Amin Hassani2e4eda52019-01-07 14:01:17 -0800481 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(
482#if BASE_VER < 576279
483 Bind(&base::DoNothing)
484#else
485 base::DoNothing()
486#endif
487 ));
Alex Deymo41a75a72014-04-15 15:36:22 -0700488}
489
Gilad Arnolda65fced2014-07-23 09:01:31 -0700490TEST_F(UmEvaluationContextTest,
491 IsMonotonicTimeGreaterThanDoesntRecordPastTimestamps) {
492 // IsMonotonicTimeGreaterThan() should ignore timestamps on the past for
493 // reevaluation.
494 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
495 fake_clock_.GetMonotonicTime() - TimeDelta::FromSeconds(20)));
496 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
497 fake_clock_.GetMonotonicTime() - TimeDelta::FromSeconds(1)));
498
499 // Callback should not be scheduled.
Amin Hassani2e4eda52019-01-07 14:01:17 -0800500 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(
501#if BASE_VER < 576279
502 Bind(&base::DoNothing)
503#else
504 base::DoNothing()
505#endif
506 ));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700507}
508
Alex Deymo63784a52014-05-28 10:46:14 -0700509TEST_F(UmEvaluationContextTest, DumpContext) {
David Zeuthenc1490282014-04-29 16:25:03 -0700510 // |fail_var_| yield "(no value)" since it is unset.
511 eval_ctx_->GetValue(&fail_var_);
512
513 // Check that this is included.
514 fake_int_var_.reset(new int(42));
515 eval_ctx_->GetValue(&fake_int_var_);
516
517 // Check that double-quotes are escaped properly.
518 fake_poll_var_.reset(new string("Hello \"world\"!"));
519 eval_ctx_->GetValue(&fake_poll_var_);
520
521 // Note that the variables are printed in alphabetical order. Also
Gilad Arnolda65fced2014-07-23 09:01:31 -0700522 // see UmEvaluationContextText::SetUp() where the values used for
523 // |evaluation_start_{monotonic,wallclock| are set.
David Zeuthenc1490282014-04-29 16:25:03 -0700524 EXPECT_EQ("{\n"
Gilad Arnolda65fced2014-07-23 09:01:31 -0700525 " \"evaluation_start_monotonic\": \"4/22/2009 19:25:00 GMT\",\n"
526 " \"evaluation_start_wallclock\": \"3/2/2006 1:23:45 GMT\",\n"
David Zeuthenc1490282014-04-29 16:25:03 -0700527 " \"variables\": {\n"
528 " \"fail_var\": \"(no value)\",\n"
529 " \"fake_int\": \"42\",\n"
530 " \"fake_poll\": \"Hello \\\"world\\\"!\"\n"
531 " }\n"
Gilad Arnold6e5ab5c2014-06-23 15:13:56 -0700532 "}",
David Zeuthenc1490282014-04-29 16:25:03 -0700533 eval_ctx_->DumpContext());
534}
535
Alex Deymo63784a52014-05-28 10:46:14 -0700536} // namespace chromeos_update_manager