blob: 720240ec19c9389db11a1e318e033cdc20d12dfc [file] [log] [blame]
Paul Stewarte6927402012-01-23 16:11:30 -08001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Paul Stewartc2350ee2011-10-19 12:28:40 -07002// 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/dns_client.h"
6
7#include <netdb.h>
8
9#include <string>
10#include <vector>
11
12#include <base/memory/scoped_ptr.h>
13#include <gtest/gtest.h>
14#include <gmock/gmock.h>
15
16#include "shill/event_dispatcher.h"
17#include "shill/io_handler.h"
18#include "shill/mock_ares.h"
19#include "shill/mock_control.h"
20#include "shill/mock_event_dispatcher.h"
21#include "shill/mock_time.h"
22
23using std::string;
24using std::vector;
25using testing::_;
26using testing::DoAll;
27using testing::Return;
28using testing::ReturnArg;
29using testing::ReturnNew;
30using testing::Test;
31using testing::SetArgumentPointee;
32using testing::StrEq;
33using testing::StrictMock;
34
35namespace shill {
36
37namespace {
38const char kGoodName[] = "all-systems.mcast.net";
39const char kResult[] = "224.0.0.1";
40const char kGoodServer[] = "8.8.8.8";
41const char kBadServer[] = "10.9xx8.7";
42const char kNetworkInterface[] = "eth0";
43char kReturnAddressList0[] = { 224, 0, 0, 1 };
44char *kReturnAddressList[] = { kReturnAddressList0, NULL };
45char kFakeAresChannelData = 0;
46const ares_channel kAresChannel =
47 reinterpret_cast<ares_channel>(&kFakeAresChannelData);
48const int kAresFd = 10203;
49const int kAresTimeoutMS = 2000; // ARES transaction timeout
50const int kAresWaitMS = 1000; // Time period ARES asks caller to wait
51} // namespace {}
52
53class DNSClientTest : public Test {
54 public:
55 DNSClientTest() : ares_result_(ARES_SUCCESS) {
56 time_val_.tv_sec = 0;
57 time_val_.tv_usec = 0;
58 ares_timeout_.tv_sec = kAresWaitMS / 1000;
59 ares_timeout_.tv_usec = (kAresWaitMS % 1000) * 1000;
60 hostent_.h_addrtype = IPAddress::kFamilyIPv4;
61 hostent_.h_length = sizeof(kReturnAddressList0);
62 hostent_.h_addr_list = kReturnAddressList;
63 }
64
65 virtual void SetUp() {
Paul Stewarte6927402012-01-23 16:11:30 -080066 EXPECT_CALL(time_, GetTimeMonotonic(_))
Paul Stewartc2350ee2011-10-19 12:28:40 -070067 .WillRepeatedly(DoAll(SetArgumentPointee<0>(time_val_), Return(0)));
68 SetInActive();
69 }
70
71 virtual void TearDown() {
72 // We need to make sure the dns_client instance releases ares_
73 // before the destructor for DNSClientTest deletes ares_.
74 if (dns_client_.get()) {
75 dns_client_->Stop();
76 }
77 }
78
79 void AdvanceTime(int time_ms) {
80 struct timeval adv_time = { time_ms/1000, (time_ms % 1000) * 1000 };
81 timeradd(&time_val_, &adv_time, &time_val_);
Paul Stewarte6927402012-01-23 16:11:30 -080082 EXPECT_CALL(time_, GetTimeMonotonic(_))
Paul Stewartc2350ee2011-10-19 12:28:40 -070083 .WillRepeatedly(DoAll(SetArgumentPointee<0>(time_val_), Return(0)));
84 }
85
86 void CallReplyCB() {
87 dns_client_->ReceiveDNSReplyCB(dns_client_.get(), ares_result_, 0,
88 &hostent_);
89 }
90
91 void CallDNSRead() {
92 dns_client_->HandleDNSRead(kAresFd);
93 }
94
95 void CallDNSWrite() {
96 dns_client_->HandleDNSWrite(kAresFd);
97 }
98
99 void CallTimeout() {
100 dns_client_->HandleTimeout();
101 }
102
103 void CreateClient(const vector<string> &dns_servers, int timeout_ms) {
104 dns_client_.reset(new DNSClient(IPAddress::kFamilyIPv4,
105 kNetworkInterface,
106 dns_servers,
107 timeout_ms,
108 &dispatcher_,
109 callback_target_.callback()));
110 dns_client_->ares_ = &ares_;
111 dns_client_->time_ = &time_;
112 }
113
114 void SetActive() {
115 // Returns that socket kAresFd is readable.
116 EXPECT_CALL(ares_, GetSock(_, _, _))
117 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kAresFd), Return(1)));
118 EXPECT_CALL(ares_, Timeout(_, _, _))
119 .WillRepeatedly(
120 DoAll(SetArgumentPointee<2>(ares_timeout_), ReturnArg<2>()));
121 }
122
123 void SetInActive() {
124 EXPECT_CALL(ares_, GetSock(_, _, _))
125 .WillRepeatedly(Return(0));
126 EXPECT_CALL(ares_, Timeout(_, _, _))
127 .WillRepeatedly(ReturnArg<1>());
128 }
129
130 void SetupRequest(const string &name, const string &server) {
131 vector<string> dns_servers;
132 dns_servers.push_back(server);
133 CreateClient(dns_servers, kAresTimeoutMS);
134 // These expectations are fulfilled when dns_client_->Start() is called.
135 EXPECT_CALL(ares_, InitOptions(_, _, _))
136 .WillOnce(DoAll(SetArgumentPointee<0>(kAresChannel),
137 Return(ARES_SUCCESS)));
138 EXPECT_CALL(ares_, SetLocalDev(kAresChannel, StrEq(kNetworkInterface)))
139 .Times(1);
140 EXPECT_CALL(ares_, GetHostByName(kAresChannel, StrEq(name), _, _, _));
141 }
142
143 void StartValidRequest() {
144 SetupRequest(kGoodName, kGoodServer);
145 EXPECT_CALL(dispatcher_,
146 CreateReadyHandler(kAresFd, IOHandler::kModeInput, _))
147 .WillOnce(ReturnNew<IOHandler>());
148 SetActive();
149 EXPECT_CALL(dispatcher_, PostDelayedTask(_, kAresWaitMS));
150 ASSERT_TRUE(dns_client_->Start(kGoodName));
151 EXPECT_CALL(ares_, Destroy(kAresChannel));
152 }
153
154 void TestValidCompletion() {
155 EXPECT_CALL(callback_target_, CallTarget(true));
156 EXPECT_CALL(ares_, ProcessFd(kAresChannel, kAresFd, ARES_SOCKET_BAD))
157 .WillOnce(InvokeWithoutArgs(this, &DNSClientTest::CallReplyCB));
158 CallDNSRead();
159 ASSERT_TRUE(dns_client_->address().IsValid());
160 IPAddress ipaddr(dns_client_->address().family());
161 ASSERT_TRUE(ipaddr.SetAddressFromString(kResult));
162 EXPECT_TRUE(ipaddr.Equals(dns_client_->address()));
163 }
164
165 protected:
166 class DNSCallbackTarget {
167 public:
168 DNSCallbackTarget()
169 : callback_(NewCallback(this, &DNSCallbackTarget::CallTarget)) {}
170
171 MOCK_METHOD1(CallTarget, void(bool success));
172 Callback1<bool>::Type *callback() { return callback_.get(); }
173
174 private:
175 scoped_ptr<Callback1<bool>::Type> callback_;
176 };
177
178 scoped_ptr<DNSClient> dns_client_;
179 MockEventDispatcher dispatcher_;
180 string queued_request_;
181 StrictMock<DNSCallbackTarget> callback_target_;
182 StrictMock<MockAres> ares_;
183 StrictMock<MockTime> time_;
184 struct timeval time_val_;
185 struct timeval ares_timeout_;
186 struct hostent hostent_;
187 int ares_result_;
188};
189
190class SentinelIOHandler : public IOHandler {
191 public:
192 MOCK_METHOD0(Die, void());
193 virtual ~SentinelIOHandler() { Die(); }
194};
195
196TEST_F(DNSClientTest, Constructor) {
197 vector<string> dns_servers;
198 dns_servers.push_back(kGoodServer);
199 CreateClient(dns_servers, kAresTimeoutMS);
200 EXPECT_TRUE(dns_client_->address().family() == IPAddress::kFamilyIPv4);
201 EXPECT_TRUE(dns_client_->address().IsDefault());
202}
203
204// Receive error because no DNS servers were specified.
205TEST_F(DNSClientTest, NoServers) {
206 CreateClient(vector<string>(), kAresTimeoutMS);
207 EXPECT_FALSE(dns_client_->Start(kGoodName));
208}
209
210// Receive error because the DNS server IP address is invalid.
211TEST_F(DNSClientTest, TimeoutInvalidServer) {
212 vector<string> dns_servers;
213 dns_servers.push_back(kBadServer);
214 CreateClient(dns_servers, kAresTimeoutMS);
215 ASSERT_FALSE(dns_client_->Start(kGoodName));
216}
217
218// Setup error because InitOptions failed.
219TEST_F(DNSClientTest, InitOptionsFailure) {
220 vector<string> dns_servers;
221 dns_servers.push_back(kGoodServer);
222 CreateClient(dns_servers, kAresTimeoutMS);
223 EXPECT_CALL(ares_, InitOptions(_, _, _))
224 .WillOnce(Return(ARES_EBADFLAGS));
225 EXPECT_FALSE(dns_client_->Start(kGoodName));
226}
227
228// Fail a second request because one is already in progress.
229TEST_F(DNSClientTest, MultipleRequest) {
230 StartValidRequest();
231 ASSERT_FALSE(dns_client_->Start(kGoodName));
232}
233
234TEST_F(DNSClientTest, GoodRequest) {
235 StartValidRequest();
236 TestValidCompletion();
237}
238
239TEST_F(DNSClientTest, GoodRequestWithTimeout) {
240 StartValidRequest();
241 // Insert an intermediate HandleTimeout callback.
242 AdvanceTime(kAresWaitMS);
243 EXPECT_CALL(ares_, ProcessFd(kAresChannel, ARES_SOCKET_BAD, ARES_SOCKET_BAD));
244 EXPECT_CALL(dispatcher_, PostDelayedTask(_, kAresWaitMS));
245 CallTimeout();
246 AdvanceTime(kAresWaitMS);
247 TestValidCompletion();
248}
249
250TEST_F(DNSClientTest, GoodRequestWithDNSRead) {
251 StartValidRequest();
252 // Insert an intermediate HandleDNSRead callback.
253 AdvanceTime(kAresWaitMS);
254 EXPECT_CALL(ares_, ProcessFd(kAresChannel, kAresFd, ARES_SOCKET_BAD));
255 EXPECT_CALL(dispatcher_, PostDelayedTask(_, kAresWaitMS));
256 CallDNSRead();
257 AdvanceTime(kAresWaitMS);
258 TestValidCompletion();
259}
260
261TEST_F(DNSClientTest, GoodRequestWithDNSWrite) {
262 StartValidRequest();
263 // Insert an intermediate HandleDNSWrite callback.
264 AdvanceTime(kAresWaitMS);
265 EXPECT_CALL(ares_, ProcessFd(kAresChannel, ARES_SOCKET_BAD, kAresFd));
266 EXPECT_CALL(dispatcher_, PostDelayedTask(_, kAresWaitMS));
267 CallDNSWrite();
268 AdvanceTime(kAresWaitMS);
269 TestValidCompletion();
270}
271
272// Failure due to the timeout occurring during first call to RefreshHandles.
273TEST_F(DNSClientTest, TimeoutFirstRefresh) {
274 SetupRequest(kGoodName, kGoodServer);
275 struct timeval init_time_val = time_val_;
276 AdvanceTime(kAresTimeoutMS);
Paul Stewarte6927402012-01-23 16:11:30 -0800277 EXPECT_CALL(time_, GetTimeMonotonic(_))
Paul Stewartc2350ee2011-10-19 12:28:40 -0700278 .WillOnce(DoAll(SetArgumentPointee<0>(init_time_val), Return(0)))
279 .WillRepeatedly(DoAll(SetArgumentPointee<0>(time_val_), Return(0)));
280 EXPECT_CALL(callback_target_, CallTarget(false));
281 EXPECT_CALL(ares_, Destroy(kAresChannel));
282 ASSERT_FALSE(dns_client_->Start(kGoodName));
283 EXPECT_EQ(string(DNSClient::kErrorTimedOut), dns_client_->error());
284}
285
286// Failed request due to timeout within the dns_client.
287TEST_F(DNSClientTest, TimeoutDispatcherEvent) {
288 StartValidRequest();
289 EXPECT_CALL(ares_, ProcessFd(kAresChannel,
290 ARES_SOCKET_BAD, ARES_SOCKET_BAD));
291 AdvanceTime(kAresTimeoutMS);
292 EXPECT_CALL(callback_target_, CallTarget(false));
293 CallTimeout();
294}
295
296// Failed request due to timeout reported by ARES.
297TEST_F(DNSClientTest, TimeoutFromARES) {
298 StartValidRequest();
299 AdvanceTime(kAresWaitMS);
300 ares_result_ = ARES_ETIMEOUT;
301 EXPECT_CALL(ares_, ProcessFd(kAresChannel, ARES_SOCKET_BAD, ARES_SOCKET_BAD))
302 .WillOnce(InvokeWithoutArgs(this, &DNSClientTest::CallReplyCB));
303 EXPECT_CALL(callback_target_, CallTarget(false));
304 CallTimeout();
305 EXPECT_EQ(string(DNSClient::kErrorTimedOut), dns_client_->error());
306}
307
308// Failed request due to "host not found" reported by ARES.
309TEST_F(DNSClientTest, HostNotFound) {
310 StartValidRequest();
311 AdvanceTime(kAresWaitMS);
312 ares_result_ = ARES_ENOTFOUND;
313 EXPECT_CALL(ares_, ProcessFd(kAresChannel, kAresFd, ARES_SOCKET_BAD))
314 .WillOnce(InvokeWithoutArgs(this, &DNSClientTest::CallReplyCB));
315 EXPECT_CALL(callback_target_, CallTarget(false));
316 CallDNSRead();
317 EXPECT_EQ(string(DNSClient::kErrorNotFound), dns_client_->error());
318}
319
320// Make sure IOHandles are deallocated when GetSock() reports them gone.
321TEST_F(DNSClientTest, IOHandleDeallocGetSock) {
322 SetupRequest(kGoodName, kGoodServer);
323 // This isn't any kind of scoped/ref pointer because we are tracking dealloc.
324 SentinelIOHandler *io_handler = new SentinelIOHandler();
325 EXPECT_CALL(dispatcher_,
326 CreateReadyHandler(kAresFd, IOHandler::kModeInput, _))
327 .WillOnce(Return(io_handler));
328 EXPECT_CALL(dispatcher_, PostDelayedTask(_, kAresWaitMS));
329 SetActive();
330 ASSERT_TRUE(dns_client_->Start(kGoodName));
331 AdvanceTime(kAresWaitMS);
332 SetInActive();
333 EXPECT_CALL(*io_handler, Die());
334 EXPECT_CALL(ares_, ProcessFd(kAresChannel, kAresFd, ARES_SOCKET_BAD));
335 EXPECT_CALL(dispatcher_, PostDelayedTask(_, kAresWaitMS));
336 CallDNSRead();
337 EXPECT_CALL(ares_, Destroy(kAresChannel));
338}
339
340// Make sure IOHandles are deallocated when Stop() is called.
341TEST_F(DNSClientTest, IOHandleDeallocStop) {
342 SetupRequest(kGoodName, kGoodServer);
343 // This isn't any kind of scoped/ref pointer because we are tracking dealloc.
344 SentinelIOHandler *io_handler = new SentinelIOHandler();
345 EXPECT_CALL(dispatcher_,
346 CreateReadyHandler(kAresFd, IOHandler::kModeInput, _))
347 .WillOnce(Return(io_handler));
348 EXPECT_CALL(dispatcher_, PostDelayedTask(_, kAresWaitMS));
349 SetActive();
350 ASSERT_TRUE(dns_client_->Start(kGoodName));
351 EXPECT_CALL(*io_handler, Die());
352 EXPECT_CALL(ares_, Destroy(kAresChannel));
353 dns_client_->Stop();
354}
355
356} // namespace shill