1326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu//
2326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// Copyright (C) 2014 The Android Open Source Project
3326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu//
4326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// Licensed under the Apache License, Version 2.0 (the "License");
5326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// you may not use this file except in compliance with the License.
6326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// You may obtain a copy of the License at
7326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu//
8326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu//      http://www.apache.org/licenses/LICENSE-2.0
9326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu//
10326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// Unless required by applicable law or agreed to in writing, software
11326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// distributed under the License is distributed on an "AS IS" BASIS,
12326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// See the License for the specific language governing permissions and
14326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// limitations under the License.
15326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu//
16fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
17fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include "apmanager/device_info.h"
18fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
19fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include <linux/netlink.h>
20239395699b0d70ba278d49f40d13e15254924ea5Paul Stewart#include <linux/rtnetlink.h>
21fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
22fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include <map>
23fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include <string>
24fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include <vector>
25fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
26fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include <base/files/file_util.h>
27fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include <base/files/scoped_temp_dir.h>
28fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include <gmock/gmock.h>
29fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include <gtest/gtest.h>
30fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include <shill/net/byte_string.h>
31fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include <shill/net/mock_netlink_manager.h>
32fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include "shill/net/netlink_message_matchers.h"
33fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include "shill/net/nl80211_attribute.h"
34fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include "shill/net/nl80211_message.h"
35fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include <shill/net/rtnl_message.h>
36fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
37f933540bb968efa2744ee48b40ab713ccd358d51Peter Qiu#include "apmanager/fake_device_adaptor.h"
38f933540bb968efa2744ee48b40ab713ccd358d51Peter Qiu#include "apmanager/mock_control.h"
39fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include "apmanager/mock_device.h"
40fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include "apmanager/mock_manager.h"
41fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
42fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuusing shill::ByteString;
43fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuusing shill::Nl80211Message;
44fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuusing shill::RTNLMessage;
45fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuusing std::map;
46fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuusing std::string;
47fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuusing std::vector;
48fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuusing ::testing::_;
49fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuusing ::testing::Mock;
50f933540bb968efa2744ee48b40ab713ccd358d51Peter Qiuusing ::testing::ReturnNew;
51fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
52fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiunamespace apmanager {
53fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
54fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiunamespace {
55fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
56fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuconst char kTestDeviceName[] = "test-phy";
57fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuconst char kTestInterface0Name[] = "test-interface0";
58fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuconst char kTestInterface1Name[] = "test-interface1";
59fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuconst uint32_t kTestInterface0Index = 1000;
60fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuconst uint32_t kTestInterface1Index = 1001;
61fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
62fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu}  // namespace
63fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
64fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuclass DeviceInfoTest : public testing::Test {
65fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu public:
66f933540bb968efa2744ee48b40ab713ccd358d51Peter Qiu  DeviceInfoTest()
67f933540bb968efa2744ee48b40ab713ccd358d51Peter Qiu      : manager_(&control_interface_),
68f933540bb968efa2744ee48b40ab713ccd358d51Peter Qiu        device_info_(&manager_) {}
69fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  virtual ~DeviceInfoTest() {}
70fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
71fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  virtual void SetUp() {
72fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    // Setup temporary directory for device info files.
73fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    CHECK(temp_dir_.CreateUniqueTempDir());
74fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    device_info_root_ = temp_dir_.path().Append("sys/class/net");
75fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    device_info_.device_info_root_ = device_info_root_;
76fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
77fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    // Setup mock pointers;
78fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    device_info_.netlink_manager_ = &netlink_manager_;
79f933540bb968efa2744ee48b40ab713ccd358d51Peter Qiu
80f933540bb968efa2744ee48b40ab713ccd358d51Peter Qiu    ON_CALL(control_interface_, CreateDeviceAdaptorRaw())
81f933540bb968efa2744ee48b40ab713ccd358d51Peter Qiu      .WillByDefault(ReturnNew<FakeDeviceAdaptor>());
82fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  }
83fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
84fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  bool IsWifiInterface(const string& interface_name) {
85fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    return device_info_.IsWifiInterface(interface_name);
86fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  }
87fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
88fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  void CreateDeviceInfoFile(const string& interface_name,
89fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu                            const string& file_name,
90fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu                            const string& contents) {
91fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    base::FilePath info_path =
92fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu        device_info_root_.Append(interface_name).Append(file_name);
93fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    EXPECT_TRUE(base::CreateDirectory(info_path.DirName()));
94fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    EXPECT_TRUE(base::WriteFile(info_path, contents.c_str(), contents.size()));
95fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  }
96fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
97fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  void SendLinkMsg(RTNLMessage::Mode mode,
98fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu                   uint32_t interface_index,
99fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu                   const string& interface_name) {
100fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    RTNLMessage message(RTNLMessage::kTypeLink,
101fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu                        mode,
102fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu                        0,
103fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu                        0,
104fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu                        0,
105fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu                        interface_index,
106fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu                        shill::IPAddress::kFamilyIPv4);
107fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    message.SetAttribute(static_cast<uint16_t>(IFLA_IFNAME),
108fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu                         ByteString(interface_name, true));
109fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    device_info_.LinkMsgHandler(message);
110fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  }
111fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
112fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  void VerifyInterfaceList(const vector<Device::WiFiInterface>& interfaces) {
113fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    // Verify number of elements in the interface infos map and interface index
114fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    // of the elements in the map.
115fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    EXPECT_EQ(interfaces.size(), device_info_.interface_infos_.size());
116fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    for (const auto& interface : interfaces) {
117fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu      map<uint32_t, Device::WiFiInterface>::iterator it =
118fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu          device_info_.interface_infos_.find(interface.iface_index);
119fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu      EXPECT_NE(device_info_.interface_infos_.end(), it);
120fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu      EXPECT_TRUE(interface.Equals(it->second));
121fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    }
122fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  }
123fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
124fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  void VerifyDeviceList(const vector<scoped_refptr<Device>>& devices) {
125fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    // Verify number of elements in the device map and the elements in the map.
126fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    EXPECT_EQ(devices.size(), device_info_.devices_.size());
127fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    for (const auto& device : devices) {
128fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu      map<string, scoped_refptr<Device>>::iterator it =
129fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu          device_info_.devices_.find(device->GetDeviceName());
130fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu      EXPECT_NE(device_info_.devices_.end(), it);
131fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu      EXPECT_EQ(device, it->second);
132fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    }
133fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  }
134fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  void AddInterface(const Device::WiFiInterface& interface) {
135fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    device_info_.interface_infos_[interface.iface_index] = interface;
136fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  }
137fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
1381ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu  void OnWiFiPhyInfoReceived(const Nl80211Message& message) {
1391ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu    device_info_.OnWiFiPhyInfoReceived(message);
1401ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu  }
1411ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu
142fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  void OnWiFiInterfaceInfoReceived(const Nl80211Message& message) {
143fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    device_info_.OnWiFiInterfaceInfoReceived(message);
144fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  }
145fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
146fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  void OnWiFiInterfacePhyInfoReceived(uint32_t interface_index,
147fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu                                      const Nl80211Message& message) {
148fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    device_info_.OnWiFiInterfacePhyInfoReceived(interface_index, message);
149fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  }
150fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
151fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  void RegisterDevice(scoped_refptr<Device> device) {
152fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    device_info_.RegisterDevice(device);
153fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  }
154fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
155fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu protected:
156f933540bb968efa2744ee48b40ab713ccd358d51Peter Qiu  MockControl control_interface_;
157fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  MockManager manager_;
158f933540bb968efa2744ee48b40ab713ccd358d51Peter Qiu
159fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  shill::MockNetlinkManager netlink_manager_;
160fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  base::ScopedTempDir temp_dir_;
161fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  base::FilePath device_info_root_;
162f933540bb968efa2744ee48b40ab713ccd358d51Peter Qiu  DeviceInfo device_info_;
163fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu};
164fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
165fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter QiuMATCHER_P2(IsGetInfoMessage, command, index, "") {
166fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  if (arg->message_type() != Nl80211Message::GetMessageType()) {
167fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    return false;
168fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  }
169fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  const Nl80211Message *msg = reinterpret_cast<const Nl80211Message *>(arg);
170fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  if (msg->command() != command) {
171fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    return false;
172fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  }
173fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  uint32_t interface_index;
174fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  if (!msg->const_attributes()->GetU32AttributeValue(NL80211_ATTR_IFINDEX,
175fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu                                                     &interface_index)) {
176fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu    return false;
177fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  }
178fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // kInterfaceIndex is signed, but the attribute as handed from the kernel
179fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // is unsigned.  We're silently casting it away with this assignment.
180fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  uint32_t test_interface_index = index;
181fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  return interface_index == test_interface_index;
182fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu}
183fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
184fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter QiuMATCHER_P(IsInterface, interface, "") {
185fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  return arg.Equals(interface);
186fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu}
187fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
1881ff67a70eb6dea94ba8a6a836add9810536bec31Peter QiuMATCHER_P(IsDevice, device_name, "") {
1891ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu  return arg->GetDeviceName() == device_name;
1901ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu}
1911ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu
1921ff67a70eb6dea94ba8a6a836add9810536bec31Peter QiuTEST_F(DeviceInfoTest, EnumerateDevices) {
1931ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu  shill::NewWiphyMessage message;
1941ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu
1951ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu  // No device name in the message, failed to create device.
1961ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu  EXPECT_CALL(manager_, RegisterDevice(_)).Times(0);
1971ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu  OnWiFiPhyInfoReceived(message);
1981ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu
1991ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu  // Device name in the message, device should be created/register to manager.
200310966665c47886033c8267ddcbed2bf164daf6dSamuel Tan  message.attributes()->CreateNl80211Attribute(
201310966665c47886033c8267ddcbed2bf164daf6dSamuel Tan      NL80211_ATTR_WIPHY_NAME, shill::NetlinkMessage::MessageContext());
2021ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu  message.attributes()->SetStringAttributeValue(NL80211_ATTR_WIPHY_NAME,
2031ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu                                                kTestDeviceName);
2041ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu  EXPECT_CALL(manager_, RegisterDevice(IsDevice(kTestDeviceName))).Times(1);
2051ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu  OnWiFiPhyInfoReceived(message);
2061ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu  Mock::VerifyAndClearExpectations(&manager_);
2071ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu
2081ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu  // Receive a message for a device already created, should not create/register
2091ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu  // device again.
2101ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu  EXPECT_CALL(manager_, RegisterDevice(_)).Times(0);
2111ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu  OnWiFiPhyInfoReceived(message);
2121ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu}
2131ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu
214fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter QiuTEST_F(DeviceInfoTest, IsWiFiInterface) {
215fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // No device info file exist, not a wifi interface.
216fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  EXPECT_FALSE(IsWifiInterface(kTestInterface0Name));
217fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
218fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // Device info for an ethernet device, not a wifi interface
219fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  CreateDeviceInfoFile(kTestInterface0Name, "uevent", "INTERFACE=eth0\n");
220fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  EXPECT_FALSE(IsWifiInterface(kTestInterface0Name));
221fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
222fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // Device info for a wifi interface.
223fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  CreateDeviceInfoFile(kTestInterface1Name, "uevent", "DEVTYPE=wlan\n");
224fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  EXPECT_TRUE(IsWifiInterface(kTestInterface1Name));
225fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu}
226fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
227fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter QiuTEST_F(DeviceInfoTest, InterfaceDetection) {
228fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  vector<Device::WiFiInterface> interface_list;
229fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // Ignore non-wifi interface.
230fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  SendLinkMsg(RTNLMessage::kModeAdd,
231fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu              kTestInterface0Index,
232fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu              kTestInterface0Name);
233fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  VerifyInterfaceList(interface_list);
234fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
235fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // AddLink event for wifi interface.
236fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  CreateDeviceInfoFile(kTestInterface0Name, "uevent", "DEVTYPE=wlan\n");
237fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  EXPECT_CALL(netlink_manager_, SendNl80211Message(
238fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu      IsGetInfoMessage(NL80211_CMD_GET_INTERFACE, kTestInterface0Index),
239fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu      _, _, _)).Times(1);
240fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  SendLinkMsg(RTNLMessage::kModeAdd,
241fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu              kTestInterface0Index,
242fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu              kTestInterface0Name);
243fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  interface_list.push_back(Device::WiFiInterface(
244fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu      kTestInterface0Name, "", kTestInterface0Index, 0));
245fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  VerifyInterfaceList(interface_list);
246fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  Mock::VerifyAndClearExpectations(&netlink_manager_);
247fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
248fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // AddLink event for another wifi interface.
249fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  CreateDeviceInfoFile(kTestInterface1Name, "uevent", "DEVTYPE=wlan\n");
250fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  EXPECT_CALL(netlink_manager_, SendNl80211Message(
251fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu      IsGetInfoMessage(NL80211_CMD_GET_INTERFACE, kTestInterface1Index),
252fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu      _, _, _)).Times(1);
253fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  SendLinkMsg(RTNLMessage::kModeAdd,
254fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu              kTestInterface1Index,
255fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu              kTestInterface1Name);
256fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  interface_list.push_back(Device::WiFiInterface(
257fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu      kTestInterface1Name, "", kTestInterface1Index, 0));
258fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  VerifyInterfaceList(interface_list);
259fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  Mock::VerifyAndClearExpectations(&netlink_manager_);
260fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
261fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // AddLink event for an interface that's already added, no change to interface
262fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // list.
263fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  EXPECT_CALL(netlink_manager_, SendNl80211Message(_, _, _, _)).Times(0);
264fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  SendLinkMsg(RTNLMessage::kModeAdd,
265fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu              kTestInterface0Index,
266fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu              kTestInterface0Name);
267fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  VerifyInterfaceList(interface_list);
268fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  Mock::VerifyAndClearExpectations(&netlink_manager_);
269fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
270fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // Remove the first wifi interface.
271fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  SendLinkMsg(RTNLMessage::kModeDelete,
272fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu              kTestInterface0Index,
273fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu              kTestInterface0Name);
274fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  interface_list.clear();
275fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  interface_list.push_back(Device::WiFiInterface(
276fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu      kTestInterface1Name, "", kTestInterface1Index, 0));
277fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  VerifyInterfaceList(interface_list);
278fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
279fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // Remove the non-exist interface, no change to the list.
280fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  SendLinkMsg(RTNLMessage::kModeDelete,
281fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu              kTestInterface0Index,
282fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu              kTestInterface0Name);
283fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  VerifyInterfaceList(interface_list);
284fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
285fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // Remove the last interface, list should be empty now.
286fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  SendLinkMsg(RTNLMessage::kModeDelete,
287fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu              kTestInterface1Index,
288fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu              kTestInterface1Name);
289fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  interface_list.clear();
290fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  VerifyInterfaceList(interface_list);
291fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu}
292fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
293fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter QiuTEST_F(DeviceInfoTest, ParseWifiInterfaceInfo) {
294fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // Add an interface without interface type info.
295fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  Device::WiFiInterface interface(
296fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu      kTestInterface0Name, "", kTestInterface0Index, 0);
297fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  AddInterface(interface);
298fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  vector<Device::WiFiInterface> interface_list;
299fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  interface_list.push_back(interface);
300fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
301fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // Message contain no interface index, no change to the interface info.
302fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  shill::NewInterfaceMessage message;
303fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  OnWiFiInterfaceInfoReceived(message);
304fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  VerifyInterfaceList(interface_list);
305fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
306fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // Message contain no interface type, no change to the interface info.
307310966665c47886033c8267ddcbed2bf164daf6dSamuel Tan  message.attributes()->CreateNl80211Attribute(
308310966665c47886033c8267ddcbed2bf164daf6dSamuel Tan      NL80211_ATTR_IFINDEX, shill::NetlinkMessage::MessageContext());
309fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  message.attributes()->SetU32AttributeValue(NL80211_ATTR_IFINDEX,
310fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu                                             kTestInterface0Index);
311fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  OnWiFiInterfaceInfoReceived(message);
312fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
313fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // Message contain interface type, interface info should be updated with
314fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // the interface type, and a new Nl80211 message should be send to query for
315fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // the PHY info.
316fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  EXPECT_CALL(netlink_manager_, SendNl80211Message(
317fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu      IsGetInfoMessage(NL80211_CMD_GET_WIPHY, kTestInterface0Index),
318fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu      _, _, _)).Times(1);
319310966665c47886033c8267ddcbed2bf164daf6dSamuel Tan  message.attributes()->CreateNl80211Attribute(
320310966665c47886033c8267ddcbed2bf164daf6dSamuel Tan      NL80211_ATTR_IFTYPE, shill::NetlinkMessage::MessageContext());
321fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  message.attributes()->SetU32AttributeValue(NL80211_ATTR_IFTYPE,
322fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu                                             NL80211_IFTYPE_AP);
323fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  OnWiFiInterfaceInfoReceived(message);
324fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  interface_list[0].iface_type = NL80211_IFTYPE_AP;
325fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  VerifyInterfaceList(interface_list);
326fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu}
327fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
328fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter QiuTEST_F(DeviceInfoTest, ParsePhyInfoForWifiInterface) {
329fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // Register a mock device.
330f933540bb968efa2744ee48b40ab713ccd358d51Peter Qiu  scoped_refptr<MockDevice> device = new MockDevice(&manager_);
331fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  device->SetDeviceName(kTestDeviceName);
332fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  EXPECT_CALL(manager_, RegisterDevice(_)).Times(1);
333fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  RegisterDevice(device);
334fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
335fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // PHY info message.
336fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  shill::NewWiphyMessage message;
337310966665c47886033c8267ddcbed2bf164daf6dSamuel Tan  message.attributes()->CreateNl80211Attribute(
338310966665c47886033c8267ddcbed2bf164daf6dSamuel Tan      NL80211_ATTR_WIPHY_NAME, shill::NetlinkMessage::MessageContext());
339fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  message.attributes()->SetStringAttributeValue(NL80211_ATTR_WIPHY_NAME,
340fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu                                                kTestDeviceName);
341fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
342fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // Receive PHY info message for an interface that have not been detected yet.
343fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  EXPECT_CALL(*device.get(), RegisterInterface(_)).Times(0);
344fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  OnWiFiInterfacePhyInfoReceived(kTestInterface0Index, message);
345fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
346fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // Pretend interface is detected through AddLink with interface info already
347fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // received (interface type), and still missing PHY info for that interface.
348fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  Device::WiFiInterface interface(
349fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu      kTestInterface0Name, "", kTestInterface0Index, NL80211_IFTYPE_AP);
350fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  AddInterface(interface);
351fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
352fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // PHY info is received for a detected interface, should register that
353fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // interface to the corresponding Device.
354fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  interface.device_name = kTestDeviceName;
355fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  EXPECT_CALL(*device.get(),
356fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu              RegisterInterface(IsInterface(interface))).Times(1);
357fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  OnWiFiInterfacePhyInfoReceived(kTestInterface0Index, message);
358fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu}
359fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
360fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter QiuTEST_F(DeviceInfoTest, ReceivePhyInfoBeforePhyIsEnumerated) {
361fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // New interface is detected.
362fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  Device::WiFiInterface interface(
363fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu      kTestInterface0Name, "", kTestInterface0Index, NL80211_IFTYPE_AP);
364fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  AddInterface(interface);
3651ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu  vector<Device::WiFiInterface> interface_list;
3661ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu  interface_list.push_back(interface);
367fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
368fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // Received PHY info for the interface when the corresponding PHY is not
3691ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu  // enumerated yet, new device should be created and register to manager.
370fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  shill::NewWiphyMessage message;
371310966665c47886033c8267ddcbed2bf164daf6dSamuel Tan  message.attributes()->CreateNl80211Attribute(
372310966665c47886033c8267ddcbed2bf164daf6dSamuel Tan      NL80211_ATTR_WIPHY_NAME, shill::NetlinkMessage::MessageContext());
373fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  message.attributes()->SetStringAttributeValue(NL80211_ATTR_WIPHY_NAME,
374fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu                                                kTestDeviceName);
3751ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu  EXPECT_CALL(manager_, RegisterDevice(IsDevice(kTestDeviceName))).Times(1);
376fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  OnWiFiInterfacePhyInfoReceived(kTestInterface0Index, message);
3771ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu  interface_list[0].device_name = kTestDeviceName;
3781ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu  VerifyInterfaceList(interface_list);
379fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu}
380fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
381fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter QiuTEST_F(DeviceInfoTest, RegisterDevice) {
382fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  vector<scoped_refptr<Device>> device_list;
383fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
384fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // Register a nullptr.
385fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  RegisterDevice(nullptr);
386fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  VerifyDeviceList(device_list);
387fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
388fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  // Register a device.
389f933540bb968efa2744ee48b40ab713ccd358d51Peter Qiu  device_list.push_back(new Device(&manager_, kTestDeviceName, 0));
390fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  EXPECT_CALL(manager_, RegisterDevice(device_list[0]));
391fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  RegisterDevice(device_list[0]);
392fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu  VerifyDeviceList(device_list);
393fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu}
394fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu
395fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu}  // namespace apmanager
396