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/wimax/wimax_service.h"
18
19 #include <string>
20
21 #include <base/strings/string_util.h>
22 #if defined(__ANDROID__)
23 #include <dbus/service_constants.h>
24 #else
25 #include <chromeos/dbus/service_constants.h>
26 #endif // __ANDROID__
27 #include <gtest/gtest.h>
28
29 #include "shill/error.h"
30 #include "shill/mock_adaptors.h"
31 #include "shill/mock_eap_credentials.h"
32 #include "shill/mock_manager.h"
33 #include "shill/mock_metrics.h"
34 #include "shill/mock_store.h"
35 #include "shill/nice_mock_control.h"
36 #include "shill/service_property_change_test.h"
37 #include "shill/wimax/mock_wimax.h"
38 #include "shill/wimax/mock_wimax_network_proxy.h"
39 #include "shill/wimax/mock_wimax_provider.h"
40
41 using std::string;
42 using testing::_;
43 using testing::AnyNumber;
44 using testing::Mock;
45 using testing::NiceMock;
46 using testing::Return;
47 using wimax_manager::kEAPAnonymousIdentity;
48 using wimax_manager::kEAPUserIdentity;
49 using wimax_manager::kEAPUserPassword;
50
51 namespace shill {
52
53 namespace {
54
55 const char kTestLinkName[] = "wm0";
56 const char kTestAddress[] = "0123456789AB";
57 const int kTestInterfaceIndex = 5;
58 const char kTestPath[] = "/org/chromium/WiMaxManager/Device/wm7";
59 const char kTestName[] = "Test WiMAX Network";
60 const char kTestNetworkId[] = "1234abcd";
61
62 } // namespace
63
64 class WiMaxServiceTest : public testing::Test {
65 public:
WiMaxServiceTest()66 WiMaxServiceTest()
67 : proxy_(new MockWiMaxNetworkProxy()),
68 manager_(&control_, nullptr, nullptr),
69 metrics_(nullptr),
70 device_(new MockWiMax(&control_, nullptr, &metrics_, &manager_,
71 kTestLinkName, kTestAddress, kTestInterfaceIndex,
72 kTestPath)),
73 service_(new WiMaxService(&control_, nullptr, &metrics_, &manager_)),
74 eap_(new MockEapCredentials()) {
75 service_->set_friendly_name(kTestName);
76 service_->set_network_id(kTestNetworkId);
77 service_->InitStorageIdentifier();
78 service_->eap_.reset(eap_); // Passes ownership.
79 }
80
~WiMaxServiceTest()81 virtual ~WiMaxServiceTest() {}
82
83 protected:
TearDown()84 virtual void TearDown() {
85 service_->device_ = nullptr;
86 }
87
ExpectUpdateService()88 void ExpectUpdateService() {
89 EXPECT_CALL(manager_, HasService(_)).WillOnce(Return(true));
90 EXPECT_CALL(manager_, UpdateService(_));
91 }
92
SetConnectable(bool connectable)93 void SetConnectable(bool connectable) {
94 service_->connectable_ = connectable;
95 }
96
SetDevice(WiMaxRefPtr device)97 void SetDevice(WiMaxRefPtr device) {
98 service_->SetDevice(device);
99 }
100
GetAdaptor()101 ServiceMockAdaptor* GetAdaptor() {
102 return static_cast<ServiceMockAdaptor*>(service_->adaptor());
103 }
104
105 std::unique_ptr<MockWiMaxNetworkProxy> proxy_;
106 NiceMockControl control_;
107 MockManager manager_;
108 NiceMock<MockMetrics> metrics_;
109 scoped_refptr<MockWiMax> device_;
110 WiMaxServiceRefPtr service_;
111 MockEapCredentials* eap_; // Owned by |service_|.
112 };
113
TEST_F(WiMaxServiceTest,GetConnectParameters)114 TEST_F(WiMaxServiceTest, GetConnectParameters) {
115 KeyValueStore parameters;
116 EXPECT_CALL(*eap_, PopulateWiMaxProperties(¶meters));
117 service_->GetConnectParameters(¶meters);
118 }
119
TEST_F(WiMaxServiceTest,GetDeviceRpcId)120 TEST_F(WiMaxServiceTest, GetDeviceRpcId) {
121 Error error;
122 EXPECT_EQ(control_.NullRPCIdentifier(), service_->GetDeviceRpcId(&error));
123 EXPECT_EQ(Error::kNotFound, error.type());
124 service_->device_ = device_;
125 error.Reset();
126 EXPECT_EQ(DeviceMockAdaptor::kRpcId, service_->GetDeviceRpcId(&error));
127 EXPECT_TRUE(error.IsSuccess());
128 }
129
TEST_F(WiMaxServiceTest,OnSignalStrengthChanged)130 TEST_F(WiMaxServiceTest, OnSignalStrengthChanged) {
131 const int kStrength = 55;
132 service_->OnSignalStrengthChanged(kStrength);
133 EXPECT_EQ(kStrength, service_->strength());
134 }
135
TEST_F(WiMaxServiceTest,StartStop)136 TEST_F(WiMaxServiceTest, StartStop) {
137 static const char kName[] = "My WiMAX Network";
138 const uint32_t kIdentifier = 0x1234abcd;
139 const int kStrength = 66;
140 EXPECT_FALSE(service_->connectable());
141 EXPECT_FALSE(service_->IsStarted());
142 EXPECT_FALSE(service_->IsVisible());
143 EXPECT_EQ(0, service_->strength());
144 EXPECT_FALSE(service_->proxy_.get());
145 EXPECT_CALL(*proxy_, Name(_)).WillOnce(Return(kName));
146 EXPECT_CALL(*proxy_, Identifier(_)).WillOnce(Return(kIdentifier));
147 EXPECT_CALL(*proxy_, SignalStrength(_)).WillOnce(Return(kStrength));
148 EXPECT_CALL(*proxy_, set_signal_strength_changed_callback(_));
149 ServiceMockAdaptor* adaptor = GetAdaptor();
150 EXPECT_CALL(*adaptor, EmitBoolChanged(kConnectableProperty, _))
151 .Times(AnyNumber());
152 EXPECT_CALL(*adaptor, EmitBoolChanged(kVisibleProperty, true));
153 ExpectUpdateService();
154 service_->need_passphrase_ = false;
155 EXPECT_TRUE(service_->Start(proxy_.release()));
156 EXPECT_TRUE(service_->IsStarted());
157 EXPECT_TRUE(service_->IsVisible());
158 EXPECT_EQ(kStrength, service_->strength());
159 EXPECT_EQ(kName, service_->network_name());
160 EXPECT_EQ(kTestName, service_->friendly_name());
161 EXPECT_EQ(kTestNetworkId, service_->network_id());
162 EXPECT_TRUE(service_->connectable());
163 EXPECT_TRUE(service_->proxy_.get());
164
165 service_->device_ = device_;
166 EXPECT_CALL(*device_, OnServiceStopped(_));
167 EXPECT_CALL(*adaptor, EmitBoolChanged(kVisibleProperty, false));
168 ExpectUpdateService();
169 service_->Stop();
170 EXPECT_FALSE(service_->IsStarted());
171 EXPECT_FALSE(service_->IsVisible());
172 EXPECT_EQ(0, service_->strength());
173 EXPECT_FALSE(service_->proxy_.get());
174 }
175
TEST_F(WiMaxServiceTest,Connectable)176 TEST_F(WiMaxServiceTest, Connectable) {
177 EXPECT_TRUE(service_->Is8021x());
178 EXPECT_TRUE(service_->need_passphrase_);
179 EXPECT_FALSE(service_->connectable());
180
181 EXPECT_CALL(*eap_, IsConnectableUsingPassphrase())
182 .WillOnce(Return(false))
183 .WillRepeatedly(Return(true));
184
185 // No WiMaxCredentials.
186 service_->OnEapCredentialsChanged(Service::kReasonPropertyUpdate);
187 EXPECT_TRUE(service_->need_passphrase_);
188 EXPECT_FALSE(service_->connectable());
189
190 // Not started (no proxy).
191 service_->OnEapCredentialsChanged(Service::kReasonPropertyUpdate);
192 EXPECT_FALSE(service_->need_passphrase_);
193 EXPECT_FALSE(service_->connectable());
194
195 // Connectable.
196 service_->proxy_.reset(proxy_.release());
197 ExpectUpdateService();
198 service_->OnEapCredentialsChanged(Service::kReasonPropertyUpdate);
199 EXPECT_FALSE(service_->need_passphrase_);
200 EXPECT_TRUE(service_->connectable());
201
202 // Reset WimaxConnectable state.
203 Mock::VerifyAndClearExpectations(eap_);
204 EXPECT_CALL(*eap_, set_password(""));
205 EXPECT_CALL(*eap_, IsConnectableUsingPassphrase())
206 .WillRepeatedly(Return(false));
207 ExpectUpdateService();
208 service_->ClearPassphrase();
209 EXPECT_TRUE(service_->need_passphrase_);
210 EXPECT_FALSE(service_->connectable());
211 }
212
TEST_F(WiMaxServiceTest,ChangeCredResetHasEverConnected)213 TEST_F(WiMaxServiceTest, ChangeCredResetHasEverConnected) {
214 service_->has_ever_connected_ = true;
215 EXPECT_TRUE(service_->has_ever_connected());
216 service_->OnEapCredentialsChanged(Service::kReasonPropertyUpdate);
217 EXPECT_FALSE(service_->has_ever_connected());
218 }
219
TEST_F(WiMaxServiceTest,ConvertIdentifierToNetworkId)220 TEST_F(WiMaxServiceTest, ConvertIdentifierToNetworkId) {
221 EXPECT_EQ("00000000", WiMaxService::ConvertIdentifierToNetworkId(0));
222 EXPECT_EQ("abcd1234", WiMaxService::ConvertIdentifierToNetworkId(0xabcd1234));
223 EXPECT_EQ("ffffffff", WiMaxService::ConvertIdentifierToNetworkId(0xffffffff));
224 }
225
TEST_F(WiMaxServiceTest,StorageIdentifier)226 TEST_F(WiMaxServiceTest, StorageIdentifier) {
227 static const char kStorageId[] = "wimax_test_wimax_network_1234abcd";
228 EXPECT_EQ(kStorageId, service_->GetStorageIdentifier());
229 EXPECT_EQ(kStorageId,
230 WiMaxService::CreateStorageIdentifier(kTestNetworkId, kTestName));
231 }
232
TEST_F(WiMaxServiceTest,Save)233 TEST_F(WiMaxServiceTest, Save) {
234 NiceMock<MockStore> storage;
235 string storage_id = service_->GetStorageIdentifier();
236 EXPECT_CALL(storage, SetString(storage_id, _, _))
237 .WillRepeatedly(Return(true));
238 EXPECT_CALL(storage, DeleteKey(storage_id, _)).WillRepeatedly(Return(true));
239 EXPECT_CALL(storage, SetString(storage_id,
240 WiMaxService::kStorageNetworkId,
241 kTestNetworkId));
242 EXPECT_TRUE(service_->Save(&storage));
243 }
244
TEST_F(WiMaxServiceTest,Connect)245 TEST_F(WiMaxServiceTest, Connect) {
246 // Connect but not connectable.
247 Error error;
248 EXPECT_FALSE(service_->connectable());
249 service_->Connect(&error, "in test");
250 EXPECT_EQ(Error::kOperationFailed, error.type());
251 SetConnectable(true);
252
253 // No carrier device available.
254 MockWiMaxProvider provider;
255 scoped_refptr<MockWiMax> null_device;
256 EXPECT_CALL(manager_, wimax_provider()).WillOnce(Return(&provider));
257 EXPECT_CALL(provider, SelectCarrier(_)).WillOnce(Return(null_device));
258 error.Reset();
259 service_->Connect(&error, "in test");
260 EXPECT_EQ(Error::kNoCarrier, error.type());
261
262 // Successful connect.
263 EXPECT_CALL(manager_, wimax_provider()).WillOnce(Return(&provider));
264 EXPECT_CALL(provider, SelectCarrier(_)).WillOnce(Return(device_));
265 EXPECT_CALL(*device_, ConnectTo(_, _));
266 error.Reset();
267 service_->Connect(&error, "in test");
268 EXPECT_TRUE(error.IsSuccess());
269
270 // Connect while already connected.
271 // TODO(benchan): Check for error if we populate error again after changing
272 // the way that Chrome handles Error::kAlreadyConnected situation.
273 service_->Connect(&error, "in test");
274
275 // Successful disconnect.
276 EXPECT_CALL(*eap_, set_password(_)).Times(0);
277 EXPECT_CALL(*device_, DisconnectFrom(_, _));
278 error.Reset();
279 service_->Disconnect(&error, "in test");
280 EXPECT_TRUE(error.IsSuccess());
281 EXPECT_TRUE(service_->connectable());
282
283 // Disconnect while not connected.
284 service_->Disconnect(&error, "in test");
285 EXPECT_EQ(Error::kNotConnected, error.type());
286 }
287
TEST_F(WiMaxServiceTest,Unload)288 TEST_F(WiMaxServiceTest, Unload) {
289 MockWiMaxProvider provider;
290 EXPECT_CALL(manager_, wimax_provider())
291 .Times(2)
292 .WillRepeatedly(Return(&provider));
293 EXPECT_CALL(*eap_, Reset());
294 EXPECT_CALL(*eap_, set_password(""));
295 EXPECT_CALL(*eap_, IsConnectableUsingPassphrase())
296 .WillRepeatedly(Return(false));
297 EXPECT_CALL(provider, OnServiceUnloaded(_)).WillOnce(Return(false));
298 EXPECT_FALSE(service_->Unload());
299 Mock::VerifyAndClearExpectations(eap_);
300
301 EXPECT_CALL(*eap_, Reset());
302 EXPECT_CALL(*eap_, set_password(""));
303 EXPECT_CALL(*eap_, IsConnectableUsingPassphrase())
304 .WillRepeatedly(Return(false));
305 EXPECT_CALL(provider, OnServiceUnloaded(_)).WillOnce(Return(true));
306 EXPECT_TRUE(service_->Unload());
307 }
308
TEST_F(WiMaxServiceTest,SetState)309 TEST_F(WiMaxServiceTest, SetState) {
310 service_->device_ = device_;
311 EXPECT_EQ(Service::kStateIdle, service_->state());
312
313 EXPECT_CALL(manager_, UpdateService(_));
314 service_->SetState(Service::kStateAssociating);
315 EXPECT_EQ(Service::kStateAssociating, service_->state());
316 EXPECT_TRUE(service_->device_);
317
318 EXPECT_CALL(manager_, UpdateService(_));
319 service_->SetState(Service::kStateFailure);
320 EXPECT_EQ(Service::kStateFailure, service_->state());
321 EXPECT_FALSE(service_->device_);
322 }
323
TEST_F(WiMaxServiceTest,IsAutoConnectable)324 TEST_F(WiMaxServiceTest, IsAutoConnectable) {
325 EXPECT_FALSE(service_->connectable());
326 const char* reason = "";
327
328 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
329
330 MockWiMaxProvider provider;
331 EXPECT_CALL(manager_, wimax_provider())
332 .Times(2)
333 .WillRepeatedly(Return(&provider));
334
335 SetConnectable(true);
336 EXPECT_CALL(provider, SelectCarrier(_)).WillOnce(Return(device_));
337 EXPECT_CALL(*device_, IsIdle()).WillOnce(Return(false));
338 reason = "";
339 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
340 EXPECT_EQ(WiMaxService::kAutoConnBusy, reason);
341
342 EXPECT_CALL(provider, SelectCarrier(_)).WillOnce(Return(device_));
343 EXPECT_CALL(*device_, IsIdle()).WillOnce(Return(true));
344 reason = "";
345 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
346 EXPECT_STREQ("", reason);
347 }
348
TEST_F(WiMaxServiceTest,PropertyChanges)349 TEST_F(WiMaxServiceTest, PropertyChanges) {
350 ServiceMockAdaptor* adaptor = GetAdaptor();
351 TestCommonPropertyChanges(service_, adaptor);
352 TestAutoConnectPropertyChange(service_, adaptor);
353
354 EXPECT_CALL(*adaptor,
355 EmitRpcIdentifierChanged(kDeviceProperty, _));
356 SetDevice(device_);
357 Mock::VerifyAndClearExpectations(adaptor);
358
359 EXPECT_CALL(*adaptor,
360 EmitRpcIdentifierChanged(kDeviceProperty, _));
361 SetDevice(nullptr);
362 Mock::VerifyAndClearExpectations(adaptor);
363 }
364
365 // Custom property setters should return false, and make no changes, if
366 // the new value is the same as the old value.
TEST_F(WiMaxServiceTest,CustomSetterNoopChange)367 TEST_F(WiMaxServiceTest, CustomSetterNoopChange) {
368 TestCustomSetterNoopChange(service_, &manager_);
369 }
370
371 } // namespace shill
372