1// Copyright 2013 The Chromium 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 "chrome/utility/local_discovery/service_discovery_client_impl.h" 6#include "net/dns/mdns_client_impl.h" 7#include "net/dns/mock_mdns_socket_factory.h" 8#include "testing/gmock/include/gmock/gmock.h" 9#include "testing/gtest/include/gtest/gtest.h" 10 11using ::testing::_; 12 13namespace local_discovery { 14 15namespace { 16 17const uint8 kSamplePacketA[] = { 18 // Header 19 0x00, 0x00, // ID is zeroed out 20 0x81, 0x80, // Standard query response, RA, no error 21 0x00, 0x00, // No questions (for simplicity) 22 0x00, 0x01, // 1 RR (answers) 23 0x00, 0x00, // 0 authority RRs 24 0x00, 0x00, // 0 additional RRs 25 26 0x07, 'm', 'y', 'h', 'e', 'l', 'l', 'o', 27 0x05, 'l', 'o', 'c', 'a', 'l', 28 0x00, 29 0x00, 0x01, // TYPE is A. 30 0x00, 0x01, // CLASS is IN. 31 0x00, 0x00, // TTL (4 bytes) is 16 seconds. 32 0x00, 0x10, 33 0x00, 0x04, // RDLENGTH is 4 bytes. 34 0x01, 0x02, 35 0x03, 0x04, 36}; 37 38const uint8 kSamplePacketAAAA[] = { 39 // Header 40 0x00, 0x00, // ID is zeroed out 41 0x81, 0x80, // Standard query response, RA, no error 42 0x00, 0x00, // No questions (for simplicity) 43 0x00, 0x01, // 1 RR (answers) 44 0x00, 0x00, // 0 authority RRs 45 0x00, 0x00, // 0 additional RRs 46 47 0x07, 'm', 'y', 'h', 'e', 'l', 'l', 'o', 48 0x05, 'l', 'o', 'c', 'a', 'l', 49 0x00, 50 0x00, 0x1C, // TYPE is AAAA. 51 0x00, 0x01, // CLASS is IN. 52 0x00, 0x00, // TTL (4 bytes) is 16 seconds. 53 0x00, 0x10, 54 0x00, 0x10, // RDLENGTH is 4 bytes. 55 0x00, 0x0A, 0x00, 0x00, 56 0x00, 0x00, 0x00, 0x00, 57 0x00, 0x01, 0x00, 0x02, 58 0x00, 0x03, 0x00, 0x04, 59}; 60 61class LocalDomainResolverTest : public testing::Test { 62 public: 63 virtual void SetUp() OVERRIDE { 64 mdns_client_.StartListening(&socket_factory_); 65 } 66 67 std::string IPAddressToStringWithEmpty(const net::IPAddressNumber& address) { 68 if (address.empty()) return ""; 69 return net::IPAddressToString(address); 70 } 71 72 void AddressCallback(bool resolved, 73 const net::IPAddressNumber& address_ipv4, 74 const net::IPAddressNumber& address_ipv6) { 75 AddressCallbackInternal(resolved, 76 IPAddressToStringWithEmpty(address_ipv4), 77 IPAddressToStringWithEmpty(address_ipv6)); 78 } 79 80 void RunFor(base::TimeDelta time_period) { 81 base::CancelableCallback<void()> callback(base::Bind( 82 &base::MessageLoop::Quit, 83 base::Unretained(base::MessageLoop::current()))); 84 base::MessageLoop::current()->PostDelayedTask( 85 FROM_HERE, callback.callback(), time_period); 86 87 base::MessageLoop::current()->Run(); 88 callback.Cancel(); 89 } 90 91 MOCK_METHOD3(AddressCallbackInternal, 92 void(bool resolved, 93 std::string address_ipv4, 94 std::string address_ipv6)); 95 96 net::MockMDnsSocketFactory socket_factory_; 97 net::MDnsClientImpl mdns_client_; 98 base::MessageLoop message_loop_; 99}; 100 101TEST_F(LocalDomainResolverTest, ResolveDomainA) { 102 LocalDomainResolverImpl resolver( 103 "myhello.local", net::ADDRESS_FAMILY_IPV4, 104 base::Bind(&LocalDomainResolverTest::AddressCallback, 105 base::Unretained(this)), &mdns_client_); 106 107 EXPECT_CALL(socket_factory_, OnSendTo(_)).Times(2); // Twice per query 108 109 resolver.Start(); 110 111 EXPECT_CALL(*this, AddressCallbackInternal(true, "1.2.3.4", "")); 112 113 socket_factory_.SimulateReceive(kSamplePacketA, sizeof(kSamplePacketA)); 114} 115 116TEST_F(LocalDomainResolverTest, ResolveDomainAAAA) { 117 LocalDomainResolverImpl resolver( 118 "myhello.local", net::ADDRESS_FAMILY_IPV6, 119 base::Bind(&LocalDomainResolverTest::AddressCallback, 120 base::Unretained(this)), &mdns_client_); 121 122 EXPECT_CALL(socket_factory_, OnSendTo(_)).Times(2); // Twice per query 123 124 resolver.Start(); 125 126 EXPECT_CALL(*this, AddressCallbackInternal(true, "", "a::1:2:3:4")); 127 128 socket_factory_.SimulateReceive(kSamplePacketAAAA, sizeof(kSamplePacketAAAA)); 129} 130 131TEST_F(LocalDomainResolverTest, ResolveDomainAnyOneAvailable) { 132 LocalDomainResolverImpl resolver( 133 "myhello.local", net::ADDRESS_FAMILY_UNSPECIFIED, 134 base::Bind(&LocalDomainResolverTest::AddressCallback, 135 base::Unretained(this)), &mdns_client_); 136 137 EXPECT_CALL(socket_factory_, OnSendTo(_)).Times(4); // Twice per query 138 139 resolver.Start(); 140 141 socket_factory_.SimulateReceive(kSamplePacketAAAA, sizeof(kSamplePacketAAAA)); 142 143 EXPECT_CALL(*this, AddressCallbackInternal(true, "", "a::1:2:3:4")); 144 145 RunFor(base::TimeDelta::FromMilliseconds(150)); 146} 147 148 149TEST_F(LocalDomainResolverTest, ResolveDomainAnyBothAvailable) { 150 LocalDomainResolverImpl resolver( 151 "myhello.local", net::ADDRESS_FAMILY_UNSPECIFIED, 152 base::Bind(&LocalDomainResolverTest::AddressCallback, 153 base::Unretained(this)), &mdns_client_); 154 155 EXPECT_CALL(socket_factory_, OnSendTo(_)).Times(4); // Twice per query 156 157 resolver.Start(); 158 159 EXPECT_CALL(*this, AddressCallbackInternal(true, "1.2.3.4", "a::1:2:3:4")); 160 161 socket_factory_.SimulateReceive(kSamplePacketAAAA, sizeof(kSamplePacketAAAA)); 162 163 socket_factory_.SimulateReceive(kSamplePacketA, sizeof(kSamplePacketA)); 164} 165 166TEST_F(LocalDomainResolverTest, ResolveDomainNone) { 167 LocalDomainResolverImpl resolver( 168 "myhello.local", net::ADDRESS_FAMILY_UNSPECIFIED, 169 base::Bind(&LocalDomainResolverTest::AddressCallback, 170 base::Unretained(this)), &mdns_client_); 171 172 EXPECT_CALL(socket_factory_, OnSendTo(_)).Times(4); // Twice per query 173 174 resolver.Start(); 175 176 EXPECT_CALL(*this, AddressCallbackInternal(false, "", "")); 177 178 RunFor(base::TimeDelta::FromSeconds(4)); 179} 180 181} // namespace 182 183} // namespace local_discovery 184