// Copyright 2018 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/cellular_service.h"

#include <chromeos/dbus/service_constants.h>
#include <gtest/gtest.h>

#include "shill/cellular/cellular_capability.h"
#include "shill/cellular/mock_cellular.h"
#include "shill/cellular/mock_mobile_operator_info.h"
#include "shill/cellular/mock_modem_info.h"
#include "shill/fake_store.h"
#include "shill/mock_adaptors.h"
#include "shill/mock_control.h"
#include "shill/mock_manager.h"
#include "shill/mock_metrics.h"
#include "shill/mock_profile.h"
#include "shill/service_property_change_test.h"

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

namespace shill {

namespace {
const char kImsi[] = "111222123456789";
const char kIccid[] = "1234567890000";
}  // namespace

class CellularServiceTest : public testing::Test {
 public:
  CellularServiceTest()
      : manager_(&control_, &dispatcher_, &metrics_),
        modem_info_(&control_, &manager_),
        adaptor_(nullptr) {
    Service::SetNextSerialNumberForTesting(0);
  }
  ~CellularServiceTest() override { adaptor_ = nullptr; }

  void SetUp() override {
    // Many tests set service properties which call Manager.UpdateService().
    EXPECT_CALL(manager_, UpdateService(_)).Times(AnyNumber());
    device_ = new MockCellular(&modem_info_, "usb0", kAddress, 3,
                               Cellular::kTypeCdma, "", RpcIdentifier(""));
    // CellularService expects an IMSI and SIM ID be set in the Device.
    device_->set_imsi(kImsi);
    device_->set_iccid(kIccid);
    service_ =
        new CellularService(&manager_, kImsi, kIccid, device_->GetSimCardId());
    service_->SetDevice(device_.get());
    adaptor_ = static_cast<ServiceMockAdaptor*>(service_->adaptor());

    storage_id_ = service_->GetStorageIdentifier();
    storage_.SetString(storage_id_, CellularService::kStorageType,
                       kTypeCellular);
    storage_.SetString(storage_id_, CellularService::kStorageIccid, kIccid);
    storage_.SetString(storage_id_, CellularService::kStorageImsi, kImsi);
  }

 protected:
  static const char kAddress[];

  string GetFriendlyName() const { return service_->friendly_name(); }
  bool IsAutoConnectable(const char** reason) const {
    return service_->IsAutoConnectable(reason);
  }
  bool SetAutoConnectFull(bool connect) {
    return service_->SetAutoConnectFull(connect, /*error=*/nullptr);
  }

  EventDispatcher dispatcher_;
  NiceMock<MockControl> control_;
  MockMetrics metrics_;
  NiceMock<MockManager> manager_;
  MockModemInfo modem_info_;
  scoped_refptr<MockCellular> device_;
  CellularServiceRefPtr service_;
  ServiceMockAdaptor* adaptor_;  // Owned by |service_|.
  std::string storage_id_;
  FakeStore storage_;
};

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

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

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

TEST_F(CellularServiceTest, LogName) {
  EXPECT_EQ("cellular_0", service_->log_name());
  service_->SetNetworkTechnology(kNetworkTechnologyUmts);
  EXPECT_EQ("cellular_UMTS_0", service_->log_name());
  service_->SetNetworkTechnology(kNetworkTechnologyGsm);
  EXPECT_EQ("cellular_GSM_0", service_->log_name());
  service_->SetNetworkTechnology(kNetworkTechnologyLte);
  EXPECT_EQ("cellular_LTE_0", service_->log_name());
}

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

TEST_F(CellularServiceTest, SetServingOperator) {
  static const char kCode[] = "123456";
  static const char kName[] = "Some Cellular Operator";
  Stringmap test_operator;
  service_->SetServingOperator(test_operator);
  test_operator[kOperatorCodeKey] = kCode;
  test_operator[kOperatorNameKey] = kName;
  EXPECT_CALL(*adaptor_, EmitStringmapChanged(kServingOperatorProperty, _));
  service_->SetServingOperator(test_operator);
  const Stringmap& serving_operator = service_->serving_operator();
  ASSERT_NE(serving_operator.end(), serving_operator.find(kOperatorCodeKey));
  ASSERT_NE(serving_operator.end(), serving_operator.find(kOperatorNameKey));
  EXPECT_EQ(kCode, serving_operator.find(kOperatorCodeKey)->second);
  EXPECT_EQ(kName, serving_operator.find(kOperatorNameKey)->second);
  Mock::VerifyAndClearExpectations(adaptor_);
  EXPECT_CALL(*adaptor_, EmitStringmapChanged(kServingOperatorProperty, _))
      .Times(0);
  service_->SetServingOperator(serving_operator);
}

TEST_F(CellularServiceTest, SetOLP) {
  const char kMethod[] = "GET";
  const char kURL[] = "payment.url";
  const char kPostData[] = "post_man";
  Stringmap olp;

  service_->SetOLP("", "", "");
  olp = service_->olp();  // Copy to simplify assertions below.
  EXPECT_EQ("", olp[kPaymentPortalURL]);
  EXPECT_EQ("", olp[kPaymentPortalMethod]);
  EXPECT_EQ("", olp[kPaymentPortalPostData]);

  EXPECT_CALL(*adaptor_, EmitStringmapChanged(kPaymentPortalProperty, _));
  service_->SetOLP(kURL, kMethod, kPostData);
  olp = service_->olp();  // Copy to simplify assertions below.
  EXPECT_EQ(kURL, olp[kPaymentPortalURL]);
  EXPECT_EQ(kMethod, olp[kPaymentPortalMethod]);
  EXPECT_EQ(kPostData, olp[kPaymentPortalPostData]);
}

TEST_F(CellularServiceTest, SetUsageURL) {
  static const char kUsageURL[] = "usage.url";
  EXPECT_CALL(*adaptor_, EmitStringChanged(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>(&manager_));
  service_->set_profile(profile);
  Error error;
  Stringmap testapn;
  testapn[kApnProperty] = kApn;
  testapn[kApnUsernameProperty] = kUsername;
  EXPECT_CALL(*adaptor_, EmitStringmapChanged(kCellularApnProperty, _));
  service_->SetApn(testapn, &error);
  EXPECT_TRUE(error.IsSuccess());
  Stringmap resultapn = service_->GetApn(&error);
  EXPECT_TRUE(error.IsSuccess());
  Stringmap::const_iterator it = resultapn.find(kApnProperty);
  EXPECT_TRUE(it != resultapn.end() && it->second == kApn);
  it = resultapn.find(kApnUsernameProperty);
  EXPECT_TRUE(it != resultapn.end() && it->second == kUsername);
  EXPECT_NE(nullptr, service_->GetUserSpecifiedApn());
}

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

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

TEST_F(CellularServiceTest, LastGoodApn) {
  static const char kApn[] = "TheAPN";
  static const char kUsername[] = "commander.data";
  ProfileRefPtr profile(new NiceMock<MockProfile>(&manager_));
  service_->set_profile(profile);
  Stringmap testapn;
  testapn[kApnProperty] = kApn;
  testapn[kApnUsernameProperty] = kUsername;
  EXPECT_CALL(*adaptor_, EmitStringmapChanged(kCellularLastGoodApnProperty, _));
  service_->SetLastGoodApn(testapn);
  Stringmap* resultapn = service_->GetLastGoodApn();
  ASSERT_NE(nullptr, resultapn);
  EXPECT_EQ(kApn, (*resultapn)[kApnProperty]);
  EXPECT_EQ(kUsername, (*resultapn)[kApnUsernameProperty]);

  // Now set the user-specified APN, and check that LastGoodApn is preserved.
  Stringmap userapn;
  userapn[kApnProperty] = kApn;
  userapn[kApnUsernameProperty] = kUsername;
  EXPECT_CALL(*adaptor_, EmitStringmapChanged(kCellularApnProperty, _));
  Error error;
  service_->SetApn(userapn, &error);

  ASSERT_NE(nullptr, service_->GetLastGoodApn());
  EXPECT_EQ(kApn, (*resultapn)[kApnProperty]);
  EXPECT_EQ(kUsername, (*resultapn)[kApnUsernameProperty]);
}

TEST_F(CellularServiceTest, IsAutoConnectable) {
  // This test assumes AutoConnect is not disabled by policy.
  EXPECT_CALL(manager_, IsTechnologyAutoConnectDisabled(_))
      .WillRepeatedly(Return(false));

  const char* reason = nullptr;

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

  device_->running_ = true;

  // If we're in a process of activation, don't auto-connect.
  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
              GetActivationState(_, _))
      .WillOnce(Return(PendingActivationStore::kStatePending));
  EXPECT_FALSE(IsAutoConnectable(&reason));
  EXPECT_STREQ(CellularService::kAutoConnActivating, reason);
  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
              GetActivationState(_, _))
      .WillRepeatedly(Return(PendingActivationStore::kStateActivated));

  // Auto-connect should be suppressed if we're out of credits.
  service_->NotifySubscriptionStateChanged(SubscriptionState::kOutOfCredits);
  EXPECT_FALSE(IsAutoConnectable(&reason));
  EXPECT_STREQ(CellularService::kAutoConnOutOfCredits, reason);
  service_->NotifySubscriptionStateChanged(SubscriptionState::kProvisioned);

  // A PPP authentication failure means the Service is not auto-connectable.
  service_->SetFailure(Service::kFailurePPPAuth);
  EXPECT_FALSE(IsAutoConnectable(&reason));
  EXPECT_STREQ(CellularService::kAutoConnBadPPPCredentials, reason);

  // Reset failure state, to make the Service auto-connectable again.
  service_->SetState(Service::kStateIdle);
  EXPECT_TRUE(IsAutoConnectable(&reason));

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

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

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

  // If the Service is reloaded, it is eligible for auto-connect again.
  EXPECT_TRUE(service_->Load(&storage_));
  EXPECT_TRUE(IsAutoConnectable(&reason));

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

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

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

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

TEST_F(CellularServiceTest, LoadResetsPPPAuthFailure) {
  const string kDefaultUser;
  const string kDefaultPass;
  const string kNewUser("new-username");
  const string kNewPass("new-password");
  for (const auto change_username : {false, true}) {
    for (const auto change_password : {false, true}) {
      service_->ppp_username_ = kDefaultUser;
      service_->ppp_password_ = kDefaultPass;
      service_->SetFailure(Service::kFailurePPPAuth);
      EXPECT_TRUE(service_->IsFailed());
      EXPECT_EQ(Service::kFailurePPPAuth, service_->failure());
      if (change_username) {
        storage_.SetString(storage_id_, CellularService::kStoragePPPUsername,
                           kNewUser);
      }
      if (change_password) {
        storage_.SetString(storage_id_, CellularService::kStoragePPPPassword,
                           kNewPass);
      }
      EXPECT_TRUE(service_->Load(&storage_));
      if (change_username || change_password) {
        EXPECT_NE(Service::kFailurePPPAuth, service_->failure());
      } else {
        EXPECT_EQ(Service::kFailurePPPAuth, service_->failure());
      }
    }
  }
}

// The default storage_identifier_ will be {kCellular}_{kIccid}, however older
// profile/storage entries may use a different identifier. This sets up an entry
// with a matching ICCID but an arbitrary storage id and ensures that the older
// storage_identifer_ value is set.
TEST_F(CellularServiceTest, LoadFromProfileMatchingIccid) {
  string initial_storage_id = storage_id_;
  string matching_storage_id = "another-storage-id";
  storage_.DeleteGroup(initial_storage_id);
  storage_.SetString(matching_storage_id, CellularService::kStorageType,
                     kTypeCellular);
  storage_.SetString(matching_storage_id, CellularService::kStorageIccid,
                     kIccid);
  storage_.SetString(matching_storage_id, CellularService::kStorageImsi, kImsi);

  EXPECT_TRUE(service_->IsLoadableFrom(storage_));
  EXPECT_TRUE(service_->Load(&storage_));
  EXPECT_EQ(matching_storage_id, service_->GetStorageIdentifier());
}

TEST_F(CellularServiceTest, LoadFromFirstOfMultipleMatchingProfiles) {
  string initial_storage_id = storage_id_;
  string matching_storage_ids[] = {"another-storage-id1", "another-storage-id2",
                                   "another-storage-id3"};
  storage_.DeleteGroup(initial_storage_id);
  for (auto& matching_storage_id : matching_storage_ids) {
    storage_.SetString(matching_storage_id, CellularService::kStorageType,
                       kTypeCellular);
    storage_.SetString(matching_storage_id, CellularService::kStorageIccid,
                       kIccid);
    storage_.SetString(matching_storage_id, CellularService::kStorageImsi,
                       kImsi);
  }
  EXPECT_TRUE(service_->IsLoadableFrom(storage_));
  EXPECT_TRUE(service_->Load(&storage_));
  EXPECT_EQ(matching_storage_ids[0], service_->GetStorageIdentifier());
}

TEST_F(CellularServiceTest, Save) {
  EXPECT_TRUE(service_->Save(&storage_));
  std::string iccid;
  EXPECT_TRUE(
      storage_.GetString(storage_id_, CellularService::kStorageIccid, &iccid));
  EXPECT_EQ(iccid, device_->iccid());
}

TEST_F(CellularServiceTest, SaveAndLoadApn) {
  static const char kApn[] = "petal.net";
  static const char kUsername[] = "orekid";
  static const char kPassword[] = "arlet";
  static const char kAuthentication[] = "chap";

  Error error;
  Stringmap testapn;
  testapn[kApnProperty] = kApn;
  testapn[kApnUsernameProperty] = kUsername;
  testapn[kApnPasswordProperty] = kPassword;
  testapn[kApnAuthenticationProperty] = kAuthentication;
  service_->SetApn(testapn, &error);
  ASSERT_TRUE(error.IsSuccess());
  EXPECT_TRUE(service_->Save(&storage_));

  // Clear the APN, and then load it from storage again.
  Stringmap emptyapn;
  service_->SetApn(emptyapn, &error);
  ASSERT_TRUE(error.IsSuccess());

  EXPECT_TRUE(service_->Load(&storage_));

  Stringmap resultapn = service_->GetApn(&error);
  EXPECT_TRUE(error.IsSuccess());
  EXPECT_EQ(kApn, resultapn[kApnProperty]);
  EXPECT_EQ(kUsername, resultapn[kApnUsernameProperty]);
  EXPECT_EQ(kPassword, resultapn[kApnPasswordProperty]);
  EXPECT_EQ(kAuthentication, resultapn[kApnAuthenticationProperty]);
}

TEST_F(CellularServiceTest, IgnoreUnversionedLastGoodApn) {
  static const char kApn[] = "petal.net";
  static const char kUsername[] = "orekid";
  Stringmap testapn;
  testapn[kApnProperty] = kApn;
  testapn[kApnUsernameProperty] = kUsername;
  service_->SetLastGoodApn(testapn);
  ASSERT_TRUE(service_->Save(&storage_));

  // Now clear the LastGoodAPN and try to load it. It should be ignored.
  service_->ClearLastGoodApn();
  ASSERT_TRUE(service_->Load(&storage_));
  Stringmap* resultapn = service_->GetLastGoodApn();
  EXPECT_EQ(nullptr, resultapn);
}

TEST_F(CellularServiceTest, MergeDetailsFromApnList) {
  static const char kApn[] = "petal.net";
  static const char kUsername[] = "orekid";
  static const char kPassword[] = "arlet";
  static const char kAuthentication[] = "chap";
  Stringmap fullapn;
  fullapn[kApnProperty] = kApn;
  fullapn[kApnUsernameProperty] = kUsername;
  fullapn[kApnPasswordProperty] = kPassword;
  fullapn[kApnAuthenticationProperty] = kAuthentication;
  Stringmaps apn_list{fullapn};
  device_->set_apn_list(apn_list);

  // Just set an APN with only the name. Check that we are using
  // the rest of the details.
  Error error;
  Stringmap testapn;
  testapn[kApnProperty] = kApn;
  service_->SetApn(testapn, &error);

  Stringmap resultapn = service_->GetApn(&error);
  EXPECT_TRUE(error.IsSuccess());
  EXPECT_EQ(kApn, resultapn[kApnProperty]);
  EXPECT_EQ(kUsername, resultapn[kApnUsernameProperty]);
  EXPECT_EQ(kPassword, resultapn[kApnPasswordProperty]);
  EXPECT_EQ(kAuthentication, resultapn[kApnAuthenticationProperty]);
}

// 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_);

  EXPECT_CALL(*adaptor_, EmitStringChanged(kActivationTypeProperty, _));
  service_->SetActivationType(CellularService::kActivationTypeOTA);
  Mock::VerifyAndClearExpectations(adaptor_);

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

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

  EXPECT_CALL(*adaptor_, EmitBoolChanged(kOutOfCreditsProperty, true));
  service_->NotifySubscriptionStateChanged(SubscriptionState::kOutOfCredits);
  Mock::VerifyAndClearExpectations(adaptor_);
  EXPECT_CALL(*adaptor_, EmitBoolChanged(kOutOfCreditsProperty, false));
  service_->NotifySubscriptionStateChanged(SubscriptionState::kProvisioned);
  Mock::VerifyAndClearExpectations(adaptor_);

  string roaming_state = service_->roaming_state();
  EXPECT_CALL(*adaptor_, EmitStringChanged(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_, &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));
  service_->set_profile(profile);
  testapn[kApnProperty] = kApn;
  testapn[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());
}

TEST_F(CellularServiceTest, IsMeteredByDefault) {
  // These services should be metered by default.
  EXPECT_TRUE(service_->IsMetered());
}

TEST_F(CellularServiceTest, SetActivationState) {
  // SetActivationState should emit a change.
  EXPECT_CALL(*adaptor_, EmitStringChanged(kActivationStateProperty,
                                           kActivationStateNotActivated));
  service_->SetActivationState(kActivationStateNotActivated);
  EXPECT_EQ(service_->activation_state(), kActivationStateNotActivated);
  EXPECT_CALL(*adaptor_, EmitStringChanged(kActivationStateProperty, _))
      .Times(AnyNumber());

  // Setting the activation state to activated should also set AutoConnect.
  EXPECT_FALSE(service_->auto_connect());
  service_->SetActivationState(kActivationStateActivated);
  EXPECT_EQ(service_->activation_state(), kActivationStateActivated);
  EXPECT_TRUE(service_->auto_connect());

  // After a client sets AutoConnect to false, setting the activation state to
  // activated should not set AutoConnect.
  SetAutoConnectFull(false);
  EXPECT_FALSE(service_->auto_connect());
  service_->SetActivationState(kActivationStateNotActivated);
  EXPECT_EQ(service_->activation_state(), kActivationStateNotActivated);
  EXPECT_FALSE(service_->auto_connect());
  service_->SetActivationState(kActivationStateActivated);
  EXPECT_EQ(service_->activation_state(), kActivationStateActivated);
  EXPECT_FALSE(service_->auto_connect());
}

}  // namespace shill
