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 |