shill: Service: Sort services based on dependency

If one connected service depends on another for connectivity,
it should be sorted first, overriding technology and priority
ordering.  We evaluate this by using the "Lower binder" property
of the service's connection, which is currently the case for
VPNs connections to indicate what underlying link is used.  It does
not make sense for a VPN service to be ranked at a lower priority
than its underlying technology, since the fact that it is connected
implies that the VPN is meant to be applied to it.

BUG=chromium-os:36231
TEST=Unit tests.

Change-Id: I74ee5d1213141db2c6a124ed44717c848a0e2701
Reviewed-on: https://gerrit.chromium.org/gerrit/37774
Reviewed-by: mukesh agrawal <quiche@chromium.org>
Commit-Ready: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/service_unittest.cc b/service_unittest.cc
index 00349f1..f21e8ee 100644
--- a/service_unittest.cc
+++ b/service_unittest.cc
@@ -624,6 +624,39 @@
   EXPECT_TRUE(service_->IsRemembered());
 }
 
+TEST_F(ServiceTest, IsDependentOn) {
+  EXPECT_FALSE(service_->IsDependentOn(NULL));
+
+  scoped_ptr<MockDeviceInfo> mock_device_info(
+      new NiceMock<MockDeviceInfo>(control_interface(), dispatcher(), metrics(),
+                                   &mock_manager_));
+  scoped_refptr<MockConnection> mock_connection0(
+      new NiceMock<MockConnection>(mock_device_info.get()));
+  scoped_refptr<MockConnection> mock_connection1(
+      new NiceMock<MockConnection>(mock_device_info.get()));
+
+  service_->connection_ = mock_connection0;
+  EXPECT_CALL(*mock_connection0.get(), GetLowerConnection())
+      .WillRepeatedly(Return(mock_connection1));
+  EXPECT_FALSE(service_->IsDependentOn(NULL));
+
+  scoped_refptr<ServiceUnderTest> service1 =
+      new ServiceUnderTest(control_interface(),
+                           dispatcher(),
+                           metrics(),
+                           &mock_manager_);
+  EXPECT_FALSE(service_->IsDependentOn(service1));
+
+  service1->connection_ = mock_connection0;
+  EXPECT_FALSE(service_->IsDependentOn(service1));
+
+  service1->connection_ = mock_connection1;
+  EXPECT_TRUE(service_->IsDependentOn(service1));
+
+  service_->connection_ = NULL;
+  service1->connection_ = NULL;
+}
+
 TEST_F(ServiceTest, OnPropertyChanged) {
   scoped_refptr<MockProfile> profile(
       new StrictMock<MockProfile>(control_interface(), manager()));