• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9 
10 #include "net/dns/dns_hosts.h"
11 
12 #include "base/test/metrics/histogram_tester.h"
13 #include "base/trace_event/memory_usage_estimator.h"
14 #include "build/build_config.h"
15 #include "net/base/cronet_buildflags.h"
16 #include "net/base/ip_address.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 
19 namespace net {
20 
21 namespace {
22 
23 struct ExpectedHostsEntry {
24   const char* host;
25   AddressFamily family;
26   const char* ip;
27 };
28 
PopulateExpectedHosts(const ExpectedHostsEntry * entries,size_t num_entries,DnsHosts * expected_hosts_out)29 void PopulateExpectedHosts(const ExpectedHostsEntry* entries,
30                            size_t num_entries,
31                            DnsHosts* expected_hosts_out) {
32   for (size_t i = 0; i < num_entries; ++i) {
33     DnsHostsKey key(entries[i].host, entries[i].family);
34     IPAddress& ip_ref = (*expected_hosts_out)[key];
35     ASSERT_TRUE(ip_ref.empty());
36     ASSERT_TRUE(ip_ref.AssignFromIPLiteral(entries[i].ip));
37     ASSERT_EQ(ip_ref.size(),
38         (entries[i].family == ADDRESS_FAMILY_IPV4) ? 4u : 16u);
39   }
40 }
41 
TEST(DnsHostsTest,ParseHosts)42 TEST(DnsHostsTest, ParseHosts) {
43   const std::string kContents =
44       "127.0.0.1       localhost # standard\n"
45       "\n"
46       "1.0.0.1 localhost # ignored, first hit above\n"
47       "fe00::x example company # ignored, malformed IPv6\n"
48       "1.0.0.300 company # ignored, malformed IPv4\n"
49       "1.0.0.1 # ignored, missing hostname\n"
50       "1.0.0.1\t CoMpANy # normalized to 'company' \n"
51       "::1\tlocalhost ip6-localhost ip6-loopback # comment # within a comment\n"
52       "\t fe00::0 ip6-localnet\r\n"
53       "2048::2 example\n"
54       "2048::1 company example # ignored for 'example' \n"
55       "127.0.0.1 cache1\n"
56       "127.0.0.1 cache2 # should reuse parsed IP\n"
57       "256.0.0.0 cache3 # bogus IP should not clear parsed IP cache\n"
58       "127.0.0.1 cache4 # should still be reused\n"
59       "127.0.0.2 cache5\n"
60       "127.0.0.3 .foo # entries with leading dot are ignored\n"
61       "127.0.0.3 . # just a dot is ignored\n"
62       "127.0.0.4 bar. # trailing dot is allowed, for now\n"
63       "gibberish\n"
64       "127.0.0.5 fóó.test # canonicalizes to 'xn--f-vgaa.test' due to RFC3490\n"
65       "127.0.0.6 127.0.0.1 # ignore IP host\n"
66       "2048::3 [::1] # ignore IP host";
67 
68   const ExpectedHostsEntry kEntries[] = {
69       {"localhost", ADDRESS_FAMILY_IPV4, "127.0.0.1"},
70       {"company", ADDRESS_FAMILY_IPV4, "1.0.0.1"},
71       {"localhost", ADDRESS_FAMILY_IPV6, "::1"},
72       {"ip6-localhost", ADDRESS_FAMILY_IPV6, "::1"},
73       {"ip6-loopback", ADDRESS_FAMILY_IPV6, "::1"},
74       {"ip6-localnet", ADDRESS_FAMILY_IPV6, "fe00::0"},
75       {"company", ADDRESS_FAMILY_IPV6, "2048::1"},
76       {"example", ADDRESS_FAMILY_IPV6, "2048::2"},
77       {"cache1", ADDRESS_FAMILY_IPV4, "127.0.0.1"},
78       {"cache2", ADDRESS_FAMILY_IPV4, "127.0.0.1"},
79       {"cache4", ADDRESS_FAMILY_IPV4, "127.0.0.1"},
80       {"cache5", ADDRESS_FAMILY_IPV4, "127.0.0.2"},
81       {"bar.", ADDRESS_FAMILY_IPV4, "127.0.0.4"},
82       {"xn--f-vgaa.test", ADDRESS_FAMILY_IPV4, "127.0.0.5"},
83   };
84 
85   DnsHosts expected_hosts, actual_hosts;
86   PopulateExpectedHosts(kEntries, std::size(kEntries), &expected_hosts);
87 
88   base::HistogramTester histograms;
89   ParseHosts(kContents, &actual_hosts);
90   ASSERT_EQ(expected_hosts, actual_hosts);
91   histograms.ExpectUniqueSample("Net.DNS.DnsHosts.Count", std::size(kEntries),
92                                 1);
93 #if !BUILDFLAG(CRONET_BUILD)
94   histograms.ExpectUniqueSample(
95       "Net.DNS.DnsHosts.EstimateMemoryUsage",
96       base::trace_event::EstimateMemoryUsage(actual_hosts), 1);
97 #endif
98 }
99 
TEST(DnsHostsTest,ParseHosts_CommaIsToken)100 TEST(DnsHostsTest, ParseHosts_CommaIsToken) {
101   const std::string kContents = "127.0.0.1 comma1,comma2";
102 
103   const ExpectedHostsEntry kEntries[] = {
104     { "comma1,comma2", ADDRESS_FAMILY_IPV4, "127.0.0.1" },
105   };
106 
107   DnsHosts expected_hosts, actual_hosts;
108   PopulateExpectedHosts(kEntries, std::size(kEntries), &expected_hosts);
109   ParseHostsWithCommaModeForTesting(
110       kContents, &actual_hosts, PARSE_HOSTS_COMMA_IS_TOKEN);
111   ASSERT_EQ(0UL, actual_hosts.size());
112 }
113 
TEST(DnsHostsTest,ParseHosts_CommaIsWhitespace)114 TEST(DnsHostsTest, ParseHosts_CommaIsWhitespace) {
115   std::string kContents = "127.0.0.1 comma1,comma2";
116 
117   const ExpectedHostsEntry kEntries[] = {
118     { "comma1", ADDRESS_FAMILY_IPV4, "127.0.0.1" },
119     { "comma2", ADDRESS_FAMILY_IPV4, "127.0.0.1" },
120   };
121 
122   DnsHosts expected_hosts, actual_hosts;
123   PopulateExpectedHosts(kEntries, std::size(kEntries), &expected_hosts);
124   ParseHostsWithCommaModeForTesting(
125       kContents, &actual_hosts, PARSE_HOSTS_COMMA_IS_WHITESPACE);
126   ASSERT_EQ(expected_hosts, actual_hosts);
127 }
128 
129 // Test that the right comma mode is used on each platform.
TEST(DnsHostsTest,ParseHosts_CommaModeByPlatform)130 TEST(DnsHostsTest, ParseHosts_CommaModeByPlatform) {
131   std::string kContents = "127.0.0.1 comma1,comma2";
132   DnsHosts actual_hosts;
133   ParseHosts(kContents, &actual_hosts);
134 
135 #if BUILDFLAG(IS_APPLE)
136   const ExpectedHostsEntry kEntries[] = {
137     { "comma1", ADDRESS_FAMILY_IPV4, "127.0.0.1" },
138     { "comma2", ADDRESS_FAMILY_IPV4, "127.0.0.1" },
139   };
140   DnsHosts expected_hosts;
141   PopulateExpectedHosts(kEntries, std::size(kEntries), &expected_hosts);
142   ASSERT_EQ(expected_hosts, actual_hosts);
143 #else
144   ASSERT_EQ(0UL, actual_hosts.size());
145 #endif
146 }
147 
TEST(DnsHostsTest,HostsParser_Empty)148 TEST(DnsHostsTest, HostsParser_Empty) {
149   DnsHosts hosts;
150   ParseHosts("", &hosts);
151   EXPECT_EQ(0u, hosts.size());
152 }
153 
TEST(DnsHostsTest,HostsParser_OnlyWhitespace)154 TEST(DnsHostsTest, HostsParser_OnlyWhitespace) {
155   DnsHosts hosts;
156   ParseHosts(" ", &hosts);
157   EXPECT_EQ(0u, hosts.size());
158 }
159 
TEST(DnsHostsTest,HostsParser_EndsWithNothing)160 TEST(DnsHostsTest, HostsParser_EndsWithNothing) {
161   DnsHosts hosts;
162   ParseHosts("127.0.0.1 localhost", &hosts);
163   EXPECT_EQ(1u, hosts.size());
164 }
165 
TEST(DnsHostsTest,HostsParser_EndsWithWhitespace)166 TEST(DnsHostsTest, HostsParser_EndsWithWhitespace) {
167   DnsHosts hosts;
168   ParseHosts("127.0.0.1 localhost ", &hosts);
169   EXPECT_EQ(1u, hosts.size());
170 }
171 
TEST(DnsHostsTest,HostsParser_EndsWithComment)172 TEST(DnsHostsTest, HostsParser_EndsWithComment) {
173   DnsHosts hosts;
174   ParseHosts("127.0.0.1 localhost # comment", &hosts);
175   EXPECT_EQ(1u, hosts.size());
176 }
177 
TEST(DnsHostsTest,HostsParser_EndsWithNewline)178 TEST(DnsHostsTest, HostsParser_EndsWithNewline) {
179   DnsHosts hosts;
180   ParseHosts("127.0.0.1 localhost\n", &hosts);
181   EXPECT_EQ(1u, hosts.size());
182 }
183 
TEST(DnsHostsTest,HostsParser_EndsWithTwoNewlines)184 TEST(DnsHostsTest, HostsParser_EndsWithTwoNewlines) {
185   DnsHosts hosts;
186   ParseHosts("127.0.0.1 localhost\n\n", &hosts);
187   EXPECT_EQ(1u, hosts.size());
188 }
189 
TEST(DnsHostsTest,HostsParser_EndsWithNewlineAndWhitespace)190 TEST(DnsHostsTest, HostsParser_EndsWithNewlineAndWhitespace) {
191   DnsHosts hosts;
192   ParseHosts("127.0.0.1 localhost\n ", &hosts);
193   EXPECT_EQ(1u, hosts.size());
194 }
195 
TEST(DnsHostsTest,HostsParser_EndsWithNewlineAndToken)196 TEST(DnsHostsTest, HostsParser_EndsWithNewlineAndToken) {
197   DnsHosts hosts;
198   ParseHosts("127.0.0.1 localhost\ntoken", &hosts);
199   EXPECT_EQ(1u, hosts.size());
200 }
201 
202 }  // namespace
203 
204 }  // namespace net
205