blob: 48616d48cf8057bc0991dc78b9129878e0887cf5 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/dns/dns_hosts.h"
#include "net/base/ip_address.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace {
struct ExpectedHostsEntry {
const char* host;
AddressFamily family;
const char* ip;
};
void PopulateExpectedHosts(const ExpectedHostsEntry* entries,
size_t num_entries,
DnsHosts* expected_hosts_out) {
for (size_t i = 0; i < num_entries; ++i) {
DnsHostsKey key(entries[i].host, entries[i].family);
IPAddress& ip_ref = (*expected_hosts_out)[key];
ASSERT_TRUE(ip_ref.empty());
ASSERT_TRUE(ip_ref.AssignFromIPLiteral(entries[i].ip));
ASSERT_EQ(ip_ref.size(),
(entries[i].family == ADDRESS_FAMILY_IPV4) ? 4u : 16u);
}
}
TEST(DnsHostsTest, ParseHosts) {
const std::string kContents =
"127.0.0.1 localhost\tlocalhost.localdomain # standard\n"
"\n"
"1.0.0.1 localhost # ignored, first hit above\n"
"fe00::x example company # ignored, malformed IPv6\n"
"1.0.0.300 company # ignored, malformed IPv4\n"
"1.0.0.1 # ignored, missing hostname\n"
"1.0.0.1\t CoMpANy # normalized to 'company' \n"
"::1\tlocalhost ip6-localhost ip6-loopback # comment # within a comment\n"
"\t fe00::0 ip6-localnet\r\n"
"2048::2 example\n"
"2048::1 company example # ignored for 'example' \n"
"127.0.0.1 cache1\n"
"127.0.0.1 cache2 # should reuse parsed IP\n"
"256.0.0.0 cache3 # bogus IP should not clear parsed IP cache\n"
"127.0.0.1 cache4 # should still be reused\n"
"127.0.0.2 cache5\n"
"127.0.0.3 .foo # entries with leading dot are ignored\n"
"127.0.0.3 . # just a dot is ignored\n"
"127.0.0.4 bar. # trailing dot is allowed, for now\n"
"gibberish";
const ExpectedHostsEntry kEntries[] = {
{"localhost", ADDRESS_FAMILY_IPV4, "127.0.0.1"},
{"localhost.localdomain", ADDRESS_FAMILY_IPV4, "127.0.0.1"},
{"company", ADDRESS_FAMILY_IPV4, "1.0.0.1"},
{"localhost", ADDRESS_FAMILY_IPV6, "::1"},
{"ip6-localhost", ADDRESS_FAMILY_IPV6, "::1"},
{"ip6-loopback", ADDRESS_FAMILY_IPV6, "::1"},
{"ip6-localnet", ADDRESS_FAMILY_IPV6, "fe00::0"},
{"company", ADDRESS_FAMILY_IPV6, "2048::1"},
{"example", ADDRESS_FAMILY_IPV6, "2048::2"},
{"cache1", ADDRESS_FAMILY_IPV4, "127.0.0.1"},
{"cache2", ADDRESS_FAMILY_IPV4, "127.0.0.1"},
{"cache4", ADDRESS_FAMILY_IPV4, "127.0.0.1"},
{"cache5", ADDRESS_FAMILY_IPV4, "127.0.0.2"},
{"bar.", ADDRESS_FAMILY_IPV4, "127.0.0.4"},
};
DnsHosts expected_hosts, actual_hosts;
PopulateExpectedHosts(kEntries, arraysize(kEntries), &expected_hosts);
ParseHosts(kContents, &actual_hosts);
ASSERT_EQ(expected_hosts, actual_hosts);
}
TEST(DnsHostsTest, ParseHosts_CommaIsToken) {
const std::string kContents = "127.0.0.1 comma1,comma2";
const ExpectedHostsEntry kEntries[] = {
{ "comma1,comma2", ADDRESS_FAMILY_IPV4, "127.0.0.1" },
};
DnsHosts expected_hosts, actual_hosts;
PopulateExpectedHosts(kEntries, arraysize(kEntries), &expected_hosts);
ParseHostsWithCommaModeForTesting(
kContents, &actual_hosts, PARSE_HOSTS_COMMA_IS_TOKEN);
ASSERT_EQ(0UL, actual_hosts.size());
}
TEST(DnsHostsTest, ParseHosts_CommaIsWhitespace) {
std::string kContents = "127.0.0.1 comma1,comma2";
const ExpectedHostsEntry kEntries[] = {
{ "comma1", ADDRESS_FAMILY_IPV4, "127.0.0.1" },
{ "comma2", ADDRESS_FAMILY_IPV4, "127.0.0.1" },
};
DnsHosts expected_hosts, actual_hosts;
PopulateExpectedHosts(kEntries, arraysize(kEntries), &expected_hosts);
ParseHostsWithCommaModeForTesting(
kContents, &actual_hosts, PARSE_HOSTS_COMMA_IS_WHITESPACE);
ASSERT_EQ(expected_hosts, actual_hosts);
}
// Test that the right comma mode is used on each platform.
TEST(DnsHostsTest, ParseHosts_CommaModeByPlatform) {
std::string kContents = "127.0.0.1 comma1,comma2";
DnsHosts actual_hosts;
ParseHosts(kContents, &actual_hosts);
#if defined(OS_MACOSX)
const ExpectedHostsEntry kEntries[] = {
{ "comma1", ADDRESS_FAMILY_IPV4, "127.0.0.1" },
{ "comma2", ADDRESS_FAMILY_IPV4, "127.0.0.1" },
};
DnsHosts expected_hosts;
PopulateExpectedHosts(kEntries, arraysize(kEntries), &expected_hosts);
ASSERT_EQ(expected_hosts, actual_hosts);
#else
ASSERT_EQ(0UL, actual_hosts.size());
#endif
}
TEST(DnsHostsTest, HostsParser_Empty) {
DnsHosts hosts;
ParseHosts("", &hosts);
EXPECT_EQ(0u, hosts.size());
}
TEST(DnsHostsTest, HostsParser_OnlyWhitespace) {
DnsHosts hosts;
ParseHosts(" ", &hosts);
EXPECT_EQ(0u, hosts.size());
}
TEST(DnsHostsTest, HostsParser_EndsWithNothing) {
DnsHosts hosts;
ParseHosts("127.0.0.1 localhost", &hosts);
EXPECT_EQ(1u, hosts.size());
}
TEST(DnsHostsTest, HostsParser_EndsWithWhitespace) {
DnsHosts hosts;
ParseHosts("127.0.0.1 localhost ", &hosts);
EXPECT_EQ(1u, hosts.size());
}
TEST(DnsHostsTest, HostsParser_EndsWithComment) {
DnsHosts hosts;
ParseHosts("127.0.0.1 localhost # comment", &hosts);
EXPECT_EQ(1u, hosts.size());
}
TEST(DnsHostsTest, HostsParser_EndsWithNewline) {
DnsHosts hosts;
ParseHosts("127.0.0.1 localhost\n", &hosts);
EXPECT_EQ(1u, hosts.size());
}
TEST(DnsHostsTest, HostsParser_EndsWithTwoNewlines) {
DnsHosts hosts;
ParseHosts("127.0.0.1 localhost\n\n", &hosts);
EXPECT_EQ(1u, hosts.size());
}
TEST(DnsHostsTest, HostsParser_EndsWithNewlineAndWhitespace) {
DnsHosts hosts;
ParseHosts("127.0.0.1 localhost\n ", &hosts);
EXPECT_EQ(1u, hosts.size());
}
TEST(DnsHostsTest, HostsParser_EndsWithNewlineAndToken) {
DnsHosts hosts;
ParseHosts("127.0.0.1 localhost\ntoken", &hosts);
EXPECT_EQ(1u, hosts.size());
}
} // namespace
} // namespace net