blob: 99e7ca6d6e7bfb3310c1fb4e06d2abc956dbd065 [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_dbus_properties_proxy.h"
David Rochbergfa1d31d2012-03-20 10:38:07 -040022#include "shill/mock_device_info.h"
David Rochbergfa1d31d2012-03-20 10:38:07 -040023#include "shill/mock_modem.h"
Prathmesh Prabhu27526f12013-03-25 19:42:18 -070024#include "shill/mock_modem_info.h"
David Rochbergfa1d31d2012-03-20 10:38:07 -040025#include "shill/mock_rtnl_handler.h"
Darin Petkove0a312e2011-07-20 13:45:28 -070026#include "shill/proxy_factory.h"
27#include "shill/rtnl_handler.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::_;
32using testing::DoAll;
33using testing::Return;
Chris Masone626719f2011-08-18 16:58:48 -070034using testing::SetArgumentPointee;
David Rochbergfa1d31d2012-03-20 10:38:07 -040035using testing::StrEq;
Darin Petkove0a312e2011-07-20 13:45:28 -070036using testing::StrictMock;
37using testing::Test;
38
39namespace shill {
40
41namespace {
42
43const int kTestInterfaceIndex = 5;
David Rochbergfa1d31d2012-03-20 10:38:07 -040044const char kLinkName[] = "usb0";
45const char kOwner[] = ":1.18";
Jason Glasgowa585fc32012-06-06 11:04:09 -040046const char kService[] = "org.chromium.ModemManager";
David Rochbergfa1d31d2012-03-20 10:38:07 -040047const char kPath[] = "/org/chromium/ModemManager/Gobi/0";
48const unsigned char kAddress[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
49const char kAddressAsString[] = "000102030405";
Darin Petkove0a312e2011-07-20 13:45:28 -070050
Darin Petkove0a312e2011-07-20 13:45:28 -070051} // namespace
52
53class ModemTest : public Test {
54 public:
55 ModemTest()
Prathmesh Prabhu27526f12013-03-25 19:42:18 -070056 : modem_info_(NULL, &dispatcher_, NULL, NULL, NULL),
57 device_info_(modem_info_.control_interface(), modem_info_.dispatcher(),
58 modem_info_.metrics(), modem_info_.manager()),
Darin Petkov3b292332011-07-28 14:17:24 -070059 proxy_(new MockDBusPropertiesProxy()),
60 proxy_factory_(this),
David Rochbergfa1d31d2012-03-20 10:38:07 -040061 modem_(
62 new StrictModem(
63 kOwner,
Jason Glasgowa585fc32012-06-06 11:04:09 -040064 kService,
David Rochbergfa1d31d2012-03-20 10:38:07 -040065 kPath,
Prathmesh Prabhu27526f12013-03-25 19:42:18 -070066 &modem_info_)) {}
Darin Petkove0a312e2011-07-20 13:45:28 -070067 virtual void SetUp();
68 virtual void TearDown();
69
David Rochbergfa1d31d2012-03-20 10:38:07 -040070 void ReplaceSingletons() {
71 modem_->rtnl_handler_ = &rtnl_handler_;
Darin Petkove0a312e2011-07-20 13:45:28 -070072 }
73
74 protected:
75 class TestProxyFactory : public ProxyFactory {
76 public:
Paul Stewart7355ce12011-09-02 10:47:01 -070077 explicit TestProxyFactory(ModemTest *test) : test_(test) {}
Darin Petkove0a312e2011-07-20 13:45:28 -070078
79 virtual DBusPropertiesProxyInterface *CreateDBusPropertiesProxy(
mukesh agrawal1830fa12011-09-26 14:31:40 -070080 const string &/*path*/,
81 const string &/*service*/) {
Darin Petkov3b292332011-07-28 14:17:24 -070082 return test_->proxy_.release();
Darin Petkove0a312e2011-07-20 13:45:28 -070083 }
84
85 private:
Darin Petkov3b292332011-07-28 14:17:24 -070086 ModemTest *test_;
Darin Petkove0a312e2011-07-20 13:45:28 -070087 };
88
Darin Petkove0a312e2011-07-20 13:45:28 -070089 EventDispatcher dispatcher_;
Prathmesh Prabhu27526f12013-03-25 19:42:18 -070090 MockModemInfo modem_info_;
91 MockDeviceInfo device_info_;
Darin Petkov3b292332011-07-28 14:17:24 -070092 scoped_ptr<MockDBusPropertiesProxy> proxy_;
Darin Petkove0a312e2011-07-20 13:45:28 -070093 TestProxyFactory proxy_factory_;
David Rochbergfa1d31d2012-03-20 10:38:07 -040094 scoped_ptr<StrictModem> modem_;
95 MockRTNLHandler rtnl_handler_;
96 ByteString expected_address_;
Darin Petkove0a312e2011-07-20 13:45:28 -070097};
98
Darin Petkove0a312e2011-07-20 13:45:28 -070099void ModemTest::SetUp() {
Jason Glasgowe9089492012-02-23 17:57:37 -0500100 EXPECT_EQ(kOwner, modem_->owner_);
Jason Glasgowa585fc32012-06-06 11:04:09 -0400101 EXPECT_EQ(kService, modem_->service_);
Jason Glasgowe9089492012-02-23 17:57:37 -0500102 EXPECT_EQ(kPath, modem_->path_);
David Rochbergfa1d31d2012-03-20 10:38:07 -0400103 ReplaceSingletons();
104 expected_address_ = ByteString(kAddress, arraysize(kAddress));
105
106 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(kLinkName)).
107 WillRepeatedly(Return(kTestInterfaceIndex));
108
Prathmesh Prabhu27526f12013-03-25 19:42:18 -0700109 EXPECT_CALL(*modem_info_.mock_manager(), device_info())
110 .WillRepeatedly(Return(&device_info_));
Darin Petkove0a312e2011-07-20 13:45:28 -0700111}
112
113void ModemTest::TearDown() {
Jason Glasgowe9089492012-02-23 17:57:37 -0500114 modem_.reset();
Darin Petkove0a312e2011-07-20 13:45:28 -0700115}
116
David Rochbergfa1d31d2012-03-20 10:38:07 -0400117TEST_F(ModemTest, PendingDevicePropertiesAndCreate) {
118 static const char kSentinel[] = "sentinel";
119 static const uint32 kSentinelValue = 17;
Darin Petkove0a312e2011-07-20 13:45:28 -0700120
Ben Chan876efd32012-09-28 15:25:13 -0700121 DBusInterfaceToProperties properties;
122 properties[MM_MODEM_INTERFACE][kSentinel].writer().append_uint32(
123 kSentinelValue);
David Rochbergfa1d31d2012-03-20 10:38:07 -0400124
125 EXPECT_CALL(*modem_, GetLinkName(_, _)).WillRepeatedly(DoAll(
126 SetArgumentPointee<1>(string(kLinkName)),
127 Return(true)));
128 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(StrEq(kLinkName))).
129 WillRepeatedly(Return(kTestInterfaceIndex));
130
131 // The first time we call CreateDeviceFromModemProperties,
132 // GetMACAddress will fail.
Prathmesh Prabhu27526f12013-03-25 19:42:18 -0700133 EXPECT_CALL(device_info_, GetMACAddress(kTestInterfaceIndex, _)).
David Rochbergfa1d31d2012-03-20 10:38:07 -0400134 WillOnce(Return(false));
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400135 EXPECT_CALL(*modem_, GetModemInterface()).
136 WillRepeatedly(Return(MM_MODEM_INTERFACE));
David Rochbergfa1d31d2012-03-20 10:38:07 -0400137 modem_->CreateDeviceFromModemProperties(properties);
Jason Glasgowe9089492012-02-23 17:57:37 -0500138 EXPECT_FALSE(modem_->device_.get());
Darin Petkove0a312e2011-07-20 13:45:28 -0700139
David Rochbergfa1d31d2012-03-20 10:38:07 -0400140 // On the second time, we allow GetMACAddress to succeed. Now we
141 // expect a device to be built
Prathmesh Prabhu27526f12013-03-25 19:42:18 -0700142 EXPECT_CALL(device_info_, GetMACAddress(kTestInterfaceIndex, _)).
David Rochbergfa1d31d2012-03-20 10:38:07 -0400143 WillOnce(DoAll(SetArgumentPointee<1>(expected_address_),
144 Return(true)));
145
146 // modem will take ownership
Darin Petkova0a0efe2012-06-27 12:50:01 +0200147 MockCellular *cellular = new MockCellular(
Prathmesh Prabhu27526f12013-03-25 19:42:18 -0700148 &modem_info_,
David Rochbergfa1d31d2012-03-20 10:38:07 -0400149 kLinkName,
150 kAddressAsString,
151 kTestInterfaceIndex,
Ben Chan3ecdf822012-08-06 12:29:23 -0700152 Cellular::kTypeCDMA,
David Rochbergfa1d31d2012-03-20 10:38:07 -0400153 kOwner,
Jason Glasgowa585fc32012-06-06 11:04:09 -0400154 kService,
David Rochbergfa1d31d2012-03-20 10:38:07 -0400155 kPath,
Ben Chan3ecdf822012-08-06 12:29:23 -0700156 ProxyFactory::GetInstance());
David Rochbergfa1d31d2012-03-20 10:38:07 -0400157
158 EXPECT_CALL(*modem_,
159 ConstructCellular(StrEq(kLinkName),
160 StrEq(kAddressAsString),
161 kTestInterfaceIndex)).
162 WillOnce(Return(cellular));
163
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400164 EXPECT_CALL(*cellular, OnDBusPropertiesChanged(
165 _,
166 HasDBusPropertyWithValueU32(kSentinel, kSentinelValue),
167 _));
Prathmesh Prabhu27526f12013-03-25 19:42:18 -0700168 EXPECT_CALL(device_info_, RegisterDevice(_));
David Rochbergfa1d31d2012-03-20 10:38:07 -0400169 modem_->OnDeviceInfoAvailable(kLinkName);
170
171 EXPECT_TRUE(modem_->device_.get());
Darin Petkova0a0efe2012-06-27 12:50:01 +0200172
173 // Add expectations for the evental |modem_| destruction.
174 EXPECT_CALL(*cellular, DestroyService());
Prathmesh Prabhu27526f12013-03-25 19:42:18 -0700175 EXPECT_CALL(device_info_, DeregisterDevice(_));
David Rochbergfa1d31d2012-03-20 10:38:07 -0400176}
177
178TEST_F(ModemTest, EarlyDeviceProperties) {
179 // OnDeviceInfoAvailable called before
180 // CreateDeviceFromModemProperties: Do nothing
181 modem_->OnDeviceInfoAvailable(kLinkName);
182 EXPECT_FALSE(modem_->device_.get());
183}
184
185TEST_F(ModemTest, CreateDeviceEarlyFailures) {
Ben Chan876efd32012-09-28 15:25:13 -0700186 DBusInterfaceToProperties properties;
David Rochbergfa1d31d2012-03-20 10:38:07 -0400187
188 EXPECT_CALL(*modem_, ConstructCellular(_, _, _)).Times(0);
Ben Chan876efd32012-09-28 15:25:13 -0700189 EXPECT_CALL(*modem_, GetModemInterface()).
190 WillRepeatedly(Return(MM_MODEM_INTERFACE));
191
192 // No modem interface properties: no device created
193 modem_->CreateDeviceFromModemProperties(properties);
194 EXPECT_FALSE(modem_->device_.get());
195
196 properties[MM_MODEM_INTERFACE] = DBusPropertiesMap();
David Rochbergfa1d31d2012-03-20 10:38:07 -0400197
198 // No link name: no device created
199 EXPECT_CALL(*modem_, GetLinkName(_, _)).WillOnce(Return(false));
200 modem_->CreateDeviceFromModemProperties(properties);
Jason Glasgowe9089492012-02-23 17:57:37 -0500201 EXPECT_FALSE(modem_->device_.get());
Darin Petkove0a312e2011-07-20 13:45:28 -0700202
David Rochbergfa1d31d2012-03-20 10:38:07 -0400203 // Link name, but no ifindex: no device created
204 EXPECT_CALL(*modem_, GetLinkName(_, _)).WillOnce(DoAll(
205 SetArgumentPointee<1>(string(kLinkName)),
206 Return(true)));
207 EXPECT_CALL(rtnl_handler_, GetInterfaceIndex(StrEq(kLinkName))).WillOnce(
208 Return(-1));
209 modem_->CreateDeviceFromModemProperties(properties);
Jason Glasgowe9089492012-02-23 17:57:37 -0500210 EXPECT_FALSE(modem_->device_.get());
David Rochbergfa1d31d2012-03-20 10:38:07 -0400211}
Darin Petkove0a312e2011-07-20 13:45:28 -0700212
David Rochbergfa1d31d2012-03-20 10:38:07 -0400213TEST_F(ModemTest, RejectPPPModem) {
214 // TODO(rochberg): Port this to ModemClassic
Darin Petkove0a312e2011-07-20 13:45:28 -0700215}
216
217} // namespace shill