PolicyManager: Initial support of async PolicyRequests.

This patch adds the new method PolicyManager::AsyncPolicyRequest
that takes a callback to be called once the policy request finishes.

If the given policy request returns kAskMeAgainLater, its evaluation
will be re-scheduled until it returns a given value. On this initial
patch, the evaluation is re-scheduled to happen after a fixed amount
of time instead of using the information collected on the
EvaluationContext.

BUG=chromium:340871
TEST=Unittest added.

Change-Id: If0e2888f26c379b806d811d52c4c3d4a8a6d8efb
Reviewed-on: https://chromium-review.googlesource.com/189636
Tested-by: Alex Deymo <deymo@chromium.org>
Reviewed-by: Alex Deymo <deymo@chromium.org>
Commit-Queue: Alex Deymo <deymo@chromium.org>
diff --git a/policy_manager/policy_manager_unittest.cc b/policy_manager/policy_manager_unittest.cc
index b9253d3..9e28ebc 100644
--- a/policy_manager/policy_manager_unittest.cc
+++ b/policy_manager/policy_manager_unittest.cc
@@ -2,19 +2,28 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include <base/bind.h>
 #include <base/memory/scoped_ptr.h>
 #include <base/time.h>
 #include <gtest/gtest.h>
 #include <gmock/gmock.h>
-#include <string>
 
 #include "update_engine/policy_manager/default_policy.h"
 #include "update_engine/policy_manager/mock_policy.h"
 #include "update_engine/policy_manager/pmtest_utils.h"
 #include "update_engine/policy_manager/policy_manager.h"
+#include "update_engine/test_utils.h"
 
+using base::Bind;
+using base::Callback;
 using base::TimeDelta;
+using std::pair;
 using std::string;
+using std::vector;
 
 using testing::_;
 using testing::Return;
@@ -43,7 +52,7 @@
   }
 };
 
-// The LazyPolicy always returns
+// The LazyPolicy always returns EvalStatus::kAskMeAgainLater.
 class LazyPolicy : public DefaultPolicy {
   virtual EvalStatus UpdateCheckAllowed(EvaluationContext* ec, State* state,
                                         string* error,
@@ -52,6 +61,16 @@
   }
 };
 
+// AccumulateCallsCallback() adds to the passed |acc| accumulator vector pairs
+// of EvalStatus and T instances. This allows to create a callback that keeps
+// track of when it is called and the arguments passed to it, to be used with
+// the PolicyManager::AsyncPolicyRequest().
+template<typename T>
+static void AccumulateCallsCallback(vector<pair<EvalStatus, T>>* acc,
+                                    EvalStatus status, const T& result) {
+  acc->push_back(std::make_pair(status, result));
+}
+
 TEST_F(PmPolicyManagerTest, PolicyRequestCall) {
   bool result;
   EvalStatus status = pmut_.PolicyRequest(&Policy::UpdateCheckAllowed, &result);
@@ -89,4 +108,22 @@
   EXPECT_EQ(status, EvalStatus::kAskMeAgainLater);
 }
 
+TEST_F(PmPolicyManagerTest, AsyncPolicyRequestDelaysEvaluation) {
+  // To avoid differences in code execution order between an AsyncPolicyRequest
+  // call on a policy that returns AskMeAgainLater the first time and one that
+  // succeeds the first time, we ensure that the passed callback is called from
+  // the main loop in both cases even when we could evaluate it right now.
+  pmut_.policy_.reset(new FailingPolicy());
+
+  vector<pair<EvalStatus, bool>> calls;
+  Callback<void(EvalStatus, const bool& result)> callback =
+      Bind(AccumulateCallsCallback<bool>, &calls);
+
+  pmut_.AsyncPolicyRequest(callback, &Policy::UpdateCheckAllowed);
+  // The callback should wait until we run the main loop for it to be executed.
+  EXPECT_EQ(0, calls.size());
+  chromeos_update_engine::RunGMainLoopMaxIterations(100);
+  EXPECT_EQ(1, calls.size());
+}
+
 }  // namespace chromeos_policy_manager