| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/dns/dns_config_service.h" | 5 #include "net/dns/dns_config_service.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/cancelable_callback.h" | 9 #include "base/cancelable_callback.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| 11 #include "base/message_loop.h" | 11 #include "base/message_loop.h" |
| 12 #include "base/test/test_timeouts.h" | 12 #include "base/test/test_timeouts.h" |
| 13 #include "testing/gtest/include/gtest/gtest.h" | 13 #include "testing/gtest/include/gtest/gtest.h" |
| 14 | 14 |
| 15 namespace net { | 15 namespace net { |
| 16 | 16 |
| 17 namespace { | 17 namespace { |
| 18 | 18 |
| 19 class DnsConfigServiceTest : public testing::Test { | 19 class DnsConfigServiceTest : public testing::Test { |
| 20 public: | 20 public: |
| 21 void OnConfigChanged(const DnsConfig& config) { | 21 void OnConfigChanged(const DnsConfig& config) { |
| 22 EXPECT_FALSE(config.Equals(last_config_)) << | |
| 23 "Config must be different from last call."; | |
| 24 last_config_ = config; | 22 last_config_ = config; |
| 25 if (quit_on_config_) | 23 if (quit_on_config_) |
| 26 MessageLoop::current()->Quit(); | 24 MessageLoop::current()->Quit(); |
| 27 } | 25 } |
| 28 | 26 |
| 29 protected: | 27 protected: |
| 30 class TestDnsConfigService : public DnsConfigService { | 28 class TestDnsConfigService : public DnsConfigService { |
| 31 public: | 29 public: |
| 32 virtual void OnDNSChanged(unsigned detail) OVERRIDE {} | 30 virtual void ReadNow() OVERRIDE {} |
| 31 virtual bool StartWatching() OVERRIDE { return true; } |
| 33 | 32 |
| 34 // Expose the protected methods to this test suite. | 33 // Expose the protected methods to this test suite. |
| 35 void InvalidateConfig() { | 34 void InvalidateConfig() { |
| 36 DnsConfigService::InvalidateConfig(); | 35 DnsConfigService::InvalidateConfig(); |
| 37 } | 36 } |
| 38 | 37 |
| 39 void InvalidateHosts() { | 38 void InvalidateHosts() { |
| 40 DnsConfigService::InvalidateHosts(); | 39 DnsConfigService::InvalidateHosts(); |
| 41 } | 40 } |
| 42 | 41 |
| 43 void OnConfigRead(const DnsConfig& config) { | 42 void OnConfigRead(const DnsConfig& config) { |
| 44 DnsConfigService::OnConfigRead(config); | 43 DnsConfigService::OnConfigRead(config); |
| 45 } | 44 } |
| 46 | 45 |
| 47 void OnHostsRead(const DnsHosts& hosts) { | 46 void OnHostsRead(const DnsHosts& hosts) { |
| 48 DnsConfigService::OnHostsRead(hosts); | 47 DnsConfigService::OnHostsRead(hosts); |
| 49 } | 48 } |
| 49 |
| 50 void set_watch_failed(bool value) { |
| 51 DnsConfigService::set_watch_failed(value); |
| 52 } |
| 50 }; | 53 }; |
| 51 | 54 |
| 52 void WaitForConfig(base::TimeDelta timeout) { | 55 void WaitForConfig(base::TimeDelta timeout) { |
| 53 base::CancelableClosure closure(MessageLoop::QuitClosure()); | 56 base::CancelableClosure closure(MessageLoop::QuitClosure()); |
| 54 MessageLoop::current()->PostDelayedTask(FROM_HERE, | 57 MessageLoop::current()->PostDelayedTask(FROM_HERE, |
| 55 closure.callback(), | 58 closure.callback(), |
| 56 timeout); | 59 timeout); |
| 57 quit_on_config_ = true; | 60 quit_on_config_ = true; |
| 58 MessageLoop::current()->Run(); | 61 MessageLoop::current()->Run(); |
| 59 quit_on_config_ = false; | 62 quit_on_config_ = false; |
| 60 closure.Cancel(); | 63 closure.Cancel(); |
| 61 } | 64 } |
| 62 | 65 |
| 63 // Generate a config using the given seed.. | 66 // Generate a config using the given seed.. |
| 64 DnsConfig MakeConfig(unsigned seed) { | 67 DnsConfig MakeConfig(unsigned seed) { |
| 65 DnsConfig config; | 68 DnsConfig config; |
| 66 IPAddressNumber ip; | 69 IPAddressNumber ip; |
| 67 EXPECT_TRUE(ParseIPLiteralToNumber("1.2.3.4", &ip)); | 70 CHECK(ParseIPLiteralToNumber("1.2.3.4", &ip)); |
| 68 config.nameservers.push_back(IPEndPoint(ip, seed & 0xFFFF)); | 71 config.nameservers.push_back(IPEndPoint(ip, seed & 0xFFFF)); |
| 69 EXPECT_TRUE(config.IsValid()); | 72 EXPECT_TRUE(config.IsValid()); |
| 70 return config; | 73 return config; |
| 71 } | 74 } |
| 72 | 75 |
| 73 // Generate hosts using the given seed. | 76 // Generate hosts using the given seed. |
| 74 DnsHosts MakeHosts(unsigned seed) { | 77 DnsHosts MakeHosts(unsigned seed) { |
| 75 DnsHosts hosts; | 78 DnsHosts hosts; |
| 76 std::string hosts_content = "127.0.0.1 localhost"; | 79 std::string hosts_content = "127.0.0.1 localhost"; |
| 77 hosts_content.append(seed, '1'); | 80 hosts_content.append(seed, '1'); |
| 78 ParseHosts(hosts_content, &hosts); | 81 ParseHosts(hosts_content, &hosts); |
| 79 EXPECT_FALSE(hosts.empty()); | 82 EXPECT_FALSE(hosts.empty()); |
| 80 return hosts; | 83 return hosts; |
| 81 } | 84 } |
| 82 | 85 |
| 83 virtual void SetUp() OVERRIDE { | 86 virtual void SetUp() OVERRIDE { |
| 84 quit_on_config_ = false; | 87 quit_on_config_ = false; |
| 85 | 88 |
| 86 service_.reset(new TestDnsConfigService()); | 89 service_.reset(new TestDnsConfigService()); |
| 87 service_->Watch(base::Bind(&DnsConfigServiceTest::OnConfigChanged, | 90 service_->WatchConfig(base::Bind(&DnsConfigServiceTest::OnConfigChanged, |
| 88 base::Unretained(this))); | 91 base::Unretained(this))); |
| 89 EXPECT_FALSE(last_config_.IsValid()); | 92 EXPECT_FALSE(last_config_.IsValid()); |
| 90 } | 93 } |
| 91 | 94 |
| 92 DnsConfig last_config_; | 95 DnsConfig last_config_; |
| 93 bool quit_on_config_; | 96 bool quit_on_config_; |
| 94 | 97 |
| 95 // Service under test. | 98 // Service under test. |
| 96 scoped_ptr<TestDnsConfigService> service_; | 99 scoped_ptr<TestDnsConfigService> service_; |
| 97 }; | 100 }; |
| 98 | 101 |
| 99 } // namespace | 102 } // namespace |
| 100 | 103 |
| 101 TEST_F(DnsConfigServiceTest, FirstConfig) { | 104 TEST_F(DnsConfigServiceTest, FirstConfig) { |
| 102 DnsConfig config = MakeConfig(1); | 105 DnsConfig config = MakeConfig(1); |
| 103 | 106 |
| 104 service_->OnConfigRead(config); | 107 service_->OnConfigRead(config); |
| 105 // No hosts yet, so no config. | 108 // No hosts yet, so no config. |
| 106 EXPECT_FALSE(last_config_.IsValid()); | 109 EXPECT_TRUE(last_config_.Equals(DnsConfig())); |
| 107 | 110 |
| 108 service_->OnHostsRead(config.hosts); | 111 service_->OnHostsRead(config.hosts); |
| 109 // Empty hosts is acceptable. | |
| 110 EXPECT_TRUE(last_config_.IsValid()); | |
| 111 EXPECT_TRUE(last_config_.Equals(config)); | 112 EXPECT_TRUE(last_config_.Equals(config)); |
| 112 } | 113 } |
| 113 | 114 |
| 114 TEST_F(DnsConfigServiceTest, Timeout) { | 115 TEST_F(DnsConfigServiceTest, Timeout) { |
| 115 DnsConfig config = MakeConfig(1); | 116 DnsConfig config = MakeConfig(1); |
| 116 config.hosts = MakeHosts(1); | 117 config.hosts = MakeHosts(1); |
| 117 ASSERT_TRUE(config.IsValid()); | 118 ASSERT_TRUE(config.IsValid()); |
| 118 | 119 |
| 119 service_->OnConfigRead(config); | 120 service_->OnConfigRead(config); |
| 120 service_->OnHostsRead(config.hosts); | 121 service_->OnHostsRead(config.hosts); |
| 121 EXPECT_TRUE(last_config_.IsValid()); | 122 EXPECT_FALSE(last_config_.Equals(DnsConfig())); |
| 122 EXPECT_TRUE(last_config_.Equals(config)); | 123 EXPECT_TRUE(last_config_.Equals(config)); |
| 123 | 124 |
| 124 service_->InvalidateConfig(); | 125 service_->InvalidateConfig(); |
| 125 WaitForConfig(TestTimeouts::action_timeout()); | 126 WaitForConfig(TestTimeouts::action_timeout()); |
| 126 EXPECT_FALSE(last_config_.IsValid()); | 127 EXPECT_FALSE(last_config_.Equals(config)); |
| 128 EXPECT_TRUE(last_config_.Equals(DnsConfig())); |
| 127 | 129 |
| 128 service_->OnConfigRead(config); | 130 service_->OnConfigRead(config); |
| 131 EXPECT_FALSE(last_config_.Equals(DnsConfig())); |
| 129 EXPECT_TRUE(last_config_.Equals(config)); | 132 EXPECT_TRUE(last_config_.Equals(config)); |
| 130 | 133 |
| 131 service_->InvalidateHosts(); | 134 service_->InvalidateHosts(); |
| 132 WaitForConfig(TestTimeouts::action_timeout()); | 135 WaitForConfig(TestTimeouts::action_timeout()); |
| 133 EXPECT_FALSE(last_config_.IsValid()); | 136 EXPECT_FALSE(last_config_.Equals(config)); |
| 137 EXPECT_TRUE(last_config_.Equals(DnsConfig())); |
| 134 | 138 |
| 139 DnsConfig bad_config = last_config_ = MakeConfig(0xBAD); |
| 135 service_->InvalidateConfig(); | 140 service_->InvalidateConfig(); |
| 136 // We don't expect an update. This should time out. If we get an update, | 141 // We don't expect an update. This should time out. |
| 137 // we'll detect unchanged config. | |
| 138 WaitForConfig(base::TimeDelta::FromMilliseconds(100) + | 142 WaitForConfig(base::TimeDelta::FromMilliseconds(100) + |
| 139 TestTimeouts::tiny_timeout()); | 143 TestTimeouts::tiny_timeout()); |
| 140 EXPECT_FALSE(last_config_.IsValid()); | 144 EXPECT_TRUE(last_config_.Equals(bad_config)) << "Unexpected change"; |
| 141 | 145 |
| 146 last_config_ = DnsConfig(); |
| 142 service_->OnConfigRead(config); | 147 service_->OnConfigRead(config); |
| 143 service_->OnHostsRead(config.hosts); | 148 service_->OnHostsRead(config.hosts); |
| 149 EXPECT_FALSE(last_config_.Equals(DnsConfig())); |
| 144 EXPECT_TRUE(last_config_.Equals(config)); | 150 EXPECT_TRUE(last_config_.Equals(config)); |
| 145 } | 151 } |
| 146 | 152 |
| 147 TEST_F(DnsConfigServiceTest, SameConfig) { | 153 TEST_F(DnsConfigServiceTest, SameConfig) { |
| 148 DnsConfig config = MakeConfig(1); | 154 DnsConfig config = MakeConfig(1); |
| 149 config.hosts = MakeHosts(1); | 155 config.hosts = MakeHosts(1); |
| 150 | 156 |
| 151 service_->OnConfigRead(config); | 157 service_->OnConfigRead(config); |
| 152 service_->OnHostsRead(config.hosts); | 158 service_->OnHostsRead(config.hosts); |
| 159 EXPECT_FALSE(last_config_.Equals(DnsConfig())); |
| 153 EXPECT_TRUE(last_config_.Equals(config)); | 160 EXPECT_TRUE(last_config_.Equals(config)); |
| 154 | 161 |
| 155 // OnConfigChanged will catch if there was no change. | 162 last_config_ = DnsConfig(); |
| 156 service_->OnConfigRead(config); | 163 service_->OnConfigRead(config); |
| 157 EXPECT_TRUE(last_config_.Equals(config)); | 164 EXPECT_TRUE(last_config_.Equals(DnsConfig())) << "Unexpected change"; |
| 158 | 165 |
| 159 service_->OnHostsRead(config.hosts); | 166 service_->OnHostsRead(config.hosts); |
| 160 EXPECT_TRUE(last_config_.Equals(config)); | 167 EXPECT_TRUE(last_config_.Equals(DnsConfig())) << "Unexpected change"; |
| 161 } | 168 } |
| 162 | 169 |
| 163 TEST_F(DnsConfigServiceTest, DifferentConfig) { | 170 TEST_F(DnsConfigServiceTest, DifferentConfig) { |
| 164 DnsConfig config1 = MakeConfig(1); | 171 DnsConfig config1 = MakeConfig(1); |
| 165 DnsConfig config2 = MakeConfig(2); | 172 DnsConfig config2 = MakeConfig(2); |
| 166 DnsConfig config3 = MakeConfig(1); | 173 DnsConfig config3 = MakeConfig(1); |
| 167 config1.hosts = MakeHosts(1); | 174 config1.hosts = MakeHosts(1); |
| 168 config2.hosts = MakeHosts(1); | 175 config2.hosts = MakeHosts(1); |
| 169 config3.hosts = MakeHosts(2); | 176 config3.hosts = MakeHosts(2); |
| 170 ASSERT_TRUE(config1.EqualsIgnoreHosts(config3)); | 177 ASSERT_TRUE(config1.EqualsIgnoreHosts(config3)); |
| 171 ASSERT_FALSE(config1.Equals(config2)); | 178 ASSERT_FALSE(config1.Equals(config2)); |
| 172 ASSERT_FALSE(config1.Equals(config3)); | 179 ASSERT_FALSE(config1.Equals(config3)); |
| 173 ASSERT_FALSE(config2.Equals(config3)); | 180 ASSERT_FALSE(config2.Equals(config3)); |
| 174 | 181 |
| 175 service_->OnConfigRead(config1); | 182 service_->OnConfigRead(config1); |
| 176 service_->OnHostsRead(config1.hosts); | 183 service_->OnHostsRead(config1.hosts); |
| 184 EXPECT_FALSE(last_config_.Equals(DnsConfig())); |
| 177 EXPECT_TRUE(last_config_.Equals(config1)); | 185 EXPECT_TRUE(last_config_.Equals(config1)); |
| 178 | 186 |
| 179 // It doesn't matter for this tests, but increases coverage. | 187 // It doesn't matter for this tests, but increases coverage. |
| 180 service_->InvalidateConfig(); | 188 service_->InvalidateConfig(); |
| 181 service_->InvalidateHosts(); | 189 service_->InvalidateHosts(); |
| 182 | 190 |
| 183 service_->OnConfigRead(config2); | 191 service_->OnConfigRead(config2); |
| 184 service_->OnHostsRead(config2.hosts); | 192 EXPECT_TRUE(last_config_.Equals(config1)) << "Unexpected change"; |
| 193 service_->OnHostsRead(config2.hosts); // Not an actual change. |
| 194 EXPECT_FALSE(last_config_.Equals(config1)); |
| 185 EXPECT_TRUE(last_config_.Equals(config2)); | 195 EXPECT_TRUE(last_config_.Equals(config2)); |
| 186 | 196 |
| 187 service_->OnConfigRead(config3); | 197 service_->OnConfigRead(config3); |
| 198 EXPECT_TRUE(last_config_.EqualsIgnoreHosts(config3)); |
| 188 service_->OnHostsRead(config3.hosts); | 199 service_->OnHostsRead(config3.hosts); |
| 200 EXPECT_FALSE(last_config_.Equals(config2)); |
| 189 EXPECT_TRUE(last_config_.Equals(config3)); | 201 EXPECT_TRUE(last_config_.Equals(config3)); |
| 190 } | 202 } |
| 191 | 203 |
| 204 TEST_F(DnsConfigServiceTest, WatchFailure) { |
| 205 DnsConfig config1 = MakeConfig(1); |
| 206 DnsConfig config2 = MakeConfig(2); |
| 207 config1.hosts = MakeHosts(1); |
| 208 config2.hosts = MakeHosts(2); |
| 209 |
| 210 service_->OnConfigRead(config1); |
| 211 service_->OnHostsRead(config1.hosts); |
| 212 EXPECT_FALSE(last_config_.Equals(DnsConfig())); |
| 213 EXPECT_TRUE(last_config_.Equals(config1)); |
| 214 |
| 215 // Simulate watch failure. |
| 216 service_->set_watch_failed(true); |
| 217 service_->InvalidateConfig(); |
| 218 WaitForConfig(TestTimeouts::action_timeout()); |
| 219 EXPECT_FALSE(last_config_.Equals(config1)); |
| 220 EXPECT_TRUE(last_config_.Equals(DnsConfig())); |
| 221 |
| 222 DnsConfig bad_config = last_config_ = MakeConfig(0xBAD); |
| 223 // Actual change in config, so expect an update, but it should be empty. |
| 224 service_->OnConfigRead(config1); |
| 225 EXPECT_FALSE(last_config_.Equals(bad_config)); |
| 226 EXPECT_TRUE(last_config_.Equals(DnsConfig())); |
| 227 |
| 228 last_config_ = bad_config; |
| 229 // Actual change in config, so expect an update, but it should be empty. |
| 230 service_->InvalidateConfig(); |
| 231 service_->OnConfigRead(config2); |
| 232 EXPECT_FALSE(last_config_.Equals(bad_config)); |
| 233 EXPECT_TRUE(last_config_.Equals(DnsConfig())); |
| 234 |
| 235 last_config_ = bad_config; |
| 236 // No change, so no update. |
| 237 service_->InvalidateConfig(); |
| 238 service_->OnConfigRead(config2); |
| 239 EXPECT_TRUE(last_config_.Equals(bad_config)); |
| 240 } |
| 241 |
| 192 #if (defined(OS_POSIX) && !defined(OS_ANDROID)) || defined(OS_WIN) | 242 #if (defined(OS_POSIX) && !defined(OS_ANDROID)) || defined(OS_WIN) |
| 193 // TODO(szym): This is really an integration test and can time out if HOSTS is | 243 // TODO(szym): This is really an integration test and can time out if HOSTS is |
| 194 // huge. http://crbug.com/107810 | 244 // huge. http://crbug.com/107810 |
| 195 TEST_F(DnsConfigServiceTest, FLAKY_GetSystemConfig) { | 245 TEST_F(DnsConfigServiceTest, FLAKY_GetSystemConfig) { |
| 196 service_.reset(); | 246 service_.reset(); |
| 197 scoped_ptr<DnsConfigService> service(DnsConfigService::CreateSystemService()); | 247 scoped_ptr<DnsConfigService> service(DnsConfigService::CreateSystemService()); |
| 198 | 248 |
| 199 service->Read(base::Bind(&DnsConfigServiceTest::OnConfigChanged, | 249 service->ReadConfig(base::Bind(&DnsConfigServiceTest::OnConfigChanged, |
| 200 base::Unretained(this))); | 250 base::Unretained(this))); |
| 201 base::TimeDelta kTimeout = TestTimeouts::action_max_timeout(); | 251 base::TimeDelta kTimeout = TestTimeouts::action_max_timeout(); |
| 202 WaitForConfig(kTimeout); | 252 WaitForConfig(kTimeout); |
| 203 ASSERT_TRUE(last_config_.IsValid()) << "Did not receive DnsConfig in " << | 253 ASSERT_TRUE(last_config_.IsValid()) << "Did not receive DnsConfig in " << |
| 204 kTimeout.InSecondsF() << "s"; | 254 kTimeout.InSecondsF() << "s"; |
| 205 } | 255 } |
| 206 #endif // OS_POSIX || OS_WIN | 256 #endif // OS_POSIX || OS_WIN |
| 207 | 257 |
| 208 } // namespace net | 258 } // namespace net |
| 209 | 259 |
| OLD | NEW |