blob: 56481228150330c58f9dceaf3d96c27a8cc98e72 [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
Chris Masone626719f2011-08-18 16:58:48 -07009#include <gmock/gmock.h>
Darin Petkove0a312e2011-07-20 13:45:28 -070010#include <gtest/gtest.h>
11#include <mm/mm-modem.h>
12#include <net/if.h>
13#include <sys/ioctl.h>
14
15#include "shill/cellular.h"
Darin Petkov721ac932011-11-16 15:43:09 +010016#include "shill/cellular_capability_gsm.h"
David Rochbergfa1d31d2012-03-20 10:38:07 -040017#include "shill/dbus_property_matchers.h"
Paul Stewart26b327e2011-10-19 11:38:09 -070018#include "shill/event_dispatcher.h"
Darin Petkove0a312e2011-07-20 13:45:28 -070019#include "shill/manager.h"
David Rochbergfa1d31d2012-03-20 10:38:07 -040020#include "shill/mock_cellular.h"
Darin Petkove0a312e2011-07-20 13:45:28 -070021#include "shill/mock_control.h"
22#include "shill/mock_dbus_properties_proxy.h"
David Rochbergfa1d31d2012-03-20 10:38:07 -040023#include "shill/mock_device_info.h"
Darin Petkove0a312e2011-07-20 13:45:28 -070024#include "shill/mock_glib.h"
Chris Masone626719f2011-08-18 16:58:48 -070025#include "shill/mock_manager.h"
Thieu Le3426c8f2012-01-11 17:35:11 -080026#include "shill/mock_metrics.h"
David Rochbergfa1d31d2012-03-20 10:38:07 -040027#include "shill/mock_modem.h"
28#include "shill/mock_rtnl_handler.h"
Darin Petkove0a312e2011-07-20 13:45:28 -070029#include "shill/proxy_factory.h"
30#include "shill/rtnl_handler.h"
Darin Petkove0a312e2011-07-20 13:45:28 -070031
32using std::string;
Darin Petkov6f9eaa32011-08-09 15:26:44 -070033using std::vector;
Darin Petkove0a312e2011-07-20 13:45:28 -070034using testing::_;
35using testing::DoAll;
36using testing::Return;
Chris Masone626719f2011-08-18 16:58:48 -070037using testing::SetArgumentPointee;
David Rochbergfa1d31d2012-03-20 10:38:07 -040038using testing::StrEq;
Darin Petkove0a312e2011-07-20 13:45:28 -070039using testing::StrictMock;
40using testing::Test;
41
42namespace shill {
43
44namespace {
45
46const int kTestInterfaceIndex = 5;
David Rochbergfa1d31d2012-03-20 10:38:07 -040047const char kLinkName[] = "usb0";
48const char kOwner[] = ":1.18";
Jason Glasgowa585fc32012-06-06 11:04:09 -040049const char kService[] = "org.chromium.ModemManager";
David Rochbergfa1d31d2012-03-20 10:38:07 -040050const char kPath[] = "/org/chromium/ModemManager/Gobi/0";
51const unsigned char kAddress[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
52const char kAddressAsString[] = "000102030405";
Darin Petkove0a312e2011-07-20 13:45:28 -070053
54ACTION(SetInterfaceIndex) {
55 if (arg2) {
56 reinterpret_cast<struct ifreq *>(arg2)->ifr_ifindex = kTestInterfaceIndex;
57 }
58}
59
60} // namespace
61
62class ModemTest : public Test {
63 public:
64 ModemTest()
Thieu Le3426c8f2012-01-11 17:35:11 -080065 : manager_(&control_interface_, &dispatcher_, &metrics_, &glib_),
Jason Glasgowe9089492012-02-23 17:57:37 -050066 info_(&control_interface_, &dispatcher_, &metrics_, &manager_),
Darin Petkov3b292332011-07-28 14:17:24 -070067 proxy_(new MockDBusPropertiesProxy()),
68 proxy_factory_(this),
David Rochbergfa1d31d2012-03-20 10:38:07 -040069 modem_(
70 new StrictModem(
71 kOwner,
Jason Glasgowa585fc32012-06-06 11:04:09 -040072 kService,
David Rochbergfa1d31d2012-03-20 10:38:07 -040073 kPath,
74 &control_interface_,
75 &dispatcher_,
76 &metrics_,
77 &manager_,
Ben Chan62028b22012-11-05 11:20:02 -080078 static_cast<CellularOperatorInfo *>(NULL),
David Rochbergfa1d31d2012-03-20 10:38:07 -040079 static_cast<mobile_provider_db *>(NULL))) {}
Darin Petkove0a312e2011-07-20 13:45:28 -070080 virtual void SetUp();
81 virtual void TearDown();
82
David Rochbergfa1d31d2012-03-20 10:38:07 -040083 void ReplaceSingletons() {
84 modem_->rtnl_handler_ = &rtnl_handler_;
Darin Petkove0a312e2011-07-20 13:45:28 -070085 }
86
87 protected:
88 class TestProxyFactory : public ProxyFactory {
89 public:
Paul Stewart7355ce12011-09-02 10:47:01 -070090 explicit TestProxyFactory(ModemTest *test) : test_(test) {}
Darin Petkove0a312e2011-07-20 13:45:28 -070091
92 virtual DBusPropertiesProxyInterface *CreateDBusPropertiesProxy(
mukesh agrawal1830fa12011-09-26 14:31:40 -070093 const string &/*path*/,
94 const string &/*service*/) {
Darin Petkov3b292332011-07-28 14:17:24 -070095 return test_->proxy_.release();
Darin Petkove0a312e2011-07-20 13:45:28 -070096 }
97
98 private:
Darin Petkov3b292332011-07-28 14:17:24 -070099 ModemTest *test_;
Darin Petkove0a312e2011-07-20 13:45:28 -0700100 };
101
Darin Petkove0a312e2011-07-20 13:45:28 -0700102 MockGLib glib_;
103 MockControl control_interface_;
104 EventDispatcher dispatcher_;
Thieu Le3426c8f2012-01-11 17:35:11 -0800105 MockMetrics metrics_;
Chris Masone626719f2011-08-18 16:58:48 -0700106 MockManager manager_;
Jason Glasgowe9089492012-02-23 17:57:37 -0500107 MockDeviceInfo info_;
Darin Petkov3b292332011-07-28 14:17:24 -0700108 scoped_ptr<MockDBusPropertiesProxy> proxy_;
Darin Petkove0a312e2011-07-20 13:45:28 -0700109 TestProxyFactory proxy_factory_;
David Rochbergfa1d31d2012-03-20 10:38:07 -0400110 scoped_ptr<StrictModem> modem_;
111 MockRTNLHandler rtnl_handler_;
112 ByteString expected_address_;
Darin Petkove0a312e2011-07-20 13:45:28 -0700113};
114
Darin Petkove0a312e2011-07-20 13:45:28 -0700115void ModemTest::SetUp() {
Jason Glasgowe9089492012-02-23 17:57:37 -0500116 EXPECT_EQ(kOwner, modem_->owner_);
Jason Glasgowa585fc32012-06-06 11:04:09 -0400117 EXPECT_EQ(kService, modem_->service_);
Jason Glasgowe9089492012-02-23 17:57:37 -0500118 EXPECT_EQ(kPath, modem_->path_);
David Rochbergfa1d31d2012-03-20 10:38:07 -0400119 ReplaceSingletons();
120 expected_address_ = ByteString(kAddress, arraysize(kAddress));
121
122 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(kLinkName)).
123 WillRepeatedly(Return(kTestInterfaceIndex));
124
David Rochbergfa1d31d2012-03-20 10:38:07 -0400125 EXPECT_CALL(manager_, device_info()).WillRepeatedly(Return(&info_));
Darin Petkove0a312e2011-07-20 13:45:28 -0700126}
127
128void ModemTest::TearDown() {
Jason Glasgowe9089492012-02-23 17:57:37 -0500129 modem_.reset();
Darin Petkove0a312e2011-07-20 13:45:28 -0700130}
131
David Rochbergfa1d31d2012-03-20 10:38:07 -0400132TEST_F(ModemTest, PendingDevicePropertiesAndCreate) {
133 static const char kSentinel[] = "sentinel";
134 static const uint32 kSentinelValue = 17;
Darin Petkove0a312e2011-07-20 13:45:28 -0700135
Ben Chan876efd32012-09-28 15:25:13 -0700136 DBusInterfaceToProperties properties;
137 properties[MM_MODEM_INTERFACE][kSentinel].writer().append_uint32(
138 kSentinelValue);
David Rochbergfa1d31d2012-03-20 10:38:07 -0400139
140 EXPECT_CALL(*modem_, GetLinkName(_, _)).WillRepeatedly(DoAll(
141 SetArgumentPointee<1>(string(kLinkName)),
142 Return(true)));
143 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(StrEq(kLinkName))).
144 WillRepeatedly(Return(kTestInterfaceIndex));
145
146 // The first time we call CreateDeviceFromModemProperties,
147 // GetMACAddress will fail.
148 EXPECT_CALL(info_, GetMACAddress(kTestInterfaceIndex, _)).
149 WillOnce(Return(false));
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400150 EXPECT_CALL(*modem_, GetModemInterface()).
151 WillRepeatedly(Return(MM_MODEM_INTERFACE));
David Rochbergfa1d31d2012-03-20 10:38:07 -0400152 modem_->CreateDeviceFromModemProperties(properties);
Jason Glasgowe9089492012-02-23 17:57:37 -0500153 EXPECT_FALSE(modem_->device_.get());
Darin Petkove0a312e2011-07-20 13:45:28 -0700154
David Rochbergfa1d31d2012-03-20 10:38:07 -0400155 // On the second time, we allow GetMACAddress to succeed. Now we
156 // expect a device to be built
157 EXPECT_CALL(info_, GetMACAddress(kTestInterfaceIndex, _)).
158 WillOnce(DoAll(SetArgumentPointee<1>(expected_address_),
159 Return(true)));
160
161 // modem will take ownership
Darin Petkova0a0efe2012-06-27 12:50:01 +0200162 MockCellular *cellular = new MockCellular(
David Rochbergfa1d31d2012-03-20 10:38:07 -0400163 &control_interface_,
164 &dispatcher_,
165 &metrics_,
166 &manager_,
167 kLinkName,
168 kAddressAsString,
169 kTestInterfaceIndex,
Ben Chan3ecdf822012-08-06 12:29:23 -0700170 Cellular::kTypeCDMA,
David Rochbergfa1d31d2012-03-20 10:38:07 -0400171 kOwner,
Jason Glasgowa585fc32012-06-06 11:04:09 -0400172 kService,
David Rochbergfa1d31d2012-03-20 10:38:07 -0400173 kPath,
Ben Chan62028b22012-11-05 11:20:02 -0800174 static_cast<CellularOperatorInfo *>(NULL),
Ben Chan3ecdf822012-08-06 12:29:23 -0700175 static_cast<mobile_provider_db *>(NULL),
176 ProxyFactory::GetInstance());
David Rochbergfa1d31d2012-03-20 10:38:07 -0400177
178 EXPECT_CALL(*modem_,
179 ConstructCellular(StrEq(kLinkName),
180 StrEq(kAddressAsString),
181 kTestInterfaceIndex)).
182 WillOnce(Return(cellular));
183
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400184 EXPECT_CALL(*cellular, OnDBusPropertiesChanged(
185 _,
186 HasDBusPropertyWithValueU32(kSentinel, kSentinelValue),
187 _));
David Rochbergfa1d31d2012-03-20 10:38:07 -0400188 EXPECT_CALL(info_, RegisterDevice(_));
David Rochbergfa1d31d2012-03-20 10:38:07 -0400189 modem_->OnDeviceInfoAvailable(kLinkName);
190
191 EXPECT_TRUE(modem_->device_.get());
Darin Petkova0a0efe2012-06-27 12:50:01 +0200192
193 // Add expectations for the evental |modem_| destruction.
194 EXPECT_CALL(*cellular, DestroyService());
195 EXPECT_CALL(info_, DeregisterDevice(_));
David Rochbergfa1d31d2012-03-20 10:38:07 -0400196}
197
198TEST_F(ModemTest, EarlyDeviceProperties) {
199 // OnDeviceInfoAvailable called before
200 // CreateDeviceFromModemProperties: Do nothing
201 modem_->OnDeviceInfoAvailable(kLinkName);
202 EXPECT_FALSE(modem_->device_.get());
203}
204
205TEST_F(ModemTest, CreateDeviceEarlyFailures) {
Ben Chan876efd32012-09-28 15:25:13 -0700206 DBusInterfaceToProperties properties;
David Rochbergfa1d31d2012-03-20 10:38:07 -0400207
208 EXPECT_CALL(*modem_, ConstructCellular(_, _, _)).Times(0);
Ben Chan876efd32012-09-28 15:25:13 -0700209 EXPECT_CALL(*modem_, GetModemInterface()).
210 WillRepeatedly(Return(MM_MODEM_INTERFACE));
211
212 // No modem interface properties: no device created
213 modem_->CreateDeviceFromModemProperties(properties);
214 EXPECT_FALSE(modem_->device_.get());
215
216 properties[MM_MODEM_INTERFACE] = DBusPropertiesMap();
David Rochbergfa1d31d2012-03-20 10:38:07 -0400217
218 // No link name: no device created
219 EXPECT_CALL(*modem_, GetLinkName(_, _)).WillOnce(Return(false));
220 modem_->CreateDeviceFromModemProperties(properties);
Jason Glasgowe9089492012-02-23 17:57:37 -0500221 EXPECT_FALSE(modem_->device_.get());
Darin Petkove0a312e2011-07-20 13:45:28 -0700222
David Rochbergfa1d31d2012-03-20 10:38:07 -0400223 // Link name, but no ifindex: no device created
224 EXPECT_CALL(*modem_, GetLinkName(_, _)).WillOnce(DoAll(
225 SetArgumentPointee<1>(string(kLinkName)),
226 Return(true)));
227 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(StrEq(kLinkName))).WillOnce(
228 Return(-1));
229 modem_->CreateDeviceFromModemProperties(properties);
Jason Glasgowe9089492012-02-23 17:57:37 -0500230 EXPECT_FALSE(modem_->device_.get());
David Rochbergfa1d31d2012-03-20 10:38:07 -0400231}
Darin Petkove0a312e2011-07-20 13:45:28 -0700232
David Rochbergfa1d31d2012-03-20 10:38:07 -0400233TEST_F(ModemTest, RejectPPPModem) {
234 // TODO(rochberg): Port this to ModemClassic
Darin Petkove0a312e2011-07-20 13:45:28 -0700235}
236
237} // namespace shill