| OLD | NEW |
| (Empty) |
| 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->empty()) | |
| 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 void ReadNow() override {} | |
| 125 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 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 | |
| OLD | NEW |