dns_client_unittest.cc revision f582b50dc416de301f3e4a5f1712a93b9ce02e95
1// 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/dns_client.h"
6
7#include <netdb.h>
8
9#include <string>
10#include <vector>
11
12#include <base/bind.h>
13#include <base/memory/scoped_ptr.h>
14#include <gtest/gtest.h>
15#include <gmock/gmock.h>
16
17#include "shill/error.h"
18#include "shill/event_dispatcher.h"
19#include "shill/io_handler.h"
20#include "shill/mock_ares.h"
21#include "shill/mock_control.h"
22#include "shill/mock_event_dispatcher.h"
23#include "shill/mock_time.h"
24
25using base::Bind;
26using base::Unretained;
27using std::string;
28using std::vector;
29using testing::_;
30using testing::DoAll;
31using testing::Return;
32using testing::ReturnArg;
33using testing::ReturnNew;
34using testing::Test;
35using testing::SetArgumentPointee;
36using testing::StrEq;
37using testing::StrictMock;
38
39namespace shill {
40
41namespace {
42const char kGoodName[] = "all-systems.mcast.net";
43const char kResult[] = "224.0.0.1";
44const char kGoodServer[] = "8.8.8.8";
45const char kBadServer[] = "10.9xx8.7";
46const char kNetworkInterface[] = "eth0";
47char kReturnAddressList0[] = { 224, 0, 0, 1 };
48char *kReturnAddressList[] = { kReturnAddressList0, NULL };
49char kFakeAresChannelData = 0;
50const ares_channel kAresChannel =
51    reinterpret_cast<ares_channel>(&kFakeAresChannelData);
52const int kAresFd = 10203;
53const int kAresTimeoutMS = 2000;  // ARES transaction timeout
54const int kAresWaitMS = 1000;     // Time period ARES asks caller to wait
55}  // namespace {}
56
57MATCHER_P(IsSuccess, is_success, "") {
58  return is_success == arg.IsSuccess();
59}
60
61MATCHER_P2(IsFailure, failure_type, failure_message, "") {
62  return failure_type == arg.type() && failure_message == arg.message();
63}
64
65class DNSClientTest : public Test {
66 public:
67  DNSClientTest()
68      : ares_result_(ARES_SUCCESS), address_result_(IPAddress::kFamilyUnknown) {
69    time_val_.tv_sec = 0;
70    time_val_.tv_usec = 0;
71    ares_timeout_.tv_sec = kAresWaitMS / 1000;
72    ares_timeout_.tv_usec = (kAresWaitMS % 1000) * 1000;
73    hostent_.h_addrtype = IPAddress::kFamilyIPv4;
74    hostent_.h_length = sizeof(kReturnAddressList0);
75    hostent_.h_addr_list = kReturnAddressList;
76  }
77
78  virtual void SetUp() {
79    EXPECT_CALL(time_, GetTimeMonotonic(_))
80        .WillRepeatedly(DoAll(SetArgumentPointee<0>(time_val_), Return(0)));
81    SetInActive();
82  }
83
84  virtual void TearDown() {
85    // We need to make sure the dns_client instance releases ares_
86    // before the destructor for DNSClientTest deletes ares_.
87    if (dns_client_.get()) {
88      dns_client_->Stop();
89    }
90  }
91
92  void AdvanceTime(int time_ms) {
93    struct timeval adv_time = { time_ms/1000, (time_ms % 1000) * 1000 };
94    timeradd(&time_val_, &adv_time, &time_val_);
95    EXPECT_CALL(time_, GetTimeMonotonic(_))
96        .WillRepeatedly(DoAll(SetArgumentPointee<0>(time_val_), Return(0)));
97  }
98
99  void CallReplyCB() {
100    dns_client_->ReceiveDNSReplyCB(dns_client_.get(), ares_result_, 0,
101                                   &hostent_);
102  }
103
104  void CallDNSRead() {
105    dns_client_->HandleDNSRead(kAresFd);
106  }
107
108  void CallDNSWrite() {
109    dns_client_->HandleDNSWrite(kAresFd);
110  }
111
112  void CallTimeout() {
113    dns_client_->HandleTimeout();
114  }
115
116  void CallCompletion() {
117    dns_client_->HandleCompletion();
118  }
119
120  void CreateClient(const vector<string> &dns_servers, int timeout_ms) {
121    dns_client_.reset(new DNSClient(IPAddress::kFamilyIPv4,
122                                    kNetworkInterface,
123                                    dns_servers,
124                                    timeout_ms,
125                                    &dispatcher_,
126                                    callback_target_.callback()));
127    dns_client_->ares_ = &ares_;
128    dns_client_->time_ = &time_;
129  }
130
131  void SetActive() {
132    // Returns that socket kAresFd is readable.
133    EXPECT_CALL(ares_, GetSock(_, _, _))
134        .WillRepeatedly(DoAll(SetArgumentPointee<1>(kAresFd), Return(1)));
135    EXPECT_CALL(ares_, Timeout(_, _, _))
136        .WillRepeatedly(
137            DoAll(SetArgumentPointee<2>(ares_timeout_), ReturnArg<2>()));
138  }
139
140  void SetInActive() {
141    EXPECT_CALL(ares_, GetSock(_, _, _))
142        .WillRepeatedly(Return(0));
143    EXPECT_CALL(ares_, Timeout(_, _, _))
144        .WillRepeatedly(ReturnArg<1>());
145  }
146
147  void SetupRequest(const string &name, const string &server) {
148    vector<string> dns_servers;
149    dns_servers.push_back(server);
150    CreateClient(dns_servers, kAresTimeoutMS);
151    // These expectations are fulfilled when dns_client_->Start() is called.
152    EXPECT_CALL(ares_, InitOptions(_, _, _))
153        .WillOnce(DoAll(SetArgumentPointee<0>(kAresChannel),
154                        Return(ARES_SUCCESS)));
155    EXPECT_CALL(ares_, SetLocalDev(kAresChannel, StrEq(kNetworkInterface)))
156        .Times(1);
157    EXPECT_CALL(ares_, GetHostByName(kAresChannel, StrEq(name), _, _, _));
158  }
159
160  void StartValidRequest() {
161    SetupRequest(kGoodName, kGoodServer);
162    EXPECT_CALL(dispatcher_,
163                CreateReadyHandler(kAresFd, IOHandler::kModeInput, _))
164        .WillOnce(ReturnNew<IOHandler>());
165    SetActive();
166    EXPECT_CALL(dispatcher_, PostDelayedTask(_, kAresWaitMS));
167    Error error;
168    ASSERT_TRUE(dns_client_->Start(kGoodName, &error));
169    EXPECT_TRUE(error.IsSuccess());
170    EXPECT_CALL(ares_, Destroy(kAresChannel));
171  }
172
173  void TestValidCompletion() {
174    EXPECT_CALL(ares_, ProcessFd(kAresChannel, kAresFd, ARES_SOCKET_BAD))
175        .WillOnce(InvokeWithoutArgs(this, &DNSClientTest::CallReplyCB));
176    ExpectPostCompletionTask();
177    CallDNSRead();
178
179    // Make sure that the address value is correct as held in the DNSClient.
180    ASSERT_TRUE(dns_client_->address_.IsValid());
181    IPAddress ipaddr(dns_client_->address_.family());
182    ASSERT_TRUE(ipaddr.SetAddressFromString(kResult));
183    EXPECT_TRUE(ipaddr.Equals(dns_client_->address_));
184
185    // Make sure the callback gets called with a success result, and save
186    // the callback address argument in |address_result_|.
187    EXPECT_CALL(callback_target_, CallTarget(IsSuccess(true), _))
188        .WillOnce(Invoke(this, &DNSClientTest::SaveCallbackArgs));
189    CallCompletion();
190
191    // Make sure the address was successfully passed to the callback.
192    EXPECT_TRUE(ipaddr.Equals(address_result_));
193    EXPECT_TRUE(dns_client_->address_.IsDefault());
194  }
195
196  void SaveCallbackArgs(const Error &error, const IPAddress &address)  {
197    error_result_.CopyFrom(error);
198    address_result_ = address;
199  }
200
201  void ExpectPostCompletionTask() {
202    EXPECT_CALL(dispatcher_, PostTask(_));
203  }
204
205  void ExpectReset() {
206    EXPECT_TRUE(dns_client_->address_.family() == IPAddress::kFamilyIPv4);
207    EXPECT_TRUE(dns_client_->address_.IsDefault());
208    EXPECT_FALSE(dns_client_->resolver_state_.get());
209  }
210
211 protected:
212  class DNSCallbackTarget {
213   public:
214    DNSCallbackTarget()
215        : callback_(Bind(&DNSCallbackTarget::CallTarget, Unretained(this))) {}
216
217    MOCK_METHOD2(CallTarget, void(const Error &error,
218                                  const IPAddress &address));
219    const DNSClient::ClientCallback &callback() { return callback_; }
220
221   private:
222    DNSClient::ClientCallback callback_;
223  };
224
225  scoped_ptr<DNSClient> dns_client_;
226  StrictMock<MockEventDispatcher> dispatcher_;
227  string queued_request_;
228  StrictMock<DNSCallbackTarget> callback_target_;
229  StrictMock<MockAres> ares_;
230  StrictMock<MockTime> time_;
231  struct timeval time_val_;
232  struct timeval ares_timeout_;
233  struct hostent hostent_;
234  int ares_result_;
235  Error error_result_;
236  IPAddress address_result_;
237};
238
239class SentinelIOHandler : public IOHandler {
240 public:
241  MOCK_METHOD0(Die, void());
242  virtual ~SentinelIOHandler() { Die(); }
243};
244
245TEST_F(DNSClientTest, Constructor) {
246  vector<string> dns_servers;
247  dns_servers.push_back(kGoodServer);
248  CreateClient(dns_servers, kAresTimeoutMS);
249  ExpectReset();
250}
251
252// Receive error because no DNS servers were specified.
253TEST_F(DNSClientTest, NoServers) {
254  CreateClient(vector<string>(), kAresTimeoutMS);
255  Error error;
256  EXPECT_FALSE(dns_client_->Start(kGoodName, &error));
257  EXPECT_EQ(Error::kInvalidArguments, error.type());
258}
259
260// Receive error because the DNS server IP address is invalid.
261TEST_F(DNSClientTest, TimeoutInvalidServer) {
262  vector<string> dns_servers;
263  dns_servers.push_back(kBadServer);
264  CreateClient(dns_servers, kAresTimeoutMS);
265  Error error;
266  ASSERT_FALSE(dns_client_->Start(kGoodName, &error));
267  EXPECT_EQ(Error::kInvalidArguments, error.type());
268}
269
270// Setup error because InitOptions failed.
271TEST_F(DNSClientTest, InitOptionsFailure) {
272  vector<string> dns_servers;
273  dns_servers.push_back(kGoodServer);
274  CreateClient(dns_servers, kAresTimeoutMS);
275  EXPECT_CALL(ares_, InitOptions(_, _, _))
276      .WillOnce(Return(ARES_EBADFLAGS));
277  Error error;
278  EXPECT_FALSE(dns_client_->Start(kGoodName, &error));
279  EXPECT_EQ(Error::kOperationFailed, error.type());
280}
281
282// Fail a second request because one is already in progress.
283TEST_F(DNSClientTest, MultipleRequest) {
284  StartValidRequest();
285  Error error;
286  ASSERT_FALSE(dns_client_->Start(kGoodName, &error));
287  EXPECT_EQ(Error::kInProgress, error.type());
288}
289
290TEST_F(DNSClientTest, GoodRequest) {
291  StartValidRequest();
292  TestValidCompletion();
293}
294
295TEST_F(DNSClientTest, GoodRequestWithTimeout) {
296  StartValidRequest();
297  // Insert an intermediate HandleTimeout callback.
298  AdvanceTime(kAresWaitMS);
299  EXPECT_CALL(ares_, ProcessFd(kAresChannel, ARES_SOCKET_BAD, ARES_SOCKET_BAD));
300  EXPECT_CALL(dispatcher_, PostDelayedTask(_, kAresWaitMS));
301  CallTimeout();
302  AdvanceTime(kAresWaitMS);
303  TestValidCompletion();
304}
305
306TEST_F(DNSClientTest, GoodRequestWithDNSRead) {
307  StartValidRequest();
308  // Insert an intermediate HandleDNSRead callback.
309  AdvanceTime(kAresWaitMS);
310  EXPECT_CALL(ares_, ProcessFd(kAresChannel, kAresFd, ARES_SOCKET_BAD));
311  EXPECT_CALL(dispatcher_, PostDelayedTask(_, kAresWaitMS));
312  CallDNSRead();
313  AdvanceTime(kAresWaitMS);
314  TestValidCompletion();
315}
316
317TEST_F(DNSClientTest, GoodRequestWithDNSWrite) {
318  StartValidRequest();
319  // Insert an intermediate HandleDNSWrite callback.
320  AdvanceTime(kAresWaitMS);
321  EXPECT_CALL(ares_, ProcessFd(kAresChannel, ARES_SOCKET_BAD, kAresFd));
322  EXPECT_CALL(dispatcher_, PostDelayedTask(_, kAresWaitMS));
323  CallDNSWrite();
324  AdvanceTime(kAresWaitMS);
325  TestValidCompletion();
326}
327
328// Failure due to the timeout occurring during first call to RefreshHandles.
329TEST_F(DNSClientTest, TimeoutFirstRefresh) {
330  SetupRequest(kGoodName, kGoodServer);
331  struct timeval init_time_val = time_val_;
332  AdvanceTime(kAresTimeoutMS);
333  EXPECT_CALL(time_, GetTimeMonotonic(_))
334      .WillOnce(DoAll(SetArgumentPointee<0>(init_time_val), Return(0)))
335      .WillRepeatedly(DoAll(SetArgumentPointee<0>(time_val_), Return(0)));
336  EXPECT_CALL(callback_target_, CallTarget(IsSuccess(false), _))
337      .Times(0);
338  EXPECT_CALL(ares_, Destroy(kAresChannel));
339  Error error;
340  // Expect the DNSClient to post a completion task.  However this task will
341  // never run since the Stop() gets called before returning.  We confirm
342  // that the task indeed gets canceled below in ExpectReset().
343  ExpectPostCompletionTask();
344  ASSERT_FALSE(dns_client_->Start(kGoodName, &error));
345  EXPECT_EQ(Error::kOperationTimeout, error.type());
346  EXPECT_EQ(string(DNSClient::kErrorTimedOut), error.message());
347  ExpectReset();
348}
349
350// Failed request due to timeout within the dns_client.
351TEST_F(DNSClientTest, TimeoutDispatcherEvent) {
352  StartValidRequest();
353  EXPECT_CALL(ares_, ProcessFd(kAresChannel,
354                               ARES_SOCKET_BAD, ARES_SOCKET_BAD));
355  AdvanceTime(kAresTimeoutMS);
356  ExpectPostCompletionTask();
357  CallTimeout();
358  EXPECT_CALL(callback_target_, CallTarget(
359      IsFailure(Error::kOperationTimeout, DNSClient::kErrorTimedOut), _));
360  CallCompletion();
361}
362
363// Failed request due to timeout reported by ARES.
364TEST_F(DNSClientTest, TimeoutFromARES) {
365  StartValidRequest();
366  AdvanceTime(kAresWaitMS);
367  ares_result_ = ARES_ETIMEOUT;
368  EXPECT_CALL(ares_, ProcessFd(kAresChannel, ARES_SOCKET_BAD, ARES_SOCKET_BAD))
369        .WillOnce(InvokeWithoutArgs(this, &DNSClientTest::CallReplyCB));
370  ExpectPostCompletionTask();
371  CallTimeout();
372  EXPECT_CALL(callback_target_, CallTarget(
373      IsFailure(Error::kOperationTimeout, DNSClient::kErrorTimedOut), _));
374  CallCompletion();
375}
376
377// Failed request due to "host not found" reported by ARES.
378TEST_F(DNSClientTest, HostNotFound) {
379  StartValidRequest();
380  AdvanceTime(kAresWaitMS);
381  ares_result_ = ARES_ENOTFOUND;
382  EXPECT_CALL(ares_, ProcessFd(kAresChannel, kAresFd, ARES_SOCKET_BAD))
383      .WillOnce(InvokeWithoutArgs(this, &DNSClientTest::CallReplyCB));
384  ExpectPostCompletionTask();
385  CallDNSRead();
386  EXPECT_CALL(callback_target_, CallTarget(
387      IsFailure(Error::kOperationFailed, DNSClient::kErrorNotFound), _));
388  CallCompletion();
389}
390
391// Make sure IOHandles are deallocated when GetSock() reports them gone.
392TEST_F(DNSClientTest, IOHandleDeallocGetSock) {
393  SetupRequest(kGoodName, kGoodServer);
394  // This isn't any kind of scoped/ref pointer because we are tracking dealloc.
395  SentinelIOHandler *io_handler = new SentinelIOHandler();
396  EXPECT_CALL(dispatcher_,
397              CreateReadyHandler(kAresFd, IOHandler::kModeInput, _))
398      .WillOnce(Return(io_handler));
399  EXPECT_CALL(dispatcher_, PostDelayedTask(_, kAresWaitMS));
400  SetActive();
401  Error error;
402  ASSERT_TRUE(dns_client_->Start(kGoodName, &error));
403  AdvanceTime(kAresWaitMS);
404  SetInActive();
405  EXPECT_CALL(*io_handler, Die());
406  EXPECT_CALL(ares_, ProcessFd(kAresChannel, kAresFd, ARES_SOCKET_BAD));
407  EXPECT_CALL(dispatcher_, PostDelayedTask(_, kAresWaitMS));
408  CallDNSRead();
409  EXPECT_CALL(ares_, Destroy(kAresChannel));
410}
411
412// Make sure IOHandles are deallocated when Stop() is called.
413TEST_F(DNSClientTest, IOHandleDeallocStop) {
414  SetupRequest(kGoodName, kGoodServer);
415  // This isn't any kind of scoped/ref pointer because we are tracking dealloc.
416  SentinelIOHandler *io_handler = new SentinelIOHandler();
417  EXPECT_CALL(dispatcher_,
418              CreateReadyHandler(kAresFd, IOHandler::kModeInput, _))
419      .WillOnce(Return(io_handler));
420  EXPECT_CALL(dispatcher_, PostDelayedTask(_, kAresWaitMS));
421  SetActive();
422  Error error;
423  ASSERT_TRUE(dns_client_->Start(kGoodName, &error));
424  EXPECT_CALL(*io_handler, Die());
425  EXPECT_CALL(ares_, Destroy(kAresChannel));
426  dns_client_->Stop();
427}
428
429}  // namespace shill
430