1 //
2 // Copyright (C) 2012 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include "shill/cellular/cellular_capability_gsm.h"
18 
19 #include <base/bind.h>
20 #if defined(__ANDROID__)
21 #include <dbus/service_constants.h>
22 #else
23 #include <chromeos/dbus/service_constants.h>
24 #endif  // __ANDROID__
25 #include <mm/mm-modem.h>
26 
27 #include "shill/cellular/cellular.h"
28 #include "shill/cellular/cellular_service.h"
29 #include "shill/cellular/mock_modem_cdma_proxy.h"
30 #include "shill/cellular/mock_modem_gobi_proxy.h"
31 #include "shill/cellular/mock_modem_gsm_card_proxy.h"
32 #include "shill/cellular/mock_modem_gsm_network_proxy.h"
33 #include "shill/cellular/mock_modem_info.h"
34 #include "shill/cellular/mock_modem_proxy.h"
35 #include "shill/cellular/mock_modem_simple_proxy.h"
36 #include "shill/error.h"
37 #include "shill/mock_adaptors.h"
38 #include "shill/mock_control.h"
39 #include "shill/mock_profile.h"
40 #include "shill/net/mock_rtnl_handler.h"
41 #include "shill/test_event_dispatcher.h"
42 #include "shill/testing.h"
43 
44 using base::Bind;
45 using base::Unretained;
46 using std::string;
47 using testing::InSequence;
48 using testing::NiceMock;
49 using testing::_;
50 
51 namespace shill {
52 
53 class CellularCapabilityTest : public testing::Test {
54  public:
CellularCapabilityTest()55   CellularCapabilityTest()
56       : control_interface_(this),
57         modem_info_(&control_interface_, &dispatcher_, nullptr, nullptr),
58         create_gsm_card_proxy_from_factory_(false),
59         proxy_(new MockModemProxy()),
60         simple_proxy_(new MockModemSimpleProxy()),
61         cdma_proxy_(new MockModemCDMAProxy()),
62         gsm_card_proxy_(new MockModemGSMCardProxy()),
63         gsm_network_proxy_(new MockModemGSMNetworkProxy()),
64         gobi_proxy_(new MockModemGobiProxy()),
65         capability_(nullptr),
66         device_adaptor_(nullptr),
67         cellular_(new Cellular(&modem_info_,
68                                "",
69                                "",
70                                0,
71                                Cellular::kTypeGSM,
72                                "",
73                                "")) {
74     modem_info_.metrics()->RegisterDevice(cellular_->interface_index(),
75                             Technology::kCellular);
76   }
77 
~CellularCapabilityTest()78   virtual ~CellularCapabilityTest() {
79     cellular_->service_ = nullptr;
80     capability_ = nullptr;
81     device_adaptor_ = nullptr;
82   }
83 
SetUp()84   virtual void SetUp() {
85     static_cast<Device*>(cellular_.get())->rtnl_handler_ = &rtnl_handler_;
86 
87     capability_ = static_cast<CellularCapabilityClassic*>(
88         cellular_->capability_.get());
89     device_adaptor_ =
90         static_cast<DeviceMockAdaptor*>(cellular_->adaptor());
91     ASSERT_NE(nullptr, device_adaptor_);;
92   }
93 
TearDown()94   virtual void TearDown() {
95     capability_->control_interface_ = nullptr;
96   }
97 
CreateService()98   void CreateService() {
99     // The following constants are never directly accessed by the tests.
100     const char kStorageIdentifier[] = "default_test_storage_id";
101     const char kFriendlyServiceName[] = "default_test_service_name";
102     const char kOperatorCode[] = "10010";
103     const char kOperatorName[] = "default_test_operator_name";
104     const char kOperatorCountry[] = "us";
105 
106     // Simulate all the side-effects of Cellular::CreateService
107     auto service = new CellularService(&modem_info_, cellular_);
108     service->SetStorageIdentifier(kStorageIdentifier);
109     service->SetFriendlyName(kFriendlyServiceName);
110 
111     Stringmap serving_operator;
112     serving_operator[kOperatorCodeKey] = kOperatorCode;
113     serving_operator[kOperatorNameKey] = kOperatorName;
114     serving_operator[kOperatorCountryKey] = kOperatorCountry;
115 
116     service->set_serving_operator(serving_operator);
117     cellular_->set_home_provider(serving_operator);
118     cellular_->service_ = service;
119   }
120 
GetGsmCapability()121   CellularCapabilityGSM* GetGsmCapability() {
122     return static_cast<CellularCapabilityGSM*>(cellular_->capability_.get());
123   }
124 
ReleaseCapabilityProxies()125   void ReleaseCapabilityProxies() {
126     capability_->ReleaseProxies();
127   }
128 
InvokeEnable(bool enable,Error * error,const ResultCallback & callback,int timeout)129   void InvokeEnable(bool enable, Error* error,
130                     const ResultCallback& callback, int timeout) {
131     callback.Run(Error());
132   }
InvokeEnableFail(bool enable,Error * error,const ResultCallback & callback,int timeout)133   void InvokeEnableFail(bool enable, Error* error,
134                         const ResultCallback& callback, int timeout) {
135     callback.Run(Error(Error::kOperationFailed));
136   }
InvokeDisconnect(Error * error,const ResultCallback & callback,int timeout)137   void InvokeDisconnect(Error* error, const ResultCallback& callback,
138                         int timeout) {
139     callback.Run(Error());
140   }
InvokeDisconnectFail(Error * error,const ResultCallback & callback,int timeout)141   void InvokeDisconnectFail(Error* error, const ResultCallback& callback,
142                             int timeout) {
143     callback.Run(Error(Error::kOperationFailed));
144   }
InvokeGetModemStatus(Error * error,const KeyValueStoreCallback & callback,int timeout)145   void InvokeGetModemStatus(Error* error,
146                             const KeyValueStoreCallback& callback,
147                             int timeout) {
148     KeyValueStore props;
149     props.SetString("carrier", kTestCarrier);
150     props.SetString("unknown-property", "irrelevant-value");
151     callback.Run(props, Error());
152   }
InvokeGetModemInfo(Error * error,const ModemInfoCallback & callback,int timeout)153   void InvokeGetModemInfo(Error* error, const ModemInfoCallback& callback,
154                           int timeout) {
155     callback.Run(kManufacturer, kModelID, kHWRev, Error());
156   }
InvokeSetCarrier(const string & carrier,Error * error,const ResultCallback & callback,int timeout)157   void InvokeSetCarrier(const string& carrier, Error* error,
158                         const ResultCallback& callback, int timeout) {
159     callback.Run(Error());
160   }
161 
162   MOCK_METHOD1(TestCallback, void(const Error& error));
163 
164  protected:
165   static const char kTestMobileProviderDBPath[];
166   static const char kTestCarrier[];
167   static const char kManufacturer[];
168   static const char kModelID[];
169   static const char kHWRev[];
170 
171   class TestControl : public MockControl {
172    public:
TestControl(CellularCapabilityTest * test)173     explicit TestControl(CellularCapabilityTest* test) : test_(test) {}
174 
CreateModemProxy(const string &,const string &)175     virtual ModemProxyInterface* CreateModemProxy(
176         const string& /*path*/,
177         const string& /*service*/) {
178       return test_->proxy_.release();
179     }
180 
CreateModemSimpleProxy(const string &,const string &)181     virtual ModemSimpleProxyInterface* CreateModemSimpleProxy(
182         const string& /*path*/,
183         const string& /*service*/) {
184       return test_->simple_proxy_.release();
185     }
186 
CreateModemCDMAProxy(const string &,const string &)187     virtual ModemCDMAProxyInterface* CreateModemCDMAProxy(
188         const string& /*path*/,
189         const string& /*service*/) {
190       return test_->cdma_proxy_.release();
191     }
192 
CreateModemGSMCardProxy(const string &,const string &)193     virtual ModemGSMCardProxyInterface* CreateModemGSMCardProxy(
194         const string& /*path*/,
195         const string& /*service*/) {
196       // TODO(benchan): This code conditionally returns a nullptr to avoid
197       // CellularCapabilityGSM::InitProperties (and thus
198       // CellularCapabilityGSM::GetIMSI) from being called during the
199       // construction. Remove this workaround after refactoring the tests.
200       return test_->create_gsm_card_proxy_from_factory_ ?
201           test_->gsm_card_proxy_.release() : nullptr;
202     }
203 
CreateModemGSMNetworkProxy(const string &,const string &)204     virtual ModemGSMNetworkProxyInterface* CreateModemGSMNetworkProxy(
205         const string& /*path*/,
206         const string& /*service*/) {
207       return test_->gsm_network_proxy_.release();
208     }
209 
CreateModemGobiProxy(const string &,const string &)210     virtual ModemGobiProxyInterface* CreateModemGobiProxy(
211         const string& /*path*/,
212         const string& /*service*/) {
213       return test_->gobi_proxy_.release();
214     }
215 
216    private:
217     CellularCapabilityTest* test_;
218   };
219 
SetProxy()220   void SetProxy() {
221     capability_->proxy_.reset(proxy_.release());
222   }
223 
SetSimpleProxy()224   void SetSimpleProxy() {
225     capability_->simple_proxy_.reset(simple_proxy_.release());
226   }
227 
SetGSMNetworkProxy()228   void SetGSMNetworkProxy() {
229     CellularCapabilityGSM* gsm_capability =
230         static_cast<CellularCapabilityGSM*>(cellular_->capability_.get());
231     gsm_capability->network_proxy_.reset(gsm_network_proxy_.release());
232   }
233 
SetCellularType(Cellular::Type type)234   void SetCellularType(Cellular::Type type) {
235     cellular_->InitCapability(type);
236     capability_ = static_cast<CellularCapabilityClassic*>(
237         cellular_->capability_.get());
238   }
239 
AllowCreateGSMCardProxyFromFactory()240   void AllowCreateGSMCardProxyFromFactory() {
241     create_gsm_card_proxy_from_factory_ = true;
242   }
243 
244   EventDispatcherForTest dispatcher_;
245   TestControl control_interface_;
246   MockModemInfo modem_info_;
247   MockRTNLHandler rtnl_handler_;
248   bool create_gsm_card_proxy_from_factory_;
249   std::unique_ptr<MockModemProxy> proxy_;
250   std::unique_ptr<MockModemSimpleProxy> simple_proxy_;
251   std::unique_ptr<MockModemCDMAProxy> cdma_proxy_;
252   std::unique_ptr<MockModemGSMCardProxy> gsm_card_proxy_;
253   std::unique_ptr<MockModemGSMNetworkProxy> gsm_network_proxy_;
254   std::unique_ptr<MockModemGobiProxy> gobi_proxy_;
255   CellularCapabilityClassic* capability_;  // Owned by |cellular_|.
256   DeviceMockAdaptor* device_adaptor_;  // Owned by |cellular_|.
257   CellularRefPtr cellular_;
258 };
259 
260 const char CellularCapabilityTest::kTestMobileProviderDBPath[] =
261     "provider_db_unittest.bfd";
262 const char CellularCapabilityTest::kTestCarrier[] = "The Cellular Carrier";
263 const char CellularCapabilityTest::kManufacturer[] = "Company";
264 const char CellularCapabilityTest::kModelID[] = "Gobi 2000";
265 const char CellularCapabilityTest::kHWRev[] = "A00B1234";
266 
TEST_F(CellularCapabilityTest,GetModemStatus)267 TEST_F(CellularCapabilityTest, GetModemStatus) {
268   SetCellularType(Cellular::kTypeCDMA);
269   EXPECT_CALL(*simple_proxy_,
270               GetModemStatus(_, _, CellularCapability::kTimeoutDefault)).
271       WillOnce(Invoke(this, &CellularCapabilityTest::InvokeGetModemStatus));
272   EXPECT_CALL(*this, TestCallback(IsSuccess()));
273   SetSimpleProxy();
274   ResultCallback callback =
275       Bind(&CellularCapabilityTest::TestCallback, Unretained(this));
276   capability_->GetModemStatus(callback);
277   EXPECT_EQ(kTestCarrier, cellular_->carrier());
278 }
279 
TEST_F(CellularCapabilityTest,GetModemInfo)280 TEST_F(CellularCapabilityTest, GetModemInfo) {
281   EXPECT_CALL(*proxy_, GetModemInfo(_, _, CellularCapability::kTimeoutDefault))
282       .WillOnce(Invoke(this, &CellularCapabilityTest::InvokeGetModemInfo));
283   EXPECT_CALL(*this, TestCallback(IsSuccess()));
284   SetProxy();
285   ResultCallback callback =
286       Bind(&CellularCapabilityTest::TestCallback, Unretained(this));
287   capability_->GetModemInfo(callback);
288   EXPECT_EQ(kManufacturer, cellular_->manufacturer());
289   EXPECT_EQ(kModelID, cellular_->model_id());
290   EXPECT_EQ(kHWRev, cellular_->hardware_revision());
291 }
292 
TEST_F(CellularCapabilityTest,EnableModemSucceed)293 TEST_F(CellularCapabilityTest, EnableModemSucceed) {
294   EXPECT_CALL(*proxy_, Enable(true, _, _, CellularCapability::kTimeoutEnable))
295       .WillOnce(Invoke(this, &CellularCapabilityTest::InvokeEnable));
296   EXPECT_CALL(*this, TestCallback(IsSuccess()));
297   ResultCallback callback =
298       Bind(&CellularCapabilityTest::TestCallback, Unretained(this));
299   SetProxy();
300   capability_->EnableModem(callback);
301 }
302 
TEST_F(CellularCapabilityTest,EnableModemFail)303 TEST_F(CellularCapabilityTest, EnableModemFail) {
304   EXPECT_CALL(*proxy_, Enable(true, _, _, CellularCapability::kTimeoutEnable))
305       .WillOnce(Invoke(this, &CellularCapabilityTest::InvokeEnableFail));
306   EXPECT_CALL(*this, TestCallback(IsFailure()));
307   ResultCallback callback =
308       Bind(&CellularCapabilityTest::TestCallback, Unretained(this));
309   SetProxy();
310   capability_->EnableModem(callback);
311 }
312 
TEST_F(CellularCapabilityTest,FinishEnable)313 TEST_F(CellularCapabilityTest, FinishEnable) {
314   EXPECT_CALL(*gsm_network_proxy_,
315               GetRegistrationInfo(nullptr, _,
316                                   CellularCapability::kTimeoutDefault));
317   EXPECT_CALL(
318       *gsm_network_proxy_,
319       GetSignalQuality(nullptr, _, CellularCapability::kTimeoutDefault));
320   EXPECT_CALL(*this, TestCallback(IsSuccess()));
321   SetGSMNetworkProxy();
322   capability_->FinishEnable(
323       Bind(&CellularCapabilityTest::TestCallback, Unretained(this)));
324 }
325 
TEST_F(CellularCapabilityTest,UnsupportedOperation)326 TEST_F(CellularCapabilityTest, UnsupportedOperation) {
327   Error error;
328   EXPECT_CALL(*this, TestCallback(IsSuccess())).Times(0);
329   capability_->CellularCapability::Reset(
330       &error,
331       Bind(&CellularCapabilityTest::TestCallback, Unretained(this)));
332   EXPECT_TRUE(error.IsFailure());
333   EXPECT_EQ(Error::kNotSupported, error.type());
334 }
335 
TEST_F(CellularCapabilityTest,AllowRoaming)336 TEST_F(CellularCapabilityTest, AllowRoaming) {
337   EXPECT_FALSE(cellular_->GetAllowRoaming(nullptr));
338   cellular_->SetAllowRoaming(false, nullptr);
339   EXPECT_FALSE(cellular_->GetAllowRoaming(nullptr));
340 
341   {
342     InSequence seq;
343     EXPECT_CALL(*device_adaptor_,
344                 EmitBoolChanged(kCellularAllowRoamingProperty, true));
345     EXPECT_CALL(*device_adaptor_,
346                 EmitBoolChanged(kCellularAllowRoamingProperty, false));
347   }
348 
349   cellular_->state_ = Cellular::kStateConnected;
350   static_cast<CellularCapabilityGSM*>(capability_)->registration_state_ =
351       MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING;
352   cellular_->SetAllowRoaming(true, nullptr);
353   EXPECT_TRUE(cellular_->GetAllowRoaming(nullptr));
354   EXPECT_EQ(Cellular::kStateConnected, cellular_->state_);
355 
356   EXPECT_CALL(*proxy_, Disconnect(_, _, CellularCapability::kTimeoutDisconnect))
357       .WillOnce(Invoke(this, &CellularCapabilityTest::InvokeDisconnect));
358   SetProxy();
359   cellular_->state_ = Cellular::kStateConnected;
360   cellular_->SetAllowRoaming(false, nullptr);
361   EXPECT_FALSE(cellular_->GetAllowRoaming(nullptr));
362   EXPECT_EQ(Cellular::kStateRegistered, cellular_->state_);
363 }
364 
TEST_F(CellularCapabilityTest,SetCarrier)365 TEST_F(CellularCapabilityTest, SetCarrier) {
366   static const char kCarrier[] = "Generic UMTS";
367   EXPECT_CALL(
368       *gobi_proxy_,
369       SetCarrier(kCarrier, _, _,
370                  CellularCapabilityClassic::kTimeoutSetCarrierMilliseconds))
371       .WillOnce(Invoke(this, &CellularCapabilityTest::InvokeSetCarrier));
372   EXPECT_CALL(*this, TestCallback(IsSuccess()));
373   Error error;
374   capability_->SetCarrier(kCarrier, &error,
375                           Bind(&CellularCapabilityTest::TestCallback,
376                                Unretained(this)));
377   EXPECT_TRUE(error.IsSuccess());
378 }
379 
380 MATCHER_P(HasApn, apn, "") {
381   return arg.ContainsString(kApnProperty) && apn == arg.GetString(kApnProperty);
382 }
383 
384 MATCHER(HasNoApn, "") {
385   return !arg.ContainsString(kApnProperty);
386 }
387 
TEST_F(CellularCapabilityTest,TryApns)388 TEST_F(CellularCapabilityTest, TryApns) {
389   static const string kLastGoodApn("remembered.apn");
390   static const string kLastGoodUsername("remembered.user");
391   static const string kSuppliedApn("my.apn");
392   static const string kTmobileApn1("epc.tmobile.com");
393   static const string kTmobileApn2("wap.voicestream.com");
394   static const string kTmobileApn3("internet2.voicestream.com");
395   static const string kTmobileApn4("internet3.voicestream.com");
396   const Stringmaps kDatabaseApnList {{{ kApnProperty, kTmobileApn1 }},
397                                      {{ kApnProperty, kTmobileApn2 }},
398                                      {{ kApnProperty, kTmobileApn3 }},
399                                      {{ kApnProperty, kTmobileApn4 }}};
400 
401 
402   CreateService();
403   // Supply the database APNs to |cellular_| object.
404   cellular_->set_apn_list(kDatabaseApnList);
405   ProfileRefPtr profile(new NiceMock<MockProfile>(
406       modem_info_.control_interface(), modem_info_.metrics(),
407       modem_info_.manager()));
408   cellular_->service()->set_profile(profile);
409 
410   Error error;
411   Stringmap apn_info;
412   KeyValueStore props;
413   CellularCapabilityGSM* gsm_capability = GetGsmCapability();
414 
415   apn_info[kApnProperty] = kLastGoodApn;
416   apn_info[kApnUsernameProperty] = kLastGoodUsername;
417   cellular_->service()->SetLastGoodApn(apn_info);
418   props.Clear();
419   EXPECT_TRUE(props.IsEmpty());
420   gsm_capability->SetupConnectProperties(&props);
421   // We expect the list to contain the last good APN, plus
422   // the 4 APNs from the mobile provider info database.
423   EXPECT_EQ(5, gsm_capability->apn_try_list_.size());
424   EXPECT_TRUE(props.ContainsString(kApnProperty));
425   EXPECT_EQ(kLastGoodApn, props.GetString(kApnProperty));
426   EXPECT_TRUE(props.ContainsString(kApnUsernameProperty));
427   EXPECT_EQ(kLastGoodUsername,
428             props.GetString(kApnUsernameProperty));
429 
430   apn_info.clear();
431   props.Clear();
432   apn_info[kApnProperty] = kSuppliedApn;
433   // Setting the APN has the side effect of clearing the LastGoodApn,
434   // so the try list will have 5 elements, with the first one being
435   // the supplied APN.
436   cellular_->service()->SetApn(apn_info, &error);
437   EXPECT_TRUE(props.IsEmpty());
438   gsm_capability->SetupConnectProperties(&props);
439   EXPECT_EQ(5, gsm_capability->apn_try_list_.size());
440   EXPECT_TRUE(props.ContainsString(kApnProperty));
441   EXPECT_EQ(kSuppliedApn, props.GetString(kApnProperty));
442 
443   apn_info.clear();
444   props.Clear();
445   apn_info[kApnProperty] = kLastGoodApn;
446   apn_info[kApnUsernameProperty] = kLastGoodUsername;
447   // Now when LastGoodAPN is set, it will be the one selected.
448   cellular_->service()->SetLastGoodApn(apn_info);
449   EXPECT_TRUE(props.IsEmpty());
450   gsm_capability->SetupConnectProperties(&props);
451   // We expect the list to contain the last good APN, plus
452   // the user-supplied APN, plus the 4 APNs from the mobile
453   // provider info database.
454   EXPECT_EQ(6, gsm_capability->apn_try_list_.size());
455   EXPECT_TRUE(props.ContainsString(kApnProperty));
456   EXPECT_EQ(kLastGoodApn, props.GetString(kApnProperty));
457 
458   // Now try all the given APNs.
459   using testing::InSequence;
460   {
461     InSequence dummy;
462     EXPECT_CALL(*simple_proxy_, Connect(HasApn(kLastGoodApn), _, _, _));
463     EXPECT_CALL(*simple_proxy_, Connect(HasApn(kSuppliedApn), _, _, _));
464     EXPECT_CALL(*simple_proxy_, Connect(HasApn(kTmobileApn1), _, _, _));
465     EXPECT_CALL(*simple_proxy_, Connect(HasApn(kTmobileApn2), _, _, _));
466     EXPECT_CALL(*simple_proxy_, Connect(HasApn(kTmobileApn3), _, _, _));
467     EXPECT_CALL(*simple_proxy_, Connect(HasApn(kTmobileApn4), _, _, _));
468     EXPECT_CALL(*simple_proxy_, Connect(HasNoApn(), _, _, _));
469   }
470   SetSimpleProxy();
471   gsm_capability->Connect(props, &error, ResultCallback());
472   Error cerror(Error::kInvalidApn);
473   gsm_capability->OnConnectReply(ResultCallback(), cerror);
474   EXPECT_EQ(5, gsm_capability->apn_try_list_.size());
475   gsm_capability->OnConnectReply(ResultCallback(), cerror);
476   EXPECT_EQ(4, gsm_capability->apn_try_list_.size());
477   gsm_capability->OnConnectReply(ResultCallback(), cerror);
478   EXPECT_EQ(3, gsm_capability->apn_try_list_.size());
479   gsm_capability->OnConnectReply(ResultCallback(), cerror);
480   EXPECT_EQ(2, gsm_capability->apn_try_list_.size());
481   gsm_capability->OnConnectReply(ResultCallback(), cerror);
482   EXPECT_EQ(1, gsm_capability->apn_try_list_.size());
483   gsm_capability->OnConnectReply(ResultCallback(), cerror);
484   EXPECT_EQ(0, gsm_capability->apn_try_list_.size());
485 }
486 
TEST_F(CellularCapabilityTest,StopModemDisconnectSuccess)487 TEST_F(CellularCapabilityTest, StopModemDisconnectSuccess) {
488   EXPECT_CALL(*proxy_, Disconnect(_, _, CellularCapability::kTimeoutDisconnect))
489       .WillOnce(Invoke(this,
490                        &CellularCapabilityTest::InvokeDisconnect));
491   EXPECT_CALL(*proxy_, Enable(_, _, _, CellularCapability::kTimeoutEnable))
492       .WillOnce(Invoke(this,
493                        &CellularCapabilityTest::InvokeEnable));
494   EXPECT_CALL(*this, TestCallback(IsSuccess()));
495   SetProxy();
496 
497   Error error;
498   capability_->StopModem(
499       &error, Bind(&CellularCapabilityTest::TestCallback, Unretained(this)));
500   dispatcher_.DispatchPendingEvents();
501 }
502 
TEST_F(CellularCapabilityTest,StopModemDisconnectFail)503 TEST_F(CellularCapabilityTest, StopModemDisconnectFail) {
504   EXPECT_CALL(*proxy_, Disconnect(_, _, CellularCapability::kTimeoutDisconnect))
505       .WillOnce(Invoke(this,
506                        &CellularCapabilityTest::InvokeDisconnectFail));
507   EXPECT_CALL(*proxy_, Enable(_, _, _, CellularCapability::kTimeoutEnable))
508       .WillOnce(Invoke(this,
509                        &CellularCapabilityTest::InvokeEnable));
510   EXPECT_CALL(*this, TestCallback(IsSuccess()));
511   SetProxy();
512 
513   Error error;
514   capability_->StopModem(
515       &error, Bind(&CellularCapabilityTest::TestCallback, Unretained(this)));
516   dispatcher_.DispatchPendingEvents();
517 }
518 
TEST_F(CellularCapabilityTest,DisconnectNoProxy)519 TEST_F(CellularCapabilityTest, DisconnectNoProxy) {
520   Error error;
521   ResultCallback disconnect_callback;
522   EXPECT_CALL(*proxy_, Disconnect(_, _, CellularCapability::kTimeoutDisconnect))
523       .Times(0);
524   ReleaseCapabilityProxies();
525   capability_->Disconnect(&error, disconnect_callback);
526 }
527 
528 }  // namespace shill
529