Home | History | Annotate | Download | only in cellular
      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:
     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 
     94 const char CellularServiceTest::kAddress[] = "000102030405";
     95 
     96 TEST_F(CellularServiceTest, Constructor) {
     97   EXPECT_TRUE(service_->connectable());
     98 }
     99 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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.
    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.
    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