// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
// Copyright (c) 2001-2007 International Computer Science Institute
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software")
// to deal in the Software without restriction, subject to the conditions
// listed in the XORP LICENSE file. These conditions include: you must
// preserve this copyright notice, and you cannot mention the copyright
// holders in advertising related to the Software without their permission.
// The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
// notice is a summary of the XORP LICENSE file; the license in that file is
// legally binding.
#ident "$XORP: xorp/libxorp/test_ipnet.cc,v 1.16 2007/02/16 22:46:24 pavlin Exp $"
#include "libxorp_module.h"
#include "libxorp/xorp.h"
#include "libxorp/xlog.h"
#include "libxorp/exceptions.hh"
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
#include "ipv4net.hh"
// ----------------------------------------------------------------------------
// Verbose output
static bool s_verbose = false;
inline bool verbose() { return s_verbose; }
inline void set_verbose(bool v) { s_verbose = v; }
#define verbose_log(x...) \
do { \
if (verbose()) { \
printf("From %s:%d: ", __FILE__, __LINE__); \
printf(x); \
} \
} while(0)
// ----------------------------------------------------------------------------
// The tests
static bool
v4_serialization_test()
{
struct s_data {
const char* net;
IPv4 v4;
uint32_t prefix_len;
} srep[] = {
{ "128.16.92.160/27", IPv4(htonl_literal(0x80105ca0U)), 27 },
{ "128.16.0.0/16", IPv4(htonl_literal(0x80100000U)), 16 },
{ "255.255.255.255/32", IPv4(htonl_literal(0xffffffffU)), 32},
{ "0.0.0.0/16", IPv4(htonl_literal(0x00000000U)), 16 },
};
for (size_t i = 0; i < sizeof(srep) / sizeof(srep[0]); i++) {
IPv4Net n(srep[i].net);
if (n.prefix_len() != srep[i].prefix_len) {
verbose_log("item %u bad prefix_len %u\n", XORP_UINT_CAST(i),
XORP_UINT_CAST(n.prefix_len()));
return false;
} else if (n.masked_addr() != srep[i].v4) {
verbose_log("item %u bad addr %s != %s\n",
XORP_UINT_CAST(i), n.masked_addr().str().c_str(),
srep[i].v4.str().c_str());
return false;
} else if (n.netmask() != IPv4::make_prefix(n.prefix_len())) {
verbose_log("item %u bad netmask %s != %s\n",
XORP_UINT_CAST(i), n.netmask().str().c_str(),
IPv4::make_prefix(n.prefix_len()).str().c_str());
return false;
}
IPv4Net u (n.str().c_str());
if (u != n) {
verbose_log("item %u to string and back failed.",
XORP_UINT_CAST(i));
return false;
}
}
verbose_log("Passed serialization test.\n");
return true;
}
static bool
v4_less_than_test()
{
const char* d[] = { "128.16.0.0/24", "128.16.64.0/24",
"128.16.0.0/16", "128.17.0.0/24" };
for (size_t i = 1; i < sizeof(d) / sizeof(d[0]); i++) {
IPv4Net lower(d[i - 1]);
IPv4Net upper(d[i]);
if (!(lower < upper)) {
verbose_log("%s is not less than %s\n",
lower.str().c_str(),
upper.str().c_str());
return false;
}
}
verbose_log("Passed operator< test.\n");
return true;
}
static bool
v4_is_unicast_test()
{
IPv4Net uni("128.16.0.0/24"); // regular unicast
IPv4Net multi("224.0.0.0/24"); // multicast, not valid
IPv4Net odd1("128.0.0.0/1"); // not valid, includes multicast
IPv4Net odd2("192.0.0.0/2"); // not valid, includes multicast
IPv4Net odd3("0.0.0.0/1"); // only unicast, should be valid
IPv4Net odd4("128.0.0.0/2"); // only unicast, should be valid
IPv4Net deflt("0.0.0.0/0"); // default route, is valid
if (!uni.is_unicast()) {
verbose_log("%s failed is_unicast test.\n", uni.str().c_str());
return false;
}
if (multi.is_unicast()) {
verbose_log("%s failed is_unicast test.\n", multi.str().c_str());
return false;
}
if (odd1.is_unicast()) {
verbose_log("%s failed is_unicast test.\n", odd1.str().c_str());
return false;
}
if (odd2.is_unicast()) {
verbose_log("%s failed is_unicast test.\n", odd2.str().c_str());
return false;
}
if (!odd3.is_unicast()) {
verbose_log("%s failed is_unicast test.\n", odd3.str().c_str());
return false;
}
if (!odd4.is_unicast()) {
verbose_log("%s failed is_unicast test.\n", odd4.str().c_str());
return false;
}
if (!deflt.is_unicast()) {
verbose_log("%s failed is_unicast test.\n", deflt.str().c_str());
return false;
}
verbose_log("Passed is_unicast test.\n");
return true;
}
static bool
v4_overlap_test()
{
// Address that overlap with netmask
struct x {
const char* a;
const char* b;
size_t overlap;
} data[] = {
{ "180.10.10.0", "180.10.8.0", 22 },
{ "180.10.10.0", "180.10.200.0", 16 },
{ "180.10.20.0", "180.255.200.0", 8 },
};
for (size_t i = 0; i < sizeof(data) / sizeof(data[0]); i++) {
for (size_t p = 0; p < 32; p++) {
IPv4 a(data[i].a);
IPv4 b(data[i].b);
IPv4Net u(a, p);
IPv4Net v(b, p);
if (u.is_overlap(v) != (p <= data[i].overlap)) {
verbose_log("bad overlap %u\n", XORP_UINT_CAST(p));
return -1;
}
}
}
verbose_log("Passed overlap test.\n");
return true;
}
static bool
test_ipv4net_okay()
{
return (v4_serialization_test() == true) &
(v4_less_than_test() == true) &
(v4_overlap_test() == true) &
(v4_is_unicast_test() == true);
}
// ----------------------------------------------------------------------------
// Usage
static void
usage(const char* argv0)
{
fprintf(stderr, "usage: %s [-v]\n", argv0);
fprintf(stderr, "A test program for XORP ipnet classes\n");
}
// ----------------------------------------------------------------------------
// main
int main(int argc, char* const* argv)
{
//
// Initialize and start xlog
//
xlog_init(argv[0], NULL);
xlog_set_verbose(XLOG_VERBOSE_LOW); // Least verbose messages
// XXX: verbosity of the error messages temporary increased
xlog_level_set_verbose(XLOG_LEVEL_ERROR, XLOG_VERBOSE_HIGH);
xlog_add_default_output();
xlog_start();
int ch;
while ((ch = getopt(argc, argv, "hv")) != -1) {
switch (ch) {
case 'v':
set_verbose(true);
break;
case 'h':
case '?':
default:
usage(argv[0]);
xlog_stop();
xlog_exit();
return -1;
}
}
argc -= optind;
argv += optind;
int r = 0;
XorpUnexpectedHandler x(xorp_unexpected_handler);
try {
if (test_ipv4net_okay() == false) {
r = -2;
}
} catch (...) {
xorp_catch_standard_exceptions();
r = -3;
}
//
// Gracefully stop and exit xlog
//
xlog_stop();
xlog_exit();
return r;
}
syntax highlighted by Code2HTML, v. 0.9.1