| // Copyright 2018 The ChromiumOS Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "patchpanel/subnet.h" |
| |
| #include <arpa/inet.h> |
| #include <stdint.h> |
| |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include <base/functional/bind.h> |
| #include <base/functional/callback_helpers.h> |
| #include <base/strings/string_util.h> |
| #include <gtest/gtest.h> |
| |
| #include "patchpanel/net_util.h" |
| |
| // TODO(akahuang): Change the unittest to concrete test cases, instead of using |
| // lots of calculation and for loop inside the test. (go/tott/643) |
| |
| namespace patchpanel { |
| namespace { |
| |
| constexpr net_base::IPv4Address kContainerBaseAddress(100, 115, 92, 192); |
| constexpr net_base::IPv4Address kVmBaseAddress(100, 115, 92, 24); |
| constexpr net_base::IPv4Address kParallelsBaseAddress(100, 115, 92, 128); |
| |
| constexpr uint32_t kContainerSubnetPrefixLength = 28; |
| constexpr uint32_t kVmSubnetPrefixLength = 30; |
| constexpr uint32_t kParallelsSubnetPrefixLength = 28; |
| |
| // kExpectedAvailableCount[i] == AvailableCount() for subnet with prefix_length |
| // i. |
| constexpr uint32_t kExpectedAvailableCount[] = { |
| 0xfffffffe, 0x7ffffffe, 0x3ffffffe, 0x1ffffffe, 0xffffffe, 0x7fffffe, |
| 0x3fffffe, 0x1fffffe, 0xfffffe, 0x7ffffe, 0x3ffffe, 0x1ffffe, |
| 0xffffe, 0x7fffe, 0x3fffe, 0x1fffe, 0xfffe, 0x7ffe, |
| 0x3ffe, 0x1ffe, 0xffe, 0x7fe, 0x3fe, 0x1fe, |
| 0xfe, 0x7e, 0x3e, 0x1e, 0xe, 0x6, |
| 0x2, 0x0, |
| }; |
| |
| class VmSubnetTest : public ::testing::TestWithParam<uint32_t> {}; |
| class ContainerSubnetTest : public ::testing::TestWithParam<uint32_t> {}; |
| class PrefixTest : public ::testing::TestWithParam<int> {}; |
| |
| void SetTrue(bool* value) { |
| *value = true; |
| } |
| |
| } // namespace |
| |
| TEST_P(VmSubnetTest, CIDRAtOffset) { |
| uint32_t index = GetParam(); |
| Subnet subnet( |
| *net_base::IPv4CIDR::CreateFromAddressAndPrefix( |
| AddOffset(kVmBaseAddress, index * 4), kVmSubnetPrefixLength), |
| base::DoNothing()); |
| |
| for (uint32_t offset = 1; offset <= subnet.AvailableCount(); ++offset) { |
| const auto expected_cidr = *net_base::IPv4CIDR::CreateFromAddressAndPrefix( |
| AddOffset(kVmBaseAddress, index * 4 + offset), kVmSubnetPrefixLength); |
| EXPECT_EQ(expected_cidr, subnet.CIDRAtOffset(offset)); |
| } |
| } |
| |
| INSTANTIATE_TEST_SUITE_P(AllValues, |
| VmSubnetTest, |
| ::testing::Range(uint32_t{0}, uint32_t{26})); |
| |
| TEST_P(ContainerSubnetTest, CIDRAtOffset) { |
| uint32_t index = GetParam(); |
| Subnet subnet(*net_base::IPv4CIDR::CreateFromAddressAndPrefix( |
| AddOffset(kContainerBaseAddress, index * 16), |
| kContainerSubnetPrefixLength), |
| base::DoNothing()); |
| |
| for (uint32_t offset = 1; offset <= subnet.AvailableCount(); ++offset) { |
| const auto expected_cidr = *net_base::IPv4CIDR::CreateFromAddressAndPrefix( |
| AddOffset(kContainerBaseAddress, index * 16 + offset), |
| kContainerSubnetPrefixLength); |
| EXPECT_EQ(expected_cidr, subnet.CIDRAtOffset(offset)); |
| } |
| } |
| |
| INSTANTIATE_TEST_SUITE_P(AllValues, |
| ContainerSubnetTest, |
| ::testing::Range(uint32_t{1}, uint32_t{4})); |
| |
| TEST_P(PrefixTest, AvailableCount) { |
| int prefix_length = GetParam(); |
| |
| Subnet subnet( |
| *net_base::IPv4CIDR::CreateFromAddressAndPrefix({}, prefix_length), |
| base::DoNothing()); |
| EXPECT_EQ(kExpectedAvailableCount[prefix_length], subnet.AvailableCount()); |
| } |
| |
| INSTANTIATE_TEST_SUITE_P(AllValues, PrefixTest, ::testing::Range(8, 32)); |
| |
| TEST(SubtnetAddress, StringConversion) { |
| Subnet container_subnet( |
| *net_base::IPv4CIDR::CreateFromAddressAndPrefix( |
| kContainerBaseAddress, kContainerSubnetPrefixLength), |
| base::DoNothing()); |
| EXPECT_EQ("100.115.92.192/28", container_subnet.base_cidr().ToString()); |
| { |
| EXPECT_EQ(*net_base::IPv4CIDR::CreateFromCIDRString("100.115.92.193/28"), |
| container_subnet.CIDRAtOffset(1)); |
| EXPECT_EQ(*net_base::IPv4CIDR::CreateFromCIDRString("100.115.92.194/28"), |
| container_subnet.CIDRAtOffset(2)); |
| EXPECT_EQ(*net_base::IPv4CIDR::CreateFromCIDRString("100.115.92.205/28"), |
| container_subnet.CIDRAtOffset(13)); |
| EXPECT_EQ(*net_base::IPv4CIDR::CreateFromCIDRString("100.115.92.206/28"), |
| container_subnet.CIDRAtOffset(14)); |
| } |
| |
| Subnet vm_subnet(*net_base::IPv4CIDR::CreateFromAddressAndPrefix( |
| kVmBaseAddress, kVmSubnetPrefixLength), |
| base::DoNothing()); |
| EXPECT_EQ("100.115.92.24/30", vm_subnet.base_cidr().ToString()); |
| { |
| EXPECT_EQ(*net_base::IPv4CIDR::CreateFromCIDRString("100.115.92.25/30"), |
| vm_subnet.CIDRAtOffset(1)); |
| EXPECT_EQ(*net_base::IPv4CIDR::CreateFromCIDRString("100.115.92.26/30"), |
| vm_subnet.CIDRAtOffset(2)); |
| } |
| |
| Subnet parallels_subnet( |
| *net_base::IPv4CIDR::CreateFromAddressAndPrefix( |
| kParallelsBaseAddress, kParallelsSubnetPrefixLength), |
| base::DoNothing()); |
| EXPECT_EQ("100.115.92.128/28", parallels_subnet.base_cidr().ToString()); |
| { |
| EXPECT_EQ(*net_base::IPv4CIDR::CreateFromCIDRString("100.115.92.129/28"), |
| parallels_subnet.CIDRAtOffset(1)); |
| EXPECT_EQ(*net_base::IPv4CIDR::CreateFromCIDRString("100.115.92.130/28"), |
| parallels_subnet.CIDRAtOffset(2)); |
| EXPECT_EQ(*net_base::IPv4CIDR::CreateFromCIDRString("100.115.92.141/28"), |
| parallels_subnet.CIDRAtOffset(13)); |
| EXPECT_EQ(*net_base::IPv4CIDR::CreateFromCIDRString("100.115.92.142/28"), |
| parallels_subnet.CIDRAtOffset(14)); |
| } |
| } |
| |
| // Tests that the Subnet runs the provided cleanup callback when it gets |
| // destroyed. |
| TEST(Subnet, Cleanup) { |
| bool called = false; |
| |
| { |
| Subnet subnet(*net_base::IPv4CIDR::CreateFromAddressAndPrefix({}, 24), |
| base::BindOnce(&SetTrue, &called)); |
| } |
| |
| EXPECT_TRUE(called); |
| } |
| |
| } // namespace patchpanel |