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/vpn/vpn_service.h"
18
19#include <string>
20
21#if defined(__ANDROID__)
22#include <dbus/service_constants.h>
23#else
24#include <chromeos/dbus/service_constants.h>
25#endif  // __ANDROID__
26#include <gtest/gtest.h>
27
28#include "shill/error.h"
29#include "shill/mock_adaptors.h"
30#include "shill/mock_connection.h"
31#include "shill/mock_device_info.h"
32#include "shill/mock_manager.h"
33#include "shill/mock_metrics.h"
34#include "shill/mock_profile.h"
35#include "shill/mock_store.h"
36#include "shill/net/mock_sockets.h"
37#include "shill/nice_mock_control.h"
38#include "shill/service_property_change_test.h"
39#include "shill/vpn/mock_vpn_driver.h"
40#include "shill/vpn/mock_vpn_provider.h"
41
42using std::string;
43using testing::_;
44using testing::Mock;
45using testing::NiceMock;
46using testing::Return;
47using testing::ReturnRef;
48using testing::ReturnRefOfCopy;
49
50namespace shill {
51
52class VPNServiceTest : public testing::Test {
53 public:
54  VPNServiceTest()
55      : interface_name_("test-interface"),
56        driver_(new MockVPNDriver()),
57        manager_(&control_, nullptr, nullptr),
58        metrics_(nullptr),
59        device_info_(&control_, nullptr, nullptr, nullptr),
60        connection_(new NiceMock<MockConnection>(&device_info_)),
61        sockets_(new MockSockets()),
62        service_(new VPNService(&control_, nullptr, &metrics_, &manager_,
63                                driver_)) {
64    service_->sockets_.reset(sockets_);  // Passes ownership.
65  }
66
67  virtual ~VPNServiceTest() {}
68
69 protected:
70  virtual void SetUp() {
71    ON_CALL(*connection_, interface_name())
72        .WillByDefault(ReturnRef(interface_name_));
73    ON_CALL(*connection_, ipconfig_rpc_identifier())
74        .WillByDefault(ReturnRef(ipconfig_rpc_identifier_));
75  }
76
77  virtual void TearDown() {
78    EXPECT_CALL(device_info_, FlushAddresses(0));
79  }
80
81  void SetServiceState(Service::ConnectState state) {
82    service_->state_ = state;
83  }
84
85  void SetHasEverConnected(bool connected) {
86    service_->has_ever_connected_ = connected;
87  }
88
89  void SetConnectable(bool connectable) {
90    service_->connectable_ = connectable;
91  }
92
93  const char* GetAutoConnOffline() {
94    return Service::kAutoConnOffline;
95  }
96
97  const char* GetAutoConnNeverConnected() {
98    return VPNService::kAutoConnNeverConnected;
99  }
100
101  const char* GetAutoConnVPNAlreadyActive() {
102    return VPNService::kAutoConnVPNAlreadyActive;
103  }
104
105  bool IsAutoConnectable(const char** reason) const {
106    return service_->IsAutoConnectable(reason);
107  }
108
109  // Takes ownership of |provider|.
110  void SetVPNProvider(VPNProvider* provider) {
111    manager_.vpn_provider_.reset(provider);
112    manager_.UpdateProviderMapping();
113  }
114
115  ServiceMockAdaptor* GetAdaptor() {
116    return static_cast<ServiceMockAdaptor*>(service_->adaptor());
117  }
118
119  std::string interface_name_;
120  std::string ipconfig_rpc_identifier_;
121  MockVPNDriver* driver_;  // Owned by |service_|.
122  NiceMockControl control_;
123  MockManager manager_;
124  MockMetrics metrics_;
125  MockDeviceInfo device_info_;
126  scoped_refptr<NiceMock<MockConnection>> connection_;
127  MockSockets* sockets_;  // Owned by |service_|.
128  VPNServiceRefPtr service_;
129};
130
131TEST_F(VPNServiceTest, Connect) {
132  EXPECT_TRUE(service_->connectable());
133  Error error;
134  EXPECT_CALL(*driver_, Connect(_, &error));
135  service_->Connect(&error, "in test");
136  EXPECT_TRUE(error.IsSuccess());
137}
138
139TEST_F(VPNServiceTest, ConnectAlreadyConnected) {
140  Error error;
141  EXPECT_CALL(*driver_, Connect(_, _)).Times(0);
142  SetServiceState(Service::kStateOnline);
143  service_->Connect(&error, "in test");
144  EXPECT_EQ(Error::kAlreadyConnected, error.type());
145  error.Reset();
146  SetServiceState(Service::kStateConfiguring);
147  service_->Connect(&error, "in test");
148  EXPECT_EQ(Error::kInProgress, error.type());
149}
150
151TEST_F(VPNServiceTest, Disconnect) {
152  Error error;
153  EXPECT_CALL(*driver_, Disconnect());
154  service_->Disconnect(&error, "in test");
155  EXPECT_TRUE(error.IsSuccess());
156}
157
158TEST_F(VPNServiceTest, CreateStorageIdentifierNoHost) {
159  KeyValueStore args;
160  Error error;
161  args.SetString(kNameProperty, "vpn-name");
162  EXPECT_EQ("", VPNService::CreateStorageIdentifier(args, &error));
163  EXPECT_EQ(Error::kInvalidProperty, error.type());
164}
165
166TEST_F(VPNServiceTest, CreateStorageIdentifierNoName) {
167  KeyValueStore args;
168  Error error;
169  args.SetString(kProviderHostProperty, "10.8.0.1");
170  EXPECT_EQ("", VPNService::CreateStorageIdentifier(args, &error));
171  EXPECT_EQ(Error::kNotSupported, error.type());
172}
173
174TEST_F(VPNServiceTest, CreateStorageIdentifier) {
175  KeyValueStore args;
176  Error error;
177  args.SetString(kNameProperty, "vpn-name");
178  args.SetString(kProviderHostProperty, "10.8.0.1");
179  EXPECT_EQ("vpn_10_8_0_1_vpn_name",
180            VPNService::CreateStorageIdentifier(args, &error));
181  EXPECT_TRUE(error.IsSuccess());
182}
183
184TEST_F(VPNServiceTest, GetStorageIdentifier) {
185  EXPECT_EQ("", service_->GetStorageIdentifier());
186  service_->set_storage_id("foo");
187  EXPECT_EQ("foo", service_->GetStorageIdentifier());
188}
189
190TEST_F(VPNServiceTest, GetDeviceRpcId) {
191  Error error;
192  EXPECT_EQ("/", service_->GetDeviceRpcId(&error));
193  EXPECT_EQ(Error::kNotSupported, error.type());
194}
195
196TEST_F(VPNServiceTest, Load) {
197  NiceMock<MockStore> storage;
198  static const char kStorageID[] = "storage-id";
199  service_->set_storage_id(kStorageID);
200  EXPECT_CALL(storage, ContainsGroup(kStorageID)).WillOnce(Return(true));
201  EXPECT_CALL(*driver_, Load(&storage, kStorageID))
202      .WillOnce(Return(true));
203  EXPECT_TRUE(service_->Load(&storage));
204}
205
206TEST_F(VPNServiceTest, Save) {
207  NiceMock<MockStore> storage;
208  static const char kStorageID[] = "storage-id";
209  service_->set_storage_id(kStorageID);
210  EXPECT_CALL(*driver_, Save(&storage, kStorageID, false))
211      .WillOnce(Return(true));
212  EXPECT_TRUE(service_->Save(&storage));
213}
214
215TEST_F(VPNServiceTest, SaveCredentials) {
216  NiceMock<MockStore> storage;
217  static const char kStorageID[] = "storage-id";
218  service_->set_storage_id(kStorageID);
219  service_->set_save_credentials(true);
220  EXPECT_CALL(*driver_, Save(&storage, kStorageID, true))
221      .WillOnce(Return(true));
222  EXPECT_TRUE(service_->Save(&storage));
223}
224
225TEST_F(VPNServiceTest, Unload) {
226  service_->SetAutoConnect(true);
227  service_->set_save_credentials(true);
228  EXPECT_CALL(*driver_, Disconnect());
229  EXPECT_CALL(*driver_, UnloadCredentials());
230  MockVPNProvider* provider = new MockVPNProvider;
231  SetVPNProvider(provider);
232  provider->services_.push_back(service_);
233  service_->Unload();
234  EXPECT_FALSE(service_->auto_connect());
235  EXPECT_FALSE(service_->save_credentials());
236  EXPECT_TRUE(provider->services_.empty());
237}
238
239TEST_F(VPNServiceTest, InitPropertyStore) {
240  EXPECT_CALL(*driver_, InitPropertyStore(service_->mutable_store()));
241  service_->InitDriverPropertyStore();
242}
243
244TEST_F(VPNServiceTest, EnableAndRetainAutoConnect) {
245  EXPECT_FALSE(service_->retain_auto_connect());
246  EXPECT_FALSE(service_->auto_connect());
247  service_->EnableAndRetainAutoConnect();
248  EXPECT_TRUE(service_->retain_auto_connect());
249  EXPECT_FALSE(service_->auto_connect());
250}
251
252TEST_F(VPNServiceTest, SetConnection) {
253  EXPECT_FALSE(service_->connection_binder_.get());
254  EXPECT_FALSE(service_->connection());
255  EXPECT_CALL(*sockets_, Socket(_, _, _)).WillOnce(Return(-1));
256  service_->SetConnection(connection_);
257  ASSERT_TRUE(service_->connection_binder_.get());
258  EXPECT_EQ(connection_.get(),
259            service_->connection_binder_->connection().get());
260  EXPECT_EQ(connection_.get(), service_->connection().get());
261  EXPECT_CALL(*driver_, OnConnectionDisconnected()).Times(0);
262}
263
264TEST_F(VPNServiceTest, OnConnectionDisconnected) {
265  EXPECT_CALL(*sockets_, Socket(_, _, _)).WillOnce(Return(-1));
266  service_->SetConnection(connection_);
267  EXPECT_CALL(*driver_, OnConnectionDisconnected()).Times(1);
268  connection_->OnLowerDisconnect();
269}
270
271TEST_F(VPNServiceTest, IsAutoConnectableOffline) {
272  EXPECT_TRUE(service_->connectable());
273  const char* reason = nullptr;
274  EXPECT_CALL(manager_, IsConnected()).WillOnce(Return(false));
275  EXPECT_FALSE(IsAutoConnectable(&reason));
276  EXPECT_STREQ(GetAutoConnOffline(), reason);
277}
278
279TEST_F(VPNServiceTest, IsAutoConnectableNeverConnected) {
280  EXPECT_TRUE(service_->connectable());
281  EXPECT_FALSE(service_->has_ever_connected());
282  const char* reason = nullptr;
283  EXPECT_CALL(manager_, IsConnected()).WillOnce(Return(true));
284  EXPECT_FALSE(IsAutoConnectable(&reason));
285  EXPECT_STREQ(GetAutoConnNeverConnected(), reason);
286}
287
288TEST_F(VPNServiceTest, IsAutoConnectableVPNAlreadyActive) {
289  EXPECT_TRUE(service_->connectable());
290  SetHasEverConnected(true);
291  EXPECT_CALL(manager_, IsConnected()).WillOnce(Return(true));
292  MockVPNProvider* provider = new MockVPNProvider;
293  SetVPNProvider(provider);
294  EXPECT_CALL(*provider, HasActiveService()).WillOnce(Return(true));
295  const char* reason = nullptr;
296  EXPECT_FALSE(IsAutoConnectable(&reason));
297  EXPECT_STREQ(GetAutoConnVPNAlreadyActive(), reason);
298}
299
300TEST_F(VPNServiceTest, IsAutoConnectableNotConnectable) {
301  const char* reason = nullptr;
302  SetConnectable(false);
303  EXPECT_FALSE(IsAutoConnectable(&reason));
304}
305
306TEST_F(VPNServiceTest, IsAutoConnectable) {
307  EXPECT_TRUE(service_->connectable());
308  SetHasEverConnected(true);
309  EXPECT_CALL(manager_, IsConnected()).WillOnce(Return(true));
310  MockVPNProvider* provider = new MockVPNProvider;
311  SetVPNProvider(provider);
312  EXPECT_CALL(*provider, HasActiveService()).WillOnce(Return(false));
313  const char* reason = nullptr;
314  EXPECT_TRUE(IsAutoConnectable(&reason));
315  EXPECT_FALSE(reason);
316}
317
318TEST_F(VPNServiceTest, SetNamePropertyTrivial) {
319  Error error;
320  // A null change returns false, but with error set to success.
321  EXPECT_FALSE(service_->mutable_store()->SetAnyProperty(
322      kNameProperty, brillo::Any(service_->friendly_name()), &error));
323  EXPECT_FALSE(error.IsFailure());
324}
325
326TEST_F(VPNServiceTest, SetNameProperty) {
327  const string kHost = "1.2.3.4";
328  driver_->args()->SetString(kProviderHostProperty, kHost);
329  string kOldId = service_->GetStorageIdentifier();
330  Error error;
331  const string kName = "New Name";
332  scoped_refptr<MockProfile> profile(
333      new MockProfile(&control_, &metrics_, &manager_));
334  EXPECT_CALL(*profile, DeleteEntry(kOldId, _));
335  EXPECT_CALL(*profile, UpdateService(_));
336  service_->set_profile(profile);
337  EXPECT_TRUE(service_->mutable_store()->SetAnyProperty(
338      kNameProperty, brillo::Any(kName), &error));
339  EXPECT_NE(service_->GetStorageIdentifier(), kOldId);
340  EXPECT_EQ(kName, service_->friendly_name());
341}
342
343TEST_F(VPNServiceTest, PropertyChanges) {
344  TestCommonPropertyChanges(service_, GetAdaptor());
345  TestAutoConnectPropertyChange(service_, GetAdaptor());
346
347  const string kHost = "1.2.3.4";
348  scoped_refptr<MockProfile> profile(
349      new NiceMock<MockProfile>(&control_, &metrics_, &manager_));
350  service_->set_profile(profile);
351  driver_->args()->SetString(kProviderHostProperty, kHost);
352  TestNamePropertyChange(service_, GetAdaptor());
353}
354
355// Custom property setters should return false, and make no changes, if
356// the new value is the same as the old value.
357TEST_F(VPNServiceTest, CustomSetterNoopChange) {
358  TestCustomSetterNoopChange(service_, &manager_);
359}
360
361TEST_F(VPNServiceTest, GetPhysicalTechnologyPropertyFailsIfNoCarrier) {
362  scoped_refptr<Connection> null_connection;
363
364  EXPECT_CALL(*sockets_, Socket(_, _, _)).WillOnce(Return(-1));
365  service_->SetConnection(connection_);
366  EXPECT_EQ(connection_.get(), service_->connection().get());
367
368  // Simulate an error in the GetCarrierConnection() returning a NULL reference.
369  EXPECT_CALL(*connection_, GetCarrierConnection())
370      .WillOnce(Return(null_connection));
371
372  Error error;
373  EXPECT_EQ("", service_->GetPhysicalTechnologyProperty(&error));
374  EXPECT_EQ(Error::kOperationFailed, error.type());
375}
376
377TEST_F(VPNServiceTest, GetPhysicalTechnologyPropertyOverWifi) {
378  scoped_refptr<NiceMock<MockConnection>> lower_connection_ =
379      new NiceMock<MockConnection>(&device_info_);
380
381  EXPECT_CALL(*connection_, technology())
382      .Times(0);
383  EXPECT_CALL(*connection_, GetCarrierConnection())
384      .WillOnce(Return(lower_connection_));
385
386  EXPECT_CALL(*sockets_, Socket(_, _, _)).WillOnce(Return(-1));
387  service_->SetConnection(connection_);
388  EXPECT_EQ(connection_.get(), service_->connection().get());
389
390  // Set the type of the lower connection to "wifi" and expect that type to be
391  // returned by GetPhysicalTechnologyProperty().
392  EXPECT_CALL(*lower_connection_, technology())
393      .WillOnce(Return(Technology::kWifi));
394
395  Error error;
396  EXPECT_EQ(kTypeWifi, service_->GetPhysicalTechnologyProperty(&error));
397  EXPECT_TRUE(error.IsSuccess());
398
399  // Clear expectations now, so the Return(lower_connection_) action releases
400  // the reference to |lower_connection_| allowing it to be destroyed now.
401  Mock::VerifyAndClearExpectations(connection_.get());
402  // Destroying the |lower_connection_| at function exit will also call an extra
403  // FlushAddresses on the |device_info_| object.
404  EXPECT_CALL(device_info_, FlushAddresses(0));
405}
406
407TEST_F(VPNServiceTest, GetTethering) {
408  scoped_refptr<Connection> null_connection;
409
410  EXPECT_CALL(*sockets_, Socket(_, _, _)).WillOnce(Return(-1));
411  service_->SetConnection(connection_);
412  EXPECT_EQ(connection_.get(), service_->connection().get());
413
414  // Simulate an error in the GetCarrierConnection() returning a NULL reference.
415  EXPECT_CALL(*connection_, GetCarrierConnection())
416      .WillOnce(Return(null_connection));
417
418  {
419    Error error;
420    EXPECT_EQ("", service_->GetTethering(&error));
421    EXPECT_EQ(Error::kOperationFailed, error.type());
422  }
423
424  scoped_refptr<NiceMock<MockConnection>> lower_connection_ =
425      new NiceMock<MockConnection>(&device_info_);
426
427  EXPECT_CALL(*connection_, tethering()).Times(0);
428  EXPECT_CALL(*connection_, GetCarrierConnection())
429      .WillRepeatedly(Return(lower_connection_));
430
431  const char kTethering[] = "moon unit";
432  EXPECT_CALL(*lower_connection_, tethering())
433      .WillOnce(ReturnRefOfCopy(string(kTethering)))
434      .WillOnce(ReturnRefOfCopy(string()));
435
436  {
437    Error error;
438    EXPECT_EQ(kTethering, service_->GetTethering(&error));
439    EXPECT_TRUE(error.IsSuccess());
440  }
441  {
442    Error error;
443    EXPECT_EQ("", service_->GetTethering(&error));
444    EXPECT_EQ(Error::kNotSupported, error.type());
445  }
446
447  // Clear expectations now, so the Return(lower_connection_) action releases
448  // the reference to |lower_connection_| allowing it to be destroyed now.
449  Mock::VerifyAndClearExpectations(connection_.get());
450  // Destroying the |lower_connection_| at function exit will also call an extra
451  // FlushAddresses on the |device_info_| object.
452  EXPECT_CALL(device_info_, FlushAddresses(0));
453}
454
455}  // namespace shill
456