dns_client_unittest.cc revision c2350ee42c6734750ef8a57bae20f23a224cbc53
1// 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 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() { 66 EXPECT_CALL(time_, GetTimeOfDay(_, _)) 67 .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_); 82 EXPECT_CALL(time_, GetTimeOfDay(_, _)) 83 .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); 277 EXPECT_CALL(time_, GetTimeOfDay(_, _)) 278 .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 357