blob: 474c080fd60adfff3a6d724356491c903203fe72 [file] [log] [blame]
Eric Shienbrood5de44ab2011-12-05 10:46:27 -05001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "shill/cellular_capability_gsm.h"
6
Eric Shienbrood9a245532012-03-07 14:20:39 -05007#include <base/bind.h>
Eric Shienbrood5de44ab2011-12-05 10:46:27 -05008#include <chromeos/dbus/service_constants.h>
9#include <gtest/gtest.h>
10#include <mm/mm-modem.h>
11#include <mobile_provider.h>
12
13#include "shill/cellular.h"
14#include "shill/cellular_service.h"
15#include "shill/error.h"
16#include "shill/event_dispatcher.h"
17#include "shill/mock_adaptors.h"
Eric Shienbrood9a245532012-03-07 14:20:39 -050018#include "shill/mock_glib.h"
19#include "shill/mock_manager.h"
20#include "shill/mock_metrics.h"
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050021#include "shill/mock_modem_cdma_proxy.h"
22#include "shill/mock_modem_gsm_card_proxy.h"
23#include "shill/mock_modem_gsm_network_proxy.h"
24#include "shill/mock_modem_proxy.h"
25#include "shill/mock_modem_simple_proxy.h"
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -040026#include "shill/mock_profile.h"
Eric Shienbrood9a245532012-03-07 14:20:39 -050027#include "shill/mock_rtnl_handler.h"
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050028#include "shill/nice_mock_control.h"
29#include "shill/proxy_factory.h"
30
Eric Shienbrood9a245532012-03-07 14:20:39 -050031using base::Bind;
32using base::Unretained;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050033using std::string;
Darin Petkov9c1dcef2012-02-07 15:58:26 +010034using testing::InSequence;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050035using testing::NiceMock;
Eric Shienbrood9a245532012-03-07 14:20:39 -050036using testing::_;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050037
38namespace shill {
39
Eric Shienbrood9a245532012-03-07 14:20:39 -050040MATCHER(IsSuccess, "") {
41 return arg.IsSuccess();
42}
43MATCHER(IsFailure, "") {
44 return arg.IsFailure();
45}
46
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050047class CellularCapabilityTest : public testing::Test {
48 public:
49 CellularCapabilityTest()
Eric Shienbrood9a245532012-03-07 14:20:39 -050050 : manager_(&control_, &dispatcher_, &metrics_, &glib_),
51 cellular_(new Cellular(&control_,
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050052 &dispatcher_,
53 NULL,
Eric Shienbrood9a245532012-03-07 14:20:39 -050054 &manager_,
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050055 "",
56 "",
57 0,
58 Cellular::kTypeGSM,
59 "",
60 "",
61 NULL)),
62 proxy_(new MockModemProxy()),
63 simple_proxy_(new MockModemSimpleProxy()),
64 cdma_proxy_(new MockModemCDMAProxy()),
65 gsm_card_proxy_(new MockModemGSMCardProxy()),
66 gsm_network_proxy_(new MockModemGSMNetworkProxy()),
67 proxy_factory_(this),
68 capability_(NULL),
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -040069 device_adaptor_(NULL),
70 provider_db_(NULL) {}
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050071
72 virtual ~CellularCapabilityTest() {
73 cellular_->service_ = NULL;
74 capability_ = NULL;
75 device_adaptor_ = NULL;
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -040076 mobile_provider_close_db(provider_db_);
77 provider_db_ = NULL;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050078 }
79
80 virtual void SetUp() {
Eric Shienbrood9a245532012-03-07 14:20:39 -050081 static_cast<Device *>(cellular_)->rtnl_handler_ = &rtnl_handler_;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050082 capability_ = cellular_->capability_.get();
83 device_adaptor_ =
84 dynamic_cast<NiceMock<DeviceMockAdaptor> *>(cellular_->adaptor());
85 }
86
87 virtual void TearDown() {
88 capability_->proxy_factory_ = NULL;
89 }
90
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -040091 void InitProviderDB() {
92 provider_db_ = mobile_provider_open_db(kTestMobileProviderDBPath);
93 ASSERT_TRUE(provider_db_);
94 cellular_->provider_db_ = provider_db_;
95 }
96
97 void SetService() {
98 cellular_->service_ = new CellularService(
99 &control_, &dispatcher_, &metrics_, NULL, cellular_);
100 }
101
102 CellularCapabilityGSM *GetGsmCapability() {
103 return dynamic_cast<CellularCapabilityGSM *>(cellular_->capability_.get());
104 }
105
Eric Shienbrood9a245532012-03-07 14:20:39 -0500106 void InvokeEnable(bool enable, Error *error,
107 const ResultCallback &callback, int timeout) {
108 callback.Run(Error());
109 }
110 void InvokeEnableFail(bool enable, Error *error,
111 const ResultCallback &callback, int timeout) {
112 callback.Run(Error(Error::kOperationFailed));
113 }
114 void InvokeDisconnect(Error *error, const ResultCallback &callback,
115 int timeout) {
116 callback.Run(Error());
117 }
Thieu Le923006b2012-04-05 16:32:58 -0700118 void InvokeDisconnectFail(Error *error, const ResultCallback &callback,
119 int timeout) {
120 callback.Run(Error(Error::kOperationFailed));
121 }
Eric Shienbrood9a245532012-03-07 14:20:39 -0500122 void InvokeGetModemStatus(Error *error,
123 const DBusPropertyMapCallback &callback,
124 int timeout) {
125 DBusPropertiesMap props;
126 props["carrier"].writer().append_string(kTestCarrier);
127 props["unknown-property"].writer().append_string("irrelevant-value");
128 callback.Run(props, Error());
129 }
130 void InvokeGetModemInfo(Error *error, const ModemInfoCallback &callback,
131 int timeout) {
132 ModemHardwareInfo info;
133 info._1 = kManufacturer;
134 info._2 = kModelID;
135 info._3 = kHWRev;
136 callback.Run(info, Error());
137 }
138
139 MOCK_METHOD1(TestCallback, void(const Error &error));
140
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500141 protected:
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400142 static const char kTestMobileProviderDBPath[];
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500143 static const char kTestCarrier[];
Eric Shienbrood9a245532012-03-07 14:20:39 -0500144 static const char kManufacturer[];
145 static const char kModelID[];
146 static const char kHWRev[];
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500147
148 class TestProxyFactory : public ProxyFactory {
149 public:
150 explicit TestProxyFactory(CellularCapabilityTest *test) : test_(test) {}
151
152 virtual ModemProxyInterface *CreateModemProxy(
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500153 const string &/*path*/,
154 const string &/*service*/) {
155 return test_->proxy_.release();
156 }
157
158 virtual ModemSimpleProxyInterface *CreateModemSimpleProxy(
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500159 const string &/*path*/,
160 const string &/*service*/) {
161 return test_->simple_proxy_.release();
162 }
163
164 virtual ModemCDMAProxyInterface *CreateModemCDMAProxy(
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500165 const string &/*path*/,
166 const string &/*service*/) {
167 return test_->cdma_proxy_.release();
168 }
169
170 virtual ModemGSMCardProxyInterface *CreateModemGSMCardProxy(
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500171 const string &/*path*/,
172 const string &/*service*/) {
173 return test_->gsm_card_proxy_.release();
174 }
175
176 virtual ModemGSMNetworkProxyInterface *CreateModemGSMNetworkProxy(
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500177 const string &/*path*/,
178 const string &/*service*/) {
179 return test_->gsm_network_proxy_.release();
180 }
181
182 private:
183 CellularCapabilityTest *test_;
184 };
185
186 void SetProxy() {
187 capability_->proxy_.reset(proxy_.release());
188 }
189
190 void SetSimpleProxy() {
191 capability_->simple_proxy_.reset(simple_proxy_.release());
192 }
193
Eric Shienbrood9a245532012-03-07 14:20:39 -0500194 void SetGSMNetworkProxy() {
195 CellularCapabilityGSM *gsm_capability =
196 dynamic_cast<CellularCapabilityGSM *>(cellular_->capability_.get());
197 gsm_capability->network_proxy_.reset(gsm_network_proxy_.release());
198 }
199
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500200 void SetCellularType(Cellular::Type type) {
201 cellular_->InitCapability(type, &proxy_factory_);
202 capability_ = cellular_->capability_.get();
203 }
204
205 NiceMockControl control_;
206 EventDispatcher dispatcher_;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500207 MockMetrics metrics_;
208 MockGLib glib_;
209 MockManager manager_;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500210 CellularRefPtr cellular_;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500211 MockRTNLHandler rtnl_handler_;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500212 scoped_ptr<MockModemProxy> proxy_;
213 scoped_ptr<MockModemSimpleProxy> simple_proxy_;
214 scoped_ptr<MockModemCDMAProxy> cdma_proxy_;
215 scoped_ptr<MockModemGSMCardProxy> gsm_card_proxy_;
216 scoped_ptr<MockModemGSMNetworkProxy> gsm_network_proxy_;
217 TestProxyFactory proxy_factory_;
218 CellularCapability *capability_; // Owned by |cellular_|.
219 NiceMock<DeviceMockAdaptor> *device_adaptor_; // Owned by |cellular_|.
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400220 mobile_provider_db *provider_db_;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500221};
222
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400223const char CellularCapabilityTest::kTestMobileProviderDBPath[] =
224 "provider_db_unittest.bfd";
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500225const char CellularCapabilityTest::kTestCarrier[] = "The Cellular Carrier";
Eric Shienbrood9a245532012-03-07 14:20:39 -0500226const char CellularCapabilityTest::kManufacturer[] = "Company";
227const char CellularCapabilityTest::kModelID[] = "Gobi 2000";
228const char CellularCapabilityTest::kHWRev[] = "A00B1234";
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500229
230TEST_F(CellularCapabilityTest, GetModemStatus) {
231 SetCellularType(Cellular::kTypeCDMA);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500232 EXPECT_CALL(*simple_proxy_,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500233 GetModemStatus(_, _, CellularCapability::kTimeoutDefault)).
234 WillOnce(Invoke(this, &CellularCapabilityTest::InvokeGetModemStatus));
235 EXPECT_CALL(*this, TestCallback(IsSuccess()));
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500236 SetSimpleProxy();
Eric Shienbrood9a245532012-03-07 14:20:39 -0500237 ResultCallback callback =
238 Bind(&CellularCapabilityTest::TestCallback, Unretained(this));
239 capability_->GetModemStatus(callback);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500240 EXPECT_EQ(kTestCarrier, capability_->carrier_);
241 EXPECT_EQ(kTestCarrier, cellular_->home_provider_.GetName());
242}
243
244TEST_F(CellularCapabilityTest, GetModemInfo) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500245 EXPECT_CALL(*proxy_, GetModemInfo(_, _, CellularCapability::kTimeoutDefault))
246 .WillOnce(Invoke(this, &CellularCapabilityTest::InvokeGetModemInfo));
247 EXPECT_CALL(*this, TestCallback(IsSuccess()));
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500248 SetProxy();
Eric Shienbrood9a245532012-03-07 14:20:39 -0500249 ResultCallback callback =
250 Bind(&CellularCapabilityTest::TestCallback, Unretained(this));
251 capability_->GetModemInfo(callback);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500252 EXPECT_EQ(kManufacturer, capability_->manufacturer_);
253 EXPECT_EQ(kModelID, capability_->model_id_);
254 EXPECT_EQ(kHWRev, capability_->hardware_revision_);
255}
256
257TEST_F(CellularCapabilityTest, EnableModemSucceed) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500258 EXPECT_CALL(*proxy_, Enable(true, _, _, CellularCapability::kTimeoutEnable))
259 .WillOnce(Invoke(this, &CellularCapabilityTest::InvokeEnable));
260 EXPECT_CALL(*this, TestCallback(IsSuccess()));
261 ResultCallback callback =
262 Bind(&CellularCapabilityTest::TestCallback, Unretained(this));
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500263 SetProxy();
Eric Shienbrood9a245532012-03-07 14:20:39 -0500264 capability_->EnableModem(callback);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500265}
266
267TEST_F(CellularCapabilityTest, EnableModemFail) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500268 EXPECT_CALL(*proxy_, Enable(true, _, _, CellularCapability::kTimeoutEnable))
269 .WillOnce(Invoke(this, &CellularCapabilityTest::InvokeEnableFail));
270 EXPECT_CALL(*this, TestCallback(IsFailure()));
271 ResultCallback callback =
272 Bind(&CellularCapabilityTest::TestCallback, Unretained(this));
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500273 SetProxy();
Eric Shienbrood9a245532012-03-07 14:20:39 -0500274 capability_->EnableModem(callback);
275}
276
277TEST_F(CellularCapabilityTest, FinishEnable) {
278 EXPECT_CALL(*gsm_network_proxy_,
279 GetRegistrationInfo(NULL, _,
280 CellularCapability::kTimeoutDefault));
281 EXPECT_CALL(*gsm_network_proxy_,
282 GetSignalQuality(NULL, _, CellularCapability::kTimeoutDefault));
283 EXPECT_CALL(*this, TestCallback(IsSuccess()));
284 SetGSMNetworkProxy();
285 capability_->FinishEnable(
286 Bind(&CellularCapabilityTest::TestCallback, Unretained(this)));
287}
288
289TEST_F(CellularCapabilityTest, UnsupportedOperation) {
290 Error error;
291 EXPECT_CALL(*this, TestCallback(IsSuccess())).Times(0);
292 capability_->CellularCapability::Scan(&error,
293 Bind(&CellularCapabilityTest::TestCallback, Unretained(this)));
294 EXPECT_TRUE(error.IsFailure());
295 EXPECT_EQ(Error::kNotSupported, error.type());
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500296}
297
Darin Petkov9c1dcef2012-02-07 15:58:26 +0100298TEST_F(CellularCapabilityTest, AllowRoaming) {
299 EXPECT_FALSE(capability_->GetAllowRoaming(NULL));
300 capability_->SetAllowRoaming(false, NULL);
301 EXPECT_FALSE(capability_->GetAllowRoaming(NULL));
302
303 {
304 InSequence seq;
305 EXPECT_CALL(*device_adaptor_, EmitBoolChanged(
306 flimflam::kCellularAllowRoamingProperty, true));
307 EXPECT_CALL(*device_adaptor_, EmitBoolChanged(
308 flimflam::kCellularAllowRoamingProperty, false));
309 }
310
311 cellular_->state_ = Cellular::kStateConnected;
312 dynamic_cast<CellularCapabilityGSM *>(capability_)->registration_state_ =
313 MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING;
314 capability_->SetAllowRoaming(true, NULL);
315 EXPECT_TRUE(capability_->GetAllowRoaming(NULL));
316 EXPECT_EQ(Cellular::kStateConnected, cellular_->state_);
317
Eric Shienbrood9a245532012-03-07 14:20:39 -0500318 EXPECT_CALL(*proxy_, Disconnect(_, _, CellularCapability::kTimeoutDefault))
319 .WillOnce(Invoke(this, &CellularCapabilityTest::InvokeDisconnect));
Darin Petkov9c1dcef2012-02-07 15:58:26 +0100320 SetProxy();
321 cellular_->state_ = Cellular::kStateConnected;
322 capability_->SetAllowRoaming(false, NULL);
323 EXPECT_FALSE(capability_->GetAllowRoaming(NULL));
324 EXPECT_EQ(Cellular::kStateRegistered, cellular_->state_);
325}
326
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400327MATCHER_P(HasApn, apn, "") {
328 DBusPropertiesMap::const_iterator it = arg.find(flimflam::kApnProperty);
329 return it != arg.end() && apn == it->second.reader().get_string();
330}
331
332MATCHER(HasNoApn, "") {
333 return arg.find(flimflam::kApnProperty) == arg.end();
334}
335
336TEST_F(CellularCapabilityTest, TryApns) {
337 static const string kLastGoodApn("remembered.apn");
338 static const string kSuppliedApn("my.apn");
339 static const string kTmobileApn1("epc.tmobile.com");
340 static const string kTmobileApn2("wap.voicestream.com");
341 static const string kTmobileApn3("internet2.voicestream.com");
342 static const string kTmobileApn4("internet3.voicestream.com");
343
344 using testing::InSequence;
345 {
346 InSequence dummy;
347 EXPECT_CALL(*simple_proxy_, Connect(HasApn(kLastGoodApn), _, _, _));
348 EXPECT_CALL(*simple_proxy_, Connect(HasApn(kSuppliedApn), _, _, _));
349 EXPECT_CALL(*simple_proxy_, Connect(HasApn(kTmobileApn1), _, _, _));
350 EXPECT_CALL(*simple_proxy_, Connect(HasApn(kTmobileApn2), _, _, _));
351 EXPECT_CALL(*simple_proxy_, Connect(HasApn(kTmobileApn3), _, _, _));
352 EXPECT_CALL(*simple_proxy_, Connect(HasApn(kTmobileApn4), _, _, _));
353 EXPECT_CALL(*simple_proxy_, Connect(HasNoApn(), _, _, _));
354 }
355 CellularCapabilityGSM *gsm_capability = GetGsmCapability();
356 SetService();
357 gsm_capability->imsi_ = "310240123456789";
358 InitProviderDB();
359 gsm_capability->SetHomeProvider();
360 ProfileRefPtr profile(new NiceMock<MockProfile>(
361 &control_, reinterpret_cast<Manager *>(NULL)));
362 cellular_->service()->set_profile(profile);
363
364 Error error;
365 Stringmap apn_info;
366 DBusPropertiesMap props;
367 apn_info[flimflam::kApnProperty] = kSuppliedApn;
368 cellular_->service()->SetApn(apn_info, &error);
369
370 apn_info.clear();
371 apn_info[flimflam::kApnProperty] = kLastGoodApn;
372 cellular_->service()->SetLastGoodApn(apn_info);
373
374 capability_->SetupConnectProperties(&props);
375 // We expect the list to contain the last good APN, plus
376 // the user-supplied APN, plus the 4 APNs from the mobile
377 // provider info database.
378 EXPECT_EQ(6, gsm_capability->apn_try_list_.size());
379 EXPECT_FALSE(props.find(flimflam::kApnProperty) == props.end());
380 EXPECT_EQ(kLastGoodApn, props[flimflam::kApnProperty].reader().get_string());
381
382 SetSimpleProxy();
383 capability_->Connect(props, &error, ResultCallback());
384 Error cerror(Error::kInvalidApn);
385 capability_->OnConnectReply(ResultCallback(), cerror);
386 EXPECT_EQ(5, gsm_capability->apn_try_list_.size());
387 capability_->OnConnectReply(ResultCallback(), cerror);
388 EXPECT_EQ(4, gsm_capability->apn_try_list_.size());
389 capability_->OnConnectReply(ResultCallback(), cerror);
390 EXPECT_EQ(3, gsm_capability->apn_try_list_.size());
391 capability_->OnConnectReply(ResultCallback(), cerror);
392 EXPECT_EQ(2, gsm_capability->apn_try_list_.size());
393 capability_->OnConnectReply(ResultCallback(), cerror);
394 EXPECT_EQ(1, gsm_capability->apn_try_list_.size());
395 capability_->OnConnectReply(ResultCallback(), cerror);
396 EXPECT_EQ(0, gsm_capability->apn_try_list_.size());
397}
398
Thieu Le923006b2012-04-05 16:32:58 -0700399TEST_F(CellularCapabilityTest, StopModemDisconnectSuccess) {
400 EXPECT_CALL(*proxy_, Disconnect(_, _, CellularCapability::kTimeoutDefault))
401 .WillOnce(Invoke(this,
402 &CellularCapabilityTest::InvokeDisconnect));
403 EXPECT_CALL(*proxy_, Enable(_, _, _, CellularCapability::kTimeoutDefault))
404 .WillOnce(Invoke(this,
405 &CellularCapabilityTest::InvokeEnable));
406 EXPECT_CALL(*this, TestCallback(IsSuccess()));
407 SetProxy();
408
409 Error error;
410 capability_->StopModem(
411 &error, Bind(&CellularCapabilityTest::TestCallback, Unretained(this)));
412 dispatcher_.DispatchPendingEvents();
413}
414
415TEST_F(CellularCapabilityTest, StopModemDisconnectFail) {
416 EXPECT_CALL(*proxy_, Disconnect(_, _, CellularCapability::kTimeoutDefault))
417 .WillOnce(Invoke(this,
418 &CellularCapabilityTest::InvokeDisconnectFail));
419 EXPECT_CALL(*proxy_, Enable(_, _, _, CellularCapability::kTimeoutDefault))
420 .WillOnce(Invoke(this,
421 &CellularCapabilityTest::InvokeEnable));
422 EXPECT_CALL(*this, TestCallback(IsSuccess()));
423 SetProxy();
424
425 Error error;
426 capability_->StopModem(
427 &error, Bind(&CellularCapabilityTest::TestCallback, Unretained(this)));
428 dispatcher_.DispatchPendingEvents();
429}
430
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500431} // namespace shill