blob: 83e2e61c58dd6de4f5e80a1ad960fd9720b722e5 [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"
Paul Stewart8e7e4592012-04-29 09:47:48 -070024#include "shill/property_store_inspector.h"
Darin Petkovb451d6e2012-04-23 11:56:41 +020025
26using std::string;
27using testing::_;
28using testing::AnyNumber;
Darin Petkov0e9735d2012-04-24 12:33:45 +020029using testing::NiceMock;
Darin Petkovb451d6e2012-04-23 11:56:41 +020030using testing::Return;
31using testing::SetArgumentPointee;
Darin Petkov0e9735d2012-04-24 12:33:45 +020032using testing::StrictMock;
Darin Petkovb451d6e2012-04-23 11:56:41 +020033using testing::Test;
34
35namespace shill {
36
37namespace {
Darin Petkov602303f2012-06-06 12:15:59 +020038
Darin Petkovb451d6e2012-04-23 11:56:41 +020039const char kHostProperty[] = "VPN.Host";
40const char kOTPProperty[] = "VPN.OTP";
Darin Petkovcb715292012-04-25 13:04:37 +020041const char kPINProperty[] = "VPN.PIN";
Darin Petkov4e9066f2012-06-11 13:17:06 +020042const char kPSKProperty[] = "VPN.PSK";
Darin Petkovb451d6e2012-04-23 11:56:41 +020043const char kPasswordProperty[] = "VPN.Password";
44const char kPortProperty[] = "VPN.Port";
Darin Petkovcb715292012-04-25 13:04:37 +020045
46const char kPIN[] = "5555";
47const char kPassword[] = "random-password";
48const char kPort[] = "1234";
49const char kStorageID[] = "vpn_service_id";
50
Darin Petkovb451d6e2012-04-23 11:56:41 +020051} // namespace
52
53class VPNDriverUnderTest : public VPNDriver {
54 public:
Darin Petkov602303f2012-06-06 12:15:59 +020055 VPNDriverUnderTest(EventDispatcher *dispatcher, Manager *manager);
Darin Petkovb451d6e2012-04-23 11:56:41 +020056 virtual ~VPNDriverUnderTest() {}
57
58 // Inherited from VPNDriver.
59 MOCK_METHOD2(ClaimInterface, bool(const string &link_name,
60 int interface_index));
61 MOCK_METHOD2(Connect, void(const VPNServiceRefPtr &service, Error *error));
62 MOCK_METHOD0(Disconnect, void());
Darin Petkov5eb05422012-05-11 15:45:25 +020063 MOCK_METHOD0(OnConnectionDisconnected, void());
Darin Petkovb451d6e2012-04-23 11:56:41 +020064 MOCK_CONST_METHOD0(GetProviderType, string());
65
66 private:
67 static const Property kProperties[];
68
69 DISALLOW_COPY_AND_ASSIGN(VPNDriverUnderTest);
70};
71
72// static
73const VPNDriverUnderTest::Property VPNDriverUnderTest::kProperties[] = {
74 { kHostProperty, 0 },
Darin Petkovcb715292012-04-25 13:04:37 +020075 { kOTPProperty, Property::kEphemeral },
76 { kPINProperty, Property::kWriteOnly },
Darin Petkov4e9066f2012-06-11 13:17:06 +020077 { kPSKProperty, Property::kCredential },
Darin Petkovcb715292012-04-25 13:04:37 +020078 { kPasswordProperty, Property::kCredential },
Darin Petkovb451d6e2012-04-23 11:56:41 +020079 { kPortProperty, 0 },
80 { flimflam::kProviderNameProperty, 0 },
81};
82
Darin Petkov602303f2012-06-06 12:15:59 +020083VPNDriverUnderTest::VPNDriverUnderTest(
84 EventDispatcher *dispatcher, Manager *manager)
85 : VPNDriver(dispatcher, manager, kProperties, arraysize(kProperties)) {}
Darin Petkovb451d6e2012-04-23 11:56:41 +020086
87class VPNDriverTest : public Test {
88 public:
Darin Petkov0e9735d2012-04-24 12:33:45 +020089 VPNDriverTest()
90 : device_info_(&control_, &dispatcher_, &metrics_, &manager_),
91 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:
97 void SetArg(const string &arg, const string &value) {
98 driver_.args()->SetString(arg, value);
99 }
100
101 KeyValueStore *GetArgs() { return driver_.args(); }
102
Paul Stewart8e7e4592012-04-29 09:47:48 -0700103 bool GetProviderProperty(const PropertyStore &store,
104 const string &key,
105 string *value);
Darin Petkovb451d6e2012-04-23 11:56:41 +0200106
Darin Petkov0e9735d2012-04-24 12:33:45 +0200107 NiceMockControl control_;
108 NiceMock<MockDeviceInfo> device_info_;
109 EventDispatcher dispatcher_;
110 MockMetrics metrics_;
111 MockGLib glib_;
112 MockManager manager_;
Darin Petkovb451d6e2012-04-23 11:56:41 +0200113 VPNDriverUnderTest driver_;
114};
115
Paul Stewart8e7e4592012-04-29 09:47:48 -0700116bool VPNDriverTest::GetProviderProperty(const PropertyStore &store,
117 const string &key,
118 string *value) {
Paul Stewart8e7e4592012-04-29 09:47:48 -0700119 PropertyStoreInspector inspector(&store);
120 KeyValueStore provider_properties;
121 EXPECT_TRUE(inspector.GetKeyValueStoreProperty(
Darin Petkov4682aa82012-05-31 16:24:11 +0200122 flimflam::kProviderProperty, &provider_properties));
Paul Stewart8e7e4592012-04-29 09:47:48 -0700123 if (!provider_properties.ContainsString(key)) {
124 return false;
Darin Petkovb451d6e2012-04-23 11:56:41 +0200125 }
Paul Stewart8e7e4592012-04-29 09:47:48 -0700126 if (value != NULL) {
127 *value = provider_properties.GetString(key);
Darin Petkovb451d6e2012-04-23 11:56:41 +0200128 }
Paul Stewart8e7e4592012-04-29 09:47:48 -0700129 return true;
Darin Petkovb451d6e2012-04-23 11:56:41 +0200130}
131
132TEST_F(VPNDriverTest, Load) {
133 MockStore storage;
Darin Petkov4e9066f2012-06-11 13:17:06 +0200134 GetArgs()->SetString(kHostProperty, "1.2.3.4");
135 GetArgs()->SetString(kPSKProperty, "1234");
Darin Petkovb451d6e2012-04-23 11:56:41 +0200136 EXPECT_CALL(storage, GetString(kStorageID, _, _))
137 .WillRepeatedly(Return(false));
Darin Petkovcb715292012-04-25 13:04:37 +0200138 EXPECT_CALL(storage, GetString(_, kOTPProperty, _)).Times(0);
139 EXPECT_CALL(storage, GetCryptedString(_, kOTPProperty, _)).Times(0);
Darin Petkovb451d6e2012-04-23 11:56:41 +0200140 EXPECT_CALL(storage, GetString(kStorageID, kPortProperty, _))
Darin Petkovcb715292012-04-25 13:04:37 +0200141 .WillOnce(DoAll(SetArgumentPointee<2>(string(kPort)), Return(true)));
142 EXPECT_CALL(storage, GetString(kStorageID, kPINProperty, _))
143 .WillOnce(DoAll(SetArgumentPointee<2>(string(kPIN)), Return(true)));
Darin Petkov4e9066f2012-06-11 13:17:06 +0200144 EXPECT_CALL(storage, GetCryptedString(kStorageID, kPSKProperty, _))
145 .WillOnce(Return(false));
Darin Petkovb451d6e2012-04-23 11:56:41 +0200146 EXPECT_CALL(storage, GetCryptedString(kStorageID, kPasswordProperty, _))
Darin Petkovcb715292012-04-25 13:04:37 +0200147 .WillOnce(DoAll(SetArgumentPointee<2>(string(kPassword)), Return(true)));
Darin Petkovb451d6e2012-04-23 11:56:41 +0200148 EXPECT_TRUE(driver_.Load(&storage, kStorageID));
149 EXPECT_EQ(kPort, GetArgs()->LookupString(kPortProperty, ""));
Darin Petkovcb715292012-04-25 13:04:37 +0200150 EXPECT_EQ(kPIN, GetArgs()->LookupString(kPINProperty, ""));
Darin Petkovb451d6e2012-04-23 11:56:41 +0200151 EXPECT_EQ(kPassword, GetArgs()->LookupString(kPasswordProperty, ""));
Darin Petkov4e9066f2012-06-11 13:17:06 +0200152
153 // Properties missing from the persistent store should be deleted.
154 EXPECT_FALSE(GetArgs()->ContainsString(kHostProperty));
155 EXPECT_FALSE(GetArgs()->ContainsString(kPSKProperty));
Darin Petkovb451d6e2012-04-23 11:56:41 +0200156}
157
Darin Petkov4e9066f2012-06-11 13:17:06 +0200158TEST_F(VPNDriverTest, Save) {
159 SetArg(flimflam::kProviderNameProperty, "");
Darin Petkovcb715292012-04-25 13:04:37 +0200160 SetArg(kPINProperty, kPIN);
Darin Petkovb451d6e2012-04-23 11:56:41 +0200161 SetArg(kPortProperty, kPort);
162 SetArg(kPasswordProperty, kPassword);
163 SetArg(kOTPProperty, "987654");
164 MockStore storage;
Darin Petkov4e9066f2012-06-11 13:17:06 +0200165 EXPECT_CALL(storage,
166 SetString(kStorageID, flimflam::kProviderNameProperty, ""))
167 .WillOnce(Return(true));
Darin Petkovb451d6e2012-04-23 11:56:41 +0200168 EXPECT_CALL(storage, SetString(kStorageID, kPortProperty, kPort))
169 .WillOnce(Return(true));
Darin Petkovcb715292012-04-25 13:04:37 +0200170 EXPECT_CALL(storage, SetString(kStorageID, kPINProperty, kPIN))
171 .WillOnce(Return(true));
Darin Petkovb451d6e2012-04-23 11:56:41 +0200172 EXPECT_CALL(storage,
173 SetCryptedString(kStorageID, kPasswordProperty, kPassword))
174 .WillOnce(Return(true));
Darin Petkovcb715292012-04-25 13:04:37 +0200175 EXPECT_CALL(storage, SetCryptedString(_, kOTPProperty, _)).Times(0);
176 EXPECT_CALL(storage, SetString(_, kOTPProperty, _)).Times(0);
Darin Petkov4e9066f2012-06-11 13:17:06 +0200177 EXPECT_CALL(storage, DeleteKey(kStorageID, flimflam::kProviderNameProperty))
178 .Times(0);
179 EXPECT_CALL(storage, DeleteKey(kStorageID, kPSKProperty)).Times(1);
Darin Petkovb451d6e2012-04-23 11:56:41 +0200180 EXPECT_CALL(storage, DeleteKey(kStorageID, kHostProperty)).Times(1);
Darin Petkovcb715292012-04-25 13:04:37 +0200181 EXPECT_TRUE(driver_.Save(&storage, kStorageID, true));
182}
183
Darin Petkov4e9066f2012-06-11 13:17:06 +0200184TEST_F(VPNDriverTest, SaveNoCredentials) {
Darin Petkovcb715292012-04-25 13:04:37 +0200185 SetArg(kPasswordProperty, kPassword);
Darin Petkov4e9066f2012-06-11 13:17:06 +0200186 SetArg(kPSKProperty, "");
Darin Petkovcb715292012-04-25 13:04:37 +0200187 MockStore storage;
188 EXPECT_CALL(storage, SetString(_, kPasswordProperty, _)).Times(0);
189 EXPECT_CALL(storage, SetCryptedString(_, kPasswordProperty, _)).Times(0);
190 EXPECT_CALL(storage, DeleteKey(kStorageID, _)).Times(AnyNumber());
191 EXPECT_CALL(storage, DeleteKey(kStorageID, kPasswordProperty)).Times(1);
Darin Petkov4e9066f2012-06-11 13:17:06 +0200192 EXPECT_CALL(storage, DeleteKey(kStorageID, kPSKProperty)).Times(1);
Darin Petkovcb715292012-04-25 13:04:37 +0200193 EXPECT_TRUE(driver_.Save(&storage, kStorageID, false));
194}
195
196TEST_F(VPNDriverTest, UnloadCredentials) {
197 SetArg(kOTPProperty, "654321");
198 SetArg(kPasswordProperty, kPassword);
199 SetArg(kPortProperty, kPort);
200 driver_.UnloadCredentials();
201 EXPECT_FALSE(GetArgs()->ContainsString(kOTPProperty));
202 EXPECT_FALSE(GetArgs()->ContainsString(kPasswordProperty));
203 EXPECT_EQ(kPort, GetArgs()->LookupString(kPortProperty, ""));
Darin Petkovb451d6e2012-04-23 11:56:41 +0200204}
205
206TEST_F(VPNDriverTest, InitPropertyStore) {
207 // Figure out if the store is actually hooked up to the driver argument
208 // KeyValueStore.
209 PropertyStore store;
210 driver_.InitPropertyStore(&store);
Paul Stewart8e7e4592012-04-29 09:47:48 -0700211 PropertyStoreInspector inspector(&store);
Darin Petkovb451d6e2012-04-23 11:56:41 +0200212
213 // An un-set property should not be readable.
Darin Petkov4682aa82012-05-31 16:24:11 +0200214 EXPECT_FALSE(inspector.GetStringProperty(kPortProperty, NULL));
Paul Stewart8e7e4592012-04-29 09:47:48 -0700215 EXPECT_FALSE(GetProviderProperty(store, kPortProperty, NULL));
Darin Petkovb451d6e2012-04-23 11:56:41 +0200216
Darin Petkovb451d6e2012-04-23 11:56:41 +0200217 const string kProviderName = "boo";
218 SetArg(kPortProperty, kPort);
219 SetArg(kPasswordProperty, kPassword);
220 SetArg(flimflam::kProviderNameProperty, kProviderName);
Darin Petkov4e9066f2012-06-11 13:17:06 +0200221 SetArg(kHostProperty, "");
Darin Petkovb451d6e2012-04-23 11:56:41 +0200222
223 // We should not be able to read a property out of the driver args using the
224 // key to the args directly.
Darin Petkov4682aa82012-05-31 16:24:11 +0200225 EXPECT_FALSE(inspector.GetStringProperty(kPortProperty, NULL));
Darin Petkovb451d6e2012-04-23 11:56:41 +0200226
227 // We should instead be able to find it within the "Provider" stringmap.
Paul Stewart8e7e4592012-04-29 09:47:48 -0700228 string value;
229 EXPECT_TRUE(GetProviderProperty(store, kPortProperty, &value));
230 EXPECT_EQ(kPort, value);
Darin Petkovb451d6e2012-04-23 11:56:41 +0200231
Darin Petkov4e9066f2012-06-11 13:17:06 +0200232 // We should be able to read empty properties from the "Provider" stringmap.
233 {
234 string value;
235 EXPECT_TRUE(GetProviderProperty(store, kHostProperty, &value));
236 EXPECT_TRUE(value.empty());
237 }
238
Darin Petkovb451d6e2012-04-23 11:56:41 +0200239 // Properties that start with the prefix "Provider." should be mapped to the
240 // name in the Properties dict with the prefix removed.
Paul Stewart8e7e4592012-04-29 09:47:48 -0700241 EXPECT_TRUE(GetProviderProperty(store, flimflam::kNameProperty, &value));
242 EXPECT_EQ(kProviderName, value);
Darin Petkovb451d6e2012-04-23 11:56:41 +0200243
Paul Stewart8e7e4592012-04-29 09:47:48 -0700244 // If we clear a property, we should no longer be able to find it.
Darin Petkovb451d6e2012-04-23 11:56:41 +0200245 {
246 Error error;
247 EXPECT_TRUE(store.ClearProperty(kPortProperty, &error));
248 EXPECT_TRUE(error.IsSuccess());
Paul Stewart8e7e4592012-04-29 09:47:48 -0700249 EXPECT_FALSE(GetProviderProperty(store, kPortProperty, NULL));
Darin Petkovb451d6e2012-04-23 11:56:41 +0200250 }
251
252 // A second attempt to clear this property should return an error.
253 {
254 Error error;
255 EXPECT_FALSE(store.ClearProperty(kPortProperty, &error));
256 EXPECT_EQ(Error::kNotFound, error.type());
257 }
258
Darin Petkovcb715292012-04-25 13:04:37 +0200259 // Test write only properties.
Paul Stewart8e7e4592012-04-29 09:47:48 -0700260 EXPECT_FALSE(GetProviderProperty(store, kPINProperty, NULL));
Darin Petkovb451d6e2012-04-23 11:56:41 +0200261
262 // Write properties to the driver args using the PropertyStore interface.
Darin Petkovcb715292012-04-25 13:04:37 +0200263 {
264 const string kValue = "some-value";
Darin Petkovb451d6e2012-04-23 11:56:41 +0200265 Error error;
Darin Petkovcb715292012-04-25 13:04:37 +0200266 EXPECT_TRUE(store.SetStringProperty(kPINProperty, kValue, &error));
267 EXPECT_EQ(kValue, GetArgs()->GetString(kPINProperty));
Darin Petkovb451d6e2012-04-23 11:56:41 +0200268 }
269}
270
Darin Petkov602303f2012-06-06 12:15:59 +0200271TEST_F(VPNDriverTest, ConnectTimeout) {
272 EXPECT_EQ(&dispatcher_, driver_.dispatcher_);
273 EXPECT_TRUE(driver_.connect_timeout_callback_.IsCancelled());
274 EXPECT_FALSE(driver_.IsConnectTimeoutStarted());
275 EXPECT_EQ(VPNDriver::kDefaultConnectTimeoutSeconds,
276 driver_.connect_timeout_seconds_);
277 driver_.connect_timeout_seconds_ = 0;
278 driver_.StartConnectTimeout();
279 EXPECT_FALSE(driver_.connect_timeout_callback_.IsCancelled());
280 EXPECT_TRUE(driver_.IsConnectTimeoutStarted());
281 driver_.dispatcher_ = NULL;
282 driver_.StartConnectTimeout(); // Expect no crash.
283 EXPECT_CALL(driver_, OnConnectionDisconnected());
284 dispatcher_.DispatchPendingEvents();
285 EXPECT_TRUE(driver_.connect_timeout_callback_.IsCancelled());
286 EXPECT_FALSE(driver_.IsConnectTimeoutStarted());
287}
288
Darin Petkovb451d6e2012-04-23 11:56:41 +0200289} // namespace shill