blob: d950f98e6a0a757d4a23801789b417f602ac7cd7 [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
Jason Glasgow82f9ab32012-04-04 14:27:19 -04005#include "shill/modem.h"
6
Darin Petkov6f9eaa32011-08-09 15:26:44 -07007#include <vector>
8
mukesh agrawal9da07772013-05-15 14:15:17 -07009#include <base/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
16#include "shill/cellular.h"
Darin Petkov721ac932011-11-16 15:43:09 +010017#include "shill/cellular_capability_gsm.h"
David Rochbergfa1d31d2012-03-20 10:38:07 -040018#include "shill/dbus_property_matchers.h"
Paul Stewart26b327e2011-10-19 11:38:09 -070019#include "shill/event_dispatcher.h"
Darin Petkove0a312e2011-07-20 13:45:28 -070020#include "shill/manager.h"
David Rochbergfa1d31d2012-03-20 10:38:07 -040021#include "shill/mock_cellular.h"
Darin Petkove0a312e2011-07-20 13:45:28 -070022#include "shill/mock_dbus_properties_proxy.h"
David Rochbergfa1d31d2012-03-20 10:38:07 -040023#include "shill/mock_device_info.h"
David Rochbergfa1d31d2012-03-20 10:38:07 -040024#include "shill/mock_modem.h"
Prathmesh Prabhu27526f12013-03-25 19:42:18 -070025#include "shill/mock_modem_info.h"
David Rochbergfa1d31d2012-03-20 10:38:07 -040026#include "shill/mock_rtnl_handler.h"
Darin Petkove0a312e2011-07-20 13:45:28 -070027#include "shill/proxy_factory.h"
28#include "shill/rtnl_handler.h"
Darin Petkove0a312e2011-07-20 13:45:28 -070029
30using std::string;
Darin Petkov6f9eaa32011-08-09 15:26:44 -070031using std::vector;
Darin Petkove0a312e2011-07-20 13:45:28 -070032using testing::_;
mukesh agrawal12533ad2013-08-01 15:43:23 -070033using testing::AnyNumber;
Darin Petkove0a312e2011-07-20 13:45:28 -070034using testing::DoAll;
35using testing::Return;
Chris Masone626719f2011-08-18 16:58:48 -070036using testing::SetArgumentPointee;
David Rochbergfa1d31d2012-03-20 10:38:07 -040037using testing::StrEq;
Darin Petkove0a312e2011-07-20 13:45:28 -070038using testing::StrictMock;
39using testing::Test;
40
41namespace shill {
42
43namespace {
44
45const int kTestInterfaceIndex = 5;
David Rochbergfa1d31d2012-03-20 10:38:07 -040046const char kLinkName[] = "usb0";
47const char kOwner[] = ":1.18";
Jason Glasgowa585fc32012-06-06 11:04:09 -040048const char kService[] = "org.chromium.ModemManager";
David Rochbergfa1d31d2012-03-20 10:38:07 -040049const char kPath[] = "/org/chromium/ModemManager/Gobi/0";
50const unsigned char kAddress[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
51const char kAddressAsString[] = "000102030405";
Darin Petkove0a312e2011-07-20 13:45:28 -070052
Darin Petkove0a312e2011-07-20 13:45:28 -070053} // namespace
54
55class ModemTest : public Test {
56 public:
57 ModemTest()
Prathmesh Prabhu27526f12013-03-25 19:42:18 -070058 : modem_info_(NULL, &dispatcher_, NULL, NULL, NULL),
59 device_info_(modem_info_.control_interface(), modem_info_.dispatcher(),
60 modem_info_.metrics(), modem_info_.manager()),
Darin Petkov3b292332011-07-28 14:17:24 -070061 proxy_(new MockDBusPropertiesProxy()),
62 proxy_factory_(this),
David Rochbergfa1d31d2012-03-20 10:38:07 -040063 modem_(
64 new StrictModem(
65 kOwner,
Jason Glasgowa585fc32012-06-06 11:04:09 -040066 kService,
David Rochbergfa1d31d2012-03-20 10:38:07 -040067 kPath,
Prathmesh Prabhu27526f12013-03-25 19:42:18 -070068 &modem_info_)) {}
Darin Petkove0a312e2011-07-20 13:45:28 -070069 virtual void SetUp();
70 virtual void TearDown();
71
David Rochbergfa1d31d2012-03-20 10:38:07 -040072 void ReplaceSingletons() {
73 modem_->rtnl_handler_ = &rtnl_handler_;
Darin Petkove0a312e2011-07-20 13:45:28 -070074 }
75
76 protected:
77 class TestProxyFactory : public ProxyFactory {
78 public:
Paul Stewart7355ce12011-09-02 10:47:01 -070079 explicit TestProxyFactory(ModemTest *test) : test_(test) {}
Darin Petkove0a312e2011-07-20 13:45:28 -070080
81 virtual DBusPropertiesProxyInterface *CreateDBusPropertiesProxy(
mukesh agrawal1830fa12011-09-26 14:31:40 -070082 const string &/*path*/,
83 const string &/*service*/) {
Darin Petkov3b292332011-07-28 14:17:24 -070084 return test_->proxy_.release();
Darin Petkove0a312e2011-07-20 13:45:28 -070085 }
86
87 private:
Darin Petkov3b292332011-07-28 14:17:24 -070088 ModemTest *test_;
Darin Petkove0a312e2011-07-20 13:45:28 -070089 };
90
Darin Petkove0a312e2011-07-20 13:45:28 -070091 EventDispatcher dispatcher_;
Prathmesh Prabhu27526f12013-03-25 19:42:18 -070092 MockModemInfo modem_info_;
93 MockDeviceInfo device_info_;
Darin Petkov3b292332011-07-28 14:17:24 -070094 scoped_ptr<MockDBusPropertiesProxy> proxy_;
Darin Petkove0a312e2011-07-20 13:45:28 -070095 TestProxyFactory proxy_factory_;
David Rochbergfa1d31d2012-03-20 10:38:07 -040096 scoped_ptr<StrictModem> modem_;
97 MockRTNLHandler rtnl_handler_;
98 ByteString expected_address_;
Darin Petkove0a312e2011-07-20 13:45:28 -070099};
100
Darin Petkove0a312e2011-07-20 13:45:28 -0700101void ModemTest::SetUp() {
Jason Glasgowe9089492012-02-23 17:57:37 -0500102 EXPECT_EQ(kOwner, modem_->owner_);
Jason Glasgowa585fc32012-06-06 11:04:09 -0400103 EXPECT_EQ(kService, modem_->service_);
Jason Glasgowe9089492012-02-23 17:57:37 -0500104 EXPECT_EQ(kPath, modem_->path_);
David Rochbergfa1d31d2012-03-20 10:38:07 -0400105 ReplaceSingletons();
106 expected_address_ = ByteString(kAddress, arraysize(kAddress));
107
108 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(kLinkName)).
109 WillRepeatedly(Return(kTestInterfaceIndex));
110
Prathmesh Prabhu27526f12013-03-25 19:42:18 -0700111 EXPECT_CALL(*modem_info_.mock_manager(), device_info())
112 .WillRepeatedly(Return(&device_info_));
Darin Petkove0a312e2011-07-20 13:45:28 -0700113}
114
115void ModemTest::TearDown() {
Jason Glasgowe9089492012-02-23 17:57:37 -0500116 modem_.reset();
Darin Petkove0a312e2011-07-20 13:45:28 -0700117}
118
David Rochbergfa1d31d2012-03-20 10:38:07 -0400119TEST_F(ModemTest, PendingDevicePropertiesAndCreate) {
120 static const char kSentinel[] = "sentinel";
121 static const uint32 kSentinelValue = 17;
Darin Petkove0a312e2011-07-20 13:45:28 -0700122
Ben Chan876efd32012-09-28 15:25:13 -0700123 DBusInterfaceToProperties properties;
124 properties[MM_MODEM_INTERFACE][kSentinel].writer().append_uint32(
125 kSentinelValue);
David Rochbergfa1d31d2012-03-20 10:38:07 -0400126
127 EXPECT_CALL(*modem_, GetLinkName(_, _)).WillRepeatedly(DoAll(
128 SetArgumentPointee<1>(string(kLinkName)),
129 Return(true)));
130 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(StrEq(kLinkName))).
131 WillRepeatedly(Return(kTestInterfaceIndex));
132
133 // The first time we call CreateDeviceFromModemProperties,
134 // GetMACAddress will fail.
Prathmesh Prabhu27526f12013-03-25 19:42:18 -0700135 EXPECT_CALL(device_info_, GetMACAddress(kTestInterfaceIndex, _)).
David Rochbergfa1d31d2012-03-20 10:38:07 -0400136 WillOnce(Return(false));
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400137 EXPECT_CALL(*modem_, GetModemInterface()).
138 WillRepeatedly(Return(MM_MODEM_INTERFACE));
David Rochbergfa1d31d2012-03-20 10:38:07 -0400139 modem_->CreateDeviceFromModemProperties(properties);
Jason Glasgowe9089492012-02-23 17:57:37 -0500140 EXPECT_FALSE(modem_->device_.get());
Darin Petkove0a312e2011-07-20 13:45:28 -0700141
David Rochbergfa1d31d2012-03-20 10:38:07 -0400142 // On the second time, we allow GetMACAddress to succeed. Now we
143 // expect a device to be built
Prathmesh Prabhu27526f12013-03-25 19:42:18 -0700144 EXPECT_CALL(device_info_, GetMACAddress(kTestInterfaceIndex, _)).
David Rochbergfa1d31d2012-03-20 10:38:07 -0400145 WillOnce(DoAll(SetArgumentPointee<1>(expected_address_),
146 Return(true)));
147
148 // modem will take ownership
Darin Petkova0a0efe2012-06-27 12:50:01 +0200149 MockCellular *cellular = new MockCellular(
Prathmesh Prabhu27526f12013-03-25 19:42:18 -0700150 &modem_info_,
David Rochbergfa1d31d2012-03-20 10:38:07 -0400151 kLinkName,
152 kAddressAsString,
153 kTestInterfaceIndex,
Ben Chan3ecdf822012-08-06 12:29:23 -0700154 Cellular::kTypeCDMA,
David Rochbergfa1d31d2012-03-20 10:38:07 -0400155 kOwner,
Jason Glasgowa585fc32012-06-06 11:04:09 -0400156 kService,
David Rochbergfa1d31d2012-03-20 10:38:07 -0400157 kPath,
Ben Chan3ecdf822012-08-06 12:29:23 -0700158 ProxyFactory::GetInstance());
David Rochbergfa1d31d2012-03-20 10:38:07 -0400159
160 EXPECT_CALL(*modem_,
161 ConstructCellular(StrEq(kLinkName),
162 StrEq(kAddressAsString),
163 kTestInterfaceIndex)).
164 WillOnce(Return(cellular));
165
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400166 EXPECT_CALL(*cellular, OnDBusPropertiesChanged(
167 _,
168 HasDBusPropertyWithValueU32(kSentinel, kSentinelValue),
169 _));
Prathmesh Prabhu27526f12013-03-25 19:42:18 -0700170 EXPECT_CALL(device_info_, RegisterDevice(_));
David Rochbergfa1d31d2012-03-20 10:38:07 -0400171 modem_->OnDeviceInfoAvailable(kLinkName);
172
173 EXPECT_TRUE(modem_->device_.get());
Darin Petkova0a0efe2012-06-27 12:50:01 +0200174
mukesh agrawal9da07772013-05-15 14:15:17 -0700175 // Add expectations for the eventual |modem_| destruction.
Darin Petkova0a0efe2012-06-27 12:50:01 +0200176 EXPECT_CALL(*cellular, DestroyService());
Prathmesh Prabhu27526f12013-03-25 19:42:18 -0700177 EXPECT_CALL(device_info_, DeregisterDevice(_));
David Rochbergfa1d31d2012-03-20 10:38:07 -0400178}
179
180TEST_F(ModemTest, EarlyDeviceProperties) {
181 // OnDeviceInfoAvailable called before
182 // CreateDeviceFromModemProperties: Do nothing
183 modem_->OnDeviceInfoAvailable(kLinkName);
184 EXPECT_FALSE(modem_->device_.get());
185}
186
187TEST_F(ModemTest, CreateDeviceEarlyFailures) {
Ben Chan876efd32012-09-28 15:25:13 -0700188 DBusInterfaceToProperties properties;
David Rochbergfa1d31d2012-03-20 10:38:07 -0400189
190 EXPECT_CALL(*modem_, ConstructCellular(_, _, _)).Times(0);
Ben Chan876efd32012-09-28 15:25:13 -0700191 EXPECT_CALL(*modem_, GetModemInterface()).
192 WillRepeatedly(Return(MM_MODEM_INTERFACE));
193
194 // No modem interface properties: no device created
195 modem_->CreateDeviceFromModemProperties(properties);
196 EXPECT_FALSE(modem_->device_.get());
197
198 properties[MM_MODEM_INTERFACE] = DBusPropertiesMap();
David Rochbergfa1d31d2012-03-20 10:38:07 -0400199
David Rochbergfa1d31d2012-03-20 10:38:07 -0400200 // Link name, but no ifindex: no device created
201 EXPECT_CALL(*modem_, GetLinkName(_, _)).WillOnce(DoAll(
202 SetArgumentPointee<1>(string(kLinkName)),
203 Return(true)));
204 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(StrEq(kLinkName))).WillOnce(
205 Return(-1));
206 modem_->CreateDeviceFromModemProperties(properties);
Jason Glasgowe9089492012-02-23 17:57:37 -0500207 EXPECT_FALSE(modem_->device_.get());
mukesh agrawal12533ad2013-08-01 15:43:23 -0700208
209 // The params are good, but the device is blacklisted.
210 EXPECT_CALL(*modem_, GetLinkName(_, _)).WillOnce(DoAll(
211 SetArgumentPointee<1>(string(kLinkName)),
212 Return(true)));
213 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(StrEq(kLinkName)))
214 .WillOnce(Return(kTestInterfaceIndex));
215 EXPECT_CALL(device_info_, GetMACAddress(kTestInterfaceIndex, _))
216 .WillOnce(DoAll(SetArgumentPointee<1>(expected_address_),
217 Return(true)));
218 EXPECT_CALL(device_info_, IsDeviceBlackListed(kLinkName))
219 .WillRepeatedly(Return(true));
220 modem_->CreateDeviceFromModemProperties(properties);
221 EXPECT_FALSE(modem_->device_.get());
222
223 // No link name: see CreateDevicePPP.
David Rochbergfa1d31d2012-03-20 10:38:07 -0400224}
Darin Petkove0a312e2011-07-20 13:45:28 -0700225
mukesh agrawal9da07772013-05-15 14:15:17 -0700226TEST_F(ModemTest, CreateDevicePPP) {
227 DBusInterfaceToProperties properties;
228 properties[MM_MODEM_INTERFACE] = DBusPropertiesMap();
229
230 string dev_name(
231 base::StringPrintf(Modem::kFakeDevNameFormat, Modem::fake_dev_serial_));
232
233 // |modem_| will take ownership.
234 MockCellular *cellular = new MockCellular(
235 &modem_info_,
236 dev_name,
237 Modem::kFakeDevAddress,
238 Modem::kFakeDevInterfaceIndex,
239 Cellular::kTypeUniversal,
240 kOwner,
241 kService,
242 kPath,
243 ProxyFactory::GetInstance());
244
245 EXPECT_CALL(*modem_, GetModemInterface()).
246 WillRepeatedly(Return(MM_MODEM_INTERFACE));
247 // No link name: assumed to be a PPP dongle.
248 EXPECT_CALL(*modem_, GetLinkName(_, _)).WillOnce(Return(false));
249 EXPECT_CALL(*modem_,
250 ConstructCellular(dev_name,
251 StrEq(Modem::kFakeDevAddress),
252 Modem::kFakeDevInterfaceIndex)).
253 WillOnce(Return(cellular));
254 EXPECT_CALL(device_info_, RegisterDevice(_));
255
256 modem_->CreateDeviceFromModemProperties(properties);
257 EXPECT_TRUE(modem_->device_.get());
258
259 // Add expectations for the eventual |modem_| destruction.
260 EXPECT_CALL(*cellular, DestroyService());
261 EXPECT_CALL(device_info_, DeregisterDevice(_));
262}
263
mukesh agrawal12533ad2013-08-01 15:43:23 -0700264TEST_F(ModemTest, GetDeviceParams) {
265 string mac_address;
266 int interface_index = 2;
267 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(_)).WillOnce(Return(-1));
268 EXPECT_CALL(device_info_, GetMACAddress(_, _)).Times(AnyNumber())
269 .WillRepeatedly(Return(false));
270 EXPECT_FALSE(modem_->GetDeviceParams(&mac_address, &interface_index));
271 EXPECT_EQ(-1, interface_index);
272
273 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(_)).WillOnce(Return(-2));
274 EXPECT_CALL(device_info_, GetMACAddress(_, _)).Times(AnyNumber())
275 .WillRepeatedly(Return(false));
276 EXPECT_FALSE(modem_->GetDeviceParams(&mac_address, &interface_index));
277 EXPECT_EQ(-2, interface_index);
278
279 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(_)).WillOnce(Return(1));
280 EXPECT_CALL(device_info_, GetMACAddress(_, _)).WillOnce(Return(false));
281 EXPECT_FALSE(modem_->GetDeviceParams(&mac_address, &interface_index));
282 EXPECT_EQ(1, interface_index);
283
284 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(_)).WillOnce(Return(2));
285 EXPECT_CALL(device_info_, GetMACAddress(2, _)).
286 WillOnce(DoAll(SetArgumentPointee<1>(expected_address_),
287 Return(true)));
288 EXPECT_TRUE(modem_->GetDeviceParams(&mac_address, &interface_index));
289 EXPECT_EQ(2, interface_index);
290 EXPECT_EQ(kAddressAsString, mac_address);
291
292}
293
David Rochbergfa1d31d2012-03-20 10:38:07 -0400294TEST_F(ModemTest, RejectPPPModem) {
295 // TODO(rochberg): Port this to ModemClassic
Darin Petkove0a312e2011-07-20 13:45:28 -0700296}
297
298} // namespace shill