X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2Ftest%2FIPAddressTest.cpp;h=5097eafa646e04bfa7754ccc6eb92c90cda0561c;hb=156f70334627e5a100283b5334c0a2121d5a45a2;hp=b9cb43de254b5f9db99b7e173c0734f402c09ceb;hpb=dced19f55cf70ce7c0b881af5125d95b76321373;p=folly.git diff --git a/folly/test/IPAddressTest.cpp b/folly/test/IPAddressTest.cpp index b9cb43de..5097eafa 100644 --- a/folly/test/IPAddressTest.cpp +++ b/folly/test/IPAddressTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2014 Facebook, Inc. + * Copyright 2016 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,14 +14,15 @@ * limitations under the License. */ -#include "IPAddressTest.h" +#include #include -#include "folly/Bits.h" -#include "folly/Format.h" -#include "folly/String.h" -#include "folly/MacAddress.h" +#include +#include +#include +#include +#include using namespace folly; using namespace std; @@ -29,16 +30,22 @@ using namespace std; // tests code example TEST(IPAddress, CodeExample) { EXPECT_EQ(4, sizeof(IPAddressV4)); - EXPECT_EQ(16, sizeof(IPAddressV6)); - EXPECT_EQ(20, sizeof(IPAddress)); + EXPECT_EQ(20, sizeof(IPAddressV6)); + EXPECT_EQ(24, sizeof(IPAddress)); + IPAddress uninitaddr; IPAddress v4addr("192.0.2.129"); IPAddress v6map("::ffff:192.0.2.129"); + ASSERT_TRUE(uninitaddr.empty()); + ASSERT_FALSE(v4addr.empty()); + ASSERT_FALSE(v6map.empty()); EXPECT_TRUE(v4addr.inSubnet("192.0.2.0/24")); EXPECT_TRUE(v4addr.inSubnet(IPAddress("192.0.2.0"), 24)); EXPECT_TRUE(v4addr.inSubnet("192.0.2.128/30")); EXPECT_FALSE(v4addr.inSubnet("192.0.2.128/32")); EXPECT_EQ(2164392128, v4addr.asV4().toLong()); EXPECT_EQ(3221226113, v4addr.asV4().toLongHBO()); + ASSERT_FALSE(uninitaddr.isV4()); + ASSERT_FALSE(uninitaddr.isV6()); ASSERT_TRUE(v4addr.isV4()); ASSERT_TRUE(v6map.isV6()); EXPECT_TRUE(v4addr == v6map); @@ -47,6 +54,24 @@ TEST(IPAddress, CodeExample) { EXPECT_TRUE(IPAddress::createIPv6(v4addr) == v6map.asV6()); } +TEST(IPAddress, Scope) { + // Test that link-local scope is saved + auto str = "fe80::62eb:69ff:fe9b:ba60%eth0"; + IPAddressV6 a2(str); + EXPECT_EQ(str, a2.str()); + + sockaddr_in6 sock = a2.toSockAddr(); + EXPECT_NE(0, sock.sin6_scope_id); + + IPAddress a1(str); + EXPECT_EQ(str, a1.str()); + + a2.setScopeId(0); + EXPECT_NE(a1, a2); + + EXPECT_TRUE(a2 < a1); +} + TEST(IPAddress, Ordering) { IPAddress a1("0.1.1.1"); IPAddress a2("1.1.1.0"); @@ -195,6 +220,28 @@ TEST(IPAddress, CtorDefault) { EXPECT_EQ(IPAddressV6("::0"), v6); } +TEST(IPAddressV4, validate) { + EXPECT_TRUE(IPAddressV4::validate("0.0.0.0")); + EXPECT_FALSE(IPAddressV4::validate("0.0.0.")); + EXPECT_TRUE(IPAddressV4::validate("127.127.127.127")); +} + +TEST(IPAddressV6, validate) { + EXPECT_TRUE(IPAddressV6::validate("2620:0:1cfe:face:b00c::3")); + EXPECT_FALSE(IPAddressV6::validate("0.0.0.0")); + EXPECT_TRUE(IPAddressV6::validate("[2620:0:1cfe:face:b00c::3]")); + EXPECT_TRUE(IPAddressV6::validate("::ffff:0.1.1.1")); + EXPECT_TRUE(IPAddressV6::validate("2620:0000:1cfe:face:b00c:0000:0000:0003")); + EXPECT_TRUE( + IPAddressV6::validate("2620:0000:1cfe:face:b00c:0000:127.127.127.127")); +} + +TEST(IPAddress, validate) { + EXPECT_TRUE(IPAddress::validate("0.0.0.0")); + EXPECT_TRUE(IPAddress::validate("::")); + EXPECT_FALSE(IPAddress::validate("asdf")); +} + // Test addresses constructed using a in[6]_addr value TEST_P(IPAddressTest, CtorAddress) { AddressData param = GetParam(); @@ -266,6 +313,7 @@ TEST(IPAddress, CtorSockaddr) { { // setup sockaddr_in6 addr; + memset(&addr, 0, sizeof(addr)); in6_addr sin_addr; ByteArray16 sec{{ // 2620:0:1cfe:face:b00c::3 @@ -373,6 +421,14 @@ TEST_P(IPAddressCtorBinaryTest, InvalidBinary) { IPAddressFormatException); } +TEST(IPAddressSource, ToHex) { + vector data = {{0xff, 0x20, 0x45}}; + EXPECT_EQ(detail::Bytes::toHex(data.data(), 0), ""); + EXPECT_EQ(detail::Bytes::toHex(data.data(), 1), "ff"); + EXPECT_EQ(detail::Bytes::toHex(data.data(), 2), "ff20"); + EXPECT_EQ(detail::Bytes::toHex(data.data(), 3), "ff2045"); +} + // Test toFullyQualified() TEST(IPAddress, ToFullyQualifiedFb) { IPAddress ip("2620:0:1cfe:face:b00c::3"); @@ -384,6 +440,11 @@ TEST(IPAddress, ToFullyQualifiedLocal) { EXPECT_EQ("0000:0000:0000:0000:0000:0000:0000:0001", ip.toFullyQualified()) << ip; } +TEST(IPAddress, ToFullyQualifiedSize) { + auto actual = IPAddressV6::kToFullyQualifiedSize; + auto expected = IPAddress("::").toFullyQualified().size(); + EXPECT_EQ(expected, actual); +} // test v4-v6 mapped addresses TEST_P(IPAddressMappedTest, MappedEqual) { @@ -414,8 +475,8 @@ TEST_P(IPAddressMaskTest, Masks) { IPAddress ip(param.address); IPAddress masked = ip.mask(param.mask); EXPECT_EQ(param.subnet, masked.str()) - << param.address << "/" << to_string(param.mask) - << " -> " << param.subnet; + << param.address << "/" << folly::to(param.mask) << " -> " + << param.subnet; } // Test inSubnet calculations @@ -435,6 +496,26 @@ TEST_P(IPAddressMaskBoundaryTest, NonMaskedSubnet) { EXPECT_EQ(param.inSubnet, ip.inSubnet(subnet, param.mask)); } +TEST(IPAddress, UnitializedEqual) { + IPAddress addrEmpty; + IPAddress ip4("127.0.0.1"); + EXPECT_FALSE(addrEmpty == ip4); + EXPECT_FALSE(ip4 == addrEmpty); + IPAddress ip6("::1"); + EXPECT_FALSE(addrEmpty == ip6); + EXPECT_FALSE(ip6 == addrEmpty); + IPAddress ip6Map("::ffff:192.0.2.129"); + EXPECT_FALSE(addrEmpty == ip6Map); + EXPECT_FALSE(ip6Map == addrEmpty); + IPAddress ip4Zero("0.0.0.0"); + EXPECT_FALSE(addrEmpty == ip4Zero); + EXPECT_FALSE(ip4Zero == addrEmpty); + IPAddress ip6Zero("::"); + EXPECT_FALSE(addrEmpty == ip6Zero); + EXPECT_FALSE(ip6Zero == addrEmpty); + EXPECT_EQ(addrEmpty, addrEmpty); +} + // Test subnet calcs with 6to4 addresses TEST(IPAddress, InSubnetWith6to4) { auto ip = IPAddress("2002:c000:022a::"); // 192.0.2.42 @@ -450,19 +531,35 @@ TEST(IPAddress, InSubnetWith6to4) { EXPECT_TRUE(ip3.inSubnet(subnet3, 16)); } -static vector > invalidMasks = { +static const vector ipv4Strs = { + "127.0.0.1", + "198.168.0.1", + "8.8.0.0", +}; +TEST(IPAddress, getIPv6For6To4) { + for (auto ipv4Str : ipv4Strs) { + auto ip = IPAddress(ipv4Str); + EXPECT_TRUE(ip.isV4()); + IPAddressV4 ipv4 = ip.asV4(); + auto ipv6 = ipv4.getIPv6For6To4(); + EXPECT_EQ(ipv6.type(), IPAddressV6::Type::T6TO4); + auto ipv4New = ipv6.getIPv4For6To4(); + EXPECT_TRUE(ipv4Str.compare(ipv4New.str()) == 0); + } +} + +static const vector > invalidMasks = { {"127.0.0.1", 33}, {"::1", 129}, }; TEST(IPAddress, InvalidMask) { for (auto& tc : invalidMasks) { - uint8_t mask = tc.second; auto ip = IPAddress(tc.first); EXPECT_THROW(ip.mask(tc.second), IPAddressFormatException); } } -static vector > v6types = { +static const vector > v6types = { {"::1", IPAddressV6::Type::NORMAL}, {"2620:0:1cfe:face:b00c::3", IPAddressV6::Type::NORMAL}, {"2001:0000:4136:e378:8000:63bf:3fff:fdd2", IPAddressV6::Type::TEREDO}, @@ -501,12 +598,12 @@ TEST(IPAddress, V6Types) { break; default: throw std::range_error("Invalid expected type: " + - to_string(tc.second)); + folly::to(tc.second)); } } } -static vector > provideToLong = { +static const vector > provideToLong = { {"0.0.0.0", 0}, {"10.0.0.0", 167772160}, {"126.131.128.23", 2122547223}, @@ -565,7 +662,23 @@ TEST(IPAddress, fromBinaryV4) { IPAddressFormatException); } -static vector > > provideBinary16Bytes = { +TEST(IPAddress, toBinaryV4) { + for (auto& tc : provideToLong) { + SCOPED_TRACE(tc.first); + union { + uint8_t u8[4]; + uint32_t u32; + } data; + data.u32 = Endian::big(tc.second); + ByteRange bytes(data.u8, 4); + + auto fromBin = IPAddressV4::fromBinary(bytes); + auto toBin = fromBin.toBinary(); + EXPECT_EQ(bytes, toBin); + } +} + +static const vector > > provideBinary16Bytes = { {"::0", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, @@ -611,6 +724,17 @@ TEST(IPAddress, fromBinaryV6) { IPAddressFormatException); } +TEST(IPAddress, toBinaryV6) { + for (auto& tc : provideBinary16Bytes) { + SCOPED_TRACE(tc.first); + ByteRange bytes(&tc.second.front(), tc.second.size()); + + auto fromBin = IPAddressV6::fromBinary(bytes); + auto toBin = fromBin.toBinary(); + EXPECT_EQ(bytes, toBin); + } +} + TEST_P(IPAddressFlagTest, IsLoopback) { AddressFlags param = GetParam(); IPAddress addr(param.address); @@ -645,10 +769,7 @@ TEST_P(IPAddressFlagTest, IsZero) { TEST_P(IPAddressFlagTest, IsLinkLocal) { AddressFlags param = GetParam(); - if (param.version != 6) { - return; - } - IPAddressV6 addr(param.address); + IPAddress addr(param.address); EXPECT_EQ(param.isLinkLocal(), addr.isLinkLocal()) << addr; } @@ -681,7 +802,7 @@ TEST(IPAddress, SolicitedNodeAddress) { TEST_P(IPAddressByteAccessorTest, CheckBytes) { auto addrData = GetParam(); IPAddress ip(addrData.address); - auto i = 0; + size_t i = 0; for (auto byitr = addrData.bytes.begin(); i < ip.byteCount(); ++i, ++byitr) { EXPECT_EQ(*byitr, ip.getNthMSByte(i)); EXPECT_EQ(*byitr, ip.isV4() ? @@ -705,7 +826,7 @@ TEST_P(IPAddressBitAccessorTest, CheckBits) { //We will traverse the IPAddress bits from 0 to bitCount -1 auto bitr = folly::makeBitIterator(littleEndianAddrData.begin()); IPAddress ip(addrData.address); - for (auto i = 0; i < ip.bitCount(); ++i) { + for (size_t i = 0; i < ip.bitCount(); ++i) { auto msbIndex = ip.bitCount() - i - 1; EXPECT_EQ(*bitr, ip.getNthMSBit(msbIndex)); EXPECT_EQ(*bitr, ip.isV4() ? ip.asV4().getNthMSBit(msbIndex) : @@ -768,6 +889,19 @@ TEST(IPAddress, InvalidBBitAccess) { EXPECT_THROW(asV6.getNthLSBit(-1), std::invalid_argument); } +TEST(IPAddress, StringFormat) { + in6_addr a6; + for (int i = 0; i < 8; ++i) { + a6.s6_addr16[i] = htons(0x0123 + ((i%4) * 0x4444)); + } + EXPECT_EQ("0123:4567:89ab:cdef:0123:4567:89ab:cdef", + detail::fastIpv6ToString(a6)); + + in_addr a4; + a4.s_addr = htonl(0x01020304); + EXPECT_EQ("1.2.3.4", detail::fastIpv4ToString(a4)); +} + TEST(IPAddress, LongestCommonPrefix) { IPAddress ip10("10.0.0.0"); IPAddress ip11("11.0.0.0"); @@ -851,7 +985,7 @@ TEST(IPAddress, LongestCommonPrefix) { } -static vector validAddressProvider = { +static const vector validAddressProvider = { AddressData("127.0.0.1", {127,0,0,1}, 4), AddressData("69.63.189.16", {69,63,189,16}, 4), AddressData("0.0.0.0", {0,0,0,0}, 4), @@ -861,7 +995,7 @@ static vector validAddressProvider = { {38,32,0,0,28,254,250,206,176,12,0,0,0,0,0,3}, 6), }; -static vector invalidAddressProvider = { +static const vector invalidAddressProvider = { "", "foo", "1.1.1.256", @@ -871,7 +1005,7 @@ static vector invalidAddressProvider = { "[1234]", }; -static vector invalidBinaryProvider = { +static const vector invalidBinaryProvider = { {0x31, 0x32, 0x37, 0x2e, 0x30, 0x30, 0x2e, 0x30, 0x2e, 0x31}, // foo {0x66, 0x6f, 0x6f}, @@ -909,13 +1043,16 @@ static vector flagProvider = { AddressFlags("127.0.0.1", 4, IS_LOCAL | IS_PVT_NONROUTE), AddressFlags("::1", 6, IS_LOCAL | IS_PVT_NONROUTE), + // link-local v4 + AddressFlags("169.254.0.1", 4, IS_LINK_LOCAL | IS_PVT_NONROUTE), + // private v4 AddressFlags("10.0.0.0", 4, IS_PVT_NONROUTE), AddressFlags("10.11.12.13", 4, IS_PVT_NONROUTE), AddressFlags("10.255.255.255", 4, IS_PVT_NONROUTE), - AddressFlags("127.128.129.200", 4, IS_PVT_NONROUTE), - AddressFlags("127.255.255.255", 4, IS_PVT_NONROUTE), - AddressFlags("169.254.0.0", 4, IS_PVT_NONROUTE), + AddressFlags("127.128.129.200", 4, IS_LOCAL | IS_PVT_NONROUTE), + AddressFlags("127.255.255.255", 4, IS_LOCAL | IS_PVT_NONROUTE), + AddressFlags("169.254.0.0", 4, IS_LINK_LOCAL | IS_PVT_NONROUTE), AddressFlags("192.168.0.0", 4, IS_PVT_NONROUTE), AddressFlags("192.168.200.255", 4, IS_PVT_NONROUTE), AddressFlags("192.168.255.255", 4, IS_PVT_NONROUTE), @@ -964,7 +1101,7 @@ static vector flagProvider = { AddressFlags("ff02::1", 6, IS_NONROUTABLE | IS_LINK_LOCAL_BROADCAST), }; -static vector > mapProvider = { +static const vector > mapProvider = { {"::ffff:192.0.2.128", "192.0.2.128"}, {"192.0.2.128", "::ffff:192.0.2.128"}, {"::FFFF:129.144.52.38", "129.144.52.38"}, @@ -973,7 +1110,7 @@ static vector > mapProvider = { {"::FFFF:222.1.41.90", "222.1.41.90"}, }; -static vector masksProvider = { +static const vector masksProvider = { MaskData("255.255.255.255", 1, "128.0.0.0"), MaskData("255.255.255.255", 2, "192.0.0.0"), MaskData("192.0.2.42", 16, "192.0.0.0"), @@ -1017,7 +1154,7 @@ static vector masksProvider = { MaskData("2620:0:1cfe:face:b00c::3", 0, "::") }; -static vector maskBoundaryProvider = { +static const vector maskBoundaryProvider = { MaskBoundaryData("10.1.1.1", 24, "10.1.1.1", true), MaskBoundaryData("10.1.1.1", 8, "10.1.2.3", true), MaskBoundaryData("2620:0:1cfe:face:b00c::1", 48, "2620:0:1cfe::", true),