blob: 1f2a3fa992ab6b6292d499312f09a9e9636bed34 [file] [log] [blame]
Darin Petkov33af05c2012-02-28 10:10:30 +01001// 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/openvpn_driver.h"
6
Darin Petkova9b1fed2012-02-29 11:49:05 +01007#include <algorithm>
8
Paul Stewart291a4732012-03-14 19:19:02 -07009#include <base/file_path.h>
10#include <base/file_util.h>
11#include <base/string_util.h>
Darin Petkovfe6a9372012-02-28 16:25:06 +010012#include <chromeos/dbus/service_constants.h>
Darin Petkov33af05c2012-02-28 10:10:30 +010013#include <gtest/gtest.h>
14
Paul Stewartebd38562012-03-23 13:06:40 -070015#include "shill/dbus_adaptor.h"
Darin Petkov33af05c2012-02-28 10:10:30 +010016#include "shill/error.h"
Darin Petkov14c29ec2012-03-02 11:34:19 +010017#include "shill/ipconfig.h"
Darin Petkova9b1fed2012-02-29 11:49:05 +010018#include "shill/mock_adaptors.h"
Paul Stewartca6abd42012-03-01 15:45:29 -080019#include "shill/mock_device_info.h"
Darin Petkovf20994f2012-03-05 16:12:19 +010020#include "shill/mock_glib.h"
21#include "shill/mock_manager.h"
22#include "shill/mock_metrics.h"
Darin Petkov3c5e4dc2012-04-02 14:44:27 +020023#include "shill/mock_nss.h"
Darin Petkov46463022012-03-29 14:57:32 +020024#include "shill/mock_openvpn_management_server.h"
Darin Petkovf3c71d72012-03-21 12:32:15 +010025#include "shill/mock_store.h"
Darin Petkov36a3ace2012-03-06 17:22:14 +010026#include "shill/mock_vpn.h"
Darin Petkov79d74c92012-03-07 17:20:32 +010027#include "shill/mock_vpn_service.h"
Darin Petkova9b1fed2012-02-29 11:49:05 +010028#include "shill/nice_mock_control.h"
Paul Stewart8e7e4592012-04-29 09:47:48 -070029#include "shill/property_store_inspector.h"
Darin Petkova9b1fed2012-02-29 11:49:05 +010030#include "shill/rpc_task.h"
Darin Petkov55771b72012-04-25 09:25:19 +020031#include "shill/scope_logger.h"
Darin Petkovf20994f2012-03-05 16:12:19 +010032#include "shill/vpn.h"
Darin Petkov79d74c92012-03-07 17:20:32 +010033#include "shill/vpn_service.h"
Darin Petkov33af05c2012-02-28 10:10:30 +010034
Darin Petkova9b1fed2012-02-29 11:49:05 +010035using std::map;
Darin Petkovfe6a9372012-02-28 16:25:06 +010036using std::string;
37using std::vector;
Paul Stewartca6abd42012-03-01 15:45:29 -080038using testing::_;
Darin Petkovf3c71d72012-03-21 12:32:15 +010039using testing::AnyNumber;
Paul Stewartca6abd42012-03-01 15:45:29 -080040using testing::DoAll;
Darin Petkov3c5e4dc2012-04-02 14:44:27 +020041using testing::ElementsAreArray;
Darin Petkovf3c71d72012-03-21 12:32:15 +010042using testing::Ne;
Paul Stewartce4ec192012-03-14 12:53:46 -070043using testing::NiceMock;
Paul Stewartca6abd42012-03-01 15:45:29 -080044using testing::Return;
45using testing::SetArgumentPointee;
Paul Stewartce4ec192012-03-14 12:53:46 -070046using testing::StrictMock;
Darin Petkovfe6a9372012-02-28 16:25:06 +010047
Darin Petkov33af05c2012-02-28 10:10:30 +010048namespace shill {
49
Darin Petkova9b1fed2012-02-29 11:49:05 +010050class OpenVPNDriverTest : public testing::Test,
51 public RPCTaskDelegate {
Darin Petkov33af05c2012-02-28 10:10:30 +010052 public:
Darin Petkovfe6a9372012-02-28 16:25:06 +010053 OpenVPNDriverTest()
Darin Petkov0e9735d2012-04-24 12:33:45 +020054 : device_info_(&control_, &dispatcher_, &metrics_, &manager_),
Darin Petkovf20994f2012-03-05 16:12:19 +010055 manager_(&control_, &dispatcher_, &metrics_, &glib_),
Darin Petkov79d74c92012-03-07 17:20:32 +010056 driver_(new OpenVPNDriver(&control_, &dispatcher_, &metrics_, &manager_,
Paul Stewart451aa7f2012-04-11 19:07:58 -070057 &device_info_, &glib_)),
Darin Petkov79d74c92012-03-07 17:20:32 +010058 service_(new MockVPNService(&control_, &dispatcher_, &metrics_,
59 &manager_, driver_)),
60 device_(new MockVPN(&control_, &dispatcher_, &metrics_, &manager_,
Darin Petkov46463022012-03-29 14:57:32 +020061 kInterfaceName, kInterfaceIndex)),
62 management_server_(new NiceMock<MockOpenVPNManagementServer>()) {
63 driver_->management_server_.reset(management_server_);
Darin Petkov3c5e4dc2012-04-02 14:44:27 +020064 driver_->nss_ = &nss_;
Darin Petkov46463022012-03-29 14:57:32 +020065 }
Darin Petkovfe6a9372012-02-28 16:25:06 +010066
Darin Petkov33af05c2012-02-28 10:10:30 +010067 virtual ~OpenVPNDriverTest() {}
68
Darin Petkov36a3ace2012-03-06 17:22:14 +010069 virtual void TearDown() {
Darin Petkov79d74c92012-03-07 17:20:32 +010070 driver_->child_watch_tag_ = 0;
71 driver_->pid_ = 0;
72 driver_->device_ = NULL;
73 driver_->service_ = NULL;
Darin Petkov1a462de2012-05-02 11:10:48 +020074 if (!lsb_release_file_.empty()) {
75 EXPECT_TRUE(file_util::Delete(lsb_release_file_, false));
76 lsb_release_file_.clear();
77 }
Darin Petkov36a3ace2012-03-06 17:22:14 +010078 }
Darin Petkova9b1fed2012-02-29 11:49:05 +010079
Darin Petkov33af05c2012-02-28 10:10:30 +010080 protected:
Darin Petkovfe6a9372012-02-28 16:25:06 +010081 static const char kOption[];
82 static const char kProperty[];
83 static const char kValue[];
84 static const char kOption2[];
85 static const char kProperty2[];
86 static const char kValue2[];
Darin Petkov60596742012-03-05 12:17:17 +010087 static const char kGateway1[];
88 static const char kNetmask1[];
89 static const char kNetwork1[];
90 static const char kGateway2[];
91 static const char kNetmask2[];
92 static const char kNetwork2[];
Darin Petkov79d74c92012-03-07 17:20:32 +010093 static const char kInterfaceName[];
94 static const int kInterfaceIndex;
Darin Petkovfe6a9372012-02-28 16:25:06 +010095
Darin Petkovb451d6e2012-04-23 11:56:41 +020096 void SetArg(const string &arg, const string &value) {
97 driver_->args()->SetString(arg, value);
Darin Petkovfe6a9372012-02-28 16:25:06 +010098 }
99
Darin Petkovf3c71d72012-03-21 12:32:15 +0100100 KeyValueStore *GetArgs() {
Darin Petkovb451d6e2012-04-23 11:56:41 +0200101 return driver_->args();
Darin Petkovf3c71d72012-03-21 12:32:15 +0100102 }
103
Paul Stewartca6abd42012-03-01 15:45:29 -0800104 // Used to assert that a flag appears in the options.
105 void ExpectInFlags(const vector<string> &options, const string &flag,
106 const string &value);
107
Darin Petkov1a462de2012-05-02 11:10:48 +0200108 void SetupLSBRelease();
109
Darin Petkov36a3ace2012-03-06 17:22:14 +0100110 // Inherited from RPCTaskDelegate.
Darin Petkov209e6292012-04-20 11:33:32 +0200111 virtual void GetLogin(string *user, string *password);
Darin Petkov36a3ace2012-03-06 17:22:14 +0100112 virtual void Notify(const string &reason, const map<string, string> &dict);
Paul Stewartca6abd42012-03-01 15:45:29 -0800113
Darin Petkova9b1fed2012-02-29 11:49:05 +0100114 NiceMockControl control_;
Darin Petkov0e9735d2012-04-24 12:33:45 +0200115 NiceMock<MockDeviceInfo> device_info_;
Darin Petkovf20994f2012-03-05 16:12:19 +0100116 EventDispatcher dispatcher_;
117 MockMetrics metrics_;
118 MockGLib glib_;
119 MockManager manager_;
Darin Petkov46463022012-03-29 14:57:32 +0200120 OpenVPNDriver *driver_; // Owned by |service_|.
Darin Petkov79d74c92012-03-07 17:20:32 +0100121 scoped_refptr<MockVPNService> service_;
122 scoped_refptr<MockVPN> device_;
Darin Petkov3c5e4dc2012-04-02 14:44:27 +0200123 MockNSS nss_;
Darin Petkov46463022012-03-29 14:57:32 +0200124
125 // Owned by |driver_|.
126 NiceMock<MockOpenVPNManagementServer> *management_server_;
Darin Petkov1a462de2012-05-02 11:10:48 +0200127
128 FilePath lsb_release_file_;
Darin Petkov33af05c2012-02-28 10:10:30 +0100129};
130
Darin Petkovfe6a9372012-02-28 16:25:06 +0100131const char OpenVPNDriverTest::kOption[] = "--openvpn-option";
132const char OpenVPNDriverTest::kProperty[] = "OpenVPN.SomeProperty";
133const char OpenVPNDriverTest::kValue[] = "some-property-value";
134const char OpenVPNDriverTest::kOption2[] = "--openvpn-option2";
135const char OpenVPNDriverTest::kProperty2[] = "OpenVPN.SomeProperty2";
136const char OpenVPNDriverTest::kValue2[] = "some-property-value2";
Darin Petkov60596742012-03-05 12:17:17 +0100137const char OpenVPNDriverTest::kGateway1[] = "10.242.2.13";
138const char OpenVPNDriverTest::kNetmask1[] = "255.255.255.255";
139const char OpenVPNDriverTest::kNetwork1[] = "10.242.2.1";
140const char OpenVPNDriverTest::kGateway2[] = "10.242.2.14";
141const char OpenVPNDriverTest::kNetmask2[] = "255.255.0.0";
142const char OpenVPNDriverTest::kNetwork2[] = "192.168.0.0";
Darin Petkov79d74c92012-03-07 17:20:32 +0100143const char OpenVPNDriverTest::kInterfaceName[] = "tun0";
144const int OpenVPNDriverTest::kInterfaceIndex = 123;
Darin Petkovfe6a9372012-02-28 16:25:06 +0100145
Darin Petkov209e6292012-04-20 11:33:32 +0200146void OpenVPNDriverTest::GetLogin(string */*user*/, string */*password*/) {}
147
Darin Petkova9b1fed2012-02-29 11:49:05 +0100148void OpenVPNDriverTest::Notify(const string &/*reason*/,
149 const map<string, string> &/*dict*/) {}
150
Paul Stewartca6abd42012-03-01 15:45:29 -0800151void OpenVPNDriverTest::ExpectInFlags(const vector<string> &options,
152 const string &flag,
153 const string &value) {
154 vector<string>::const_iterator it =
155 std::find(options.begin(), options.end(), flag);
156
157 EXPECT_TRUE(it != options.end());
158 if (it != options.end())
Darin Petkov36a3ace2012-03-06 17:22:14 +0100159 return; // Don't crash below.
Paul Stewartca6abd42012-03-01 15:45:29 -0800160 it++;
161 EXPECT_TRUE(it != options.end());
162 if (it != options.end())
Darin Petkov36a3ace2012-03-06 17:22:14 +0100163 return; // Don't crash below.
Paul Stewartca6abd42012-03-01 15:45:29 -0800164 EXPECT_EQ(value, *it);
165}
166
Darin Petkov1a462de2012-05-02 11:10:48 +0200167void OpenVPNDriverTest::SetupLSBRelease() {
168 static const char kLSBReleaseContents[] =
169 "\n"
170 "=\n"
171 "foo=\n"
172 "=bar\n"
173 "zoo==\n"
174 "CHROMEOS_RELEASE_BOARD=x86-alex\n"
175 "CHROMEOS_RELEASE_NAME=Chromium OS\n"
176 "CHROMEOS_RELEASE_VERSION=2202.0\n";
177 EXPECT_TRUE(file_util::CreateTemporaryFile(&lsb_release_file_));
178 EXPECT_EQ(arraysize(kLSBReleaseContents),
179 file_util::WriteFile(lsb_release_file_,
180 kLSBReleaseContents,
181 arraysize(kLSBReleaseContents)));
182 EXPECT_EQ(OpenVPNDriver::kLSBReleaseFile, driver_->lsb_release_file_.value());
183 driver_->lsb_release_file_ = lsb_release_file_;
184}
185
Darin Petkov33af05c2012-02-28 10:10:30 +0100186TEST_F(OpenVPNDriverTest, Connect) {
Darin Petkov79d74c92012-03-07 17:20:32 +0100187 EXPECT_CALL(*service_, SetState(Service::kStateConfiguring));
188 const string interface = kInterfaceName;
Darin Petkovf20994f2012-03-05 16:12:19 +0100189 EXPECT_CALL(device_info_, CreateTunnelInterface(_))
Darin Petkov79d74c92012-03-07 17:20:32 +0100190 .WillOnce(DoAll(SetArgumentPointee<0>(interface), Return(true)));
191 Error error;
192 driver_->Connect(service_, &error);
193 EXPECT_TRUE(error.IsSuccess());
194 EXPECT_EQ(kInterfaceName, driver_->tunnel_interface_);
195}
196
197TEST_F(OpenVPNDriverTest, ConnectTunnelFailure) {
198 EXPECT_CALL(*service_, SetState(Service::kStateConfiguring));
Darin Petkov0e9735d2012-04-24 12:33:45 +0200199 EXPECT_CALL(device_info_, CreateTunnelInterface(_)).WillOnce(Return(false));
Darin Petkov79d74c92012-03-07 17:20:32 +0100200 EXPECT_CALL(*service_, SetState(Service::kStateFailure));
201 Error error;
202 driver_->Connect(service_, &error);
203 EXPECT_EQ(Error::kInternalError, error.type());
204 EXPECT_TRUE(driver_->tunnel_interface_.empty());
Darin Petkov33af05c2012-02-28 10:10:30 +0100205}
206
Darin Petkov0e9735d2012-04-24 12:33:45 +0200207namespace {
208MATCHER_P(IsIPAddress, address, "") {
209 IPAddress ip_address(IPAddress::kFamilyIPv4);
210 EXPECT_TRUE(ip_address.SetAddressFromString(address));
211 return ip_address.Equals(arg);
212}
213} // namespace
214
Darin Petkov14c29ec2012-03-02 11:34:19 +0100215TEST_F(OpenVPNDriverTest, Notify) {
Darin Petkov0e9735d2012-04-24 12:33:45 +0200216 map<string, string> config;
Darin Petkov79d74c92012-03-07 17:20:32 +0100217 driver_->device_ = device_;
218 EXPECT_CALL(*device_, UpdateIPConfig(_));
Darin Petkov0e9735d2012-04-24 12:33:45 +0200219 driver_->Notify("up", config);
Darin Petkov79d74c92012-03-07 17:20:32 +0100220}
221
222TEST_F(OpenVPNDriverTest, NotifyFail) {
223 map<string, string> dict;
224 driver_->device_ = device_;
225 EXPECT_CALL(*device_, OnDisconnected());
226 driver_->Notify("fail", dict);
Darin Petkov14c29ec2012-03-02 11:34:19 +0100227}
228
Darin Petkov60596742012-03-05 12:17:17 +0100229TEST_F(OpenVPNDriverTest, GetRouteOptionEntry) {
230 OpenVPNDriver::RouteOptions routes;
231 EXPECT_EQ(NULL, OpenVPNDriver::GetRouteOptionEntry("foo", "bar", &routes));
232 EXPECT_TRUE(routes.empty());
233 EXPECT_EQ(NULL, OpenVPNDriver::GetRouteOptionEntry("foo", "foo", &routes));
234 EXPECT_TRUE(routes.empty());
235 EXPECT_EQ(NULL, OpenVPNDriver::GetRouteOptionEntry("foo", "fooZ", &routes));
236 EXPECT_TRUE(routes.empty());
237 IPConfig::Route *route =
238 OpenVPNDriver::GetRouteOptionEntry("foo", "foo12", &routes);
239 EXPECT_EQ(1, routes.size());
240 EXPECT_EQ(route, &routes[12]);
241 route = OpenVPNDriver::GetRouteOptionEntry("foo", "foo13", &routes);
242 EXPECT_EQ(2, routes.size());
243 EXPECT_EQ(route, &routes[13]);
244}
245
246TEST_F(OpenVPNDriverTest, ParseRouteOption) {
247 OpenVPNDriver::RouteOptions routes;
248 OpenVPNDriver::ParseRouteOption("foo", "bar", &routes);
249 EXPECT_TRUE(routes.empty());
250 OpenVPNDriver::ParseRouteOption("gateway_2", kGateway2, &routes);
251 OpenVPNDriver::ParseRouteOption("netmask_2", kNetmask2, &routes);
252 OpenVPNDriver::ParseRouteOption("network_2", kNetwork2, &routes);
253 EXPECT_EQ(1, routes.size());
254 OpenVPNDriver::ParseRouteOption("gateway_1", kGateway1, &routes);
255 OpenVPNDriver::ParseRouteOption("netmask_1", kNetmask1, &routes);
256 OpenVPNDriver::ParseRouteOption("network_1", kNetwork1, &routes);
257 EXPECT_EQ(2, routes.size());
258 EXPECT_EQ(kGateway1, routes[1].gateway);
259 EXPECT_EQ(kNetmask1, routes[1].netmask);
260 EXPECT_EQ(kNetwork1, routes[1].host);
261 EXPECT_EQ(kGateway2, routes[2].gateway);
262 EXPECT_EQ(kNetmask2, routes[2].netmask);
263 EXPECT_EQ(kNetwork2, routes[2].host);
264}
265
266TEST_F(OpenVPNDriverTest, SetRoutes) {
267 OpenVPNDriver::RouteOptions routes;
268 routes[1].gateway = "1.2.3.4";
269 routes[1].host= "1.2.3.4";
270 routes[2].host = "2.3.4.5";
271 routes[2].netmask = "255.0.0.0";
272 routes[3].netmask = "255.0.0.0";
273 routes[3].gateway = "1.2.3.5";
274 routes[5].host = kNetwork2;
275 routes[5].netmask = kNetmask2;
276 routes[5].gateway = kGateway2;
277 routes[4].host = kNetwork1;
278 routes[4].netmask = kNetmask1;
279 routes[4].gateway = kGateway1;
280 IPConfig::Properties props;
281 OpenVPNDriver::SetRoutes(routes, &props);
282 ASSERT_EQ(2, props.routes.size());
283 EXPECT_EQ(kGateway1, props.routes[0].gateway);
284 EXPECT_EQ(kNetmask1, props.routes[0].netmask);
285 EXPECT_EQ(kNetwork1, props.routes[0].host);
286 EXPECT_EQ(kGateway2, props.routes[1].gateway);
287 EXPECT_EQ(kNetmask2, props.routes[1].netmask);
288 EXPECT_EQ(kNetwork2, props.routes[1].host);
289}
290
Darin Petkov14c29ec2012-03-02 11:34:19 +0100291TEST_F(OpenVPNDriverTest, ParseForeignOption) {
292 IPConfig::Properties props;
293 OpenVPNDriver::ParseForeignOption("", &props);
294 OpenVPNDriver::ParseForeignOption("dhcp-option DOMAIN", &props);
295 OpenVPNDriver::ParseForeignOption("dhcp-option DOMAIN zzz.com foo", &props);
296 OpenVPNDriver::ParseForeignOption("dhcp-Option DOmAIN xyz.com", &props);
297 ASSERT_EQ(1, props.domain_search.size());
298 EXPECT_EQ("xyz.com", props.domain_search[0]);
299 OpenVPNDriver::ParseForeignOption("dhcp-option DnS 1.2.3.4", &props);
300 ASSERT_EQ(1, props.dns_servers.size());
301 EXPECT_EQ("1.2.3.4", props.dns_servers[0]);
302}
303
304TEST_F(OpenVPNDriverTest, ParseForeignOptions) {
305 // Basically test that std::map is a sorted container.
306 map<int, string> options;
307 options[5] = "dhcp-option DOMAIN five.com";
308 options[2] = "dhcp-option DOMAIN two.com";
309 options[8] = "dhcp-option DOMAIN eight.com";
310 options[7] = "dhcp-option DOMAIN seven.com";
311 options[4] = "dhcp-option DOMAIN four.com";
312 IPConfig::Properties props;
313 OpenVPNDriver::ParseForeignOptions(options, &props);
314 ASSERT_EQ(5, props.domain_search.size());
315 EXPECT_EQ("two.com", props.domain_search[0]);
316 EXPECT_EQ("four.com", props.domain_search[1]);
317 EXPECT_EQ("five.com", props.domain_search[2]);
318 EXPECT_EQ("seven.com", props.domain_search[3]);
319 EXPECT_EQ("eight.com", props.domain_search[4]);
320}
321
322TEST_F(OpenVPNDriverTest, ParseIPConfiguration) {
323 map<string, string> config;
324 config["ifconfig_loCal"] = "4.5.6.7";
325 config["ifconfiG_broadcast"] = "1.2.255.255";
326 config["ifconFig_netmAsk"] = "255.255.255.0";
327 config["ifconfig_remotE"] = "33.44.55.66";
328 config["route_vpN_gateway"] = "192.168.1.1";
Paul Stewartce4ec192012-03-14 12:53:46 -0700329 config["trusted_ip"] = "99.88.77.66";
Darin Petkov14c29ec2012-03-02 11:34:19 +0100330 config["tun_mtu"] = "1000";
331 config["foreign_option_2"] = "dhcp-option DNS 4.4.4.4";
332 config["foreign_option_1"] = "dhcp-option DNS 1.1.1.1";
333 config["foreign_option_3"] = "dhcp-option DNS 2.2.2.2";
Darin Petkov60596742012-03-05 12:17:17 +0100334 config["route_network_2"] = kNetwork2;
335 config["route_network_1"] = kNetwork1;
336 config["route_netmask_2"] = kNetmask2;
337 config["route_netmask_1"] = kNetmask1;
338 config["route_gateway_2"] = kGateway2;
339 config["route_gateway_1"] = kGateway1;
Darin Petkov14c29ec2012-03-02 11:34:19 +0100340 config["foo"] = "bar";
341 IPConfig::Properties props;
342 OpenVPNDriver::ParseIPConfiguration(config, &props);
343 EXPECT_EQ(IPAddress::kFamilyIPv4, props.address_family);
344 EXPECT_EQ("4.5.6.7", props.address);
345 EXPECT_EQ("1.2.255.255", props.broadcast_address);
Paul Stewart48100b02012-03-19 07:53:52 -0700346 EXPECT_EQ(24, props.subnet_prefix);
Darin Petkov14c29ec2012-03-02 11:34:19 +0100347 EXPECT_EQ("33.44.55.66", props.peer_address);
348 EXPECT_EQ("192.168.1.1", props.gateway);
Paul Stewartce4ec192012-03-14 12:53:46 -0700349 EXPECT_EQ("99.88.77.66", props.trusted_ip);
Darin Petkov14c29ec2012-03-02 11:34:19 +0100350 EXPECT_EQ(1000, props.mtu);
351 ASSERT_EQ(3, props.dns_servers.size());
352 EXPECT_EQ("1.1.1.1", props.dns_servers[0]);
353 EXPECT_EQ("4.4.4.4", props.dns_servers[1]);
354 EXPECT_EQ("2.2.2.2", props.dns_servers[2]);
Darin Petkov60596742012-03-05 12:17:17 +0100355 ASSERT_EQ(2, props.routes.size());
356 EXPECT_EQ(kGateway1, props.routes[0].gateway);
357 EXPECT_EQ(kNetmask1, props.routes[0].netmask);
358 EXPECT_EQ(kNetwork1, props.routes[0].host);
359 EXPECT_EQ(kGateway2, props.routes[1].gateway);
360 EXPECT_EQ(kNetmask2, props.routes[1].netmask);
361 EXPECT_EQ(kNetwork2, props.routes[1].host);
Darin Petkov14c29ec2012-03-02 11:34:19 +0100362}
363
Darin Petkovfe6a9372012-02-28 16:25:06 +0100364TEST_F(OpenVPNDriverTest, InitOptionsNoHost) {
365 Error error;
366 vector<string> options;
Darin Petkov79d74c92012-03-07 17:20:32 +0100367 driver_->InitOptions(&options, &error);
Darin Petkovfe6a9372012-02-28 16:25:06 +0100368 EXPECT_EQ(Error::kInvalidArguments, error.type());
369 EXPECT_TRUE(options.empty());
370}
371
372TEST_F(OpenVPNDriverTest, InitOptions) {
373 static const char kHost[] = "192.168.2.254";
Darin Petkov1fa81942012-04-02 11:38:08 +0200374 static const char kTLSAuthContents[] = "SOME-RANDOM-CONTENTS\n";
Darin Petkov3c5e4dc2012-04-02 14:44:27 +0200375 static const char kCaCertNSS[] = "{1234}";
Darin Petkove0d5dd12012-04-04 16:10:48 +0200376 static const char kID[] = "TestPKCS11ID";
377 FilePath empty_cert;
378 SetArg(flimflam::kProviderHostProperty, kHost);
379 SetArg(flimflam::kOpenVPNTLSAuthContentsProperty, kTLSAuthContents);
380 SetArg(flimflam::kOpenVPNCaCertNSSProperty, kCaCertNSS);
381 SetArg(flimflam::kOpenVPNClientCertIdProperty, kID);
Darin Petkov79d74c92012-03-07 17:20:32 +0100382 driver_->rpc_task_.reset(new RPCTask(&control_, this));
Darin Petkov79d74c92012-03-07 17:20:32 +0100383 driver_->tunnel_interface_ = kInterfaceName;
Darin Petkove0d5dd12012-04-04 16:10:48 +0200384 EXPECT_CALL(*management_server_, Start(_, _, _)).WillOnce(Return(true));
385 EXPECT_CALL(nss_, GetPEMCertfile(kCaCertNSS, _)).WillOnce(Return(empty_cert));
386
387 Error error;
388 vector<string> options;
389 driver_->InitOptions(&options, &error);
390 EXPECT_TRUE(error.IsSuccess());
391 EXPECT_EQ("--client", options[0]);
392 ExpectInFlags(options, "--remote", kHost);
393 ExpectInFlags(options, "CONNMAN_PATH", RPCTaskMockAdaptor::kRpcId);
394 ExpectInFlags(options, "--dev", kInterfaceName);
395 ExpectInFlags(options, "--group", "openvpn");
396 EXPECT_EQ(kInterfaceName, driver_->tunnel_interface_);
397 ASSERT_FALSE(driver_->tls_auth_file_.empty());
398 ExpectInFlags(options, "--tls-auth", driver_->tls_auth_file_.value());
399 string contents;
400 EXPECT_TRUE(
401 file_util::ReadFileToString(driver_->tls_auth_file_, &contents));
402 EXPECT_EQ(kTLSAuthContents, contents);
403 ExpectInFlags(options, "--pkcs11-id", kID);
Darin Petkov55771b72012-04-25 09:25:19 +0200404 EXPECT_TRUE(std::find(options.begin(), options.end(), "--syslog") !=
405 options.end());
Darin Petkove0d5dd12012-04-04 16:10:48 +0200406}
407
408TEST_F(OpenVPNDriverTest, InitNSSOptions) {
409 static const char kHost[] = "192.168.2.254";
410 static const char kCaCertNSS[] = "{1234}";
411 static const char kNSSCertfile[] = "/tmp/nss-cert";
412 FilePath empty_cert;
413 FilePath nss_cert(kNSSCertfile);
414 SetArg(flimflam::kProviderHostProperty, kHost);
415 SetArg(flimflam::kOpenVPNCaCertNSSProperty, kCaCertNSS);
Darin Petkov3c5e4dc2012-04-02 14:44:27 +0200416 EXPECT_CALL(nss_,
417 GetPEMCertfile(kCaCertNSS,
418 ElementsAreArray(kHost, arraysize(kHost) - 1)))
Darin Petkove0d5dd12012-04-04 16:10:48 +0200419 .WillOnce(Return(empty_cert))
420 .WillOnce(Return(nss_cert));
421
422 Error error;
423 vector<string> options;
424 EXPECT_TRUE(driver_->InitNSSOptions(&options, &error));
425 EXPECT_TRUE(error.IsSuccess());
426 EXPECT_TRUE(options.empty());
427 EXPECT_TRUE(driver_->InitNSSOptions(&options, &error));
428 ExpectInFlags(options, "--ca", kNSSCertfile);
429 EXPECT_TRUE(error.IsSuccess());
430
431 SetArg(flimflam::kOpenVPNCaCertProperty, "foo");
432 options.clear();
433 EXPECT_FALSE(driver_->InitNSSOptions(&options, &error));
434 EXPECT_EQ(Error::kInvalidArguments, error.type());
435 EXPECT_EQ("Can't specify both CACert and CACertNSS.", error.message());
436}
437
438TEST_F(OpenVPNDriverTest, InitPKCS11Options) {
439 vector<string> options;
440 driver_->InitPKCS11Options(&options);
441 EXPECT_TRUE(options.empty());
442
443 static const char kID[] = "TestPKCS11ID";
444 SetArg(flimflam::kOpenVPNClientCertIdProperty, kID);
445 driver_->InitPKCS11Options(&options);
446 ExpectInFlags(options, "--pkcs11-id", kID);
447 ExpectInFlags(options, "--pkcs11-providers", "libchaps.so");
448
449 static const char kProvider[] = "libpkcs11.so";
450 SetArg(flimflam::kOpenVPNProviderProperty, kProvider);
451 options.clear();
452 driver_->InitPKCS11Options(&options);
453 ExpectInFlags(options, "--pkcs11-id", kID);
454 ExpectInFlags(options, "--pkcs11-providers", kProvider);
455}
456
457TEST_F(OpenVPNDriverTest, InitManagementChannelOptions) {
458 vector<string> options;
459 EXPECT_CALL(*management_server_,
460 Start(&dispatcher_, &driver_->sockets_, &options))
461 .WillOnce(Return(false))
462 .WillOnce(Return(true));
463
464 Error error;
465 EXPECT_FALSE(driver_->InitManagementChannelOptions(&options, &error));
466 EXPECT_EQ(Error::kInternalError, error.type());
467 EXPECT_EQ("Unable to setup management channel.", error.message());
468
469 error.Reset();
470 EXPECT_TRUE(driver_->InitManagementChannelOptions(&options, &error));
471 EXPECT_TRUE(error.IsSuccess());
Darin Petkovfe6a9372012-02-28 16:25:06 +0100472}
473
Darin Petkov55771b72012-04-25 09:25:19 +0200474TEST_F(OpenVPNDriverTest, InitLoggingOptions) {
475 vector<string> options;
476 bool vpn_logging = SLOG_IS_ON(VPN, 0);
477 ScopeLogger::GetInstance()->EnableScopesByName("-vpn");
478 driver_->InitLoggingOptions(&options);
479 ASSERT_EQ(1, options.size());
480 EXPECT_EQ("--syslog", options[0]);
481 ScopeLogger::GetInstance()->EnableScopesByName("+vpn");
482 options.clear();
483 driver_->InitLoggingOptions(&options);
484 ExpectInFlags(options, "--verb", "3");
485 ScopeLogger::GetInstance()->EnableScopesByName("-vpn");
486 SetArg("OpenVPN.Verb", "2");
487 options.clear();
488 driver_->InitLoggingOptions(&options);
489 ExpectInFlags(options, "--verb", "2");
490 ScopeLogger::GetInstance()->EnableScopesByName("+vpn");
491 SetArg("OpenVPN.Verb", "1");
492 options.clear();
493 driver_->InitLoggingOptions(&options);
494 ExpectInFlags(options, "--verb", "1");
495 if (!vpn_logging) {
496 ScopeLogger::GetInstance()->EnableScopesByName("-vpn");
497 }
498}
499
Darin Petkovfe6a9372012-02-28 16:25:06 +0100500TEST_F(OpenVPNDriverTest, AppendValueOption) {
501 vector<string> options;
Darin Petkov46463022012-03-29 14:57:32 +0200502 EXPECT_FALSE(
503 driver_->AppendValueOption("OpenVPN.UnknownProperty", kOption, &options));
Darin Petkovfe6a9372012-02-28 16:25:06 +0100504 EXPECT_TRUE(options.empty());
505
Darin Petkove0d5dd12012-04-04 16:10:48 +0200506 SetArg(kProperty, "");
Darin Petkov46463022012-03-29 14:57:32 +0200507 EXPECT_FALSE(driver_->AppendValueOption(kProperty, kOption, &options));
Darin Petkovfe6a9372012-02-28 16:25:06 +0100508 EXPECT_TRUE(options.empty());
509
Darin Petkove0d5dd12012-04-04 16:10:48 +0200510 SetArg(kProperty, kValue);
511 SetArg(kProperty2, kValue2);
Darin Petkov46463022012-03-29 14:57:32 +0200512 EXPECT_TRUE(driver_->AppendValueOption(kProperty, kOption, &options));
513 EXPECT_TRUE(driver_->AppendValueOption(kProperty2, kOption2, &options));
Darin Petkovfe6a9372012-02-28 16:25:06 +0100514 EXPECT_EQ(4, options.size());
515 EXPECT_EQ(kOption, options[0]);
516 EXPECT_EQ(kValue, options[1]);
517 EXPECT_EQ(kOption2, options[2]);
518 EXPECT_EQ(kValue2, options[3]);
519}
520
521TEST_F(OpenVPNDriverTest, AppendFlag) {
522 vector<string> options;
Darin Petkov46463022012-03-29 14:57:32 +0200523 EXPECT_FALSE(
524 driver_->AppendFlag("OpenVPN.UnknownProperty", kOption, &options));
Darin Petkovfe6a9372012-02-28 16:25:06 +0100525 EXPECT_TRUE(options.empty());
526
Darin Petkove0d5dd12012-04-04 16:10:48 +0200527 SetArg(kProperty, "");
528 SetArg(kProperty2, kValue2);
Darin Petkov46463022012-03-29 14:57:32 +0200529 EXPECT_TRUE(driver_->AppendFlag(kProperty, kOption, &options));
530 EXPECT_TRUE(driver_->AppendFlag(kProperty2, kOption2, &options));
Darin Petkovfe6a9372012-02-28 16:25:06 +0100531 EXPECT_EQ(2, options.size());
532 EXPECT_EQ(kOption, options[0]);
533 EXPECT_EQ(kOption2, options[1]);
534}
535
Paul Stewartca6abd42012-03-01 15:45:29 -0800536TEST_F(OpenVPNDriverTest, ClaimInterface) {
Darin Petkov79d74c92012-03-07 17:20:32 +0100537 driver_->tunnel_interface_ = kInterfaceName;
538 EXPECT_FALSE(driver_->ClaimInterface(string(kInterfaceName) + "XXX",
539 kInterfaceIndex));
540 EXPECT_FALSE(driver_->device_);
Paul Stewartca6abd42012-03-01 15:45:29 -0800541
Darin Petkov36a3ace2012-03-06 17:22:14 +0100542 static const char kHost[] = "192.168.2.254";
Darin Petkove0d5dd12012-04-04 16:10:48 +0200543 SetArg(flimflam::kProviderHostProperty, kHost);
Darin Petkov46463022012-03-29 14:57:32 +0200544 EXPECT_CALL(*management_server_, Start(_, _, _)).WillOnce(Return(true));
Darin Petkov36a3ace2012-03-06 17:22:14 +0100545 EXPECT_CALL(glib_, SpawnAsyncWithPipesCWD(_, _, _, _, _, _, _, _, _, _))
546 .WillOnce(Return(true));
547 EXPECT_CALL(glib_, ChildWatchAdd(_, _, _)).WillOnce(Return(1));
Darin Petkov79d74c92012-03-07 17:20:32 +0100548 EXPECT_TRUE(driver_->ClaimInterface(kInterfaceName, kInterfaceIndex));
549 ASSERT_TRUE(driver_->device_);
550 EXPECT_EQ(kInterfaceIndex, driver_->device_->interface_index());
Paul Stewartca6abd42012-03-01 15:45:29 -0800551}
552
Darin Petkov36a3ace2012-03-06 17:22:14 +0100553TEST_F(OpenVPNDriverTest, Cleanup) {
Darin Petkov1fa81942012-04-02 11:38:08 +0200554 driver_->Cleanup(Service::kStateIdle); // Ensure no crash.
555
Darin Petkov36a3ace2012-03-06 17:22:14 +0100556 const unsigned int kTag = 123;
557 const int kPID = 123456;
Darin Petkov79d74c92012-03-07 17:20:32 +0100558 driver_->child_watch_tag_ = kTag;
559 driver_->pid_ = kPID;
560 driver_->rpc_task_.reset(new RPCTask(&control_, this));
561 driver_->tunnel_interface_ = kInterfaceName;
562 driver_->device_ = device_;
563 driver_->service_ = service_;
Darin Petkov1fa81942012-04-02 11:38:08 +0200564 FilePath tls_auth_file;
565 EXPECT_TRUE(file_util::CreateTemporaryFile(&tls_auth_file));
566 EXPECT_FALSE(tls_auth_file.empty());
567 EXPECT_TRUE(file_util::PathExists(tls_auth_file));
568 driver_->tls_auth_file_ = tls_auth_file;
Darin Petkov46463022012-03-29 14:57:32 +0200569 // Stop will be called twice -- once by Cleanup and once by the destructor.
570 EXPECT_CALL(*management_server_, Stop()).Times(2);
Darin Petkov36a3ace2012-03-06 17:22:14 +0100571 EXPECT_CALL(glib_, SourceRemove(kTag));
572 EXPECT_CALL(glib_, SpawnClosePID(kPID));
Darin Petkov029d3532012-04-18 14:38:04 +0200573 EXPECT_CALL(*device_, OnDisconnected());
Eric Shienbrood9a245532012-03-07 14:20:39 -0500574 EXPECT_CALL(*device_, SetEnabled(false));
Darin Petkov79d74c92012-03-07 17:20:32 +0100575 EXPECT_CALL(device_info_, DeleteInterface(kInterfaceIndex));
576 EXPECT_CALL(*service_, SetState(Service::kStateFailure));
Darin Petkov3f9131c2012-03-20 11:37:32 +0100577 driver_->Cleanup(Service::kStateFailure);
Darin Petkov79d74c92012-03-07 17:20:32 +0100578 EXPECT_EQ(0, driver_->child_watch_tag_);
579 EXPECT_EQ(0, driver_->pid_);
580 EXPECT_FALSE(driver_->rpc_task_.get());
581 EXPECT_TRUE(driver_->tunnel_interface_.empty());
582 EXPECT_FALSE(driver_->device_);
583 EXPECT_FALSE(driver_->service_);
Darin Petkov1fa81942012-04-02 11:38:08 +0200584 EXPECT_FALSE(file_util::PathExists(tls_auth_file));
585 EXPECT_TRUE(driver_->tls_auth_file_.empty());
Darin Petkov36a3ace2012-03-06 17:22:14 +0100586}
587
Darin Petkov1a462de2012-05-02 11:10:48 +0200588namespace {
589MATCHER(CheckEnv, "") {
590 if (!arg || !arg[0] || !arg[1] || arg[2]) {
591 return false;
592 }
593 return (string(arg[0]) == "IV_PLAT=Chromium OS" &&
594 string(arg[1]) == "IV_PLAT_REL=2202.0");
595}
596} // namespace
597
Darin Petkov36a3ace2012-03-06 17:22:14 +0100598TEST_F(OpenVPNDriverTest, SpawnOpenVPN) {
Darin Petkov1a462de2012-05-02 11:10:48 +0200599 SetupLSBRelease();
600
Darin Petkov79d74c92012-03-07 17:20:32 +0100601 EXPECT_FALSE(driver_->SpawnOpenVPN());
Darin Petkov36a3ace2012-03-06 17:22:14 +0100602
603 static const char kHost[] = "192.168.2.254";
Darin Petkove0d5dd12012-04-04 16:10:48 +0200604 SetArg(flimflam::kProviderHostProperty, kHost);
Darin Petkov79d74c92012-03-07 17:20:32 +0100605 driver_->tunnel_interface_ = "tun0";
606 driver_->rpc_task_.reset(new RPCTask(&control_, this));
Darin Petkov46463022012-03-29 14:57:32 +0200607 EXPECT_CALL(*management_server_, Start(_, _, _))
608 .Times(2)
609 .WillRepeatedly(Return(true));
Darin Petkov36a3ace2012-03-06 17:22:14 +0100610
611 const int kPID = 234678;
Darin Petkov1a462de2012-05-02 11:10:48 +0200612 EXPECT_CALL(glib_,
613 SpawnAsyncWithPipesCWD(_, CheckEnv(), _, _, _, _, _, _, _, _))
Darin Petkov36a3ace2012-03-06 17:22:14 +0100614 .WillOnce(Return(false))
615 .WillOnce(DoAll(SetArgumentPointee<5>(kPID), Return(true)));
616 const int kTag = 6;
Darin Petkov79d74c92012-03-07 17:20:32 +0100617 EXPECT_CALL(glib_, ChildWatchAdd(kPID, &driver_->OnOpenVPNDied, driver_))
Darin Petkov36a3ace2012-03-06 17:22:14 +0100618 .WillOnce(Return(kTag));
Darin Petkov79d74c92012-03-07 17:20:32 +0100619 EXPECT_FALSE(driver_->SpawnOpenVPN());
620 EXPECT_TRUE(driver_->SpawnOpenVPN());
621 EXPECT_EQ(kPID, driver_->pid_);
622 EXPECT_EQ(kTag, driver_->child_watch_tag_);
Darin Petkov36a3ace2012-03-06 17:22:14 +0100623}
624
625TEST_F(OpenVPNDriverTest, OnOpenVPNDied) {
626 const int kPID = 99999;
Darin Petkov79d74c92012-03-07 17:20:32 +0100627 driver_->child_watch_tag_ = 333;
628 driver_->pid_ = kPID;
Darin Petkov36a3ace2012-03-06 17:22:14 +0100629 EXPECT_CALL(glib_, SpawnClosePID(kPID));
Darin Petkov79d74c92012-03-07 17:20:32 +0100630 OpenVPNDriver::OnOpenVPNDied(kPID, 2, driver_);
631 EXPECT_EQ(0, driver_->child_watch_tag_);
632 EXPECT_EQ(0, driver_->pid_);
Darin Petkov36a3ace2012-03-06 17:22:14 +0100633}
634
Darin Petkov6aa21872012-03-09 16:10:19 +0100635TEST_F(OpenVPNDriverTest, Disconnect) {
636 driver_->device_ = device_;
637 driver_->service_ = service_;
Darin Petkov029d3532012-04-18 14:38:04 +0200638 EXPECT_CALL(*device_, OnDisconnected());
Eric Shienbrood9a245532012-03-07 14:20:39 -0500639 EXPECT_CALL(*device_, SetEnabled(false));
Darin Petkov6aa21872012-03-09 16:10:19 +0100640 EXPECT_CALL(device_info_, DeleteInterface(kInterfaceIndex));
641 EXPECT_CALL(*service_, SetState(Service::kStateIdle));
642 driver_->Disconnect();
Darin Petkova0e645e2012-04-25 11:38:59 +0200643 EXPECT_FALSE(driver_->device_);
Darin Petkov6aa21872012-03-09 16:10:19 +0100644 EXPECT_FALSE(driver_->service_);
645}
646
Darin Petkov5eb05422012-05-11 15:45:25 +0200647TEST_F(OpenVPNDriverTest, OnConnectionDisconnected) {
648 driver_->service_ = service_;
649 EXPECT_CALL(*service_, SetState(Service::kStateFailure));
650 driver_->OnConnectionDisconnected();
651 EXPECT_FALSE(driver_->service_);
652}
653
Darin Petkov271fe522012-03-27 13:47:29 +0200654TEST_F(OpenVPNDriverTest, OnReconnecting) {
655 driver_->OnReconnecting(); // Expect no crash.
656 driver_->device_ = device_;
657 driver_->service_ = service_;
658 EXPECT_CALL(*device_, OnDisconnected());
659 EXPECT_CALL(*service_, SetState(Service::kStateAssociating));
660 driver_->OnReconnecting();
661}
662
Paul Stewart291a4732012-03-14 19:19:02 -0700663TEST_F(OpenVPNDriverTest, VerifyPaths) {
664 // Ensure that the various path constants that the OpenVPN driver uses
Darin Petkova0e645e2012-04-25 11:38:59 +0200665 // actually exists in the build image. Due to build dependencies, they should
666 // already exist by the time we run unit tests.
Paul Stewart291a4732012-03-14 19:19:02 -0700667
Darin Petkova0e645e2012-04-25 11:38:59 +0200668 // The OpenVPNDriver path constants are absolute. FilePath::Append asserts
669 // that its argument is not an absolute path, so we need to strip the leading
670 // separators. There's nothing built into FilePath to do so.
671 static const char *kPaths[] = {
672 OpenVPNDriver::kOpenVPNPath,
673 OpenVPNDriver::kOpenVPNScript,
674 };
675 for (size_t i = 0; i < arraysize(kPaths); i++) {
676 string path(kPaths[i]);
677 TrimString(path, FilePath::kSeparators, &path);
678 EXPECT_TRUE(file_util::PathExists(FilePath(SYSROOT).Append(path)))
679 << kPaths[i];
680 }
Paul Stewart291a4732012-03-14 19:19:02 -0700681}
682
Darin Petkovd4325392012-04-23 15:48:22 +0200683TEST_F(OpenVPNDriverTest, InitPropertyStore) {
684 // Sanity test property store initialization.
685 PropertyStore store;
686 driver_->InitPropertyStore(&store);
687 const string kUser = "joe";
688 Error error;
689 EXPECT_TRUE(
690 store.SetStringProperty(flimflam::kOpenVPNUserProperty, kUser, &error));
691 EXPECT_TRUE(error.IsSuccess());
Darin Petkovb536a742012-04-26 11:31:28 +0200692 EXPECT_EQ(kUser, GetArgs()->LookupString(flimflam::kOpenVPNUserProperty, ""));
693}
694
695TEST_F(OpenVPNDriverTest, GetProvider) {
696 PropertyStore store;
697 driver_->InitPropertyStore(&store);
Paul Stewart8e7e4592012-04-29 09:47:48 -0700698 PropertyStoreInspector inspector(&store);
Darin Petkovb536a742012-04-26 11:31:28 +0200699 {
700 Error error;
701 KeyValueStore props;
702 EXPECT_TRUE(
Paul Stewart8e7e4592012-04-29 09:47:48 -0700703 inspector.GetKeyValueStoreProperty(
704 flimflam::kProviderProperty, &props, &error));
Darin Petkovb536a742012-04-26 11:31:28 +0200705 EXPECT_TRUE(props.LookupBool(flimflam::kPassphraseRequiredProperty, false));
706 }
707 {
708 Error error;
709 KeyValueStore props;
710 SetArg(flimflam::kOpenVPNPasswordProperty, "random-password");
711 EXPECT_TRUE(
Paul Stewart8e7e4592012-04-29 09:47:48 -0700712 inspector.GetKeyValueStoreProperty(
713 flimflam::kProviderProperty, &props, &error));
Darin Petkovb536a742012-04-26 11:31:28 +0200714 EXPECT_FALSE(props.LookupBool(flimflam::kPassphraseRequiredProperty, true));
715 }
Darin Petkovd4325392012-04-23 15:48:22 +0200716}
717
Darin Petkov1a462de2012-05-02 11:10:48 +0200718TEST_F(OpenVPNDriverTest, ParseLSBRelease) {
719 SetupLSBRelease();
720 map<string, string> lsb_release;
721 EXPECT_TRUE(driver_->ParseLSBRelease(&lsb_release));
722 EXPECT_TRUE(ContainsKey(lsb_release, "foo") && lsb_release["foo"] == "");
723 EXPECT_EQ("=", lsb_release["zoo"]);
724 EXPECT_EQ("Chromium OS", lsb_release[OpenVPNDriver::kChromeOSReleaseName]);
725 EXPECT_EQ("2202.0", lsb_release[OpenVPNDriver::kChromeOSReleaseVersion]);
726 driver_->lsb_release_file_ = FilePath("/non/existent/file");
727 EXPECT_FALSE(driver_->ParseLSBRelease(NULL));
728}
729
730TEST_F(OpenVPNDriverTest, InitEnvironment) {
731 vector<string> env;
732 SetupLSBRelease();
733 driver_->InitEnvironment(&env);
734 ASSERT_EQ(2, env.size());
735 EXPECT_EQ("IV_PLAT=Chromium OS", env[0]);
736 EXPECT_EQ("IV_PLAT_REL=2202.0", env[1]);
737 env.clear();
738 EXPECT_EQ(0, file_util::WriteFile(lsb_release_file_, "", 0));
739 driver_->InitEnvironment(&env);
740 EXPECT_EQ(0, env.size());
741}
742
Darin Petkov33af05c2012-02-28 10:10:30 +0100743} // namespace shill