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