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 11 using ::testing::_; 12 13 namespace local_discovery { 14 15 namespace { 16 17 const 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 38 const 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 61 class LocalDomainResolverTest : public testing::Test { 62 public: 63 LocalDomainResolverTest() : socket_factory_(new net::MockMDnsSocketFactory), 64 mdns_client_( 65 scoped_ptr<net::MDnsConnection::SocketFactory>( 66 socket_factory_)) { 67 } 68 69 ~LocalDomainResolverTest() { 70 } 71 72 virtual void SetUp() OVERRIDE { 73 mdns_client_.StartListening(); 74 } 75 76 void AddressCallback(bool resolved, const net::IPAddressNumber& address) { 77 if (address == net::IPAddressNumber()) { 78 AddressCallbackInternal(resolved, ""); 79 } else { 80 AddressCallbackInternal(resolved, net::IPAddressToString(address)); 81 } 82 } 83 84 void RunFor(base::TimeDelta time_period) { 85 base::CancelableCallback<void()> callback(base::Bind( 86 &base::MessageLoop::Quit, 87 base::Unretained(base::MessageLoop::current()))); 88 base::MessageLoop::current()->PostDelayedTask( 89 FROM_HERE, callback.callback(), time_period); 90 91 base::MessageLoop::current()->Run(); 92 callback.Cancel(); 93 } 94 95 MOCK_METHOD2(AddressCallbackInternal, 96 void(bool resolved, std::string address)); 97 98 net::MockMDnsSocketFactory* socket_factory_; 99 net::MDnsClientImpl mdns_client_; 100 base::MessageLoop message_loop_; 101 }; 102 103 TEST_F(LocalDomainResolverTest, ResolveDomainA) { 104 LocalDomainResolverImpl resolver( 105 "myhello.local", net::ADDRESS_FAMILY_IPV4, 106 base::Bind(&LocalDomainResolverTest::AddressCallback, 107 base::Unretained(this)), &mdns_client_); 108 109 EXPECT_CALL(*socket_factory_, OnSendTo(_)) 110 .Times(2); // Twice per query 111 112 resolver.Start(); 113 114 EXPECT_CALL(*this, AddressCallbackInternal(true, "1.2.3.4")); 115 116 socket_factory_->SimulateReceive( 117 kSamplePacketA, sizeof(kSamplePacketA)); 118 } 119 120 TEST_F(LocalDomainResolverTest, ResolveDomainAAAA) { 121 LocalDomainResolverImpl resolver( 122 "myhello.local", net::ADDRESS_FAMILY_IPV6, 123 base::Bind(&LocalDomainResolverTest::AddressCallback, 124 base::Unretained(this)), &mdns_client_); 125 126 EXPECT_CALL(*socket_factory_, OnSendTo(_)) 127 .Times(2); // Twice per query 128 129 resolver.Start(); 130 131 EXPECT_CALL(*this, AddressCallbackInternal(true, "a::1:2:3:4")); 132 133 socket_factory_->SimulateReceive( 134 kSamplePacketAAAA, sizeof(kSamplePacketAAAA)); 135 } 136 137 TEST_F(LocalDomainResolverTest, ResolveDomainAny) { 138 LocalDomainResolverImpl resolver( 139 "myhello.local", net::ADDRESS_FAMILY_UNSPECIFIED, 140 base::Bind(&LocalDomainResolverTest::AddressCallback, 141 base::Unretained(this)), &mdns_client_); 142 143 EXPECT_CALL(*socket_factory_, OnSendTo(_)) 144 .Times(4); // Twice per query 145 146 resolver.Start(); 147 148 EXPECT_CALL(*this, AddressCallbackInternal(true, "a::1:2:3:4")); 149 150 socket_factory_->SimulateReceive( 151 kSamplePacketAAAA, sizeof(kSamplePacketAAAA)); 152 } 153 154 TEST_F(LocalDomainResolverTest, ResolveDomainNone) { 155 LocalDomainResolverImpl resolver( 156 "myhello.local", net::ADDRESS_FAMILY_UNSPECIFIED, 157 base::Bind(&LocalDomainResolverTest::AddressCallback, 158 base::Unretained(this)), &mdns_client_); 159 160 EXPECT_CALL(*socket_factory_, OnSendTo(_)) 161 .Times(4); // Twice per query 162 163 resolver.Start(); 164 165 EXPECT_CALL(*this, AddressCallbackInternal(false, "")); 166 167 RunFor(base::TimeDelta::FromSeconds(4)); 168 } 169 170 } // namespace 171 172 } // namespace local_discovery 173