blob: 4891e188def9b5c4b86bda042905e25d5498fcc4 [file] [log] [blame]
/*
*
* Copyright (c) 2015-2017 Nest Labs, Inc.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file
* This file implements a unit test suite for <tt>nl::Inet::IPAddress</tt>,
* a class to store and format IPV4 and IPV6 Internet Protocol addresses.
*
*/
#include <InetLayer/IPAddress.h>
#include "ToolCommon.h"
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
#include "lwip/init.h"
#include "lwip/ip_addr.h"
#else
#include <sys/socket.h>
#include <netinet/in.h>
#endif
#include <nltest.h>
#define LLA_PREFIX 0xfe800000
#define ULA_PREFIX 0xfd000000
#define MCAST_PREFIX 0xff000000
#define NUM_MCAST_SCOPES 7
#define NUM_MCAST_GROUPS 2
#define NUM_BYTES_IN_IPV6 16
#define ULA_UP_24_BIT_MASK 0xffffff0000
#define ULA_LO_16_BIT_MASK 0x000000ffff
#define NUM_FIELDS_IN_ADDR sizeof(IPAddress)/sizeof(uint32_t)
using namespace nl::Inet;
// Test input vector format.
struct TestContext {
uint32_t addr[4];
const IPAddressType ipAddrType;
const char *ip;
bool isIPv4;
bool isMcast;
bool isULA;
bool isLLA;
uint64_t global;
uint16_t subnet;
uint64_t interface;
};
// Test input data.
static struct TestContext sContext[] = {
{
{ 0x26200000, 0x10e70400, 0xe83fb28f, 0x9c3a1941 }, kIPAddressType_IPv6,
"2620:0:10e7:400:e83f:b28f:9c3a:1941",
0, 0, 0, 0,
0, 0, 0
},
{
{ 0xfe800000, 0x00000000, 0x8edcd4ff, 0xfe3aebfb }, kIPAddressType_IPv6,
"fe80::8edc:d4ff:fe3a:ebfb",
0, 0, 0, 1,
0, 0, 0
},
{
{ 0xff010000, 0x00000000, 0x00000000, 0x00000001 }, kIPAddressType_IPv6,
"ff01::1",
0, 1, 0, 0,
0, 0, 0
},
{
{ 0xfd000000, 0x00010001, 0x00000000, 0x00000001 }, kIPAddressType_IPv6,
"fd00:0:1:1::1",
0, 0, 1, 0,
0x1, 1, 1
},
{
{ 0xfd123456, 0x0001abcd, 0xabcdef00, 0xfedcba09 }, kIPAddressType_IPv6,
"fd12:3456:1:abcd:abcd:ef00:fedc:ba09",
0, 0, 1, 0,
0x1234560001, 0xabcd, 0xabcdef00fedcba09
},
{
{ 0xfdffffff, 0xffffffff, 0xffffffff, 0xffffffff }, kIPAddressType_IPv6,
"fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
0, 0, 1, 0,
0xffffffffff, 0xffff, 0xffffffffffffffff
},
#if INET_CONFIG_ENABLE_IPV4
{
{ 0x00000000, 0x00000000, 0x0000ffff, 0xffffff00 }, kIPAddressType_IPv4,
"255.255.255.0",
1, 0, 0, 0,
0, 0, 0
},
{
{ 0x00000000, 0x00000000, 0x0000ffff, 0x7f000001 }, kIPAddressType_IPv4,
"127.0.0.1",
1, 0, 0, 0,
0, 0, 0
},
#endif // INET_CONFIG_ENABLE_IPV4
{
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, kIPAddressType_Any,
"::",
0, 0, 0, 0,
0, 0, 0
}
};
static const size_t kTestElements = sizeof(sContext)/sizeof(struct TestContext);
// Utility functions.
/**
* Load input test directly into IPAddress.
*/
static void SetupIPAddress(IPAddress& addr, struct TestContext *inContext)
{
for (size_t i = 0; i < NUM_FIELDS_IN_ADDR; i++)
{
addr.Addr[i] = htonl(inContext->addr[i]);
}
}
/**
* Zero out IP address.
*/
static void ClearIPAddress(IPAddress& addr)
{
for (size_t i = 0; i < NUM_FIELDS_IN_ADDR; i++)
{
addr.Addr[i] = 0;
}
}
// Test functions invoked from the suite.
/**
* Test IP address conversion from a string.
*/
static void CheckFromString(nlTestSuite *inSuite, void *inContext)
{
struct TestContext *theContext = static_cast<struct TestContext *>(inContext);
for (size_t ith = 0; ith < kTestElements; ith++)
{
IPAddress test_addr;
IPAddress::FromString(theContext->ip, test_addr);
NL_TEST_ASSERT(inSuite, test_addr.Addr[0] == htonl(theContext->addr[0]));
NL_TEST_ASSERT(inSuite, test_addr.Addr[1] == htonl(theContext->addr[1]));
NL_TEST_ASSERT(inSuite, test_addr.Addr[2] == htonl(theContext->addr[2]));
NL_TEST_ASSERT(inSuite, test_addr.Addr[3] == htonl(theContext->addr[3]));
theContext++;
}
}
/**
* Test correct identification of IPv6 ULA addresses.
*/
static void CheckIsIPv6ULA(nlTestSuite *inSuite, void *inContext)
{
struct TestContext *theContext = static_cast<struct TestContext *>(inContext);
for (size_t ith = 0; ith < kTestElements; ith++)
{
IPAddress test_addr;
SetupIPAddress(test_addr, theContext);
NL_TEST_ASSERT(inSuite, test_addr.IsIPv6ULA() == theContext->isULA);
theContext++;
}
}
/**
* Test correct identification of IPv6 Link Local addresses.
*/
static void CheckIsIPv6LLA(nlTestSuite *inSuite, void *inContext)
{
struct TestContext *theContext = static_cast<struct TestContext *>(inContext);
for (size_t ith = 0; ith < kTestElements; ith++)
{
IPAddress test_addr;
SetupIPAddress(test_addr, theContext);
NL_TEST_ASSERT(inSuite, test_addr.IsIPv6LinkLocal() == theContext->isLLA);
theContext++;
}
}
/**
* Test correct identification of IPv6 multicast addresses.
*/
static void CheckIsMulticast(nlTestSuite *inSuite, void *inContext)
{
struct TestContext *theContext = static_cast<struct TestContext *>(inContext);
for (size_t ith = 0; ith < kTestElements; ith++)
{
IPAddress test_addr;
SetupIPAddress(test_addr, theContext);
NL_TEST_ASSERT(inSuite, test_addr.IsMulticast() == theContext->isMcast);
theContext++;
}
}
/**
* Test IPAddress equal operator.
*/
static void CheckOperatorEqual(nlTestSuite *inSuite, void *inContext)
{
struct TestContext *theFirstContext = static_cast<struct TestContext *>(inContext);
for (size_t ith = 0; ith < kTestElements; ith++)
{
IPAddress test_addr_1;
struct TestContext *theSecondContext = static_cast<struct TestContext *>(inContext);
SetupIPAddress(test_addr_1, theFirstContext);
for (size_t jth = 0; jth < kTestElements; jth++)
{
IPAddress test_addr_2;
SetupIPAddress(test_addr_2, theSecondContext);
if (theFirstContext == theSecondContext)
{
NL_TEST_ASSERT(inSuite, test_addr_1 == test_addr_2);
}
else
{
NL_TEST_ASSERT(inSuite, !(test_addr_1 == test_addr_2));
}
theSecondContext++;
}
theFirstContext++;
}
}
/**
* Test IPAddress not-equal operator.
*/
static void CheckOperatorNotEqual(nlTestSuite *inSuite, void *inContext)
{
struct TestContext *theFirstContext = static_cast<struct TestContext *>(inContext);
for (size_t ith = 0; ith < kTestElements; ith++)
{
IPAddress test_addr_1;
struct TestContext *theSecondContext = static_cast<struct TestContext *>(inContext);
SetupIPAddress(test_addr_1, theFirstContext);
for (size_t jth = 0; jth < kTestElements; jth++)
{
IPAddress test_addr_2;
SetupIPAddress(test_addr_2, theSecondContext);
if (theFirstContext == theSecondContext)
{
NL_TEST_ASSERT(inSuite, !(test_addr_1 != test_addr_2));
}
else
{
NL_TEST_ASSERT(inSuite, test_addr_1 != test_addr_2);
}
theSecondContext++;
}
theFirstContext++;
}
}
/**
* Test IPAddress assign operator.
*/
static void CheckOperatorAssign(nlTestSuite *inSuite, void *inContext)
{
struct TestContext *theFirstContext = static_cast<struct TestContext *>(inContext);
for (size_t ith = 0; ith < kTestElements; ith++)
{
struct TestContext *theSecondContext = static_cast<struct TestContext *>(inContext);
for (size_t jth = 0; jth < kTestElements; jth++)
{
IPAddress test_addr_1, test_addr_2;
ClearIPAddress(test_addr_1);
SetupIPAddress(test_addr_2, theSecondContext);
// Use operator to assign IPAddress from test_addr_2 to test_addr_1
test_addr_1 = test_addr_2;
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[0] == test_addr_2.Addr[0]);
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[1] == test_addr_2.Addr[1]);
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[2] == test_addr_2.Addr[2]);
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[3] == test_addr_2.Addr[3]);
theSecondContext++;
}
theFirstContext++;
}
}
/**
* Test IPAddress v6 conversion to native representation.
*/
static void CheckToIPv6(nlTestSuite *inSuite, void *inContext)
{
struct TestContext *theContext = static_cast<struct TestContext *>(inContext);
for (size_t ith = 0; ith < kTestElements; ith++)
{
IPAddress test_addr;
uint32_t addr[4];
addr[0] = htonl(theContext->addr[0]);
addr[1] = htonl(theContext->addr[1]);
addr[2] = htonl(theContext->addr[2]);
addr[3] = htonl(theContext->addr[3]);
SetupIPAddress(test_addr, theContext);
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
ip6_addr_t ip_addr_1, ip_addr_2;
ip_addr_1 = *(ip6_addr_t *)addr;
#else
struct in6_addr ip_addr_1, ip_addr_2;
ip_addr_1 = *(struct in6_addr *)addr;
#endif
ip_addr_2 = test_addr.ToIPv6();
NL_TEST_ASSERT(inSuite, !memcmp(&ip_addr_1, &ip_addr_2, sizeof(ip_addr_1)));
theContext++;
}
}
/**
* Test native IPv6 conversion into IPAddress.
*/
static void CheckFromIPv6(nlTestSuite *inSuite, void *inContext)
{
struct TestContext *theContext = static_cast<struct TestContext *>(inContext);
for (size_t ith = 0; ith < kTestElements; ith++)
{
IPAddress test_addr_1, test_addr_2;
uint32_t addr[4];
addr[0] = htonl(theContext->addr[0]);
addr[1] = htonl(theContext->addr[1]);
addr[2] = htonl(theContext->addr[2]);
addr[3] = htonl(theContext->addr[3]);
SetupIPAddress(test_addr_1, theContext);
ClearIPAddress(test_addr_2);
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
ip6_addr_t ip_addr;
ip_addr = *(ip6_addr_t *)addr;
#else
struct in6_addr ip_addr;
ip_addr = *(struct in6_addr *)addr;
#endif
test_addr_2 = IPAddress::FromIPv6(ip_addr);
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[0] == test_addr_2.Addr[0]);
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[1] == test_addr_2.Addr[1]);
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[2] == test_addr_2.Addr[2]);
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[3] == test_addr_2.Addr[3]);
theContext++;
}
}
#if INET_CONFIG_ENABLE_IPV4
/**
* Test correct identification of IPv4 addresses.
*/
static void CheckIsIPv4(nlTestSuite *inSuite, void *inContext)
{
struct TestContext *theContext = static_cast<struct TestContext *>(inContext);
for (size_t ith = 0; ith < kTestElements; ith++)
{
IPAddress test_addr;
SetupIPAddress(test_addr, theContext);
NL_TEST_ASSERT(inSuite, test_addr.IsIPv4() == theContext->isIPv4);
theContext++;
}
}
/**
* Test IPAddress v4 conversion to native representation.
*/
static void CheckToIPv4(nlTestSuite *inSuite, void *inContext)
{
struct TestContext *theContext = static_cast<struct TestContext *>(inContext);
for (size_t ith = 0; ith < kTestElements; ith++)
{
IPAddress test_addr;
SetupIPAddress(test_addr, theContext);
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
ip4_addr_t ip_addr_1, ip_addr_2;
ip_addr_1.addr = lwip_htonl(theContext->addr[3]);
#else
struct in_addr ip_addr_1, ip_addr_2;
ip_addr_1.s_addr = htonl(theContext->addr[3]);
#endif
ip_addr_2 = test_addr.ToIPv4();
NL_TEST_ASSERT(inSuite, !memcmp(&ip_addr_1, &ip_addr_2, sizeof(ip_addr_1)));
theContext++;
}
}
/**
* Test native IPv4 conversion into IPAddress.
*/
static void CheckFromIPv4(nlTestSuite *inSuite, void *inContext)
{
struct TestContext *theContext = static_cast<struct TestContext *>(inContext);
for (size_t ith = 0; ith < kTestElements; ith++)
{
IPAddress test_addr_1, test_addr_2;
SetupIPAddress(test_addr_1, theContext);
// Convert to IPv4 (test_addr_1);
test_addr_1.Addr[0] = 0;
test_addr_1.Addr[1] = 0;
test_addr_1.Addr[2] = htonl(0xffff);
ClearIPAddress(test_addr_2);
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
ip4_addr_t ip_addr;
ip_addr.addr = lwip_htonl(theContext->addr[3]);
#else
struct in_addr ip_addr;
ip_addr.s_addr = htonl(theContext->addr[3]);
#endif
test_addr_2 = IPAddress::FromIPv4(ip_addr);
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[0] == test_addr_2.Addr[0]);
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[1] == test_addr_2.Addr[1]);
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[2] == test_addr_2.Addr[2]);
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[3] == test_addr_2.Addr[3]);
theContext++;
}
}
#endif // INET_CONFIG_ENABLE_IPV4
/**
* Test IPAddress address conversion from socket.
*/
static void CheckFromSocket(nlTestSuite *inSuite, void *inContext)
{
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
(void)inSuite;
// This test is only supported for non LWIP stack.
#else // INET_LWIP
struct TestContext *theContext = static_cast<struct TestContext *>(inContext);
for (size_t ith = 0; ith < kTestElements; ith++)
{
IPAddress test_addr_1, test_addr_2;
uint32_t addr[4];
struct sockaddr_in6 sock_v6;
#if INET_CONFIG_ENABLE_IPV4
struct sockaddr_in sock_v4;
#endif // INET_CONFIG_ENABLE_IPV4
addr[0] = htonl(theContext->addr[0]);
addr[1] = htonl(theContext->addr[1]);
addr[2] = htonl(theContext->addr[2]);
addr[3] = htonl(theContext->addr[3]);
SetupIPAddress(test_addr_1, theContext);
ClearIPAddress(test_addr_2);
switch (theContext->ipAddrType)
{
#if INET_CONFIG_ENABLE_IPV4
case kIPAddressType_IPv4:
memset(&sock_v4, 0, sizeof(struct sockaddr_in));
sock_v4.sin_family = AF_INET;
memcpy(&sock_v4.sin_addr.s_addr, &addr[3], sizeof(struct in_addr));
test_addr_2 = IPAddress::FromSockAddr((struct sockaddr &)sock_v4);
break;
#endif // INET_CONFIG_ENABLE_IPV4
case kIPAddressType_IPv6:
memset(&sock_v6, 0, sizeof(struct sockaddr_in6));
sock_v6.sin6_family = AF_INET6;
memcpy(&sock_v6.sin6_addr.s6_addr, addr, sizeof(struct in6_addr));
test_addr_2 = IPAddress::FromSockAddr((struct sockaddr &)sock_v6);
break;
case kIPAddressType_Any:
memset(&sock_v6, 0, sizeof(struct sockaddr_in6));
sock_v6.sin6_family = 0;
memcpy(&sock_v6.sin6_addr.s6_addr, addr, sizeof(struct in6_addr));
test_addr_2 = IPAddress::FromSockAddr((struct sockaddr &)sock_v6);
break;
default:
continue;
}
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[0] == test_addr_2.Addr[0]);
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[1] == test_addr_2.Addr[1]);
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[2] == test_addr_2.Addr[2]);
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[3] == test_addr_2.Addr[3]);
theContext++;
}
#endif // INET_LWIP
}
/**
* Test IP address type.
*/
static void CheckType(nlTestSuite *inSuite, void *inContext)
{
struct TestContext *theContext = static_cast<struct TestContext *>(inContext);
for (size_t ith = 0; ith < kTestElements; ith++)
{
IPAddress test_addr;
SetupIPAddress(test_addr, theContext);
NL_TEST_ASSERT(inSuite, test_addr.Type() == theContext->ipAddrType);
theContext++;
}
}
/**
* Test IP address interface ID.
*/
static void CheckInterface(nlTestSuite *inSuite, void *inContext)
{
struct TestContext *theContext = static_cast<struct TestContext *>(inContext);
for (size_t ith = 0; ith < kTestElements; ith++)
{
IPAddress test_addr;
SetupIPAddress(test_addr, theContext);
NL_TEST_ASSERT(inSuite, test_addr.InterfaceId() == theContext->interface);
theContext++;
}
}
/**
* Test IP address subnet.
*/
static void CheckSubnet(nlTestSuite *inSuite, void *inContext)
{
struct TestContext *theContext = static_cast<struct TestContext *>(inContext);
for (size_t ith = 0; ith < kTestElements; ith++)
{
IPAddress test_addr;
SetupIPAddress(test_addr, theContext);
NL_TEST_ASSERT(inSuite, test_addr.Subnet() == theContext->subnet);
theContext++;
}
}
/**
* Test IP address global ID.
*/
static void CheckGlobal(nlTestSuite *inSuite, void *inContext)
{
struct TestContext *theContext = static_cast<struct TestContext *>(inContext);
for (size_t ith = 0; ith < kTestElements; ith++)
{
IPAddress test_addr;
SetupIPAddress(test_addr, theContext);
NL_TEST_ASSERT(inSuite, test_addr.GlobalId() == theContext->global);
theContext++;
}
}
/**
* Test address encoding with Weave::Encoding.
*/
static void CheckEncoding(nlTestSuite *inSuite, void *inContext)
{
struct TestContext *theContext = static_cast<struct TestContext *>(inContext);
for (size_t ith = 0; ith < kTestElements; ith++)
{
IPAddress test_addr;
uint8_t *p;
uint8_t buffer[NUM_BYTES_IN_IPV6];
SetupIPAddress(test_addr, theContext);
memset(&buffer, 0, NUM_BYTES_IN_IPV6);
p = buffer;
// Call EncodeAddress function that we test.
test_addr.WriteAddress(p);
// buffer has address in network byte order
NL_TEST_ASSERT(inSuite, buffer[3] == (uint8_t)(theContext->addr[0]));
NL_TEST_ASSERT(inSuite, buffer[2] == (uint8_t)(theContext->addr[0] >> 8));
NL_TEST_ASSERT(inSuite, buffer[1] == (uint8_t)(theContext->addr[0] >> 16));
NL_TEST_ASSERT(inSuite, buffer[0] == (uint8_t)(theContext->addr[0] >> 24));
NL_TEST_ASSERT(inSuite, buffer[7] == (uint8_t)(theContext->addr[1]));
NL_TEST_ASSERT(inSuite, buffer[6] == (uint8_t)(theContext->addr[1] >> 8));
NL_TEST_ASSERT(inSuite, buffer[5] == (uint8_t)(theContext->addr[1] >> 16));
NL_TEST_ASSERT(inSuite, buffer[4] == (uint8_t)(theContext->addr[1] >> 24));
NL_TEST_ASSERT(inSuite, buffer[11] == (uint8_t)(theContext->addr[2]));
NL_TEST_ASSERT(inSuite, buffer[10] == (uint8_t)(theContext->addr[2] >> 8));
NL_TEST_ASSERT(inSuite, buffer[9] == (uint8_t)(theContext->addr[2] >> 16));
NL_TEST_ASSERT(inSuite, buffer[8] == (uint8_t)(theContext->addr[2] >> 24));
NL_TEST_ASSERT(inSuite, buffer[15] == (uint8_t)(theContext->addr[3]));
NL_TEST_ASSERT(inSuite, buffer[14] == (uint8_t)(theContext->addr[3] >> 8));
NL_TEST_ASSERT(inSuite, buffer[13] == (uint8_t)(theContext->addr[3] >> 16));
NL_TEST_ASSERT(inSuite, buffer[12] == (uint8_t)(theContext->addr[3] >> 24));
theContext++;
}
}
/**
* Test address decoding with Weave::Decoding.
*/
static void CheckDecoding(nlTestSuite *inSuite, void *inContext)
{
struct TestContext *theContext = static_cast<struct TestContext *>(inContext);
for (size_t ith = 0; ith < kTestElements; ith++)
{
IPAddress test_addr_1, test_addr_2;
uint8_t buffer[NUM_BYTES_IN_IPV6];
uint8_t *p;
uint8_t b;
SetupIPAddress(test_addr_1, theContext);
ClearIPAddress(test_addr_2);
memset(&buffer, 0, NUM_BYTES_IN_IPV6);
p = buffer;
for (b = 0; b < NUM_BYTES_IN_IPV6; b++)
{
buffer[b] = (uint8_t)(theContext->addr[b / 4] >> ((3 - b % 4) * 8));
}
// Call ReadAddress function that we test.
IPAddress::ReadAddress(p, test_addr_2);
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[0] == test_addr_2.Addr[0]);
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[1] == test_addr_2.Addr[1]);
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[2] == test_addr_2.Addr[2]);
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[3] == test_addr_2.Addr[3]);
theContext++;
}
}
/**
* Test address symmetricity of encoding and decoding with Weave::(De/En)code.
*/
static void CheckEcodeDecodeSymmetricity(nlTestSuite *inSuite, void *inContext)
{
struct TestContext *theContext = static_cast<struct TestContext *>(inContext);
for (size_t ith = 0; ith < kTestElements; ith++)
{
IPAddress test_addr_1, test_addr_2;
uint8_t buffer[NUM_BYTES_IN_IPV6];
uint8_t *p;
SetupIPAddress(test_addr_1, theContext);
ClearIPAddress(test_addr_2);
memset(&buffer, 0, NUM_BYTES_IN_IPV6);
p = buffer;
// Call EncodeAddress function that we test.
test_addr_1.WriteAddress(p);
// Move pointer back to the beginning of the buffer.
p = buffer;
// Call ReadAddress function that we test.
IPAddress::ReadAddress(p, test_addr_2);
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[0] == test_addr_2.Addr[0]);
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[1] == test_addr_2.Addr[1]);
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[2] == test_addr_2.Addr[2]);
NL_TEST_ASSERT(inSuite, test_addr_1.Addr[3] == test_addr_2.Addr[3]);
theContext++;
}
}
/**
* Test assembling ULA address.
*/
static void CheckMakeULA(nlTestSuite *inSuite, void *inContext)
{
struct TestContext *theContext = static_cast<struct TestContext *>(inContext);
for (size_t ith = 0; ith < kTestElements; ith++)
{
IPAddress test_addr;
// Call MakeULA function that we test.
test_addr = IPAddress::MakeULA(theContext->global, theContext->subnet,
theContext->interface);
NL_TEST_ASSERT(inSuite, test_addr.Addr[0] ==
htonl(ULA_PREFIX | (theContext->global & ULA_UP_24_BIT_MASK) >> 16));
NL_TEST_ASSERT(inSuite, test_addr.Addr[1] ==
htonl((theContext->global & ULA_LO_16_BIT_MASK) << 16 | theContext->subnet));
NL_TEST_ASSERT(inSuite, test_addr.Addr[2] == htonl(theContext->interface >> 32));
NL_TEST_ASSERT(inSuite, test_addr.Addr[3] == htonl(theContext->interface));
theContext++;
}
}
/**
* Test assembling LLA address.
*/
static void CheckMakeLLA(nlTestSuite *inSuite, void *inContext)
{
struct TestContext *theContext = static_cast<struct TestContext *>(inContext);
for (size_t ith = 0; ith < kTestElements; ith++)
{
IPAddress test_addr;
// Call MakeLLA function that we test.
test_addr = IPAddress::MakeLLA(theContext->interface);
NL_TEST_ASSERT(inSuite, test_addr.Addr[0] == htonl(LLA_PREFIX));
NL_TEST_ASSERT(inSuite, test_addr.Addr[1] == 0);
NL_TEST_ASSERT(inSuite, test_addr.Addr[2] == htonl(theContext->interface >> 32));
NL_TEST_ASSERT(inSuite, test_addr.Addr[3] == htonl(theContext->interface));
theContext++;
}
}
/**
* Test assembling IPv6 Multicast address.
*/
static void CheckMakeIPv6Multicast(nlTestSuite *inSuite, void *inContext)
{
int s, g;
IPv6MulticastScope scope[NUM_MCAST_SCOPES] =
{
kIPv6MulticastScope_Interface,
kIPv6MulticastScope_Link,
#if INET_CONFIG_ENABLE_IPV4
kIPv6MulticastScope_IPv4,
#endif // INET_CONFIG_ENABLE_IPV4
kIPv6MulticastScope_Admin,
kIPv6MulticastScope_Site,
kIPv6MulticastScope_Organization,
kIPv6MulticastScope_Global
};
IPV6MulticastGroup group[NUM_MCAST_GROUPS] =
{
kIPV6MulticastGroup_AllNodes,
kIPV6MulticastGroup_AllRouters
};
for (s = 0; s < NUM_MCAST_SCOPES; s++)
{
for (g = 0; g < NUM_MCAST_GROUPS; g++)
{
IPAddress test_addr;
// Call MakeIPv6Multicast function that we test.
test_addr = IPAddress::MakeIPv6Multicast(scope[s], group[g]);
NL_TEST_ASSERT(inSuite, test_addr.Addr[0] == htonl(MCAST_PREFIX | (scope[s] << 16)));
NL_TEST_ASSERT(inSuite, test_addr.Addr[1] == 0);
NL_TEST_ASSERT(inSuite, test_addr.Addr[2] == 0);
NL_TEST_ASSERT(inSuite, test_addr.Addr[3] == htonl(group[g]));
}
}
}
/**
* Test IPPrefix.
*/
static void CheckIPPrefix(nlTestSuite *inSuite, void *inContext)
{
struct TestContext *theFirstContext = static_cast<struct TestContext *>(inContext);
for (size_t ith = 0; ith < kTestElements; ith++)
{
IPPrefix ipprefix_1, ipprefix_2;
IPAddress test_addr_1;
SetupIPAddress(test_addr_1, theFirstContext);
ipprefix_1.IPAddr = test_addr_1;
ipprefix_1.Length = 128 - ith;
ipprefix_2 = ipprefix_1;
NL_TEST_ASSERT(inSuite, !ipprefix_1.IsZero());
NL_TEST_ASSERT(inSuite, !ipprefix_2.IsZero());
NL_TEST_ASSERT(inSuite, ipprefix_1 == ipprefix_2);
NL_TEST_ASSERT(inSuite, !(ipprefix_1 != ipprefix_2));
#if !WEAVE_SYSTEM_CONFIG_USE_LWIP
NL_TEST_ASSERT(inSuite, ipprefix_1.MatchAddress(test_addr_1));
#endif
theFirstContext++;
}
}
// Test Suite
/**
* Test Suite. It lists all the test functions.
*/
static const nlTest sTests[] = {
NL_TEST_DEF("From String Conversion", CheckFromString),
#if INET_CONFIG_ENABLE_IPV4
NL_TEST_DEF("IPv4 Detection", CheckIsIPv4),
NL_TEST_DEF("Convert IPv4 to IPAddress", CheckFromIPv4),
NL_TEST_DEF("Convert IPAddress to IPv4", CheckToIPv4),
#endif // INET_CONFIG_ENABLE_IPV4
NL_TEST_DEF("IPv6 ULA Detection", CheckIsIPv6ULA),
NL_TEST_DEF("IPv6 Link Local Detection", CheckIsIPv6LLA),
NL_TEST_DEF("IPv6 Multicast Detection", CheckIsMulticast),
NL_TEST_DEF("Equivalence Operator", CheckOperatorEqual),
NL_TEST_DEF("Non-Equivalence Operator", CheckOperatorNotEqual),
NL_TEST_DEF("Assign Operator", CheckOperatorAssign),
NL_TEST_DEF("Convert IPv6 to IPAddress", CheckFromIPv6),
NL_TEST_DEF("Convert IPAddress to IPv6", CheckToIPv6),
NL_TEST_DEF("Assign address from socket", CheckFromSocket),
NL_TEST_DEF("Address Type", CheckType),
NL_TEST_DEF("Address Interface ID", CheckInterface),
NL_TEST_DEF("Address Subnet", CheckSubnet),
NL_TEST_DEF("Address Global ID", CheckGlobal),
NL_TEST_DEF("Assemble IPv6 ULA address", CheckMakeULA),
NL_TEST_DEF("Assemble IPv6 LLA address", CheckMakeLLA),
NL_TEST_DEF("Assemble IPv6 Multicast address", CheckMakeIPv6Multicast),
NL_TEST_DEF("Weave Encoding", CheckEncoding),
NL_TEST_DEF("Weave Decoding", CheckDecoding),
NL_TEST_DEF("Weave Encode / Decode Symmetricity", CheckEcodeDecodeSymmetricity),
NL_TEST_DEF("IPPrefix test", CheckIPPrefix),
NL_TEST_SENTINEL()
};
/**
* Set up the test suite.
*/
static int TestSetup(void *inContext)
{
return (SUCCESS);
}
/**
* Tear down the test suite.
*/
static int TestTeardown(void *inContext)
{
return (SUCCESS);
}
int main(void)
{
nlTestSuite theSuite = {
"inet-address",
&sTests[0],
TestSetup,
TestTeardown
};
// Generate machine-readable, comma-separated value (CSV) output.
nl_test_set_output_style(OUTPUT_CSV);
// Run test suit againt one context.
nlTestRunner(&theSuite, &sContext);
return nlTestRunnerStats(&theSuite);
}