| // 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/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/mock_store.h" |
| #include "shill/service_property_change_test.h" |
| |
| using std::string; |
| using testing::_; |
| using testing::AnyNumber; |
| using testing::InSequence; |
| using testing::Mock; |
| using testing::NiceMock; |
| using testing::Return; |
| using testing::SetArgPointee; |
| using testing::StrEq; |
| |
| namespace shill { |
| |
| namespace { |
| const char kImsi[] = "111222123456789"; |
| const char kIccid[] = "1234567890000"; |
| } // namespace |
| |
| MATCHER_P2(ContainsCellularProperties, key, value, "") { |
| return arg.template Contains<string>(CellularService::kStorageType) && |
| arg.template Get<string>(CellularService::kStorageType) == |
| kTypeCellular && |
| arg.template Contains<string>(key) && |
| arg.template Get<string>(key) == value; |
| } |
| |
| class CellularServiceTest : public testing::Test { |
| public: |
| CellularServiceTest() |
| : modem_info_(nullptr, &dispatcher_, nullptr, nullptr), |
| adaptor_(nullptr) { |
| Service::SetNextSerialNumberForTesting(0); |
| // Many tests set service properties which call Manager.UpdateService(). |
| EXPECT_CALL(*modem_info_.mock_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(modem_info_.manager(), kImsi, kIccid, |
| device_->GetSimCardId()); |
| service_->SetDevice(device_.get()); |
| } |
| ~CellularServiceTest() override { adaptor_ = nullptr; } |
| |
| void SetUp() override { |
| adaptor_ = static_cast<ServiceMockAdaptor*>(service_->adaptor()); |
| } |
| |
| 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, 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>(modem_info_.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()); |
| EXPECT_EQ(2, resultapn.size()); |
| 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>(modem_info_.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()); |
| ASSERT_EQ(2, service_->GetApn(&error).size()); |
| |
| 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>(modem_info_.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(2, resultapn->size()); |
| 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(2, resultapn->size()); |
| 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(*modem_info_.mock_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(service_->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(service_->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(service_->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(service_->IsAutoConnectable(&reason)); |
| EXPECT_STREQ(CellularService::kAutoConnBadPPPCredentials, reason); |
| |
| // Reset failure state, to make the Service auto-connectable again. |
| service_->SetState(Service::kStateIdle); |
| 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("RPC", &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(_)).WillRepeatedly(Return(true)); |
| EXPECT_CALL(storage, GetString(_, _, _)).WillRepeatedly(Return(true)); |
| EXPECT_CALL(storage, GetGroupsWithProperties(ContainsCellularProperties( |
| CellularService::kStorageImsi, device_->imsi()))) |
| .WillRepeatedly(Return(std::set<string>{"matching-storage-id"})); |
| EXPECT_TRUE(service_->Load(&storage)); |
| EXPECT_TRUE(service_->IsAutoConnectable(&reason)); |
| |
| // A non-user initiated Disconnect doesn't change anything. |
| service_->Disconnect(&error, "in test"); |
| EXPECT_TRUE(service_->IsAutoConnectable(&reason)); |
| |
| // A resume also re-enables auto-connect. |
| service_->UserInitiatedDisconnect("RPC", &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, LoadResetsPPPAuthFailure) { |
| NiceMock<MockStore> storage; |
| EXPECT_CALL(storage, ContainsGroup(_)).WillRepeatedly(Return(true)); |
| EXPECT_CALL(storage, GetString(_, _, _)).WillRepeatedly(Return(true)); |
| EXPECT_CALL(storage, GetGroupsWithProperties(ContainsCellularProperties( |
| CellularService::kStorageImsi, device_->imsi()))) |
| .WillRepeatedly(Return(std::set<string>{"matching-storage-id"})); |
| |
| 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) { |
| EXPECT_CALL(storage, |
| GetString(_, CellularService::kStoragePPPUsername, _)) |
| .WillOnce(DoAll(SetArgPointee<2>(kNewUser), Return(true))) |
| .RetiresOnSaturation(); |
| } |
| if (change_password) { |
| EXPECT_CALL(storage, |
| GetString(_, CellularService::kStoragePPPPassword, _)) |
| .WillOnce(DoAll(SetArgPointee<2>(kNewPass), Return(true))) |
| .RetiresOnSaturation(); |
| } |
| EXPECT_TRUE(service_->Load(&storage)); |
| if (change_username || change_password) { |
| EXPECT_NE(Service::kFailurePPPAuth, service_->failure()); |
| } else { |
| EXPECT_EQ(Service::kFailurePPPAuth, service_->failure()); |
| } |
| } |
| } |
| } |
| |
| TEST_F(CellularServiceTest, LoadFromProfileMatchingImsi) { |
| NiceMock<MockStore> storage; |
| string initial_storage_id = service_->GetStorageIdentifier(); |
| string matching_storage_id = "another-storage-id"; |
| std::set<string> groups = {matching_storage_id}; |
| EXPECT_CALL(storage, ContainsGroup(initial_storage_id)).Times(0); |
| EXPECT_CALL(storage, ContainsGroup(matching_storage_id)) |
| .WillOnce(Return(true)); |
| EXPECT_CALL(storage, GetGroupsWithProperties(ContainsCellularProperties( |
| CellularService::kStorageImsi, device_->imsi()))) |
| .WillRepeatedly(Return(groups)); |
| EXPECT_CALL(storage, GetString(_, _, _)).WillRepeatedly(Return(true)); |
| EXPECT_TRUE(service_->IsLoadableFrom(storage)); |
| EXPECT_TRUE(service_->Load(&storage)); |
| EXPECT_EQ(matching_storage_id, service_->GetStorageIdentifier()); |
| } |
| |
| TEST_F(CellularServiceTest, LoadFromFirstOfMultipleMatchingProfiles) { |
| NiceMock<MockStore> storage; |
| string initial_storage_id = service_->GetStorageIdentifier(); |
| string matching_storage_id1 = "another-storage-id1"; |
| string matching_storage_id2 = "another-storage-id2"; |
| string matching_storage_id3 = "another-storage-id3"; |
| std::set<string> groups = { |
| matching_storage_id1, |
| matching_storage_id2, |
| matching_storage_id3, |
| }; |
| EXPECT_CALL(storage, ContainsGroup(initial_storage_id)).Times(0); |
| EXPECT_CALL(storage, ContainsGroup(matching_storage_id1)) |
| .WillOnce(Return(true)); |
| EXPECT_CALL(storage, GetGroupsWithProperties(ContainsCellularProperties( |
| CellularService::kStorageImsi, device_->imsi()))) |
| .WillRepeatedly(Return(groups)); |
| EXPECT_CALL(storage, GetString(_, _, _)).WillRepeatedly(Return(true)); |
| EXPECT_TRUE(service_->IsLoadableFrom(storage)); |
| EXPECT_TRUE(service_->Load(&storage)); |
| EXPECT_EQ(matching_storage_id1, service_->GetStorageIdentifier()); |
| } |
| |
| // The default storage_identifier_ will be {kCellular}_{kImsi}, however older |
| // profile/storage entries may use a different identifier. This sets up an entry |
| // with a matching IMSI but an arbitrary storage id and ensures that the older |
| // storage_identifer_ value is set. |
| TEST_F(CellularServiceTest, LoadFromOlderProfile) { |
| NiceMock<MockStore> storage; |
| string storage_id = "arbitrary-storage-id"; |
| std::set<string> groups = {storage_id}; |
| |
| EXPECT_CALL(storage, GetGroupsWithProperties(ContainsCellularProperties( |
| CellularService::kStorageImsi, kImsi))) |
| .WillRepeatedly(Return(groups)); |
| EXPECT_CALL(storage, ContainsGroup(storage_id)).WillRepeatedly(Return(true)); |
| |
| EXPECT_TRUE(service_->IsLoadableFrom(storage)); |
| EXPECT_TRUE(service_->Load(&storage)); |
| EXPECT_EQ(storage_id, service_->GetStorageIdentifier()); |
| } |
| |
| TEST_F(CellularServiceTest, Save) { |
| NiceMock<MockStore> storage; |
| EXPECT_CALL(storage, SetString(_, _, _)).WillRepeatedly(Return(true)); |
| EXPECT_CALL(storage, SetString(service_->GetStorageIdentifier(), |
| StrEq(Service::kStorageType), kTypeCellular)) |
| .Times(1); |
| EXPECT_CALL(storage, |
| SetString(service_->GetStorageIdentifier(), |
| StrEq(CellularService::kStorageImsi), device_->imsi())) |
| .Times(1); |
| EXPECT_CALL(storage, SetString(service_->GetStorageIdentifier(), |
| StrEq(CellularService::kStorageIccid), |
| device_->iccid())) |
| .Times(1); |
| EXPECT_TRUE(service_->Save(&storage)); |
| } |
| |
| // 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_, 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)); |
| 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()); |
| } |
| |
| } // namespace shill |