shill: PropertyChangeNotifier: Initial commit

Add a PropertyObserver, whose task is to track changes
to the returned value of an accessor.  Further, create
a ServicePropertyChangeNotifier, whose task is to monitor
a collection of PropertyObservers for a Service and call
the appropriate Emit*Property method for those properties
which have changed.

BUG=chromium:379948
TEST=Unit tests
Change-Id: I450b74b388f8ecb44010f277cc77149412b24950
Reviewed-on: https://chromium-review.googlesource.com/202441
Reviewed-by: mukesh agrawal <quiche@chromium.org>
Commit-Queue: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/property_observer_unittest.cc b/property_observer_unittest.cc
new file mode 100644
index 0000000..3b8e09e
--- /dev/null
+++ b/property_observer_unittest.cc
@@ -0,0 +1,90 @@
+// 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 "shill/property_observer.h"
+
+#include <string>
+
+#include <base/bind.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "shill/accessor_interface.h"
+#include "shill/error.h"
+
+using base::Bind;
+using base::Unretained;
+using testing::_;
+using testing::DoAll;
+using testing::Mock;
+using testing::Return;
+
+namespace shill {
+
+class TestPropertyAccessor : public AccessorInterface<bool> {
+ public:
+  MOCK_METHOD1(Clear, void(Error *error));
+  MOCK_METHOD1(Get, bool(Error *error));
+  MOCK_METHOD2(Set, bool(const bool &value, Error *error));
+};
+
+class PropertyObserverTest : public testing::Test {
+ public:
+  PropertyObserverTest()
+     : test_accessor_(new TestPropertyAccessor()),
+       bool_accessor_(test_accessor_) {}
+  virtual ~PropertyObserverTest() {}
+
+  MOCK_METHOD1(TestCallback, void(const bool &value));
+
+  // Invoked method during expectations.
+  void SetError(Error *error) {
+    error->Populate(Error::kPermissionDenied);
+  }
+
+ protected:
+  bool GetSavedValue(const PropertyObserver<bool> &observer) {
+    return observer.saved_value_;
+  }
+
+  TestPropertyAccessor *test_accessor_;
+  BoolAccessor bool_accessor_;  // Owns reference to |test_accessor_|.
+};
+
+TEST_F(PropertyObserverTest, Callback) {
+  EXPECT_CALL(*test_accessor_, Get(_)).WillOnce(Return(true));
+  EXPECT_CALL(*this, TestCallback(_)).Times(0);
+  PropertyObserver<bool> observer(bool_accessor_,
+                                  Bind(&PropertyObserverTest::TestCallback,
+                                       Unretained(this)));
+  EXPECT_TRUE(GetSavedValue(observer));
+  Mock::VerifyAndClearExpectations(test_accessor_);
+
+  // Accessor returns an error.
+  EXPECT_CALL(*test_accessor_, Get(_))
+      .WillOnce(DoAll(Invoke(this, &PropertyObserverTest::SetError),
+                      Return(false)));
+  observer.Update();
+
+  // Value remains unchanged.
+  EXPECT_CALL(*test_accessor_, Get(_)).WillOnce(Return(true));
+  observer.Update();
+  Mock::VerifyAndClearExpectations(test_accessor_);
+  Mock::VerifyAndClearExpectations(this);
+
+  // Value changes.
+  EXPECT_CALL(*test_accessor_, Get(_)).WillOnce(Return(false));
+  EXPECT_CALL(*this, TestCallback(false));
+  observer.Update();
+  EXPECT_FALSE(GetSavedValue(observer));
+  Mock::VerifyAndClearExpectations(test_accessor_);
+  Mock::VerifyAndClearExpectations(this);
+
+  // Value remains unchanged (false).
+  EXPECT_CALL(*test_accessor_, Get(_)).WillOnce(Return(false));
+  EXPECT_CALL(*this, TestCallback(_)).Times(0);
+  observer.Update();
+}
+
+}  // namespace shill