blob: 8746f8bedfe5a52f7e17177393baaefda03619c1 [file] [log] [blame]
Darin Petkove7cb7f82011-06-03 13:21:51 -07001// Copyright (c) 2011 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
Darin Petkov92c43902011-06-09 20:46:06 -07005#include <base/file_util.h>
6#include <base/memory/scoped_temp_dir.h>
7#include <base/stringprintf.h>
Chris Masone43b48a12011-07-01 13:37:07 -07008#include <chromeos/dbus/service_constants.h>
Darin Petkov92c43902011-06-09 20:46:06 -07009
Chris Masone43b48a12011-07-01 13:37:07 -070010#include "shill/dbus_adaptor.h"
Darin Petkove7cb7f82011-06-03 13:21:51 -070011#include "shill/dhcp_config.h"
Darin Petkovf7897bc2011-06-08 17:13:36 -070012#include "shill/dhcp_provider.h"
Chris Masone19e30402011-07-19 15:48:47 -070013#include "shill/mock_control.h"
Darin Petkov98dd6a02011-06-10 15:12:57 -070014#include "shill/mock_dhcp_proxy.h"
Darin Petkovf7897bc2011-06-08 17:13:36 -070015#include "shill/mock_glib.h"
Chris Masone43b48a12011-07-01 13:37:07 -070016#include "shill/property_store_unittest.h"
Darin Petkove7cb7f82011-06-03 13:21:51 -070017
18using std::string;
19using std::vector;
Darin Petkovf7897bc2011-06-08 17:13:36 -070020using testing::_;
21using testing::Return;
22using testing::SetArgumentPointee;
Darin Petkove7cb7f82011-06-03 13:21:51 -070023using testing::Test;
24
25namespace shill {
26
Darin Petkov92c43902011-06-09 20:46:06 -070027namespace {
28const char kDeviceName[] = "testdevicename";
29} // namespace {}
30
Chris Masone43b48a12011-07-01 13:37:07 -070031class DHCPConfigTest : public PropertyStoreTest {
Darin Petkove7cb7f82011-06-03 13:21:51 -070032 public:
Darin Petkovf7897bc2011-06-08 17:13:36 -070033 DHCPConfigTest()
Darin Petkovf65e9282011-06-21 14:29:56 -070034 : proxy_(new MockDHCPProxy()),
Chris Masone19e30402011-07-19 15:48:47 -070035 config_(new DHCPConfig(&control_,
36 DHCPProvider::GetInstance(),
Darin Petkov92c43902011-06-09 20:46:06 -070037 kDeviceName,
Darin Petkovf65e9282011-06-21 14:29:56 -070038 &glib_)) {
Darin Petkov98dd6a02011-06-10 15:12:57 -070039 config_->proxy_.reset(proxy_); // pass ownership
40 }
Darin Petkove7cb7f82011-06-03 13:21:51 -070041
42 protected:
Darin Petkovf7897bc2011-06-08 17:13:36 -070043 MockGLib glib_;
Darin Petkov98dd6a02011-06-10 15:12:57 -070044 MockDHCPProxy * const proxy_;
Chris Masone19e30402011-07-19 15:48:47 -070045 MockControl control_;
Darin Petkovf7897bc2011-06-08 17:13:36 -070046 DHCPConfigRefPtr config_;
Darin Petkove7cb7f82011-06-03 13:21:51 -070047};
48
49TEST_F(DHCPConfigTest, GetIPv4AddressString) {
Darin Petkovf7897bc2011-06-08 17:13:36 -070050 EXPECT_EQ("255.255.255.255", config_->GetIPv4AddressString(0xffffffff));
51 EXPECT_EQ("0.0.0.0", config_->GetIPv4AddressString(0));
52 EXPECT_EQ("1.2.3.4", config_->GetIPv4AddressString(0x04030201));
Darin Petkove7cb7f82011-06-03 13:21:51 -070053}
54
55TEST_F(DHCPConfigTest, ParseConfiguration) {
56 DHCPConfig::Configuration conf;
57 conf[DHCPConfig::kConfigurationKeyIPAddress].writer().append_uint32(
58 0x01020304);
59 conf[DHCPConfig::kConfigurationKeySubnetCIDR].writer().append_byte(
60 16);
61 conf[DHCPConfig::kConfigurationKeyBroadcastAddress].writer().append_uint32(
62 0x10203040);
63 {
Darin Petkove7cb7f82011-06-03 13:21:51 -070064 vector<unsigned int> routers;
65 routers.push_back(0x02040608);
66 routers.push_back(0x03050709);
Darin Petkovf7897bc2011-06-08 17:13:36 -070067 DBus::MessageIter writer =
68 conf[DHCPConfig::kConfigurationKeyRouters].writer();
Darin Petkove7cb7f82011-06-03 13:21:51 -070069 writer << routers;
Darin Petkove7cb7f82011-06-03 13:21:51 -070070 }
71 {
Darin Petkove7cb7f82011-06-03 13:21:51 -070072 vector<unsigned int> dns;
73 dns.push_back(0x09070503);
74 dns.push_back(0x08060402);
Darin Petkovf7897bc2011-06-08 17:13:36 -070075 DBus::MessageIter writer = conf[DHCPConfig::kConfigurationKeyDNS].writer();
Darin Petkove7cb7f82011-06-03 13:21:51 -070076 writer << dns;
Darin Petkove7cb7f82011-06-03 13:21:51 -070077 }
78 conf[DHCPConfig::kConfigurationKeyDomainName].writer().append_string(
79 "domain-name");
80 {
Darin Petkove7cb7f82011-06-03 13:21:51 -070081 vector<string> search;
82 search.push_back("foo.com");
83 search.push_back("bar.com");
Darin Petkovf7897bc2011-06-08 17:13:36 -070084 DBus::MessageIter writer =
85 conf[DHCPConfig::kConfigurationKeyDomainSearch].writer();
Darin Petkove7cb7f82011-06-03 13:21:51 -070086 writer << search;
Darin Petkove7cb7f82011-06-03 13:21:51 -070087 }
88 conf[DHCPConfig::kConfigurationKeyMTU].writer().append_uint16(600);
89 conf["UnknownKey"] = DBus::Variant();
90
Darin Petkove7cb7f82011-06-03 13:21:51 -070091 IPConfig::Properties properties;
Darin Petkovf7897bc2011-06-08 17:13:36 -070092 ASSERT_TRUE(config_->ParseConfiguration(conf, &properties));
Darin Petkove7cb7f82011-06-03 13:21:51 -070093 EXPECT_EQ("4.3.2.1", properties.address);
94 EXPECT_EQ(16, properties.subnet_cidr);
95 EXPECT_EQ("64.48.32.16", properties.broadcast_address);
96 EXPECT_EQ("8.6.4.2", properties.gateway);
97 ASSERT_EQ(2, properties.dns_servers.size());
98 EXPECT_EQ("3.5.7.9", properties.dns_servers[0]);
99 EXPECT_EQ("2.4.6.8", properties.dns_servers[1]);
100 EXPECT_EQ("domain-name", properties.domain_name);
101 ASSERT_EQ(2, properties.domain_search.size());
102 EXPECT_EQ("foo.com", properties.domain_search[0]);
103 EXPECT_EQ("bar.com", properties.domain_search[1]);
104 EXPECT_EQ(600, properties.mtu);
105}
106
Darin Petkov92c43902011-06-09 20:46:06 -0700107TEST_F(DHCPConfigTest, StartFail) {
Darin Petkovf7897bc2011-06-08 17:13:36 -0700108 EXPECT_CALL(glib_, SpawnAsync(_, _, _, _, _, _, _, _))
109 .WillOnce(Return(false));
Darin Petkov92c43902011-06-09 20:46:06 -0700110 EXPECT_CALL(glib_, ChildWatchAdd(_, _, _)).Times(0);
Darin Petkovf7897bc2011-06-08 17:13:36 -0700111 EXPECT_FALSE(config_->Start());
112 EXPECT_EQ(0, config_->pid_);
Darin Petkov92c43902011-06-09 20:46:06 -0700113}
Darin Petkovf7897bc2011-06-08 17:13:36 -0700114
Darin Petkovf9b0ca82011-06-20 12:10:23 -0700115namespace {
116
117class UpdateCallbackTest {
118 public:
119 UpdateCallbackTest(const string &message,
Chris Masone2b105542011-06-22 10:58:09 -0700120 const IPConfigRefPtr &ipconfig,
Darin Petkovf9b0ca82011-06-20 12:10:23 -0700121 bool success)
122 : message_(message),
123 ipconfig_(ipconfig),
124 success_(success),
125 called_(false) {}
126
Chris Masone2b105542011-06-22 10:58:09 -0700127 void Callback(const IPConfigRefPtr &ipconfig, bool success) {
Darin Petkovf9b0ca82011-06-20 12:10:23 -0700128 called_ = true;
129 EXPECT_EQ(ipconfig_.get(), ipconfig.get()) << message_;
130 EXPECT_EQ(success_, success) << message_;
131 }
132
133 bool called() const { return called_; }
134
135 private:
136 const string message_;
137 IPConfigRefPtr ipconfig_;
138 bool success_;
139 bool called_;
140};
141
142} // namespace {}
143
144TEST_F(DHCPConfigTest, ProcessEventSignalFail) {
145 DHCPConfig::Configuration conf;
146 conf[DHCPConfig::kConfigurationKeyIPAddress].writer().append_uint32(
147 0x01020304);
148 UpdateCallbackTest callback_test(DHCPConfig::kReasonFail, config_, false);
149 config_->RegisterUpdateCallback(
150 NewCallback(&callback_test, &UpdateCallbackTest::Callback));
151 config_->ProcessEventSignal(DHCPConfig::kReasonFail, conf);
152 EXPECT_TRUE(callback_test.called());
153 EXPECT_TRUE(config_->properties().address.empty());
154}
155
156TEST_F(DHCPConfigTest, ProcessEventSignalSuccess) {
157 static const char * const kReasons[] = {
158 DHCPConfig::kReasonBound,
159 DHCPConfig::kReasonRebind,
160 DHCPConfig::kReasonReboot,
161 DHCPConfig::kReasonRenew
162 };
163 for (size_t r = 0; r < arraysize(kReasons); r++) {
164 DHCPConfig::Configuration conf;
165 string message = string(kReasons[r]) + " failed";
166 conf[DHCPConfig::kConfigurationKeyIPAddress].writer().append_uint32(r);
167 UpdateCallbackTest callback_test(message, config_, true);
168 config_->RegisterUpdateCallback(
169 NewCallback(&callback_test, &UpdateCallbackTest::Callback));
170 config_->ProcessEventSignal(kReasons[r], conf);
171 EXPECT_TRUE(callback_test.called()) << message;
172 EXPECT_EQ(base::StringPrintf("%u.0.0.0", r), config_->properties().address)
173 << message;
174 }
175}
176
177TEST_F(DHCPConfigTest, ProcessEventSignalUnknown) {
178 DHCPConfig::Configuration conf;
179 conf[DHCPConfig::kConfigurationKeyIPAddress].writer().append_uint32(
180 0x01020304);
181 static const char kReasonUnknown[] = "UNKNOWN_REASON";
182 UpdateCallbackTest callback_test(kReasonUnknown, config_, false);
183 config_->RegisterUpdateCallback(
184 NewCallback(&callback_test, &UpdateCallbackTest::Callback));
185 config_->ProcessEventSignal(kReasonUnknown, conf);
186 EXPECT_FALSE(callback_test.called());
187 EXPECT_TRUE(config_->properties().address.empty());
188}
189
190
Darin Petkov98dd6a02011-06-10 15:12:57 -0700191TEST_F(DHCPConfigTest, ReleaseIP) {
192 config_->pid_ = 1 << 18; // Ensure unknown positive PID.
Darin Petkovaceede32011-07-18 15:32:38 -0700193 EXPECT_CALL(*proxy_, Release(kDeviceName)).Times(1);
Darin Petkov98dd6a02011-06-10 15:12:57 -0700194 EXPECT_TRUE(config_->ReleaseIP());
195 config_->pid_ = 0;
196}
197
198TEST_F(DHCPConfigTest, RenewIP) {
199 config_->pid_ = 456;
Darin Petkovaceede32011-07-18 15:32:38 -0700200 EXPECT_CALL(*proxy_, Rebind(kDeviceName)).Times(1);
Darin Petkov98dd6a02011-06-10 15:12:57 -0700201 EXPECT_TRUE(config_->RenewIP());
202 config_->pid_ = 0;
203}
204
205TEST_F(DHCPConfigTest, RequestIP) {
206 config_->pid_ = 567;
Darin Petkovaceede32011-07-18 15:32:38 -0700207 EXPECT_CALL(*proxy_, Rebind(kDeviceName)).Times(1);
Darin Petkov98dd6a02011-06-10 15:12:57 -0700208 EXPECT_TRUE(config_->RenewIP());
209 config_->pid_ = 0;
210}
211
212TEST_F(DHCPConfigTest, Restart) {
213 const int kPID1 = 1 << 17; // Ensure unknown positive PID.
214 const int kPID2 = 987;
215 const unsigned int kTag1 = 11;
216 const unsigned int kTag2 = 22;
217 config_->pid_ = kPID1;
218 config_->child_watch_tag_ = kTag1;
219 DHCPProvider::GetInstance()->BindPID(kPID1, config_);
220 EXPECT_CALL(glib_, SourceRemove(kTag1)).WillOnce(Return(true));
221 EXPECT_CALL(glib_, SpawnClosePID(kPID1)).Times(1);
222 EXPECT_CALL(glib_, SpawnAsync(_, _, _, _, _, _, _, _))
223 .WillOnce(DoAll(SetArgumentPointee<6>(kPID2), Return(true)));
224 EXPECT_CALL(glib_, ChildWatchAdd(kPID2, _, _)).WillOnce(Return(kTag2));
225 EXPECT_TRUE(config_->Restart());
226 EXPECT_EQ(kPID2, config_->pid_);
227 EXPECT_EQ(config_.get(), DHCPProvider::GetInstance()->GetConfig(kPID2).get());
228 EXPECT_EQ(kTag2, config_->child_watch_tag_);
229 DHCPProvider::GetInstance()->UnbindPID(kPID2);
230 config_->pid_ = 0;
231 config_->child_watch_tag_ = 0;
232}
233
234TEST_F(DHCPConfigTest, RestartNoClient) {
235 const int kPID = 777;
236 const unsigned int kTag = 66;
237 EXPECT_CALL(glib_, SourceRemove(_)).Times(0);
238 EXPECT_CALL(glib_, SpawnClosePID(_)).Times(0);
239 EXPECT_CALL(glib_, SpawnAsync(_, _, _, _, _, _, _, _))
240 .WillOnce(DoAll(SetArgumentPointee<6>(kPID), Return(true)));
241 EXPECT_CALL(glib_, ChildWatchAdd(kPID, _, _)).WillOnce(Return(kTag));
242 EXPECT_TRUE(config_->Restart());
243 EXPECT_EQ(kPID, config_->pid_);
244 EXPECT_EQ(config_.get(), DHCPProvider::GetInstance()->GetConfig(kPID).get());
245 EXPECT_EQ(kTag, config_->child_watch_tag_);
246 DHCPProvider::GetInstance()->UnbindPID(kPID);
247 config_->pid_ = 0;
248 config_->child_watch_tag_ = 0;
249}
250
Darin Petkov92c43902011-06-09 20:46:06 -0700251TEST_F(DHCPConfigTest, StartSuccess) {
252 const int kPID = 123456;
253 const unsigned int kTag = 55;
Darin Petkovf7897bc2011-06-08 17:13:36 -0700254 EXPECT_CALL(glib_, SpawnAsync(_, _, _, _, _, _, _, _))
255 .WillOnce(DoAll(SetArgumentPointee<6>(kPID), Return(true)));
Darin Petkov92c43902011-06-09 20:46:06 -0700256 EXPECT_CALL(glib_, ChildWatchAdd(kPID, _, _)).WillOnce(Return(kTag));
Darin Petkovf7897bc2011-06-08 17:13:36 -0700257 EXPECT_TRUE(config_->Start());
258 EXPECT_EQ(kPID, config_->pid_);
Darin Petkov98dd6a02011-06-10 15:12:57 -0700259 EXPECT_EQ(config_.get(), DHCPProvider::GetInstance()->GetConfig(kPID).get());
260 EXPECT_EQ(kTag, config_->child_watch_tag_);
Darin Petkov92c43902011-06-09 20:46:06 -0700261
262 ScopedTempDir temp_dir;
263 config_->root_ = temp_dir.path();
264 FilePath varrun = temp_dir.path().Append("var/run");
265 EXPECT_TRUE(file_util::CreateDirectory(varrun));
266 FilePath pid_file =
267 varrun.Append(base::StringPrintf("dhcpcd-%s.pid", kDeviceName));
268 FilePath lease_file =
269 varrun.Append(base::StringPrintf("dhcpcd-%s.lease", kDeviceName));
270 EXPECT_EQ(0, file_util::WriteFile(pid_file, "", 0));
271 EXPECT_EQ(0, file_util::WriteFile(lease_file, "", 0));
272 ASSERT_TRUE(file_util::PathExists(pid_file));
273 ASSERT_TRUE(file_util::PathExists(lease_file));
274
275 EXPECT_CALL(glib_, SpawnClosePID(kPID)).Times(1);
276 DHCPConfig::ChildWatchCallback(kPID, 0, config_.get());
Darin Petkov98dd6a02011-06-10 15:12:57 -0700277 EXPECT_EQ(NULL, DHCPProvider::GetInstance()->GetConfig(kPID).get());
Darin Petkov92c43902011-06-09 20:46:06 -0700278 EXPECT_FALSE(file_util::PathExists(pid_file));
279 EXPECT_FALSE(file_util::PathExists(lease_file));
Darin Petkovf7897bc2011-06-08 17:13:36 -0700280}
281
Darin Petkov98dd6a02011-06-10 15:12:57 -0700282TEST_F(DHCPConfigTest, Stop) {
283 // Ensure no crashes.
284 const int kPID = 1 << 17; // Ensure unknown positive PID.
285 config_->Stop();
286 config_->pid_ = kPID;
287 config_->Stop();
288 EXPECT_CALL(glib_, SpawnClosePID(kPID)).Times(1); // Invoked by destuctor.
289}
290
Chris Masone43b48a12011-07-01 13:37:07 -0700291TEST_F(DHCPConfigTest, Dispatch) {
Chris Masone27c4aa52011-07-02 13:10:14 -0700292 EXPECT_TRUE(DBusAdaptor::DispatchOnType(config_->store(),
Chris Masone43b48a12011-07-01 13:37:07 -0700293 flimflam::kMtuProperty,
294 PropertyStoreTest::kInt32V,
295 NULL));
296 ::DBus::Error error;
297 // Ensure that an attempt to write a R/O property returns InvalidArgs error.
Chris Masone27c4aa52011-07-02 13:10:14 -0700298 EXPECT_FALSE(DBusAdaptor::DispatchOnType(config_->store(),
Chris Masone43b48a12011-07-01 13:37:07 -0700299 flimflam::kAddressProperty,
300 PropertyStoreTest::kStringV,
301 &error));
302 EXPECT_EQ(invalid_args_, error.name());
303}
304
Darin Petkove7cb7f82011-06-03 13:21:51 -0700305} // namespace shill