blob: e59b1604dd16e3ecf6d7c20bf8ecf86cfe602ca2 [file] [log] [blame]
Alex Deymo23949d42014-02-05 15:20:59 -08001// Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Alex Deymo23949d42014-02-05 15:20:59 -08005#include <string>
6
Alex Deymo53556ec2014-03-17 10:05:57 -07007#include <base/bind.h>
Alex Deymo53556ec2014-03-17 10:05:57 -07008#include <gtest/gtest.h>
9
Alex Deymo41a75a72014-04-15 15:36:22 -070010#include "update_engine/fake_clock.h"
Alex Deymo53556ec2014-03-17 10:05:57 -070011#include "update_engine/test_utils.h"
Alex Deymo63784a52014-05-28 10:46:14 -070012#include "update_engine/update_manager/evaluation_context.h"
13#include "update_engine/update_manager/fake_variable.h"
14#include "update_engine/update_manager/generic_variables.h"
15#include "update_engine/update_manager/mock_variable.h"
16#include "update_engine/update_manager/umtest_utils.h"
Alex Deymo23949d42014-02-05 15:20:59 -080017
Alex Deymo53556ec2014-03-17 10:05:57 -070018using base::Bind;
Gilad Arnoldfb794f42014-07-01 15:36:31 -070019using base::Closure;
Alex Deymo41a75a72014-04-15 15:36:22 -070020using base::Time;
Alex Deymo53556ec2014-03-17 10:05:57 -070021using base::TimeDelta;
Alex Deymo41a75a72014-04-15 15:36:22 -070022using chromeos_update_engine::FakeClock;
Alex Deymo53556ec2014-03-17 10:05:57 -070023using chromeos_update_engine::RunGMainLoopMaxIterations;
24using chromeos_update_engine::RunGMainLoopUntil;
Alex Deymo23949d42014-02-05 15:20:59 -080025using std::string;
Alex Deymo41a75a72014-04-15 15:36:22 -070026using testing::Return;
27using testing::StrictMock;
28using testing::_;
Alex Deymo23949d42014-02-05 15:20:59 -080029
Gilad Arnoldfb794f42014-07-01 15:36:31 -070030namespace chromeos_update_manager {
31
Alex Deymo53556ec2014-03-17 10:05:57 -070032namespace {
33
34void DoNothing() {}
35
36// Sets the value of the passed pointer to true.
37void SetTrue(bool* value) {
38 *value = true;
39}
40
41bool GetBoolean(bool* value) {
42 return *value;
43}
44
Gilad Arnoldfb794f42014-07-01 15:36:31 -070045template<typename T>
46void ReadVar(scoped_refptr<EvaluationContext> ec, Variable<T>* var) {
47 ec->GetValue(var);
48}
Alex Deymo53556ec2014-03-17 10:05:57 -070049
Gilad Arnoldfb794f42014-07-01 15:36:31 -070050// Runs |evaluation|; if the value pointed by |count_p| is greater than zero,
51// decrement it and schedule a reevaluation; otherwise, writes true to |done_p|.
52void EvaluateRepeatedly(Closure evaluation, scoped_refptr<EvaluationContext> ec,
53 int* count_p, bool* done_p) {
54 evaluation.Run();
55
56 // Schedule reevaluation if needed.
57 if (*count_p > 0) {
58 Closure closure = Bind(EvaluateRepeatedly, evaluation, ec, count_p, done_p);
59 ASSERT_TRUE(ec->RunOnValueChangeOrTimeout(closure))
60 << "Failed to schedule reevaluation, count_p=" << *count_p;
61 (*count_p)--;
62 } else {
63 *done_p = true;
64 }
65}
66
67} // namespace
Alex Deymo23949d42014-02-05 15:20:59 -080068
Alex Deymo63784a52014-05-28 10:46:14 -070069class UmEvaluationContextTest : public ::testing::Test {
Alex Deymo23949d42014-02-05 15:20:59 -080070 protected:
71 virtual void SetUp() {
Gilad Arnolda65fced2014-07-23 09:01:31 -070072 // Apr 22, 2009 19:25:00 UTC (this is a random reference point).
73 fake_clock_.SetMonotonicTime(Time::FromTimeT(1240428300));
74 // Mar 2, 2006 1:23:45 UTC.
David Zeuthenc1490282014-04-29 16:25:03 -070075 fake_clock_.SetWallclockTime(Time::FromTimeT(1141262625));
Gilad Arnold83ffdda2014-08-08 13:30:31 -070076 eval_ctx_ = new EvaluationContext(
77 &fake_clock_, default_timeout_, default_timeout_,
78 scoped_ptr<base::Callback<void(EvaluationContext*)>>(nullptr));
Alex Deymo23949d42014-02-05 15:20:59 -080079 }
80
Alex Deymo53556ec2014-03-17 10:05:57 -070081 virtual void TearDown() {
Gilad Arnoldfb794f42014-07-01 15:36:31 -070082 // Ensure that the evaluation context did not leak and is actually being
83 // destroyed.
84 if (eval_ctx_) {
85 base::WeakPtr<EvaluationContext> eval_ctx_weak_alias =
86 eval_ctx_->weak_ptr_factory_.GetWeakPtr();
Alex Vakulenko88b591f2014-08-28 16:48:57 -070087 ASSERT_NE(nullptr, eval_ctx_weak_alias.get());
Gilad Arnoldfb794f42014-07-01 15:36:31 -070088 eval_ctx_ = nullptr;
Alex Vakulenko88b591f2014-08-28 16:48:57 -070089 EXPECT_EQ(nullptr, eval_ctx_weak_alias.get())
Gilad Arnoldfb794f42014-07-01 15:36:31 -070090 << "The evaluation context was not destroyed! This is likely a bug "
91 "in how the test was written, look for leaking handles to the EC, "
92 "possibly through closure objects.";
93 }
94
Alex Deymo53556ec2014-03-17 10:05:57 -070095 // Check that the evaluation context removed all the observers.
96 EXPECT_TRUE(fake_int_var_.observer_list_.empty());
97 EXPECT_TRUE(fake_async_var_.observer_list_.empty());
98 EXPECT_TRUE(fake_const_var_.observer_list_.empty());
99 EXPECT_TRUE(fake_poll_var_.observer_list_.empty());
100 }
101
Alex Deymo41a75a72014-04-15 15:36:22 -0700102 base::TimeDelta default_timeout_ = base::TimeDelta::FromSeconds(5);
103
104 FakeClock fake_clock_;
Alex Deymo7b948f02014-03-10 17:01:10 -0700105 scoped_refptr<EvaluationContext> eval_ctx_;
Alex Deymo53556ec2014-03-17 10:05:57 -0700106
107 // FakeVariables used for testing the EvaluationContext. These are required
108 // here to prevent them from going away *before* the EvaluationContext under
109 // test does, which keeps a reference to them.
David Zeuthenc1490282014-04-29 16:25:03 -0700110 FakeVariable<bool> fail_var_ = {"fail_var", kVariableModePoll};
Alex Deymo53556ec2014-03-17 10:05:57 -0700111 FakeVariable<int> fake_int_var_ = {"fake_int", kVariableModePoll};
112 FakeVariable<string> fake_async_var_ = {"fake_async", kVariableModeAsync};
113 FakeVariable<string> fake_const_var_ = {"fake_const", kVariableModeConst};
114 FakeVariable<string> fake_poll_var_ = {"fake_poll",
115 TimeDelta::FromSeconds(1)};
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700116 StrictMock<MockVariable<string>> mock_var_async_ {
117 "mock_var_async", kVariableModeAsync};
118 StrictMock<MockVariable<string>> mock_var_poll_ {
119 "mock_var_poll", kVariableModePoll};
Alex Deymo23949d42014-02-05 15:20:59 -0800120};
121
Alex Deymo63784a52014-05-28 10:46:14 -0700122TEST_F(UmEvaluationContextTest, GetValueFails) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700123 // FakeVariable is initialized as returning null.
124 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&fake_int_var_));
Alex Deymo23949d42014-02-05 15:20:59 -0800125}
126
Alex Deymo63784a52014-05-28 10:46:14 -0700127TEST_F(UmEvaluationContextTest, GetValueFailsWithInvalidVar) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700128 EXPECT_EQ(nullptr, eval_ctx_->GetValue(static_cast<Variable<int>*>(nullptr)));
Alex Deymo23949d42014-02-05 15:20:59 -0800129}
130
Alex Deymo63784a52014-05-28 10:46:14 -0700131TEST_F(UmEvaluationContextTest, GetValueReturns) {
Alex Deymo23949d42014-02-05 15:20:59 -0800132 const int* p_fake_int;
133
134 fake_int_var_.reset(new int(42));
135 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700136 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800137 EXPECT_EQ(42, *p_fake_int);
138}
139
Alex Deymo63784a52014-05-28 10:46:14 -0700140TEST_F(UmEvaluationContextTest, GetValueCached) {
Alex Deymo23949d42014-02-05 15:20:59 -0800141 const int* p_fake_int;
142
143 fake_int_var_.reset(new int(42));
144 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
145
146 // Check that if the variable changes, the EvaluationContext keeps returning
147 // the cached value.
148 fake_int_var_.reset(new int(5));
149
150 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700151 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800152 EXPECT_EQ(42, *p_fake_int);
153}
154
Alex Deymo63784a52014-05-28 10:46:14 -0700155TEST_F(UmEvaluationContextTest, GetValueCachesNull) {
Alex Deymo23949d42014-02-05 15:20:59 -0800156 const int* p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700157 EXPECT_EQ(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800158
159 fake_int_var_.reset(new int(42));
Alex Deymocc0e5cf2014-04-23 20:20:11 -0700160 // A second attempt to read the variable should not work because this
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700161 // EvaluationContext already got a null value.
Alex Deymo23949d42014-02-05 15:20:59 -0800162 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700163 EXPECT_EQ(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800164}
165
Alex Deymo63784a52014-05-28 10:46:14 -0700166TEST_F(UmEvaluationContextTest, GetValueMixedTypes) {
Alex Deymo23949d42014-02-05 15:20:59 -0800167 const int* p_fake_int;
168 const string* p_fake_string;
169
170 fake_int_var_.reset(new int(42));
Alex Deymo53556ec2014-03-17 10:05:57 -0700171 fake_poll_var_.reset(new string("Hello world!"));
Alex Deymo23949d42014-02-05 15:20:59 -0800172 // Check that the EvaluationContext can handle multiple Variable types. This
173 // is mostly a compile-time check due to the template nature of this method.
174 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
Alex Deymo53556ec2014-03-17 10:05:57 -0700175 p_fake_string = eval_ctx_->GetValue(&fake_poll_var_);
Alex Deymo23949d42014-02-05 15:20:59 -0800176
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700177 ASSERT_NE(nullptr, p_fake_int);
Alex Deymo23949d42014-02-05 15:20:59 -0800178 EXPECT_EQ(42, *p_fake_int);
179
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700180 ASSERT_NE(nullptr, p_fake_string);
Alex Deymo23949d42014-02-05 15:20:59 -0800181 EXPECT_EQ("Hello world!", *p_fake_string);
182}
183
Alex Deymo53556ec2014-03-17 10:05:57 -0700184// Test that we don't schedule an event if there's no variable to wait for.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700185TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutWithoutVariables) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700186 fake_const_var_.reset(new string("Hello world!"));
187 EXPECT_EQ(*eval_ctx_->GetValue(&fake_const_var_), "Hello world!");
188
189 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
190}
191
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700192// Test that reevaluation occurs when an async variable it depends on changes.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700193TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutWithVariables) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700194 fake_async_var_.reset(new string("Async value"));
195 eval_ctx_->GetValue(&fake_async_var_);
196
197 bool value = false;
198 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
199 // Check that the scheduled callback isn't run until we signal a ValueChaged.
200 RunGMainLoopMaxIterations(100);
201 EXPECT_FALSE(value);
202
203 fake_async_var_.NotifyValueChanged();
204 EXPECT_FALSE(value);
205 // Ensure that the scheduled callback isn't run until we are back on the main
206 // loop.
207 RunGMainLoopMaxIterations(100);
208 EXPECT_TRUE(value);
209}
210
211// Test that we don't re-schedule the events if we are attending one.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700212TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutCalledTwice) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700213 fake_async_var_.reset(new string("Async value"));
214 eval_ctx_->GetValue(&fake_async_var_);
215
216 bool value = false;
217 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
218 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
219
220 // The scheduled event should still work.
221 fake_async_var_.NotifyValueChanged();
222 RunGMainLoopMaxIterations(100);
223 EXPECT_TRUE(value);
224}
225
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700226// Test that reevaluation occurs when a polling timeout fires.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700227TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutRunsFromTimeout) {
Alex Deymo53556ec2014-03-17 10:05:57 -0700228 fake_poll_var_.reset(new string("Polled value"));
229 eval_ctx_->GetValue(&fake_poll_var_);
230
231 bool value = false;
232 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
233 // Check that the scheduled callback isn't run until the timeout occurs.
234 RunGMainLoopMaxIterations(10);
235 EXPECT_FALSE(value);
236 RunGMainLoopUntil(10000, Bind(&GetBoolean, &value));
237 EXPECT_TRUE(value);
238}
239
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700240// Test that callback is called when evaluation context expires, and that it
Gilad Arnoldfd45a732014-08-07 15:53:46 -0700241// cannot be used again unless the expiration deadline is reset.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700242TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutExpires) {
243 fake_async_var_.reset(new string("Async value"));
244 eval_ctx_->GetValue(&fake_async_var_);
245
246 bool value = false;
247 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
248 // Check that the scheduled callback isn't run until the timeout occurs.
249 RunGMainLoopMaxIterations(10);
250 EXPECT_FALSE(value);
251 RunGMainLoopUntil(10000, Bind(&GetBoolean, &value));
252 EXPECT_TRUE(value);
253
254 // Ensure that we cannot reschedule an evaluation.
255 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
Gilad Arnoldfd45a732014-08-07 15:53:46 -0700256
257 // Ensure that we can reschedule an evaluation after resetting expiration.
258 eval_ctx_->ResetExpiration();
259 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700260}
261
262// Test that we clear the events when destroying the EvaluationContext.
263TEST_F(UmEvaluationContextTest, RemoveObserversAndTimeoutTest) {
264 fake_async_var_.reset(new string("Async value"));
265 eval_ctx_->GetValue(&fake_async_var_);
266
267 bool value = false;
268 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
269 eval_ctx_ = nullptr;
270
271 // This should not trigger the callback since the EvaluationContext waiting
272 // for it is gone, and it should have remove all its observers.
273 fake_async_var_.NotifyValueChanged();
274 RunGMainLoopMaxIterations(100);
275 EXPECT_FALSE(value);
276}
277
Gilad Arnoldfb794f42014-07-01 15:36:31 -0700278// Scheduling two reevaluations from the callback should succeed.
279TEST_F(UmEvaluationContextTest,
280 RunOnValueChangeOrTimeoutReevaluatesRepeatedly) {
281 fake_poll_var_.reset(new string("Polled value"));
282 Closure evaluation = Bind(ReadVar<string>, eval_ctx_, &fake_poll_var_);
283 int num_reevaluations = 2;
284 bool done = false;
285
286 // Run the evaluation once.
287 evaluation.Run();
288
289 // Schedule repeated reevaluations.
290 Closure closure = Bind(EvaluateRepeatedly, evaluation, eval_ctx_,
291 &num_reevaluations, &done);
292 ASSERT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(closure));
293 RunGMainLoopUntil(10000, Bind(&GetBoolean, &done));
294 EXPECT_EQ(0, num_reevaluations);
295}
296
Alex Deymodb799532014-03-21 13:00:00 -0700297// Test that we can delete the EvaluationContext while having pending events.
Alex Deymo63784a52014-05-28 10:46:14 -0700298TEST_F(UmEvaluationContextTest, ObjectDeletedWithPendingEventsTest) {
Alex Deymodb799532014-03-21 13:00:00 -0700299 fake_async_var_.reset(new string("Async value"));
300 fake_poll_var_.reset(new string("Polled value"));
301 eval_ctx_->GetValue(&fake_async_var_);
302 eval_ctx_->GetValue(&fake_poll_var_);
303 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
304 // TearDown() checks for leaked observers on this async_variable, which means
305 // that our object is still alive after removing its reference.
306}
307
308// Test that timed events fired after removal of the EvaluationContext don't
309// crash.
Alex Deymo63784a52014-05-28 10:46:14 -0700310TEST_F(UmEvaluationContextTest, TimeoutEventAfterDeleteTest) {
Alex Deymodb799532014-03-21 13:00:00 -0700311 FakeVariable<string> fake_short_poll_var = {"fake_short_poll", TimeDelta()};
312 fake_short_poll_var.reset(new string("Polled value"));
313 eval_ctx_->GetValue(&fake_short_poll_var);
314 bool value = false;
315 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
316 // Remove the last reference to the EvaluationContext and run the loop for
317 // 1 second to give time to the main loop to trigger the timeout Event (of 0
318 // seconds). Our callback should not be called because the EvaluationContext
319 // was removed before the timeout event is attended.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700320 eval_ctx_ = nullptr;
Alex Deymodb799532014-03-21 13:00:00 -0700321 RunGMainLoopUntil(1000, Bind(&GetBoolean, &value));
322 EXPECT_FALSE(value);
323}
324
Alex Deymo63784a52014-05-28 10:46:14 -0700325TEST_F(UmEvaluationContextTest, DefaultTimeout) {
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700326 // Test that the evaluation timeout calculation uses the default timeout on
327 // setup.
Alex Deymo41a75a72014-04-15 15:36:22 -0700328 EXPECT_CALL(mock_var_async_, GetValue(default_timeout_, _))
329 .WillOnce(Return(nullptr));
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700330 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&mock_var_async_));
Alex Deymo41a75a72014-04-15 15:36:22 -0700331}
332
Alex Deymo63784a52014-05-28 10:46:14 -0700333TEST_F(UmEvaluationContextTest, TimeoutUpdatesWithMonotonicTime) {
Alex Deymo41a75a72014-04-15 15:36:22 -0700334 fake_clock_.SetMonotonicTime(
335 fake_clock_.GetMonotonicTime() + TimeDelta::FromSeconds(1));
336
337 TimeDelta timeout = default_timeout_ - TimeDelta::FromSeconds(1);
338
339 EXPECT_CALL(mock_var_async_, GetValue(timeout, _))
340 .WillOnce(Return(nullptr));
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700341 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&mock_var_async_));
Alex Deymo41a75a72014-04-15 15:36:22 -0700342}
343
Gilad Arnolda65fced2014-07-23 09:01:31 -0700344TEST_F(UmEvaluationContextTest, ResetEvaluationResetsTimesWallclock) {
Alex Deymo41a75a72014-04-15 15:36:22 -0700345 base::Time cur_time = fake_clock_.GetWallclockTime();
346 // Advance the time on the clock but don't call ResetEvaluation yet.
347 fake_clock_.SetWallclockTime(cur_time + TimeDelta::FromSeconds(4));
348
Gilad Arnolda65fced2014-07-23 09:01:31 -0700349 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
350 cur_time - TimeDelta::FromSeconds(1)));
351 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time));
352 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
353 cur_time + TimeDelta::FromSeconds(1)));
Alex Deymo41a75a72014-04-15 15:36:22 -0700354 // Call ResetEvaluation now, which should use the new evaluation time.
355 eval_ctx_->ResetEvaluation();
356
357 cur_time = fake_clock_.GetWallclockTime();
Gilad Arnolda65fced2014-07-23 09:01:31 -0700358 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
359 cur_time - TimeDelta::FromSeconds(1)));
360 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time));
361 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
362 cur_time + TimeDelta::FromSeconds(1)));
Alex Deymo41a75a72014-04-15 15:36:22 -0700363}
364
Gilad Arnolda65fced2014-07-23 09:01:31 -0700365TEST_F(UmEvaluationContextTest, ResetEvaluationResetsTimesMonotonic) {
366 base::Time cur_time = fake_clock_.GetMonotonicTime();
367 // Advance the time on the clock but don't call ResetEvaluation yet.
368 fake_clock_.SetMonotonicTime(cur_time + TimeDelta::FromSeconds(4));
369
370 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
371 cur_time - TimeDelta::FromSeconds(1)));
372 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time));
373 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
374 cur_time + TimeDelta::FromSeconds(1)));
375 // Call ResetEvaluation now, which should use the new evaluation time.
376 eval_ctx_->ResetEvaluation();
377
378 cur_time = fake_clock_.GetMonotonicTime();
379 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
380 cur_time - TimeDelta::FromSeconds(1)));
381 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time));
382 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
383 cur_time + TimeDelta::FromSeconds(1)));
384}
385
386TEST_F(UmEvaluationContextTest,
387 IsWallclockTimeGreaterThanSignalsTriggerReevaluation) {
388 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
Alex Deymo41a75a72014-04-15 15:36:22 -0700389 fake_clock_.GetWallclockTime() + TimeDelta::FromSeconds(1)));
390
Gilad Arnolda65fced2014-07-23 09:01:31 -0700391 // The "false" from IsWallclockTimeGreaterThan means that's not that timestamp
392 // yet, so this should schedule a callback for when that happens.
Alex Deymo41a75a72014-04-15 15:36:22 -0700393 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
394}
395
Gilad Arnolda65fced2014-07-23 09:01:31 -0700396TEST_F(UmEvaluationContextTest,
397 IsMonotonicTimeGreaterThanSignalsTriggerReevaluation) {
398 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
399 fake_clock_.GetMonotonicTime() + TimeDelta::FromSeconds(1)));
400
401 // The "false" from IsMonotonicTimeGreaterThan means that's not that timestamp
402 // yet, so this should schedule a callback for when that happens.
403 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
404}
405
406TEST_F(UmEvaluationContextTest,
407 IsWallclockTimeGreaterThanDoesntRecordPastTimestamps) {
408 // IsWallclockTimeGreaterThan() should ignore timestamps on the past for
409 // reevaluation.
410 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
Alex Deymo41a75a72014-04-15 15:36:22 -0700411 fake_clock_.GetWallclockTime() - TimeDelta::FromSeconds(20)));
Gilad Arnolda65fced2014-07-23 09:01:31 -0700412 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
Alex Deymo41a75a72014-04-15 15:36:22 -0700413 fake_clock_.GetWallclockTime() - TimeDelta::FromSeconds(1)));
414
415 // Callback should not be scheduled.
416 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
417}
418
Gilad Arnolda65fced2014-07-23 09:01:31 -0700419TEST_F(UmEvaluationContextTest,
420 IsMonotonicTimeGreaterThanDoesntRecordPastTimestamps) {
421 // IsMonotonicTimeGreaterThan() should ignore timestamps on the past for
422 // reevaluation.
423 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
424 fake_clock_.GetMonotonicTime() - TimeDelta::FromSeconds(20)));
425 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
426 fake_clock_.GetMonotonicTime() - TimeDelta::FromSeconds(1)));
427
428 // Callback should not be scheduled.
429 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&DoNothing)));
430}
431
Alex Deymo63784a52014-05-28 10:46:14 -0700432TEST_F(UmEvaluationContextTest, DumpContext) {
David Zeuthenc1490282014-04-29 16:25:03 -0700433 // |fail_var_| yield "(no value)" since it is unset.
434 eval_ctx_->GetValue(&fail_var_);
435
436 // Check that this is included.
437 fake_int_var_.reset(new int(42));
438 eval_ctx_->GetValue(&fake_int_var_);
439
440 // Check that double-quotes are escaped properly.
441 fake_poll_var_.reset(new string("Hello \"world\"!"));
442 eval_ctx_->GetValue(&fake_poll_var_);
443
444 // Note that the variables are printed in alphabetical order. Also
Gilad Arnolda65fced2014-07-23 09:01:31 -0700445 // see UmEvaluationContextText::SetUp() where the values used for
446 // |evaluation_start_{monotonic,wallclock| are set.
David Zeuthenc1490282014-04-29 16:25:03 -0700447 EXPECT_EQ("{\n"
Gilad Arnolda65fced2014-07-23 09:01:31 -0700448 " \"evaluation_start_monotonic\": \"4/22/2009 19:25:00 GMT\",\n"
449 " \"evaluation_start_wallclock\": \"3/2/2006 1:23:45 GMT\",\n"
David Zeuthenc1490282014-04-29 16:25:03 -0700450 " \"variables\": {\n"
451 " \"fail_var\": \"(no value)\",\n"
452 " \"fake_int\": \"42\",\n"
453 " \"fake_poll\": \"Hello \\\"world\\\"!\"\n"
454 " }\n"
Gilad Arnold6e5ab5c2014-06-23 15:13:56 -0700455 "}",
David Zeuthenc1490282014-04-29 16:25:03 -0700456 eval_ctx_->DumpContext());
457}
458
Alex Deymo63784a52014-05-28 10:46:14 -0700459} // namespace chromeos_update_manager