blob: ccfa770ff244e3cdd6a9fdd24d2dc736b670b605 [file] [log] [blame] [edit]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net-base/ipv6_address.h"
#include <arpa/inet.h>
#include <array>
#include <set>
#include <unordered_set>
#include <base/logging.h>
#include <gtest/gtest.h>
namespace net_base {
namespace {
constexpr char kGoodString[] = "fe80::1aa9:5ff:7ebf:14c5";
constexpr IPv6Address::DataType kGoodData = {0xfe, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1a, 0xa9, 0x05, 0xff,
0x7e, 0xbf, 0x14, 0xc5};
TEST(IPv6AddressTest, DefaultConstructor) {
constexpr IPv6Address default_addr;
constexpr IPv6Address::DataType data{0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0};
EXPECT_EQ(default_addr.data(), data);
}
TEST(IPv6AddressTest, Constructor) {
// Constructed from std::array.
constexpr IPv6Address address1(kGoodData);
// Constructed from other instance.
constexpr IPv6Address address2(address1);
EXPECT_EQ(address1.data(), kGoodData);
EXPECT_EQ(address1, address2);
constexpr IPv6Address address3(0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
0xff);
EXPECT_EQ(address3.ToString(), "11:2233:4455:6677:8899:aabb:ccdd:eeff");
}
TEST(IPv6AddressTest, CreateFromString_Success) {
const auto address = IPv6Address::CreateFromString(kGoodString);
ASSERT_TRUE(address);
EXPECT_EQ(address->data(), kGoodData);
}
TEST(IPv6AddressTest, ToString) {
const IPv6Address address(kGoodData);
EXPECT_EQ(address.ToString(), kGoodString);
// Make sure std::ostream operator<<() works.
LOG(INFO) << "address = " << address;
}
TEST(IPv6AddressTest, CreateFromString_Fail) {
EXPECT_FALSE(IPv6Address::CreateFromString(""));
EXPECT_FALSE(IPv6Address::CreateFromString("192.168.10.1"));
EXPECT_FALSE(IPv6Address::CreateFromString(
"0000:1111:2222:3333:4444:5555:6666:7777:8888:9999:AAAA:BBBB"));
}
TEST(IPv4AddressTest, ToBytes) {
const std::vector<uint8_t> expected{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1a, 0xa9, 0x05, 0xff,
0x7e, 0xbf, 0x14, 0xc5};
const IPv6Address address(kGoodData);
EXPECT_EQ(address.ToBytes(), expected);
}
TEST(IPv6AddressTest, ToByteString) {
const std::string expected = {
static_cast<char>(0xfe), static_cast<char>(0x80), static_cast<char>(0x00),
static_cast<char>(0x00), static_cast<char>(0x00), static_cast<char>(0x00),
static_cast<char>(0x00), static_cast<char>(0x00), static_cast<char>(0x1a),
static_cast<char>(0xa9), static_cast<char>(0x05), static_cast<char>(0xff),
static_cast<char>(0x7e), static_cast<char>(0xbf), static_cast<char>(0x14),
static_cast<char>(0xc5)};
const IPv6Address address(kGoodData);
EXPECT_EQ(address.ToByteString(), expected);
}
TEST(IPv4Address, In6Addr) {
const struct in6_addr expected_addr = {
{{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0xa9, 0x05, 0xff,
0x7e, 0xbf, 0x14, 0xc5}}};
const auto ipv6_addr = IPv6Address(expected_addr);
EXPECT_EQ(ipv6_addr.ToString(), "fe80::1aa9:5ff:7ebf:14c5");
const auto addr = ipv6_addr.ToIn6Addr();
EXPECT_EQ(memcmp(&addr, &expected_addr, sizeof(addr)), 0);
}
TEST(IPv6AddressTest, CreateFromBytes) {
const auto expected = IPv6Address(kGoodData);
EXPECT_EQ(*IPv6Address::CreateFromBytes(kGoodData), expected);
}
TEST(IPv6AddressTest, IsZero) {
const IPv6Address default_addr;
EXPECT_TRUE(default_addr.IsZero());
const IPv6Address address(kGoodData);
EXPECT_FALSE(address.IsZero());
}
TEST(IPv6AddressTest, Order) {
const IPv6Address kOrderedAddresses[] = {
*IPv6Address::CreateFromString("::1"),
*IPv6Address::CreateFromString("2401:fa00:480:c6::30"),
*IPv6Address::CreateFromString("2401:fa00:480:c6::1:10"),
*IPv6Address::CreateFromString("2401:fa00:480:f6::6"),
*IPv6Address::CreateFromString("2401:fa01:480:f6::1"),
*IPv6Address::CreateFromString("fe80:1000::"),
*IPv6Address::CreateFromString("ff02::1")};
for (size_t i = 0; i < std::size(kOrderedAddresses); ++i) {
for (size_t j = 0; j < std::size(kOrderedAddresses); ++j) {
if (i < j) {
EXPECT_TRUE(kOrderedAddresses[i] < kOrderedAddresses[j]);
} else {
EXPECT_FALSE(kOrderedAddresses[i] < kOrderedAddresses[j]);
}
}
}
}
TEST(IPv6AddressTest, Hash) {
std::set<IPv6Address> set;
set.insert(IPv6Address());
std::unordered_set<IPv6Address> unordered_set;
unordered_set.insert(IPv6Address());
}
TEST(IPv6CIDR, CreateFromCIDRString) {
const auto address = *IPv6Address::CreateFromString("2401:fa00:480:c6::30");
const auto cidr1 = IPv6CIDR::CreateFromCIDRString("2401:fa00:480:c6::30/0");
ASSERT_TRUE(cidr1);
EXPECT_EQ(cidr1->address(), address);
EXPECT_EQ(cidr1->prefix_length(), 0);
const auto cidr2 = IPv6CIDR::CreateFromCIDRString("2401:fa00:480:c6::30/25");
ASSERT_TRUE(cidr2);
EXPECT_EQ(cidr2->address(), address);
EXPECT_EQ(cidr2->prefix_length(), 25);
const auto cidr3 = IPv6CIDR::CreateFromCIDRString("2401:fa00:480:c6::30/128");
ASSERT_TRUE(cidr3);
EXPECT_EQ(cidr3->address(), address);
EXPECT_EQ(cidr3->prefix_length(), 128);
const auto cidr4 = IPv6CIDR::CreateFromCIDRString("2401:fa00:480:c6::30");
ASSERT_TRUE(cidr4);
EXPECT_EQ(cidr4->address(), address);
EXPECT_EQ(cidr4->prefix_length(), 128);
}
TEST(IPv6CIDR, CreateFromCIDRString_Fail) {
EXPECT_FALSE(IPv6CIDR::CreateFromCIDRString("192.168.10.1"));
EXPECT_FALSE(IPv6CIDR::CreateFromCIDRString("192.168.10.1/24"));
EXPECT_FALSE(IPv6CIDR::CreateFromCIDRString("2401:fa00:480:c6::30/-1"));
EXPECT_FALSE(IPv6CIDR::CreateFromCIDRString("2401:fa00:480:c6::30/130"));
}
TEST(IPv6CIDR, CreateFromStringAndPrefix) {
const std::string address_string = "fe80:1000::";
const auto address = *IPv6Address::CreateFromString(address_string);
const auto cidr1 = IPv6CIDR::CreateFromStringAndPrefix(address_string, 0);
ASSERT_TRUE(cidr1);
EXPECT_EQ(cidr1->address(), address);
EXPECT_EQ(cidr1->prefix_length(), 0);
const auto cidr2 = IPv6CIDR::CreateFromStringAndPrefix(address_string, 64);
ASSERT_TRUE(cidr2);
EXPECT_EQ(cidr2->address(), address);
EXPECT_EQ(cidr2->prefix_length(), 64);
const auto cidr3 = IPv6CIDR::CreateFromStringAndPrefix(address_string, 128);
ASSERT_TRUE(cidr3);
EXPECT_EQ(cidr3->address(), address);
EXPECT_EQ(cidr3->prefix_length(), 128);
}
TEST(IPv6CIDR, CreateFromBytesAndPrefix) {
const int prefix_length = 64;
const std::vector<uint8_t> bytes = {std::begin(kGoodData),
std::end(kGoodData)};
const std::string byte_string = {reinterpret_cast<const char*>(bytes.data()),
bytes.size()};
const auto cidr = *IPv6CIDR::CreateFromBytesAndPrefix(bytes, prefix_length);
EXPECT_EQ(cidr.address().ToBytes(), bytes);
EXPECT_EQ(cidr.prefix_length(), prefix_length);
EXPECT_EQ(IPv6CIDR::CreateFromBytesAndPrefix(byte_string, prefix_length),
cidr);
EXPECT_FALSE(IPv6CIDR::CreateFromBytesAndPrefix(kGoodData, 129));
EXPECT_FALSE(IPv6CIDR::CreateFromBytesAndPrefix(kGoodData, -1));
}
TEST(IPv6CIDR, CreateFromAddressAndPrefix) {
const auto address = *IPv6Address::CreateFromString("::1");
EXPECT_TRUE(IPv6CIDR::CreateFromAddressAndPrefix(address, 0));
EXPECT_TRUE(IPv6CIDR::CreateFromAddressAndPrefix(address, 50));
EXPECT_TRUE(IPv6CIDR::CreateFromAddressAndPrefix(address, 128));
EXPECT_FALSE(IPv6CIDR::CreateFromAddressAndPrefix(address, 129));
EXPECT_FALSE(IPv6CIDR::CreateFromAddressAndPrefix(address, -1));
}
TEST(IPv6CIDR, DefaultConstructor) {
constexpr IPv6CIDR default_cidr;
EXPECT_EQ(default_cidr.address(), IPv6Address());
EXPECT_EQ(default_cidr.prefix_length(), 0);
constexpr IPv6Address address(kGoodData);
constexpr auto cidr = IPv6CIDR(address);
EXPECT_EQ(cidr.address(), address);
EXPECT_EQ(cidr.prefix_length(), 0);
}
TEST(IPv6CIDR, GetPrefixCIDR) {
const auto cidr1 = *IPv6CIDR::CreateFromCIDRString("2401:fa00:480:f6::6/16");
EXPECT_EQ(cidr1.GetPrefixCIDR(),
*IPv6CIDR::CreateFromCIDRString("2401::/16"));
const auto cidr2 = *IPv6CIDR::CreateFromCIDRString("2401:fa00:480:f6::6/20");
EXPECT_EQ(cidr2.GetPrefixCIDR(),
*IPv6CIDR::CreateFromCIDRString("2401:f000::/20"));
const auto cidr3 = *IPv6CIDR::CreateFromCIDRString("2401:fa00:480:f6::6/0");
EXPECT_EQ(cidr3.GetPrefixCIDR(), *IPv6CIDR::CreateFromCIDRString("::/0"));
const auto cidr4 = *IPv6CIDR::CreateFromCIDRString("2401:fa00:480:f6::6/128");
EXPECT_EQ(cidr4.GetPrefixCIDR(),
*IPv6CIDR::CreateFromCIDRString("2401:fa00:480:f6::6/128"));
}
TEST(IPv6CIDR, InSameSubnetWith) {
const auto cidr = *IPv6CIDR::CreateFromCIDRString("2401:fa00:480:f6::6/16");
EXPECT_TRUE(cidr.InSameSubnetWith(*IPv6Address::CreateFromString("2401::")));
EXPECT_TRUE(
cidr.InSameSubnetWith(*IPv6Address::CreateFromString("2401:abc::")));
EXPECT_TRUE(cidr.InSameSubnetWith(*IPv6Address::CreateFromString("2401::1")));
EXPECT_FALSE(
cidr.InSameSubnetWith(*IPv6Address::CreateFromString("2402::6")));
EXPECT_FALSE(cidr.InSameSubnetWith(*IPv6Address::CreateFromString("::6")));
}
TEST(IPv6CIDR, ToString) {
const std::string cidr_string = "2401:fa00:480:c6::1:10/24";
const auto cidr = *IPv6CIDR::CreateFromCIDRString(cidr_string);
EXPECT_EQ(cidr.ToString(), cidr_string);
// Make sure std::ostream operator<<() works.
LOG(INFO) << "cidr = " << cidr;
}
TEST(IPv6CIDR, GetNetmask) {
EXPECT_EQ(*IPv6CIDR::GetNetmask(0), *IPv6Address::CreateFromString("::"));
EXPECT_EQ(*IPv6CIDR::GetNetmask(4), *IPv6Address::CreateFromString("f000::"));
EXPECT_EQ(*IPv6CIDR::GetNetmask(23),
*IPv6Address::CreateFromString("ffff:fe00::"));
EXPECT_EQ(*IPv6CIDR::GetNetmask(128),
*IPv6Address::CreateFromString(
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
EXPECT_FALSE(IPv6CIDR::GetNetmask(-1));
EXPECT_FALSE(IPv6CIDR::GetNetmask(129));
}
TEST(IPv6CIDR, ToNetmask) {
const auto cidr1 = *IPv6CIDR::CreateFromCIDRString("2401:fa00::1/0");
EXPECT_EQ(cidr1.ToNetmask(), *IPv6Address::CreateFromString("::"));
const auto cidr2 = *IPv6CIDR::CreateFromCIDRString("2401:fa00::1/8");
EXPECT_EQ(cidr2.ToNetmask(), *IPv6Address::CreateFromString("ff00::"));
const auto cidr3 = *IPv6CIDR::CreateFromCIDRString("2401:fa00::1/24");
EXPECT_EQ(cidr3.ToNetmask(), *IPv6Address::CreateFromString("ffff:ff00::"));
}
TEST(IPv6CIDRTest, Container) {
std::set<IPv6CIDR> set;
set.insert(IPv6CIDR());
std::unordered_set<IPv6CIDR> unordered_set;
unordered_set.insert(IPv6CIDR());
}
} // namespace
} // namespace net_base