diff options
Diffstat (limited to '3rdparty/openpgm-svn-r1135/pgm/indextoaddr_unittest.c')
-rw-r--r-- | 3rdparty/openpgm-svn-r1135/pgm/indextoaddr_unittest.c | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/3rdparty/openpgm-svn-r1135/pgm/indextoaddr_unittest.c b/3rdparty/openpgm-svn-r1135/pgm/indextoaddr_unittest.c new file mode 100644 index 0000000..7699f9c --- /dev/null +++ b/3rdparty/openpgm-svn-r1135/pgm/indextoaddr_unittest.c @@ -0,0 +1,302 @@ +/* vim:ts=8:sts=8:sw=4:noai:noexpandtab + * + * unit tests for portable interface index to socket address function. + * + * Copyright (c) 2009-2010 Miru Limited. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* IFF_UP */ +#define _BSD_SOURCE 1 + +#include <errno.h> +#include <netdb.h> +#include <signal.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <net/if.h> + +#include <glib.h> +#include <check.h> + + +/* mock state */ + +struct mock_interface_t { + unsigned int index; + char* name; + unsigned int flags; + struct sockaddr_storage addr; + struct sockaddr_storage netmask; +}; + +static GList *mock_interfaces = NULL; + +struct pgm_ifaddrs_t; +struct pgm_error_t; + +static bool mock_pgm_getifaddrs (struct pgm_ifaddrs_t**, struct pgm_error_t**); +static void mock_pgm_freeifaddrs (struct pgm_ifaddrs_t*); +static unsigned mock_pgm_if_nametoindex (const sa_family_t, const char*); + + +#define pgm_getifaddrs mock_pgm_getifaddrs +#define pgm_freeifaddrs mock_pgm_freeifaddrs +#define pgm_if_nametoindex mock_pgm_if_nametoindex + + +#define INDEXTOADDR_DEBUG +#include "indextoaddr.c" + + +static +gpointer +create_interface ( + const unsigned index, + const char* name, + const char* flags + ) +{ + struct mock_interface_t* new_interface; + + g_assert (name); + g_assert (flags); + + new_interface = g_slice_alloc0 (sizeof(struct mock_interface_t)); + new_interface->index = index; + new_interface->name = g_strdup (name); + + struct sockaddr_in* sin = (gpointer)&new_interface->addr; + struct sockaddr_in6* sin6 = (gpointer)&new_interface->addr; + + gchar** tokens = g_strsplit (flags, ",", 0); + for (guint i = 0; tokens[i]; i++) + { + if (strcmp (tokens[i], "up") == 0) + new_interface->flags |= IFF_UP; + else if (strcmp (tokens[i], "down") == 0) + new_interface->flags |= 0; + else if (strcmp (tokens[i], "loop") == 0) + new_interface->flags |= IFF_LOOPBACK; + else if (strcmp (tokens[i], "broadcast") == 0) + new_interface->flags |= IFF_BROADCAST; + else if (strcmp (tokens[i], "multicast") == 0) + new_interface->flags |= IFF_MULTICAST; + else if (strncmp (tokens[i], "ip=", strlen("ip=")) == 0) { + const char* addr = tokens[i] + strlen("ip="); + g_assert (pgm_sockaddr_pton (addr, (struct sockaddr*)&new_interface->addr)); + } + else if (strncmp (tokens[i], "netmask=", strlen("netmask=")) == 0) { + const char* addr = tokens[i] + strlen("netmask="); + g_assert (pgm_sockaddr_pton (addr, (struct sockaddr*)&new_interface->netmask)); + } + else if (strncmp (tokens[i], "scope=", strlen("scope=")) == 0) { + const char* scope = tokens[i] + strlen("scope="); + g_assert (AF_INET6 == ((struct sockaddr*)&new_interface->addr)->sa_family); + ((struct sockaddr_in6*)&new_interface->addr)->sin6_scope_id = atoi (scope); + } + else + g_error ("parsing failed for flag \"%s\"", tokens[i]); + } + + g_strfreev (tokens); + return new_interface; +} + +#define APPEND_INTERFACE(a,b,c) \ + do { \ + gpointer data = create_interface ((a), (b), (c)); \ + g_assert (data); \ + mock_interfaces = g_list_append (mock_interfaces, data); \ + g_assert (mock_interfaces); g_assert (mock_interfaces->data); \ + } while (0) +static +void +mock_setup_net (void) +{ + APPEND_INTERFACE( 1, "lo", "up,loop"); + APPEND_INTERFACE( 2, "eth0", "up,broadcast,multicast"); + APPEND_INTERFACE( 3, "eth1", "down,broadcast,multicast"); + APPEND_INTERFACE( 1, "lo", "up,loop,ip=127.0.0.1,netmask=255.0.0.0"); + APPEND_INTERFACE( 2, "eth0", "up,broadcast,multicast,ip=10.6.28.33,netmask=255.255.255.0"); + APPEND_INTERFACE( 1, "lo", "up,loop,ip=::1,netmask=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff,scope=0"); + APPEND_INTERFACE( 2, "eth0", "up,broadcast,multicast,ip=2002:dce8:d28e::33,netmask=ffff:ffff:ffff:ffff::0,scope=0"); + APPEND_INTERFACE( 2, "eth0", "up,broadcast,multicast,ip=fe80::214:5eff:febd:6dda,netmask=ffff:ffff:ffff:ffff::0,scope=2"); +} + +static +void +mock_teardown_net (void) +{ + GList* list; + + list = mock_interfaces; + while (list) { + struct mock_interface_t* interface = list->data; + g_free (interface->name); + g_slice_free1 (sizeof(struct mock_interface_t), interface); + list = list->next; + } + g_list_free (mock_interfaces); +} + +/* mock functions for external references */ + +size_t +pgm_transport_pkt_offset2 ( + const bool can_fragment, + const bool use_pgmcc + ) +{ + return 0; +} + +bool +mock_pgm_getifaddrs ( + struct pgm_ifaddrs_t** ifap, + pgm_error_t** err + ) +{ + if (NULL == ifap) { + return FALSE; + } + + g_debug ("mock_getifaddrs (ifap:%p err:%p)", (gpointer)ifap, (gpointer)err); + + GList* list = mock_interfaces; + int n = g_list_length (list); + struct pgm_ifaddrs_t* ifa = calloc (n, sizeof(struct pgm_ifaddrs_t)); + struct pgm_ifaddrs_t* ift = ifa; + while (list) { + struct mock_interface_t* interface = list->data; + ift->ifa_addr = (gpointer)&interface->addr; + ift->ifa_name = interface->name; + ift->ifa_flags = interface->flags; + ift->ifa_netmask = (gpointer)&interface->netmask; + list = list->next; + if (list) { + ift->ifa_next = ift + 1; + ift = ift->ifa_next; + } + } + + *ifap = ifa; + return TRUE; +} + +static +void +mock_pgm_freeifaddrs ( + struct pgm_ifaddrs_t* ifa + ) +{ + g_debug ("mock_freeifaddrs (ifa:%p)", (gpointer)ifa); + free (ifa); +} + +unsigned +mock_pgm_if_nametoindex ( + const sa_family_t iffamily, + const char* ifname + ) +{ + GList* list = mock_interfaces; + while (list) { + const struct mock_interface_t* interface = list->data; + if (0 == strcmp (ifname, interface->name)) + return interface->index; + list = list->next; + } + return 0; +} + + +/* target: + * bool + * pgm_if_indextoaddr ( + * const unsigned ifindex, + * const sa_family_t iffamily, + * const uint32_t ifscope, + * struct sockaddr* ifsa, + * pgm_error_t** error + * ) + */ + +START_TEST (test_indextoaddr_pass_001) +{ + char saddr[INET6_ADDRSTRLEN]; + struct sockaddr_storage addr; + pgm_error_t* err = NULL; + const unsigned int ifindex = 2; + fail_unless (TRUE == pgm_if_indextoaddr (ifindex, AF_INET, 0, (struct sockaddr*)&addr, &err)); + pgm_sockaddr_ntop ((struct sockaddr*)&addr, saddr, sizeof(saddr)); + g_message ("index:%d -> %s", + ifindex, saddr); + fail_unless (TRUE == pgm_if_indextoaddr (ifindex, AF_INET6, 0, (struct sockaddr*)&addr, &err)); + pgm_sockaddr_ntop ((struct sockaddr*)&addr, saddr, sizeof(saddr)); + g_message ("index:%d -> %s", + ifindex, saddr); +} +END_TEST + +START_TEST (test_indextoaddr_fail_001) +{ + pgm_error_t* err = NULL; + fail_unless (FALSE == pgm_if_indextoaddr (0, 0, 0, NULL, &err)); +} +END_TEST + + +static +Suite* +make_test_suite (void) +{ + Suite* s; + + s = suite_create (__FILE__); + + TCase* tc_indextoaddr = tcase_create ("init-ctx"); + suite_add_tcase (s, tc_indextoaddr); + tcase_add_checked_fixture (tc_indextoaddr, mock_setup_net, mock_teardown_net); + tcase_add_test (tc_indextoaddr, test_indextoaddr_pass_001); + tcase_add_test (tc_indextoaddr, test_indextoaddr_fail_001); + return s; +} + +static +Suite* +make_master_suite (void) +{ + Suite* s = suite_create ("Master"); + return s; +} + +int +main (void) +{ + SRunner* sr = srunner_create (make_master_suite ()); + srunner_add_suite (sr, make_test_suite ()); + srunner_run_all (sr, CK_ENV); + int number_failed = srunner_ntests_failed (sr); + srunner_free (sr); + return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} + +/* eof */ |