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.h"
18
19#include <memory>
20#include <string>
21
22#include "shill/dhcp/mock_dhcp_config.h"
23#include "shill/dhcp/mock_dhcp_provider.h"
24#include "shill/mock_manager.h"
25#include "shill/mock_metrics.h"
26#include "shill/nice_mock_control.h"
27#include "shill/test_event_dispatcher.h"
28#include "shill/testing.h"
29#include "shill/wimax/mock_wimax_device_proxy.h"
30#include "shill/wimax/mock_wimax_provider.h"
31#include "shill/wimax/mock_wimax_service.h"
32
33using base::Bind;
34using base::Unretained;
35using std::string;
36using testing::_;
37using testing::NiceMock;
38using testing::Return;
39
40namespace shill {
41
42namespace {
43
44const char kTestLinkName[] = "wm0";
45const char kTestAddress[] = "01:23:45:67:89:ab";
46const int kTestInterfaceIndex = 5;
47const char kTestPath[] = "/org/chromium/WiMaxManager/Device/6";
48
49}  // namespace
50
51class WiMaxTest : public testing::Test {
52 public:
53  WiMaxTest()
54      : proxy_(new MockWiMaxDeviceProxy()),
55        metrics_(&dispatcher_),
56        manager_(&control_, &dispatcher_, &metrics_),
57        dhcp_config_(new MockDHCPConfig(&control_,
58                                        kTestLinkName)),
59        device_(new WiMax(&control_, &dispatcher_, &metrics_, &manager_,
60                          kTestLinkName, kTestAddress, kTestInterfaceIndex,
61                          kTestPath)) {}
62
63  virtual ~WiMaxTest() {}
64
65 protected:
66  class Target {
67   public:
68    virtual ~Target() {}
69
70    MOCK_METHOD1(EnabledStateChanged, void(const Error& error));
71  };
72
73  virtual void SetUp() {
74    device_->set_dhcp_provider(&dhcp_provider_);
75  }
76
77  virtual void TearDown() {
78    device_->SelectService(nullptr);
79    device_->pending_service_ = nullptr;
80  }
81
82  std::unique_ptr<MockWiMaxDeviceProxy> proxy_;
83  NiceMockControl control_;
84  EventDispatcherForTest dispatcher_;
85  NiceMock<MockMetrics> metrics_;
86  MockManager manager_;
87  MockDHCPProvider dhcp_provider_;
88  scoped_refptr<MockDHCPConfig> dhcp_config_;
89  WiMaxRefPtr device_;
90};
91
92TEST_F(WiMaxTest, Constructor) {
93  EXPECT_EQ(kTestPath, device_->path());
94  EXPECT_FALSE(device_->scanning());
95}
96
97TEST_F(WiMaxTest, StartStop) {
98  EXPECT_FALSE(device_->proxy_.get());
99  EXPECT_CALL(control_, CreateWiMaxDeviceProxy(_))
100      .WillOnce(ReturnAndReleasePointee(&proxy_));
101  EXPECT_CALL(*proxy_, Enable(_, _, _));
102  EXPECT_CALL(*proxy_, set_networks_changed_callback(_));
103  EXPECT_CALL(*proxy_, set_status_changed_callback(_));
104  EXPECT_CALL(*proxy_, Disable(_, _, _));
105  device_->Start(nullptr, EnabledStateChangedCallback());
106  ASSERT_TRUE(device_->proxy_.get());
107
108  scoped_refptr<MockWiMaxService> service(
109      new MockWiMaxService(&control_, nullptr, &metrics_, &manager_));
110  device_->pending_service_ = service;
111  EXPECT_CALL(*service, SetState(Service::kStateIdle));
112  device_->networks_.insert("path");
113  MockWiMaxProvider provider;
114  EXPECT_CALL(manager_, wimax_provider()).WillOnce(Return(&provider));
115  EXPECT_CALL(provider, OnNetworksChanged());
116  device_->StartConnectTimeout();
117  device_->Stop(nullptr, EnabledStateChangedCallback());
118  EXPECT_TRUE(device_->networks_.empty());
119  EXPECT_FALSE(device_->IsConnectTimeoutStarted());
120  EXPECT_FALSE(device_->pending_service_);
121}
122
123TEST_F(WiMaxTest, OnServiceStopped) {
124  scoped_refptr<NiceMock<MockWiMaxService>> service0(
125      new NiceMock<MockWiMaxService>(&control_, nullptr, &metrics_, &manager_));
126  scoped_refptr<MockWiMaxService> service1(
127      new MockWiMaxService(&control_, nullptr, &metrics_, &manager_));
128  device_->SelectService(service0);
129  device_->pending_service_ = service1;
130
131  device_->OnServiceStopped(nullptr);
132  EXPECT_TRUE(device_->selected_service());
133  EXPECT_TRUE(device_->pending_service_);
134
135  device_->OnServiceStopped(service0);
136  EXPECT_FALSE(device_->selected_service());
137  EXPECT_TRUE(device_->pending_service_);
138
139  device_->OnServiceStopped(service1);
140  EXPECT_FALSE(device_->selected_service());
141  EXPECT_FALSE(device_->pending_service_);
142}
143
144TEST_F(WiMaxTest, OnNetworksChanged) {
145  MockWiMaxProvider provider;
146  EXPECT_CALL(manager_, wimax_provider()).WillOnce(Return(&provider));
147  EXPECT_CALL(provider, OnNetworksChanged());
148  device_->networks_.insert("foo");
149  RpcIdentifiers networks;
150  networks.push_back("bar");
151  networks.push_back("zoo");
152  networks.push_back("bar");
153  device_->OnNetworksChanged(networks);
154  EXPECT_EQ(2, device_->networks_.size());
155  EXPECT_TRUE(ContainsKey(device_->networks_, "bar"));
156  EXPECT_TRUE(ContainsKey(device_->networks_, "zoo"));
157}
158
159TEST_F(WiMaxTest, OnConnectComplete) {
160  scoped_refptr<MockWiMaxService> service(
161      new MockWiMaxService(&control_, nullptr, &metrics_, &manager_));
162  device_->pending_service_ = service;
163  EXPECT_CALL(*service, SetState(_)).Times(0);
164  EXPECT_TRUE(device_->pending_service_);
165  EXPECT_CALL(*service, SetState(Service::kStateFailure));
166  device_->OnConnectComplete(Error(Error::kOperationFailed));
167  EXPECT_FALSE(device_->pending_service_);
168}
169
170TEST_F(WiMaxTest, OnStatusChanged) {
171  scoped_refptr<MockWiMaxService> service(
172      new MockWiMaxService(&control_, nullptr, &metrics_, &manager_));
173
174  EXPECT_EQ(wimax_manager::kDeviceStatusUninitialized, device_->status_);
175  device_->pending_service_ = service;
176  EXPECT_CALL(*service, SetState(_)).Times(0);
177  EXPECT_CALL(*service, ClearPassphrase()).Times(0);
178  device_->OnStatusChanged(wimax_manager::kDeviceStatusScanning);
179  EXPECT_TRUE(device_->pending_service_);
180  EXPECT_EQ(wimax_manager::kDeviceStatusScanning, device_->status_);
181
182  device_->status_ = wimax_manager::kDeviceStatusConnecting;
183  EXPECT_CALL(*service, SetState(Service::kStateFailure));
184  EXPECT_CALL(*service, ClearPassphrase()).Times(0);
185  device_->OnStatusChanged(wimax_manager::kDeviceStatusScanning);
186  EXPECT_FALSE(device_->pending_service_);
187
188  device_->status_ = wimax_manager::kDeviceStatusConnecting;
189  device_->SelectService(service);
190  EXPECT_CALL(*service, SetState(Service::kStateFailure));
191  EXPECT_CALL(*service, SetState(Service::kStateIdle));
192  EXPECT_CALL(*service, ClearPassphrase()).Times(0);
193  device_->OnStatusChanged(wimax_manager::kDeviceStatusScanning);
194  EXPECT_FALSE(device_->selected_service());
195
196  device_->pending_service_ = service;
197  device_->SelectService(service);
198  EXPECT_CALL(*service, SetState(_)).Times(0);
199  EXPECT_CALL(*service, ClearPassphrase()).Times(0);
200  device_->OnStatusChanged(wimax_manager::kDeviceStatusConnecting);
201  EXPECT_TRUE(device_->pending_service_);
202  EXPECT_TRUE(device_->selected_service());
203  EXPECT_EQ(wimax_manager::kDeviceStatusConnecting, device_->status_);
204
205  EXPECT_CALL(*service, SetState(Service::kStateIdle));
206  device_->SelectService(nullptr);
207}
208
209TEST_F(WiMaxTest, UseNoArpGateway) {
210  EXPECT_CALL(dhcp_provider_, CreateIPv4Config(kTestLinkName, _, false, _))
211      .WillOnce(Return(dhcp_config_));
212  device_->AcquireIPConfig();
213}
214
215TEST_F(WiMaxTest, DropService) {
216  scoped_refptr<NiceMock<MockWiMaxService>> service0(
217      new NiceMock<MockWiMaxService>(&control_, nullptr, &metrics_, &manager_));
218  scoped_refptr<MockWiMaxService> service1(
219      new MockWiMaxService(&control_, nullptr, &metrics_, &manager_));
220  device_->SelectService(service0);
221  device_->pending_service_ = service1;
222  device_->StartConnectTimeout();
223
224  EXPECT_CALL(*service0, SetState(Service::kStateIdle)).Times(2);
225  EXPECT_CALL(*service1, SetState(Service::kStateIdle));
226  device_->DropService(Service::kStateIdle);
227  EXPECT_FALSE(device_->selected_service());
228  EXPECT_FALSE(device_->pending_service_);
229  EXPECT_FALSE(device_->IsConnectTimeoutStarted());
230
231  // Expect no crash.
232  device_->DropService(Service::kStateFailure);
233}
234
235TEST_F(WiMaxTest, OnDeviceVanished) {
236  device_->proxy_.reset(proxy_.release());
237  scoped_refptr<MockWiMaxService> service(
238      new MockWiMaxService(&control_, nullptr, &metrics_, &manager_));
239  device_->pending_service_ = service;
240  EXPECT_CALL(*service, SetState(Service::kStateIdle));
241  device_->OnDeviceVanished();
242  EXPECT_FALSE(device_->proxy_.get());
243  EXPECT_FALSE(device_->pending_service_);
244}
245
246TEST_F(WiMaxTest, OnEnableComplete) {
247  MockWiMaxProvider provider;
248  EXPECT_CALL(manager_, wimax_provider()).WillOnce(Return(&provider));
249  RpcIdentifiers networks(1, "path");
250  EXPECT_CALL(*proxy_, Networks(_)).WillOnce(Return(networks));
251  device_->proxy_.reset(proxy_.release());
252  EXPECT_CALL(provider, OnNetworksChanged());
253  Target target;
254  EXPECT_CALL(target, EnabledStateChanged(_));
255  EnabledStateChangedCallback callback(
256      Bind(&Target::EnabledStateChanged, Unretained(&target)));
257  Error error;
258  device_->OnEnableComplete(callback, error);
259  EXPECT_EQ(1, device_->networks_.size());
260  EXPECT_TRUE(ContainsKey(device_->networks_, "path"));
261
262  EXPECT_TRUE(device_->proxy_.get());
263  error.Populate(Error::kOperationFailed);
264  EXPECT_CALL(target, EnabledStateChanged(_));
265  device_->OnEnableComplete(callback, error);
266  EXPECT_FALSE(device_->proxy_.get());
267}
268
269TEST_F(WiMaxTest, ConnectTimeout) {
270  EXPECT_EQ(&dispatcher_, device_->dispatcher());
271  EXPECT_TRUE(device_->connect_timeout_callback_.IsCancelled());
272  EXPECT_FALSE(device_->IsConnectTimeoutStarted());
273  EXPECT_EQ(WiMax::kDefaultConnectTimeoutSeconds,
274            device_->connect_timeout_seconds_);
275  device_->connect_timeout_seconds_ = 0;
276  device_->StartConnectTimeout();
277  EXPECT_FALSE(device_->connect_timeout_callback_.IsCancelled());
278  EXPECT_TRUE(device_->IsConnectTimeoutStarted());
279  device_->dispatcher_ = nullptr;
280  device_->StartConnectTimeout();  // Expect no crash.
281  scoped_refptr<MockWiMaxService> service(
282      new MockWiMaxService(&control_, nullptr, &metrics_, &manager_));
283  device_->pending_service_ = service;
284  EXPECT_CALL(*service, SetState(Service::kStateFailure));
285  dispatcher_.DispatchPendingEvents();
286  EXPECT_TRUE(device_->connect_timeout_callback_.IsCancelled());
287  EXPECT_FALSE(device_->IsConnectTimeoutStarted());
288  EXPECT_FALSE(device_->pending_service_);
289}
290
291TEST_F(WiMaxTest, ConnectTo) {
292  static const char kPath[] = "/network/path";
293  scoped_refptr<MockWiMaxService> service(
294      new MockWiMaxService(&control_, nullptr, &metrics_, &manager_));
295  EXPECT_CALL(*service, SetState(Service::kStateAssociating));
296  device_->status_ = wimax_manager::kDeviceStatusScanning;
297  EXPECT_CALL(*service, GetNetworkObjectPath()).WillOnce(Return(kPath));
298  EXPECT_CALL(*proxy_, Connect(kPath, _, _, _, _))
299      .WillOnce(SetErrorTypeInArgument<2>(Error::kSuccess));
300  device_->proxy_.reset(proxy_.release());
301  Error error;
302  device_->ConnectTo(service, &error);
303  EXPECT_TRUE(error.IsSuccess());
304  EXPECT_EQ(service.get(), device_->pending_service_.get());
305  EXPECT_EQ(wimax_manager::kDeviceStatusUninitialized, device_->status_);
306  EXPECT_TRUE(device_->IsConnectTimeoutStarted());
307
308  device_->ConnectTo(service, &error);
309  EXPECT_EQ(Error::kInProgress, error.type());
310
311  device_->pending_service_ = nullptr;
312}
313
314TEST_F(WiMaxTest, IsIdle) {
315  EXPECT_TRUE(device_->IsIdle());
316  scoped_refptr<NiceMock<MockWiMaxService>> service(
317      new NiceMock<MockWiMaxService>(&control_, nullptr, &metrics_, &manager_));
318  device_->pending_service_ = service;
319  EXPECT_FALSE(device_->IsIdle());
320  device_->pending_service_ = nullptr;
321  device_->SelectService(service);
322  EXPECT_FALSE(device_->IsIdle());
323}
324
325}  // namespace shill
326