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_service.h"
18
19#if defined(__ANDROID__)
20#include <dbus/service_constants.h>
21#else
22#include <chromeos/dbus/service_constants.h>
23#endif  // __ANDROID__
24#include <gtest/gtest.h>
25#include <mm/mm-modem.h>
26
27#include "shill/cellular/cellular_capability.h"
28#include "shill/cellular/cellular_capability_cdma.h"
29#include "shill/cellular/mock_cellular.h"
30#include "shill/cellular/mock_modem_info.h"
31#include "shill/cellular/mock_out_of_credits_detector.h"
32#include "shill/mock_adaptors.h"
33#include "shill/mock_manager.h"
34#include "shill/mock_metrics.h"
35#include "shill/mock_profile.h"
36#include "shill/mock_store.h"
37#include "shill/nice_mock_control.h"
38#include "shill/service_property_change_test.h"
39
40using std::string;
41using testing::_;
42using testing::InSequence;
43using testing::Mock;
44using testing::NiceMock;
45using testing::Return;
46using testing::SetArgumentPointee;
47
48namespace shill {
49
50class CellularServiceTest : public testing::Test {
51 public:
52  CellularServiceTest()
53      : modem_info_(nullptr, &dispatcher_, nullptr, nullptr),
54        device_(new MockCellular(&modem_info_,
55                                 "usb0",
56                                 kAddress,
57                                 3,
58                                 Cellular::kTypeCDMA,
59                                 "",
60                                 "")),
61        service_(new CellularService(&modem_info_, device_)),
62        adaptor_(nullptr) {}
63
64  virtual ~CellularServiceTest() {
65    adaptor_ = nullptr;
66  }
67
68  virtual void SetUp() {
69    adaptor_ =
70        static_cast<ServiceMockAdaptor*>(service_->adaptor());
71    out_of_credits_detector_ =
72        new MockOutOfCreditsDetector(nullptr, nullptr, nullptr, service_.get());
73    // Passes ownership.
74    service_->set_out_of_credits_detector(out_of_credits_detector_);
75  }
76
77  CellularCapabilityCDMA* GetCapabilityCDMA() {
78    return static_cast<CellularCapabilityCDMA*>(device_->capability_.get());
79  }
80
81 protected:
82  static const char kAddress[];
83
84  string GetFriendlyName() const { return service_->friendly_name(); }
85
86  EventDispatcher dispatcher_;
87  MockModemInfo modem_info_;
88  scoped_refptr<MockCellular> device_;
89  CellularServiceRefPtr service_;
90  ServiceMockAdaptor* adaptor_;  // Owned by |service_|.
91  MockOutOfCreditsDetector* out_of_credits_detector_;  // Owned by |service_|.
92};
93
94const char CellularServiceTest::kAddress[] = "000102030405";
95
96TEST_F(CellularServiceTest, Constructor) {
97  EXPECT_TRUE(service_->connectable());
98}
99
100TEST_F(CellularServiceTest, SetActivationState) {
101  {
102    InSequence call_sequence;
103    EXPECT_CALL(*adaptor_, EmitStringChanged(
104        kActivationStateProperty,
105        kActivationStateNotActivated));
106    EXPECT_CALL(*adaptor_, EmitBoolChanged(
107        kConnectableProperty, false));
108    EXPECT_CALL(*adaptor_, EmitStringChanged(
109        kActivationStateProperty,
110        kActivationStateActivating));
111    EXPECT_CALL(*adaptor_, EmitBoolChanged(
112        kConnectableProperty, true));
113    EXPECT_CALL(*adaptor_, EmitStringChanged(
114        kActivationStateProperty,
115        kActivationStatePartiallyActivated));
116    EXPECT_CALL(*adaptor_, EmitStringChanged(
117        kActivationStateProperty,
118        kActivationStateActivated));
119    EXPECT_CALL(*adaptor_, EmitStringChanged(
120        kActivationStateProperty,
121        kActivationStateNotActivated));
122    EXPECT_CALL(*adaptor_, EmitBoolChanged(
123        kConnectableProperty, false));
124  }
125  EXPECT_CALL(*modem_info_.mock_manager(), HasService(_))
126      .WillRepeatedly(Return(false));
127
128  EXPECT_TRUE(service_->activation_state().empty());
129  EXPECT_TRUE(service_->connectable());
130
131  service_->SetActivationState(kActivationStateNotActivated);
132  EXPECT_EQ(kActivationStateNotActivated, service_->activation_state());
133  EXPECT_FALSE(service_->connectable());
134
135  service_->SetActivationState(kActivationStateActivating);
136  EXPECT_EQ(kActivationStateActivating, service_->activation_state());
137  EXPECT_TRUE(service_->connectable());
138
139  service_->SetActivationState(kActivationStatePartiallyActivated);
140  EXPECT_EQ(kActivationStatePartiallyActivated, service_->activation_state());
141  EXPECT_TRUE(service_->connectable());
142
143  service_->SetActivationState(kActivationStateActivated);
144  EXPECT_EQ(kActivationStateActivated, service_->activation_state());
145  EXPECT_TRUE(service_->connectable());
146
147  service_->SetActivationState(kActivationStateNotActivated);
148  EXPECT_EQ(kActivationStateNotActivated, service_->activation_state());
149  EXPECT_FALSE(service_->connectable());
150}
151
152TEST_F(CellularServiceTest, SetNetworkTechnology) {
153  EXPECT_CALL(*adaptor_, EmitStringChanged(kNetworkTechnologyProperty,
154                                           kNetworkTechnologyUmts));
155  EXPECT_TRUE(service_->network_technology().empty());
156  service_->SetNetworkTechnology(kNetworkTechnologyUmts);
157  EXPECT_EQ(kNetworkTechnologyUmts, service_->network_technology());
158  service_->SetNetworkTechnology(kNetworkTechnologyUmts);
159}
160
161TEST_F(CellularServiceTest, SetRoamingState) {
162  EXPECT_CALL(*adaptor_, EmitStringChanged(kRoamingStateProperty,
163                                           kRoamingStateHome));
164  EXPECT_TRUE(service_->roaming_state().empty());
165  service_->SetRoamingState(kRoamingStateHome);
166  EXPECT_EQ(kRoamingStateHome, service_->roaming_state());
167  service_->SetRoamingState(kRoamingStateHome);
168}
169
170TEST_F(CellularServiceTest, SetStorageIdentifier) {
171  EXPECT_EQ(string(kTypeCellular) + "_" +
172            kAddress + "_" + GetFriendlyName(),
173            service_->GetStorageIdentifier());
174  service_->SetStorageIdentifier("a b c");
175  EXPECT_EQ("a_b_c", service_->GetStorageIdentifier());
176}
177
178TEST_F(CellularServiceTest, SetServingOperator) {
179  static const char kCode[] = "123456";
180  static const char kName[] = "Some Cellular Operator";
181  Stringmap test_operator;
182  service_->set_serving_operator(test_operator);
183  test_operator[kOperatorCodeKey] = kCode;
184  test_operator[kOperatorNameKey] = kName;
185  EXPECT_CALL(*adaptor_,
186              EmitStringmapChanged(kServingOperatorProperty, _));
187  service_->set_serving_operator(test_operator);
188  const Stringmap& serving_operator = service_->serving_operator();
189  ASSERT_NE(serving_operator.end(), serving_operator.find(kOperatorCodeKey));
190  ASSERT_NE(serving_operator.end(), serving_operator.find(kOperatorNameKey));
191  EXPECT_EQ(kCode, serving_operator.find(kOperatorCodeKey)->second);
192  EXPECT_EQ(kName, serving_operator.find(kOperatorNameKey)->second);
193  Mock::VerifyAndClearExpectations(adaptor_);
194  EXPECT_CALL(*adaptor_,
195              EmitStringmapChanged(kServingOperatorProperty, _)).Times(0);
196  service_->set_serving_operator(serving_operator);
197}
198
199TEST_F(CellularServiceTest, SetOLP) {
200  const char kMethod[] = "GET";
201  const char kURL[] = "payment.url";
202  const char kPostData[] = "post_man";
203  Stringmap olp;
204
205  service_->SetOLP("", "", "");
206  olp = service_->olp();  // Copy to simplify assertions below.
207  EXPECT_EQ("", olp[kPaymentPortalURL]);
208  EXPECT_EQ("", olp[kPaymentPortalMethod]);
209  EXPECT_EQ("", olp[kPaymentPortalPostData]);
210
211  EXPECT_CALL(*adaptor_,
212              EmitStringmapChanged(kPaymentPortalProperty, _));
213  service_->SetOLP(kURL, kMethod, kPostData);
214  olp = service_->olp();  // Copy to simplify assertions below.
215  EXPECT_EQ(kURL, olp[kPaymentPortalURL]);
216  EXPECT_EQ(kMethod, olp[kPaymentPortalMethod]);
217  EXPECT_EQ(kPostData, olp[kPaymentPortalPostData]);
218}
219
220TEST_F(CellularServiceTest, SetUsageURL) {
221  static const char kUsageURL[] = "usage.url";
222  EXPECT_CALL(*adaptor_, EmitStringChanged(kUsageURLProperty,
223                                           kUsageURL));
224  EXPECT_TRUE(service_->usage_url().empty());
225  service_->SetUsageURL(kUsageURL);
226  EXPECT_EQ(kUsageURL, service_->usage_url());
227  service_->SetUsageURL(kUsageURL);
228}
229
230TEST_F(CellularServiceTest, SetApn) {
231  static const char kApn[] = "TheAPN";
232  static const char kUsername[] = "commander.data";
233  ProfileRefPtr profile(new NiceMock<MockProfile>(
234      modem_info_.control_interface(), modem_info_.metrics(),
235      modem_info_.manager()));
236  service_->set_profile(profile);
237  Error error;
238  Stringmap testapn;
239  testapn[kApnProperty] = kApn;
240  testapn[kApnUsernameProperty] = kUsername;
241  {
242    InSequence seq;
243    EXPECT_CALL(*adaptor_,
244                EmitStringmapChanged(kCellularLastGoodApnProperty,
245                                     _));
246    EXPECT_CALL(*adaptor_,
247                EmitStringmapChanged(kCellularApnProperty, _));
248  }
249  service_->SetApn(testapn, &error);
250  EXPECT_TRUE(error.IsSuccess());
251  Stringmap resultapn = service_->GetApn(&error);
252  EXPECT_TRUE(error.IsSuccess());
253  EXPECT_EQ(2, resultapn.size());
254  Stringmap::const_iterator it = resultapn.find(kApnProperty);
255  EXPECT_TRUE(it != resultapn.end() && it->second == kApn);
256  it = resultapn.find(kApnUsernameProperty);
257  EXPECT_TRUE(it != resultapn.end() && it->second == kUsername);
258  EXPECT_NE(nullptr, service_->GetUserSpecifiedApn());
259}
260
261TEST_F(CellularServiceTest, ClearApn) {
262  static const char kApn[] = "TheAPN";
263  static const char kUsername[] = "commander.data";
264  ProfileRefPtr profile(new NiceMock<MockProfile>(
265      modem_info_.control_interface(), modem_info_.metrics(),
266      modem_info_.manager()));
267  service_->set_profile(profile);
268  Error error;
269  // Set up an APN to make sure that it later gets cleared.
270  Stringmap testapn;
271  testapn[kApnProperty] = kApn;
272  testapn[kApnUsernameProperty] = kUsername;
273  {
274    InSequence seq;
275    EXPECT_CALL(*adaptor_,
276                EmitStringmapChanged(kCellularLastGoodApnProperty,
277                                     _));
278    EXPECT_CALL(*adaptor_,
279                EmitStringmapChanged(kCellularApnProperty, _));
280  }
281  service_->SetApn(testapn, &error);
282  Stringmap resultapn = service_->GetApn(&error);
283  ASSERT_TRUE(error.IsSuccess());
284  ASSERT_EQ(2, service_->GetApn(&error).size());
285
286  Stringmap emptyapn;
287  EXPECT_CALL(*adaptor_,
288              EmitStringmapChanged(kCellularLastGoodApnProperty,
289                                   _)).Times(0);
290  EXPECT_CALL(*adaptor_,
291              EmitStringmapChanged(kCellularApnProperty, _)).Times(1);
292  service_->SetApn(emptyapn, &error);
293  EXPECT_TRUE(error.IsSuccess());
294  resultapn = service_->GetApn(&error);
295  EXPECT_TRUE(resultapn.empty());
296  EXPECT_EQ(nullptr, service_->GetUserSpecifiedApn());;
297}
298
299TEST_F(CellularServiceTest, LastGoodApn) {
300  static const char kApn[] = "TheAPN";
301  static const char kUsername[] = "commander.data";
302  ProfileRefPtr profile(new NiceMock<MockProfile>(
303      modem_info_.control_interface(), modem_info_.metrics(),
304      modem_info_.manager()));
305  service_->set_profile(profile);
306  Stringmap testapn;
307  testapn[kApnProperty] = kApn;
308  testapn[kApnUsernameProperty] = kUsername;
309  EXPECT_CALL(*adaptor_,
310              EmitStringmapChanged(kCellularLastGoodApnProperty, _));
311  service_->SetLastGoodApn(testapn);
312  Stringmap* resultapn = service_->GetLastGoodApn();
313  EXPECT_NE(nullptr, resultapn);
314  EXPECT_EQ(2, resultapn->size());
315  Stringmap::const_iterator it = resultapn->find(kApnProperty);
316  EXPECT_TRUE(it != resultapn->end() && it->second == kApn);
317  it = resultapn->find(kApnUsernameProperty);
318  EXPECT_TRUE(it != resultapn->end() && it->second == kUsername);
319  // Now set the user-specified APN, and check that LastGoodApn got
320  // cleared.
321  Stringmap userapn;
322  userapn[kApnProperty] = kApn;
323  userapn[kApnUsernameProperty] = kUsername;
324  {
325    InSequence seq;
326    EXPECT_CALL(*adaptor_,
327                EmitStringmapChanged(kCellularLastGoodApnProperty,
328                                     _));
329    EXPECT_CALL(*adaptor_,
330                EmitStringmapChanged(kCellularApnProperty, _));
331  }
332  Error error;
333  service_->SetApn(userapn, &error);
334  EXPECT_EQ(nullptr, service_->GetLastGoodApn());;
335}
336
337TEST_F(CellularServiceTest, IsAutoConnectable) {
338  const char* reason = nullptr;
339
340  ON_CALL(*out_of_credits_detector_, IsDetecting())
341      .WillByDefault(Return(false));
342
343  // Auto-connect should be suppressed if the device is not running.
344  device_->running_ = false;
345  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
346  EXPECT_STREQ(CellularService::kAutoConnDeviceDisabled, reason);
347
348  device_->running_ = true;
349
350  // If we're waiting on a disconnect before an activation, don't auto-connect.
351  GetCapabilityCDMA()->activation_starting_ = true;
352  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
353
354  // If we're waiting on an activation, also don't auto-connect.
355  GetCapabilityCDMA()->activation_starting_ = false;
356  GetCapabilityCDMA()->activation_state_ =
357      MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING;
358  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
359
360  GetCapabilityCDMA()->activation_state_ =
361      MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED;
362
363  // Auto-connect should be suppressed if the we're undergoing an
364  // out-of-credits detection.
365  EXPECT_CALL(*out_of_credits_detector_, IsDetecting())
366      .WillOnce(Return(true));
367  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
368  EXPECT_STREQ(CellularService::kAutoConnOutOfCreditsDetectionInProgress,
369               reason);
370  Mock::VerifyAndClearExpectations(out_of_credits_detector_);
371
372  // Auto-connect should be suppressed if we're out of credits.
373  EXPECT_CALL(*out_of_credits_detector_, IsDetecting())
374      .WillOnce(Return(false));
375  EXPECT_CALL(*out_of_credits_detector_, out_of_credits())
376      .WillOnce(Return(true));
377  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
378  EXPECT_STREQ(CellularService::kAutoConnOutOfCredits, reason);
379  Mock::VerifyAndClearExpectations(out_of_credits_detector_);
380
381  EXPECT_CALL(*out_of_credits_detector_, out_of_credits())
382      .WillRepeatedly(Return(false));
383
384  // But other activation states are fine.
385  GetCapabilityCDMA()->activation_state_ =
386      MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED;
387  EXPECT_TRUE(service_->IsAutoConnectable(&reason));
388  GetCapabilityCDMA()->activation_state_ =
389      MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED;
390  EXPECT_TRUE(service_->IsAutoConnectable(&reason));
391  GetCapabilityCDMA()->activation_state_ =
392      MM_MODEM_CDMA_ACTIVATION_STATE_PARTIALLY_ACTIVATED;
393  EXPECT_TRUE(service_->IsAutoConnectable(&reason));
394
395  // A PPP authentication failure means the Service is not auto-connectable.
396  service_->SetFailure(Service::kFailurePPPAuth);
397  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
398
399  // Reset failure state, to make the Service auto-connectable again.
400  service_->SetState(Service::kStateIdle);
401  EXPECT_TRUE(service_->IsAutoConnectable(&reason));
402
403  // The following test cases are copied from ServiceTest.IsAutoConnectable
404
405  service_->SetConnectable(true);
406  EXPECT_TRUE(service_->IsAutoConnectable(&reason));
407
408  // We should not auto-connect to a Service that a user has
409  // deliberately disconnected.
410  Error error;
411  service_->UserInitiatedDisconnect(&error);
412  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
413  EXPECT_STREQ(Service::kAutoConnExplicitDisconnect, reason);
414
415  // But if the Service is reloaded, it is eligible for auto-connect
416  // again.
417  NiceMock<MockStore> storage;
418  EXPECT_CALL(storage, ContainsGroup(service_->GetStorageIdentifier()))
419      .WillOnce(Return(true));
420  EXPECT_TRUE(service_->Load(&storage));
421  EXPECT_TRUE(service_->IsAutoConnectable(&reason));
422
423  // A non-user initiated Disconnect doesn't change anything.
424  service_->Disconnect(&error, "in test");
425  EXPECT_TRUE(service_->IsAutoConnectable(&reason));
426
427  // A resume also re-enables auto-connect.
428  service_->UserInitiatedDisconnect(&error);
429  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
430  service_->OnAfterResume();
431  EXPECT_TRUE(service_->IsAutoConnectable(&reason));
432
433  service_->SetState(Service::kStateConnected);
434  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
435  EXPECT_STREQ(Service::kAutoConnConnected, reason);
436
437  service_->SetState(Service::kStateAssociating);
438  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
439  EXPECT_STREQ(Service::kAutoConnConnecting, reason);
440}
441
442TEST_F(CellularServiceTest, LoadResetsPPPAuthFailure) {
443  NiceMock<MockStore> storage;
444  EXPECT_CALL(storage, ContainsGroup(_)).WillRepeatedly(Return(true));
445  EXPECT_CALL(storage, GetString(_, _, _)).WillRepeatedly(Return(true));
446
447  const string kDefaultUser;
448  const string kDefaultPass;
449  const string kNewUser("new-username");
450  const string kNewPass("new-password");
451  for (const auto change_username : { false, true }) {
452    for (const auto change_password : { false, true }) {
453      service_->ppp_username_ = kDefaultUser;
454      service_->ppp_password_ = kDefaultPass;
455      service_->SetFailure(Service::kFailurePPPAuth);
456      EXPECT_TRUE(service_->IsFailed());
457      EXPECT_EQ(Service::kFailurePPPAuth, service_->failure());
458      if (change_username) {
459        EXPECT_CALL(storage,
460                    GetString(_, CellularService::kStoragePPPUsername, _))
461            .WillOnce(DoAll(SetArgumentPointee<2>(kNewUser), Return(true)))
462            .RetiresOnSaturation();
463      }
464      if (change_password) {
465        EXPECT_CALL(storage,
466                    GetString(_, CellularService::kStoragePPPPassword, _))
467            .WillOnce(DoAll(SetArgumentPointee<2>(kNewPass), Return(true)))
468            .RetiresOnSaturation();
469      }
470      EXPECT_TRUE(service_->Load(&storage));
471      if (change_username || change_password) {
472        EXPECT_NE(Service::kFailurePPPAuth, service_->failure());
473      } else {
474        EXPECT_EQ(Service::kFailurePPPAuth, service_->failure());
475      }
476    }
477  }
478}
479
480// Some of these tests duplicate signals tested above. However, it's
481// convenient to have all the property change notifications documented
482// (and tested) in one place.
483TEST_F(CellularServiceTest, PropertyChanges) {
484  TestCommonPropertyChanges(service_, adaptor_);
485  TestAutoConnectPropertyChange(service_, adaptor_);
486
487  EXPECT_CALL(*adaptor_,
488              EmitStringChanged(kActivationTypeProperty, _));
489  service_->SetActivationType(CellularService::kActivationTypeOTA);
490  Mock::VerifyAndClearExpectations(adaptor_);
491
492  EXPECT_NE(kActivationStateNotActivated, service_->activation_state());
493  EXPECT_CALL(*adaptor_, EmitStringChanged(kActivationStateProperty, _));
494  service_->SetActivationState(kActivationStateNotActivated);
495  Mock::VerifyAndClearExpectations(adaptor_);
496
497  string network_technology = service_->network_technology();
498  EXPECT_CALL(*adaptor_, EmitStringChanged(kNetworkTechnologyProperty, _));
499  service_->SetNetworkTechnology(network_technology + "and some new stuff");
500  Mock::VerifyAndClearExpectations(adaptor_);
501
502  bool out_of_credits = true;
503  EXPECT_CALL(*adaptor_,
504              EmitBoolChanged(kOutOfCreditsProperty, out_of_credits));
505  service_->SignalOutOfCreditsChanged(out_of_credits);
506  Mock::VerifyAndClearExpectations(adaptor_);
507
508  string roaming_state = service_->roaming_state();
509  EXPECT_CALL(*adaptor_, EmitStringChanged(kRoamingStateProperty, _));
510  service_->SetRoamingState(roaming_state + "and some new stuff");
511  Mock::VerifyAndClearExpectations(adaptor_);
512}
513
514// Custom property setters should return false, and make no changes, if
515// the new value is the same as the old value.
516TEST_F(CellularServiceTest, CustomSetterNoopChange) {
517  // Test that we didn't break any setters provided by the base class.
518  TestCustomSetterNoopChange(service_, modem_info_.mock_manager());
519
520  // Test the new setter we added.
521  // First set up our environment...
522  static const char kApn[] = "TheAPN";
523  static const char kUsername[] = "commander.data";
524  Error error;
525  Stringmap testapn;
526  ProfileRefPtr profile(new NiceMock<MockProfile>(nullptr, nullptr, nullptr));
527  service_->set_profile(profile);
528  testapn[kApnProperty] = kApn;
529  testapn[kApnUsernameProperty] = kUsername;
530  // ... then set to a known value ...
531  EXPECT_TRUE(service_->SetApn(testapn, &error));
532  EXPECT_TRUE(error.IsSuccess());
533  // ... then set to same value.
534  EXPECT_FALSE(service_->SetApn(testapn, &error));
535  EXPECT_TRUE(error.IsSuccess());
536}
537
538}  // namespace shill
539