• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/cros/fake_system_state.h"
30 #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"
34 
35 using base::Bind;
36 using base::Closure;
37 using base::Time;
38 using base::TimeDelta;
39 using brillo::MessageLoop;
40 using brillo::MessageLoopRunMaxIterations;
41 using brillo::MessageLoopRunUntil;
42 using chromeos_update_engine::FakeClock;
43 using chromeos_update_engine::FakeSystemState;
44 using std::shared_ptr;
45 using std::string;
46 using std::unique_ptr;
47 using testing::_;
48 using testing::Return;
49 using testing::StrictMock;
50 
51 namespace chromeos_update_manager {
52 
53 namespace {
54 
55 // Sets the value of the passed pointer to true.
SetTrue(bool * value)56 void SetTrue(bool* value) {
57   *value = true;
58 }
59 
GetBoolean(bool * value)60 bool GetBoolean(bool* value) {
61   return *value;
62 }
63 
64 template <typename T>
ReadVar(shared_ptr<EvaluationContext> ec,Variable<T> * var)65 void ReadVar(shared_ptr<EvaluationContext> ec, Variable<T>* var) {
66   ec->GetValue(var);
67 }
68 
69 // 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|.
EvaluateRepeatedly(Closure evaluation,shared_ptr<EvaluationContext> ec,int * count_p,bool * done_p)71 void EvaluateRepeatedly(Closure evaluation,
72                         shared_ptr<EvaluationContext> ec,
73                         int* count_p,
74                         bool* done_p) {
75   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
89 
90 class UmEvaluationContextTest : public ::testing::Test {
91  protected:
SetUp()92   void SetUp() override {
93     FakeSystemState::CreateInstance();
94     fake_clock_ = FakeSystemState::Get()->fake_clock();
95     loop_.SetAsCurrent();
96     // Apr 22, 2009 19:25:00 UTC (this is a random reference point).
97     fake_clock_->SetMonotonicTime(Time::FromTimeT(1240428300));
98     // Mar 2, 2006 1:23:45 UTC.
99     fake_clock_->SetWallclockTime(Time::FromTimeT(1141262625));
100     eval_ctx_.reset(new EvaluationContext(
101         default_timeout_,
102         default_timeout_,
103         unique_ptr<base::Callback<void(EvaluationContext*)>>(nullptr)));
104   }
105 
TearDown()106   void TearDown() override {
107     // 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();
112       ASSERT_NE(nullptr, eval_ctx_weak_alias.get());
113       eval_ctx_ = nullptr;
114       EXPECT_EQ(nullptr, eval_ctx_weak_alias.get())
115           << "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 
120     // 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());
125 
126     EXPECT_FALSE(loop_.PendingTasks());
127   }
128 
129   TimeDelta default_timeout_ = TimeDelta::FromSeconds(5);
130 
131   brillo::FakeMessageLoop loop_{nullptr};
132   FakeClock* fake_clock_;
133   shared_ptr<EvaluationContext> eval_ctx_;
134 
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.
138   FakeVariable<bool> fail_var_ = {"fail_var", kVariableModePoll};
139   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)};
144   StrictMock<MockVariable<string>> mock_var_async_{"mock_var_async",
145                                                    kVariableModeAsync};
146   StrictMock<MockVariable<string>> mock_var_poll_{"mock_var_poll",
147                                                   kVariableModePoll};
148 };
149 
TEST_F(UmEvaluationContextTest,GetValueFails)150 TEST_F(UmEvaluationContextTest, GetValueFails) {
151   // FakeVariable is initialized as returning null.
152   EXPECT_EQ(nullptr, eval_ctx_->GetValue(&fake_int_var_));
153 }
154 
TEST_F(UmEvaluationContextTest,GetValueFailsWithInvalidVar)155 TEST_F(UmEvaluationContextTest, GetValueFailsWithInvalidVar) {
156   EXPECT_EQ(nullptr, eval_ctx_->GetValue(static_cast<Variable<int>*>(nullptr)));
157 }
158 
TEST_F(UmEvaluationContextTest,GetValueReturns)159 TEST_F(UmEvaluationContextTest, GetValueReturns) {
160   const int* p_fake_int;
161 
162   fake_int_var_.reset(new int(42));
163   p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
164   ASSERT_NE(nullptr, p_fake_int);
165   EXPECT_EQ(42, *p_fake_int);
166 }
167 
TEST_F(UmEvaluationContextTest,GetValueCached)168 TEST_F(UmEvaluationContextTest, GetValueCached) {
169   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_);
179   ASSERT_NE(nullptr, p_fake_int);
180   EXPECT_EQ(42, *p_fake_int);
181 }
182 
TEST_F(UmEvaluationContextTest,GetValueCachesNull)183 TEST_F(UmEvaluationContextTest, GetValueCachesNull) {
184   const int* p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
185   EXPECT_EQ(nullptr, p_fake_int);
186 
187   fake_int_var_.reset(new int(42));
188   // A second attempt to read the variable should not work because this
189   // EvaluationContext already got a null value.
190   p_fake_int = eval_ctx_->GetValue(&fake_int_var_);
191   EXPECT_EQ(nullptr, p_fake_int);
192 }
193 
TEST_F(UmEvaluationContextTest,GetValueMixedTypes)194 TEST_F(UmEvaluationContextTest, GetValueMixedTypes) {
195   const int* p_fake_int;
196   const string* p_fake_string;
197 
198   fake_int_var_.reset(new int(42));
199   fake_poll_var_.reset(new string("Hello world!"));
200   // 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_);
203   p_fake_string = eval_ctx_->GetValue(&fake_poll_var_);
204 
205   ASSERT_NE(nullptr, p_fake_int);
206   EXPECT_EQ(42, *p_fake_int);
207 
208   ASSERT_NE(nullptr, p_fake_string);
209   EXPECT_EQ("Hello world!", *p_fake_string);
210 }
211 
212 // Test that we don't schedule an event if there's no variable to wait for.
TEST_F(UmEvaluationContextTest,RunOnValueChangeOrTimeoutWithoutVariables)213 TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutWithoutVariables) {
214   fake_const_var_.reset(new string("Hello world!"));
215   EXPECT_EQ(*eval_ctx_->GetValue(&fake_const_var_), "Hello world!");
216 
217   EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
218 }
219 
220 // Test that reevaluation occurs when an async variable it depends on changes.
TEST_F(UmEvaluationContextTest,RunOnValueChangeOrTimeoutWithVariables)221 TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutWithVariables) {
222   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.
228   MessageLoopRunMaxIterations(MessageLoop::current(), 100);
229   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.
235   MessageLoopRunMaxIterations(MessageLoop::current(), 100);
236   EXPECT_TRUE(value);
237 }
238 
239 // Test that we don't re-schedule the events if we are attending one.
TEST_F(UmEvaluationContextTest,RunOnValueChangeOrTimeoutCalledTwice)240 TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutCalledTwice) {
241   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();
250   MessageLoopRunMaxIterations(MessageLoop::current(), 100);
251   EXPECT_TRUE(value);
252 }
253 
254 // Test that reevaluation occurs when a polling timeout fires.
TEST_F(UmEvaluationContextTest,RunOnValueChangeOrTimeoutRunsFromTimeout)255 TEST_F(UmEvaluationContextTest, RunOnValueChangeOrTimeoutRunsFromTimeout) {
256   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.
262   MessageLoopRunMaxIterations(MessageLoop::current(), 10);
263   EXPECT_FALSE(value);
264   MessageLoopRunUntil(MessageLoop::current(),
265                       TimeDelta::FromSeconds(10),
266                       Bind(&GetBoolean, &value));
267   EXPECT_TRUE(value);
268 }
269 
270 // Test that callback is called when evaluation context expires, and that it
271 // cannot be used again unless the expiration deadline is reset.
TEST_F(UmEvaluationContextTest,RunOnValueChangeOrTimeoutExpires)272 TEST_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.
279   MessageLoopRunMaxIterations(MessageLoop::current(), 10);
280   EXPECT_FALSE(value);
281   MessageLoopRunUntil(MessageLoop::current(),
282                       TimeDelta::FromSeconds(10),
283                       Bind(&GetBoolean, &value));
284   EXPECT_TRUE(value);
285 
286   // Ensure that we cannot reschedule an evaluation.
287   EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
288 
289   // Ensure that we can reschedule an evaluation after resetting expiration.
290   eval_ctx_->ResetExpiration();
291   EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
292 }
293 
294 // Test that we clear the events when destroying the EvaluationContext.
TEST_F(UmEvaluationContextTest,RemoveObserversAndTimeoutTest)295 TEST_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();
306   MessageLoopRunMaxIterations(MessageLoop::current(), 100);
307   EXPECT_FALSE(value);
308 }
309 
310 // Scheduling two reevaluations from the callback should succeed.
TEST_F(UmEvaluationContextTest,RunOnValueChangeOrTimeoutReevaluatesRepeatedly)311 TEST_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.
322   Closure closure = Bind(
323       EvaluateRepeatedly, evaluation, eval_ctx_, &num_reevaluations, &done);
324   ASSERT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(closure));
325   MessageLoopRunUntil(MessageLoop::current(),
326                       TimeDelta::FromSeconds(10),
327                       Bind(&GetBoolean, &done));
328   EXPECT_EQ(0, num_reevaluations);
329 }
330 
331 // Test that we can delete the EvaluationContext while having pending events.
TEST_F(UmEvaluationContextTest,ObjectDeletedWithPendingEventsTest)332 TEST_F(UmEvaluationContextTest, ObjectDeletedWithPendingEventsTest) {
333   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_);
337   EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
338   // 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.
TEST_F(UmEvaluationContextTest,TimeoutEventAfterDeleteTest)344 TEST_F(UmEvaluationContextTest, TimeoutEventAfterDeleteTest) {
345   FakeVariable<string> fake_short_poll_var = {"fake_short_poll",
346                                               TimeDelta::FromSeconds(1)};
347   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
352   // 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
354   // was removed before the timeout event is attended.
355   eval_ctx_ = nullptr;
356   MessageLoopRunUntil(MessageLoop::current(),
357                       TimeDelta::FromSeconds(10),
358                       Bind(&GetBoolean, &value));
359   EXPECT_FALSE(value);
360 }
361 
TEST_F(UmEvaluationContextTest,DefaultTimeout)362 TEST_F(UmEvaluationContextTest, DefaultTimeout) {
363   // Test that the evaluation timeout calculation uses the default timeout on
364   // setup.
365   EXPECT_CALL(mock_var_async_, GetValue(default_timeout_, _))
366       .WillOnce(Return(nullptr));
367   EXPECT_EQ(nullptr, eval_ctx_->GetValue(&mock_var_async_));
368 }
369 
TEST_F(UmEvaluationContextTest,TimeoutUpdatesWithMonotonicTime)370 TEST_F(UmEvaluationContextTest, TimeoutUpdatesWithMonotonicTime) {
371   fake_clock_->SetMonotonicTime(fake_clock_->GetMonotonicTime() +
372                                 TimeDelta::FromSeconds(1));
373 
374   TimeDelta timeout = default_timeout_ - TimeDelta::FromSeconds(1);
375 
376   EXPECT_CALL(mock_var_async_, GetValue(timeout, _)).WillOnce(Return(nullptr));
377   EXPECT_EQ(nullptr, eval_ctx_->GetValue(&mock_var_async_));
378 }
379 
TEST_F(UmEvaluationContextTest,ResetEvaluationResetsTimesWallclock)380 TEST_F(UmEvaluationContextTest, ResetEvaluationResetsTimesWallclock) {
381   Time cur_time = fake_clock_->GetWallclockTime();
382   // Advance the time on the clock but don't call ResetEvaluation yet.
383   fake_clock_->SetWallclockTime(cur_time + TimeDelta::FromSeconds(4));
384 
385   EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time -
386                                                     TimeDelta::FromSeconds(1)));
387   EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time));
388   EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
389       cur_time + TimeDelta::FromSeconds(1)));
390   // Call ResetEvaluation now, which should use the new evaluation time.
391   eval_ctx_->ResetEvaluation();
392 
393   cur_time = fake_clock_->GetWallclockTime();
394   EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time -
395                                                     TimeDelta::FromSeconds(1)));
396   EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(cur_time));
397   EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
398       cur_time + TimeDelta::FromSeconds(1)));
399 }
400 
TEST_F(UmEvaluationContextTest,ResetEvaluationResetsTimesMonotonic)401 TEST_F(UmEvaluationContextTest, ResetEvaluationResetsTimesMonotonic) {
402   Time cur_time = fake_clock_->GetMonotonicTime();
403   // Advance the time on the clock but don't call ResetEvaluation yet.
404   fake_clock_->SetMonotonicTime(cur_time + TimeDelta::FromSeconds(4));
405 
406   EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time -
407                                                     TimeDelta::FromSeconds(1)));
408   EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time));
409   EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
410       cur_time + TimeDelta::FromSeconds(1)));
411   // Call ResetEvaluation now, which should use the new evaluation time.
412   eval_ctx_->ResetEvaluation();
413 
414   cur_time = fake_clock_->GetMonotonicTime();
415   EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time -
416                                                     TimeDelta::FromSeconds(1)));
417   EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(cur_time));
418   EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
419       cur_time + TimeDelta::FromSeconds(1)));
420 }
421 
TEST_F(UmEvaluationContextTest,IsWallclockTimeGreaterThanSignalsTriggerReevaluation)422 TEST_F(UmEvaluationContextTest,
423        IsWallclockTimeGreaterThanSignalsTriggerReevaluation) {
424   EXPECT_FALSE(eval_ctx_->IsWallclockTimeGreaterThan(
425       fake_clock_->GetWallclockTime() + TimeDelta::FromSeconds(1)));
426 
427   // The "false" from IsWallclockTimeGreaterThan means that's not that timestamp
428   // yet, so this should schedule a callback for when that happens.
429   EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
430 }
431 
TEST_F(UmEvaluationContextTest,IsMonotonicTimeGreaterThanSignalsTriggerReevaluation)432 TEST_F(UmEvaluationContextTest,
433        IsMonotonicTimeGreaterThanSignalsTriggerReevaluation) {
434   EXPECT_FALSE(eval_ctx_->IsMonotonicTimeGreaterThan(
435       fake_clock_->GetMonotonicTime() + TimeDelta::FromSeconds(1)));
436 
437   // The "false" from IsMonotonicTimeGreaterThan means that's not that timestamp
438   // yet, so this should schedule a callback for when that happens.
439   EXPECT_TRUE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
440 }
441 
TEST_F(UmEvaluationContextTest,IsWallclockTimeGreaterThanDoesntRecordPastTimestamps)442 TEST_F(UmEvaluationContextTest,
443        IsWallclockTimeGreaterThanDoesntRecordPastTimestamps) {
444   // IsWallclockTimeGreaterThan() should ignore timestamps on the past for
445   // reevaluation.
446   EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
447       fake_clock_->GetWallclockTime() - TimeDelta::FromSeconds(20)));
448   EXPECT_TRUE(eval_ctx_->IsWallclockTimeGreaterThan(
449       fake_clock_->GetWallclockTime() - TimeDelta::FromSeconds(1)));
450 
451   // Callback should not be scheduled.
452   EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
453 }
454 
TEST_F(UmEvaluationContextTest,IsMonotonicTimeGreaterThanDoesntRecordPastTimestamps)455 TEST_F(UmEvaluationContextTest,
456        IsMonotonicTimeGreaterThanDoesntRecordPastTimestamps) {
457   // IsMonotonicTimeGreaterThan() should ignore timestamps on the past for
458   // reevaluation.
459   EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
460       fake_clock_->GetMonotonicTime() - TimeDelta::FromSeconds(20)));
461   EXPECT_TRUE(eval_ctx_->IsMonotonicTimeGreaterThan(
462       fake_clock_->GetMonotonicTime() - TimeDelta::FromSeconds(1)));
463 
464   // Callback should not be scheduled.
465   EXPECT_FALSE(eval_ctx_->RunOnValueChangeOrTimeout(base::DoNothing()));
466 }
467 
TEST_F(UmEvaluationContextTest,DumpContext)468 TEST_F(UmEvaluationContextTest, DumpContext) {
469   // |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
481   // see UmEvaluationContextText::SetUp() where the values used for
482   // |evaluation_start_{monotonic,wallclock| are set.
483   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());
494 }
495 
496 }  // namespace chromeos_update_manager
497