1 // Copyright (c) 2012 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 "net/dns/dns_config_service.h" 6 7 #include "base/basictypes.h" 8 #include "base/bind.h" 9 #include "base/cancelable_callback.h" 10 #include "base/memory/scoped_ptr.h" 11 #include "base/message_loop/message_loop.h" 12 #include "base/strings/string_split.h" 13 #include "base/test/test_timeouts.h" 14 #include "net/base/net_util.h" 15 #include "net/dns/dns_protocol.h" 16 #include "testing/gtest/include/gtest/gtest.h" 17 18 namespace net { 19 20 namespace { 21 22 const NameServerClassifier::NameServersType kNone = 23 NameServerClassifier::NAME_SERVERS_TYPE_NONE; 24 const NameServerClassifier::NameServersType kGoogle = 25 NameServerClassifier::NAME_SERVERS_TYPE_GOOGLE_PUBLIC_DNS; 26 const NameServerClassifier::NameServersType kPrivate = 27 NameServerClassifier::NAME_SERVERS_TYPE_PRIVATE; 28 const NameServerClassifier::NameServersType kPublic = 29 NameServerClassifier::NAME_SERVERS_TYPE_PUBLIC; 30 const NameServerClassifier::NameServersType kMixed = 31 NameServerClassifier::NAME_SERVERS_TYPE_MIXED; 32 33 class NameServerClassifierTest : public testing::Test { 34 protected: 35 NameServerClassifier::NameServersType Classify( 36 const std::string& servers_string) { 37 std::vector<std::string> server_strings; 38 base::SplitString(servers_string, ' ', &server_strings); 39 40 std::vector<IPEndPoint> servers; 41 for (std::vector<std::string>::const_iterator it = server_strings.begin(); 42 it != server_strings.end(); 43 ++it) { 44 if (*it == "") 45 continue; 46 47 IPAddressNumber address; 48 bool parsed = ParseIPLiteralToNumber(*it, &address); 49 EXPECT_TRUE(parsed); 50 servers.push_back(IPEndPoint(address, dns_protocol::kDefaultPort)); 51 } 52 53 return classifier_.GetNameServersType(servers); 54 } 55 56 private: 57 NameServerClassifier classifier_; 58 }; 59 60 TEST_F(NameServerClassifierTest, None) { 61 EXPECT_EQ(kNone, Classify("")); 62 } 63 64 TEST_F(NameServerClassifierTest, Google) { 65 EXPECT_EQ(kGoogle, Classify("8.8.8.8")); 66 EXPECT_EQ(kGoogle, Classify("8.8.8.8 8.8.4.4")); 67 EXPECT_EQ(kGoogle, Classify("2001:4860:4860::8888")); 68 EXPECT_EQ(kGoogle, Classify("2001:4860:4860::8888 2001:4860:4860::8844")); 69 EXPECT_EQ(kGoogle, Classify("2001:4860:4860::8888 8.8.8.8")); 70 71 // Make sure nobody took any shortcuts on the IP matching: 72 EXPECT_EQ(kPublic, Classify("8.8.8.4")); 73 EXPECT_EQ(kPublic, Classify("8.8.4.8")); 74 EXPECT_EQ(kPublic, Classify("2001:4860:4860::8884")); 75 EXPECT_EQ(kPublic, Classify("2001:4860:4860::8848")); 76 EXPECT_EQ(kPublic, Classify("2001:4860:4860::1:8888")); 77 EXPECT_EQ(kPublic, Classify("2001:4860:4860:1::8888")); 78 } 79 80 TEST_F(NameServerClassifierTest, PrivateLocalhost) { 81 EXPECT_EQ(kPrivate, Classify("127.0.0.1")); 82 EXPECT_EQ(kPrivate, Classify("::1")); 83 } 84 85 TEST_F(NameServerClassifierTest, PrivateRfc1918) { 86 EXPECT_EQ(kPrivate, Classify("10.0.0.0 10.255.255.255")); 87 EXPECT_EQ(kPrivate, Classify("172.16.0.0 172.31.255.255")); 88 EXPECT_EQ(kPrivate, Classify("192.168.0.0 192.168.255.255")); 89 EXPECT_EQ(kPrivate, Classify("10.1.1.1 172.16.1.1 192.168.1.1")); 90 } 91 92 TEST_F(NameServerClassifierTest, PrivateIPv4LinkLocal) { 93 EXPECT_EQ(kPrivate, Classify("169.254.0.0 169.254.255.255")); 94 } 95 96 TEST_F(NameServerClassifierTest, PrivateIPv6LinkLocal) { 97 EXPECT_EQ(kPrivate, 98 Classify("fe80:: fe80:ffff:ffff:ffff:ffff:ffff:ffff:ffff")); 99 } 100 101 TEST_F(NameServerClassifierTest, Public) { 102 EXPECT_EQ(kPublic, Classify("4.2.2.1")); 103 EXPECT_EQ(kPublic, Classify("4.2.2.1 4.2.2.2")); 104 } 105 106 TEST_F(NameServerClassifierTest, Mixed) { 107 EXPECT_EQ(kMixed, Classify("8.8.8.8 192.168.1.1")); 108 EXPECT_EQ(kMixed, Classify("8.8.8.8 4.2.2.1")); 109 EXPECT_EQ(kMixed, Classify("192.168.1.1 4.2.2.1")); 110 EXPECT_EQ(kMixed, Classify("8.8.8.8 192.168.1.1 4.2.2.1")); 111 } 112 113 class DnsConfigServiceTest : public testing::Test { 114 public: 115 void OnConfigChanged(const DnsConfig& config) { 116 last_config_ = config; 117 if (quit_on_config_) 118 base::MessageLoop::current()->Quit(); 119 } 120 121 protected: 122 class TestDnsConfigService : public DnsConfigService { 123 public: 124 virtual void ReadNow() OVERRIDE {} 125 virtual bool StartWatching() OVERRIDE { return true; } 126 127 // Expose the protected methods to this test suite. 128 void InvalidateConfig() { 129 DnsConfigService::InvalidateConfig(); 130 } 131 132 void InvalidateHosts() { 133 DnsConfigService::InvalidateHosts(); 134 } 135 136 void OnConfigRead(const DnsConfig& config) { 137 DnsConfigService::OnConfigRead(config); 138 } 139 140 void OnHostsRead(const DnsHosts& hosts) { 141 DnsConfigService::OnHostsRead(hosts); 142 } 143 144 void set_watch_failed(bool value) { 145 DnsConfigService::set_watch_failed(value); 146 } 147 }; 148 149 void WaitForConfig(base::TimeDelta timeout) { 150 base::CancelableClosure closure(base::MessageLoop::QuitClosure()); 151 base::MessageLoop::current()->PostDelayedTask( 152 FROM_HERE, closure.callback(), timeout); 153 quit_on_config_ = true; 154 base::MessageLoop::current()->Run(); 155 quit_on_config_ = false; 156 closure.Cancel(); 157 } 158 159 // Generate a config using the given seed.. 160 DnsConfig MakeConfig(unsigned seed) { 161 DnsConfig config; 162 IPAddressNumber ip; 163 CHECK(ParseIPLiteralToNumber("1.2.3.4", &ip)); 164 config.nameservers.push_back(IPEndPoint(ip, seed & 0xFFFF)); 165 EXPECT_TRUE(config.IsValid()); 166 return config; 167 } 168 169 // Generate hosts using the given seed. 170 DnsHosts MakeHosts(unsigned seed) { 171 DnsHosts hosts; 172 std::string hosts_content = "127.0.0.1 localhost"; 173 hosts_content.append(seed, '1'); 174 ParseHosts(hosts_content, &hosts); 175 EXPECT_FALSE(hosts.empty()); 176 return hosts; 177 } 178 179 virtual void SetUp() OVERRIDE { 180 quit_on_config_ = false; 181 182 service_.reset(new TestDnsConfigService()); 183 service_->WatchConfig(base::Bind(&DnsConfigServiceTest::OnConfigChanged, 184 base::Unretained(this))); 185 EXPECT_FALSE(last_config_.IsValid()); 186 } 187 188 DnsConfig last_config_; 189 bool quit_on_config_; 190 191 // Service under test. 192 scoped_ptr<TestDnsConfigService> service_; 193 }; 194 195 } // namespace 196 197 TEST_F(DnsConfigServiceTest, FirstConfig) { 198 DnsConfig config = MakeConfig(1); 199 200 service_->OnConfigRead(config); 201 // No hosts yet, so no config. 202 EXPECT_TRUE(last_config_.Equals(DnsConfig())); 203 204 service_->OnHostsRead(config.hosts); 205 EXPECT_TRUE(last_config_.Equals(config)); 206 } 207 208 TEST_F(DnsConfigServiceTest, Timeout) { 209 DnsConfig config = MakeConfig(1); 210 config.hosts = MakeHosts(1); 211 ASSERT_TRUE(config.IsValid()); 212 213 service_->OnConfigRead(config); 214 service_->OnHostsRead(config.hosts); 215 EXPECT_FALSE(last_config_.Equals(DnsConfig())); 216 EXPECT_TRUE(last_config_.Equals(config)); 217 218 service_->InvalidateConfig(); 219 WaitForConfig(TestTimeouts::action_timeout()); 220 EXPECT_FALSE(last_config_.Equals(config)); 221 EXPECT_TRUE(last_config_.Equals(DnsConfig())); 222 223 service_->OnConfigRead(config); 224 EXPECT_FALSE(last_config_.Equals(DnsConfig())); 225 EXPECT_TRUE(last_config_.Equals(config)); 226 227 service_->InvalidateHosts(); 228 WaitForConfig(TestTimeouts::action_timeout()); 229 EXPECT_FALSE(last_config_.Equals(config)); 230 EXPECT_TRUE(last_config_.Equals(DnsConfig())); 231 232 DnsConfig bad_config = last_config_ = MakeConfig(0xBAD); 233 service_->InvalidateConfig(); 234 // We don't expect an update. This should time out. 235 WaitForConfig(base::TimeDelta::FromMilliseconds(100) + 236 TestTimeouts::tiny_timeout()); 237 EXPECT_TRUE(last_config_.Equals(bad_config)) << "Unexpected change"; 238 239 last_config_ = DnsConfig(); 240 service_->OnConfigRead(config); 241 service_->OnHostsRead(config.hosts); 242 EXPECT_FALSE(last_config_.Equals(DnsConfig())); 243 EXPECT_TRUE(last_config_.Equals(config)); 244 } 245 246 TEST_F(DnsConfigServiceTest, SameConfig) { 247 DnsConfig config = MakeConfig(1); 248 config.hosts = MakeHosts(1); 249 250 service_->OnConfigRead(config); 251 service_->OnHostsRead(config.hosts); 252 EXPECT_FALSE(last_config_.Equals(DnsConfig())); 253 EXPECT_TRUE(last_config_.Equals(config)); 254 255 last_config_ = DnsConfig(); 256 service_->OnConfigRead(config); 257 EXPECT_TRUE(last_config_.Equals(DnsConfig())) << "Unexpected change"; 258 259 service_->OnHostsRead(config.hosts); 260 EXPECT_TRUE(last_config_.Equals(DnsConfig())) << "Unexpected change"; 261 } 262 263 TEST_F(DnsConfigServiceTest, DifferentConfig) { 264 DnsConfig config1 = MakeConfig(1); 265 DnsConfig config2 = MakeConfig(2); 266 DnsConfig config3 = MakeConfig(1); 267 config1.hosts = MakeHosts(1); 268 config2.hosts = MakeHosts(1); 269 config3.hosts = MakeHosts(2); 270 ASSERT_TRUE(config1.EqualsIgnoreHosts(config3)); 271 ASSERT_FALSE(config1.Equals(config2)); 272 ASSERT_FALSE(config1.Equals(config3)); 273 ASSERT_FALSE(config2.Equals(config3)); 274 275 service_->OnConfigRead(config1); 276 service_->OnHostsRead(config1.hosts); 277 EXPECT_FALSE(last_config_.Equals(DnsConfig())); 278 EXPECT_TRUE(last_config_.Equals(config1)); 279 280 // It doesn't matter for this tests, but increases coverage. 281 service_->InvalidateConfig(); 282 service_->InvalidateHosts(); 283 284 service_->OnConfigRead(config2); 285 EXPECT_TRUE(last_config_.Equals(config1)) << "Unexpected change"; 286 service_->OnHostsRead(config2.hosts); // Not an actual change. 287 EXPECT_FALSE(last_config_.Equals(config1)); 288 EXPECT_TRUE(last_config_.Equals(config2)); 289 290 service_->OnConfigRead(config3); 291 EXPECT_TRUE(last_config_.EqualsIgnoreHosts(config3)); 292 service_->OnHostsRead(config3.hosts); 293 EXPECT_FALSE(last_config_.Equals(config2)); 294 EXPECT_TRUE(last_config_.Equals(config3)); 295 } 296 297 TEST_F(DnsConfigServiceTest, WatchFailure) { 298 DnsConfig config1 = MakeConfig(1); 299 DnsConfig config2 = MakeConfig(2); 300 config1.hosts = MakeHosts(1); 301 config2.hosts = MakeHosts(2); 302 303 service_->OnConfigRead(config1); 304 service_->OnHostsRead(config1.hosts); 305 EXPECT_FALSE(last_config_.Equals(DnsConfig())); 306 EXPECT_TRUE(last_config_.Equals(config1)); 307 308 // Simulate watch failure. 309 service_->set_watch_failed(true); 310 service_->InvalidateConfig(); 311 WaitForConfig(TestTimeouts::action_timeout()); 312 EXPECT_FALSE(last_config_.Equals(config1)); 313 EXPECT_TRUE(last_config_.Equals(DnsConfig())); 314 315 DnsConfig bad_config = last_config_ = MakeConfig(0xBAD); 316 // Actual change in config, so expect an update, but it should be empty. 317 service_->OnConfigRead(config1); 318 EXPECT_FALSE(last_config_.Equals(bad_config)); 319 EXPECT_TRUE(last_config_.Equals(DnsConfig())); 320 321 last_config_ = bad_config; 322 // Actual change in config, so expect an update, but it should be empty. 323 service_->InvalidateConfig(); 324 service_->OnConfigRead(config2); 325 EXPECT_FALSE(last_config_.Equals(bad_config)); 326 EXPECT_TRUE(last_config_.Equals(DnsConfig())); 327 328 last_config_ = bad_config; 329 // No change, so no update. 330 service_->InvalidateConfig(); 331 service_->OnConfigRead(config2); 332 EXPECT_TRUE(last_config_.Equals(bad_config)); 333 } 334 335 #if (defined(OS_POSIX) && !defined(OS_ANDROID)) || defined(OS_WIN) 336 // TODO(szym): This is really an integration test and can time out if HOSTS is 337 // huge. http://crbug.com/107810 338 TEST_F(DnsConfigServiceTest, DISABLED_GetSystemConfig) { 339 service_.reset(); 340 scoped_ptr<DnsConfigService> service(DnsConfigService::CreateSystemService()); 341 342 service->ReadConfig(base::Bind(&DnsConfigServiceTest::OnConfigChanged, 343 base::Unretained(this))); 344 base::TimeDelta kTimeout = TestTimeouts::action_max_timeout(); 345 WaitForConfig(kTimeout); 346 ASSERT_TRUE(last_config_.IsValid()) << "Did not receive DnsConfig in " << 347 kTimeout.InSecondsF() << "s"; 348 } 349 #endif // OS_POSIX || OS_WIN 350 351 } // namespace net 352 353