shill: Device: Add LinkMonitor

Start link monitoring for technologies for which it is enabled.
Add facilities in the manager and default profile to determine
and persist a list of technologies for which link monitoring
is enabled.  Provide a means for the Device to report the current
rolling average LinkMonitor response time.

BUG=chromium-os:32600
TEST=Unit tests

Change-Id: I39dcc8ce2332d7be3c95d9953b4ae7d7172d7df1
Reviewed-on: https://gerrit.chromium.org/gerrit/29731
Commit-Ready: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
Reviewed-by: Paul Stewart <pstew@chromium.org>
diff --git a/device_unittest.cc b/device_unittest.cc
index 86ac95d..42ee525 100644
--- a/device_unittest.cc
+++ b/device_unittest.cc
@@ -29,6 +29,7 @@
 #include "shill/mock_dhcp_provider.h"
 #include "shill/mock_glib.h"
 #include "shill/mock_ipconfig.h"
+#include "shill/mock_link_monitor.h"
 #include "shill/mock_manager.h"
 #include "shill/mock_metrics.h"
 #include "shill/mock_portal_detector.h"
@@ -120,6 +121,26 @@
     device_->connection_ = connection;
   }
 
+  void SetLinkMonitor(LinkMonitor *link_monitor) {
+    device_->set_link_monitor(link_monitor);  // Passes ownership.
+  }
+
+  bool StartLinkMonitor() {
+    return device_->StartLinkMonitor();
+  }
+
+  void StopLinkMonitor() {
+    device_->StopLinkMonitor();
+  }
+
+  uint64 GetLinkMonitorResponseTime(Error *error) {
+    return device_->GetLinkMonitorResponseTime(error);
+  }
+
+  void SetManager(Manager *manager) {
+    device_->manager_ = manager;
+  }
+
   MockControl control_interface_;
   DeviceRefPtr device_;
   MockDeviceInfo device_info_;
@@ -338,7 +359,7 @@
                                   metrics(),
                                   glib());
   EXPECT_CALL(manager, UpdateDevice(_));
-  device_->manager_ = &manager;
+  SetManager(&manager);
   Error error;
   device_->SetEnabledPersistent(true, &error, ResultCallback());
   EXPECT_TRUE(device_->enabled_persistent_);
@@ -396,6 +417,51 @@
   device_->OnAfterResume();
 }
 
+TEST_F(DeviceTest, LinkMonitor) {
+  scoped_refptr<MockConnection> connection(
+      new StrictMock<MockConnection>(&device_info_));
+  MockManager manager(control_interface(),
+                      dispatcher(),
+                      metrics(),
+                      glib());
+  scoped_refptr<MockService> service(
+      new StrictMock<MockService>(control_interface(),
+                                  dispatcher(),
+                                  metrics(),
+                                  &manager));
+  SelectService(service);
+  SetConnection(connection.get());
+  MockLinkMonitor *link_monitor = new StrictMock<MockLinkMonitor>();
+  SetLinkMonitor(link_monitor);  // Passes ownership.
+  SetManager(&manager);
+  EXPECT_CALL(*link_monitor, Start()).Times(0);
+  EXPECT_CALL(manager, IsTechnologyLinkMonitorEnabled(Technology::kUnknown))
+      .WillOnce(Return(false))
+      .WillRepeatedly(Return(true));
+  EXPECT_FALSE(StartLinkMonitor());
+
+  EXPECT_CALL(*link_monitor, Start())
+      .WillOnce(Return(false))
+      .WillOnce(Return(true));
+  EXPECT_FALSE(StartLinkMonitor());
+  EXPECT_TRUE(StartLinkMonitor());
+
+  unsigned int kResponseTime = 123;
+  EXPECT_CALL(*link_monitor, GetResponseTimeMilliseconds())
+      .WillOnce(Return(kResponseTime));
+  {
+    Error error;
+    EXPECT_EQ(kResponseTime, GetLinkMonitorResponseTime(&error));
+    EXPECT_TRUE(error.IsSuccess());
+  }
+  StopLinkMonitor();
+  {
+    Error error;
+    EXPECT_EQ(0, GetLinkMonitorResponseTime(&error));
+    EXPECT_FALSE(error.IsSuccess());
+  }
+}
+
 class DevicePortalDetectionTest : public DeviceTest {
  public:
   DevicePortalDetectionTest()
@@ -415,7 +481,7 @@
     SelectService(service_);
     SetConnection(connection_.get());
     device_->portal_detector_.reset(portal_detector_);  // Passes ownership.
-    device_->manager_ = &manager_;
+    SetManager(&manager_);
   }
 
  protected: