blob: 24801777b10adf915c907c486150285bf7a03865 [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::_;
33using 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()
Prathmesh Prabhu27526f12013-03-25 19:42:18 -070057 : modem_info_(NULL, &dispatcher_, NULL, NULL, NULL),
58 device_info_(modem_info_.control_interface(), modem_info_.dispatcher(),
59 modem_info_.metrics(), modem_info_.manager()),
Darin Petkov3b292332011-07-28 14:17:24 -070060 proxy_(new MockDBusPropertiesProxy()),
61 proxy_factory_(this),
David Rochbergfa1d31d2012-03-20 10:38:07 -040062 modem_(
63 new StrictModem(
64 kOwner,
Jason Glasgowa585fc32012-06-06 11:04:09 -040065 kService,
David Rochbergfa1d31d2012-03-20 10:38:07 -040066 kPath,
Prathmesh Prabhu27526f12013-03-25 19:42:18 -070067 &modem_info_)) {}
Darin Petkove0a312e2011-07-20 13:45:28 -070068 virtual void SetUp();
69 virtual void TearDown();
70
David Rochbergfa1d31d2012-03-20 10:38:07 -040071 void ReplaceSingletons() {
72 modem_->rtnl_handler_ = &rtnl_handler_;
Darin Petkove0a312e2011-07-20 13:45:28 -070073 }
74
75 protected:
76 class TestProxyFactory : public ProxyFactory {
77 public:
Paul Stewart7355ce12011-09-02 10:47:01 -070078 explicit TestProxyFactory(ModemTest *test) : test_(test) {}
Darin Petkove0a312e2011-07-20 13:45:28 -070079
80 virtual DBusPropertiesProxyInterface *CreateDBusPropertiesProxy(
mukesh agrawal1830fa12011-09-26 14:31:40 -070081 const string &/*path*/,
82 const string &/*service*/) {
Darin Petkov3b292332011-07-28 14:17:24 -070083 return test_->proxy_.release();
Darin Petkove0a312e2011-07-20 13:45:28 -070084 }
85
86 private:
Darin Petkov3b292332011-07-28 14:17:24 -070087 ModemTest *test_;
Darin Petkove0a312e2011-07-20 13:45:28 -070088 };
89
Darin Petkove0a312e2011-07-20 13:45:28 -070090 EventDispatcher dispatcher_;
Prathmesh Prabhu27526f12013-03-25 19:42:18 -070091 MockModemInfo modem_info_;
92 MockDeviceInfo device_info_;
Darin Petkov3b292332011-07-28 14:17:24 -070093 scoped_ptr<MockDBusPropertiesProxy> proxy_;
Darin Petkove0a312e2011-07-20 13:45:28 -070094 TestProxyFactory proxy_factory_;
David Rochbergfa1d31d2012-03-20 10:38:07 -040095 scoped_ptr<StrictModem> modem_;
96 MockRTNLHandler rtnl_handler_;
97 ByteString expected_address_;
Darin Petkove0a312e2011-07-20 13:45:28 -070098};
99
Darin Petkove0a312e2011-07-20 13:45:28 -0700100void ModemTest::SetUp() {
Jason Glasgowe9089492012-02-23 17:57:37 -0500101 EXPECT_EQ(kOwner, modem_->owner_);
Jason Glasgowa585fc32012-06-06 11:04:09 -0400102 EXPECT_EQ(kService, modem_->service_);
Jason Glasgowe9089492012-02-23 17:57:37 -0500103 EXPECT_EQ(kPath, modem_->path_);
David Rochbergfa1d31d2012-03-20 10:38:07 -0400104 ReplaceSingletons();
105 expected_address_ = ByteString(kAddress, arraysize(kAddress));
106
107 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(kLinkName)).
108 WillRepeatedly(Return(kTestInterfaceIndex));
109
Prathmesh Prabhu27526f12013-03-25 19:42:18 -0700110 EXPECT_CALL(*modem_info_.mock_manager(), device_info())
111 .WillRepeatedly(Return(&device_info_));
Darin Petkove0a312e2011-07-20 13:45:28 -0700112}
113
114void ModemTest::TearDown() {
Jason Glasgowe9089492012-02-23 17:57:37 -0500115 modem_.reset();
Darin Petkove0a312e2011-07-20 13:45:28 -0700116}
117
David Rochbergfa1d31d2012-03-20 10:38:07 -0400118TEST_F(ModemTest, PendingDevicePropertiesAndCreate) {
119 static const char kSentinel[] = "sentinel";
120 static const uint32 kSentinelValue = 17;
Darin Petkove0a312e2011-07-20 13:45:28 -0700121
Ben Chan876efd32012-09-28 15:25:13 -0700122 DBusInterfaceToProperties properties;
123 properties[MM_MODEM_INTERFACE][kSentinel].writer().append_uint32(
124 kSentinelValue);
David Rochbergfa1d31d2012-03-20 10:38:07 -0400125
126 EXPECT_CALL(*modem_, GetLinkName(_, _)).WillRepeatedly(DoAll(
127 SetArgumentPointee<1>(string(kLinkName)),
128 Return(true)));
129 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(StrEq(kLinkName))).
130 WillRepeatedly(Return(kTestInterfaceIndex));
131
132 // The first time we call CreateDeviceFromModemProperties,
133 // GetMACAddress will fail.
Prathmesh Prabhu27526f12013-03-25 19:42:18 -0700134 EXPECT_CALL(device_info_, GetMACAddress(kTestInterfaceIndex, _)).
David Rochbergfa1d31d2012-03-20 10:38:07 -0400135 WillOnce(Return(false));
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400136 EXPECT_CALL(*modem_, GetModemInterface()).
137 WillRepeatedly(Return(MM_MODEM_INTERFACE));
David Rochbergfa1d31d2012-03-20 10:38:07 -0400138 modem_->CreateDeviceFromModemProperties(properties);
Jason Glasgowe9089492012-02-23 17:57:37 -0500139 EXPECT_FALSE(modem_->device_.get());
Darin Petkove0a312e2011-07-20 13:45:28 -0700140
David Rochbergfa1d31d2012-03-20 10:38:07 -0400141 // On the second time, we allow GetMACAddress to succeed. Now we
142 // expect a device to be built
Prathmesh Prabhu27526f12013-03-25 19:42:18 -0700143 EXPECT_CALL(device_info_, GetMACAddress(kTestInterfaceIndex, _)).
David Rochbergfa1d31d2012-03-20 10:38:07 -0400144 WillOnce(DoAll(SetArgumentPointee<1>(expected_address_),
145 Return(true)));
146
147 // modem will take ownership
Darin Petkova0a0efe2012-06-27 12:50:01 +0200148 MockCellular *cellular = new MockCellular(
Prathmesh Prabhu27526f12013-03-25 19:42:18 -0700149 &modem_info_,
David Rochbergfa1d31d2012-03-20 10:38:07 -0400150 kLinkName,
151 kAddressAsString,
152 kTestInterfaceIndex,
Ben Chan3ecdf822012-08-06 12:29:23 -0700153 Cellular::kTypeCDMA,
David Rochbergfa1d31d2012-03-20 10:38:07 -0400154 kOwner,
Jason Glasgowa585fc32012-06-06 11:04:09 -0400155 kService,
David Rochbergfa1d31d2012-03-20 10:38:07 -0400156 kPath,
Ben Chan3ecdf822012-08-06 12:29:23 -0700157 ProxyFactory::GetInstance());
David Rochbergfa1d31d2012-03-20 10:38:07 -0400158
159 EXPECT_CALL(*modem_,
160 ConstructCellular(StrEq(kLinkName),
161 StrEq(kAddressAsString),
162 kTestInterfaceIndex)).
163 WillOnce(Return(cellular));
164
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400165 EXPECT_CALL(*cellular, OnDBusPropertiesChanged(
166 _,
167 HasDBusPropertyWithValueU32(kSentinel, kSentinelValue),
168 _));
Prathmesh Prabhu27526f12013-03-25 19:42:18 -0700169 EXPECT_CALL(device_info_, RegisterDevice(_));
David Rochbergfa1d31d2012-03-20 10:38:07 -0400170 modem_->OnDeviceInfoAvailable(kLinkName);
171
172 EXPECT_TRUE(modem_->device_.get());
Darin Petkova0a0efe2012-06-27 12:50:01 +0200173
mukesh agrawal9da07772013-05-15 14:15:17 -0700174 // Add expectations for the eventual |modem_| destruction.
Darin Petkova0a0efe2012-06-27 12:50:01 +0200175 EXPECT_CALL(*cellular, DestroyService());
Prathmesh Prabhu27526f12013-03-25 19:42:18 -0700176 EXPECT_CALL(device_info_, DeregisterDevice(_));
David Rochbergfa1d31d2012-03-20 10:38:07 -0400177}
178
179TEST_F(ModemTest, EarlyDeviceProperties) {
180 // OnDeviceInfoAvailable called before
181 // CreateDeviceFromModemProperties: Do nothing
182 modem_->OnDeviceInfoAvailable(kLinkName);
183 EXPECT_FALSE(modem_->device_.get());
184}
185
186TEST_F(ModemTest, CreateDeviceEarlyFailures) {
Ben Chan876efd32012-09-28 15:25:13 -0700187 DBusInterfaceToProperties properties;
David Rochbergfa1d31d2012-03-20 10:38:07 -0400188
189 EXPECT_CALL(*modem_, ConstructCellular(_, _, _)).Times(0);
Ben Chan876efd32012-09-28 15:25:13 -0700190 EXPECT_CALL(*modem_, GetModemInterface()).
191 WillRepeatedly(Return(MM_MODEM_INTERFACE));
192
193 // No modem interface properties: no device created
194 modem_->CreateDeviceFromModemProperties(properties);
195 EXPECT_FALSE(modem_->device_.get());
196
197 properties[MM_MODEM_INTERFACE] = DBusPropertiesMap();
David Rochbergfa1d31d2012-03-20 10:38:07 -0400198
David Rochbergfa1d31d2012-03-20 10:38:07 -0400199 // Link name, but no ifindex: no device created
200 EXPECT_CALL(*modem_, GetLinkName(_, _)).WillOnce(DoAll(
201 SetArgumentPointee<1>(string(kLinkName)),
202 Return(true)));
203 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(StrEq(kLinkName))).WillOnce(
204 Return(-1));
205 modem_->CreateDeviceFromModemProperties(properties);
Jason Glasgowe9089492012-02-23 17:57:37 -0500206 EXPECT_FALSE(modem_->device_.get());
David Rochbergfa1d31d2012-03-20 10:38:07 -0400207}
Darin Petkove0a312e2011-07-20 13:45:28 -0700208
mukesh agrawal9da07772013-05-15 14:15:17 -0700209TEST_F(ModemTest, CreateDevicePPP) {
210 DBusInterfaceToProperties properties;
211 properties[MM_MODEM_INTERFACE] = DBusPropertiesMap();
212
213 string dev_name(
214 base::StringPrintf(Modem::kFakeDevNameFormat, Modem::fake_dev_serial_));
215
216 // |modem_| will take ownership.
217 MockCellular *cellular = new MockCellular(
218 &modem_info_,
219 dev_name,
220 Modem::kFakeDevAddress,
221 Modem::kFakeDevInterfaceIndex,
222 Cellular::kTypeUniversal,
223 kOwner,
224 kService,
225 kPath,
226 ProxyFactory::GetInstance());
227
228 EXPECT_CALL(*modem_, GetModemInterface()).
229 WillRepeatedly(Return(MM_MODEM_INTERFACE));
230 // No link name: assumed to be a PPP dongle.
231 EXPECT_CALL(*modem_, GetLinkName(_, _)).WillOnce(Return(false));
232 EXPECT_CALL(*modem_,
233 ConstructCellular(dev_name,
234 StrEq(Modem::kFakeDevAddress),
235 Modem::kFakeDevInterfaceIndex)).
236 WillOnce(Return(cellular));
237 EXPECT_CALL(device_info_, RegisterDevice(_));
238
239 modem_->CreateDeviceFromModemProperties(properties);
240 EXPECT_TRUE(modem_->device_.get());
241
242 // Add expectations for the eventual |modem_| destruction.
243 EXPECT_CALL(*cellular, DestroyService());
244 EXPECT_CALL(device_info_, DeregisterDevice(_));
245}
246
David Rochbergfa1d31d2012-03-20 10:38:07 -0400247TEST_F(ModemTest, RejectPPPModem) {
248 // TODO(rochberg): Port this to ModemClassic
Darin Petkove0a312e2011-07-20 13:45:28 -0700249}
250
251} // namespace shill