1 //
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 //
16
17 #include "update_engine/update_manager/evaluation_context.h"
18
19 #include <memory>
20 #include <string>
21
22 #include <base/bind.h>
23 #include <base/bind_helpers.h>
24 #include <brillo/message_loops/fake_message_loop.h>
25 #include <brillo/message_loops/message_loop_utils.h>
26 #include <gtest/gtest.h>
27
28 #include "update_engine/common/fake_clock.h"
29 #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"
33
34 using base::Bind;
35 using base::Closure;
36 using base::Time;
37 using base::TimeDelta;
38 using brillo::MessageLoop;
39 using brillo::MessageLoopRunMaxIterations;
40 using brillo::MessageLoopRunUntil;
41 using chromeos_update_engine::FakeClock;
42 using std::string;
43 using std::unique_ptr;
44 using testing::_;
45 using testing::Return;
46 using testing::StrictMock;
47
48 namespace chromeos_update_manager {
49
50 namespace {
51
52 // Sets the value of the passed pointer to true.
SetTrue(bool * value)53 void SetTrue(bool* value) {
54 *value = true;
55 }
56
GetBoolean(bool * value)57 bool GetBoolean(bool* value) {
58 return *value;
59 }
60
61 template <typename T>
ReadVar(scoped_refptr<EvaluationContext> ec,Variable<T> * var)62 void ReadVar(scoped_refptr<EvaluationContext> ec, Variable<T>* var) {
63 ec->GetValue(var);
64 }
65
66 // 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|.
EvaluateRepeatedly(Closure evaluation,scoped_refptr<EvaluationContext> ec,int * count_p,bool * done_p)68 void EvaluateRepeatedly(Closure evaluation,
69 scoped_refptr<EvaluationContext> ec,
70 int* count_p,
71 bool* done_p) {
72 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
86
87 class UmEvaluationContextTest : public ::testing::Test {
88 protected:
SetUp()89 void SetUp() override {
90 loop_.SetAsCurrent();
91 // 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.
94 fake_clock_.SetWallclockTime(Time::FromTimeT(1141262625));
95 eval_ctx_ = new EvaluationContext(
96 &fake_clock_,
97 default_timeout_,
98 default_timeout_,
99 unique_ptr<base::Callback<void(EvaluationContext*)>>(nullptr));
100 }
101
TearDown()102 void TearDown() override {
103 // 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();
108 ASSERT_NE(nullptr, eval_ctx_weak_alias.get());
109 eval_ctx_ = nullptr;
110 EXPECT_EQ(nullptr, eval_ctx_weak_alias.get())
111 << "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
116 // 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());
121
122 EXPECT_FALSE(loop_.PendingTasks());
123 }
124
125 TimeDelta default_timeout_ = TimeDelta::FromSeconds(5);
126
127 brillo::FakeMessageLoop loop_{nullptr};
128 FakeClock fake_clock_;
129 scoped_refptr<EvaluationContext> eval_ctx_;
130
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.
134 FakeVariable<bool> fail_var_ = {"fail_var", kVariableModePoll};
135 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)};
140 StrictMock<MockVariable<string>> mock_var_async_{"mock_var_async",
141 kVariableModeAsync};
142 StrictMock<MockVariable<string>> mock_var_poll_{"mock_var_poll",
143 kVariableModePoll};
144 };
145
TEST_F(UmEvaluationContextTest,GetValueFails)146 TEST_F(UmEvaluationContextTest, GetValueFails) {
147 // FakeVariable is initialized as returning null.
148 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&fake_int_var_));
149 }
150
TEST_F(UmEvaluationContextTest,GetValueFailsWithInvalidVar)151 TEST_F(UmEvaluationContextTest, GetValueFailsWithInvalidVar) {
152 EXPECT_EQ(nullptr, eval_ctx_->GetValue(static_cast<Variable<int>*>(nullptr)));
153 }
154
TEST_F(UmEvaluationContextTest,GetValueReturns)155 TEST_F(UmEvaluationContextTest, GetValueReturns) {
156 const int* p_fake_int;
157
158 fake_int_var_.reset(new int(42));
159 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
160 ASSERT_NE(nullptr, p_fake_int);
161 EXPECT_EQ(42, *p_fake_int);
162 }
163
TEST_F(UmEvaluationContextTest,GetValueCached)164 TEST_F(UmEvaluationContextTest, GetValueCached) {
165 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_);
175 ASSERT_NE(nullptr, p_fake_int);
176 EXPECT_EQ(42, *p_fake_int);
177 }
178
TEST_F(UmEvaluationContextTest,GetValueCachesNull)179 TEST_F(UmEvaluationContextTest, GetValueCachesNull) {
180 const int* p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
181 EXPECT_EQ(nullptr, p_fake_int);
182
183 fake_int_var_.reset(new int(42));
184 // A second attempt to read the variable should not work because this
185 // EvaluationContext already got a null value.
186 p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
187 EXPECT_EQ(nullptr, p_fake_int);
188 }
189
TEST_F(UmEvaluationContextTest,GetValueMixedTypes)190 TEST_F(UmEvaluationContextTest, GetValueMixedTypes) {
191 const int* p_fake_int;
192 const string* p_fake_string;
193
194 fake_int_var_.reset(new int(42));
195 fake_poll_var_.reset(new string("Hello world!"));
196 // 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_);
199 p_fake_string = eval_ctx_->GetValue(&fake_poll_var_);
200
201 ASSERT_NE(nullptr, p_fake_int);
202 EXPECT_EQ(42, *p_fake_int);
203
204 ASSERT_NE(nullptr, p_fake_string);
205 EXPECT_EQ("Hello world!", *p_fake_string);
206 }
207
208 // Test that we don't schedule an event if there's no variable to wait for.
TEST_F(UmEvaluationContextTest,RunOnValueChangeOrTimeoutWithoutVariables)209 TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutWithoutVariables) {
210 fake_const_var_.reset(new string("Hello world!"));
211 EXPECT_EQ(*eval_ctx_->GetValue(&fake_const_var_), "Hello world!");
212
213 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(
214 #if BASE_VER < 576279
215 Bind(&base::DoNothing)
216 #else
217 base::DoNothing()
218 #endif
219 ));
220 }
221
222 // Test that reevaluation occurs when an async variable it depends on changes.
TEST_F(UmEvaluationContextTest,RunOnValueChangeOrTimeoutWithVariables)223 TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutWithVariables) {
224 fake_async_var_.reset(new string("Async value"));
225 eval_ctx_->GetValue(&fake_async_var_);
226
227 bool value = false;
228 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
229 // Check that the scheduled callback isn't run until we signal a ValueChaged.
230 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
231 EXPECT_FALSE(value);
232
233 fake_async_var_.NotifyValueChanged();
234 EXPECT_FALSE(value);
235 // Ensure that the scheduled callback isn't run until we are back on the main
236 // loop.
237 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
238 EXPECT_TRUE(value);
239 }
240
241 // Test that we don't re-schedule the events if we are attending one.
TEST_F(UmEvaluationContextTest,RunOnValueChangeOrTimeoutCalledTwice)242 TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutCalledTwice) {
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 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
249
250 // The scheduled event should still work.
251 fake_async_var_.NotifyValueChanged();
252 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
253 EXPECT_TRUE(value);
254 }
255
256 // Test that reevaluation occurs when a polling timeout fires.
TEST_F(UmEvaluationContextTest,RunOnValueChangeOrTimeoutRunsFromTimeout)257 TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutRunsFromTimeout) {
258 fake_poll_var_.reset(new string("Polled value"));
259 eval_ctx_->GetValue(&fake_poll_var_);
260
261 bool value = false;
262 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
263 // Check that the scheduled callback isn't run until the timeout occurs.
264 MessageLoopRunMaxIterations(MessageLoop::current(), 10);
265 EXPECT_FALSE(value);
266 MessageLoopRunUntil(MessageLoop::current(),
267 TimeDelta::FromSeconds(10),
268 Bind(&GetBoolean, &value));
269 EXPECT_TRUE(value);
270 }
271
272 // Test that callback is called when evaluation context expires, and that it
273 // cannot be used again unless the expiration deadline is reset.
TEST_F(UmEvaluationContextTest,RunOnValueChangeOrTimeoutExpires)274 TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutExpires) {
275 fake_async_var_.reset(new string("Async value"));
276 eval_ctx_->GetValue(&fake_async_var_);
277
278 bool value = false;
279 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
280 // Check that the scheduled callback isn't run until the timeout occurs.
281 MessageLoopRunMaxIterations(MessageLoop::current(), 10);
282 EXPECT_FALSE(value);
283 MessageLoopRunUntil(MessageLoop::current(),
284 TimeDelta::FromSeconds(10),
285 Bind(&GetBoolean, &value));
286 EXPECT_TRUE(value);
287
288 // Ensure that we cannot reschedule an evaluation.
289 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(
290 #if BASE_VER < 576279
291 Bind(&base::DoNothing)
292 #else
293 base::DoNothing()
294 #endif
295 ));
296
297 // Ensure that we can reschedule an evaluation after resetting expiration.
298 eval_ctx_->ResetExpiration();
299 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(
300 #if BASE_VER < 576279
301 Bind(&base::DoNothing)
302 #else
303 base::DoNothing()
304 #endif
305 ));
306 }
307
308 // Test that we clear the events when destroying the EvaluationContext.
TEST_F(UmEvaluationContextTest,RemoveObserversAndTimeoutTest)309 TEST_F(UmEvaluationContextTest, RemoveObserversAndTimeoutTest) {
310 fake_async_var_.reset(new string("Async value"));
311 eval_ctx_->GetValue(&fake_async_var_);
312
313 bool value = false;
314 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
315 eval_ctx_ = nullptr;
316
317 // This should not trigger the callback since the EvaluationContext waiting
318 // for it is gone, and it should have remove all its observers.
319 fake_async_var_.NotifyValueChanged();
320 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
321 EXPECT_FALSE(value);
322 }
323
324 // Scheduling two reevaluations from the callback should succeed.
TEST_F(UmEvaluationContextTest,RunOnValueChangeOrTimeoutReevaluatesRepeatedly)325 TEST_F(UmEvaluationContextTest,
326 RunOnValueChangeOrTimeoutReevaluatesRepeatedly) {
327 fake_poll_var_.reset(new string("Polled value"));
328 Closure evaluation = Bind(ReadVar<string>, eval_ctx_, &fake_poll_var_);
329 int num_reevaluations = 2;
330 bool done = false;
331
332 // Run the evaluation once.
333 evaluation.Run();
334
335 // Schedule repeated reevaluations.
336 Closure closure = Bind(
337 EvaluateRepeatedly, evaluation, eval_ctx_, &num_reevaluations, &done);
338 ASSERT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(closure));
339 MessageLoopRunUntil(MessageLoop::current(),
340 TimeDelta::FromSeconds(10),
341 Bind(&GetBoolean, &done));
342 EXPECT_EQ(0, num_reevaluations);
343 }
344
345 // Test that we can delete the EvaluationContext while having pending events.
TEST_F(UmEvaluationContextTest,ObjectDeletedWithPendingEventsTest)346 TEST_F(UmEvaluationContextTest, ObjectDeletedWithPendingEventsTest) {
347 fake_async_var_.reset(new string("Async value"));
348 fake_poll_var_.reset(new string("Polled value"));
349 eval_ctx_->GetValue(&fake_async_var_);
350 eval_ctx_->GetValue(&fake_poll_var_);
351 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(
352 #if BASE_VER < 576279
353 Bind(&base::DoNothing)
354 #else
355 base::DoNothing()
356 #endif
357 ));
358 // TearDown() checks for leaked observers on this async_variable, which means
359 // that our object is still alive after removing its reference.
360 }
361
362 // Test that timed events fired after removal of the EvaluationContext don't
363 // crash.
TEST_F(UmEvaluationContextTest,TimeoutEventAfterDeleteTest)364 TEST_F(UmEvaluationContextTest, TimeoutEventAfterDeleteTest) {
365 FakeVariable<string> fake_short_poll_var = {"fake_short_poll",
366 TimeDelta::FromSeconds(1)};
367 fake_short_poll_var.reset(new string("Polled value"));
368 eval_ctx_->GetValue(&fake_short_poll_var);
369 bool value = false;
370 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(Bind(&SetTrue, &value)));
371 // Remove the last reference to the EvaluationContext and run the loop for
372 // 10 seconds to give time to the main loop to trigger the timeout Event (of 1
373 // second). Our callback should not be called because the EvaluationContext
374 // was removed before the timeout event is attended.
375 eval_ctx_ = nullptr;
376 MessageLoopRunUntil(MessageLoop::current(),
377 TimeDelta::FromSeconds(10),
378 Bind(&GetBoolean, &value));
379 EXPECT_FALSE(value);
380 }
381
TEST_F(UmEvaluationContextTest,DefaultTimeout)382 TEST_F(UmEvaluationContextTest, DefaultTimeout) {
383 // Test that the evaluation timeout calculation uses the default timeout on
384 // setup.
385 EXPECT_CALL(mock_var_async_, GetValue(default_timeout_, _))
386 .WillOnce(Return(nullptr));
387 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&mock_var_async_));
388 }
389
TEST_F(UmEvaluationContextTest,TimeoutUpdatesWithMonotonicTime)390 TEST_F(UmEvaluationContextTest, TimeoutUpdatesWithMonotonicTime) {
391 fake_clock_.SetMonotonicTime(fake_clock_.GetMonotonicTime() +
392 TimeDelta::FromSeconds(1));
393
394 TimeDelta timeout = default_timeout_ - TimeDelta::FromSeconds(1);
395
396 EXPECT_CALL(mock_var_async_, GetValue(timeout, _)).WillOnce(Return(nullptr));
397 EXPECT_EQ(nullptr, eval_ctx_->GetValue(&mock_var_async_));
398 }
399
TEST_F(UmEvaluationContextTest,ResetEvaluationResetsTimesWallclock)400 TEST_F(UmEvaluationContextTest, ResetEvaluationResetsTimesWallclock) {
401 Time cur_time = fake_clock_.GetWallclockTime();
402 // Advance the time on the clock but don't call ResetEvaluation yet.
403 fake_clock_.SetWallclockTime(cur_time + TimeDelta::FromSeconds(4));
404
405 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time -
406 TimeDelta::FromSeconds(1)));
407 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time));
408 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
409 cur_time + TimeDelta::FromSeconds(1)));
410 // Call ResetEvaluation now, which should use the new evaluation time.
411 eval_ctx_->ResetEvaluation();
412
413 cur_time = fake_clock_.GetWallclockTime();
414 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time -
415 TimeDelta::FromSeconds(1)));
416 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time));
417 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
418 cur_time + TimeDelta::FromSeconds(1)));
419 }
420
TEST_F(UmEvaluationContextTest,ResetEvaluationResetsTimesMonotonic)421 TEST_F(UmEvaluationContextTest, ResetEvaluationResetsTimesMonotonic) {
422 Time cur_time = fake_clock_.GetMonotonicTime();
423 // Advance the time on the clock but don't call ResetEvaluation yet.
424 fake_clock_.SetMonotonicTime(cur_time + TimeDelta::FromSeconds(4));
425
426 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time -
427 TimeDelta::FromSeconds(1)));
428 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time));
429 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
430 cur_time + TimeDelta::FromSeconds(1)));
431 // Call ResetEvaluation now, which should use the new evaluation time.
432 eval_ctx_->ResetEvaluation();
433
434 cur_time = fake_clock_.GetMonotonicTime();
435 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time -
436 TimeDelta::FromSeconds(1)));
437 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time));
438 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
439 cur_time + TimeDelta::FromSeconds(1)));
440 }
441
TEST_F(UmEvaluationContextTest,IsWallclockTimeGreaterThanSignalsTriggerReevaluation)442 TEST_F(UmEvaluationContextTest,
443 IsWallclockTimeGreaterThanSignalsTriggerReevaluation) {
444 EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
445 fake_clock_.GetWallclockTime() + TimeDelta::FromSeconds(1)));
446
447 // The "false" from IsWallclockTimeGreaterThan means that's not that timestamp
448 // yet, so this should schedule a callback for when that happens.
449 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(
450 #if BASE_VER < 576279
451 Bind(&base::DoNothing)
452 #else
453 base::DoNothing()
454 #endif
455 ));
456 }
457
TEST_F(UmEvaluationContextTest,IsMonotonicTimeGreaterThanSignalsTriggerReevaluation)458 TEST_F(UmEvaluationContextTest,
459 IsMonotonicTimeGreaterThanSignalsTriggerReevaluation) {
460 EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
461 fake_clock_.GetMonotonicTime() + TimeDelta::FromSeconds(1)));
462
463 // The "false" from IsMonotonicTimeGreaterThan means that's not that timestamp
464 // yet, so this should schedule a callback for when that happens.
465 EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(
466 #if BASE_VER < 576279
467 Bind(&base::DoNothing)
468 #else
469 base::DoNothing()
470 #endif
471 ));
472 }
473
TEST_F(UmEvaluationContextTest,IsWallclockTimeGreaterThanDoesntRecordPastTimestamps)474 TEST_F(UmEvaluationContextTest,
475 IsWallclockTimeGreaterThanDoesntRecordPastTimestamps) {
476 // IsWallclockTimeGreaterThan() should ignore timestamps on the past for
477 // reevaluation.
478 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
479 fake_clock_.GetWallclockTime() - TimeDelta::FromSeconds(20)));
480 EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
481 fake_clock_.GetWallclockTime() - TimeDelta::FromSeconds(1)));
482
483 // Callback should not be scheduled.
484 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(
485 #if BASE_VER < 576279
486 Bind(&base::DoNothing)
487 #else
488 base::DoNothing()
489 #endif
490 ));
491 }
492
TEST_F(UmEvaluationContextTest,IsMonotonicTimeGreaterThanDoesntRecordPastTimestamps)493 TEST_F(UmEvaluationContextTest,
494 IsMonotonicTimeGreaterThanDoesntRecordPastTimestamps) {
495 // IsMonotonicTimeGreaterThan() should ignore timestamps on the past for
496 // reevaluation.
497 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
498 fake_clock_.GetMonotonicTime() - TimeDelta::FromSeconds(20)));
499 EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
500 fake_clock_.GetMonotonicTime() - TimeDelta::FromSeconds(1)));
501
502 // Callback should not be scheduled.
503 EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(
504 #if BASE_VER < 576279
505 Bind(&base::DoNothing)
506 #else
507 base::DoNothing()
508 #endif
509 ));
510 }
511
TEST_F(UmEvaluationContextTest,DumpContext)512 TEST_F(UmEvaluationContextTest, DumpContext) {
513 // |fail_var_| yield "(no value)" since it is unset.
514 eval_ctx_->GetValue(&fail_var_);
515
516 // Check that this is included.
517 fake_int_var_.reset(new int(42));
518 eval_ctx_->GetValue(&fake_int_var_);
519
520 // Check that double-quotes are escaped properly.
521 fake_poll_var_.reset(new string("Hello \"world\"!"));
522 eval_ctx_->GetValue(&fake_poll_var_);
523
524 // Note that the variables are printed in alphabetical order. Also
525 // see UmEvaluationContextText::SetUp() where the values used for
526 // |evaluation_start_{monotonic,wallclock| are set.
527 EXPECT_EQ(
528 "{\n"
529 " \"evaluation_start_monotonic\": \"4/22/2009 19:25:00 GMT\",\n"
530 " \"evaluation_start_wallclock\": \"3/2/2006 1:23:45 GMT\",\n"
531 " \"variables\": {\n"
532 " \"fail_var\": \"(no value)\",\n"
533 " \"fake_int\": \"42\",\n"
534 " \"fake_poll\": \"Hello \\\"world\\\"!\"\n"
535 " }\n"
536 "}",
537 eval_ctx_->DumpContext());
538 }
539
540 } // namespace chromeos_update_manager
541