blob: c51c79f2d01a56931a2632aca1734bce2973269a [file] [edit]
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Unittests for inet_ntop.
///
//===----------------------------------------------------------------------===//
#include "hdr/errno_macros.h"
#include "hdr/sys_socket_macros.h"
#include "hdr/types/struct_in6_addr.h"
#include "hdr/types/struct_in_addr.h"
#include "src/__support/endian_internal.h"
#include "src/arpa/inet/inet_ntop.h"
#include "test/UnitTest/ErrnoCheckingTest.h"
#include "test/UnitTest/Test.h"
using LlvmLibcInetNtopTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
TEST_F(LlvmLibcInetNtopTest, InvalidFamily) {
char buf[64];
struct in_addr addr = {0};
ASSERT_EQ(static_cast<const char *>(nullptr),
LIBC_NAMESPACE::inet_ntop(AF_INET + AF_INET6 + 1, &addr, buf,
sizeof(buf)));
ASSERT_ERRNO_EQ(EAFNOSUPPORT);
}
static void *ipv4(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
static struct in_addr addr;
addr.s_addr = LIBC_NAMESPACE::Endian::to_big_endian(
static_cast<uint32_t>(a) << 24 | static_cast<uint32_t>(b) << 16 |
static_cast<uint32_t>(c) << 8 | static_cast<uint32_t>(d));
return &addr;
}
static void *ipv6(uint16_t a, uint16_t b, uint16_t c, uint16_t d, uint16_t e,
uint16_t f, uint16_t g, uint16_t h) {
static struct in6_addr addr;
addr.s6_addr16[0] = LIBC_NAMESPACE::Endian::to_big_endian(a);
addr.s6_addr16[1] = LIBC_NAMESPACE::Endian::to_big_endian(b);
addr.s6_addr16[2] = LIBC_NAMESPACE::Endian::to_big_endian(c);
addr.s6_addr16[3] = LIBC_NAMESPACE::Endian::to_big_endian(d);
addr.s6_addr16[4] = LIBC_NAMESPACE::Endian::to_big_endian(e);
addr.s6_addr16[5] = LIBC_NAMESPACE::Endian::to_big_endian(f);
addr.s6_addr16[6] = LIBC_NAMESPACE::Endian::to_big_endian(g);
addr.s6_addr16[7] = LIBC_NAMESPACE::Endian::to_big_endian(h);
return &addr;
}
TEST_F(LlvmLibcInetNtopTest, IPv4Tests) {
char buf[16];
EXPECT_STREQ("127.0.0.1", LIBC_NAMESPACE::inet_ntop(
AF_INET, ipv4(127, 0, 0, 1), buf, sizeof(buf)));
ASSERT_ERRNO_SUCCESS();
// Test buffer too small (needs 10 bytes including null terminator)
EXPECT_EQ(static_cast<const char *>(nullptr),
LIBC_NAMESPACE::inet_ntop(AF_INET, ipv4(127, 0, 0, 1), buf, 9));
ASSERT_ERRNO_EQ(ENOSPC);
EXPECT_STREQ("127.0.0.1",
LIBC_NAMESPACE::inet_ntop(AF_INET, ipv4(127, 0, 0, 1), buf, 10));
ASSERT_ERRNO_SUCCESS();
EXPECT_STREQ("255.255.255.255",
LIBC_NAMESPACE::inet_ntop(AF_INET, ipv4(255, 255, 255, 255), buf,
sizeof(buf)));
ASSERT_ERRNO_SUCCESS();
// Test buffer too small (needs 16 bytes)
EXPECT_EQ(
static_cast<const char *>(nullptr),
LIBC_NAMESPACE::inet_ntop(AF_INET, ipv4(255, 255, 255, 255), buf, 15));
ASSERT_ERRNO_EQ(ENOSPC);
// Boundary conditions for the number of digits.
EXPECT_STREQ("0.0.0.0",
LIBC_NAMESPACE::inet_ntop(AF_INET, ipv4(0, 0, 0, 0), buf, 10));
ASSERT_ERRNO_SUCCESS();
EXPECT_STREQ("0.0.0.1",
LIBC_NAMESPACE::inet_ntop(AF_INET, ipv4(0, 0, 0, 1), buf, 10));
ASSERT_ERRNO_SUCCESS();
EXPECT_STREQ("0.0.0.9",
LIBC_NAMESPACE::inet_ntop(AF_INET, ipv4(0, 0, 0, 9), buf, 10));
ASSERT_ERRNO_SUCCESS();
EXPECT_STREQ("0.0.0.10",
LIBC_NAMESPACE::inet_ntop(AF_INET, ipv4(0, 0, 0, 10), buf, 11));
ASSERT_ERRNO_SUCCESS();
EXPECT_STREQ("0.0.0.11",
LIBC_NAMESPACE::inet_ntop(AF_INET, ipv4(0, 0, 0, 11), buf, 11));
ASSERT_ERRNO_SUCCESS();
EXPECT_STREQ("0.0.0.99",
LIBC_NAMESPACE::inet_ntop(AF_INET, ipv4(0, 0, 0, 99), buf, 11));
ASSERT_ERRNO_SUCCESS();
EXPECT_STREQ("0.0.0.100",
LIBC_NAMESPACE::inet_ntop(AF_INET, ipv4(0, 0, 0, 100), buf, 12));
ASSERT_ERRNO_SUCCESS();
}
TEST_F(LlvmLibcInetNtopTest, IPv6Tests) {
char buf[64];
// No compression
EXPECT_STREQ("1:2:3:4:5:6:7:8",
LIBC_NAMESPACE::inet_ntop(AF_INET6, ipv6(1, 2, 3, 4, 5, 6, 7, 8),
buf, sizeof(buf)));
ASSERT_ERRNO_SUCCESS();
// Compression, fully compressed.
EXPECT_STREQ(static_cast<const char *>(nullptr),
LIBC_NAMESPACE::inet_ntop(AF_INET6, ipv6(0, 0, 0, 0, 0, 0, 0, 0),
buf, 2));
ASSERT_ERRNO_EQ(ENOSPC);
EXPECT_STREQ("::", LIBC_NAMESPACE::inet_ntop(
AF_INET6, ipv6(0, 0, 0, 0, 0, 0, 0, 0), buf, 3));
ASSERT_ERRNO_SUCCESS();
// Leading block of zeroes.
EXPECT_STREQ("::1", LIBC_NAMESPACE::inet_ntop(
AF_INET6, ipv6(0, 0, 0, 0, 0, 0, 0, 1), buf, 4));
ASSERT_ERRNO_SUCCESS();
EXPECT_EQ(static_cast<const char *>(nullptr),
LIBC_NAMESPACE::inet_ntop(AF_INET6, ipv6(0, 0, 0, 0, 0, 0, 0, 1),
buf, 3));
ASSERT_ERRNO_EQ(ENOSPC);
EXPECT_STREQ("::1:2:3", LIBC_NAMESPACE::inet_ntop(
AF_INET6, ipv6(0, 0, 0, 0, 0, 1, 2, 3), buf, 8));
ASSERT_ERRNO_SUCCESS();
// Trailing block of zeroes.
EXPECT_STREQ("1::", LIBC_NAMESPACE::inet_ntop(
AF_INET6, ipv6(1, 0, 0, 0, 0, 0, 0, 0), buf, 4));
ASSERT_ERRNO_SUCCESS();
EXPECT_STREQ("1:2::", LIBC_NAMESPACE::inet_ntop(
AF_INET6, ipv6(1, 2, 0, 0, 0, 0, 0, 0), buf, 6));
ASSERT_ERRNO_SUCCESS();
// Middle of string.
EXPECT_STREQ("2001:db8::1",
LIBC_NAMESPACE::inet_ntop(AF_INET6,
ipv6(0x2001, 0x0db8, 0, 0, 0, 0, 0, 1),
buf, sizeof(buf)));
ASSERT_ERRNO_SUCCESS();
EXPECT_STREQ("2001:db8:0:1::1",
LIBC_NAMESPACE::inet_ntop(AF_INET6,
ipv6(0x2001, 0x0db8, 0, 1, 0, 0, 0, 1),
buf, sizeof(buf)));
ASSERT_ERRNO_SUCCESS();
// Longer block wins.
EXPECT_STREQ("2001:0:0:1::1", LIBC_NAMESPACE::inet_ntop(
AF_INET6, ipv6(0x2001, 0, 0, 1, 0, 0, 0, 1),
buf, sizeof(buf)));
ASSERT_ERRNO_SUCCESS();
EXPECT_STREQ("0:0:1:1::",
LIBC_NAMESPACE::inet_ntop(AF_INET6, ipv6(0, 0, 1, 1, 0, 0, 0, 0),
buf, sizeof(buf)));
ASSERT_ERRNO_SUCCESS();
// In case of ties, the first block wins.
EXPECT_STREQ("::1:0:0:1:0:0",
LIBC_NAMESPACE::inet_ntop(AF_INET6, ipv6(0, 0, 1, 0, 0, 1, 0, 0),
buf, sizeof(buf)));
ASSERT_ERRNO_SUCCESS();
// A single zero is not compressed, no matter it's position.
EXPECT_STREQ("0:1:1:1:1:1:1:1",
LIBC_NAMESPACE::inet_ntop(AF_INET6, ipv6(0, 1, 1, 1, 1, 1, 1, 1),
buf, sizeof(buf)));
ASSERT_ERRNO_SUCCESS();
EXPECT_STREQ("1:0:1:1:1:1:1:1",
LIBC_NAMESPACE::inet_ntop(AF_INET6, ipv6(1, 0, 1, 1, 1, 1, 1, 1),
buf, sizeof(buf)));
ASSERT_ERRNO_SUCCESS();
EXPECT_STREQ("1:1:1:1:1:1:1:0",
LIBC_NAMESPACE::inet_ntop(AF_INET6, ipv6(1, 1, 1, 1, 1, 1, 1, 0),
buf, sizeof(buf)));
ASSERT_ERRNO_SUCCESS();
// V4 mapped addresses.
EXPECT_STREQ("::ffff:192.168.0.1",
LIBC_NAMESPACE::inet_ntop(
AF_INET6, ipv6(0, 0, 0, 0, 0, 0xffff, 0xc0a8, 1), buf, 19));
ASSERT_ERRNO_SUCCESS();
EXPECT_STREQ("::192.168.0.1", LIBC_NAMESPACE::inet_ntop(
AF_INET6, ipv6(0, 0, 0, 0, 0, 0, 0xc0a8, 1),
buf, sizeof(buf)));
ASSERT_ERRNO_SUCCESS();
// If only the last component is set, we don't v4-map.
EXPECT_STREQ("::dead", LIBC_NAMESPACE::inet_ntop(
AF_INET6, ipv6(0, 0, 0, 0, 0, 0, 0, 0xdead), buf,
sizeof(buf)));
ASSERT_ERRNO_SUCCESS();
// But we do for the penultimate.
EXPECT_STREQ("::10.13.0.0", LIBC_NAMESPACE::inet_ntop(
AF_INET6, ipv6(0, 0, 0, 0, 0, 0, 0x0a0d, 0),
buf, sizeof(buf)));
ASSERT_ERRNO_SUCCESS();
// Edge cases for numbers of digits.
EXPECT_STREQ("0:1::", LIBC_NAMESPACE::inet_ntop(
AF_INET6, ipv6(0, 1, 0, 0, 0, 0, 0, 0), buf, 6));
ASSERT_ERRNO_SUCCESS();
EXPECT_STREQ("1:1::", LIBC_NAMESPACE::inet_ntop(
AF_INET6, ipv6(1, 1, 0, 0, 0, 0, 0, 0), buf, 6));
ASSERT_ERRNO_SUCCESS();
EXPECT_STREQ("2:1::", LIBC_NAMESPACE::inet_ntop(
AF_INET6, ipv6(2, 1, 0, 0, 0, 0, 0, 0), buf, 6));
ASSERT_ERRNO_SUCCESS();
EXPECT_STREQ("4:1::", LIBC_NAMESPACE::inet_ntop(
AF_INET6, ipv6(4, 1, 0, 0, 0, 0, 0, 0), buf, 6));
ASSERT_ERRNO_SUCCESS();
EXPECT_STREQ("8:1::", LIBC_NAMESPACE::inet_ntop(
AF_INET6, ipv6(8, 1, 0, 0, 0, 0, 0, 0), buf, 6));
ASSERT_ERRNO_SUCCESS();
EXPECT_STREQ("10:1::",
LIBC_NAMESPACE::inet_ntop(
AF_INET6, ipv6(0x10, 1, 0, 0, 0, 0, 0, 0), buf, 7));
ASSERT_ERRNO_SUCCESS();
EXPECT_STREQ("ff:1::",
LIBC_NAMESPACE::inet_ntop(
AF_INET6, ipv6(0xff, 1, 0, 0, 0, 0, 0, 0), buf, 7));
ASSERT_ERRNO_SUCCESS();
EXPECT_STREQ("100:1::",
LIBC_NAMESPACE::inet_ntop(
AF_INET6, ipv6(0x100, 1, 0, 0, 0, 0, 0, 0), buf, 8));
ASSERT_ERRNO_SUCCESS();
EXPECT_STREQ("fff:1::",
LIBC_NAMESPACE::inet_ntop(
AF_INET6, ipv6(0xfff, 1, 0, 0, 0, 0, 0, 0), buf, 8));
ASSERT_ERRNO_SUCCESS();
EXPECT_STREQ("1000:1::",
LIBC_NAMESPACE::inet_ntop(
AF_INET6, ipv6(0x1000, 1, 0, 0, 0, 0, 0, 0), buf, 9));
ASSERT_ERRNO_SUCCESS();
// Maximum length address.
EXPECT_STREQ("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
LIBC_NAMESPACE::inet_ntop(AF_INET6,
ipv6(0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff),
buf, 40));
ASSERT_ERRNO_SUCCESS();
EXPECT_EQ(static_cast<const char *>(nullptr),
LIBC_NAMESPACE::inet_ntop(AF_INET6,
ipv6(0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff),
buf, 39));
ASSERT_ERRNO_EQ(ENOSPC);
// IPv4-mapped max length
EXPECT_STREQ(
"::ffff:255.255.255.255",
LIBC_NAMESPACE::inet_ntop(
AF_INET6, ipv6(0, 0, 0, 0, 0, 0xffff, 0xffff, 0xffff), buf, 23));
ASSERT_ERRNO_SUCCESS();
EXPECT_EQ(
static_cast<const char *>(nullptr),
LIBC_NAMESPACE::inet_ntop(
AF_INET6, ipv6(0, 0, 0, 0, 0, 0xffff, 0xffff, 0xffff), buf, 22));
ASSERT_ERRNO_EQ(ENOSPC);
}