Home | History | Annotate | Download | only in geolocation
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/browser/geolocation/wifi_data_provider_linux.h"
      6 
      7 #include "base/memory/ref_counted.h"
      8 #include "base/memory/scoped_ptr.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "base/strings/utf_string_conversions.h"
     11 #include "dbus/message.h"
     12 #include "dbus/mock_bus.h"
     13 #include "dbus/mock_object_proxy.h"
     14 #include "dbus/object_path.h"
     15 #include "dbus/object_proxy.h"
     16 #include "testing/gmock/include/gmock/gmock.h"
     17 #include "testing/gtest/include/gtest/gtest.h"
     18 
     19 using ::testing::_;
     20 using ::testing::Invoke;
     21 using ::testing::Return;
     22 using ::testing::Unused;
     23 
     24 namespace content {
     25 
     26 class GeolocationWifiDataProviderLinuxTest : public testing::Test {
     27   virtual void SetUp() {
     28     // Create a mock bus.
     29     dbus::Bus::Options options;
     30     options.bus_type = dbus::Bus::SYSTEM;
     31     mock_bus_ = new dbus::MockBus(options);
     32 
     33     // Create a mock proxy that behaves as NetworkManager.
     34     mock_network_manager_proxy_ =
     35         new dbus::MockObjectProxy(
     36             mock_bus_.get(),
     37             "org.freedesktop.NetworkManager",
     38             dbus::ObjectPath("/org/freedesktop/NetworkManager"));
     39     // Set an expectation so mock_network_manager_proxy_'s
     40     // CallMethodAndBlock() will use CreateNetworkManagerProxyResponse()
     41     // to return responses.
     42     EXPECT_CALL(*mock_network_manager_proxy_.get(),
     43                 MockCallMethodAndBlock(_, _))
     44         .WillRepeatedly(Invoke(this,
     45                                &GeolocationWifiDataProviderLinuxTest::
     46                                    CreateNetworkManagerProxyResponse));
     47 
     48     // Create a mock proxy that behaves as NetworkManager/Devices/0.
     49     mock_device_proxy_ =
     50         new dbus::MockObjectProxy(
     51             mock_bus_.get(),
     52             "org.freedesktop.NetworkManager",
     53             dbus::ObjectPath("/org/freedesktop/NetworkManager/Devices/0"));
     54     EXPECT_CALL(*mock_device_proxy_.get(), MockCallMethodAndBlock(_, _))
     55         .WillRepeatedly(Invoke(
     56              this,
     57              &GeolocationWifiDataProviderLinuxTest::CreateDeviceProxyResponse));
     58 
     59     // Create a mock proxy that behaves as NetworkManager/AccessPoint/0.
     60     mock_access_point_proxy_ =
     61         new dbus::MockObjectProxy(
     62             mock_bus_.get(),
     63             "org.freedesktop.NetworkManager",
     64             dbus::ObjectPath("/org/freedesktop/NetworkManager/AccessPoint/0"));
     65     EXPECT_CALL(*mock_access_point_proxy_.get(), MockCallMethodAndBlock(_, _))
     66         .WillRepeatedly(Invoke(this,
     67                                &GeolocationWifiDataProviderLinuxTest::
     68                                    CreateAccessPointProxyResponse));
     69 
     70     // Set an expectation so mock_bus_'s GetObjectProxy() for the given
     71     // service name and the object path will return
     72     // mock_network_manager_proxy_.
     73     EXPECT_CALL(
     74         *mock_bus_.get(),
     75         GetObjectProxy("org.freedesktop.NetworkManager",
     76                        dbus::ObjectPath("/org/freedesktop/NetworkManager")))
     77         .WillOnce(Return(mock_network_manager_proxy_.get()));
     78     // Likewise, set an expectation for mock_device_proxy_.
     79     EXPECT_CALL(
     80         *mock_bus_.get(),
     81         GetObjectProxy(
     82             "org.freedesktop.NetworkManager",
     83             dbus::ObjectPath("/org/freedesktop/NetworkManager/Devices/0")))
     84         .WillOnce(Return(mock_device_proxy_.get()))
     85         .WillOnce(Return(mock_device_proxy_.get()));
     86     // Likewise, set an expectation for mock_access_point_proxy_.
     87     EXPECT_CALL(
     88         *mock_bus_.get(),
     89         GetObjectProxy(
     90             "org.freedesktop.NetworkManager",
     91             dbus::ObjectPath("/org/freedesktop/NetworkManager/AccessPoint/0")))
     92         .WillOnce(Return(mock_access_point_proxy_.get()));
     93 
     94     // ShutdownAndBlock() should be called.
     95     EXPECT_CALL(*mock_bus_.get(), ShutdownAndBlock()).WillOnce(Return());
     96 
     97     // Create the wlan API with the mock bus object injected.
     98     wifi_provider_linux_ = new WifiDataProviderLinux;
     99     wlan_api_.reset(
    100         wifi_provider_linux_->NewWlanApiForTesting(mock_bus_.get()));
    101     ASSERT_TRUE(wlan_api_.get());
    102   }
    103 
    104  protected:
    105   // DeviceDataProviderImplBase, a super class of WifiDataProviderLinux,
    106   // requires a message loop to be present. message_loop_ is defined here,
    107   // as it should outlive wifi_provider_linux_.
    108   base::MessageLoop message_loop_;
    109   scoped_refptr<dbus::MockBus> mock_bus_;
    110   scoped_refptr<dbus::MockObjectProxy> mock_network_manager_proxy_;
    111   scoped_refptr<dbus::MockObjectProxy> mock_access_point_proxy_;
    112   scoped_refptr<dbus::MockObjectProxy> mock_device_proxy_;
    113   scoped_refptr<WifiDataProviderLinux>  wifi_provider_linux_;
    114   scoped_ptr<WifiDataProviderCommon::WlanApiInterface> wlan_api_;
    115 
    116  private:
    117   // Creates a response for |mock_network_manager_proxy_|.
    118   dbus::Response* CreateNetworkManagerProxyResponse(
    119       dbus::MethodCall* method_call,
    120       Unused) {
    121     if (method_call->GetInterface() == "org.freedesktop.NetworkManager" &&
    122         method_call->GetMember() == "GetDevices") {
    123       // The list of devices is asked. Return the object path.
    124       std::vector<dbus::ObjectPath> object_paths;
    125       object_paths.push_back(
    126           dbus::ObjectPath("/org/freedesktop/NetworkManager/Devices/0"));
    127 
    128       scoped_ptr<dbus::Response> response = dbus::Response::CreateEmpty();
    129       dbus::MessageWriter writer(response.get());
    130       writer.AppendArrayOfObjectPaths(object_paths);
    131       return response.release();
    132     }
    133 
    134     LOG(ERROR) << "Unexpected method call: " << method_call->ToString();
    135     return NULL;
    136   }
    137 
    138   // Creates a response for |mock_device_proxy_|.
    139   dbus::Response* CreateDeviceProxyResponse(dbus::MethodCall* method_call,
    140                                             Unused) {
    141     if (method_call->GetInterface() == DBUS_INTERFACE_PROPERTIES &&
    142         method_call->GetMember() == "Get") {
    143       dbus::MessageReader reader(method_call);
    144       std::string interface_name;
    145       std::string property_name;
    146       if (reader.PopString(&interface_name) &&
    147           reader.PopString(&property_name)) {
    148         // The device type is asked. Respond that the device type is wifi.
    149         scoped_ptr<dbus::Response> response = dbus::Response::CreateEmpty();
    150         dbus::MessageWriter writer(response.get());
    151         // This matches NM_DEVICE_TYPE_WIFI in wifi_data_provider_linux.cc.
    152         const int kDeviceTypeWifi = 2;
    153         writer.AppendVariantOfUint32(kDeviceTypeWifi);
    154         return response.release();
    155       }
    156     } else if (method_call->GetInterface() ==
    157                "org.freedesktop.NetworkManager.Device.Wireless" &&
    158                method_call->GetMember() == "GetAccessPoints") {
    159       // The list of access points is asked. Return the object path.
    160       scoped_ptr<dbus::Response> response = dbus::Response::CreateEmpty();
    161       dbus::MessageWriter writer(response.get());
    162       std::vector<dbus::ObjectPath> object_paths;
    163       object_paths.push_back(
    164           dbus::ObjectPath("/org/freedesktop/NetworkManager/AccessPoint/0"));
    165       writer.AppendArrayOfObjectPaths(object_paths);
    166       return response.release();
    167     }
    168 
    169     LOG(ERROR) << "Unexpected method call: " << method_call->ToString();
    170     return NULL;
    171   }
    172 
    173 
    174   // Creates a response for |mock_access_point_proxy_|.
    175   dbus::Response* CreateAccessPointProxyResponse(dbus::MethodCall* method_call,
    176                                                  Unused) {
    177     if (method_call->GetInterface() == DBUS_INTERFACE_PROPERTIES &&
    178         method_call->GetMember() == "Get") {
    179       dbus::MessageReader reader(method_call);
    180 
    181       std::string interface_name;
    182       std::string property_name;
    183       if (reader.PopString(&interface_name) &&
    184           reader.PopString(&property_name)) {
    185         scoped_ptr<dbus::Response> response = dbus::Response::CreateEmpty();
    186         dbus::MessageWriter writer(response.get());
    187 
    188         if (property_name == "Ssid") {
    189           const uint8 kSsid[] = {0x74, 0x65, 0x73, 0x74};  // "test"
    190           dbus::MessageWriter variant_writer(response.get());
    191           writer.OpenVariant("ay", &variant_writer);
    192           variant_writer.AppendArrayOfBytes(kSsid, arraysize(kSsid));
    193           writer.CloseContainer(&variant_writer);
    194         } else if (property_name == "HwAddress") {
    195           // This will be converted to "00-11-22-33-44-55".
    196           const std::string kMacAddress = "00:11:22:33:44:55";
    197           writer.AppendVariantOfString(kMacAddress);
    198         } else if (property_name == "Strength") {
    199           // This will be converted to -50.
    200           const uint8 kStrength = 100;
    201           writer.AppendVariantOfByte(kStrength);
    202         } else if (property_name == "Frequency") {
    203           // This will be converted to channel 4.
    204           const uint32 kFrequency = 2427;
    205           writer.AppendVariantOfUint32(kFrequency);
    206         }
    207         return response.release();
    208       }
    209     }
    210 
    211     LOG(ERROR) << "Unexpected method call: " << method_call->ToString();
    212     return NULL;
    213   }
    214 };
    215 
    216 TEST_F(GeolocationWifiDataProviderLinuxTest, GetAccessPointData) {
    217   WifiData::AccessPointDataSet access_point_data_set;
    218   ASSERT_TRUE(wlan_api_->GetAccessPointData(&access_point_data_set));
    219 
    220   ASSERT_EQ(1U, access_point_data_set.size());
    221   AccessPointData access_point_data = *access_point_data_set.begin();
    222 
    223   // Check the contents of the access point data.
    224   // The expected values come from CreateAccessPointProxyResponse() above.
    225   EXPECT_EQ("test", UTF16ToUTF8(access_point_data.ssid));
    226   EXPECT_EQ("00-11-22-33-44-55", UTF16ToUTF8(access_point_data.mac_address));
    227   EXPECT_EQ(-50, access_point_data.radio_signal_strength);
    228   EXPECT_EQ(4, access_point_data.channel);
    229 }
    230 
    231 }  // namespace content
    232