• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
40 using std::string;
41 using testing::_;
42 using testing::InSequence;
43 using testing::Mock;
44 using testing::NiceMock;
45 using testing::Return;
46 using testing::SetArgumentPointee;
47 
48 namespace shill {
49 
50 class CellularServiceTest : public testing::Test {
51  public:
CellularServiceTest()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 
~CellularServiceTest()64   virtual ~CellularServiceTest() {
65     adaptor_ = nullptr;
66   }
67 
SetUp()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 
GetCapabilityCDMA()77   CellularCapabilityCDMA* GetCapabilityCDMA() {
78     return static_cast<CellularCapabilityCDMA*>(device_->capability_.get());
79   }
80 
81  protected:
82   static const char kAddress[];
83 
GetFriendlyName() const84   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 
94 const char CellularServiceTest::kAddress[] = "000102030405";
95 
TEST_F(CellularServiceTest,Constructor)96 TEST_F(CellularServiceTest, Constructor) {
97   EXPECT_TRUE(service_->connectable());
98 }
99 
TEST_F(CellularServiceTest,SetActivationState)100 TEST_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 
TEST_F(CellularServiceTest,SetNetworkTechnology)152 TEST_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 
TEST_F(CellularServiceTest,SetRoamingState)161 TEST_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 
TEST_F(CellularServiceTest,SetStorageIdentifier)170 TEST_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 
TEST_F(CellularServiceTest,SetServingOperator)178 TEST_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 
TEST_F(CellularServiceTest,SetOLP)199 TEST_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 
TEST_F(CellularServiceTest,SetUsageURL)220 TEST_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 
TEST_F(CellularServiceTest,SetApn)230 TEST_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 
TEST_F(CellularServiceTest,ClearApn)261 TEST_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 
TEST_F(CellularServiceTest,LastGoodApn)299 TEST_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 
TEST_F(CellularServiceTest,IsAutoConnectable)337 TEST_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 
TEST_F(CellularServiceTest,LoadResetsPPPAuthFailure)442 TEST_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.
TEST_F(CellularServiceTest,PropertyChanges)483 TEST_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.
TEST_F(CellularServiceTest,CustomSetterNoopChange)516 TEST_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