blob: fdb408b8334c73bfbd99333b99634d6ab4fe058c [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"
Amin Hassani0468a762020-11-17 23:53:48 -080029#include "update_engine/cros/fake_system_state.h"
Alex Deymo63784a52014-05-28 10:46:14 -070030#include "update_engine/update_manager/fake_variable.h"
31#include "update_engine/update_manager/generic_variables.h"
32#include "update_engine/update_manager/mock_variable.h"
33#include "update_engine/update_manager/umtest_utils.h"
Alex Deymo23949d42014-02-05 15:20:59 -080034
Alex Deymo53556ec2014-03-17 10:05:57 -070035using base::Bind;
Gilad Arnoldfb794f42014-07-01 15:36:31 -070036using base::Closure;
Alex Deymo41a75a72014-04-15 15:36:22 -070037using base::Time;
Alex Deymo53556ec2014-03-17 10:05:57 -070038using base::TimeDelta;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070039using brillo::MessageLoop;
40using brillo::MessageLoopRunMaxIterations;
41using brillo::MessageLoopRunUntil;
Alex Deymo41a75a72014-04-15 15:36:22 -070042using chromeos_update_engine::FakeClock;
Amin Hassani0468a762020-11-17 23:53:48 -080043using chromeos_update_engine::FakeSystemState;
Amin Hassania2c8b922019-08-14 19:41:03 -070044using std::shared_ptr;
Alex Deymo23949d42014-02-05 15:20:59 -080045using std::string;
Ben Chan02f7c1d2014-10-18 15:18:02 -070046using std::unique_ptr;
Amin Hassani4b717432019-01-14 16:24:20 -080047using testing::_;
Alex Deymo41a75a72014-04-15 15:36:22 -070048using testing::Return;
49using testing::StrictMock;
Alex Deymo23949d42014-02-05 15:20:59 -080050
Gilad Arnoldfb794f42014-07-01 15:36:31 -070051namespace chromeos_update_manager {
52
Alex Deymo53556ec2014-03-17 10:05:57 -070053namespace {
54
Alex Deymo53556ec2014-03-17 10:05:57 -070055// Sets the value of the passed pointer to true.
56void SetTrue(bool* value) {
57 *value = true;
58}
59
60bool GetBoolean(bool* value) {
61 return *value;
62}
63
Amin Hassani4b717432019-01-14 16:24:20 -080064template <typename T>
Amin Hassania2c8b922019-08-14 19:41:03 -070065void ReadVar(shared_ptr<EvaluationContext> ec, Variable<T>* var) {
Gilad Arnoldfb794f42014-07-01 15:36:31 -070066 ec->GetValue(var);
67}
Alex Deymo53556ec2014-03-17 10:05:57 -070068
Gilad Arnoldfb794f42014-07-01 15:36:31 -070069// Runs |evaluation|; if the value pointed by |count_p| is greater than zero,
70// decrement it and schedule a reevaluation; otherwise, writes true to |done_p|.
Amin Hassani4b717432019-01-14 16:24:20 -080071void EvaluateRepeatedly(Closure evaluation,
Amin Hassania2c8b922019-08-14 19:41:03 -070072 shared_ptr<EvaluationContext> ec,
Amin Hassani4b717432019-01-14 16:24:20 -080073 int* count_p,
74 bool* done_p) {
Gilad Arnoldfb794f42014-07-01 15:36:31 -070075 evaluation.Run();
76
77 // Schedule reevaluation if needed.
78 if (*count_p > 0) {
79 Closure closure = Bind(EvaluateRepeatedly, evaluation, ec, count_p, done_p);
80 ASSERT_TRUE(ec->RunOnValueChangeOrTimeout(closure))
81 << "Failed to schedule reevaluation, count_p=" << *count_p;
82 (*count_p)--;
83 } else {
84 *done_p = true;
85 }
86}
87
88} // namespace
Alex Deymo23949d42014-02-05 15:20:59 -080089
Alex Deymo63784a52014-05-28 10:46:14 -070090class UmEvaluationContextTest : public ::testing::Test {
Alex Deymo23949d42014-02-05 15:20:59 -080091 protected:
Alex Deymo610277e2014-11-11 21:18:11 -080092 void SetUp() override {
Amin Hassani0468a762020-11-17 23:53:48 -080093 FakeSystemState::CreateInstance();
94 fake_clock_ = FakeSystemState::Get()->fake_clock();
Alex Deymo509dd532015-06-10 14:11:05 -070095 loop_.SetAsCurrent();
Gilad Arnolda65fced2014-07-23 09:01:31 -070096 // Apr 22, 2009 19:25:00 UTC (this is a random reference point).
Amin Hassani0468a762020-11-17 23:53:48 -080097 fake_clock_->SetMonotonicTime(Time::FromTimeT(1240428300));
Gilad Arnolda65fced2014-07-23 09:01:31 -070098 // Mar 2, 2006 1:23:45 UTC.
Amin Hassani0468a762020-11-17 23:53:48 -080099 fake_clock_->SetWallclockTime(Time::FromTimeT(1141262625));
Amin Hassania2c8b922019-08-14 19:41:03 -0700100 eval_ctx_.reset(new EvaluationContext(
Amin Hassani4b717432019-01-14 16:24:20 -0800101 default_timeout_,
102 default_timeout_,
Amin Hassania2c8b922019-08-14 19:41:03 -0700103 unique_ptr<base::Callback<void(EvaluationContext*)>>(nullptr)));
Alex Deymo23949d42014-02-05 15:20:59 -0800104 }
105
Alex Deymo610277e2014-11-11 21:18:11 -0800106 void TearDown() override {
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700107 // Ensure that the evaluation context did not leak and is actually being
108 // destroyed.
109 if (eval_ctx_) {
110 base::WeakPtr<EvaluationContext> eval_ctx_weak_alias =
111 eval_ctx_->weak_ptr_factory_.GetWeakPtr();
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700112 ASSERT_NE(nullptr, eval_ctx_weak_alias.get());
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700113 eval_ctx_ = nullptr;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700114 EXPECT_EQ(nullptr, eval_ctx_weak_alias.get())
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700115 << "The evaluation context was not destroyed! This is likely a bug "
116 "in how the test was written, look for leaking handles to the EC, "
117 "possibly through closure objects.";
118 }
119
Alex Deymo53556ec2014-03-17 10:05:57 -0700120 // Check that the evaluation context removed all the observers.
121 EXPECT_TRUE(fake_int_var_.observer_list_.empty());
122 EXPECT_TRUE(fake_async_var_.observer_list_.empty());
123 EXPECT_TRUE(fake_const_var_.observer_list_.empty());
124 EXPECT_TRUE(fake_poll_var_.observer_list_.empty());
Alex Deymo509dd532015-06-10 14:11:05 -0700125
126 EXPECT_FALSE(loop_.PendingTasks());
Alex Deymo53556ec2014-03-17 10:05:57 -0700127 }
128
Alex Deymof329b932014-10-30 01:37:48 -0700129 TimeDelta default_timeout_ = TimeDelta::FromSeconds(5);
Alex Deymo41a75a72014-04-15 15:36:22 -0700130
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700131 brillo::FakeMessageLoop loop_{nullptr};
Amin Hassani0468a762020-11-17 23:53:48 -0800132 FakeClock* fake_clock_;
Amin Hassania2c8b922019-08-14 19:41:03 -0700133 shared_ptr<EvaluationContext> eval_ctx_;
Alex Deymo53556ec2014-03-17 10:05:57 -0700134
135 // FakeVariables used for testing the EvaluationContext. These are required
136 // here to prevent them from going away *before* the EvaluationContext under
137 // test does, which keeps a reference to them.
David Zeuthenc1490282014-04-29 16:25:03 -0700138 FakeVariable<bool> fail_var_ = {"fail_var", kVariableModePoll};
Alex Deymo53556ec2014-03-17 10:05:57 -0700139 FakeVariable<int> fake_int_var_ = {"fake_int", kVariableModePoll};
140 FakeVariable<string> fake_async_var_ = {"fake_async", kVariableModeAsync};
141 FakeVariable<string> fake_const_var_ = {"fake_const", kVariableModeConst};
142 FakeVariable<string> fake_poll_var_ = {"fake_poll",
143 TimeDelta::FromSeconds(1)};
Amin Hassani4b717432019-01-14 16:24:20 -0800144 StrictMock<MockVariable<string>> mock_var_async_{"mock_var_async",
145 kVariableModeAsync};
146 StrictMock<MockVariable<string>> mock_var_poll_{"mock_var_poll",
147 kVariableModePoll};
Alex Deymo23949d42014-02-05 15:20:59 -0800148};
149
Alex Deymo63784a52014-05-28 10:46:14 -0700150TEST_F(UmEvaluationContextTest, GetValueFails) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700151 // FakeVariable is initialized as returning null.
152 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&fake_int_var_));
Alex Deymo23949d42014-02-05 15:20:59 -0800153}
154
Alex Deymo63784a52014-05-28 10:46:14 -0700155TEST_F(UmEvaluationContextTest, GetValueFailsWithInvalidVar) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700156 EXPECT_EQ(nullptr, eval_ctx_->GetValue(static_cast<Variable<int>*>(nullptr)));
Alex Deymo23949d42014-02-05 15:20:59 -0800157}
158
Alex Deymo63784a52014-05-28 10:46:14 -0700159TEST_F(UmEvaluationContextTest, GetValueReturns) {
Alex Deymo23949d42014-02-05 15:20:59 -0800160 const int* p_fake_int;
161
162 fake_int_var_.reset(new int(42));
163 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700164 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800165 EXPECT_EQ(42, *p_fake_int);
166}
167
Alex Deymo63784a52014-05-28 10:46:14 -0700168TEST_F(UmEvaluationContextTest, GetValueCached) {
Alex Deymo23949d42014-02-05 15:20:59 -0800169 const int* p_fake_int;
170
171 fake_int_var_.reset(new int(42));
172 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
173
174 // Check that if the variable changes, the EvaluationContext keeps returning
175 // the cached value.
176 fake_int_var_.reset(new int(5));
177
178 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700179 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800180 EXPECT_EQ(42, *p_fake_int);
181}
182
Alex Deymo63784a52014-05-28 10:46:14 -0700183TEST_F(UmEvaluationContextTest, GetValueCachesNull) {
Alex Deymo23949d42014-02-05 15:20:59 -0800184 const int* p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700185 EXPECT_EQ(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800186
187 fake_int_var_.reset(new int(42));
Alex Deymocc0e5cf2014-04-23 20:20:11 -0700188 // A second attempt to read the variable should not work because this
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700189 // EvaluationContext already got a null value.
Alex Deymo23949d42014-02-05 15:20:59 -0800190 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700191 EXPECT_EQ(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800192}
193
Alex Deymo63784a52014-05-28 10:46:14 -0700194TEST_F(UmEvaluationContextTest, GetValueMixedTypes) {
Alex Deymo23949d42014-02-05 15:20:59 -0800195 const int* p_fake_int;
196 const string* p_fake_string;
197
198 fake_int_var_.reset(new int(42));
Alex Deymo53556ec2014-03-17 10:05:57 -0700199 fake_poll_var_.reset(new string("Hello world!"));
Alex Deymo23949d42014-02-05 15:20:59 -0800200 // Check that the EvaluationContext can handle multiple Variable types. This
201 // is mostly a compile-time check due to the template nature of this method.
202 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Deymo53556ec2014-03-17 10:05:57 -0700203 p_fake_string = eval_ctx_->GetValue(&fake_poll_var_);
Alex Deymo23949d42014-02-05 15:20:59 -0800204
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700205 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800206 EXPECT_EQ(42, *p_fake_int);
207
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700208 ASSERT_NE(nullptr, p_fake_string);
Alex Deymo23949d42014-02-05 15:20:59 -0800209 EXPECT_EQ("Hello world!", *p_fake_string);
210}
211
Alex Deymo53556ec2014-03-17 10:05:57 -0700212// Test that we don't schedule an event if there's no variable to wait for.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700213TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutWithoutVariables) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700214 fake_const_var_.reset(new string("Hello world!"));
215 EXPECT_EQ(*eval_ctx_->GetValue(&fake_const_var_), "Hello world!");
216
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700217 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Alex Deymo53556ec2014-03-17 10:05:57 -0700218}
219
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700220// Test that reevaluation occurs when an async variable it depends on changes.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700221TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutWithVariables) {
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 // Check that the scheduled callback isn't run until we signal a ValueChaged.
Alex Deymo509dd532015-06-10 14:11:05 -0700228 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
Alex Deymo53556ec2014-03-17 10:05:57 -0700229 EXPECT_FALSE(value);
230
231 fake_async_var_.NotifyValueChanged();
232 EXPECT_FALSE(value);
233 // Ensure that the scheduled callback isn't run until we are back on the main
234 // loop.
Alex Deymo509dd532015-06-10 14:11:05 -0700235 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
Alex Deymo53556ec2014-03-17 10:05:57 -0700236 EXPECT_TRUE(value);
237}
238
239// Test that we don't re-schedule the events if we are attending one.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700240TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutCalledTwice) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700241 fake_async_var_.reset(new string("Async value"));
242 eval_ctx_->GetValue(&fake_async_var_);
243
244 bool value = false;
245 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
246 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
247
248 // The scheduled event should still work.
249 fake_async_var_.NotifyValueChanged();
Alex Deymo509dd532015-06-10 14:11:05 -0700250 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
Alex Deymo53556ec2014-03-17 10:05:57 -0700251 EXPECT_TRUE(value);
252}
253
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700254// Test that reevaluation occurs when a polling timeout fires.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700255TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutRunsFromTimeout) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700256 fake_poll_var_.reset(new string("Polled value"));
257 eval_ctx_->GetValue(&fake_poll_var_);
258
259 bool value = false;
260 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
261 // Check that the scheduled callback isn't run until the timeout occurs.
Alex Deymo509dd532015-06-10 14:11:05 -0700262 MessageLoopRunMaxIterations(MessageLoop::current(), 10);
Alex Deymo53556ec2014-03-17 10:05:57 -0700263 EXPECT_FALSE(value);
Alex Deymo509dd532015-06-10 14:11:05 -0700264 MessageLoopRunUntil(MessageLoop::current(),
265 TimeDelta::FromSeconds(10),
266 Bind(&GetBoolean, &value));
Alex Deymo53556ec2014-03-17 10:05:57 -0700267 EXPECT_TRUE(value);
268}
269
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700270// Test that callback is called when evaluation context expires, and that it
Gilad Arnoldfd45a732014-08-07 15:53:46 -0700271// cannot be used again unless the expiration deadline is reset.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700272TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutExpires) {
273 fake_async_var_.reset(new string("Async value"));
274 eval_ctx_->GetValue(&fake_async_var_);
275
276 bool value = false;
277 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
278 // Check that the scheduled callback isn't run until the timeout occurs.
Alex Deymo509dd532015-06-10 14:11:05 -0700279 MessageLoopRunMaxIterations(MessageLoop::current(), 10);
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700280 EXPECT_FALSE(value);
Alex Deymo509dd532015-06-10 14:11:05 -0700281 MessageLoopRunUntil(MessageLoop::current(),
282 TimeDelta::FromSeconds(10),
283 Bind(&GetBoolean, &value));
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700284 EXPECT_TRUE(value);
285
286 // Ensure that we cannot reschedule an evaluation.
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700287 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Gilad Arnoldfd45a732014-08-07 15:53:46 -0700288
289 // Ensure that we can reschedule an evaluation after resetting expiration.
290 eval_ctx_->ResetExpiration();
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700291 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700292}
293
294// Test that we clear the events when destroying the EvaluationContext.
295TEST_F(UmEvaluationContextTest, RemoveObserversAndTimeoutTest) {
296 fake_async_var_.reset(new string("Async value"));
297 eval_ctx_->GetValue(&fake_async_var_);
298
299 bool value = false;
300 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
301 eval_ctx_ = nullptr;
302
303 // This should not trigger the callback since the EvaluationContext waiting
304 // for it is gone, and it should have remove all its observers.
305 fake_async_var_.NotifyValueChanged();
Alex Deymo509dd532015-06-10 14:11:05 -0700306 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700307 EXPECT_FALSE(value);
308}
309
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700310// Scheduling two reevaluations from the callback should succeed.
311TEST_F(UmEvaluationContextTest,
312 RunOnValueChangeOrTimeoutReevaluatesRepeatedly) {
313 fake_poll_var_.reset(new string("Polled value"));
314 Closure evaluation = Bind(ReadVar<string>, eval_ctx_, &fake_poll_var_);
315 int num_reevaluations = 2;
316 bool done = false;
317
318 // Run the evaluation once.
319 evaluation.Run();
320
321 // Schedule repeated reevaluations.
Amin Hassani4b717432019-01-14 16:24:20 -0800322 Closure closure = Bind(
323 EvaluateRepeatedly, evaluation, eval_ctx_, &num_reevaluations, &done);
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700324 ASSERT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(closure));
Alex Deymo509dd532015-06-10 14:11:05 -0700325 MessageLoopRunUntil(MessageLoop::current(),
326 TimeDelta::FromSeconds(10),
327 Bind(&GetBoolean, &done));
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700328 EXPECT_EQ(0, num_reevaluations);
329}
330
Alex Deymodb799532014-03-21 13:00:00 -0700331// Test that we can delete the EvaluationContext while having pending events.
Alex Deymo63784a52014-05-28 10:46:14 -0700332TEST_F(UmEvaluationContextTest, ObjectDeletedWithPendingEventsTest) {
Alex Deymodb799532014-03-21 13:00:00 -0700333 fake_async_var_.reset(new string("Async value"));
334 fake_poll_var_.reset(new string("Polled value"));
335 eval_ctx_->GetValue(&fake_async_var_);
336 eval_ctx_->GetValue(&fake_poll_var_);
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700337 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Alex Deymodb799532014-03-21 13:00:00 -0700338 // TearDown() checks for leaked observers on this async_variable, which means
339 // that our object is still alive after removing its reference.
340}
341
342// Test that timed events fired after removal of the EvaluationContext don't
343// crash.
Alex Deymo63784a52014-05-28 10:46:14 -0700344TEST_F(UmEvaluationContextTest, TimeoutEventAfterDeleteTest) {
Alex Deymo0bb23412015-06-19 00:04:46 -0700345 FakeVariable<string> fake_short_poll_var = {"fake_short_poll",
346 TimeDelta::FromSeconds(1)};
Alex Deymodb799532014-03-21 13:00:00 -0700347 fake_short_poll_var.reset(new string("Polled value"));
348 eval_ctx_->GetValue(&fake_short_poll_var);
349 bool value = false;
350 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
351 // Remove the last reference to the EvaluationContext and run the loop for
Alex Deymo0bb23412015-06-19 00:04:46 -0700352 // 10 seconds to give time to the main loop to trigger the timeout Event (of 1
353 // second). Our callback should not be called because the EvaluationContext
Alex Deymodb799532014-03-21 13:00:00 -0700354 // was removed before the timeout event is attended.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700355 eval_ctx_ = nullptr;
Alex Deymo509dd532015-06-10 14:11:05 -0700356 MessageLoopRunUntil(MessageLoop::current(),
357 TimeDelta::FromSeconds(10),
358 Bind(&GetBoolean, &value));
Alex Deymodb799532014-03-21 13:00:00 -0700359 EXPECT_FALSE(value);
360}
361
Alex Deymo63784a52014-05-28 10:46:14 -0700362TEST_F(UmEvaluationContextTest, DefaultTimeout) {
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700363 // Test that the evaluation timeout calculation uses the default timeout on
364 // setup.
Alex Deymo41a75a72014-04-15 15:36:22 -0700365 EXPECT_CALL(mock_var_async_, GetValue(default_timeout_, _))
366 .WillOnce(Return(nullptr));
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700367 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&mock_var_async_));
Alex Deymo41a75a72014-04-15 15:36:22 -0700368}
369
Alex Deymo63784a52014-05-28 10:46:14 -0700370TEST_F(UmEvaluationContextTest, TimeoutUpdatesWithMonotonicTime) {
Amin Hassani0468a762020-11-17 23:53:48 -0800371 fake_clock_->SetMonotonicTime(fake_clock_->GetMonotonicTime() +
372 TimeDelta::FromSeconds(1));
Alex Deymo41a75a72014-04-15 15:36:22 -0700373
374 TimeDelta timeout = default_timeout_ - TimeDelta::FromSeconds(1);
375
Amin Hassani4b717432019-01-14 16:24:20 -0800376 EXPECT_CALL(mock_var_async_, GetValue(timeout, _)).WillOnce(Return(nullptr));
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700377 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&mock_var_async_));
Alex Deymo41a75a72014-04-15 15:36:22 -0700378}
379
Gilad Arnolda65fced2014-07-23 09:01:31 -0700380TEST_F(UmEvaluationContextTest, ResetEvaluationResetsTimesWallclock) {
Amin Hassani0468a762020-11-17 23:53:48 -0800381 Time cur_time = fake_clock_->GetWallclockTime();
Alex Deymo41a75a72014-04-15 15:36:22 -0700382 // Advance the time on the clock but don't call ResetEvaluation yet.
Amin Hassani0468a762020-11-17 23:53:48 -0800383 fake_clock_->SetWallclockTime(cur_time + TimeDelta::FromSeconds(4));
Alex Deymo41a75a72014-04-15 15:36:22 -0700384
Amin Hassani4b717432019-01-14 16:24:20 -0800385 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time -
386 TimeDelta::FromSeconds(1)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700387 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time));
388 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
Amin Hassani4b717432019-01-14 16:24:20 -0800389 cur_time + TimeDelta::FromSeconds(1)));
Alex Deymo41a75a72014-04-15 15:36:22 -0700390 // Call ResetEvaluation now, which should use the new evaluation time.
391 eval_ctx_->ResetEvaluation();
392
Amin Hassani0468a762020-11-17 23:53:48 -0800393 cur_time = fake_clock_->GetWallclockTime();
Amin Hassani4b717432019-01-14 16:24:20 -0800394 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time -
395 TimeDelta::FromSeconds(1)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700396 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time));
397 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
Amin Hassani4b717432019-01-14 16:24:20 -0800398 cur_time + TimeDelta::FromSeconds(1)));
Alex Deymo41a75a72014-04-15 15:36:22 -0700399}
400
Gilad Arnolda65fced2014-07-23 09:01:31 -0700401TEST_F(UmEvaluationContextTest, ResetEvaluationResetsTimesMonotonic) {
Amin Hassani0468a762020-11-17 23:53:48 -0800402 Time cur_time = fake_clock_->GetMonotonicTime();
Gilad Arnolda65fced2014-07-23 09:01:31 -0700403 // Advance the time on the clock but don't call ResetEvaluation yet.
Amin Hassani0468a762020-11-17 23:53:48 -0800404 fake_clock_->SetMonotonicTime(cur_time + TimeDelta::FromSeconds(4));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700405
Amin Hassani4b717432019-01-14 16:24:20 -0800406 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time -
407 TimeDelta::FromSeconds(1)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700408 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time));
409 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
Amin Hassani4b717432019-01-14 16:24:20 -0800410 cur_time + TimeDelta::FromSeconds(1)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700411 // Call ResetEvaluation now, which should use the new evaluation time.
412 eval_ctx_->ResetEvaluation();
413
Amin Hassani0468a762020-11-17 23:53:48 -0800414 cur_time = fake_clock_->GetMonotonicTime();
Amin Hassani4b717432019-01-14 16:24:20 -0800415 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time -
416 TimeDelta::FromSeconds(1)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700417 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time));
418 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
Amin Hassani4b717432019-01-14 16:24:20 -0800419 cur_time + TimeDelta::FromSeconds(1)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700420}
421
422TEST_F(UmEvaluationContextTest,
423 IsWallclockTimeGreaterThanSignalsTriggerReevaluation) {
424 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
Amin Hassani0468a762020-11-17 23:53:48 -0800425 fake_clock_->GetWallclockTime() + TimeDelta::FromSeconds(1)));
Alex Deymo41a75a72014-04-15 15:36:22 -0700426
Gilad Arnolda65fced2014-07-23 09:01:31 -0700427 // The "false" from IsWallclockTimeGreaterThan means that's not that timestamp
428 // yet, so this should schedule a callback for when that happens.
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700429 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Alex Deymo41a75a72014-04-15 15:36:22 -0700430}
431
Gilad Arnolda65fced2014-07-23 09:01:31 -0700432TEST_F(UmEvaluationContextTest,
433 IsMonotonicTimeGreaterThanSignalsTriggerReevaluation) {
434 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
Amin Hassani0468a762020-11-17 23:53:48 -0800435 fake_clock_->GetMonotonicTime() + TimeDelta::FromSeconds(1)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700436
437 // The "false" from IsMonotonicTimeGreaterThan means that's not that timestamp
438 // yet, so this should schedule a callback for when that happens.
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700439 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700440}
441
442TEST_F(UmEvaluationContextTest,
443 IsWallclockTimeGreaterThanDoesntRecordPastTimestamps) {
444 // IsWallclockTimeGreaterThan() should ignore timestamps on the past for
445 // reevaluation.
446 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
Amin Hassani0468a762020-11-17 23:53:48 -0800447 fake_clock_->GetWallclockTime() - TimeDelta::FromSeconds(20)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700448 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
Amin Hassani0468a762020-11-17 23:53:48 -0800449 fake_clock_->GetWallclockTime() - TimeDelta::FromSeconds(1)));
Alex Deymo41a75a72014-04-15 15:36:22 -0700450
451 // Callback should not be scheduled.
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700452 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Alex Deymo41a75a72014-04-15 15:36:22 -0700453}
454
Gilad Arnolda65fced2014-07-23 09:01:31 -0700455TEST_F(UmEvaluationContextTest,
456 IsMonotonicTimeGreaterThanDoesntRecordPastTimestamps) {
457 // IsMonotonicTimeGreaterThan() should ignore timestamps on the past for
458 // reevaluation.
459 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
Amin Hassani0468a762020-11-17 23:53:48 -0800460 fake_clock_->GetMonotonicTime() - TimeDelta::FromSeconds(20)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700461 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
Amin Hassani0468a762020-11-17 23:53:48 -0800462 fake_clock_->GetMonotonicTime() - TimeDelta::FromSeconds(1)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700463
464 // Callback should not be scheduled.
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700465 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700466}
467
Alex Deymo63784a52014-05-28 10:46:14 -0700468TEST_F(UmEvaluationContextTest, DumpContext) {
David Zeuthenc1490282014-04-29 16:25:03 -0700469 // |fail_var_| yield "(no value)" since it is unset.
470 eval_ctx_->GetValue(&fail_var_);
471
472 // Check that this is included.
473 fake_int_var_.reset(new int(42));
474 eval_ctx_->GetValue(&fake_int_var_);
475
476 // Check that double-quotes are escaped properly.
477 fake_poll_var_.reset(new string("Hello \"world\"!"));
478 eval_ctx_->GetValue(&fake_poll_var_);
479
480 // Note that the variables are printed in alphabetical order. Also
Gilad Arnolda65fced2014-07-23 09:01:31 -0700481 // see UmEvaluationContextText::SetUp() where the values used for
482 // |evaluation_start_{monotonic,wallclock| are set.
Amin Hassani4b717432019-01-14 16:24:20 -0800483 EXPECT_EQ(
484 "{\n"
485 " \"evaluation_start_monotonic\": \"4/22/2009 19:25:00 GMT\",\n"
486 " \"evaluation_start_wallclock\": \"3/2/2006 1:23:45 GMT\",\n"
487 " \"variables\": {\n"
488 " \"fail_var\": \"(no value)\",\n"
489 " \"fake_int\": \"42\",\n"
490 " \"fake_poll\": \"Hello \\\"world\\\"!\"\n"
491 " }\n"
492 "}",
493 eval_ctx_->DumpContext());
David Zeuthenc1490282014-04-29 16:25:03 -0700494}
495
Alex Deymo63784a52014-05-28 10:46:14 -0700496} // namespace chromeos_update_manager