// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "shill/cellular_service.h"

#include <chromeos/dbus/service_constants.h>
#include <gtest/gtest.h>
#include <mm/mm-modem.h>

#include "shill/cellular_capability.h"
#include "shill/cellular_capability_cdma.h"
#include "shill/mock_adaptors.h"
#include "shill/mock_cellular.h"
#include "shill/mock_manager.h"
#include "shill/mock_metrics.h"
#include "shill/mock_modem_info.h"
#include "shill/mock_profile.h"
#include "shill/mock_store.h"
#include "shill/nice_mock_control.h"
#include "shill/proxy_factory.h"
#include "shill/service_property_change_test.h"

using std::string;
using testing::_;
using testing::InSequence;
using testing::Mock;
using testing::NiceMock;
using testing::Return;

namespace shill {

class CellularServiceTest : public testing::Test {
 public:
  CellularServiceTest()
      : modem_info_(NULL, &dispatcher_, NULL, NULL, NULL),
        device_(new MockCellular(&modem_info_,
                                 "usb0",
                                 kAddress,
                                 3,
                                 Cellular::kTypeCDMA,
                                 "",
                                 "",
                                 "",
                                 ProxyFactory::GetInstance())),
        service_(new CellularService(&modem_info_, device_)),
        adaptor_(NULL) {}

  virtual ~CellularServiceTest() {
    adaptor_ = NULL;
  }

  virtual void SetUp() {
    adaptor_ =
        dynamic_cast<ServiceMockAdaptor *>(service_->adaptor());
  }

  CellularCapabilityCDMA *GetCapabilityCDMA() {
    return dynamic_cast<CellularCapabilityCDMA *>(device_->capability_.get());
  }

 protected:
  static const char kAddress[];

  string GetFriendlyName() const { return service_->friendly_name(); }

  EventDispatcher dispatcher_;
  MockModemInfo modem_info_;
  scoped_refptr<MockCellular> device_;
  CellularServiceRefPtr service_;
  ServiceMockAdaptor *adaptor_;  // Owned by |service_|.
};

const char CellularServiceTest::kAddress[] = "000102030405";

TEST_F(CellularServiceTest, Constructor) {
  EXPECT_TRUE(service_->connectable());
}

TEST_F(CellularServiceTest, SetActivationState) {
  {
    InSequence call_sequence;
    EXPECT_CALL(*adaptor_, EmitStringChanged(
        flimflam::kActivationStateProperty,
        flimflam::kActivationStateNotActivated));
    EXPECT_CALL(*adaptor_, EmitBoolChanged(
        flimflam::kConnectableProperty, false));
    EXPECT_CALL(*adaptor_, EmitStringChanged(
        flimflam::kActivationStateProperty,
        flimflam::kActivationStateActivating));
    EXPECT_CALL(*adaptor_, EmitBoolChanged(
        flimflam::kConnectableProperty, true));
    EXPECT_CALL(*adaptor_, EmitStringChanged(
        flimflam::kActivationStateProperty,
        flimflam::kActivationStatePartiallyActivated));
    EXPECT_CALL(*adaptor_, EmitStringChanged(
        flimflam::kActivationStateProperty,
        flimflam::kActivationStateActivated));
    EXPECT_CALL(*adaptor_, EmitStringChanged(
        flimflam::kActivationStateProperty,
        flimflam::kActivationStateNotActivated));
    EXPECT_CALL(*adaptor_, EmitBoolChanged(
        flimflam::kConnectableProperty, false));
  }
  EXPECT_CALL(*modem_info_.mock_manager(), HasService(_))
      .WillRepeatedly(Return(false));

  EXPECT_TRUE(service_->activation_state().empty());
  EXPECT_TRUE(service_->connectable());

  service_->SetActivationState(flimflam::kActivationStateNotActivated);
  EXPECT_EQ(flimflam::kActivationStateNotActivated,
            service_->activation_state());
  EXPECT_FALSE(service_->connectable());

  service_->SetActivationState(flimflam::kActivationStateActivating);
  EXPECT_EQ(flimflam::kActivationStateActivating, service_->activation_state());
  EXPECT_TRUE(service_->connectable());

  service_->SetActivationState(flimflam::kActivationStatePartiallyActivated);
  EXPECT_EQ(flimflam::kActivationStatePartiallyActivated,
            service_->activation_state());
  EXPECT_TRUE(service_->connectable());

  service_->SetActivationState(flimflam::kActivationStateActivated);
  EXPECT_EQ(flimflam::kActivationStateActivated, service_->activation_state());
  EXPECT_TRUE(service_->connectable());

  service_->SetActivationState(flimflam::kActivationStateNotActivated);
  EXPECT_EQ(flimflam::kActivationStateNotActivated,
            service_->activation_state());
  EXPECT_FALSE(service_->connectable());
}

TEST_F(CellularServiceTest, SetNetworkTechnology) {
  EXPECT_CALL(*adaptor_, EmitStringChanged(flimflam::kNetworkTechnologyProperty,
                                           flimflam::kNetworkTechnologyUmts));
  EXPECT_TRUE(service_->network_technology().empty());
  service_->SetNetworkTechnology(flimflam::kNetworkTechnologyUmts);
  EXPECT_EQ(flimflam::kNetworkTechnologyUmts, service_->network_technology());
  service_->SetNetworkTechnology(flimflam::kNetworkTechnologyUmts);
}

TEST_F(CellularServiceTest, SetRoamingState) {
  EXPECT_CALL(*adaptor_, EmitStringChanged(flimflam::kRoamingStateProperty,
                                           flimflam::kRoamingStateHome));
  EXPECT_TRUE(service_->roaming_state().empty());
  service_->SetRoamingState(flimflam::kRoamingStateHome);
  EXPECT_EQ(flimflam::kRoamingStateHome, service_->roaming_state());
  service_->SetRoamingState(flimflam::kRoamingStateHome);
}

TEST_F(CellularServiceTest, FriendlyName) {
  static const char kCarrier[] = "Cellular Carrier";
  GetCapabilityCDMA()->carrier_ = kCarrier;
  service_ = new CellularService(&modem_info_, device_);
  EXPECT_EQ(kCarrier, GetFriendlyName());
}

TEST_F(CellularServiceTest, SetStorageIdentifier) {
  EXPECT_EQ(string(flimflam::kTypeCellular) + "_" +
            kAddress + "_" + GetFriendlyName(),
            service_->GetStorageIdentifier());
  service_->SetStorageIdentifier("a b c");
  EXPECT_EQ("a_b_c", service_->GetStorageIdentifier());
}

TEST_F(CellularServiceTest, SetServingOperator) {
  EXPECT_CALL(*adaptor_,
              EmitStringmapChanged(flimflam::kServingOperatorProperty, _));
  static const char kCode[] = "123456";
  static const char kName[] = "Some Cellular Operator";
  Cellular::Operator oper;
  service_->SetServingOperator(oper);
  oper.SetCode(kCode);
  oper.SetName(kName);
  service_->SetServingOperator(oper);
  EXPECT_EQ(kCode, service_->serving_operator().GetCode());
  EXPECT_EQ(kName, service_->serving_operator().GetName());
  service_->SetServingOperator(oper);
}

TEST_F(CellularServiceTest, SetOLP) {
  EXPECT_CALL(*adaptor_,
              EmitStringmapChanged(flimflam::kPaymentPortalProperty, _));
  static const char kURL[] = "payment.url";
  static const char kMethod[] = "GET";
  CellularService::OLP olp;
  service_->SetOLP(olp);
  olp.SetURL(kURL);
  olp.SetMethod(kMethod);
  service_->SetOLP(olp);
  EXPECT_EQ(kURL, service_->olp().GetURL());
  EXPECT_EQ(kMethod, service_->olp().GetMethod());
  service_->SetOLP(olp);
}

TEST_F(CellularServiceTest, SetUsageURL) {
  static const char kUsageURL[] = "usage.url";
  EXPECT_CALL(*adaptor_, EmitStringChanged(flimflam::kUsageURLProperty,
                                           kUsageURL));
  EXPECT_TRUE(service_->usage_url().empty());
  service_->SetUsageURL(kUsageURL);
  EXPECT_EQ(kUsageURL, service_->usage_url());
  service_->SetUsageURL(kUsageURL);
}

TEST_F(CellularServiceTest, SetApn) {
  static const char kApn[] = "TheAPN";
  static const char kUsername[] = "commander.data";
  ProfileRefPtr profile(new NiceMock<MockProfile>(
      modem_info_.control_interface(), modem_info_.metrics(),
      modem_info_.manager()));
  service_->set_profile(profile);
  Error error;
  Stringmap testapn;
  testapn[flimflam::kApnProperty] = kApn;
  testapn[flimflam::kApnUsernameProperty] = kUsername;
  {
    InSequence seq;
    EXPECT_CALL(*adaptor_,
                EmitStringmapChanged(flimflam::kCellularLastGoodApnProperty,
                                     _));
    EXPECT_CALL(*adaptor_,
                EmitStringmapChanged(flimflam::kCellularApnProperty, _));
  }
  service_->SetApn(testapn, &error);
  EXPECT_TRUE(error.IsSuccess());
  Stringmap resultapn = service_->GetApn(&error);
  EXPECT_TRUE(error.IsSuccess());
  EXPECT_EQ(2, resultapn.size());
  Stringmap::const_iterator it = resultapn.find(flimflam::kApnProperty);
  EXPECT_TRUE(it != resultapn.end() && it->second == kApn);
  it = resultapn.find(flimflam::kApnUsernameProperty);
  EXPECT_TRUE(it != resultapn.end() && it->second == kUsername);
  EXPECT_FALSE(service_->GetUserSpecifiedApn() == NULL);
}

TEST_F(CellularServiceTest, ClearApn) {
  static const char kApn[] = "TheAPN";
  static const char kUsername[] = "commander.data";
  ProfileRefPtr profile(new NiceMock<MockProfile>(
      modem_info_.control_interface(), modem_info_.metrics(),
      modem_info_.manager()));
  service_->set_profile(profile);
  Error error;
  // Set up an APN to make sure that it later gets cleared.
  Stringmap testapn;
  testapn[flimflam::kApnProperty] = kApn;
  testapn[flimflam::kApnUsernameProperty] = kUsername;
  {
    InSequence seq;
    EXPECT_CALL(*adaptor_,
                EmitStringmapChanged(flimflam::kCellularLastGoodApnProperty,
                                     _));
    EXPECT_CALL(*adaptor_,
                EmitStringmapChanged(flimflam::kCellularApnProperty, _));
  }
  service_->SetApn(testapn, &error);
  Stringmap resultapn = service_->GetApn(&error);
  ASSERT_TRUE(error.IsSuccess());
  ASSERT_EQ(2, service_->GetApn(&error).size());

  Stringmap emptyapn;
  EXPECT_CALL(*adaptor_,
              EmitStringmapChanged(flimflam::kCellularLastGoodApnProperty,
                                   _)).Times(0);
  EXPECT_CALL(*adaptor_,
              EmitStringmapChanged(flimflam::kCellularApnProperty, _)).Times(1);
  service_->SetApn(emptyapn, &error);
  EXPECT_TRUE(error.IsSuccess());
  resultapn = service_->GetApn(&error);
  EXPECT_TRUE(resultapn.empty());
  EXPECT_TRUE(service_->GetUserSpecifiedApn() == NULL);
}

TEST_F(CellularServiceTest, LastGoodApn) {
  static const char kApn[] = "TheAPN";
  static const char kUsername[] = "commander.data";
  ProfileRefPtr profile(new NiceMock<MockProfile>(
      modem_info_.control_interface(), modem_info_.metrics(),
      modem_info_.manager()));
  service_->set_profile(profile);
  Stringmap testapn;
  testapn[flimflam::kApnProperty] = kApn;
  testapn[flimflam::kApnUsernameProperty] = kUsername;
  EXPECT_CALL(*adaptor_,
              EmitStringmapChanged(flimflam::kCellularLastGoodApnProperty, _));
  service_->SetLastGoodApn(testapn);
  Stringmap *resultapn = service_->GetLastGoodApn();
  EXPECT_FALSE(resultapn == NULL);
  EXPECT_EQ(2, resultapn->size());
  Stringmap::const_iterator it = resultapn->find(flimflam::kApnProperty);
  EXPECT_TRUE(it != resultapn->end() && it->second == kApn);
  it = resultapn->find(flimflam::kApnUsernameProperty);
  EXPECT_TRUE(it != resultapn->end() && it->second == kUsername);
  // Now set the user-specified APN, and check that LastGoodApn got
  // cleared.
  Stringmap userapn;
  userapn[flimflam::kApnProperty] = kApn;
  userapn[flimflam::kApnUsernameProperty] = kUsername;
  {
    InSequence seq;
    EXPECT_CALL(*adaptor_,
                EmitStringmapChanged(flimflam::kCellularLastGoodApnProperty,
                                     _));
    EXPECT_CALL(*adaptor_,
                EmitStringmapChanged(flimflam::kCellularApnProperty, _));
  }
  Error error;
  service_->SetApn(userapn, &error);
  EXPECT_TRUE(service_->GetLastGoodApn() == NULL);
}

TEST_F(CellularServiceTest, IsAutoConnectable) {
  const char *reason = NULL;

  // Auto-connect should be suppressed if the device is not running.
  device_->running_ = false;
  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
  EXPECT_STREQ(CellularService::kAutoConnDeviceDisabled, reason);

  device_->running_ = true;

  // If we're waiting on a disconnect before an activation, don't auto-connect.
  GetCapabilityCDMA()->activation_starting_ = true;
  EXPECT_FALSE(service_->IsAutoConnectable(&reason));

  // If we're waiting on an activation, also don't auto-connect.
  GetCapabilityCDMA()->activation_starting_ = false;
  GetCapabilityCDMA()->activation_state_ =
      MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING;
  EXPECT_FALSE(service_->IsAutoConnectable(&reason));

  GetCapabilityCDMA()->activation_state_ =
      MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED;

  // Auto-connect should be suppressed if the we're undergoing an
  // out-of-credits detection.
  service_->out_of_credits_detection_in_progress_ = true;
  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
  EXPECT_STREQ(CellularService::kAutoConnOutOfCreditsDetectionInProgress,
               reason);

  // Auto-connect should be suppressed if we're out of credits.
  service_->out_of_credits_detection_in_progress_ = false;
  service_->out_of_credits_ = true;
  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
  EXPECT_STREQ(CellularService::kAutoConnOutOfCredits, reason);

  service_->out_of_credits_ = false;

  // But other activation states are fine.
  GetCapabilityCDMA()->activation_state_ =
      MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED;
  EXPECT_TRUE(service_->IsAutoConnectable(&reason));
  GetCapabilityCDMA()->activation_state_ =
      MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED;
  EXPECT_TRUE(service_->IsAutoConnectable(&reason));
  GetCapabilityCDMA()->activation_state_ =
      MM_MODEM_CDMA_ACTIVATION_STATE_PARTIALLY_ACTIVATED;
  EXPECT_TRUE(service_->IsAutoConnectable(&reason));

  // The following test cases are copied from ServiceTest.IsAutoConnectable

  service_->SetConnectable(true);
  EXPECT_TRUE(service_->IsAutoConnectable(&reason));

  // We should not auto-connect to a Service that a user has
  // deliberately disconnected.
  Error error;
  service_->UserInitiatedDisconnect(&error);
  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
  EXPECT_STREQ(Service::kAutoConnExplicitDisconnect, reason);

  // But if the Service is reloaded, it is eligible for auto-connect
  // again.
  NiceMock<MockStore> storage;
  EXPECT_CALL(storage, ContainsGroup(service_->GetStorageIdentifier()))
      .WillOnce(Return(true));
  EXPECT_TRUE(service_->Load(&storage));
  EXPECT_TRUE(service_->IsAutoConnectable(&reason));

  // A non-user initiated Disconnect doesn't change anything.
  service_->Disconnect(&error);
  EXPECT_TRUE(service_->IsAutoConnectable(&reason));

  // A resume also re-enables auto-connect.
  service_->UserInitiatedDisconnect(&error);
  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
  service_->OnAfterResume();
  EXPECT_TRUE(service_->IsAutoConnectable(&reason));

  service_->SetState(Service::kStateConnected);
  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
  EXPECT_STREQ(Service::kAutoConnConnected, reason);

  service_->SetState(Service::kStateAssociating);
  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
  EXPECT_STREQ(Service::kAutoConnConnecting, reason);
}

TEST_F(CellularServiceTest, OutOfCreditsDetected) {
  service_->set_enforce_out_of_credits_detection(true);
  EXPECT_CALL(*device_, Connect(_)).Times(3);
  Error error;
  service_->Connect(&error, "in test");
  service_->SetState(Service::kStateAssociating);
  service_->SetState(Service::kStateFailure);
  EXPECT_TRUE(service_->out_of_credits_detection_in_progress_);
  dispatcher_.DispatchPendingEvents();
  service_->SetState(Service::kStateConfiguring);
  service_->SetState(Service::kStateIdle);
  EXPECT_TRUE(service_->out_of_credits_detection_in_progress_);
  dispatcher_.DispatchPendingEvents();
  service_->SetState(Service::kStateConnected);
  service_->SetState(Service::kStateIdle);
  EXPECT_TRUE(service_->out_of_credits_);
  EXPECT_FALSE(service_->out_of_credits_detection_in_progress_);
}

TEST_F(CellularServiceTest, OutOfCreditsDetectionNotSkippedAfterSlowResume) {
  service_->set_enforce_out_of_credits_detection(true);
  service_->OnAfterResume();
  service_->resume_start_time_ =
      base::Time::Now() -
      base::TimeDelta::FromSeconds(
          CellularService::kOutOfCreditsResumeIgnoreSeconds + 1);
  EXPECT_CALL(*device_, Connect(_)).Times(3);
  Error error;
  service_->Connect(&error, "in test");
  service_->SetState(Service::kStateAssociating);
  service_->SetState(Service::kStateFailure);
  EXPECT_TRUE(service_->out_of_credits_detection_in_progress_);
  dispatcher_.DispatchPendingEvents();
  service_->SetState(Service::kStateConfiguring);
  service_->SetState(Service::kStateIdle);
  EXPECT_TRUE(service_->out_of_credits_detection_in_progress_);
  dispatcher_.DispatchPendingEvents();
  service_->SetState(Service::kStateConnected);
  service_->SetState(Service::kStateIdle);
  EXPECT_TRUE(service_->out_of_credits_);
  EXPECT_FALSE(service_->out_of_credits_detection_in_progress_);
}

TEST_F(CellularServiceTest, OutOfCreditsDetectionSkippedAfterResume) {
  service_->set_enforce_out_of_credits_detection(true);
  service_->OnAfterResume();
  EXPECT_CALL(*device_, Connect(_));
  Error error;
  service_->Connect(&error, "in test");
  service_->SetState(Service::kStateConnected);
  service_->SetState(Service::kStateIdle);
  EXPECT_FALSE(service_->out_of_credits_);
  EXPECT_FALSE(service_->out_of_credits_detection_in_progress_);
  // There should not be any pending connect requests but dispatch pending
  // events anyway to be sure.
  dispatcher_.DispatchPendingEvents();
}

TEST_F(CellularServiceTest, OutOfCreditsDetectionSkippedAlreadyOutOfCredits) {
  service_->set_enforce_out_of_credits_detection(true);
  EXPECT_CALL(*device_, Connect(_));
  Error error;
  service_->Connect(&error, "in test");
  service_->out_of_credits_ = true;
  service_->SetState(Service::kStateConnected);
  service_->SetState(Service::kStateIdle);
  EXPECT_FALSE(service_->out_of_credits_detection_in_progress_);
  // There should not be any pending connect requests but dispatch pending
  // events anyway to be sure.
  dispatcher_.DispatchPendingEvents();
}

TEST_F(CellularServiceTest, OutOfCreditsDetectionSkippedExplicitDisconnect) {
  service_->set_enforce_out_of_credits_detection(true);
  EXPECT_CALL(*device_, Connect(_));
  Error error;
  service_->Connect(&error, "in test");
  service_->SetState(Service::kStateConnected);
  service_->UserInitiatedDisconnect(&error);
  service_->SetState(Service::kStateIdle);
  EXPECT_FALSE(service_->out_of_credits_);
  EXPECT_FALSE(service_->out_of_credits_detection_in_progress_);
  // There should not be any pending connect requests but dispatch pending
  // events anyway to be sure.
  dispatcher_.DispatchPendingEvents();
}

TEST_F(CellularServiceTest, OutOfCreditsNotDetectedConnectionNotDropped) {
  service_->set_enforce_out_of_credits_detection(true);
  EXPECT_CALL(*device_, Connect(_));
  Error error;
  service_->Connect(&error, "in test");
  service_->SetState(Service::kStateAssociating);
  service_->SetState(Service::kStateConfiguring);
  service_->SetState(Service::kStateConnected);
  EXPECT_FALSE(service_->out_of_credits_);
  EXPECT_FALSE(service_->out_of_credits_detection_in_progress_);
  // There should not be any pending connect requests but dispatch pending
  // events anyway to be sure.
  dispatcher_.DispatchPendingEvents();
}

TEST_F(CellularServiceTest, OutOfCreditsNotDetectedIntermittentNetwork) {
  service_->set_enforce_out_of_credits_detection(true);
  EXPECT_CALL(*device_, Connect(_));
  Error error;
  service_->Connect(&error, "in test");
  service_->SetState(Service::kStateConnected);
  service_->connect_start_time_ =
      base::Time::Now() -
      base::TimeDelta::FromSeconds(
          CellularService::kOutOfCreditsConnectionDropSeconds + 1);
  service_->SetState(Service::kStateIdle);
  EXPECT_FALSE(service_->out_of_credits_);
  EXPECT_FALSE(service_->out_of_credits_detection_in_progress_);
  // There should not be any pending connect requests but dispatch pending
  // events anyway to be sure.
  dispatcher_.DispatchPendingEvents();
}

TEST_F(CellularServiceTest, OutOfCreditsNotEnforced) {
  EXPECT_CALL(*device_, Connect(_));
  Error error;
  service_->Connect(&error, "in test");
  service_->SetState(Service::kStateConnected);
  service_->SetState(Service::kStateIdle);
  EXPECT_FALSE(service_->out_of_credits_);
  EXPECT_FALSE(service_->out_of_credits_detection_in_progress_);
  // There should not be any pending connect requests but dispatch pending
  // events anyway to be sure.
  dispatcher_.DispatchPendingEvents();
}

// Some of these tests duplicate signals tested above. However, it's
// convenient to have all the property change notifications documented
// (and tested) in one place.
TEST_F(CellularServiceTest, PropertyChanges) {
  TestCommonPropertyChanges(service_, adaptor_);
  TestAutoConnectPropertyChange(service_, adaptor_);

  bool activate_over_non_cellular =
      service_->activate_over_non_cellular_network();
  EXPECT_CALL(*adaptor_,
              EmitBoolChanged(kActivateOverNonCellularNetworkProperty, _));
  service_->SetActivateOverNonCellularNetwork(!activate_over_non_cellular);
  Mock::VerifyAndClearExpectations(adaptor_);

  EXPECT_NE(flimflam::kActivationStateNotActivated,
            service_->activation_state());
  EXPECT_CALL(*adaptor_,
              EmitStringChanged(flimflam::kActivationStateProperty, _));
  service_->SetActivationState(flimflam::kActivationStateNotActivated);
  Mock::VerifyAndClearExpectations(adaptor_);

  string network_technology = service_->network_technology();
  EXPECT_CALL(*adaptor_,
              EmitStringChanged(flimflam::kNetworkTechnologyProperty, _));
  service_->SetNetworkTechnology(network_technology + "and some new stuff");
  Mock::VerifyAndClearExpectations(adaptor_);

  bool out_of_credits = service_->out_of_credits();
  EXPECT_CALL(*adaptor_, EmitBoolChanged(kOutOfCreditsProperty, _));
  service_->SetOutOfCredits(!out_of_credits);
  Mock::VerifyAndClearExpectations(adaptor_);

  string roaming_state = service_->roaming_state();
  EXPECT_CALL(*adaptor_,
              EmitStringChanged(flimflam::kRoamingStateProperty, _));
  service_->SetRoamingState(roaming_state + "and some new stuff");
  Mock::VerifyAndClearExpectations(adaptor_);
}

// Custom property setters should return false, and make no changes, if
// the new value is the same as the old value.
TEST_F(CellularServiceTest, CustomSetterNoopChange) {
  // Test that we didn't break any setters provided by the base class.
  TestCustomSetterNoopChange(service_, modem_info_.mock_manager());

  // Test the new setter we added.
  // First set up our environment...
  static const char kApn[] = "TheAPN";
  static const char kUsername[] = "commander.data";
  Error error;
  Stringmap testapn;
  ProfileRefPtr profile(new NiceMock<MockProfile>(nullptr, nullptr, nullptr));
  service_->set_profile(profile);
  testapn[flimflam::kApnProperty] = kApn;
  testapn[flimflam::kApnUsernameProperty] = kUsername;
  // ... then set to a known value ...
  EXPECT_TRUE(service_->SetApn(testapn, &error));
  EXPECT_TRUE(error.IsSuccess());
  // ... then set to same value.
  EXPECT_FALSE(service_->SetApn(testapn, &error));
  EXPECT_TRUE(error.IsSuccess());
}

}  // namespace shill
