blob: 151b0b5500360af99167fa1ab0d097e84eb0b831 [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;
Amin Hassani4b717432019-01-14 16:24:20 -080044using testing::_;
Alex Deymo41a75a72014-04-15 15:36:22 -070045using testing::Return;
46using testing::StrictMock;
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
Amin Hassani4b717432019-01-14 16:24:20 -080061template <typename T>
Gilad Arnoldfb794f42014-07-01 15:36:31 -070062void 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|.
Amin Hassani4b717432019-01-14 16:24:20 -080068void EvaluateRepeatedly(Closure evaluation,
69 scoped_refptr<EvaluationContext> ec,
70 int* count_p,
71 bool* done_p) {
Gilad Arnoldfb794f42014-07-01 15:36:31 -070072 evaluation.Run();
73
74 // Schedule reevaluation if needed.
75 if (*count_p > 0) {
76 Closure closure = Bind(EvaluateRepeatedly, evaluation, ec, count_p, done_p);
77 ASSERT_TRUE(ec->RunOnValueChangeOrTimeout(closure))
78 << "Failed to schedule reevaluation, count_p=" << *count_p;
79 (*count_p)--;
80 } else {
81 *done_p = true;
82 }
83}
84
85} // namespace
Alex Deymo23949d42014-02-05 15:20:59 -080086
Alex Deymo63784a52014-05-28 10:46:14 -070087class UmEvaluationContextTest : public ::testing::Test {
Alex Deymo23949d42014-02-05 15:20:59 -080088 protected:
Alex Deymo610277e2014-11-11 21:18:11 -080089 void SetUp() override {
Alex Deymo509dd532015-06-10 14:11:05 -070090 loop_.SetAsCurrent();
Gilad Arnolda65fced2014-07-23 09:01:31 -070091 // Apr 22, 2009 19:25:00 UTC (this is a random reference point).
92 fake_clock_.SetMonotonicTime(Time::FromTimeT(1240428300));
93 // Mar 2, 2006 1:23:45 UTC.
David Zeuthenc1490282014-04-29 16:25:03 -070094 fake_clock_.SetWallclockTime(Time::FromTimeT(1141262625));
Gilad Arnold83ffdda2014-08-08 13:30:31 -070095 eval_ctx_ = new EvaluationContext(
Amin Hassani4b717432019-01-14 16:24:20 -080096 &fake_clock_,
97 default_timeout_,
98 default_timeout_,
Ben Chan02f7c1d2014-10-18 15:18:02 -070099 unique_ptr<base::Callback<void(EvaluationContext*)>>(nullptr));
Alex Deymo23949d42014-02-05 15:20:59 -0800100 }
101
Alex Deymo610277e2014-11-11 21:18:11 -0800102 void TearDown() override {
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700103 // Ensure that the evaluation context did not leak and is actually being
104 // destroyed.
105 if (eval_ctx_) {
106 base::WeakPtr<EvaluationContext> eval_ctx_weak_alias =
107 eval_ctx_->weak_ptr_factory_.GetWeakPtr();
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700108 ASSERT_NE(nullptr, eval_ctx_weak_alias.get());
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700109 eval_ctx_ = nullptr;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700110 EXPECT_EQ(nullptr, eval_ctx_weak_alias.get())
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700111 << "The evaluation context was not destroyed! This is likely a bug "
112 "in how the test was written, look for leaking handles to the EC, "
113 "possibly through closure objects.";
114 }
115
Alex Deymo53556ec2014-03-17 10:05:57 -0700116 // Check that the evaluation context removed all the observers.
117 EXPECT_TRUE(fake_int_var_.observer_list_.empty());
118 EXPECT_TRUE(fake_async_var_.observer_list_.empty());
119 EXPECT_TRUE(fake_const_var_.observer_list_.empty());
120 EXPECT_TRUE(fake_poll_var_.observer_list_.empty());
Alex Deymo509dd532015-06-10 14:11:05 -0700121
122 EXPECT_FALSE(loop_.PendingTasks());
Alex Deymo53556ec2014-03-17 10:05:57 -0700123 }
124
Alex Deymof329b932014-10-30 01:37:48 -0700125 TimeDelta default_timeout_ = TimeDelta::FromSeconds(5);
Alex Deymo41a75a72014-04-15 15:36:22 -0700126
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700127 brillo::FakeMessageLoop loop_{nullptr};
Alex Deymo41a75a72014-04-15 15:36:22 -0700128 FakeClock fake_clock_;
Alex Deymo7b948f02014-03-10 17:01:10 -0700129 scoped_refptr<EvaluationContext> eval_ctx_;
Alex Deymo53556ec2014-03-17 10:05:57 -0700130
131 // FakeVariables used for testing the EvaluationContext. These are required
132 // here to prevent them from going away *before* the EvaluationContext under
133 // test does, which keeps a reference to them.
David Zeuthenc1490282014-04-29 16:25:03 -0700134 FakeVariable<bool> fail_var_ = {"fail_var", kVariableModePoll};
Alex Deymo53556ec2014-03-17 10:05:57 -0700135 FakeVariable<int> fake_int_var_ = {"fake_int", kVariableModePoll};
136 FakeVariable<string> fake_async_var_ = {"fake_async", kVariableModeAsync};
137 FakeVariable<string> fake_const_var_ = {"fake_const", kVariableModeConst};
138 FakeVariable<string> fake_poll_var_ = {"fake_poll",
139 TimeDelta::FromSeconds(1)};
Amin Hassani4b717432019-01-14 16:24:20 -0800140 StrictMock<MockVariable<string>> mock_var_async_{"mock_var_async",
141 kVariableModeAsync};
142 StrictMock<MockVariable<string>> mock_var_poll_{"mock_var_poll",
143 kVariableModePoll};
Alex Deymo23949d42014-02-05 15:20:59 -0800144};
145
Alex Deymo63784a52014-05-28 10:46:14 -0700146TEST_F(UmEvaluationContextTest, GetValueFails) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700147 // FakeVariable is initialized as returning null.
148 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&fake_int_var_));
Alex Deymo23949d42014-02-05 15:20:59 -0800149}
150
Alex Deymo63784a52014-05-28 10:46:14 -0700151TEST_F(UmEvaluationContextTest, GetValueFailsWithInvalidVar) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700152 EXPECT_EQ(nullptr, eval_ctx_->GetValue(static_cast<Variable<int>*>(nullptr)));
Alex Deymo23949d42014-02-05 15:20:59 -0800153}
154
Alex Deymo63784a52014-05-28 10:46:14 -0700155TEST_F(UmEvaluationContextTest, GetValueReturns) {
Alex Deymo23949d42014-02-05 15:20:59 -0800156 const int* p_fake_int;
157
158 fake_int_var_.reset(new int(42));
159 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700160 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800161 EXPECT_EQ(42, *p_fake_int);
162}
163
Alex Deymo63784a52014-05-28 10:46:14 -0700164TEST_F(UmEvaluationContextTest, GetValueCached) {
Alex Deymo23949d42014-02-05 15:20:59 -0800165 const int* p_fake_int;
166
167 fake_int_var_.reset(new int(42));
168 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
169
170 // Check that if the variable changes, the EvaluationContext keeps returning
171 // the cached value.
172 fake_int_var_.reset(new int(5));
173
174 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700175 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800176 EXPECT_EQ(42, *p_fake_int);
177}
178
Alex Deymo63784a52014-05-28 10:46:14 -0700179TEST_F(UmEvaluationContextTest, GetValueCachesNull) {
Alex Deymo23949d42014-02-05 15:20:59 -0800180 const int* p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700181 EXPECT_EQ(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800182
183 fake_int_var_.reset(new int(42));
Alex Deymocc0e5cf2014-04-23 20:20:11 -0700184 // A second attempt to read the variable should not work because this
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700185 // EvaluationContext already got a null value.
Alex Deymo23949d42014-02-05 15:20:59 -0800186 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700187 EXPECT_EQ(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800188}
189
Alex Deymo63784a52014-05-28 10:46:14 -0700190TEST_F(UmEvaluationContextTest, GetValueMixedTypes) {
Alex Deymo23949d42014-02-05 15:20:59 -0800191 const int* p_fake_int;
192 const string* p_fake_string;
193
194 fake_int_var_.reset(new int(42));
Alex Deymo53556ec2014-03-17 10:05:57 -0700195 fake_poll_var_.reset(new string("Hello world!"));
Alex Deymo23949d42014-02-05 15:20:59 -0800196 // Check that the EvaluationContext can handle multiple Variable types. This
197 // is mostly a compile-time check due to the template nature of this method.
198 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Deymo53556ec2014-03-17 10:05:57 -0700199 p_fake_string = eval_ctx_->GetValue(&fake_poll_var_);
Alex Deymo23949d42014-02-05 15:20:59 -0800200
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700201 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800202 EXPECT_EQ(42, *p_fake_int);
203
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700204 ASSERT_NE(nullptr, p_fake_string);
Alex Deymo23949d42014-02-05 15:20:59 -0800205 EXPECT_EQ("Hello world!", *p_fake_string);
206}
207
Alex Deymo53556ec2014-03-17 10:05:57 -0700208// Test that we don't schedule an event if there's no variable to wait for.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700209TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutWithoutVariables) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700210 fake_const_var_.reset(new string("Hello world!"));
211 EXPECT_EQ(*eval_ctx_->GetValue(&fake_const_var_), "Hello world!");
212
Amin Hassani2e4eda52019-01-07 14:01:17 -0800213#if BASE_VER < 576279
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700214 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&base::DoNothing)));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800215#else
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700216 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800217#endif
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.
Amin Hassani2e4eda52019-01-07 14:01:17 -0800287#if BASE_VER < 576279
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700288 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&base::DoNothing)));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800289#else
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700290 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800291#endif
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#if BASE_VER < 576279
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700296 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&base::DoNothing)));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800297#else
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700298 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800299#endif
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700300}
301
302// Test that we clear the events when destroying the EvaluationContext.
303TEST_F(UmEvaluationContextTest, RemoveObserversAndTimeoutTest) {
304 fake_async_var_.reset(new string("Async value"));
305 eval_ctx_->GetValue(&fake_async_var_);
306
307 bool value = false;
308 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
309 eval_ctx_ = nullptr;
310
311 // This should not trigger the callback since the EvaluationContext waiting
312 // for it is gone, and it should have remove all its observers.
313 fake_async_var_.NotifyValueChanged();
Alex Deymo509dd532015-06-10 14:11:05 -0700314 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700315 EXPECT_FALSE(value);
316}
317
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700318// Scheduling two reevaluations from the callback should succeed.
319TEST_F(UmEvaluationContextTest,
320 RunOnValueChangeOrTimeoutReevaluatesRepeatedly) {
321 fake_poll_var_.reset(new string("Polled value"));
322 Closure evaluation = Bind(ReadVar<string>, eval_ctx_, &fake_poll_var_);
323 int num_reevaluations = 2;
324 bool done = false;
325
326 // Run the evaluation once.
327 evaluation.Run();
328
329 // Schedule repeated reevaluations.
Amin Hassani4b717432019-01-14 16:24:20 -0800330 Closure closure = Bind(
331 EvaluateRepeatedly, evaluation, eval_ctx_, &num_reevaluations, &done);
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700332 ASSERT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(closure));
Alex Deymo509dd532015-06-10 14:11:05 -0700333 MessageLoopRunUntil(MessageLoop::current(),
334 TimeDelta::FromSeconds(10),
335 Bind(&GetBoolean, &done));
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700336 EXPECT_EQ(0, num_reevaluations);
337}
338
Alex Deymodb799532014-03-21 13:00:00 -0700339// Test that we can delete the EvaluationContext while having pending events.
Alex Deymo63784a52014-05-28 10:46:14 -0700340TEST_F(UmEvaluationContextTest, ObjectDeletedWithPendingEventsTest) {
Alex Deymodb799532014-03-21 13:00:00 -0700341 fake_async_var_.reset(new string("Async value"));
342 fake_poll_var_.reset(new string("Polled value"));
343 eval_ctx_->GetValue(&fake_async_var_);
344 eval_ctx_->GetValue(&fake_poll_var_);
Amin Hassani2e4eda52019-01-07 14:01:17 -0800345#if BASE_VER < 576279
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700346 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&base::DoNothing)));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800347#else
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700348 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800349#endif
Alex Deymodb799532014-03-21 13:00:00 -0700350 // TearDown() checks for leaked observers on this async_variable, which means
351 // that our object is still alive after removing its reference.
352}
353
354// Test that timed events fired after removal of the EvaluationContext don't
355// crash.
Alex Deymo63784a52014-05-28 10:46:14 -0700356TEST_F(UmEvaluationContextTest, TimeoutEventAfterDeleteTest) {
Alex Deymo0bb23412015-06-19 00:04:46 -0700357 FakeVariable<string> fake_short_poll_var = {"fake_short_poll",
358 TimeDelta::FromSeconds(1)};
Alex Deymodb799532014-03-21 13:00:00 -0700359 fake_short_poll_var.reset(new string("Polled value"));
360 eval_ctx_->GetValue(&fake_short_poll_var);
361 bool value = false;
362 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
363 // Remove the last reference to the EvaluationContext and run the loop for
Alex Deymo0bb23412015-06-19 00:04:46 -0700364 // 10 seconds to give time to the main loop to trigger the timeout Event (of 1
365 // second). Our callback should not be called because the EvaluationContext
Alex Deymodb799532014-03-21 13:00:00 -0700366 // was removed before the timeout event is attended.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700367 eval_ctx_ = nullptr;
Alex Deymo509dd532015-06-10 14:11:05 -0700368 MessageLoopRunUntil(MessageLoop::current(),
369 TimeDelta::FromSeconds(10),
370 Bind(&GetBoolean, &value));
Alex Deymodb799532014-03-21 13:00:00 -0700371 EXPECT_FALSE(value);
372}
373
Alex Deymo63784a52014-05-28 10:46:14 -0700374TEST_F(UmEvaluationContextTest, DefaultTimeout) {
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700375 // Test that the evaluation timeout calculation uses the default timeout on
376 // setup.
Alex Deymo41a75a72014-04-15 15:36:22 -0700377 EXPECT_CALL(mock_var_async_, GetValue(default_timeout_, _))
378 .WillOnce(Return(nullptr));
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700379 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&mock_var_async_));
Alex Deymo41a75a72014-04-15 15:36:22 -0700380}
381
Alex Deymo63784a52014-05-28 10:46:14 -0700382TEST_F(UmEvaluationContextTest, TimeoutUpdatesWithMonotonicTime) {
Amin Hassani4b717432019-01-14 16:24:20 -0800383 fake_clock_.SetMonotonicTime(fake_clock_.GetMonotonicTime() +
384 TimeDelta::FromSeconds(1));
Alex Deymo41a75a72014-04-15 15:36:22 -0700385
386 TimeDelta timeout = default_timeout_ - TimeDelta::FromSeconds(1);
387
Amin Hassani4b717432019-01-14 16:24:20 -0800388 EXPECT_CALL(mock_var_async_, GetValue(timeout, _)).WillOnce(Return(nullptr));
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700389 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&mock_var_async_));
Alex Deymo41a75a72014-04-15 15:36:22 -0700390}
391
Gilad Arnolda65fced2014-07-23 09:01:31 -0700392TEST_F(UmEvaluationContextTest, ResetEvaluationResetsTimesWallclock) {
Alex Deymof329b932014-10-30 01:37:48 -0700393 Time cur_time = fake_clock_.GetWallclockTime();
Alex Deymo41a75a72014-04-15 15:36:22 -0700394 // Advance the time on the clock but don't call ResetEvaluation yet.
395 fake_clock_.SetWallclockTime(cur_time + TimeDelta::FromSeconds(4));
396
Amin Hassani4b717432019-01-14 16:24:20 -0800397 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time -
398 TimeDelta::FromSeconds(1)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700399 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time));
400 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
Amin Hassani4b717432019-01-14 16:24:20 -0800401 cur_time + TimeDelta::FromSeconds(1)));
Alex Deymo41a75a72014-04-15 15:36:22 -0700402 // Call ResetEvaluation now, which should use the new evaluation time.
403 eval_ctx_->ResetEvaluation();
404
405 cur_time = fake_clock_.GetWallclockTime();
Amin Hassani4b717432019-01-14 16:24:20 -0800406 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time -
407 TimeDelta::FromSeconds(1)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700408 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time));
409 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
Amin Hassani4b717432019-01-14 16:24:20 -0800410 cur_time + TimeDelta::FromSeconds(1)));
Alex Deymo41a75a72014-04-15 15:36:22 -0700411}
412
Gilad Arnolda65fced2014-07-23 09:01:31 -0700413TEST_F(UmEvaluationContextTest, ResetEvaluationResetsTimesMonotonic) {
Alex Deymof329b932014-10-30 01:37:48 -0700414 Time cur_time = fake_clock_.GetMonotonicTime();
Gilad Arnolda65fced2014-07-23 09:01:31 -0700415 // Advance the time on the clock but don't call ResetEvaluation yet.
416 fake_clock_.SetMonotonicTime(cur_time + TimeDelta::FromSeconds(4));
417
Amin Hassani4b717432019-01-14 16:24:20 -0800418 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time -
419 TimeDelta::FromSeconds(1)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700420 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time));
421 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
Amin Hassani4b717432019-01-14 16:24:20 -0800422 cur_time + TimeDelta::FromSeconds(1)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700423 // Call ResetEvaluation now, which should use the new evaluation time.
424 eval_ctx_->ResetEvaluation();
425
426 cur_time = fake_clock_.GetMonotonicTime();
Amin Hassani4b717432019-01-14 16:24:20 -0800427 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time -
428 TimeDelta::FromSeconds(1)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700429 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time));
430 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
Amin Hassani4b717432019-01-14 16:24:20 -0800431 cur_time + TimeDelta::FromSeconds(1)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700432}
433
434TEST_F(UmEvaluationContextTest,
435 IsWallclockTimeGreaterThanSignalsTriggerReevaluation) {
436 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
Alex Deymo41a75a72014-04-15 15:36:22 -0700437 fake_clock_.GetWallclockTime() + TimeDelta::FromSeconds(1)));
438
Gilad Arnolda65fced2014-07-23 09:01:31 -0700439 // The "false" from IsWallclockTimeGreaterThan means that's not that timestamp
440 // yet, so this should schedule a callback for when that happens.
Amin Hassani2e4eda52019-01-07 14:01:17 -0800441#if BASE_VER < 576279
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700442 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&base::DoNothing)));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800443#else
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700444 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800445#endif
Alex Deymo41a75a72014-04-15 15:36:22 -0700446}
447
Gilad Arnolda65fced2014-07-23 09:01:31 -0700448TEST_F(UmEvaluationContextTest,
449 IsMonotonicTimeGreaterThanSignalsTriggerReevaluation) {
450 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
451 fake_clock_.GetMonotonicTime() + TimeDelta::FromSeconds(1)));
452
453 // The "false" from IsMonotonicTimeGreaterThan means that's not that timestamp
454 // yet, so this should schedule a callback for when that happens.
Amin Hassani2e4eda52019-01-07 14:01:17 -0800455#if BASE_VER < 576279
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700456 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&base::DoNothing)));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800457#else
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700458 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800459#endif
Gilad Arnolda65fced2014-07-23 09:01:31 -0700460}
461
462TEST_F(UmEvaluationContextTest,
463 IsWallclockTimeGreaterThanDoesntRecordPastTimestamps) {
464 // IsWallclockTimeGreaterThan() should ignore timestamps on the past for
465 // reevaluation.
466 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
Alex Deymo41a75a72014-04-15 15:36:22 -0700467 fake_clock_.GetWallclockTime() - TimeDelta::FromSeconds(20)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700468 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
Alex Deymo41a75a72014-04-15 15:36:22 -0700469 fake_clock_.GetWallclockTime() - TimeDelta::FromSeconds(1)));
470
471 // Callback should not be scheduled.
Amin Hassani2e4eda52019-01-07 14:01:17 -0800472#if BASE_VER < 576279
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700473 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&base::DoNothing)));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800474#else
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700475 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800476#endif
Alex Deymo41a75a72014-04-15 15:36:22 -0700477}
478
Gilad Arnolda65fced2014-07-23 09:01:31 -0700479TEST_F(UmEvaluationContextTest,
480 IsMonotonicTimeGreaterThanDoesntRecordPastTimestamps) {
481 // IsMonotonicTimeGreaterThan() should ignore timestamps on the past for
482 // reevaluation.
483 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
484 fake_clock_.GetMonotonicTime() - TimeDelta::FromSeconds(20)));
485 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
486 fake_clock_.GetMonotonicTime() - TimeDelta::FromSeconds(1)));
487
488 // Callback should not be scheduled.
Amin Hassani2e4eda52019-01-07 14:01:17 -0800489#if BASE_VER < 576279
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700490 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&base::DoNothing)));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800491#else
Jae Hoon Kim9d9492f2019-06-17 14:52:48 -0700492 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
Amin Hassani2e4eda52019-01-07 14:01:17 -0800493#endif
Gilad Arnolda65fced2014-07-23 09:01:31 -0700494}
495
Alex Deymo63784a52014-05-28 10:46:14 -0700496TEST_F(UmEvaluationContextTest, DumpContext) {
David Zeuthenc1490282014-04-29 16:25:03 -0700497 // |fail_var_| yield "(no value)" since it is unset.
498 eval_ctx_->GetValue(&fail_var_);
499
500 // Check that this is included.
501 fake_int_var_.reset(new int(42));
502 eval_ctx_->GetValue(&fake_int_var_);
503
504 // Check that double-quotes are escaped properly.
505 fake_poll_var_.reset(new string("Hello \"world\"!"));
506 eval_ctx_->GetValue(&fake_poll_var_);
507
508 // Note that the variables are printed in alphabetical order. Also
Gilad Arnolda65fced2014-07-23 09:01:31 -0700509 // see UmEvaluationContextText::SetUp() where the values used for
510 // |evaluation_start_{monotonic,wallclock| are set.
Amin Hassani4b717432019-01-14 16:24:20 -0800511 EXPECT_EQ(
512 "{\n"
513 " \"evaluation_start_monotonic\": \"4/22/2009 19:25:00 GMT\",\n"
514 " \"evaluation_start_wallclock\": \"3/2/2006 1:23:45 GMT\",\n"
515 " \"variables\": {\n"
516 " \"fail_var\": \"(no value)\",\n"
517 " \"fake_int\": \"42\",\n"
518 " \"fake_poll\": \"Hello \\\"world\\\"!\"\n"
519 " }\n"
520 "}",
521 eval_ctx_->DumpContext());
David Zeuthenc1490282014-04-29 16:25:03 -0700522}
523
Alex Deymo63784a52014-05-28 10:46:14 -0700524} // namespace chromeos_update_manager