blob: 2cabe1c85ac04979e4414d615e18ce413e4cb0e6 [file] [log] [blame]
Darin Petkovb451d6e2012-04-23 11:56:41 +02001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "shill/vpn_driver.h"
6
7#include <base/stl_util.h>
8#include <base/string_number_conversions.h>
9#include <chromeos/dbus/service_constants.h>
10#include <gmock/gmock.h>
11#include <gtest/gtest.h>
12
Darin Petkov0e9735d2012-04-24 12:33:45 +020013#include "shill/event_dispatcher.h"
14#include "shill/glib.h"
15#include "shill/mock_connection.h"
16#include "shill/mock_device_info.h"
17#include "shill/mock_glib.h"
18#include "shill/mock_manager.h"
19#include "shill/mock_metrics.h"
20#include "shill/mock_service.h"
Darin Petkovb451d6e2012-04-23 11:56:41 +020021#include "shill/mock_store.h"
Darin Petkov0e9735d2012-04-24 12:33:45 +020022#include "shill/nice_mock_control.h"
Darin Petkovb451d6e2012-04-23 11:56:41 +020023#include "shill/property_store.h"
24
25using std::string;
26using testing::_;
27using testing::AnyNumber;
Darin Petkov0e9735d2012-04-24 12:33:45 +020028using testing::NiceMock;
Darin Petkovb451d6e2012-04-23 11:56:41 +020029using testing::Return;
30using testing::SetArgumentPointee;
Darin Petkov0e9735d2012-04-24 12:33:45 +020031using testing::StrictMock;
Darin Petkovb451d6e2012-04-23 11:56:41 +020032using testing::Test;
33
34namespace shill {
35
36namespace {
Darin Petkov602303f2012-06-06 12:15:59 +020037
Darin Petkovb451d6e2012-04-23 11:56:41 +020038const char kHostProperty[] = "VPN.Host";
39const char kOTPProperty[] = "VPN.OTP";
Darin Petkovcb715292012-04-25 13:04:37 +020040const char kPINProperty[] = "VPN.PIN";
Darin Petkov4e9066f2012-06-11 13:17:06 +020041const char kPSKProperty[] = "VPN.PSK";
Darin Petkovb451d6e2012-04-23 11:56:41 +020042const char kPasswordProperty[] = "VPN.Password";
43const char kPortProperty[] = "VPN.Port";
Darin Petkovcb715292012-04-25 13:04:37 +020044
45const char kPIN[] = "5555";
46const char kPassword[] = "random-password";
47const char kPort[] = "1234";
48const char kStorageID[] = "vpn_service_id";
49
Darin Petkovb451d6e2012-04-23 11:56:41 +020050} // namespace
51
52class VPNDriverUnderTest : public VPNDriver {
53 public:
Darin Petkov602303f2012-06-06 12:15:59 +020054 VPNDriverUnderTest(EventDispatcher *dispatcher, Manager *manager);
Darin Petkovb451d6e2012-04-23 11:56:41 +020055 virtual ~VPNDriverUnderTest() {}
56
57 // Inherited from VPNDriver.
58 MOCK_METHOD2(ClaimInterface, bool(const string &link_name,
59 int interface_index));
60 MOCK_METHOD2(Connect, void(const VPNServiceRefPtr &service, Error *error));
61 MOCK_METHOD0(Disconnect, void());
Darin Petkov5eb05422012-05-11 15:45:25 +020062 MOCK_METHOD0(OnConnectionDisconnected, void());
Darin Petkovb451d6e2012-04-23 11:56:41 +020063 MOCK_CONST_METHOD0(GetProviderType, string());
64
65 private:
66 static const Property kProperties[];
67
68 DISALLOW_COPY_AND_ASSIGN(VPNDriverUnderTest);
69};
70
71// static
72const VPNDriverUnderTest::Property VPNDriverUnderTest::kProperties[] = {
73 { kHostProperty, 0 },
Darin Petkovcb715292012-04-25 13:04:37 +020074 { kOTPProperty, Property::kEphemeral },
75 { kPINProperty, Property::kWriteOnly },
Darin Petkov4e9066f2012-06-11 13:17:06 +020076 { kPSKProperty, Property::kCredential },
Darin Petkovcb715292012-04-25 13:04:37 +020077 { kPasswordProperty, Property::kCredential },
Darin Petkovb451d6e2012-04-23 11:56:41 +020078 { kPortProperty, 0 },
Darin Petkov4e02ba22013-04-02 13:44:08 +020079 { flimflam::kProviderTypeProperty, 0 },
Darin Petkovb451d6e2012-04-23 11:56:41 +020080};
81
Darin Petkov602303f2012-06-06 12:15:59 +020082VPNDriverUnderTest::VPNDriverUnderTest(
83 EventDispatcher *dispatcher, Manager *manager)
84 : VPNDriver(dispatcher, manager, kProperties, arraysize(kProperties)) {}
Darin Petkovb451d6e2012-04-23 11:56:41 +020085
86class VPNDriverTest : public Test {
87 public:
Darin Petkov0e9735d2012-04-24 12:33:45 +020088 VPNDriverTest()
89 : device_info_(&control_, &dispatcher_, &metrics_, &manager_),
Thieu Le6c1e3bb2013-02-06 15:20:35 -080090 metrics_(&dispatcher_),
Darin Petkov0e9735d2012-04-24 12:33:45 +020091 manager_(&control_, &dispatcher_, &metrics_, &glib_),
Darin Petkov602303f2012-06-06 12:15:59 +020092 driver_(&dispatcher_, &manager_) {}
Darin Petkovb451d6e2012-04-23 11:56:41 +020093
94 virtual ~VPNDriverTest() {}
95
96 protected:
Darin Petkov0cd0d1e2013-02-11 12:49:10 +010097 EventDispatcher *dispatcher() { return driver_.dispatcher_; }
98 void set_dispatcher(EventDispatcher *dispatcher) {
99 driver_.dispatcher_ = dispatcher;
100 }
101
102 const base::CancelableClosure &connect_timeout_callback() {
103 return driver_.connect_timeout_callback_;
104 }
105
106 bool IsConnectTimeoutStarted() { return driver_.IsConnectTimeoutStarted(); }
107 int connect_timeout_seconds() { return driver_.connect_timeout_seconds(); }
108
109 void StartConnectTimeout(int timeout_seconds) {
110 driver_.StartConnectTimeout(timeout_seconds);
111 }
112
113 void StopConnectTimeout() { driver_.StopConnectTimeout(); }
114
Darin Petkovb451d6e2012-04-23 11:56:41 +0200115 void SetArg(const string &arg, const string &value) {
116 driver_.args()->SetString(arg, value);
117 }
118
119 KeyValueStore *GetArgs() { return driver_.args(); }
120
Paul Stewart8e7e4592012-04-29 09:47:48 -0700121 bool GetProviderProperty(const PropertyStore &store,
122 const string &key,
123 string *value);
Darin Petkovb451d6e2012-04-23 11:56:41 +0200124
Darin Petkov0e9735d2012-04-24 12:33:45 +0200125 NiceMockControl control_;
126 NiceMock<MockDeviceInfo> device_info_;
127 EventDispatcher dispatcher_;
128 MockMetrics metrics_;
129 MockGLib glib_;
130 MockManager manager_;
Darin Petkovb451d6e2012-04-23 11:56:41 +0200131 VPNDriverUnderTest driver_;
132};
133
Paul Stewart8e7e4592012-04-29 09:47:48 -0700134bool VPNDriverTest::GetProviderProperty(const PropertyStore &store,
135 const string &key,
136 string *value) {
Paul Stewart8e7e4592012-04-29 09:47:48 -0700137 KeyValueStore provider_properties;
Paul Stewarte6e8e492013-01-17 11:00:50 -0800138 Error error;
139 EXPECT_TRUE(store.GetKeyValueStoreProperty(
140 flimflam::kProviderProperty, &provider_properties, &error));
Paul Stewart8e7e4592012-04-29 09:47:48 -0700141 if (!provider_properties.ContainsString(key)) {
142 return false;
Darin Petkovb451d6e2012-04-23 11:56:41 +0200143 }
Paul Stewart8e7e4592012-04-29 09:47:48 -0700144 if (value != NULL) {
145 *value = provider_properties.GetString(key);
Darin Petkovb451d6e2012-04-23 11:56:41 +0200146 }
Paul Stewart8e7e4592012-04-29 09:47:48 -0700147 return true;
Darin Petkovb451d6e2012-04-23 11:56:41 +0200148}
149
150TEST_F(VPNDriverTest, Load) {
151 MockStore storage;
Darin Petkov4e9066f2012-06-11 13:17:06 +0200152 GetArgs()->SetString(kHostProperty, "1.2.3.4");
153 GetArgs()->SetString(kPSKProperty, "1234");
Darin Petkovb451d6e2012-04-23 11:56:41 +0200154 EXPECT_CALL(storage, GetString(kStorageID, _, _))
155 .WillRepeatedly(Return(false));
Darin Petkovcb715292012-04-25 13:04:37 +0200156 EXPECT_CALL(storage, GetString(_, kOTPProperty, _)).Times(0);
157 EXPECT_CALL(storage, GetCryptedString(_, kOTPProperty, _)).Times(0);
Darin Petkovb451d6e2012-04-23 11:56:41 +0200158 EXPECT_CALL(storage, GetString(kStorageID, kPortProperty, _))
Darin Petkovcb715292012-04-25 13:04:37 +0200159 .WillOnce(DoAll(SetArgumentPointee<2>(string(kPort)), Return(true)));
160 EXPECT_CALL(storage, GetString(kStorageID, kPINProperty, _))
161 .WillOnce(DoAll(SetArgumentPointee<2>(string(kPIN)), Return(true)));
Darin Petkov4e9066f2012-06-11 13:17:06 +0200162 EXPECT_CALL(storage, GetCryptedString(kStorageID, kPSKProperty, _))
163 .WillOnce(Return(false));
Darin Petkovb451d6e2012-04-23 11:56:41 +0200164 EXPECT_CALL(storage, GetCryptedString(kStorageID, kPasswordProperty, _))
Darin Petkovcb715292012-04-25 13:04:37 +0200165 .WillOnce(DoAll(SetArgumentPointee<2>(string(kPassword)), Return(true)));
Darin Petkovb451d6e2012-04-23 11:56:41 +0200166 EXPECT_TRUE(driver_.Load(&storage, kStorageID));
167 EXPECT_EQ(kPort, GetArgs()->LookupString(kPortProperty, ""));
Darin Petkovcb715292012-04-25 13:04:37 +0200168 EXPECT_EQ(kPIN, GetArgs()->LookupString(kPINProperty, ""));
Darin Petkovb451d6e2012-04-23 11:56:41 +0200169 EXPECT_EQ(kPassword, GetArgs()->LookupString(kPasswordProperty, ""));
Darin Petkov4e9066f2012-06-11 13:17:06 +0200170
171 // Properties missing from the persistent store should be deleted.
172 EXPECT_FALSE(GetArgs()->ContainsString(kHostProperty));
173 EXPECT_FALSE(GetArgs()->ContainsString(kPSKProperty));
Darin Petkovb451d6e2012-04-23 11:56:41 +0200174}
175
Darin Petkov4e9066f2012-06-11 13:17:06 +0200176TEST_F(VPNDriverTest, Save) {
Darin Petkov4e02ba22013-04-02 13:44:08 +0200177 SetArg(flimflam::kProviderTypeProperty, "");
Darin Petkovcb715292012-04-25 13:04:37 +0200178 SetArg(kPINProperty, kPIN);
Darin Petkovb451d6e2012-04-23 11:56:41 +0200179 SetArg(kPortProperty, kPort);
180 SetArg(kPasswordProperty, kPassword);
181 SetArg(kOTPProperty, "987654");
182 MockStore storage;
Darin Petkov4e9066f2012-06-11 13:17:06 +0200183 EXPECT_CALL(storage,
Darin Petkov4e02ba22013-04-02 13:44:08 +0200184 SetString(kStorageID, flimflam::kProviderTypeProperty, ""))
Darin Petkov4e9066f2012-06-11 13:17:06 +0200185 .WillOnce(Return(true));
Darin Petkovb451d6e2012-04-23 11:56:41 +0200186 EXPECT_CALL(storage, SetString(kStorageID, kPortProperty, kPort))
187 .WillOnce(Return(true));
Darin Petkovcb715292012-04-25 13:04:37 +0200188 EXPECT_CALL(storage, SetString(kStorageID, kPINProperty, kPIN))
189 .WillOnce(Return(true));
Darin Petkovb451d6e2012-04-23 11:56:41 +0200190 EXPECT_CALL(storage,
191 SetCryptedString(kStorageID, kPasswordProperty, kPassword))
192 .WillOnce(Return(true));
Darin Petkovcb715292012-04-25 13:04:37 +0200193 EXPECT_CALL(storage, SetCryptedString(_, kOTPProperty, _)).Times(0);
194 EXPECT_CALL(storage, SetString(_, kOTPProperty, _)).Times(0);
Darin Petkov4e02ba22013-04-02 13:44:08 +0200195 EXPECT_CALL(storage, DeleteKey(kStorageID, flimflam::kProviderTypeProperty))
Darin Petkov4e9066f2012-06-11 13:17:06 +0200196 .Times(0);
197 EXPECT_CALL(storage, DeleteKey(kStorageID, kPSKProperty)).Times(1);
Darin Petkovb451d6e2012-04-23 11:56:41 +0200198 EXPECT_CALL(storage, DeleteKey(kStorageID, kHostProperty)).Times(1);
Darin Petkovcb715292012-04-25 13:04:37 +0200199 EXPECT_TRUE(driver_.Save(&storage, kStorageID, true));
200}
201
Darin Petkov4e9066f2012-06-11 13:17:06 +0200202TEST_F(VPNDriverTest, SaveNoCredentials) {
Darin Petkovcb715292012-04-25 13:04:37 +0200203 SetArg(kPasswordProperty, kPassword);
Darin Petkov4e9066f2012-06-11 13:17:06 +0200204 SetArg(kPSKProperty, "");
Darin Petkovcb715292012-04-25 13:04:37 +0200205 MockStore storage;
206 EXPECT_CALL(storage, SetString(_, kPasswordProperty, _)).Times(0);
207 EXPECT_CALL(storage, SetCryptedString(_, kPasswordProperty, _)).Times(0);
208 EXPECT_CALL(storage, DeleteKey(kStorageID, _)).Times(AnyNumber());
209 EXPECT_CALL(storage, DeleteKey(kStorageID, kPasswordProperty)).Times(1);
Darin Petkov4e9066f2012-06-11 13:17:06 +0200210 EXPECT_CALL(storage, DeleteKey(kStorageID, kPSKProperty)).Times(1);
Darin Petkovcb715292012-04-25 13:04:37 +0200211 EXPECT_TRUE(driver_.Save(&storage, kStorageID, false));
212}
213
214TEST_F(VPNDriverTest, UnloadCredentials) {
215 SetArg(kOTPProperty, "654321");
216 SetArg(kPasswordProperty, kPassword);
217 SetArg(kPortProperty, kPort);
218 driver_.UnloadCredentials();
219 EXPECT_FALSE(GetArgs()->ContainsString(kOTPProperty));
220 EXPECT_FALSE(GetArgs()->ContainsString(kPasswordProperty));
221 EXPECT_EQ(kPort, GetArgs()->LookupString(kPortProperty, ""));
Darin Petkovb451d6e2012-04-23 11:56:41 +0200222}
223
224TEST_F(VPNDriverTest, InitPropertyStore) {
225 // Figure out if the store is actually hooked up to the driver argument
226 // KeyValueStore.
227 PropertyStore store;
228 driver_.InitPropertyStore(&store);
229
230 // An un-set property should not be readable.
Paul Stewarte6e8e492013-01-17 11:00:50 -0800231 {
232 Error error;
233 EXPECT_FALSE(store.GetStringProperty(kPortProperty, NULL, &error));
234 EXPECT_EQ(Error::kInvalidArguments, error.type());
235 }
Paul Stewart8e7e4592012-04-29 09:47:48 -0700236 EXPECT_FALSE(GetProviderProperty(store, kPortProperty, NULL));
Darin Petkovb451d6e2012-04-23 11:56:41 +0200237
Darin Petkov4e02ba22013-04-02 13:44:08 +0200238 const string kProviderType = "boo";
Darin Petkovb451d6e2012-04-23 11:56:41 +0200239 SetArg(kPortProperty, kPort);
240 SetArg(kPasswordProperty, kPassword);
Darin Petkov4e02ba22013-04-02 13:44:08 +0200241 SetArg(flimflam::kProviderTypeProperty, kProviderType);
Darin Petkov4e9066f2012-06-11 13:17:06 +0200242 SetArg(kHostProperty, "");
Darin Petkovb451d6e2012-04-23 11:56:41 +0200243
244 // We should not be able to read a property out of the driver args using the
245 // key to the args directly.
Paul Stewarte6e8e492013-01-17 11:00:50 -0800246 {
247 Error error;
248 EXPECT_FALSE(store.GetStringProperty(kPortProperty, NULL, &error));
249 EXPECT_EQ(Error::kInvalidArguments, error.type());
250 }
Darin Petkovb451d6e2012-04-23 11:56:41 +0200251
252 // We should instead be able to find it within the "Provider" stringmap.
Paul Stewarte6e8e492013-01-17 11:00:50 -0800253 {
254 string value;
255 EXPECT_TRUE(GetProviderProperty(store, kPortProperty, &value));
256 EXPECT_EQ(kPort, value);
257 }
Darin Petkovb451d6e2012-04-23 11:56:41 +0200258
Darin Petkov4e9066f2012-06-11 13:17:06 +0200259 // We should be able to read empty properties from the "Provider" stringmap.
260 {
261 string value;
262 EXPECT_TRUE(GetProviderProperty(store, kHostProperty, &value));
263 EXPECT_TRUE(value.empty());
264 }
265
Darin Petkovb451d6e2012-04-23 11:56:41 +0200266 // Properties that start with the prefix "Provider." should be mapped to the
267 // name in the Properties dict with the prefix removed.
Paul Stewarte6e8e492013-01-17 11:00:50 -0800268 {
269 string value;
Darin Petkov4e02ba22013-04-02 13:44:08 +0200270 EXPECT_TRUE(GetProviderProperty(store, flimflam::kTypeProperty, &value));
271 EXPECT_EQ(kProviderType, value);
Paul Stewarte6e8e492013-01-17 11:00:50 -0800272 }
Darin Petkovb451d6e2012-04-23 11:56:41 +0200273
Paul Stewart8e7e4592012-04-29 09:47:48 -0700274 // If we clear a property, we should no longer be able to find it.
Darin Petkovb451d6e2012-04-23 11:56:41 +0200275 {
276 Error error;
277 EXPECT_TRUE(store.ClearProperty(kPortProperty, &error));
278 EXPECT_TRUE(error.IsSuccess());
Paul Stewart8e7e4592012-04-29 09:47:48 -0700279 EXPECT_FALSE(GetProviderProperty(store, kPortProperty, NULL));
Darin Petkovb451d6e2012-04-23 11:56:41 +0200280 }
281
282 // A second attempt to clear this property should return an error.
283 {
284 Error error;
285 EXPECT_FALSE(store.ClearProperty(kPortProperty, &error));
286 EXPECT_EQ(Error::kNotFound, error.type());
287 }
288
Darin Petkovcb715292012-04-25 13:04:37 +0200289 // Test write only properties.
Paul Stewart8e7e4592012-04-29 09:47:48 -0700290 EXPECT_FALSE(GetProviderProperty(store, kPINProperty, NULL));
Darin Petkovb451d6e2012-04-23 11:56:41 +0200291
292 // Write properties to the driver args using the PropertyStore interface.
Darin Petkovcb715292012-04-25 13:04:37 +0200293 {
294 const string kValue = "some-value";
Darin Petkovb451d6e2012-04-23 11:56:41 +0200295 Error error;
Darin Petkovcb715292012-04-25 13:04:37 +0200296 EXPECT_TRUE(store.SetStringProperty(kPINProperty, kValue, &error));
297 EXPECT_EQ(kValue, GetArgs()->GetString(kPINProperty));
Darin Petkovb451d6e2012-04-23 11:56:41 +0200298 }
299}
300
Darin Petkov602303f2012-06-06 12:15:59 +0200301TEST_F(VPNDriverTest, ConnectTimeout) {
Darin Petkov0cd0d1e2013-02-11 12:49:10 +0100302 EXPECT_EQ(&dispatcher_, dispatcher());
303 EXPECT_TRUE(connect_timeout_callback().IsCancelled());
304 EXPECT_FALSE(IsConnectTimeoutStarted());
305 StartConnectTimeout(0);
306 EXPECT_FALSE(connect_timeout_callback().IsCancelled());
307 EXPECT_TRUE(IsConnectTimeoutStarted());
308 set_dispatcher(NULL);
309 StartConnectTimeout(0); // Expect no crash.
Darin Petkov602303f2012-06-06 12:15:59 +0200310 dispatcher_.DispatchPendingEvents();
Darin Petkov0cd0d1e2013-02-11 12:49:10 +0100311 EXPECT_TRUE(connect_timeout_callback().IsCancelled());
312 EXPECT_FALSE(IsConnectTimeoutStarted());
313}
314
315TEST_F(VPNDriverTest, StartStopConnectTimeout) {
316 EXPECT_FALSE(IsConnectTimeoutStarted());
317 EXPECT_EQ(0, connect_timeout_seconds());
318 const int kTimeout = 123;
319 StartConnectTimeout(kTimeout);
320 EXPECT_TRUE(IsConnectTimeoutStarted());
321 EXPECT_EQ(kTimeout, connect_timeout_seconds());
322 StartConnectTimeout(kTimeout - 20);
323 EXPECT_EQ(kTimeout, connect_timeout_seconds());
324 StopConnectTimeout();
325 EXPECT_FALSE(IsConnectTimeoutStarted());
326 EXPECT_EQ(0, connect_timeout_seconds());
Darin Petkov602303f2012-06-06 12:15:59 +0200327}
328
Darin Petkovb451d6e2012-04-23 11:56:41 +0200329} // namespace shill