blob: a50defd30cc0cf52a1cf515037835512e57d3719 [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;
Amin Hassania2c8b922019-08-14 19:41:03 -070042using std::shared_ptr;
Alex Deymo23949d42014-02-05 15:20:59 -080043using std::string;
Ben Chan02f7c1d2014-10-18 15:18:02 -070044using std::unique_ptr;
Amin Hassani4b717432019-01-14 16:24:20 -080045using testing::_;
Alex Deymo41a75a72014-04-15 15:36:22 -070046using testing::Return;
47using testing::StrictMock;
Alex Deymo23949d42014-02-05 15:20:59 -080048
Gilad Arnoldfb794f42014-07-01 15:36:31 -070049namespace chromeos_update_manager {
50
Alex Deymo53556ec2014-03-17 10:05:57 -070051namespace {
52
Alex Deymo53556ec2014-03-17 10:05:57 -070053// 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
Amin Hassani4b717432019-01-14 16:24:20 -080062template <typename T>
Amin Hassania2c8b922019-08-14 19:41:03 -070063void ReadVar(shared_ptr<EvaluationContext> ec, Variable<T>* var) {
Gilad Arnoldfb794f42014-07-01 15:36:31 -070064 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|.
Amin Hassani4b717432019-01-14 16:24:20 -080069void EvaluateRepeatedly(Closure evaluation,
Amin Hassania2c8b922019-08-14 19:41:03 -070070 shared_ptr<EvaluationContext> ec,
Amin Hassani4b717432019-01-14 16:24:20 -080071 int* count_p,
72 bool* done_p) {
Gilad Arnoldfb794f42014-07-01 15:36:31 -070073 evaluation.Run();
74
75 // Schedule reevaluation if needed.
76 if (*count_p > 0) {
77 Closure closure = Bind(EvaluateRepeatedly, evaluation, ec, count_p, done_p);
78 ASSERT_TRUE(ec->RunOnValueChangeOrTimeout(closure))
79 << "Failed to schedule reevaluation, count_p=" << *count_p;
80 (*count_p)--;
81 } else {
82 *done_p = true;
83 }
84}
85
86} // namespace
Alex Deymo23949d42014-02-05 15:20:59 -080087
Alex Deymo63784a52014-05-28 10:46:14 -070088class UmEvaluationContextTest : public ::testing::Test {
Alex Deymo23949d42014-02-05 15:20:59 -080089 protected:
Alex Deymo610277e2014-11-11 21:18:11 -080090 void SetUp() override {
Alex Deymo509dd532015-06-10 14:11:05 -070091 loop_.SetAsCurrent();
Gilad Arnolda65fced2014-07-23 09:01:31 -070092 // Apr 22, 2009 19:25:00 UTC (this is a random reference point).
93 fake_clock_.SetMonotonicTime(Time::FromTimeT(1240428300));
94 // Mar 2, 2006 1:23:45 UTC.
David Zeuthenc1490282014-04-29 16:25:03 -070095 fake_clock_.SetWallclockTime(Time::FromTimeT(1141262625));
Amin Hassania2c8b922019-08-14 19:41:03 -070096 eval_ctx_.reset(new EvaluationContext(
Amin Hassani4b717432019-01-14 16:24:20 -080097 &fake_clock_,
98 default_timeout_,
99 default_timeout_,
Amin Hassania2c8b922019-08-14 19:41:03 -0700100 unique_ptr<base::Callback<void(EvaluationContext*)>>(nullptr)));
Alex Deymo23949d42014-02-05 15:20:59 -0800101 }
102
Alex Deymo610277e2014-11-11 21:18:11 -0800103 void TearDown() override {
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700104 // Ensure that the evaluation context did not leak and is actually being
105 // destroyed.
106 if (eval_ctx_) {
107 base::WeakPtr<EvaluationContext> eval_ctx_weak_alias =
108 eval_ctx_->weak_ptr_factory_.GetWeakPtr();
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700109 ASSERT_NE(nullptr, eval_ctx_weak_alias.get());
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700110 eval_ctx_ = nullptr;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700111 EXPECT_EQ(nullptr, eval_ctx_weak_alias.get())
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700112 << "The evaluation context was not destroyed! This is likely a bug "
113 "in how the test was written, look for leaking handles to the EC, "
114 "possibly through closure objects.";
115 }
116
Alex Deymo53556ec2014-03-17 10:05:57 -0700117 // Check that the evaluation context removed all the observers.
118 EXPECT_TRUE(fake_int_var_.observer_list_.empty());
119 EXPECT_TRUE(fake_async_var_.observer_list_.empty());
120 EXPECT_TRUE(fake_const_var_.observer_list_.empty());
121 EXPECT_TRUE(fake_poll_var_.observer_list_.empty());
Alex Deymo509dd532015-06-10 14:11:05 -0700122
123 EXPECT_FALSE(loop_.PendingTasks());
Alex Deymo53556ec2014-03-17 10:05:57 -0700124 }
125
Alex Deymof329b932014-10-30 01:37:48 -0700126 TimeDelta default_timeout_ = TimeDelta::FromSeconds(5);
Alex Deymo41a75a72014-04-15 15:36:22 -0700127
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700128 brillo::FakeMessageLoop loop_{nullptr};
Alex Deymo41a75a72014-04-15 15:36:22 -0700129 FakeClock fake_clock_;
Amin Hassania2c8b922019-08-14 19:41:03 -0700130 shared_ptr<EvaluationContext> eval_ctx_;
Alex Deymo53556ec2014-03-17 10:05:57 -0700131
132 // FakeVariables used for testing the EvaluationContext. These are required
133 // here to prevent them from going away *before* the EvaluationContext under
134 // test does, which keeps a reference to them.
David Zeuthenc1490282014-04-29 16:25:03 -0700135 FakeVariable<bool> fail_var_ = {"fail_var", kVariableModePoll};
Alex Deymo53556ec2014-03-17 10:05:57 -0700136 FakeVariable<int> fake_int_var_ = {"fake_int", kVariableModePoll};
137 FakeVariable<string> fake_async_var_ = {"fake_async", kVariableModeAsync};
138 FakeVariable<string> fake_const_var_ = {"fake_const", kVariableModeConst};
139 FakeVariable<string> fake_poll_var_ = {"fake_poll",
140 TimeDelta::FromSeconds(1)};
Amin Hassani4b717432019-01-14 16:24:20 -0800141 StrictMock<MockVariable<string>> mock_var_async_{"mock_var_async",
142 kVariableModeAsync};
143 StrictMock<MockVariable<string>> mock_var_poll_{"mock_var_poll",
144 kVariableModePoll};
Alex Deymo23949d42014-02-05 15:20:59 -0800145};
146
Alex Deymo63784a52014-05-28 10:46:14 -0700147TEST_F(UmEvaluationContextTest, GetValueFails) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700148 // FakeVariable is initialized as returning null.
149 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&fake_int_var_));
Alex Deymo23949d42014-02-05 15:20:59 -0800150}
151
Alex Deymo63784a52014-05-28 10:46:14 -0700152TEST_F(UmEvaluationContextTest, GetValueFailsWithInvalidVar) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700153 EXPECT_EQ(nullptr, eval_ctx_->GetValue(static_cast<Variable<int>*>(nullptr)));
Alex Deymo23949d42014-02-05 15:20:59 -0800154}
155
Alex Deymo63784a52014-05-28 10:46:14 -0700156TEST_F(UmEvaluationContextTest, GetValueReturns) {
Alex Deymo23949d42014-02-05 15:20:59 -0800157 const int* p_fake_int;
158
159 fake_int_var_.reset(new int(42));
160 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700161 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800162 EXPECT_EQ(42, *p_fake_int);
163}
164
Alex Deymo63784a52014-05-28 10:46:14 -0700165TEST_F(UmEvaluationContextTest, GetValueCached) {
Alex Deymo23949d42014-02-05 15:20:59 -0800166 const int* p_fake_int;
167
168 fake_int_var_.reset(new int(42));
169 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
170
171 // Check that if the variable changes, the EvaluationContext keeps returning
172 // the cached value.
173 fake_int_var_.reset(new int(5));
174
175 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700176 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800177 EXPECT_EQ(42, *p_fake_int);
178}
179
Alex Deymo63784a52014-05-28 10:46:14 -0700180TEST_F(UmEvaluationContextTest, GetValueCachesNull) {
Alex Deymo23949d42014-02-05 15:20:59 -0800181 const int* p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700182 EXPECT_EQ(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800183
184 fake_int_var_.reset(new int(42));
Alex Deymocc0e5cf2014-04-23 20:20:11 -0700185 // A second attempt to read the variable should not work because this
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700186 // EvaluationContext already got a null value.
Alex Deymo23949d42014-02-05 15:20:59 -0800187 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700188 EXPECT_EQ(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800189}
190
Alex Deymo63784a52014-05-28 10:46:14 -0700191TEST_F(UmEvaluationContextTest, GetValueMixedTypes) {
Alex Deymo23949d42014-02-05 15:20:59 -0800192 const int* p_fake_int;
193 const string* p_fake_string;
194
195 fake_int_var_.reset(new int(42));
Alex Deymo53556ec2014-03-17 10:05:57 -0700196 fake_poll_var_.reset(new string("Hello world!"));
Alex Deymo23949d42014-02-05 15:20:59 -0800197 // Check that the EvaluationContext can handle multiple Variable types. This
198 // is mostly a compile-time check due to the template nature of this method.
199 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Deymo53556ec2014-03-17 10:05:57 -0700200 p_fake_string = eval_ctx_->GetValue(&fake_poll_var_);
Alex Deymo23949d42014-02-05 15:20:59 -0800201
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700202 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800203 EXPECT_EQ(42, *p_fake_int);
204
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700205 ASSERT_NE(nullptr, p_fake_string);
Alex Deymo23949d42014-02-05 15:20:59 -0800206 EXPECT_EQ("Hello world!", *p_fake_string);
207}
208
Alex Deymo53556ec2014-03-17 10:05:57 -0700209// Test that we don't schedule an event if there's no variable to wait for.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700210TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutWithoutVariables) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700211 fake_const_var_.reset(new string("Hello world!"));
212 EXPECT_EQ(*eval_ctx_->GetValue(&fake_const_var_), "Hello world!");
213
Amin Hassani2e4eda52019-01-07 14:01:17 -0800214#if BASE_VER < 576279
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700215 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&base::DoNothing)));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800216#else
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700217 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800218#endif
Alex Deymo53556ec2014-03-17 10:05:57 -0700219}
220
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700221// Test that reevaluation occurs when an async variable it depends on changes.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700222TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutWithVariables) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700223 fake_async_var_.reset(new string("Async value"));
224 eval_ctx_->GetValue(&fake_async_var_);
225
226 bool value = false;
227 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
228 // Check that the scheduled callback isn't run until we signal a ValueChaged.
Alex Deymo509dd532015-06-10 14:11:05 -0700229 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
Alex Deymo53556ec2014-03-17 10:05:57 -0700230 EXPECT_FALSE(value);
231
232 fake_async_var_.NotifyValueChanged();
233 EXPECT_FALSE(value);
234 // Ensure that the scheduled callback isn't run until we are back on the main
235 // loop.
Alex Deymo509dd532015-06-10 14:11:05 -0700236 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
Alex Deymo53556ec2014-03-17 10:05:57 -0700237 EXPECT_TRUE(value);
238}
239
240// Test that we don't re-schedule the events if we are attending one.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700241TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutCalledTwice) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700242 fake_async_var_.reset(new string("Async value"));
243 eval_ctx_->GetValue(&fake_async_var_);
244
245 bool value = false;
246 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
247 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
248
249 // The scheduled event should still work.
250 fake_async_var_.NotifyValueChanged();
Alex Deymo509dd532015-06-10 14:11:05 -0700251 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
Alex Deymo53556ec2014-03-17 10:05:57 -0700252 EXPECT_TRUE(value);
253}
254
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700255// Test that reevaluation occurs when a polling timeout fires.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700256TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutRunsFromTimeout) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700257 fake_poll_var_.reset(new string("Polled value"));
258 eval_ctx_->GetValue(&fake_poll_var_);
259
260 bool value = false;
261 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
262 // Check that the scheduled callback isn't run until the timeout occurs.
Alex Deymo509dd532015-06-10 14:11:05 -0700263 MessageLoopRunMaxIterations(MessageLoop::current(), 10);
Alex Deymo53556ec2014-03-17 10:05:57 -0700264 EXPECT_FALSE(value);
Alex Deymo509dd532015-06-10 14:11:05 -0700265 MessageLoopRunUntil(MessageLoop::current(),
266 TimeDelta::FromSeconds(10),
267 Bind(&GetBoolean, &value));
Alex Deymo53556ec2014-03-17 10:05:57 -0700268 EXPECT_TRUE(value);
269}
270
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700271// Test that callback is called when evaluation context expires, and that it
Gilad Arnoldfd45a732014-08-07 15:53:46 -0700272// cannot be used again unless the expiration deadline is reset.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700273TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutExpires) {
274 fake_async_var_.reset(new string("Async value"));
275 eval_ctx_->GetValue(&fake_async_var_);
276
277 bool value = false;
278 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
279 // Check that the scheduled callback isn't run until the timeout occurs.
Alex Deymo509dd532015-06-10 14:11:05 -0700280 MessageLoopRunMaxIterations(MessageLoop::current(), 10);
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700281 EXPECT_FALSE(value);
Alex Deymo509dd532015-06-10 14:11:05 -0700282 MessageLoopRunUntil(MessageLoop::current(),
283 TimeDelta::FromSeconds(10),
284 Bind(&GetBoolean, &value));
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700285 EXPECT_TRUE(value);
286
287 // Ensure that we cannot reschedule an evaluation.
Amin Hassani2e4eda52019-01-07 14:01:17 -0800288#if BASE_VER < 576279
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700289 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&base::DoNothing)));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800290#else
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700291 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800292#endif
Gilad Arnoldfd45a732014-08-07 15:53:46 -0700293
294 // Ensure that we can reschedule an evaluation after resetting expiration.
295 eval_ctx_->ResetExpiration();
Amin Hassani2e4eda52019-01-07 14:01:17 -0800296#if BASE_VER < 576279
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700297 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&base::DoNothing)));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800298#else
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700299 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800300#endif
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700301}
302
303// Test that we clear the events when destroying the EvaluationContext.
304TEST_F(UmEvaluationContextTest, RemoveObserversAndTimeoutTest) {
305 fake_async_var_.reset(new string("Async value"));
306 eval_ctx_->GetValue(&fake_async_var_);
307
308 bool value = false;
309 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
310 eval_ctx_ = nullptr;
311
312 // This should not trigger the callback since the EvaluationContext waiting
313 // for it is gone, and it should have remove all its observers.
314 fake_async_var_.NotifyValueChanged();
Alex Deymo509dd532015-06-10 14:11:05 -0700315 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700316 EXPECT_FALSE(value);
317}
318
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700319// Scheduling two reevaluations from the callback should succeed.
320TEST_F(UmEvaluationContextTest,
321 RunOnValueChangeOrTimeoutReevaluatesRepeatedly) {
322 fake_poll_var_.reset(new string("Polled value"));
323 Closure evaluation = Bind(ReadVar<string>, eval_ctx_, &fake_poll_var_);
324 int num_reevaluations = 2;
325 bool done = false;
326
327 // Run the evaluation once.
328 evaluation.Run();
329
330 // Schedule repeated reevaluations.
Amin Hassani4b717432019-01-14 16:24:20 -0800331 Closure closure = Bind(
332 EvaluateRepeatedly, evaluation, eval_ctx_, &num_reevaluations, &done);
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700333 ASSERT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(closure));
Alex Deymo509dd532015-06-10 14:11:05 -0700334 MessageLoopRunUntil(MessageLoop::current(),
335 TimeDelta::FromSeconds(10),
336 Bind(&GetBoolean, &done));
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700337 EXPECT_EQ(0, num_reevaluations);
338}
339
Alex Deymodb799532014-03-21 13:00:00 -0700340// Test that we can delete the EvaluationContext while having pending events.
Alex Deymo63784a52014-05-28 10:46:14 -0700341TEST_F(UmEvaluationContextTest, ObjectDeletedWithPendingEventsTest) {
Alex Deymodb799532014-03-21 13:00:00 -0700342 fake_async_var_.reset(new string("Async value"));
343 fake_poll_var_.reset(new string("Polled value"));
344 eval_ctx_->GetValue(&fake_async_var_);
345 eval_ctx_->GetValue(&fake_poll_var_);
Amin Hassani2e4eda52019-01-07 14:01:17 -0800346#if BASE_VER < 576279
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700347 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&base::DoNothing)));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800348#else
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700349 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800350#endif
Alex Deymodb799532014-03-21 13:00:00 -0700351 // TearDown() checks for leaked observers on this async_variable, which means
352 // that our object is still alive after removing its reference.
353}
354
355// Test that timed events fired after removal of the EvaluationContext don't
356// crash.
Alex Deymo63784a52014-05-28 10:46:14 -0700357TEST_F(UmEvaluationContextTest, TimeoutEventAfterDeleteTest) {
Alex Deymo0bb23412015-06-19 00:04:46 -0700358 FakeVariable<string> fake_short_poll_var = {"fake_short_poll",
359 TimeDelta::FromSeconds(1)};
Alex Deymodb799532014-03-21 13:00:00 -0700360 fake_short_poll_var.reset(new string("Polled value"));
361 eval_ctx_->GetValue(&fake_short_poll_var);
362 bool value = false;
363 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
364 // Remove the last reference to the EvaluationContext and run the loop for
Alex Deymo0bb23412015-06-19 00:04:46 -0700365 // 10 seconds to give time to the main loop to trigger the timeout Event (of 1
366 // second). Our callback should not be called because the EvaluationContext
Alex Deymodb799532014-03-21 13:00:00 -0700367 // was removed before the timeout event is attended.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700368 eval_ctx_ = nullptr;
Alex Deymo509dd532015-06-10 14:11:05 -0700369 MessageLoopRunUntil(MessageLoop::current(),
370 TimeDelta::FromSeconds(10),
371 Bind(&GetBoolean, &value));
Alex Deymodb799532014-03-21 13:00:00 -0700372 EXPECT_FALSE(value);
373}
374
Alex Deymo63784a52014-05-28 10:46:14 -0700375TEST_F(UmEvaluationContextTest, DefaultTimeout) {
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700376 // Test that the evaluation timeout calculation uses the default timeout on
377 // setup.
Alex Deymo41a75a72014-04-15 15:36:22 -0700378 EXPECT_CALL(mock_var_async_, GetValue(default_timeout_, _))
379 .WillOnce(Return(nullptr));
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700380 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&mock_var_async_));
Alex Deymo41a75a72014-04-15 15:36:22 -0700381}
382
Alex Deymo63784a52014-05-28 10:46:14 -0700383TEST_F(UmEvaluationContextTest, TimeoutUpdatesWithMonotonicTime) {
Amin Hassani4b717432019-01-14 16:24:20 -0800384 fake_clock_.SetMonotonicTime(fake_clock_.GetMonotonicTime() +
385 TimeDelta::FromSeconds(1));
Alex Deymo41a75a72014-04-15 15:36:22 -0700386
387 TimeDelta timeout = default_timeout_ - TimeDelta::FromSeconds(1);
388
Amin Hassani4b717432019-01-14 16:24:20 -0800389 EXPECT_CALL(mock_var_async_, GetValue(timeout, _)).WillOnce(Return(nullptr));
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700390 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&mock_var_async_));
Alex Deymo41a75a72014-04-15 15:36:22 -0700391}
392
Gilad Arnolda65fced2014-07-23 09:01:31 -0700393TEST_F(UmEvaluationContextTest, ResetEvaluationResetsTimesWallclock) {
Alex Deymof329b932014-10-30 01:37:48 -0700394 Time cur_time = fake_clock_.GetWallclockTime();
Alex Deymo41a75a72014-04-15 15:36:22 -0700395 // Advance the time on the clock but don't call ResetEvaluation yet.
396 fake_clock_.SetWallclockTime(cur_time + TimeDelta::FromSeconds(4));
397
Amin Hassani4b717432019-01-14 16:24:20 -0800398 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time -
399 TimeDelta::FromSeconds(1)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700400 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time));
401 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
Amin Hassani4b717432019-01-14 16:24:20 -0800402 cur_time + TimeDelta::FromSeconds(1)));
Alex Deymo41a75a72014-04-15 15:36:22 -0700403 // Call ResetEvaluation now, which should use the new evaluation time.
404 eval_ctx_->ResetEvaluation();
405
406 cur_time = fake_clock_.GetWallclockTime();
Amin Hassani4b717432019-01-14 16:24:20 -0800407 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time -
408 TimeDelta::FromSeconds(1)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700409 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time));
410 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
Amin Hassani4b717432019-01-14 16:24:20 -0800411 cur_time + TimeDelta::FromSeconds(1)));
Alex Deymo41a75a72014-04-15 15:36:22 -0700412}
413
Gilad Arnolda65fced2014-07-23 09:01:31 -0700414TEST_F(UmEvaluationContextTest, ResetEvaluationResetsTimesMonotonic) {
Alex Deymof329b932014-10-30 01:37:48 -0700415 Time cur_time = fake_clock_.GetMonotonicTime();
Gilad Arnolda65fced2014-07-23 09:01:31 -0700416 // Advance the time on the clock but don't call ResetEvaluation yet.
417 fake_clock_.SetMonotonicTime(cur_time + TimeDelta::FromSeconds(4));
418
Amin Hassani4b717432019-01-14 16:24:20 -0800419 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time -
420 TimeDelta::FromSeconds(1)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700421 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time));
422 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
Amin Hassani4b717432019-01-14 16:24:20 -0800423 cur_time + TimeDelta::FromSeconds(1)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700424 // Call ResetEvaluation now, which should use the new evaluation time.
425 eval_ctx_->ResetEvaluation();
426
427 cur_time = fake_clock_.GetMonotonicTime();
Amin Hassani4b717432019-01-14 16:24:20 -0800428 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time -
429 TimeDelta::FromSeconds(1)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700430 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time));
431 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
Amin Hassani4b717432019-01-14 16:24:20 -0800432 cur_time + TimeDelta::FromSeconds(1)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700433}
434
435TEST_F(UmEvaluationContextTest,
436 IsWallclockTimeGreaterThanSignalsTriggerReevaluation) {
437 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
Alex Deymo41a75a72014-04-15 15:36:22 -0700438 fake_clock_.GetWallclockTime() + TimeDelta::FromSeconds(1)));
439
Gilad Arnolda65fced2014-07-23 09:01:31 -0700440 // The "false" from IsWallclockTimeGreaterThan means that's not that timestamp
441 // yet, so this should schedule a callback for when that happens.
Amin Hassani2e4eda52019-01-07 14:01:17 -0800442#if BASE_VER < 576279
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700443 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&base::DoNothing)));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800444#else
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700445 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800446#endif
Alex Deymo41a75a72014-04-15 15:36:22 -0700447}
448
Gilad Arnolda65fced2014-07-23 09:01:31 -0700449TEST_F(UmEvaluationContextTest,
450 IsMonotonicTimeGreaterThanSignalsTriggerReevaluation) {
451 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
452 fake_clock_.GetMonotonicTime() + TimeDelta::FromSeconds(1)));
453
454 // The "false" from IsMonotonicTimeGreaterThan means that's not that timestamp
455 // yet, so this should schedule a callback for when that happens.
Amin Hassani2e4eda52019-01-07 14:01:17 -0800456#if BASE_VER < 576279
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700457 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&base::DoNothing)));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800458#else
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700459 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800460#endif
Gilad Arnolda65fced2014-07-23 09:01:31 -0700461}
462
463TEST_F(UmEvaluationContextTest,
464 IsWallclockTimeGreaterThanDoesntRecordPastTimestamps) {
465 // IsWallclockTimeGreaterThan() should ignore timestamps on the past for
466 // reevaluation.
467 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
Alex Deymo41a75a72014-04-15 15:36:22 -0700468 fake_clock_.GetWallclockTime() - TimeDelta::FromSeconds(20)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700469 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
Alex Deymo41a75a72014-04-15 15:36:22 -0700470 fake_clock_.GetWallclockTime() - TimeDelta::FromSeconds(1)));
471
472 // Callback should not be scheduled.
Amin Hassani2e4eda52019-01-07 14:01:17 -0800473#if BASE_VER < 576279
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700474 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&base::DoNothing)));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800475#else
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700476 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800477#endif
Alex Deymo41a75a72014-04-15 15:36:22 -0700478}
479
Gilad Arnolda65fced2014-07-23 09:01:31 -0700480TEST_F(UmEvaluationContextTest,
481 IsMonotonicTimeGreaterThanDoesntRecordPastTimestamps) {
482 // IsMonotonicTimeGreaterThan() should ignore timestamps on the past for
483 // reevaluation.
484 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
485 fake_clock_.GetMonotonicTime() - TimeDelta::FromSeconds(20)));
486 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
487 fake_clock_.GetMonotonicTime() - TimeDelta::FromSeconds(1)));
488
489 // Callback should not be scheduled.
Amin Hassani2e4eda52019-01-07 14:01:17 -0800490#if BASE_VER < 576279
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700491 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&base::DoNothing)));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800492#else
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700493 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800494#endif
Gilad Arnolda65fced2014-07-23 09:01:31 -0700495}
496
Alex Deymo63784a52014-05-28 10:46:14 -0700497TEST_F(UmEvaluationContextTest, DumpContext) {
David Zeuthenc1490282014-04-29 16:25:03 -0700498 // |fail_var_| yield "(no value)" since it is unset.
499 eval_ctx_->GetValue(&fail_var_);
500
501 // Check that this is included.
502 fake_int_var_.reset(new int(42));
503 eval_ctx_->GetValue(&fake_int_var_);
504
505 // Check that double-quotes are escaped properly.
506 fake_poll_var_.reset(new string("Hello \"world\"!"));
507 eval_ctx_->GetValue(&fake_poll_var_);
508
509 // Note that the variables are printed in alphabetical order. Also
Gilad Arnolda65fced2014-07-23 09:01:31 -0700510 // see UmEvaluationContextText::SetUp() where the values used for
511 // |evaluation_start_{monotonic,wallclock| are set.
Amin Hassani4b717432019-01-14 16:24:20 -0800512 EXPECT_EQ(
513 "{\n"
514 " \"evaluation_start_monotonic\": \"4/22/2009 19:25:00 GMT\",\n"
515 " \"evaluation_start_wallclock\": \"3/2/2006 1:23:45 GMT\",\n"
516 " \"variables\": {\n"
517 " \"fail_var\": \"(no value)\",\n"
518 " \"fake_int\": \"42\",\n"
519 " \"fake_poll\": \"Hello \\\"world\\\"!\"\n"
520 " }\n"
521 "}",
522 eval_ctx_->DumpContext());
David Zeuthenc1490282014-04-29 16:25:03 -0700523}
524
Alex Deymo63784a52014-05-28 10:46:14 -0700525} // namespace chromeos_update_manager