blob: 041c4a05ddf900c28101d30bdb6dbc906c1f876b [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 {
37const char kHostProperty[] = "VPN.Host";
38const char kOTPProperty[] = "VPN.OTP";
39const char kPasswordProperty[] = "VPN.Password";
40const char kPortProperty[] = "VPN.Port";
41} // namespace
42
43class VPNDriverUnderTest : public VPNDriver {
44 public:
Darin Petkov0e9735d2012-04-24 12:33:45 +020045 VPNDriverUnderTest(Manager *manager);
Darin Petkovb451d6e2012-04-23 11:56:41 +020046 virtual ~VPNDriverUnderTest() {}
47
48 // Inherited from VPNDriver.
49 MOCK_METHOD2(ClaimInterface, bool(const string &link_name,
50 int interface_index));
51 MOCK_METHOD2(Connect, void(const VPNServiceRefPtr &service, Error *error));
52 MOCK_METHOD0(Disconnect, void());
53 MOCK_CONST_METHOD0(GetProviderType, string());
54
55 private:
56 static const Property kProperties[];
57
58 DISALLOW_COPY_AND_ASSIGN(VPNDriverUnderTest);
59};
60
61// static
62const VPNDriverUnderTest::Property VPNDriverUnderTest::kProperties[] = {
63 { kHostProperty, 0 },
64 { kOTPProperty, Property::kEphemeral | Property::kCrypted },
65 { kPasswordProperty, Property::kCrypted },
66 { kPortProperty, 0 },
67 { flimflam::kProviderNameProperty, 0 },
68};
69
Darin Petkov0e9735d2012-04-24 12:33:45 +020070VPNDriverUnderTest::VPNDriverUnderTest(Manager *manager)
71 : VPNDriver(manager, kProperties, arraysize(kProperties)) {}
Darin Petkovb451d6e2012-04-23 11:56:41 +020072
73class VPNDriverTest : public Test {
74 public:
Darin Petkov0e9735d2012-04-24 12:33:45 +020075 VPNDriverTest()
76 : device_info_(&control_, &dispatcher_, &metrics_, &manager_),
77 manager_(&control_, &dispatcher_, &metrics_, &glib_),
78 driver_(&manager_) {}
Darin Petkovb451d6e2012-04-23 11:56:41 +020079
80 virtual ~VPNDriverTest() {}
81
82 protected:
83 void SetArg(const string &arg, const string &value) {
84 driver_.args()->SetString(arg, value);
85 }
86
87 KeyValueStore *GetArgs() { return driver_.args(); }
88
89 bool FindStringPropertyInStore(const PropertyStore &store,
90 const string &key,
91 string *value,
92 Error *error);
93 bool FindStringmapPropertyInStore(const PropertyStore &store,
94 const string &key,
95 Stringmap *value,
96 Error *error);
97
Darin Petkov0e9735d2012-04-24 12:33:45 +020098 NiceMockControl control_;
99 NiceMock<MockDeviceInfo> device_info_;
100 EventDispatcher dispatcher_;
101 MockMetrics metrics_;
102 MockGLib glib_;
103 MockManager manager_;
Darin Petkovb451d6e2012-04-23 11:56:41 +0200104 VPNDriverUnderTest driver_;
105};
106
107bool VPNDriverTest::FindStringPropertyInStore(const PropertyStore &store,
108 const string &key,
109 string *value,
110 Error *error) {
111 ReadablePropertyConstIterator<std::string> it =
112 store.GetStringPropertiesIter();
113 for ( ; !it.AtEnd(); it.Advance()) {
114 if (it.Key() == key) {
115 *value = it.Value(error);
116 return error->IsSuccess();
117 }
118 }
119 error->Populate(Error::kNotFound);
120 return false;
121}
122
123bool VPNDriverTest::FindStringmapPropertyInStore(const PropertyStore &store,
124 const string &key,
125 Stringmap *value,
126 Error *error) {
127 ReadablePropertyConstIterator<Stringmap> it =
128 store.GetStringmapPropertiesIter();
129 for ( ; !it.AtEnd(); it.Advance()) {
130 if (it.Key() == key) {
131 *value = it.Value(error);
132 return error->IsSuccess();
133 }
134 }
135 error->Populate(Error::kNotFound);
136 return false;
137}
138
139TEST_F(VPNDriverTest, Load) {
140 MockStore storage;
141 static const char kStorageID[] = "vpn_service_id";
142 const string kPort = "1234";
143 const string kPassword = "random-password";
144 EXPECT_CALL(storage, GetString(kStorageID, _, _))
145 .WillRepeatedly(Return(false));
146 EXPECT_CALL(storage, GetString(kStorageID, kOTPProperty, _)).Times(0);
147 EXPECT_CALL(storage, GetCryptedString(kStorageID, kOTPProperty, _)).Times(0);
148 EXPECT_CALL(storage, GetString(kStorageID, kPortProperty, _))
149 .WillOnce(DoAll(SetArgumentPointee<2>(kPort), Return(true)));
150 EXPECT_CALL(storage, GetCryptedString(kStorageID, kPasswordProperty, _))
151 .WillOnce(DoAll(SetArgumentPointee<2>(kPassword), Return(true)));
152 EXPECT_TRUE(driver_.Load(&storage, kStorageID));
153 EXPECT_EQ(kPort, GetArgs()->LookupString(kPortProperty, ""));
154 EXPECT_EQ(kPassword, GetArgs()->LookupString(kPasswordProperty, ""));
155}
156
157TEST_F(VPNDriverTest, Store) {
158 const string kPort = "1234";
159 const string kPassword = "foobar";
160 SetArg(kPortProperty, kPort);
161 SetArg(kPasswordProperty, kPassword);
162 SetArg(kOTPProperty, "987654");
163 MockStore storage;
164 static const char kStorageID[] = "vpn_service_id";
165 EXPECT_CALL(storage, SetString(kStorageID, kPortProperty, kPort))
166 .WillOnce(Return(true));
167 EXPECT_CALL(storage,
168 SetCryptedString(kStorageID, kPasswordProperty, kPassword))
169 .WillOnce(Return(true));
170 EXPECT_CALL(storage, SetCryptedString(kStorageID, kOTPProperty, _)).Times(0);
171 EXPECT_CALL(storage, SetString(kStorageID, kOTPProperty, _)).Times(0);
172 EXPECT_CALL(storage, DeleteKey(kStorageID, _)).Times(AnyNumber());
173 EXPECT_CALL(storage, DeleteKey(kStorageID, kHostProperty)).Times(1);
174 EXPECT_TRUE(driver_.Save(&storage, kStorageID));
175}
176
177TEST_F(VPNDriverTest, InitPropertyStore) {
178 // Figure out if the store is actually hooked up to the driver argument
179 // KeyValueStore.
180 PropertyStore store;
181 driver_.InitPropertyStore(&store);
182
183 // An un-set property should not be readable.
184 {
185 Error error;
186 string string_property;
187 EXPECT_FALSE(
188 FindStringPropertyInStore(
189 store, kPortProperty, &string_property, &error));
190 EXPECT_EQ(Error::kNotFound, error.type());
191 }
192
193 const string kPort = "1234";
194 const string kPassword = "foobar";
195 const string kProviderName = "boo";
196 SetArg(kPortProperty, kPort);
197 SetArg(kPasswordProperty, kPassword);
198 SetArg(flimflam::kProviderNameProperty, kProviderName);
199
200 // We should not be able to read a property out of the driver args using the
201 // key to the args directly.
202 {
203 Error error;
204 string string_property;
205 EXPECT_FALSE(
206 FindStringPropertyInStore(
207 store, kPortProperty, &string_property, &error));
208 EXPECT_EQ(Error::kNotFound, error.type());
209 }
210
211 // We should instead be able to find it within the "Provider" stringmap.
212 {
213 Error error;
214 Stringmap provider_properties;
215 EXPECT_TRUE(
216 FindStringmapPropertyInStore(
217 store, flimflam::kProviderProperty, &provider_properties, &error));
218 EXPECT_TRUE(ContainsKey(provider_properties, kPortProperty));
219 EXPECT_EQ(kPort, provider_properties[kPortProperty]);
220 }
221
222 // Properties that start with the prefix "Provider." should be mapped to the
223 // name in the Properties dict with the prefix removed.
224 {
225 Error error;
226 Stringmap provider_properties;
227 EXPECT_TRUE(
228 FindStringmapPropertyInStore(
229 store, flimflam::kProviderProperty, &provider_properties, &error));
230 EXPECT_TRUE(ContainsKey(provider_properties, flimflam::kNameProperty));
231 EXPECT_EQ(kProviderName, provider_properties[flimflam::kNameProperty]);
232 }
233
234 // If we clear this property, we should no longer be able to find it.
235 {
236 Error error;
237 EXPECT_TRUE(store.ClearProperty(kPortProperty, &error));
238 EXPECT_TRUE(error.IsSuccess());
239 string string_property;
240 EXPECT_FALSE(
241 FindStringPropertyInStore(
242 store, kPortProperty, &string_property, &error));
243 EXPECT_EQ(Error::kNotFound, error.type());
244 }
245
246 // A second attempt to clear this property should return an error.
247 {
248 Error error;
249 EXPECT_FALSE(store.ClearProperty(kPortProperty, &error));
250 EXPECT_EQ(Error::kNotFound, error.type());
251 }
252
253 // These ones should be write-only.
254 static const char * const kWriteOnly[] = {
255 kPasswordProperty,
256 kOTPProperty
257 };
258
259 for (size_t i = 0; i < arraysize(kWriteOnly); i++) {
260 Error error;
261 string string_property;
262 EXPECT_FALSE(
263 FindStringPropertyInStore(
264 store, kWriteOnly[i], &string_property, &error)) << kWriteOnly[i];
265 // We get NotFound here instead of PermissionDenied here due to the
266 // implementation of ReadablePropertyConstIterator: it shields us from
267 // store members for which Value() would have returned an error.
268 EXPECT_EQ(Error::kNotFound, error.type()) << kWriteOnly[i];
269 }
270
271 // Write properties to the driver args using the PropertyStore interface.
272 for (size_t i = 0; i < arraysize(kWriteOnly); i++) {
273 string value = "some-value-" + base::UintToString(i);
274 Error error;
275 EXPECT_TRUE(store.SetStringProperty(kWriteOnly[i], value, &error))
276 << kWriteOnly[i];
277 EXPECT_EQ(value, GetArgs()->GetString(kWriteOnly[i])) << kWriteOnly[i];
278 }
279}
280
Darin Petkovb451d6e2012-04-23 11:56:41 +0200281} // namespace shill