blob: 2ee7bed264e28a1a476a4981266cc2d1292d8a15 [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/base/ip_address_number.h"
#include "base/format_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "net/base/net_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace {
// Helper to strignize an IP number (used to define expectations).
std::string DumpIPNumber(const IPAddressNumber& v) {
std::string out;
for (size_t i = 0; i < v.size(); ++i) {
if (i != 0)
out.append(",");
out.append(base::IntToString(static_cast<int>(v[i])));
}
return out;
}
TEST(IpAddressNumberTest, IPAddressToString) {
uint8_t addr1[4] = {0, 0, 0, 0};
EXPECT_EQ("0.0.0.0", IPAddressToString(addr1, sizeof(addr1)));
uint8_t addr2[4] = {192, 168, 0, 1};
EXPECT_EQ("192.168.0.1", IPAddressToString(addr2, sizeof(addr2)));
uint8_t addr3[16] = {0xFE, 0xDC, 0xBA, 0x98};
EXPECT_EQ("fedc:ba98::", IPAddressToString(addr3, sizeof(addr3)));
}
TEST(IpAddressNumberTest, IPAddressToStringWithPort) {
uint8_t addr1[4] = {0, 0, 0, 0};
EXPECT_EQ("0.0.0.0:3", IPAddressToStringWithPort(addr1, sizeof(addr1), 3));
uint8_t addr2[4] = {192, 168, 0, 1};
EXPECT_EQ("192.168.0.1:99",
IPAddressToStringWithPort(addr2, sizeof(addr2), 99));
uint8_t addr3[16] = {0xFE, 0xDC, 0xBA, 0x98};
EXPECT_EQ("[fedc:ba98::]:8080",
IPAddressToStringWithPort(addr3, sizeof(addr3), 8080));
}
// Test that invalid IP literals fail to parse.
TEST(IpAddressNumberTest, ParseIPLiteralToNumber_FailParse) {
IPAddressNumber number;
EXPECT_FALSE(ParseIPLiteralToNumber("bad value", &number));
EXPECT_FALSE(ParseIPLiteralToNumber("bad:value", &number));
EXPECT_FALSE(ParseIPLiteralToNumber(std::string(), &number));
EXPECT_FALSE(ParseIPLiteralToNumber("192.168.0.1:30", &number));
EXPECT_FALSE(ParseIPLiteralToNumber(" 192.168.0.1 ", &number));
EXPECT_FALSE(ParseIPLiteralToNumber("[::1]", &number));
}
// Test parsing an IPv4 literal.
TEST(IpAddressNumberTest, ParseIPLiteralToNumber_IPv4) {
IPAddressNumber number;
EXPECT_TRUE(ParseIPLiteralToNumber("192.168.0.1", &number));
EXPECT_EQ("192,168,0,1", DumpIPNumber(number));
EXPECT_EQ("192.168.0.1", IPAddressToString(number));
}
// Test parsing an IPv6 literal.
TEST(IpAddressNumberTest, ParseIPLiteralToNumber_IPv6) {
IPAddressNumber number;
EXPECT_TRUE(ParseIPLiteralToNumber("1:abcd::3:4:ff", &number));
EXPECT_EQ("0,1,171,205,0,0,0,0,0,0,0,3,0,4,0,255", DumpIPNumber(number));
EXPECT_EQ("1:abcd::3:4:ff", IPAddressToString(number));
}
// Test mapping an IPv4 address to an IPv6 address.
TEST(IpAddressNumberTest, ConvertIPv4NumberToIPv6Number) {
IPAddressNumber ipv4_number;
EXPECT_TRUE(ParseIPLiteralToNumber("192.168.0.1", &ipv4_number));
IPAddressNumber ipv6_number =
ConvertIPv4NumberToIPv6Number(ipv4_number);
// ::ffff:192.168.0.1
EXPECT_EQ("0,0,0,0,0,0,0,0,0,0,255,255,192,168,0,1",
DumpIPNumber(ipv6_number));
EXPECT_EQ("::ffff:c0a8:1", IPAddressToString(ipv6_number));
}
TEST(IpAddressNumberTest, ParseURLHostnameToNumber_FailParse) {
IPAddressNumber number;
EXPECT_FALSE(ParseURLHostnameToNumber("bad value", &number));
EXPECT_FALSE(ParseURLHostnameToNumber("bad:value", &number));
EXPECT_FALSE(ParseURLHostnameToNumber(std::string(), &number));
EXPECT_FALSE(ParseURLHostnameToNumber("192.168.0.1:30", &number));
EXPECT_FALSE(ParseURLHostnameToNumber(" 192.168.0.1 ", &number));
EXPECT_FALSE(ParseURLHostnameToNumber("::1", &number));
}
TEST(IpAddressNumberTest, ParseURLHostnameToNumber_IPv4) {
IPAddressNumber number;
EXPECT_TRUE(ParseURLHostnameToNumber("192.168.0.1", &number));
EXPECT_EQ("192,168,0,1", DumpIPNumber(number));
EXPECT_EQ("192.168.0.1", IPAddressToString(number));
}
TEST(IpAddressNumberTest, ParseURLHostnameToNumber_IPv6) {
IPAddressNumber number;
EXPECT_TRUE(ParseURLHostnameToNumber("[1:abcd::3:4:ff]", &number));
EXPECT_EQ("0,1,171,205,0,0,0,0,0,0,0,3,0,4,0,255", DumpIPNumber(number));
EXPECT_EQ("1:abcd::3:4:ff", IPAddressToString(number));
}
TEST(IpAddressNumberTest, IsIPv4Mapped) {
IPAddressNumber ipv4_number;
EXPECT_TRUE(ParseIPLiteralToNumber("192.168.0.1", &ipv4_number));
EXPECT_FALSE(IsIPv4Mapped(ipv4_number));
IPAddressNumber ipv6_number;
EXPECT_TRUE(ParseIPLiteralToNumber("::1", &ipv4_number));
EXPECT_FALSE(IsIPv4Mapped(ipv6_number));
IPAddressNumber ipv4mapped_number;
EXPECT_TRUE(ParseIPLiteralToNumber("::ffff:0101:1", &ipv4mapped_number));
EXPECT_TRUE(IsIPv4Mapped(ipv4mapped_number));
}
TEST(IpAddressNumberTest, ConvertIPv4MappedToIPv4) {
IPAddressNumber ipv4mapped_number;
EXPECT_TRUE(ParseIPLiteralToNumber("::ffff:0101:1", &ipv4mapped_number));
IPAddressNumber expected;
EXPECT_TRUE(ParseIPLiteralToNumber("1.1.0.1", &expected));
IPAddressNumber result = ConvertIPv4MappedToIPv4(ipv4mapped_number);
EXPECT_EQ(expected, result);
}
// Test parsing invalid CIDR notation literals.
TEST(IpAddressNumberTest, ParseCIDRBlock_Invalid) {
const char* const bad_literals[] = {
"foobar",
"",
"192.168.0.1",
"::1",
"/",
"/1",
"1",
"192.168.1.1/-1",
"192.168.1.1/33",
"::1/-3",
"a::3/129",
"::1/x",
"192.168.0.1//11"
};
for (size_t i = 0; i < arraysize(bad_literals); ++i) {
IPAddressNumber ip_number;
size_t prefix_length_in_bits;
EXPECT_FALSE(ParseCIDRBlock(bad_literals[i],
&ip_number,
&prefix_length_in_bits));
}
}
// Test parsing a valid CIDR notation literal.
TEST(IpAddressNumberTest, ParseCIDRBlock_Valid) {
IPAddressNumber ip_number;
size_t prefix_length_in_bits;
EXPECT_TRUE(ParseCIDRBlock("192.168.0.1/11",
&ip_number,
&prefix_length_in_bits));
EXPECT_EQ("192,168,0,1", DumpIPNumber(ip_number));
EXPECT_EQ(11u, prefix_length_in_bits);
}
TEST(IpAddressNumberTest, IPNumberMatchesPrefix) {
struct {
const char* const cidr_literal;
const char* const ip_literal;
bool expected_to_match;
} tests[] = {
// IPv4 prefix with IPv4 inputs.
{
"10.10.1.32/27",
"10.10.1.44",
true
},
{
"10.10.1.32/27",
"10.10.1.90",
false
},
{
"10.10.1.32/27",
"10.10.1.90",
false
},
// IPv6 prefix with IPv6 inputs.
{
"2001:db8::/32",
"2001:DB8:3:4::5",
true
},
{
"2001:db8::/32",
"2001:c8::",
false
},
// IPv6 prefix with IPv4 inputs.
{
"2001:db8::/33",
"192.168.0.1",
false
},
{
"::ffff:192.168.0.1/112",
"192.168.33.77",
true
},
// IPv4 prefix with IPv6 inputs.
{
"10.11.33.44/16",
"::ffff:0a0b:89",
true
},
{
"10.11.33.44/16",
"::ffff:10.12.33.44",
false
},
};
for (size_t i = 0; i < arraysize(tests); ++i) {
SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: %s, %s", i,
tests[i].cidr_literal,
tests[i].ip_literal));
IPAddressNumber ip_number;
EXPECT_TRUE(ParseIPLiteralToNumber(tests[i].ip_literal, &ip_number));
IPAddressNumber ip_prefix;
size_t prefix_length_in_bits;
EXPECT_TRUE(ParseCIDRBlock(tests[i].cidr_literal,
&ip_prefix,
&prefix_length_in_bits));
EXPECT_EQ(tests[i].expected_to_match,
IPNumberMatchesPrefix(ip_number,
ip_prefix,
prefix_length_in_bits));
}
}
} // anonymous namespace
} // namespace net