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