blob: e7b0c31eba2bf29866b252e47afe2746aed719e7 [file] [log] [blame]
Darin Petkov41c0e0a2012-01-09 16:38:53 +01001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Darin Petkove0a312e2011-07-20 13:45:28 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ben Chanc54afe52014-11-05 10:28:08 -08005#include "shill/cellular/modem.h"
Jason Glasgow82f9ab32012-04-04 14:27:19 -04006
Darin Petkov6f9eaa32011-08-09 15:26:44 -07007#include <vector>
8
Ben Chana0ddf462014-02-06 11:32:42 -08009#include <base/strings/stringprintf.h>
Chris Masone626719f2011-08-18 16:58:48 -070010#include <gmock/gmock.h>
Darin Petkove0a312e2011-07-20 13:45:28 -070011#include <gtest/gtest.h>
12#include <mm/mm-modem.h>
13#include <net/if.h>
14#include <sys/ioctl.h>
15
Ben Chanc54afe52014-11-05 10:28:08 -080016#include "shill/cellular/cellular.h"
17#include "shill/cellular/cellular_capability_gsm.h"
18#include "shill/cellular/mock_cellular.h"
19#include "shill/cellular/mock_modem.h"
20#include "shill/cellular/mock_modem_info.h"
David Rochbergfa1d31d2012-03-20 10:38:07 -040021#include "shill/dbus_property_matchers.h"
Paul Stewart26b327e2011-10-19 11:38:09 -070022#include "shill/event_dispatcher.h"
Darin Petkove0a312e2011-07-20 13:45:28 -070023#include "shill/manager.h"
David Rochbergfa1d31d2012-03-20 10:38:07 -040024#include "shill/mock_device_info.h"
Peter Qiu8d6b5972014-10-28 15:33:34 -070025#include "shill/net/mock_rtnl_handler.h"
26#include "shill/net/rtnl_handler.h"
Darin Petkove0a312e2011-07-20 13:45:28 -070027#include "shill/proxy_factory.h"
Darin Petkove0a312e2011-07-20 13:45:28 -070028
29using std::string;
Darin Petkov6f9eaa32011-08-09 15:26:44 -070030using std::vector;
Darin Petkove0a312e2011-07-20 13:45:28 -070031using testing::_;
mukesh agrawal12533ad2013-08-01 15:43:23 -070032using testing::AnyNumber;
Darin Petkove0a312e2011-07-20 13:45:28 -070033using testing::DoAll;
34using testing::Return;
Chris Masone626719f2011-08-18 16:58:48 -070035using testing::SetArgumentPointee;
David Rochbergfa1d31d2012-03-20 10:38:07 -040036using testing::StrEq;
Darin Petkove0a312e2011-07-20 13:45:28 -070037using testing::StrictMock;
38using testing::Test;
39
40namespace shill {
41
42namespace {
43
44const int kTestInterfaceIndex = 5;
David Rochbergfa1d31d2012-03-20 10:38:07 -040045const char kLinkName[] = "usb0";
46const char kOwner[] = ":1.18";
Jason Glasgowa585fc32012-06-06 11:04:09 -040047const char kService[] = "org.chromium.ModemManager";
David Rochbergfa1d31d2012-03-20 10:38:07 -040048const char kPath[] = "/org/chromium/ModemManager/Gobi/0";
49const unsigned char kAddress[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
50const char kAddressAsString[] = "000102030405";
Darin Petkove0a312e2011-07-20 13:45:28 -070051
Darin Petkove0a312e2011-07-20 13:45:28 -070052} // namespace
53
54class ModemTest : public Test {
55 public:
56 ModemTest()
Ben Chanea18c6c2014-09-30 13:08:26 -070057 : modem_info_(nullptr, &dispatcher_, nullptr, nullptr, nullptr),
Prathmesh Prabhu27526f12013-03-25 19:42:18 -070058 device_info_(modem_info_.control_interface(), modem_info_.dispatcher(),
59 modem_info_.metrics(), modem_info_.manager()),
David Rochbergfa1d31d2012-03-20 10:38:07 -040060 modem_(
61 new StrictModem(
62 kOwner,
Jason Glasgowa585fc32012-06-06 11:04:09 -040063 kService,
David Rochbergfa1d31d2012-03-20 10:38:07 -040064 kPath,
Prathmesh Prabhu27526f12013-03-25 19:42:18 -070065 &modem_info_)) {}
Darin Petkove0a312e2011-07-20 13:45:28 -070066 virtual void SetUp();
67 virtual void TearDown();
68
David Rochbergfa1d31d2012-03-20 10:38:07 -040069 void ReplaceSingletons() {
70 modem_->rtnl_handler_ = &rtnl_handler_;
Darin Petkove0a312e2011-07-20 13:45:28 -070071 }
72
73 protected:
Darin Petkove0a312e2011-07-20 13:45:28 -070074 EventDispatcher dispatcher_;
Prathmesh Prabhu27526f12013-03-25 19:42:18 -070075 MockModemInfo modem_info_;
76 MockDeviceInfo device_info_;
Ben Chanc20ed132014-10-16 12:25:03 -070077 std::unique_ptr<StrictModem> modem_;
David Rochbergfa1d31d2012-03-20 10:38:07 -040078 MockRTNLHandler rtnl_handler_;
79 ByteString expected_address_;
Darin Petkove0a312e2011-07-20 13:45:28 -070080};
81
Darin Petkove0a312e2011-07-20 13:45:28 -070082void ModemTest::SetUp() {
Jason Glasgowe9089492012-02-23 17:57:37 -050083 EXPECT_EQ(kOwner, modem_->owner_);
Jason Glasgowa585fc32012-06-06 11:04:09 -040084 EXPECT_EQ(kService, modem_->service_);
Jason Glasgowe9089492012-02-23 17:57:37 -050085 EXPECT_EQ(kPath, modem_->path_);
David Rochbergfa1d31d2012-03-20 10:38:07 -040086 ReplaceSingletons();
87 expected_address_ = ByteString(kAddress, arraysize(kAddress));
88
89 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(kLinkName)).
90 WillRepeatedly(Return(kTestInterfaceIndex));
91
Prathmesh Prabhu27526f12013-03-25 19:42:18 -070092 EXPECT_CALL(*modem_info_.mock_manager(), device_info())
93 .WillRepeatedly(Return(&device_info_));
Darin Petkove0a312e2011-07-20 13:45:28 -070094}
95
96void ModemTest::TearDown() {
Jason Glasgowe9089492012-02-23 17:57:37 -050097 modem_.reset();
Darin Petkove0a312e2011-07-20 13:45:28 -070098}
99
David Rochbergfa1d31d2012-03-20 10:38:07 -0400100TEST_F(ModemTest, PendingDevicePropertiesAndCreate) {
101 static const char kSentinel[] = "sentinel";
Ben Chan7fab8972014-08-10 17:14:46 -0700102 static const uint32_t kSentinelValue = 17;
Darin Petkove0a312e2011-07-20 13:45:28 -0700103
Ben Chan876efd32012-09-28 15:25:13 -0700104 DBusInterfaceToProperties properties;
105 properties[MM_MODEM_INTERFACE][kSentinel].writer().append_uint32(
106 kSentinelValue);
David Rochbergfa1d31d2012-03-20 10:38:07 -0400107
108 EXPECT_CALL(*modem_, GetLinkName(_, _)).WillRepeatedly(DoAll(
109 SetArgumentPointee<1>(string(kLinkName)),
110 Return(true)));
111 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(StrEq(kLinkName))).
112 WillRepeatedly(Return(kTestInterfaceIndex));
113
114 // The first time we call CreateDeviceFromModemProperties,
115 // GetMACAddress will fail.
Prathmesh Prabhu27526f12013-03-25 19:42:18 -0700116 EXPECT_CALL(device_info_, GetMACAddress(kTestInterfaceIndex, _)).
David Rochbergfa1d31d2012-03-20 10:38:07 -0400117 WillOnce(Return(false));
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400118 EXPECT_CALL(*modem_, GetModemInterface()).
119 WillRepeatedly(Return(MM_MODEM_INTERFACE));
David Rochbergfa1d31d2012-03-20 10:38:07 -0400120 modem_->CreateDeviceFromModemProperties(properties);
Jason Glasgowe9089492012-02-23 17:57:37 -0500121 EXPECT_FALSE(modem_->device_.get());
Darin Petkove0a312e2011-07-20 13:45:28 -0700122
David Rochbergfa1d31d2012-03-20 10:38:07 -0400123 // On the second time, we allow GetMACAddress to succeed. Now we
124 // expect a device to be built
Prathmesh Prabhu27526f12013-03-25 19:42:18 -0700125 EXPECT_CALL(device_info_, GetMACAddress(kTestInterfaceIndex, _)).
David Rochbergfa1d31d2012-03-20 10:38:07 -0400126 WillOnce(DoAll(SetArgumentPointee<1>(expected_address_),
127 Return(true)));
128
129 // modem will take ownership
Paul Stewart2f6c7892015-06-16 13:13:10 -0700130 MockCellular* cellular = new MockCellular(
Prathmesh Prabhu27526f12013-03-25 19:42:18 -0700131 &modem_info_,
David Rochbergfa1d31d2012-03-20 10:38:07 -0400132 kLinkName,
133 kAddressAsString,
134 kTestInterfaceIndex,
Ben Chan3ecdf822012-08-06 12:29:23 -0700135 Cellular::kTypeCDMA,
David Rochbergfa1d31d2012-03-20 10:38:07 -0400136 kOwner,
Jason Glasgowa585fc32012-06-06 11:04:09 -0400137 kService,
David Rochbergfa1d31d2012-03-20 10:38:07 -0400138 kPath,
Ben Chan3ecdf822012-08-06 12:29:23 -0700139 ProxyFactory::GetInstance());
David Rochbergfa1d31d2012-03-20 10:38:07 -0400140
141 EXPECT_CALL(*modem_,
142 ConstructCellular(StrEq(kLinkName),
143 StrEq(kAddressAsString),
144 kTestInterfaceIndex)).
145 WillOnce(Return(cellular));
146
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400147 EXPECT_CALL(*cellular, OnDBusPropertiesChanged(
148 _,
149 HasDBusPropertyWithValueU32(kSentinel, kSentinelValue),
150 _));
Prathmesh Prabhu27526f12013-03-25 19:42:18 -0700151 EXPECT_CALL(device_info_, RegisterDevice(_));
David Rochbergfa1d31d2012-03-20 10:38:07 -0400152 modem_->OnDeviceInfoAvailable(kLinkName);
153
154 EXPECT_TRUE(modem_->device_.get());
Darin Petkova0a0efe2012-06-27 12:50:01 +0200155
mukesh agrawal9da07772013-05-15 14:15:17 -0700156 // Add expectations for the eventual |modem_| destruction.
Darin Petkova0a0efe2012-06-27 12:50:01 +0200157 EXPECT_CALL(*cellular, DestroyService());
Prathmesh Prabhu27526f12013-03-25 19:42:18 -0700158 EXPECT_CALL(device_info_, DeregisterDevice(_));
David Rochbergfa1d31d2012-03-20 10:38:07 -0400159}
160
161TEST_F(ModemTest, EarlyDeviceProperties) {
162 // OnDeviceInfoAvailable called before
163 // CreateDeviceFromModemProperties: Do nothing
164 modem_->OnDeviceInfoAvailable(kLinkName);
165 EXPECT_FALSE(modem_->device_.get());
166}
167
168TEST_F(ModemTest, CreateDeviceEarlyFailures) {
Ben Chan876efd32012-09-28 15:25:13 -0700169 DBusInterfaceToProperties properties;
David Rochbergfa1d31d2012-03-20 10:38:07 -0400170
171 EXPECT_CALL(*modem_, ConstructCellular(_, _, _)).Times(0);
Ben Chan876efd32012-09-28 15:25:13 -0700172 EXPECT_CALL(*modem_, GetModemInterface()).
173 WillRepeatedly(Return(MM_MODEM_INTERFACE));
174
175 // No modem interface properties: no device created
176 modem_->CreateDeviceFromModemProperties(properties);
177 EXPECT_FALSE(modem_->device_.get());
178
179 properties[MM_MODEM_INTERFACE] = DBusPropertiesMap();
David Rochbergfa1d31d2012-03-20 10:38:07 -0400180
David Rochbergfa1d31d2012-03-20 10:38:07 -0400181 // Link name, but no ifindex: no device created
182 EXPECT_CALL(*modem_, GetLinkName(_, _)).WillOnce(DoAll(
183 SetArgumentPointee<1>(string(kLinkName)),
184 Return(true)));
185 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(StrEq(kLinkName))).WillOnce(
186 Return(-1));
187 modem_->CreateDeviceFromModemProperties(properties);
Jason Glasgowe9089492012-02-23 17:57:37 -0500188 EXPECT_FALSE(modem_->device_.get());
mukesh agrawal12533ad2013-08-01 15:43:23 -0700189
190 // The params are good, but the device is blacklisted.
191 EXPECT_CALL(*modem_, GetLinkName(_, _)).WillOnce(DoAll(
192 SetArgumentPointee<1>(string(kLinkName)),
193 Return(true)));
194 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(StrEq(kLinkName)))
195 .WillOnce(Return(kTestInterfaceIndex));
196 EXPECT_CALL(device_info_, GetMACAddress(kTestInterfaceIndex, _))
197 .WillOnce(DoAll(SetArgumentPointee<1>(expected_address_),
198 Return(true)));
199 EXPECT_CALL(device_info_, IsDeviceBlackListed(kLinkName))
200 .WillRepeatedly(Return(true));
201 modem_->CreateDeviceFromModemProperties(properties);
202 EXPECT_FALSE(modem_->device_.get());
203
204 // No link name: see CreateDevicePPP.
David Rochbergfa1d31d2012-03-20 10:38:07 -0400205}
Darin Petkove0a312e2011-07-20 13:45:28 -0700206
mukesh agrawal9da07772013-05-15 14:15:17 -0700207TEST_F(ModemTest, CreateDevicePPP) {
208 DBusInterfaceToProperties properties;
209 properties[MM_MODEM_INTERFACE] = DBusPropertiesMap();
210
211 string dev_name(
212 base::StringPrintf(Modem::kFakeDevNameFormat, Modem::fake_dev_serial_));
213
214 // |modem_| will take ownership.
Paul Stewart2f6c7892015-06-16 13:13:10 -0700215 MockCellular* cellular = new MockCellular(
mukesh agrawal9da07772013-05-15 14:15:17 -0700216 &modem_info_,
217 dev_name,
218 Modem::kFakeDevAddress,
219 Modem::kFakeDevInterfaceIndex,
220 Cellular::kTypeUniversal,
221 kOwner,
222 kService,
223 kPath,
224 ProxyFactory::GetInstance());
225
226 EXPECT_CALL(*modem_, GetModemInterface()).
227 WillRepeatedly(Return(MM_MODEM_INTERFACE));
228 // No link name: assumed to be a PPP dongle.
229 EXPECT_CALL(*modem_, GetLinkName(_, _)).WillOnce(Return(false));
230 EXPECT_CALL(*modem_,
231 ConstructCellular(dev_name,
232 StrEq(Modem::kFakeDevAddress),
233 Modem::kFakeDevInterfaceIndex)).
234 WillOnce(Return(cellular));
235 EXPECT_CALL(device_info_, RegisterDevice(_));
236
237 modem_->CreateDeviceFromModemProperties(properties);
238 EXPECT_TRUE(modem_->device_.get());
239
240 // Add expectations for the eventual |modem_| destruction.
241 EXPECT_CALL(*cellular, DestroyService());
242 EXPECT_CALL(device_info_, DeregisterDevice(_));
243}
244
mukesh agrawal12533ad2013-08-01 15:43:23 -0700245TEST_F(ModemTest, GetDeviceParams) {
246 string mac_address;
247 int interface_index = 2;
248 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(_)).WillOnce(Return(-1));
249 EXPECT_CALL(device_info_, GetMACAddress(_, _)).Times(AnyNumber())
250 .WillRepeatedly(Return(false));
251 EXPECT_FALSE(modem_->GetDeviceParams(&mac_address, &interface_index));
252 EXPECT_EQ(-1, interface_index);
253
254 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(_)).WillOnce(Return(-2));
255 EXPECT_CALL(device_info_, GetMACAddress(_, _)).Times(AnyNumber())
256 .WillRepeatedly(Return(false));
257 EXPECT_FALSE(modem_->GetDeviceParams(&mac_address, &interface_index));
258 EXPECT_EQ(-2, interface_index);
259
260 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(_)).WillOnce(Return(1));
261 EXPECT_CALL(device_info_, GetMACAddress(_, _)).WillOnce(Return(false));
262 EXPECT_FALSE(modem_->GetDeviceParams(&mac_address, &interface_index));
263 EXPECT_EQ(1, interface_index);
264
265 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(_)).WillOnce(Return(2));
266 EXPECT_CALL(device_info_, GetMACAddress(2, _)).
267 WillOnce(DoAll(SetArgumentPointee<1>(expected_address_),
268 Return(true)));
269 EXPECT_TRUE(modem_->GetDeviceParams(&mac_address, &interface_index));
270 EXPECT_EQ(2, interface_index);
271 EXPECT_EQ(kAddressAsString, mac_address);
mukesh agrawal12533ad2013-08-01 15:43:23 -0700272}
273
David Rochbergfa1d31d2012-03-20 10:38:07 -0400274TEST_F(ModemTest, RejectPPPModem) {
275 // TODO(rochberg): Port this to ModemClassic
Darin Petkove0a312e2011-07-20 13:45:28 -0700276}
277
278} // namespace shill