shill: monitor bss signal strength

This wires WiFiEndpoint up to a proxy, to monitor
changes in the corresponding wpa_supplicant BSS
object.

The WiFiEndpoint object notifies its WiFi object
about the change, and WiFi relays the information
to the appropriate WiFiService.

BUG=chromium-os:16786
TEST=new unit tests, manual

Manual testing: ran on device (with --v=1000), observed
"signal is now" messages in log file.

Collateral changes:
- fix WiFiService leak in WiFi (reset |current_service| on Stop)
- suppress some "uninteresting call" messages in
  WiFiMainTest.CurrentBSSChangedUpdateServiceEndpoint

Change-Id: Ic329ecd28f73d93238d517a73105f2cd35cbff2e
Reviewed-on: https://gerrit.chromium.org/gerrit/15868
Commit-Ready: mukesh agrawal <quiche@chromium.org>
Reviewed-by: mukesh agrawal <quiche@chromium.org>
Tested-by: mukesh agrawal <quiche@chromium.org>
diff --git a/wifi_unittest.cc b/wifi_unittest.cc
index d3bcfde..d7366ef 100644
--- a/wifi_unittest.cc
+++ b/wifi_unittest.cc
@@ -37,6 +37,7 @@
 #include "shill/mock_metrics.h"
 #include "shill/mock_rtnl_handler.h"
 #include "shill/mock_store.h"
+#include "shill/mock_supplicant_bss_proxy.h"
 #include "shill/mock_supplicant_interface_proxy.h"
 #include "shill/mock_supplicant_process_proxy.h"
 #include "shill/mock_wifi_service.h"
@@ -57,6 +58,7 @@
 using ::testing::DefaultValue;
 using ::testing::DoAll;
 using ::testing::InSequence;
+using ::testing::Invoke;
 using ::testing::Mock;
 using ::testing::NiceMock;
 using ::testing::Return;
@@ -166,6 +168,8 @@
         supplicant_process_proxy_(new NiceMock<MockSupplicantProcessProxy>()),
         supplicant_interface_proxy_(
             new NiceMock<MockSupplicantInterfaceProxy>(wifi_)),
+        supplicant_bss_proxy_(
+            new NiceMock<MockSupplicantBSSProxy>()),
         dhcp_config_(new MockDHCPConfig(&control_interface_,
                                         &dispatcher_,
                                         &dhcp_provider_,
@@ -194,10 +198,14 @@
     ON_CALL(manager_, device_info()).
         WillByDefault(Return(&device_info_));
     EXPECT_CALL(manager_, DeregisterService(_)).Times(AnyNumber());
+    EXPECT_CALL(*supplicant_bss_proxy_, Die()).Times(AnyNumber());
   }
 
   virtual void TearDown() {
     EXPECT_CALL(*manager(), UpdateService(_)).Times(AnyNumber());
+    if (supplicant_bss_proxy_.get()) {
+      EXPECT_CALL(*supplicant_bss_proxy_, Die());
+    }
     wifi_->proxy_factory_ = NULL;
     // must Stop WiFi instance, to clear its list of services.
     // otherwise, the WiFi instance will not be deleted. (because
@@ -211,7 +219,7 @@
 
   class TestProxyFactory : public ProxyFactory {
    public:
-    explicit TestProxyFactory(WiFiMainTest *test) : test_(test) {}
+    explicit TestProxyFactory(WiFiMainTest *test);
 
     virtual SupplicantProcessProxyInterface *CreateSupplicantProcessProxy(
         const char */*dbus_path*/, const char */*dbus_addr*/) {
@@ -225,7 +233,20 @@
       return test_->supplicant_interface_proxy_.release();
     }
 
+    MOCK_METHOD3(CreateSupplicantBSSProxy,
+                 SupplicantBSSProxyInterface *(
+                     WiFiEndpoint *wifi_endpoint,
+                     const DBus::Path &object_path,
+                     const char *dbus_addr));
+
    private:
+    SupplicantBSSProxyInterface *CreateSupplicantBSSProxyInternal(
+        WiFiEndpoint */*wifi_endpoint*/,
+        const DBus::Path &/*object_path*/,
+        const char */*dbus_addr*/) {
+      return test_->supplicant_bss_proxy_.release();
+    }
+
     WiFiMainTest *test_;
   };
 
@@ -266,7 +287,7 @@
     wifi_->DisconnectFrom(service);
   }
   WiFiEndpointRefPtr MakeEndpoint(const string &ssid, const string &bssid) {
-    return WiFiEndpoint::MakeOpenEndpoint(ssid, bssid);
+    return WiFiEndpoint::MakeOpenEndpoint(&proxy_factory_, NULL, ssid, bssid);
   }
   MockWiFiServiceRefPtr MakeMockService() {
     vector<uint8_t> ssid(1, 'a');
@@ -397,6 +418,10 @@
     return wifi_;
   }
 
+  TestProxyFactory *proxy_factory() {
+    return &proxy_factory_;
+  }
+
   EventDispatcher dispatcher_;
   NiceMock<MockRTNLHandler> rtnl_handler_;
 
@@ -419,6 +444,7 @@
 
   scoped_ptr<MockSupplicantProcessProxy> supplicant_process_proxy_;
   scoped_ptr<MockSupplicantInterfaceProxy> supplicant_interface_proxy_;
+  scoped_ptr<MockSupplicantBSSProxy> supplicant_bss_proxy_;
   MockDHCPProvider dhcp_provider_;
   scoped_refptr<MockDHCPConfig> dhcp_config_;
 
@@ -465,6 +491,14 @@
   wifi_->BSSAddedTask(bss_path, bss_properties);
 }
 
+WiFiMainTest::TestProxyFactory::TestProxyFactory(WiFiMainTest *test)
+    : test_(test) {
+  EXPECT_CALL(*this, CreateSupplicantBSSProxy(_, _, _)).Times(AnyNumber());
+  ON_CALL(*this, CreateSupplicantBSSProxy(_, _, _))
+      .WillByDefault(
+          Invoke(this, (&TestProxyFactory::CreateSupplicantBSSProxyInternal)));
+}
+
 TEST_F(WiFiMainTest, ProxiesSetUpDuringStart) {
   EXPECT_TRUE(GetSupplicantProcessProxy() == NULL);
   EXPECT_TRUE(GetSupplicantInterfaceProxy() == NULL);
@@ -1400,6 +1434,10 @@
 }
 
 TEST_F(WiFiMainTest, CurrentBSSChangedUpdateServiceEndpoint) {
+  EXPECT_CALL(*manager(), RegisterService(_)).Times(AnyNumber());
+  EXPECT_CALL(*manager(), HasService(_)).Times(AnyNumber());
+  EXPECT_CALL(*manager(), UpdateService(_)).Times(AnyNumber());
+
   const uint16 frequency1 = 2412;
   const uint16 frequency2 = 2442;
   StartWiFi();
@@ -1567,4 +1605,31 @@
   dispatcher_.DispatchPendingEvents();
 }
 
+TEST_F(WiFiMainTest, BSSAddedCreatesBSSProxy) {
+  EXPECT_CALL(*manager(), RegisterService(_)).Times(AnyNumber());
+  // TODO(quiche): Consider using a factory for WiFiEndpoints, so that
+  // we can test the interaction between WiFi and WiFiEndpoint. (Right
+  // now, we're testing across multiple layers.)
+  EXPECT_CALL(*supplicant_bss_proxy_, Die()).Times(AnyNumber());
+  EXPECT_CALL(*proxy_factory(), CreateSupplicantBSSProxy(_, _, _));
+  StartWiFi();
+  ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc);
+}
+
+TEST_F(WiFiMainTest, BSSRemovedDestroysBSSProxy) {
+  // TODO(quiche): As for BSSAddedCreatesBSSProxy, consider using a
+  // factory for WiFiEndpoints.
+  EXPECT_CALL(*manager(), RegisterService(_)).Times(AnyNumber());
+
+  // Get the pointer before we transfer ownership.
+  MockSupplicantBSSProxy *proxy = supplicant_bss_proxy_.get();
+  EXPECT_CALL(*proxy, Die());
+  StartWiFi();
+  ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc);
+  RemoveBSS("bss0");
+  // Check this now, to make sure RemoveBSS killed the proxy (rather
+  // than TearDown).
+  Mock::VerifyAndClearExpectations(proxy);
+}
+
 }  // namespace shill