PolicyManager: Add a generic copy variable.

This patch includes a generic class of Variable that creates copies
of a referenced object using the copy constructor. A provider that
needs to return the value of fixed object like a private member can
simply use this generic CopyVariable class.

BUG=None
TEST=unittest

Change-Id: I4e7703c0d25990f42c9c83228ba177baffadc194
Reviewed-on: https://chromium-review.googlesource.com/181963
Reviewed-by: Alex Deymo <[email protected]>
Tested-by: Alex Deymo <[email protected]>
Commit-Queue: Alex Deymo <[email protected]>
diff --git a/policy_manager/generic_variables-inl.h b/policy_manager/generic_variables-inl.h
new file mode 100644
index 0000000..f44a287
--- /dev/null
+++ b/policy_manager/generic_variables-inl.h
@@ -0,0 +1,21 @@
+// Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_POLICY_MANAGER_GENERIC_VARIABLES_INL_H
+#define CHROMEOS_PLATFORM_UPDATE_ENGINE_POLICY_MANAGER_GENERIC_VARIABLES_INL_H
+
+namespace chromeos_policy_manager {
+
+template<typename T>
+CopyVariable<T>::CopyVariable(const T& ref) : ref_(ref) {}
+
+template<typename T>
+const T* CopyVariable<T>::GetValue(base::TimeDelta /* timeout */,
+                                   std::string* /* errmsg */) {
+  return new T(ref_);
+};
+
+}  // namespace chromeos_policy_manager
+
+#endif  // CHROMEOS_PLATFORM_UPDATE_ENGINE_POLICY_MANAGER_GENERIC_VARIABLES_INL_H
diff --git a/policy_manager/generic_variables.h b/policy_manager/generic_variables.h
new file mode 100644
index 0000000..321c89a
--- /dev/null
+++ b/policy_manager/generic_variables.h
@@ -0,0 +1,69 @@
+// Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Generic and provider independent Variable subclasses. These variables can be
+// used by any state provider to implement simple variables to avoid repeat the
+// same common code on different state providers.
+
+#ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_POLICY_MANAGER_GENERIC_VARIABLES_H
+#define CHROMEOS_PLATFORM_UPDATE_ENGINE_POLICY_MANAGER_GENERIC_VARIABLES_H
+
+#include "policy_manager/variable.h"
+
+namespace chromeos_policy_manager {
+
+// Variable class returning a copy of a given object using the copy constructor.
+// This template class can be used to define variables that expose as a variable
+// any fixed object, such as the a provider's private member. The variable will
+// create copies of the provided object using the copy constructor of that
+// class.
+//
+// For example, a state provider exposing a private method as a variable could
+// be implemented in this way:
+//
+// * On something_vars.h:
+//   Variable<MyType>* var_something;
+//
+// * On something_provider:
+//   class SomethingProvider {
+//    public:
+//      SomethingProvider(...) {
+//        var_something = new CopyVariable<MyType>(priv_object_);
+//      }
+//      ~SomethingProvider() {
+//        delete var_something;
+//        var_something = NULL;
+//      }
+//    private:
+//     MyType priv_object_;
+//   };
+template<typename T>
+class CopyVariable : public Variable<T> {
+ public:
+  // Creates the variable returning copies of the passed |obj| reference. The
+  // reference to this object is kept and it should be available whenever the
+  // GetValue() method is called.
+  CopyVariable(const T& obj);
+
+  virtual ~CopyVariable() {}
+
+ protected:
+  friend class PMCopyVariableTest;
+  FRIEND_TEST(PMCopyVariableTest, SimpleTest);
+  FRIEND_TEST(PMCopyVariableTest, UseCopyConstructorTest);
+
+  // Variable override.
+  virtual const T* GetValue(base::TimeDelta timeout, std::string* errmsg);
+
+ private:
+  // Reference to the object to be copied by GetValue().
+  const T& ref_;
+};
+
+}  // namespace chromeos_policy_manager
+
+// Include implementation on header files for templates.
+#include "policy_manager/generic_variables-inl.h"
+
+#endif  // CHROMEOS_PLATFORM_UPDATE_ENGINE_POLICY_MANAGER_GENERIC_VARIABLES_H
diff --git a/policy_manager/generic_variables_unittest.cc b/policy_manager/generic_variables_unittest.cc
new file mode 100644
index 0000000..6758e23
--- /dev/null
+++ b/policy_manager/generic_variables_unittest.cc
@@ -0,0 +1,62 @@
+// Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <gtest/gtest.h>
+#include "policy_manager/generic_variables.h"
+
+using base::TimeDelta;
+using std::string;
+
+namespace chromeos_policy_manager {
+
+TEST(PMCopyVariableTest, SimpleTest) {
+  int obj_int = 5;
+
+  CopyVariable<int> var(obj_int);
+
+  string errmsg = "Nope";
+
+  const int* res_1 = var.GetValue(TimeDelta::FromSeconds(1), &errmsg);
+  EXPECT_NE(res_1, static_cast<void*>(NULL));
+  EXPECT_EQ(5, *res_1);
+
+  obj_int = 42;
+
+  // Check the result in res_1 is actually a new copy.
+  EXPECT_EQ(5, *res_1);
+
+  const int* res_2 = var.GetValue(TimeDelta::FromSeconds(1), &errmsg);
+  EXPECT_NE(res_2, static_cast<void*>(NULL));
+  EXPECT_EQ(42, *res_2);
+
+  delete res_1;
+  delete res_2;
+}
+
+class ConstructorTestClass {
+ public:
+  ConstructorTestClass(void) : copied_(false) {}
+
+  ConstructorTestClass(const ConstructorTestClass& /* ignored */)
+      : copied_(true) {}
+
+  // Tells if the instance was constructed using the copy-constructor.
+  bool copied_;
+};
+
+TEST(PMCopyVariableTest, UseCopyConstructorTest) {
+  ConstructorTestClass obj;
+  ASSERT_FALSE(obj.copied_);
+
+  string errmsg;
+  CopyVariable<ConstructorTestClass> var(obj);
+  const ConstructorTestClass* value =
+      var.GetValue(TimeDelta::FromSeconds(1), &errmsg);
+  EXPECT_NE(value, static_cast<void*>(NULL));
+  EXPECT_TRUE(value->copied_);
+
+  delete value;
+}
+
+}  // namespace chromeos_policy_manager