From 793790d089a184c1b9c526589db62f1ccb6a093e Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Wed, 24 Oct 2012 23:19:14 +0200 Subject: [PATCH 1/6] Initial implementation of an async DNS client API with getaddrinfo + pthreads. --- CMakeLists.txt | 9 +- src/network/backend.c | 3 + src/network/dnsresolver.c | 383 ++++++++++++++++++++++++++++++++++++++ src/network/dnsresolver.h | 119 ++++++++++++ src/network/network.c | 8 +- src/system.h | 6 + src/uhub.h | 1 + 7 files changed, 521 insertions(+), 8 deletions(-) create mode 100644 src/network/dnsresolver.c create mode 100644 src/network/dnsresolver.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9662dcf..9d8ed68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,10 +83,6 @@ if (SQLITE_SUPPORT) target_link_libraries(mod_auth_sqlite sqlite3 utils) target_link_libraries(uhub-passwd sqlite3 utils) set_target_properties(mod_auth_sqlite PROPERTIES PREFIX "") - - if (UNIX) - target_link_libraries(uhub pthread) - endif() endif() @@ -121,11 +117,12 @@ target_link_libraries(mod_logging network) if(UNIX) add_library(adcclient STATIC ${adcclient_SOURCES}) add_executable(uhub-admin ${PROJECT_SOURCE_DIR}/tools/admin.c) - target_link_libraries(uhub-admin adcclient adc network utils) + target_link_libraries(uhub-admin adcclient adc network utils pthread) + target_link_libraries(uhub pthread) if (ADC_STRESS) add_executable(adcrush ${PROJECT_SOURCE_DIR}/tools/adcrush.c ${adcclient_SOURCES}) - target_link_libraries(adcrush adcclient adc network utils) + target_link_libraries(adcrush adcclient adc network utils pthread) endif() endif() diff --git a/src/network/backend.c b/src/network/backend.c index e347b3e..678ab9d 100644 --- a/src/network/backend.c +++ b/src/network/backend.c @@ -146,6 +146,9 @@ int net_backend_process() return 0; } + // Process pending DNS results + net_dns_process(); + g_backend->handler.backend_process(g_backend->data, res); net_cleanup_process(g_backend->cleaner); diff --git a/src/network/dnsresolver.c b/src/network/dnsresolver.c new file mode 100644 index 0000000..cbd0091 --- /dev/null +++ b/src/network/dnsresolver.c @@ -0,0 +1,383 @@ +/* + * uhub - A tiny ADC p2p connection hub + * Copyright (C) 2007-2012, Jan Vidar Krey + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "uhub.h" + +#define DEBUG_LOOKUP_TIME 1 +#define MAX_CONCURRENT_JOBS 25 + +static struct net_dns_job* find_and_remove_job(struct net_dns_job* job); +static struct net_dns_result* find_and_remove_result(struct net_dns_job* job); + +struct net_dns_job +{ + net_dns_job_cb callback; + void* ptr; + + char* host; + int af; + +#ifdef DEBUG_LOOKUP_TIME + struct timeval time_start; + struct timeval time_finish; +#endif + +#ifdef POSIX_THREAD_SUPPORT + pthread_t thread_handle; +#endif +}; + +struct net_dns_result +{ + struct linked_list* addr_list; + struct net_dns_job* job; +}; + +static void free_job(struct net_dns_job* job) +{ + if (job) + { + hub_free(job->host); + hub_free(job); + } +} + +// NOTE: Any job manipulating the members of this +// struct must lock the mutex! +struct net_dns_subsystem +{ + struct linked_list* jobs; // currently running jobs + struct linked_list* results; // queue of results that are awaiting being delivered to callback. +#ifdef POSIX_THREAD_SUPPORT + pthread_mutex_t mutex; +#endif // POSIX_THREAD_SUPPORT +}; + +static struct net_dns_subsystem* g_dns = NULL; + +void net_dns_initialize() +{ + LOG_TRACE("net_dns_initialize()"); + g_dns = (struct net_dns_subsystem*) hub_malloc_zero(sizeof(struct net_dns_subsystem)); + g_dns->jobs = list_create(); + g_dns->results = list_create(); +#ifdef POSIX_THREAD_SUPPORT + pthread_mutex_init(&g_dns->mutex, NULL); +#endif +} + +void net_dns_destroy() +{ +#ifdef POSIX_THREAD_SUPPORT + struct net_dns_job* job; + pthread_mutex_lock(&g_dns->mutex); + LOG_TRACE("net_dns_destroy(): jobs=%d", (int) list_size(g_dns->jobs)); + job = (struct net_dns_job*) list_get_first(g_dns->jobs); + pthread_mutex_unlock(&g_dns->mutex); + + while (job) + { + net_dns_job_cancel(job); + + pthread_mutex_lock(&g_dns->mutex); + job = (struct net_dns_job*) list_get_first(g_dns->jobs); + pthread_mutex_unlock(&g_dns->mutex); + } +#endif +} + +#ifdef POSIX_THREAD_SUPPORT +static void dummy_free(void* ptr) +{ +} +#endif + + +void net_dns_process() +{ +#ifdef POSIX_THREAD_SUPPORT + struct net_dns_result* result; + pthread_mutex_lock(&g_dns->mutex); + LOG_DUMP("net_dns_process(): jobs=%d, results=%d", (int) list_size(g_dns->jobs), (int) list_size(g_dns->results)); + + for (result = (struct net_dns_result*) list_get_first(g_dns->results); result; result = (struct net_dns_result*) list_get_next(g_dns->results)) + { + struct net_dns_job* job = result->job; +#ifdef DEBUG_LOOKUP_TIME + struct timeval time_result; + timersub(&result->job->time_finish, &result->job->time_start, &time_result); + LOG_TRACE("DNS lookup took %d ms", (time_result.tv_sec * 1000) + (time_result.tv_usec / 1000)); +#endif + + // wait for the work thread to finish + pthread_join(job->thread_handle, NULL); + + // callback - should we delete the data immediately? + if (job->callback(job, result)) + { + net_dns_result_free(result); + } + else + { + /* Caller wants to keep the result data, and + * thus needs to call net_dns_result_free() to release it later. + * We only clean up the job data here and keep the results intact. + */ + result->job = NULL; + free_job(job); + } + } + + list_clear(g_dns->results, &dummy_free); + pthread_mutex_unlock(&g_dns->mutex); +#endif // POSIX_THREAD_SUPPORT +} + +#ifdef POSIX_THREAD_SUPPORT +static void* job_thread_resolve_name(void* ptr) +{ + struct net_dns_job* job = (struct net_dns_job*) ptr; + struct addrinfo hints, *result, *it; + struct net_dns_result* dns_results; + int ret; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = job->af; + hints.ai_protocol = IPPROTO_TCP; + + ret = getaddrinfo(job->host, NULL, &hints, &result); + if (ret != 0) + { + LOG_WARN("getaddrinfo() failed: %s", gai_strerror(ret)); + return NULL; + } + + dns_results = (struct net_dns_result*) hub_malloc(sizeof(struct net_dns_result)); + dns_results->addr_list = list_create(); + dns_results->job = job; + + for (it = result; it; it = it->ai_next) + { + struct ip_addr_encap* ipaddr = hub_malloc_zero(sizeof(struct ip_addr_encap)); + ipaddr->af = it->ai_family; + + if (it->ai_family == AF_INET) + { + struct sockaddr_in* addr4 = (struct sockaddr_in*) it->ai_addr; + memcpy(&ipaddr->internal_ip_data.in, &addr4->sin_addr, sizeof(struct in_addr)); + } + else if (it->ai_family == AF_INET6) + { + struct sockaddr_in6* addr6 = (struct sockaddr_in6*) it->ai_addr; + memcpy(&ipaddr->internal_ip_data.in6, &addr6->sin6_addr, sizeof(struct in6_addr)); + } + else + { + LOG_WARN("getaddrinfo() returned result with unknown address family: %d", it->ai_family); + hub_free(ipaddr); + continue; + } + + LOG_WARN("getaddrinfo() - Address (%d): %s", ret++, ip_convert_to_string(ipaddr)); + list_append(dns_results->addr_list, ipaddr); + } + freeaddrinfo(result); + +#ifdef DEBUG_LOOKUP_TIME + gettimeofday(&job->time_finish, NULL); +#endif + + pthread_mutex_lock(&g_dns->mutex); + list_remove(g_dns->jobs, job); + list_append(g_dns->results, dns_results); + pthread_mutex_unlock(&g_dns->mutex); + + return dns_results; +} +#endif + +extern struct net_dns_job* net_dns_gethostbyname(const char* host, int af, net_dns_job_cb callback, void* ptr) +{ + struct net_dns_job* job = (struct net_dns_job*) hub_malloc_zero(sizeof(struct net_dns_job)); + job->host = strdup(host); + job->af = af; + job->callback = callback; + job->ptr = ptr; + +#ifdef DEBUG_LOOKUP_TIME + gettimeofday(&job->time_start, NULL); +#endif + + // FIXME - scheduling - what about a max number of threads? +#ifdef POSIX_THREAD_SUPPORT + pthread_mutex_lock(&g_dns->mutex); + int err = pthread_create(&job->thread_handle, NULL, job_thread_resolve_name, job); + if (err) + { + LOG_WARN("Unable to create thread: (%d) %s", err, strerror(err)); + free_job(job); + job = NULL; + } + else + { + list_append(g_dns->jobs, job); + } + pthread_mutex_unlock(&g_dns->mutex); +#endif + return job; +} + + + +extern struct net_dns_job* net_dns_gethostbyaddr(struct ip_addr_encap* ipaddr, net_dns_job_cb callback, void* ptr) +{ + struct net_dns_job* job = (struct net_dns_job*) hub_malloc_zero(sizeof(struct net_dns_job)); +// job->host = strdup(addr); + job->af = ipaddr->af; + job->callback = callback; + job->ptr = ptr; + +#ifdef POSIX_THREAD_SUPPORT +// if (pthread_create(&job->thread_handle, NULL, start_job, job)) +// { +// free_job(job); +// return NULL; +// } +#endif + return job; +} + +// NOTE: mutex must be locked first! +static struct net_dns_job* find_and_remove_job(struct net_dns_job* job) +{ + struct net_dns_job* it; + for (it = (struct net_dns_job*) list_get_first(g_dns->jobs); it; it = (struct net_dns_job*) list_get_next(g_dns->jobs)) + { + if (it == job) + { + list_remove(g_dns->jobs, it); + return job; + } + } + return NULL; +} + +// NOTE: mutex must be locked first! +static struct net_dns_result* find_and_remove_result(struct net_dns_job* job) +{ + struct net_dns_result* it; + for (it = (struct net_dns_result*) list_get_first(g_dns->results); it; it = (struct net_dns_result*) list_get_next(g_dns->results)) + { + if (it->job == job) + { + list_remove(g_dns->results, it); + return it; + } + } + return NULL; +} + + +extern int net_dns_job_cancel(struct net_dns_job* job) +{ +#ifdef POSIX_THREAD_SUPPORT + int retval = 0; + struct net_dns_result* res; + + LOG_TRACE("net_dns_job_cancel(): job=%p, name=%s", job, job->host); + + /* + * This function looks up the job in the jobs queue (which contains only active jobs) + * If that is found then the thread is cancelled, and the object is deleted. + * If the job was not found, that is either because it was an invalid job, or because + * it was already finished. At which point it was not deleted. + * If the job is already finished, but the result has not been delivered, then this + * deletes the result and the job. + */ + pthread_mutex_lock(&g_dns->mutex); + if (find_and_remove_job(job)) + { + // job still active - cancel it, then close it. + pthread_cancel(job->thread_handle); + pthread_join(job->thread_handle, NULL); + free_job(job); + retval = 1; + } + else if ((res = find_and_remove_result(job))) + { + // job already finished - close it. + pthread_join(job->thread_handle, NULL); + net_dns_result_free(res); + } + pthread_mutex_unlock(&g_dns->mutex); + return retval; +#endif +} + +extern struct net_dns_result* net_dns_job_sync_wait(struct net_dns_job* job) +{ + struct net_dns_result* res = NULL; + + // Wait for job to finish (if not already) + // This should make sure the job is removed from jobs and a result is + // present in results. + pthread_join(job->thread_handle, NULL); + + // Remove the result in order to prevent the callback from being called. + pthread_mutex_lock(&g_dns->mutex); + res = find_and_remove_result(job); + uhub_assert(res != NULL); + res->job = NULL; + free_job(job); + pthread_mutex_unlock(&g_dns->mutex); + + return res; +} + +void* net_dns_job_get_ptr(const struct net_dns_job* job) +{ + return job->ptr; +} + +extern size_t net_dns_result_size(const struct net_dns_result* res) +{ + return list_size(res->addr_list); +} + +extern struct ip_addr_encap* net_dns_result_first(const struct net_dns_result* res) +{ + struct ip_addr_encap* ipaddr = list_get_first(res->addr_list); + LOG_TRACE("net_dns_result_first() - Address: %s", ip_convert_to_string(ipaddr)); + return ipaddr; +} + +extern struct ip_addr_encap* net_dns_result_next(const struct net_dns_result* res) +{ + struct ip_addr_encap* ipaddr = list_get_next(res->addr_list); + LOG_TRACE("net_dns_result_next() - Address: %s", ip_convert_to_string(ipaddr)); + return ipaddr; +} + +extern void net_dns_result_free(struct net_dns_result* res) +{ + list_clear(res->addr_list, &hub_free); + list_destroy(res->addr_list); + free_job(res->job); + hub_free(res); +} diff --git a/src/network/dnsresolver.h b/src/network/dnsresolver.h new file mode 100644 index 0000000..6937422 --- /dev/null +++ b/src/network/dnsresolver.h @@ -0,0 +1,119 @@ +/* + * uhub - A tiny ADC p2p connection hub + * Copyright (C) 2007-2012, Jan Vidar Krey + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#ifndef HAVE_UHUB_NETWORK_DNS_RESOLVER_H +#define HAVE_UHUB_NETWORK_DNS_RESOLVER_H + +struct net_dns_job; +struct net_dns_result; + +// ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- +/// Initialize the DNS subsystem +void net_dns_initialize(); + +/// Shutdown and destroy the DNS subsystem. This will cancel any pending DNS jobs. +void net_dns_destroy(); + +/// Process finished DNS lookups. +void net_dns_process(); + + +// ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- + +/** + * Callback to be called when the DNS job has finished. + * If the name or address could not be resolved to an IP address (host not found, or found but has no address) + * then 'result' contains an empty list (@see net_dns_result_size()). + * If resolving caused an error then result is NULL. + * + * After this callback is called the job is considered done, and is freed. + * + * @param If 1 is returned then result is deleted immediately after the callback, + * otherwise the callback becomes owner of the result data which must be freed with net_dns_result_free(). + */ +typedef int (*net_dns_job_cb)(struct net_dns_job*, const struct net_dns_result* result); + +/** + * Resolve a hostname. + * + * @param host the hostname to be resolved. + * @param af the indicated address family. Should be AF_INET, AF_INET6 (or AF_UNSPEC - which means both AF_INET and AF_INET6. + * @param callback the callback to be called when the hostname has been resolved. + * @param ptr A user-defined pointer value. + * + * @return A resolve job handle if the job has successfully started or NULL if unable to start resolving. + */ +extern struct net_dns_job* net_dns_gethostbyname(const char* host, int af, net_dns_job_cb callback, void* ptr); + +/** + * Perform a reverse DNS lookup for a given IP address. + * + * @see net_dns_gethostbyname() + * @return A resolve job handle if the job has successfully started or NULL if unable to start resolving. + */ +extern struct net_dns_job* net_dns_gethostbyaddr(struct ip_addr_encap* ipaddr, net_dns_job_cb callback, void* ptr); + +/** + * Cancel a DNS lookup job. + * + * It is only allowed to call this once after a job has been started (@see net_dns_gethostbyname(), @see net_dns_gethostbyaddr()) + * but before it has finished and delivered a to the callback address (@see net_dns_job_cb). + * + * @returns 1 if cancelled, or 0 if not cancelled (because the job was not found!) + */ +extern int net_dns_job_cancel(struct net_dns_job* job); + +/** + * Wait in a synchronous manner for a running DNS job to finished and + * return the result here. + * The job must be started with net_dns_gethostbyaddr/net_dns_gethostbyname + * and not finished or cancelled. + * + * If this function is invoked then the callback function will not be called and + * can therefore be NULL. + * + * + * struct net_dns_job* job = net_dns_gethostbyname("www.example.com", AF_INET, NULL, NULL); + * struct net_dns_result* net_dns_job_sync_wait(job); + * + */ +extern struct net_dns_result* net_dns_job_sync_wait(struct net_dns_job* job); + +/** + * Returns the user specified pointer assigned to the resolving job +*/ +extern void* net_dns_job_get_ptr(const struct net_dns_job* job); + +/// Returns the number of results provided. This is 0 if the host could not be found (or has no matching IP address). +extern size_t net_dns_result_size(const struct net_dns_result*); + +/// Returns the first result (if net_dns_result_size > 0), or NULL if not first result exists. +extern struct ip_addr_encap* net_dns_result_first(const struct net_dns_result*); + +/// Returns the next result or NULL if no next result exists. +extern struct ip_addr_encap* net_dns_result_next(const struct net_dns_result*); + +/// When finished with the results +extern void net_dns_result_free(struct net_dns_result*); + +#endif /* HAVE_UHUB_NETWORK_DNS_RESOLVER_H */ diff --git a/src/network/network.c b/src/network/network.c index f9b983f..327fe89 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -60,6 +60,9 @@ int net_initialize() #endif return -1; } + + net_dns_initialize(); + net_stats_initialize(); net_initialized = 1; return 0; @@ -94,8 +97,10 @@ int net_destroy() { LOG_TRACE("Shutting down network monitor"); + net_dns_destroy(); + net_backend_shutdown(); - + #ifdef SSL_SUPPORT net_ssl_library_shutdown(); #endif /* SSL_SUPPORT */ @@ -490,7 +495,6 @@ int net_socket_create(int af, int type, int protocol) } } #endif - return sd; } diff --git a/src/system.h b/src/system.h index e608489..e377524 100644 --- a/src/system.h +++ b/src/system.h @@ -113,11 +113,13 @@ #define uhub_assert assert #ifdef __linux__ +#define POSIX_THREAD_SUPPORT #define USE_EPOLL #include #endif #ifdef BSD_LIKE +#define POSIX_THREAD_SUPPORT /* #define USE_KQUEUE #include @@ -279,6 +281,10 @@ typedef unsigned __int64 uint64_t; #define NEED_GETOPT #endif +#ifdef POSIX_THREAD_SUPPORT +#include +#endif + #if defined(__CYGWIN__) || defined(__MINGW32__) || defined(_MSC_VER) #define PLUGIN_API __declspec(dllexport) #else diff --git a/src/uhub.h b/src/uhub.h index cb90b4c..ad29c3a 100644 --- a/src/uhub.h +++ b/src/uhub.h @@ -74,6 +74,7 @@ extern "C" { #include "network/network.h" #include "network/connection.h" +#include "network/dnsresolver.h" #include "network/ipcalc.h" #include "network/timeout.h" From b34b90f95ab1ffd16e74fd17b38e7f786b6912b9 Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Wed, 24 Oct 2012 23:22:10 +0200 Subject: [PATCH 2/6] Start using the async DNS API. --- src/tools/adcclient.c | 118 ++++++++++++++++++++++++++++++++---------- src/tools/adcclient.h | 1 + src/tools/admin.c | 7 +++ 3 files changed, 98 insertions(+), 28 deletions(-) diff --git a/src/tools/adcclient.c b/src/tools/adcclient.c index a320da9..b7458e8 100644 --- a/src/tools/adcclient.c +++ b/src/tools/adcclient.c @@ -30,6 +30,7 @@ enum ADC_client_state { ps_none, /* Not connected */ + ps_dns, /* looking up name */ ps_conn, /* Connecting... */ ps_conn_ssl, /* SSL handshake */ ps_protocol, /* Have sent HSUP */ @@ -46,6 +47,13 @@ enum ADC_client_flags cflag_pipe = 4, }; +struct ADC_client_address +{ + enum Protocol { ADC, ADCS } protocol; + char* hostname; + uint16_t port; +}; + struct ADC_client { sid_t sid; @@ -59,8 +67,9 @@ struct ADC_client size_t timeout; struct net_connection* con; struct net_timer* timer; - struct sockaddr_in addr; - char* hub_address; + struct sockaddr_storage addr; + struct net_dns_job* dns_job; + struct ADC_client_address address; char* nick; char* desc; int flags; @@ -100,6 +109,7 @@ static void ADC_client_debug(struct ADC_client* client, const char* format, ...) static const char* ADC_client_state_string[] = { "ps_none", + "ps_dns", "ps_conn", "ps_conn_ssl", "ps_protocol", @@ -154,6 +164,9 @@ static void event_callback(struct net_connection* con, int events, void *arg) switch (client->state) { + case ps_dns: + break; + case ps_conn: if (events == NET_EVENT_TIMEOUT) { @@ -162,7 +175,7 @@ static void event_callback(struct net_connection* con, int events, void *arg) } if (events & NET_EVENT_WRITE) - ADC_client_connect(client, 0); + ADC_client_connect_internal(client); break; #ifdef SSL_SUPPORT @@ -493,7 +506,7 @@ void ADC_client_send(struct ADC_client* client, struct adc_message* msg) void ADC_client_send_info(struct ADC_client* client) { ADC_TRACE; - client->info = adc_msg_construct_source(ADC_CMD_BINF, client->sid, 64); + client->info = adc_msg_construct_source(ADC_CMD_BINF, client->sid, 96); adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_NICK, client->nick); @@ -502,7 +515,17 @@ void ADC_client_send_info(struct ADC_client* client) adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_DESCRIPTION, client->desc); } - adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_USER_AGENT, PRODUCT "/" VERSION); + adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_USER_AGENT, PRODUCT " " VERSION); + adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_UPLOAD_SLOTS, 0); + adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_SHARED_SIZE, 0); + adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_SHARED_FILES, 0); + + adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_COUNT_HUB_NORMAL, 1); + adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_COUNT_HUB_REGISTER, 0); + adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_COUNT_HUB_OPERATOR, 0); + + adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_DOWNLOAD_SPEED, 5 * 1024 * 1024); + adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_UPLOAD_SPEED, 10 * 1024 * 1024); adc_cid_pid(client); ADC_client_send(client, client->info); @@ -541,20 +564,31 @@ void ADC_client_destroy(struct ADC_client* client) adc_msg_free(client->info); hub_free(client->nick); hub_free(client->desc); - hub_free(client->hub_address); + hub_free(client->address.hostname); } int ADC_client_connect(struct ADC_client* client, const char* address) { ADC_TRACE; - if (!client->hub_address) + if (client->state == ps_none) { + // Parse address and start name resolving! if (!ADC_client_parse_address(client, address)) return 0; - + return 1; + } + else if (client->state == ps_dns) + { + // Done name resolving! client->callback(client, ADC_CLIENT_CONNECTING, 0); + ADC_client_set_state(client, ps_conn); } + return ADC_client_connect_internal(client); +} + +int ADC_client_connect_internal(struct ADC_client* client) +{ int ret = net_connect(net_con_get_sd(client->con), (struct sockaddr*) &client->addr, sizeof(struct sockaddr_in)); if (ret == 0 || (ret == -1 && net_error() == EISCONN)) { @@ -632,19 +666,53 @@ void ADC_client_disconnect(struct ADC_client* client) } } +int ADC_client_dns_callback(struct net_dns_job* job, const struct net_dns_result* result) +{ + struct ADC_client* client = (struct ADC_client*) net_dns_job_get_ptr(job); + struct ip_addr_encap* ipaddr; + LOG_WARN("ADC_client_dns_callback(): result=%p (%d)", result, net_dns_result_size(result)); + + memset(&client->addr, 0, sizeof(client->addr)); + + ipaddr = net_dns_result_first(result); + switch (ipaddr->af) + { + case AF_INET: + { + struct sockaddr_in* addr4 = (struct sockaddr_in*) &client->addr; + addr4->sin_family = AF_INET; + addr4->sin_port = htons(client->address.port); + memcpy(&addr4->sin_addr, &ipaddr->internal_ip_data.in, sizeof(struct in_addr)); + break; + } + + case AF_INET6: + { + struct sockaddr_in6* addr6 = (struct sockaddr_in6*) &client->addr; + addr6->sin6_family = AF_INET6; + addr6->sin6_port = htons(client->address.port); + memcpy(&addr6->sin6_addr, &ipaddr->internal_ip_data.in6, sizeof(struct in6_addr)); + break; + } + + default: + LOG_WARN("Unknown ipaddr!"); + } + + ADC_client_connect_internal(client); + return 1; +} + static int ADC_client_parse_address(struct ADC_client* client, const char* arg) { ADC_TRACE; + const char* hub_address = arg; char* split; int ssl = 0; - struct hostent* dns; - struct in_addr* addr; if (!arg) return 0; - client->hub_address = hub_strdup(arg); - /* Minimum length of a valid address */ if (strlen(arg) < 9) return 0; @@ -653,39 +721,33 @@ static int ADC_client_parse_address(struct ADC_client* client, const char* arg) if (!strncmp(arg, "adc://", 6)) { client->flags &= ~cflag_ssl; + client->address.protocol = ADC; } else if (!strncmp(arg, "adcs://", 7)) { client->flags |= cflag_ssl; ssl = 1; + client->address.protocol = ADCS; } else return 0; /* Split hostname and port (if possible) */ - split = strrchr(client->hub_address + 6 + ssl, ':'); + hub_address = arg + 6 + ssl; + split = strrchr(hub_address, ':'); if (split == 0 || strlen(split) < 2 || strlen(split) > 6) return 0; /* Ensure port number is valid */ - int port = strtol(split+1, NULL, 10); - if (port <= 0 || port > 65535) + client->address.port = strtol(split+1, NULL, 10); + if (client->address.port <= 0 || client->address.port > 65535) return 0; - split[0] = 0; + client->address.hostname = strndup(hub_address, &split[0] - &hub_address[0]); - /* Resolve IP address (FIXME: blocking call) */ - dns = gethostbyname(client->hub_address + 6 + ssl); - if (dns) - { - addr = (struct in_addr*) dns->h_addr_list[0]; - } - - // Initialize the sockaddr struct. - memset(&client->addr, 0, sizeof(client->addr)); - client->addr.sin_family = AF_INET; - client->addr.sin_port = htons(port); - memcpy(&client->addr.sin_addr, addr, sizeof(struct in_addr)); + client->callback(client, ADC_CLIENT_NAME_LOOKUP, 0); + ADC_client_set_state(client, ps_dns); + client->dns_job = net_dns_gethostbyname(client->address.hostname, AF_UNSPEC, ADC_client_dns_callback, client); return 1; } diff --git a/src/tools/adcclient.h b/src/tools/adcclient.h index 17a07a6..47c067f 100644 --- a/src/tools/adcclient.h +++ b/src/tools/adcclient.h @@ -28,6 +28,7 @@ struct ADC_client; enum ADC_client_callback_type { + ADC_CLIENT_NAME_LOOKUP = 1000, ADC_CLIENT_CONNECTING = 1001, ADC_CLIENT_CONNECTED = 1002, ADC_CLIENT_DISCONNECTED = 1003, diff --git a/src/tools/admin.c b/src/tools/admin.c index 2c2ff05..0464dcb 100644 --- a/src/tools/admin.c +++ b/src/tools/admin.c @@ -91,6 +91,10 @@ static int handle(struct ADC_client* client, enum ADC_client_callback_type type, { switch (type) { + case ADC_CLIENT_NAME_LOOKUP: + status("Looking up hostname..."); + break; + case ADC_CLIENT_CONNECTING: status("Connecting..."); break; @@ -107,6 +111,9 @@ static int handle(struct ADC_client* client, enum ADC_client_callback_type type, status("SSL handshake."); break; + case ADC_CLIENT_SSL_OK: + break; + case ADC_CLIENT_LOGGING_IN: status("Logging in..."); break; From 168fc5bfccfb7e9d81dfaed8accd2b9b099d5fa5 Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Thu, 25 Oct 2012 00:39:44 +0200 Subject: [PATCH 3/6] Abstracted the threading code so that it works with Winthreads and pthreads. --- src/system.h | 1 + src/uhub.h | 1 + src/util/threads.c | 141 +++++++++++++++++++++++++++++++++++++++++++++ src/util/threads.h | 49 ++++++++++++++++ 4 files changed, 192 insertions(+) create mode 100644 src/util/threads.c create mode 100644 src/util/threads.h diff --git a/src/system.h b/src/system.h index e377524..98b1d85 100644 --- a/src/system.h +++ b/src/system.h @@ -34,6 +34,7 @@ #ifndef WINSOCK #define WINSOCK #endif +#define WINTHREAD_SUPPORT 1 #endif #if defined(__CYGWIN__) || defined(__MINGW32__) diff --git a/src/uhub.h b/src/uhub.h index ad29c3a..4ba9672 100644 --- a/src/uhub.h +++ b/src/uhub.h @@ -68,6 +68,7 @@ extern "C" { #include "util/memory.h" #include "util/misc.h" #include "util/tiger.h" +#include "util/threads.h" #include "adc/sid.h" #include "adc/message.h" diff --git a/src/util/threads.c b/src/util/threads.c new file mode 100644 index 0000000..814037f --- /dev/null +++ b/src/util/threads.c @@ -0,0 +1,141 @@ +/* + * uhub - A tiny ADC p2p connection hub + * Copyright (C) 2007-2012, Jan Vidar Krey + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "uhub.h" + +#ifdef POSIX_THREAD_SUPPORT +void uhub_mutex_init(uhub_mutex_t* mutex) +{ + pthread_mutex_init(mutex, NULL); +} + +void uhub_mutex_destroy(uhub_mutex_t* mutex) +{ + pthread_mutex_destroy(mutex); +} + +void uhub_mutex_lock(uhub_mutex_t* mutex) +{ + pthread_mutex_lock(mutex); +} + +void uhub_mutex_unlock(uhub_mutex_t* mutex) +{ + pthread_mutex_unlock(mutex); +} + +int uhub_mutex_trylock(uhub_mutex_t* mutex) +{ + int ret = pthread_mutex_trylock(mutex); + return (ret == 0); +} + +uhub_thread_t* uhub_thread_create(uhub_thread_start start, void* arg) +{ + uhub_thread_t* thread = (uhub_thread_t*) hub_malloc_zero(sizeof(uhub_thread_t)); + int ret = pthread_create(thread, NULL, start, arg); + if (ret == 0) + return thread; + hub_free(thread); + return NULL; +} + +void uhub_thread_cancel(uhub_thread_t* thread) +{ + pthread_cancel(thread); +} + +void* uhub_thread_join(uhub_thread_t* thread) +{ + void* ret = NULL; + pthread_join(thread, &ret); + hub_free(thread); + return ret; +} + + +#endif /* POSIX_THREAD_SUPPORT */ + +#ifdef WINTHREAD_SUPPORT + +struct winthread_data +{ + uhub_thread_t* handle; + uhub_thread_start start; + void* arg; +}; + +static DWORD WINAPI uhub_winthread_start(void* ptr) +{ + struct winthread_data* data = (struct winthread_data*) ptr; + DWORD ret = (DWORD) data->start(data->arg); + return ret; +} + +void uhub_mutex_init(uhub_mutex_t* mutex) +{ + InitializeCriticalSection(mutex); +} + +void uhub_mutex_destroy(uhub_mutex_t* mutex) +{ + DeleteCriticalSection(mutex); +} + +void uhub_mutex_lock(uhub_mutex_t* mutex) +{ + EnterCriticalSection(mutex); +} + +void uhub_mutex_unlock(uhub_mutex_t* mutex) +{ + LeaveCriticalSection(mutex); +} + +int uhub_mutex_trylock(uhub_mutex_t* mutex) +{ + return TryEnterCriticalSection(mutex); +} + +uhub_thread_t* uhub_thread_create(uhub_thread_start start, void* arg) +{ + struct winthread_data* thread = (struct winthread_data*) hub_malloc_zero(sizeof(struct winthread_data)); + thread->start = start; + thread->arg = arg; + thread->handle = CreateThread(NULL, 0, uhub_winthread_start, thread, 0, 0); + return thread; +} + +void uhub_thread_cancel(uhub_thread_t* thread) +{ + TerminateThread(thread->handle, 0); +} + +void* uhub_thread_join(uhub_thread_t* thread) +{ + void* ret = NULL; + DWORD exitCode; + WaitForSingleObject(thread->handle, INFINITE); + GetExitCodeThread(thread->handle, &exitCode); + ret = &exitCode; + CloseHandle(thread->handle); + hub_free(thread); + return ret; +} +#endif /* WINTHREAD_SUPPORT */ diff --git a/src/util/threads.h b/src/util/threads.h new file mode 100644 index 0000000..20d2186 --- /dev/null +++ b/src/util/threads.h @@ -0,0 +1,49 @@ +/* + * uhub - A tiny ADC p2p connection hub + * Copyright (C) 2007-2012, Jan Vidar Krey + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#ifndef HAVE_UHUB_UTIL_THREADS_H +#define HAVE_UHUB_UTIL_THREADS_H + +typedef void*(*uhub_thread_start)(void*) ; + +#ifdef POSIX_THREADS_SUPPORT +typedef pthread_t uhub_thread_t; +typedef pthread_mutex_t uhub_mutex_t; +#endif + +#ifdef WINTHREAD_SUPPORT +struct winthread_data; +typedef struct winthread_data uhub_thread_t; +typedef CRITICAL_SECTION uhub_mutex_t; +#endif + +// Mutexes +extern void uhub_mutex_init(uhub_mutex_t* mutex); +extern void uhub_mutex_destroy(uhub_mutex_t* mutex); +extern void uhub_mutex_lock(uhub_mutex_t* mutex); +extern void uhub_mutex_unlock(uhub_mutex_t* mutex); +extern int uhub_mutex_trylock(uhub_mutex_t* mutex); + +// Threads +uhub_thread_t* uhub_thread_create(uhub_thread_start start, void* arg); +void uhub_thread_cancel(uhub_thread_t* thread); +void* uhub_thread_join(uhub_thread_t* thread); + +#endif /* HAVE_UHUB_UTIL_THREADS_H */ + From 470c936e63a8ff7abd8d0da591a5ab56070ee5f2 Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Thu, 25 Oct 2012 00:40:16 +0200 Subject: [PATCH 4/6] Converted the DNS resolver to work with the new threading API abstraction. --- src/network/dnsresolver.c | 75 +++++++++++++++------------------------ 1 file changed, 28 insertions(+), 47 deletions(-) diff --git a/src/network/dnsresolver.c b/src/network/dnsresolver.c index cbd0091..1d5c597 100644 --- a/src/network/dnsresolver.c +++ b/src/network/dnsresolver.c @@ -19,7 +19,7 @@ #include "uhub.h" -#define DEBUG_LOOKUP_TIME 1 +// #define DEBUG_LOOKUP_TIME 1 #define MAX_CONCURRENT_JOBS 25 static struct net_dns_job* find_and_remove_job(struct net_dns_job* job); @@ -38,9 +38,7 @@ struct net_dns_job struct timeval time_finish; #endif -#ifdef POSIX_THREAD_SUPPORT - pthread_t thread_handle; -#endif + uhub_thread_t* thread_handle; }; struct net_dns_result @@ -64,9 +62,7 @@ struct net_dns_subsystem { struct linked_list* jobs; // currently running jobs struct linked_list* results; // queue of results that are awaiting being delivered to callback. -#ifdef POSIX_THREAD_SUPPORT - pthread_mutex_t mutex; -#endif // POSIX_THREAD_SUPPORT + uhub_mutex_t mutex; }; static struct net_dns_subsystem* g_dns = NULL; @@ -77,43 +73,36 @@ void net_dns_initialize() g_dns = (struct net_dns_subsystem*) hub_malloc_zero(sizeof(struct net_dns_subsystem)); g_dns->jobs = list_create(); g_dns->results = list_create(); -#ifdef POSIX_THREAD_SUPPORT - pthread_mutex_init(&g_dns->mutex, NULL); -#endif + uhub_mutex_init(&g_dns->mutex); } void net_dns_destroy() { -#ifdef POSIX_THREAD_SUPPORT struct net_dns_job* job; - pthread_mutex_lock(&g_dns->mutex); + uhub_mutex_lock(&g_dns->mutex); LOG_TRACE("net_dns_destroy(): jobs=%d", (int) list_size(g_dns->jobs)); job = (struct net_dns_job*) list_get_first(g_dns->jobs); - pthread_mutex_unlock(&g_dns->mutex); + uhub_mutex_unlock(&g_dns->mutex); while (job) { net_dns_job_cancel(job); - pthread_mutex_lock(&g_dns->mutex); + uhub_mutex_lock(&g_dns->mutex); job = (struct net_dns_job*) list_get_first(g_dns->jobs); - pthread_mutex_unlock(&g_dns->mutex); + uhub_mutex_unlock(&g_dns->mutex); } -#endif } -#ifdef POSIX_THREAD_SUPPORT static void dummy_free(void* ptr) { } -#endif void net_dns_process() { -#ifdef POSIX_THREAD_SUPPORT struct net_dns_result* result; - pthread_mutex_lock(&g_dns->mutex); + uhub_mutex_lock(&g_dns->mutex); LOG_DUMP("net_dns_process(): jobs=%d, results=%d", (int) list_size(g_dns->jobs), (int) list_size(g_dns->results)); for (result = (struct net_dns_result*) list_get_first(g_dns->results); result; result = (struct net_dns_result*) list_get_next(g_dns->results)) @@ -126,7 +115,7 @@ void net_dns_process() #endif // wait for the work thread to finish - pthread_join(job->thread_handle, NULL); + uhub_thread_join(job->thread_handle); // callback - should we delete the data immediately? if (job->callback(job, result)) @@ -145,11 +134,9 @@ void net_dns_process() } list_clear(g_dns->results, &dummy_free); - pthread_mutex_unlock(&g_dns->mutex); -#endif // POSIX_THREAD_SUPPORT + uhub_mutex_unlock(&g_dns->mutex); } -#ifdef POSIX_THREAD_SUPPORT static void* job_thread_resolve_name(void* ptr) { struct net_dns_job* job = (struct net_dns_job*) ptr; @@ -203,14 +190,14 @@ static void* job_thread_resolve_name(void* ptr) gettimeofday(&job->time_finish, NULL); #endif - pthread_mutex_lock(&g_dns->mutex); + uhub_mutex_lock(&g_dns->mutex); list_remove(g_dns->jobs, job); list_append(g_dns->results, dns_results); - pthread_mutex_unlock(&g_dns->mutex); + uhub_mutex_unlock(&g_dns->mutex); return dns_results; } -#endif + extern struct net_dns_job* net_dns_gethostbyname(const char* host, int af, net_dns_job_cb callback, void* ptr) { @@ -225,12 +212,11 @@ extern struct net_dns_job* net_dns_gethostbyname(const char* host, int af, net_d #endif // FIXME - scheduling - what about a max number of threads? -#ifdef POSIX_THREAD_SUPPORT - pthread_mutex_lock(&g_dns->mutex); - int err = pthread_create(&job->thread_handle, NULL, job_thread_resolve_name, job); - if (err) + uhub_mutex_lock(&g_dns->mutex); + job->thread_handle = uhub_thread_create(job_thread_resolve_name, job); + if (!job->thread_handle) { - LOG_WARN("Unable to create thread: (%d) %s", err, strerror(err)); + LOG_WARN("Unable to create thread"); free_job(job); job = NULL; } @@ -238,8 +224,7 @@ extern struct net_dns_job* net_dns_gethostbyname(const char* host, int af, net_d { list_append(g_dns->jobs, job); } - pthread_mutex_unlock(&g_dns->mutex); -#endif + uhub_mutex_unlock(&g_dns->mutex); return job; } @@ -253,13 +238,12 @@ extern struct net_dns_job* net_dns_gethostbyaddr(struct ip_addr_encap* ipaddr, n job->callback = callback; job->ptr = ptr; -#ifdef POSIX_THREAD_SUPPORT + // if (pthread_create(&job->thread_handle, NULL, start_job, job)) // { // free_job(job); // return NULL; // } -#endif return job; } @@ -296,7 +280,6 @@ static struct net_dns_result* find_and_remove_result(struct net_dns_job* job) extern int net_dns_job_cancel(struct net_dns_job* job) { -#ifdef POSIX_THREAD_SUPPORT int retval = 0; struct net_dns_result* res; @@ -310,24 +293,23 @@ extern int net_dns_job_cancel(struct net_dns_job* job) * If the job is already finished, but the result has not been delivered, then this * deletes the result and the job. */ - pthread_mutex_lock(&g_dns->mutex); + uhub_mutex_lock(&g_dns->mutex); if (find_and_remove_job(job)) { // job still active - cancel it, then close it. - pthread_cancel(job->thread_handle); - pthread_join(job->thread_handle, NULL); + uhub_thread_cancel(job->thread_handle); + uhub_thread_join(job->thread_handle); free_job(job); retval = 1; } else if ((res = find_and_remove_result(job))) { // job already finished - close it. - pthread_join(job->thread_handle, NULL); + uhub_thread_join(job->thread_handle); net_dns_result_free(res); } - pthread_mutex_unlock(&g_dns->mutex); + uhub_mutex_unlock(&g_dns->mutex); return retval; -#endif } extern struct net_dns_result* net_dns_job_sync_wait(struct net_dns_job* job) @@ -337,16 +319,15 @@ extern struct net_dns_result* net_dns_job_sync_wait(struct net_dns_job* job) // Wait for job to finish (if not already) // This should make sure the job is removed from jobs and a result is // present in results. - pthread_join(job->thread_handle, NULL); + uhub_thread_join(job->thread_handle); // Remove the result in order to prevent the callback from being called. - pthread_mutex_lock(&g_dns->mutex); + uhub_mutex_lock(&g_dns->mutex); res = find_and_remove_result(job); uhub_assert(res != NULL); res->job = NULL; free_job(job); - pthread_mutex_unlock(&g_dns->mutex); - + uhub_mutex_unlock(&g_dns->mutex); return res; } From 99a2307d1dd5268a11ad959292513d58b347a744 Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Thu, 25 Oct 2012 00:44:21 +0200 Subject: [PATCH 5/6] Simple compile fix. --- CMakeLists.txt | 2 +- src/util/threads.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d8ed68..01905d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,7 +110,7 @@ target_link_libraries(mod_chat_history utils) target_link_libraries(mod_chat_only utils) target_link_libraries(mod_logging utils) target_link_libraries(mod_topic utils) - +target_link_libraries(utils network) target_link_libraries(mod_welcome network) target_link_libraries(mod_logging network) diff --git a/src/util/threads.h b/src/util/threads.h index 20d2186..afc4359 100644 --- a/src/util/threads.h +++ b/src/util/threads.h @@ -22,7 +22,7 @@ typedef void*(*uhub_thread_start)(void*) ; -#ifdef POSIX_THREADS_SUPPORT +#ifdef POSIX_THREAD_SUPPORT typedef pthread_t uhub_thread_t; typedef pthread_mutex_t uhub_mutex_t; #endif From 2ec2e73f165dd147f99aa7aceef4a6e056557071 Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Thu, 25 Oct 2012 15:32:04 +0200 Subject: [PATCH 6/6] Make sure we always build the autotests. Caveat, need to run the update script manually after changing the tests (adding or removing tests). However, modifying existing tests does not require running the update script. Added a copy of exotic in the repository exotic automatically generates the skeleton code around the autotests in order to schedule the tests. --- CMakeLists.txt | 5 + autotest/exotic | 371 ++++++++++++++++ autotest/test.c | 1002 ++++++++++++++++++++++++++++++++++++++++++++ autotest/update.sh | 4 + 4 files changed, 1382 insertions(+) create mode 100755 autotest/exotic create mode 100644 autotest/test.c create mode 100755 autotest/update.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 01905d6..18c7807 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,6 +67,7 @@ add_dependencies(adc utils) add_dependencies(network utils) add_executable(uhub ${PROJECT_SOURCE_DIR}/core/main.c ${uhub_SOURCES} ) +add_executable(test ${CMAKE_SOURCE_DIR}/autotest/test.c ${uhub_SOURCES} ) add_library(mod_example MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_example.c) add_library(mod_welcome MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_welcome.c) @@ -88,6 +89,7 @@ endif() if(WIN32) target_link_libraries(uhub ws2_32) + target_link_libraries(test ws2_32) target_link_libraries(mod_logging ws2_32) target_link_libraries(mod_welcome ws2_32) endif() @@ -103,6 +105,7 @@ set_target_properties( PROPERTIES PREFIX "") target_link_libraries(uhub ${CMAKE_DL_LIBS} adc network utils) +target_link_libraries(test ${CMAKE_DL_LIBS} adc network utils) target_link_libraries(mod_example utils) target_link_libraries(mod_welcome utils) target_link_libraries(mod_auth_simple utils) @@ -119,6 +122,7 @@ if(UNIX) add_executable(uhub-admin ${PROJECT_SOURCE_DIR}/tools/admin.c) target_link_libraries(uhub-admin adcclient adc network utils pthread) target_link_libraries(uhub pthread) + target_link_libraries(test pthread) if (ADC_STRESS) add_executable(adcrush ${PROJECT_SOURCE_DIR}/tools/adcrush.c ${adcclient_SOURCES}) @@ -157,6 +161,7 @@ endif() if(SSL_SUPPORT) target_link_libraries(uhub ${SSL_LIBS}) + target_link_libraries(test ${SSL_LIBS}) if(UNIX) target_link_libraries(uhub-admin ${SSL_LIBS}) endif() diff --git a/autotest/exotic b/autotest/exotic new file mode 100755 index 0000000..d0338ef --- /dev/null +++ b/autotest/exotic @@ -0,0 +1,371 @@ +#!/usr/bin/perl -w +# exotic 0.4 +# Copyright (c) 2007-2012, Jan Vidar Krey + +use strict; + +my $program = $0; +my $file; +my $line; +my @tests; +my $found; +my $test; +my @files; + +if ($#ARGV == -1) +{ + die "Usage: $program files\n"; +} + +my $version = "0.4"; + +foreach my $arg (@ARGV) +{ + push(@files, $arg); +} + + +print "/* THIS FILE IS AUTOMATICALLY GENERATED BY EXOTIC - DO NOT EDIT THIS FILE! */\n"; +print "/* exotic/$version (Mon Nov 7 11:15:31 CET 2011) */\n\n"; + +print "#define __EXOTIC__STANDALONE__\n"; +standalone_include_exotic_h(); + +if ($#ARGV >= 0) +{ + foreach $file (@ARGV) + { + $found = 0; + open( FILE, "$file") || next; + my @data = ; + my $comment = 0; + + foreach $line (@data) { + chomp($line); + + if ($comment == 1) + { + if ($line =~ /^(.*\*\/)(.*)/) + { + $line = $2; + $comment = 0; + } + else + { + next; # ignore comment data + } + } + + if ($line =~ /^(.*)\/\*(.*)\*\/(.*)$/) + { + $line = $1 . " " . $3; # exclude comment stuff in between "/*" and "*/". + } + + if ($line =~ /^(.*)(\/\/.*)$/) { + $line = $1; # exclude stuff after "//" (FIXME: does not work if they are inside a string) + } + + if ($line =~ /\/\*/) { + $comment = 1; + next; + } + + if ($line =~ /^\s*EXO_TEST\(\s*(\w+)\s*,/) + { + $found++; + push(@tests, $1); + } + } + + if ($found > 0) { + print "#include \"" . $file . "\"\n"; + } + + close(FILE); + } + print "\n"; +} + +# Write a main() that will start the test run +print "int main(int argc, char** argv)\n{\n"; +print "\tstruct exotic_handle handle;\n\n"; +print "\tif (exotic_initialize(&handle, argc, argv) == -1)\n\t\treturn -1;\n\n"; + +if ($#tests > 0) +{ + print "\t/* Register the tests to be run */\n"; + foreach $test (@tests) + { + print "\texotic_add_test(&handle, &exotic_test_" . $test . ", \"" . $test . "\");\n"; + } +} +else +{ + print "\t/* No tests are found! */\n"; +} + +print "\n"; +print "\treturn exotic_run(&handle);\n"; +print "}\n\n"; + + +standalone_include_exotic_c(); + +sub standalone_include_exotic_h { +print ' +/* + * Exotic (EXtatic.Org Test InfrastuCture) + * Copyright (c) 2007, Jan Vidar Krey + */ + +#ifndef EXO_TEST +#define EXO_TEST(NAME, block) int exotic_test_ ## NAME (void) block +#endif + +#ifndef HAVE_EXOTIC_AUTOTEST_H +#define HAVE_EXOTIC_AUTOTEST_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int(*exo_test_t)(); + +enum exo_toggle { cfg_default, cfg_off, cfg_on }; + +struct exotic_handle +{ + enum exo_toggle config_show_summary; + enum exo_toggle config_show_pass; + enum exo_toggle config_show_fail; + unsigned int fail; + unsigned int pass; + struct exo_test_data* first; + struct exo_test_data* current; +}; + +extern int exotic_initialize(struct exotic_handle* handle, int argc, char** argv); +extern void exotic_add_test(struct exotic_handle* handle, exo_test_t, const char* name); +extern int exotic_run(struct exotic_handle* handle); + +#ifdef __cplusplus +} +#endif + +#endif /* HAVE_EXOTIC_AUTOTEST_H */ + +'; } +sub standalone_include_exotic_c { +print ' +/* + * Exotic - C/C++ source code testing + * Copyright (c) 2007, Jan Vidar Krey + */ + +#include +#include +#include +#include + +static void exotic_version(); + +#ifndef __EXOTIC__STANDALONE__ +#include "autotest.h" +static void exotic_version() +{ + printf("Extatic.org Test Infrastructure: exotic " "${version}" "\n\n"); + printf("Copyright (C) 2007 Jan Vidar Krey, janvidar@extatic.org\n"); + printf("This is free software with ABSOLUTELY NO WARRANTY.\n\n"); +} +#endif + +struct exo_test_data +{ + exo_test_t test; + char* name; + struct exo_test_data* next; +}; + + +static void exotic_summary(struct exotic_handle* handle) +{ + int total = handle->pass + handle->fail; + int pass_rate = total ? (100*handle->pass / total) : 0; + int fail_rate = total ? (100*handle->fail / total) : 0; + + printf("\n"); + printf("--------------------------------------------\n"); + printf("Results:\n"); + printf(" * Total tests run: %8d\n", total); + printf(" * Tests passed: %8d (~%d%%)\n", (int) handle->pass, pass_rate); + printf(" * Tests failed: %8d (~%d%%)\n", (int) handle->fail, fail_rate); + printf("--------------------------------------------\n"); +} + + +static void exotic_help(const char* program) +{ + printf("Usage: %s [OPTIONS]\n\n", program); + printf("Options:\n"); + printf(" --help -h Show this message\n"); + printf(" --version -v Show version\n"); + printf(" --summary -s show only summary)\n"); + printf(" --fail -f show only test failures\n"); + printf(" --pass -p show only test passes\n"); + printf("\nExamples:\n"); + printf(" %s -s -f\n\n", program); +} + + +int exotic_initialize(struct exotic_handle* handle, int argc, char** argv) +{ + int n; + if (!handle || !argv) return -1; + + memset(handle, 0, sizeof(struct exotic_handle)); + + for (n = 1; n < argc; n++) + { + if (!strcmp(argv[n], "-h") || !strcmp(argv[n], "--help")) + { + exotic_help(argv[0]); + exit(0); + } + + if (!strcmp(argv[n], "-v") || !strcmp(argv[n], "--version")) + { + exotic_version(); + exit(0); + } + + if (!strcmp(argv[n], "-s") || !strcmp(argv[n], "--summary")) + { + handle->config_show_summary = cfg_on; + continue; + } + + if (!strcmp(argv[n], "-f") || !strcmp(argv[n], "--fail")) + { + handle->config_show_fail = cfg_on; + continue; + } + + if (!strcmp(argv[n], "-p") || !strcmp(argv[n], "--pass")) + { + handle->config_show_pass = cfg_on; + continue; + } + + fprintf(stderr, "Unknown argument: %s\n\n", argv[n]); + exotic_help(argv[0]); + exit(0); + } + + if (handle->config_show_summary == cfg_on) + { + if (handle->config_show_pass == cfg_default) handle->config_show_pass = cfg_off; + if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; + + } + else if (handle->config_show_pass == cfg_on) + { + if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_off; + if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; + } + else if (handle->config_show_fail == cfg_on) + { + if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_off; + if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; + } + else + { + if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_on; + if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_on; + if (handle->config_show_pass == cfg_default) handle->config_show_pass = cfg_on; + } + return 0; +} + + +void exotic_add_test(struct exotic_handle* handle, exo_test_t func, const char* name) +{ + if (!handle) + { + fprintf(stderr, "exotic_add_test: failed, no handle!\n"); + exit(-1); + } + + struct exo_test_data* test = (struct exo_test_data*) malloc(sizeof(struct exo_test_data)); + if (!test) + { + fprintf(stderr, "exotic_add_test: out of memory!\n"); + exit(-1); + } + + /* Create the test */ + memset(test, 0, sizeof(struct exo_test_data)); + test->test = func; + test->name = strdup(name); + + /* Register the test in the handle */ + if (!handle->first) + { + handle->first = test; + handle->current = test; + } + else + { + handle->current->next = test; + handle->current = test; + } +} + + +int exotic_run(struct exotic_handle* handle) +{ + struct exo_test_data* tmp = NULL; + + if (!handle) + { + fprintf(stderr, "Error: exotic is not initialized\n"); + return -1; + } + + handle->current = handle->first; + while (handle->current) + { + tmp = handle->current; + + if (handle->current->test()) { + if (handle->config_show_pass == cfg_on) printf("* PASS test \'%s\'\n", tmp->name); + handle->pass++; + } else { + if (handle->config_show_fail == cfg_on) printf("* FAIL test \'%s\'\n", tmp->name); + handle->fail++; + } + + handle->current = handle->current->next; + + free(tmp->name); + free(tmp); + } + + if (!handle->first) + { + printf("(No tests added)\n"); + } + + if (handle->config_show_summary == cfg_on) + exotic_summary(handle); + + return (handle->fail) ? handle->fail : 0; +} + + +static void exotic_version() { + printf("exotic 0.4-standalone\n\n"); + printf("Copyright (C) 2007 Jan Vidar Krey, janvidar@extatic.org\n"); + printf("This is free software with ABSOLUTELY NO WARRANTY.\n\n"); +} +'; } + diff --git a/autotest/test.c b/autotest/test.c new file mode 100644 index 0000000..cb3142d --- /dev/null +++ b/autotest/test.c @@ -0,0 +1,1002 @@ +/* THIS FILE IS AUTOMATICALLY GENERATED BY EXOTIC - DO NOT EDIT THIS FILE! */ +/* exotic/0.4 (Mon Nov 7 11:15:31 CET 2011) */ + +#define __EXOTIC__STANDALONE__ + +/* + * Exotic (EXtatic.Org Test InfrastuCture) + * Copyright (c) 2007, Jan Vidar Krey + */ + +#ifndef EXO_TEST +#define EXO_TEST(NAME, block) int exotic_test_ ## NAME (void) block +#endif + +#ifndef HAVE_EXOTIC_AUTOTEST_H +#define HAVE_EXOTIC_AUTOTEST_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int(*exo_test_t)(); + +enum exo_toggle { cfg_default, cfg_off, cfg_on }; + +struct exotic_handle +{ + enum exo_toggle config_show_summary; + enum exo_toggle config_show_pass; + enum exo_toggle config_show_fail; + unsigned int fail; + unsigned int pass; + struct exo_test_data* first; + struct exo_test_data* current; +}; + +extern int exotic_initialize(struct exotic_handle* handle, int argc, char** argv); +extern void exotic_add_test(struct exotic_handle* handle, exo_test_t, const char* name); +extern int exotic_run(struct exotic_handle* handle); + +#ifdef __cplusplus +} +#endif + +#endif /* HAVE_EXOTIC_AUTOTEST_H */ + +#include "test_commands.tcc" +#include "test_credentials.tcc" +#include "test_eventqueue.tcc" +#include "test_hub.tcc" +#include "test_inf.tcc" +#include "test_ipfilter.tcc" +#include "test_list.tcc" +#include "test_memory.tcc" +#include "test_message.tcc" +#include "test_misc.tcc" +#include "test_sid.tcc" +#include "test_tiger.tcc" +#include "test_timer.tcc" +#include "test_tokenizer.tcc" +#include "test_usermanager.tcc" + +int main(int argc, char** argv) +{ + struct exotic_handle handle; + + if (exotic_initialize(&handle, argc, argv) == -1) + return -1; + + /* Register the tests to be run */ + exotic_add_test(&handle, &exotic_test_setup, "setup"); + exotic_add_test(&handle, &exotic_test_command_setup_user, "command_setup_user"); + exotic_add_test(&handle, &exotic_test_command_create, "command_create"); + exotic_add_test(&handle, &exotic_test_command_access_1, "command_access_1"); + exotic_add_test(&handle, &exotic_test_command_access_2, "command_access_2"); + exotic_add_test(&handle, &exotic_test_command_access_3, "command_access_3"); + exotic_add_test(&handle, &exotic_test_command_syntax_1, "command_syntax_1"); + exotic_add_test(&handle, &exotic_test_command_syntax_2, "command_syntax_2"); + exotic_add_test(&handle, &exotic_test_command_missing_args_1, "command_missing_args_1"); + exotic_add_test(&handle, &exotic_test_command_missing_args_2, "command_missing_args_2"); + exotic_add_test(&handle, &exotic_test_command_missing_args_3, "command_missing_args_3"); + exotic_add_test(&handle, &exotic_test_command_number_1, "command_number_1"); + exotic_add_test(&handle, &exotic_test_command_number_2, "command_number_2"); + exotic_add_test(&handle, &exotic_test_command_number_3, "command_number_3"); + exotic_add_test(&handle, &exotic_test_command_user_1, "command_user_1"); + exotic_add_test(&handle, &exotic_test_command_user_2, "command_user_2"); + exotic_add_test(&handle, &exotic_test_command_user_3, "command_user_3"); + exotic_add_test(&handle, &exotic_test_command_user_4, "command_user_4"); + exotic_add_test(&handle, &exotic_test_command_user_5, "command_user_5"); + exotic_add_test(&handle, &exotic_test_command_command_1, "command_command_1"); + exotic_add_test(&handle, &exotic_test_command_command_2, "command_command_2"); + exotic_add_test(&handle, &exotic_test_command_command_3, "command_command_3"); + exotic_add_test(&handle, &exotic_test_command_command_4, "command_command_4"); + exotic_add_test(&handle, &exotic_test_command_command_5, "command_command_5"); + exotic_add_test(&handle, &exotic_test_command_command_6, "command_command_6"); + exotic_add_test(&handle, &exotic_test_command_command_7, "command_command_7"); + exotic_add_test(&handle, &exotic_test_command_command_8, "command_command_8"); + exotic_add_test(&handle, &exotic_test_command_cred_1, "command_cred_1"); + exotic_add_test(&handle, &exotic_test_command_cred_2, "command_cred_2"); + exotic_add_test(&handle, &exotic_test_command_cred_3, "command_cred_3"); + exotic_add_test(&handle, &exotic_test_command_cred_4, "command_cred_4"); + exotic_add_test(&handle, &exotic_test_command_cred_5, "command_cred_5"); + exotic_add_test(&handle, &exotic_test_command_cred_6, "command_cred_6"); + exotic_add_test(&handle, &exotic_test_command_cred_7, "command_cred_7"); + exotic_add_test(&handle, &exotic_test_command_cred_8, "command_cred_8"); + exotic_add_test(&handle, &exotic_test_command_parse_3, "command_parse_3"); + exotic_add_test(&handle, &exotic_test_command_parse_4, "command_parse_4"); + exotic_add_test(&handle, &exotic_test_command_argument_integer_1, "command_argument_integer_1"); + exotic_add_test(&handle, &exotic_test_command_argument_integer_2, "command_argument_integer_2"); + exotic_add_test(&handle, &exotic_test_command_argument_integer_3, "command_argument_integer_3"); + exotic_add_test(&handle, &exotic_test_command_argument_user_1, "command_argument_user_1"); + exotic_add_test(&handle, &exotic_test_command_argument_cid_1, "command_argument_cid_1"); + exotic_add_test(&handle, &exotic_test_command_argument_cred_1, "command_argument_cred_1"); + exotic_add_test(&handle, &exotic_test_command_argument_cred_2, "command_argument_cred_2"); + exotic_add_test(&handle, &exotic_test_command_argument_cred_3, "command_argument_cred_3"); + exotic_add_test(&handle, &exotic_test_command_argument_cred_4, "command_argument_cred_4"); + exotic_add_test(&handle, &exotic_test_command_argument_cred_5, "command_argument_cred_5"); + exotic_add_test(&handle, &exotic_test_command_argument_cred_6, "command_argument_cred_6"); + exotic_add_test(&handle, &exotic_test_command_user_destroy, "command_user_destroy"); + exotic_add_test(&handle, &exotic_test_command_destroy, "command_destroy"); + exotic_add_test(&handle, &exotic_test_cleanup, "cleanup"); + exotic_add_test(&handle, &exotic_test_cred_to_string_1, "cred_to_string_1"); + exotic_add_test(&handle, &exotic_test_cred_to_string_2, "cred_to_string_2"); + exotic_add_test(&handle, &exotic_test_cred_to_string_3, "cred_to_string_3"); + exotic_add_test(&handle, &exotic_test_cred_to_string_4, "cred_to_string_4"); + exotic_add_test(&handle, &exotic_test_cred_to_string_5, "cred_to_string_5"); + exotic_add_test(&handle, &exotic_test_cred_to_string_6, "cred_to_string_6"); + exotic_add_test(&handle, &exotic_test_cred_to_string_7, "cred_to_string_7"); + exotic_add_test(&handle, &exotic_test_cred_to_string_8, "cred_to_string_8"); + exotic_add_test(&handle, &exotic_test_cred_from_string_1, "cred_from_string_1"); + exotic_add_test(&handle, &exotic_test_cred_from_string_2, "cred_from_string_2"); + exotic_add_test(&handle, &exotic_test_cred_from_string_3, "cred_from_string_3"); + exotic_add_test(&handle, &exotic_test_cred_from_string_4, "cred_from_string_4"); + exotic_add_test(&handle, &exotic_test_cred_from_string_5, "cred_from_string_5"); + exotic_add_test(&handle, &exotic_test_cred_from_string_6, "cred_from_string_6"); + exotic_add_test(&handle, &exotic_test_cred_from_string_7, "cred_from_string_7"); + exotic_add_test(&handle, &exotic_test_cred_from_string_8, "cred_from_string_8"); + exotic_add_test(&handle, &exotic_test_cred_from_string_9, "cred_from_string_9"); + exotic_add_test(&handle, &exotic_test_cred_from_string_10, "cred_from_string_10"); + exotic_add_test(&handle, &exotic_test_eventqueue_init_1, "eventqueue_init_1"); + exotic_add_test(&handle, &exotic_test_eventqueue_init_2, "eventqueue_init_2"); + exotic_add_test(&handle, &exotic_test_eventqueue_post_1, "eventqueue_post_1"); + exotic_add_test(&handle, &exotic_test_eventqueue_process_1, "eventqueue_process_1"); + exotic_add_test(&handle, &exotic_test_eventqueue_size_1, "eventqueue_size_1"); + exotic_add_test(&handle, &exotic_test_eventqueue_post_2, "eventqueue_post_2"); + exotic_add_test(&handle, &exotic_test_eventqueue_size_2, "eventqueue_size_2"); + exotic_add_test(&handle, &exotic_test_eventqueue_post_3, "eventqueue_post_3"); + exotic_add_test(&handle, &exotic_test_eventqueue_size_3, "eventqueue_size_3"); + exotic_add_test(&handle, &exotic_test_eventqueue_process_2, "eventqueue_process_2"); + exotic_add_test(&handle, &exotic_test_eventqueue_size_4, "eventqueue_size_4"); + exotic_add_test(&handle, &exotic_test_eventqueue_shutdown_1, "eventqueue_shutdown_1"); + exotic_add_test(&handle, &exotic_test_hub_net_startup, "hub_net_startup"); + exotic_add_test(&handle, &exotic_test_hub_config_initialize, "hub_config_initialize"); + exotic_add_test(&handle, &exotic_test_hub_acl_initialize, "hub_acl_initialize"); + exotic_add_test(&handle, &exotic_test_hub_service_initialize, "hub_service_initialize"); + exotic_add_test(&handle, &exotic_test_hub_variables_startup, "hub_variables_startup"); + exotic_add_test(&handle, &exotic_test_hub_variables_shutdown, "hub_variables_shutdown"); + exotic_add_test(&handle, &exotic_test_hub_acl_shutdown, "hub_acl_shutdown"); + exotic_add_test(&handle, &exotic_test_hub_config_shutdown, "hub_config_shutdown"); + exotic_add_test(&handle, &exotic_test_hub_service_shutdown, "hub_service_shutdown"); + exotic_add_test(&handle, &exotic_test_hub_net_shutdown, "hub_net_shutdown"); + exotic_add_test(&handle, &exotic_test_inf_create_setup, "inf_create_setup"); + exotic_add_test(&handle, &exotic_test_inf_ok_1, "inf_ok_1"); + exotic_add_test(&handle, &exotic_test_inf_cid_1, "inf_cid_1"); + exotic_add_test(&handle, &exotic_test_inf_cid_2, "inf_cid_2"); + exotic_add_test(&handle, &exotic_test_inf_cid_3, "inf_cid_3"); + exotic_add_test(&handle, &exotic_test_inf_cid_4, "inf_cid_4"); + exotic_add_test(&handle, &exotic_test_inf_cid_5, "inf_cid_5"); + exotic_add_test(&handle, &exotic_test_inf_cid_6, "inf_cid_6"); + exotic_add_test(&handle, &exotic_test_inf_cid_7, "inf_cid_7"); + exotic_add_test(&handle, &exotic_test_inf_cid_8, "inf_cid_8"); + exotic_add_test(&handle, &exotic_test_inf_cid_9, "inf_cid_9"); + exotic_add_test(&handle, &exotic_test_inf_pid_1, "inf_pid_1"); + exotic_add_test(&handle, &exotic_test_inf_pid_2, "inf_pid_2"); + exotic_add_test(&handle, &exotic_test_inf_pid_3, "inf_pid_3"); + exotic_add_test(&handle, &exotic_test_inf_pid_4, "inf_pid_4"); + exotic_add_test(&handle, &exotic_test_inf_pid_5, "inf_pid_5"); + exotic_add_test(&handle, &exotic_test_inf_pid_6, "inf_pid_6"); + exotic_add_test(&handle, &exotic_test_inf_pid_7, "inf_pid_7"); + exotic_add_test(&handle, &exotic_test_inf_pid_8, "inf_pid_8"); + exotic_add_test(&handle, &exotic_test_inf_pid_9, "inf_pid_9"); + exotic_add_test(&handle, &exotic_test_inf_nick_01, "inf_nick_01"); + exotic_add_test(&handle, &exotic_test_inf_nick_02, "inf_nick_02"); + exotic_add_test(&handle, &exotic_test_inf_nick_03, "inf_nick_03"); + exotic_add_test(&handle, &exotic_test_inf_nick_04, "inf_nick_04"); + exotic_add_test(&handle, &exotic_test_inf_nick_05, "inf_nick_05"); + exotic_add_test(&handle, &exotic_test_inf_nick_06, "inf_nick_06"); + exotic_add_test(&handle, &exotic_test_inf_nick_07, "inf_nick_07"); + exotic_add_test(&handle, &exotic_test_inf_nick_08, "inf_nick_08"); + exotic_add_test(&handle, &exotic_test_inf_nick_09, "inf_nick_09"); + exotic_add_test(&handle, &exotic_test_inf_nick_10, "inf_nick_10"); + exotic_add_test(&handle, &exotic_test_inf_limits_1, "inf_limits_1"); + exotic_add_test(&handle, &exotic_test_inf_limits_2, "inf_limits_2"); + exotic_add_test(&handle, &exotic_test_inf_limits_3, "inf_limits_3"); + exotic_add_test(&handle, &exotic_test_inf_limits_4, "inf_limits_4"); + exotic_add_test(&handle, &exotic_test_inf_limit_hubs_setup, "inf_limit_hubs_setup"); + exotic_add_test(&handle, &exotic_test_inf_limit_hubs_1, "inf_limit_hubs_1"); + exotic_add_test(&handle, &exotic_test_inf_limit_hubs_2, "inf_limit_hubs_2"); + exotic_add_test(&handle, &exotic_test_inf_limit_hubs_3, "inf_limit_hubs_3"); + exotic_add_test(&handle, &exotic_test_inf_limit_hubs_4, "inf_limit_hubs_4"); + exotic_add_test(&handle, &exotic_test_inf_limit_hubs_5, "inf_limit_hubs_5"); + exotic_add_test(&handle, &exotic_test_inf_limit_hubs_6, "inf_limit_hubs_6"); + exotic_add_test(&handle, &exotic_test_inf_limit_hubs_7, "inf_limit_hubs_7"); + exotic_add_test(&handle, &exotic_test_inf_destroy_setup, "inf_destroy_setup"); + exotic_add_test(&handle, &exotic_test_prepare_network, "prepare_network"); + exotic_add_test(&handle, &exotic_test_check_ipv6, "check_ipv6"); + exotic_add_test(&handle, &exotic_test_create_addresses_1, "create_addresses_1"); + exotic_add_test(&handle, &exotic_test_create_addresses_2, "create_addresses_2"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_1, "ip_is_valid_ipv4_1"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_2, "ip_is_valid_ipv4_2"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_3, "ip_is_valid_ipv4_3"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_4, "ip_is_valid_ipv4_4"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_5, "ip_is_valid_ipv4_5"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_6, "ip_is_valid_ipv4_6"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_7, "ip_is_valid_ipv4_7"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_8, "ip_is_valid_ipv4_8"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_9, "ip_is_valid_ipv4_9"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv6_1, "ip_is_valid_ipv6_1"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv6_2, "ip_is_valid_ipv6_2"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv6_3, "ip_is_valid_ipv6_3"); + exotic_add_test(&handle, &exotic_test_ip4_compare_1, "ip4_compare_1"); + exotic_add_test(&handle, &exotic_test_ip4_compare_2, "ip4_compare_2"); + exotic_add_test(&handle, &exotic_test_ip4_compare_3, "ip4_compare_3"); + exotic_add_test(&handle, &exotic_test_ip4_compare_4, "ip4_compare_4"); + exotic_add_test(&handle, &exotic_test_ip4_compare_5, "ip4_compare_5"); + exotic_add_test(&handle, &exotic_test_ip4_compare_6, "ip4_compare_6"); + exotic_add_test(&handle, &exotic_test_ip6_compare_1, "ip6_compare_1"); + exotic_add_test(&handle, &exotic_test_ip6_compare_2, "ip6_compare_2"); + exotic_add_test(&handle, &exotic_test_ip6_compare_3, "ip6_compare_3"); + exotic_add_test(&handle, &exotic_test_ip6_compare_4, "ip6_compare_4"); + exotic_add_test(&handle, &exotic_test_ip6_compare_5, "ip6_compare_5"); + exotic_add_test(&handle, &exotic_test_ip6_compare_6, "ip6_compare_6"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_0, "ipv4_lmask_create_0"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_1, "ipv4_lmask_create_1"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_2, "ipv4_lmask_create_2"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_3, "ipv4_lmask_create_3"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_4, "ipv4_lmask_create_4"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_5, "ipv4_lmask_create_5"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_6, "ipv4_lmask_create_6"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_7, "ipv4_lmask_create_7"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_8, "ipv4_lmask_create_8"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_9, "ipv4_lmask_create_9"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_10, "ipv4_lmask_create_10"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_11, "ipv4_lmask_create_11"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_12, "ipv4_lmask_create_12"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_13, "ipv4_lmask_create_13"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_14, "ipv4_lmask_create_14"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_15, "ipv4_lmask_create_15"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_16, "ipv4_lmask_create_16"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_17, "ipv4_lmask_create_17"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_18, "ipv4_lmask_create_18"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_19, "ipv4_lmask_create_19"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_20, "ipv4_lmask_create_20"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_21, "ipv4_lmask_create_21"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_22, "ipv4_lmask_create_22"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_23, "ipv4_lmask_create_23"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_24, "ipv4_lmask_create_24"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_25, "ipv4_lmask_create_25"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_26, "ipv4_lmask_create_26"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_27, "ipv4_lmask_create_27"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_28, "ipv4_lmask_create_28"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_29, "ipv4_lmask_create_29"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_30, "ipv4_lmask_create_30"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_31, "ipv4_lmask_create_31"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_32, "ipv4_lmask_create_32"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_0, "ipv4_rmask_create_0"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_1, "ipv4_rmask_create_1"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_2, "ipv4_rmask_create_2"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_3, "ipv4_rmask_create_3"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_4, "ipv4_rmask_create_4"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_5, "ipv4_rmask_create_5"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_6, "ipv4_rmask_create_6"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_7, "ipv4_rmask_create_7"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_8, "ipv4_rmask_create_8"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_9, "ipv4_rmask_create_9"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_10, "ipv4_rmask_create_10"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_11, "ipv4_rmask_create_11"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_12, "ipv4_rmask_create_12"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_13, "ipv4_rmask_create_13"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_14, "ipv4_rmask_create_14"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_15, "ipv4_rmask_create_15"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_16, "ipv4_rmask_create_16"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_17, "ipv4_rmask_create_17"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_18, "ipv4_rmask_create_18"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_19, "ipv4_rmask_create_19"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_20, "ipv4_rmask_create_20"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_21, "ipv4_rmask_create_21"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_22, "ipv4_rmask_create_22"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_23, "ipv4_rmask_create_23"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_24, "ipv4_rmask_create_24"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_25, "ipv4_rmask_create_25"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_26, "ipv4_rmask_create_26"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_27, "ipv4_rmask_create_27"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_28, "ipv4_rmask_create_28"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_29, "ipv4_rmask_create_29"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_30, "ipv4_rmask_create_30"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_31, "ipv4_rmask_create_31"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_32, "ipv4_rmask_create_32"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_0, "ip6_lmask_create_0"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_1, "ip6_lmask_create_1"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_2, "ip6_lmask_create_2"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_3, "ip6_lmask_create_3"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_4, "ip6_lmask_create_4"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_5, "ip6_lmask_create_5"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_6, "ip6_lmask_create_6"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_7, "ip6_lmask_create_7"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_8, "ip6_lmask_create_8"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_9, "ip6_lmask_create_9"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_10, "ip6_lmask_create_10"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_11, "ip6_lmask_create_11"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_12, "ip6_lmask_create_12"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_13, "ip6_lmask_create_13"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_14, "ip6_lmask_create_14"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_15, "ip6_lmask_create_15"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_16, "ip6_lmask_create_16"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_17, "ip6_lmask_create_17"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_18, "ip6_lmask_create_18"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_19, "ip6_lmask_create_19"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_20, "ip6_lmask_create_20"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_21, "ip6_lmask_create_21"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_22, "ip6_lmask_create_22"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_23, "ip6_lmask_create_23"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_24, "ip6_lmask_create_24"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_25, "ip6_lmask_create_25"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_26, "ip6_lmask_create_26"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_27, "ip6_lmask_create_27"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_28, "ip6_lmask_create_28"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_29, "ip6_lmask_create_29"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_30, "ip6_lmask_create_30"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_31, "ip6_lmask_create_31"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_32, "ip6_lmask_create_32"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_33, "ip6_lmask_create_33"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_34, "ip6_lmask_create_34"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_35, "ip6_lmask_create_35"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_36, "ip6_lmask_create_36"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_37, "ip6_lmask_create_37"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_38, "ip6_lmask_create_38"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_39, "ip6_lmask_create_39"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_40, "ip6_lmask_create_40"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_41, "ip6_lmask_create_41"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_42, "ip6_lmask_create_42"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_43, "ip6_lmask_create_43"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_44, "ip6_lmask_create_44"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_45, "ip6_lmask_create_45"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_46, "ip6_lmask_create_46"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_47, "ip6_lmask_create_47"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_48, "ip6_lmask_create_48"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_49, "ip6_lmask_create_49"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_50, "ip6_lmask_create_50"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_51, "ip6_lmask_create_51"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_52, "ip6_lmask_create_52"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_53, "ip6_lmask_create_53"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_54, "ip6_lmask_create_54"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_55, "ip6_lmask_create_55"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_56, "ip6_lmask_create_56"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_57, "ip6_lmask_create_57"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_58, "ip6_lmask_create_58"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_59, "ip6_lmask_create_59"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_60, "ip6_lmask_create_60"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_61, "ip6_lmask_create_61"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_62, "ip6_lmask_create_62"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_63, "ip6_lmask_create_63"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_64, "ip6_lmask_create_64"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_65, "ip6_lmask_create_65"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_66, "ip6_lmask_create_66"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_67, "ip6_lmask_create_67"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_68, "ip6_lmask_create_68"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_69, "ip6_lmask_create_69"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_70, "ip6_lmask_create_70"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_71, "ip6_lmask_create_71"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_72, "ip6_lmask_create_72"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_73, "ip6_lmask_create_73"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_74, "ip6_lmask_create_74"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_75, "ip6_lmask_create_75"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_76, "ip6_lmask_create_76"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_77, "ip6_lmask_create_77"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_78, "ip6_lmask_create_78"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_79, "ip6_lmask_create_79"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_80, "ip6_lmask_create_80"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_81, "ip6_lmask_create_81"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_82, "ip6_lmask_create_82"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_83, "ip6_lmask_create_83"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_84, "ip6_lmask_create_84"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_85, "ip6_lmask_create_85"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_86, "ip6_lmask_create_86"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_87, "ip6_lmask_create_87"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_88, "ip6_lmask_create_88"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_89, "ip6_lmask_create_89"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_90, "ip6_lmask_create_90"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_91, "ip6_lmask_create_91"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_92, "ip6_lmask_create_92"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_93, "ip6_lmask_create_93"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_94, "ip6_lmask_create_94"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_95, "ip6_lmask_create_95"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_96, "ip6_lmask_create_96"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_97, "ip6_lmask_create_97"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_98, "ip6_lmask_create_98"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_99, "ip6_lmask_create_99"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_100, "ip6_lmask_create_100"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_101, "ip6_lmask_create_101"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_102, "ip6_lmask_create_102"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_103, "ip6_lmask_create_103"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_104, "ip6_lmask_create_104"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_105, "ip6_lmask_create_105"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_106, "ip6_lmask_create_106"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_107, "ip6_lmask_create_107"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_108, "ip6_lmask_create_108"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_109, "ip6_lmask_create_109"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_110, "ip6_lmask_create_110"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_111, "ip6_lmask_create_111"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_112, "ip6_lmask_create_112"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_113, "ip6_lmask_create_113"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_114, "ip6_lmask_create_114"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_115, "ip6_lmask_create_115"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_116, "ip6_lmask_create_116"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_117, "ip6_lmask_create_117"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_118, "ip6_lmask_create_118"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_119, "ip6_lmask_create_119"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_120, "ip6_lmask_create_120"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_121, "ip6_lmask_create_121"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_122, "ip6_lmask_create_122"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_123, "ip6_lmask_create_123"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_124, "ip6_lmask_create_124"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_125, "ip6_lmask_create_125"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_126, "ip6_lmask_create_126"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_127, "ip6_lmask_create_127"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_128, "ip6_lmask_create_128"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_0, "ip6_rmask_create_0"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_1, "ip6_rmask_create_1"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_2, "ip6_rmask_create_2"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_3, "ip6_rmask_create_3"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_4, "ip6_rmask_create_4"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_5, "ip6_rmask_create_5"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_6, "ip6_rmask_create_6"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_7, "ip6_rmask_create_7"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_8, "ip6_rmask_create_8"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_9, "ip6_rmask_create_9"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_10, "ip6_rmask_create_10"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_11, "ip6_rmask_create_11"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_12, "ip6_rmask_create_12"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_13, "ip6_rmask_create_13"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_14, "ip6_rmask_create_14"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_15, "ip6_rmask_create_15"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_16, "ip6_rmask_create_16"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_17, "ip6_rmask_create_17"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_18, "ip6_rmask_create_18"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_19, "ip6_rmask_create_19"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_20, "ip6_rmask_create_20"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_21, "ip6_rmask_create_21"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_22, "ip6_rmask_create_22"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_23, "ip6_rmask_create_23"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_24, "ip6_rmask_create_24"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_25, "ip6_rmask_create_25"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_26, "ip6_rmask_create_26"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_27, "ip6_rmask_create_27"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_28, "ip6_rmask_create_28"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_29, "ip6_rmask_create_29"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_30, "ip6_rmask_create_30"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_31, "ip6_rmask_create_31"); + exotic_add_test(&handle, &exotic_test_check_ban_setup_1, "check_ban_setup_1"); + exotic_add_test(&handle, &exotic_test_check_ban_ipv4_1, "check_ban_ipv4_1"); + exotic_add_test(&handle, &exotic_test_check_ban_ipv4_2, "check_ban_ipv4_2"); + exotic_add_test(&handle, &exotic_test_check_ban_ipv4_3, "check_ban_ipv4_3"); + exotic_add_test(&handle, &exotic_test_check_ban_ipv4_4, "check_ban_ipv4_4"); + exotic_add_test(&handle, &exotic_test_check_ban_ipv4_5, "check_ban_ipv4_5"); + exotic_add_test(&handle, &exotic_test_check_ban_ipv6_1, "check_ban_ipv6_1"); + exotic_add_test(&handle, &exotic_test_check_ban_ipv6_2, "check_ban_ipv6_2"); + exotic_add_test(&handle, &exotic_test_check_ban_ipv6_3, "check_ban_ipv6_3"); + exotic_add_test(&handle, &exotic_test_check_ban_ipv6_4, "check_ban_ipv6_4"); + exotic_add_test(&handle, &exotic_test_check_ban_ipv6_5, "check_ban_ipv6_5"); + exotic_add_test(&handle, &exotic_test_check_ban_ipv6_6, "check_ban_ipv6_6"); + exotic_add_test(&handle, &exotic_test_check_ban_afmix_1, "check_ban_afmix_1"); + exotic_add_test(&handle, &exotic_test_check_ban_afmix_2, "check_ban_afmix_2"); + exotic_add_test(&handle, &exotic_test_ip4_bitwise_AND_1, "ip4_bitwise_AND_1"); + exotic_add_test(&handle, &exotic_test_ip4_bitwise_AND_2, "ip4_bitwise_AND_2"); + exotic_add_test(&handle, &exotic_test_ip4_bitwise_AND_3, "ip4_bitwise_AND_3"); + exotic_add_test(&handle, &exotic_test_ip4_bitwise_AND_4, "ip4_bitwise_AND_4"); + exotic_add_test(&handle, &exotic_test_ip4_bitwise_AND_5, "ip4_bitwise_AND_5"); + exotic_add_test(&handle, &exotic_test_ip4_bitwise_OR_1, "ip4_bitwise_OR_1"); + exotic_add_test(&handle, &exotic_test_ip4_bitwise_OR_2, "ip4_bitwise_OR_2"); + exotic_add_test(&handle, &exotic_test_ip4_bitwise_OR_3, "ip4_bitwise_OR_3"); + exotic_add_test(&handle, &exotic_test_ip4_bitwise_OR_4, "ip4_bitwise_OR_4"); + exotic_add_test(&handle, &exotic_test_ip4_bitwise_OR_5, "ip4_bitwise_OR_5"); + exotic_add_test(&handle, &exotic_test_ip6_bitwise_AND_1, "ip6_bitwise_AND_1"); + exotic_add_test(&handle, &exotic_test_ip6_bitwise_AND_2, "ip6_bitwise_AND_2"); + exotic_add_test(&handle, &exotic_test_ip6_bitwise_AND_3, "ip6_bitwise_AND_3"); + exotic_add_test(&handle, &exotic_test_ip6_bitwise_OR_1, "ip6_bitwise_OR_1"); + exotic_add_test(&handle, &exotic_test_ip6_bitwise_OR_2, "ip6_bitwise_OR_2"); + exotic_add_test(&handle, &exotic_test_ip6_bitwise_OR_3, "ip6_bitwise_OR_3"); + exotic_add_test(&handle, &exotic_test_ip_range_1, "ip_range_1"); + exotic_add_test(&handle, &exotic_test_ip_range_2, "ip_range_2"); + exotic_add_test(&handle, &exotic_test_ip_range_3, "ip_range_3"); + exotic_add_test(&handle, &exotic_test_ip_range_4, "ip_range_4"); + exotic_add_test(&handle, &exotic_test_shutdown_network, "shutdown_network"); + exotic_add_test(&handle, &exotic_test_list_create_destroy, "list_create_destroy"); + exotic_add_test(&handle, &exotic_test_list_create, "list_create"); + exotic_add_test(&handle, &exotic_test_list_append_1, "list_append_1"); + exotic_add_test(&handle, &exotic_test_list_remove_1, "list_remove_1"); + exotic_add_test(&handle, &exotic_test_list_append_2, "list_append_2"); + exotic_add_test(&handle, &exotic_test_list_remove_2, "list_remove_2"); + exotic_add_test(&handle, &exotic_test_list_remove_3, "list_remove_3"); + exotic_add_test(&handle, &exotic_test_list_remove_4, "list_remove_4"); + exotic_add_test(&handle, &exotic_test_list_append_3, "list_append_3"); + exotic_add_test(&handle, &exotic_test_list_append_4, "list_append_4"); + exotic_add_test(&handle, &exotic_test_list_remove_5, "list_remove_5"); + exotic_add_test(&handle, &exotic_test_list_get_index_1, "list_get_index_1"); + exotic_add_test(&handle, &exotic_test_list_get_index_2, "list_get_index_2"); + exotic_add_test(&handle, &exotic_test_list_get_index_3, "list_get_index_3"); + exotic_add_test(&handle, &exotic_test_list_get_index_4, "list_get_index_4"); + exotic_add_test(&handle, &exotic_test_list_get_first_1, "list_get_first_1"); + exotic_add_test(&handle, &exotic_test_list_get_first_next_1, "list_get_first_next_1"); + exotic_add_test(&handle, &exotic_test_list_get_first_next_2, "list_get_first_next_2"); + exotic_add_test(&handle, &exotic_test_list_get_last_1, "list_get_last_1"); + exotic_add_test(&handle, &exotic_test_list_get_last_prev_1, "list_get_last_prev_1"); + exotic_add_test(&handle, &exotic_test_list_get_last_prev_2, "list_get_last_prev_2"); + exotic_add_test(&handle, &exotic_test_list_get_last_prev_next_1, "list_get_last_prev_next_1"); + exotic_add_test(&handle, &exotic_test_list_clear, "list_clear"); + exotic_add_test(&handle, &exotic_test_list_destroy_1, "list_destroy_1"); + exotic_add_test(&handle, &exotic_test_list_destroy_2, "list_destroy_2"); + exotic_add_test(&handle, &exotic_test_test_message_refc_1, "test_message_refc_1"); + exotic_add_test(&handle, &exotic_test_test_message_refc_2, "test_message_refc_2"); + exotic_add_test(&handle, &exotic_test_test_message_refc_3, "test_message_refc_3"); + exotic_add_test(&handle, &exotic_test_test_message_refc_4, "test_message_refc_4"); + exotic_add_test(&handle, &exotic_test_test_message_refc_5, "test_message_refc_5"); + exotic_add_test(&handle, &exotic_test_test_message_refc_6, "test_message_refc_6"); + exotic_add_test(&handle, &exotic_test_test_message_refc_7, "test_message_refc_7"); + exotic_add_test(&handle, &exotic_test_adc_message_first, "adc_message_first"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_1, "adc_message_parse_1"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_2, "adc_message_parse_2"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_3, "adc_message_parse_3"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_4, "adc_message_parse_4"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_5, "adc_message_parse_5"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_6, "adc_message_parse_6"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_7, "adc_message_parse_7"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_8, "adc_message_parse_8"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_9, "adc_message_parse_9"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_10, "adc_message_parse_10"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_11, "adc_message_parse_11"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_12, "adc_message_parse_12"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_13, "adc_message_parse_13"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_14, "adc_message_parse_14"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_15, "adc_message_parse_15"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_16, "adc_message_parse_16"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_17, "adc_message_parse_17"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_18, "adc_message_parse_18"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_19, "adc_message_parse_19"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_20, "adc_message_parse_20"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_21, "adc_message_parse_21"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_22, "adc_message_parse_22"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_23, "adc_message_parse_23"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_24, "adc_message_parse_24"); + exotic_add_test(&handle, &exotic_test_adc_message_add_arg_1, "adc_message_add_arg_1"); + exotic_add_test(&handle, &exotic_test_adc_message_add_arg_2, "adc_message_add_arg_2"); + exotic_add_test(&handle, &exotic_test_adc_message_remove_arg_1, "adc_message_remove_arg_1"); + exotic_add_test(&handle, &exotic_test_adc_message_remove_arg_2, "adc_message_remove_arg_2"); + exotic_add_test(&handle, &exotic_test_adc_message_remove_arg_3, "adc_message_remove_arg_3"); + exotic_add_test(&handle, &exotic_test_adc_message_remove_arg_4, "adc_message_remove_arg_4"); + exotic_add_test(&handle, &exotic_test_adc_message_replace_arg_1, "adc_message_replace_arg_1"); + exotic_add_test(&handle, &exotic_test_adc_message_replace_arg_2, "adc_message_replace_arg_2"); + exotic_add_test(&handle, &exotic_test_adc_message_replace_arg_3, "adc_message_replace_arg_3"); + exotic_add_test(&handle, &exotic_test_adc_message_get_arg_1, "adc_message_get_arg_1"); + exotic_add_test(&handle, &exotic_test_adc_message_get_arg_2, "adc_message_get_arg_2"); + exotic_add_test(&handle, &exotic_test_adc_message_get_arg_3, "adc_message_get_arg_3"); + exotic_add_test(&handle, &exotic_test_adc_message_get_arg_4, "adc_message_get_arg_4"); + exotic_add_test(&handle, &exotic_test_adc_message_get_named_arg_1, "adc_message_get_named_arg_1"); + exotic_add_test(&handle, &exotic_test_adc_message_get_named_arg_2, "adc_message_get_named_arg_2"); + exotic_add_test(&handle, &exotic_test_adc_message_get_named_arg_3, "adc_message_get_named_arg_3"); + exotic_add_test(&handle, &exotic_test_adc_message_get_named_arg_4, "adc_message_get_named_arg_4"); + exotic_add_test(&handle, &exotic_test_adc_message_has_named_arg_1, "adc_message_has_named_arg_1"); + exotic_add_test(&handle, &exotic_test_adc_message_has_named_arg_2, "adc_message_has_named_arg_2"); + exotic_add_test(&handle, &exotic_test_adc_message_has_named_arg_3, "adc_message_has_named_arg_3"); + exotic_add_test(&handle, &exotic_test_adc_message_has_named_arg_4, "adc_message_has_named_arg_4"); + exotic_add_test(&handle, &exotic_test_adc_message_has_named_arg_5, "adc_message_has_named_arg_5"); + exotic_add_test(&handle, &exotic_test_adc_message_has_named_arg_6, "adc_message_has_named_arg_6"); + exotic_add_test(&handle, &exotic_test_adc_message_has_named_arg_7, "adc_message_has_named_arg_7"); + exotic_add_test(&handle, &exotic_test_adc_message_terminate_1, "adc_message_terminate_1"); + exotic_add_test(&handle, &exotic_test_adc_message_terminate_2, "adc_message_terminate_2"); + exotic_add_test(&handle, &exotic_test_adc_message_terminate_3, "adc_message_terminate_3"); + exotic_add_test(&handle, &exotic_test_adc_message_terminate_4, "adc_message_terminate_4"); + exotic_add_test(&handle, &exotic_test_adc_message_terminate_5, "adc_message_terminate_5"); + exotic_add_test(&handle, &exotic_test_adc_message_terminate_6, "adc_message_terminate_6"); + exotic_add_test(&handle, &exotic_test_adc_message_escape_1, "adc_message_escape_1"); + exotic_add_test(&handle, &exotic_test_adc_message_escape_2, "adc_message_escape_2"); + exotic_add_test(&handle, &exotic_test_adc_message_escape_3, "adc_message_escape_3"); + exotic_add_test(&handle, &exotic_test_adc_message_copy_1, "adc_message_copy_1"); + exotic_add_test(&handle, &exotic_test_adc_message_copy_2, "adc_message_copy_2"); + exotic_add_test(&handle, &exotic_test_adc_message_copy_3, "adc_message_copy_3"); + exotic_add_test(&handle, &exotic_test_adc_message_copy_4, "adc_message_copy_4"); + exotic_add_test(&handle, &exotic_test_adc_message_update_1, "adc_message_update_1"); + exotic_add_test(&handle, &exotic_test_adc_message_update_2, "adc_message_update_2"); + exotic_add_test(&handle, &exotic_test_adc_message_update_3, "adc_message_update_3"); + exotic_add_test(&handle, &exotic_test_adc_message_update_4, "adc_message_update_4"); + exotic_add_test(&handle, &exotic_test_adc_message_update_4_cleanup, "adc_message_update_4_cleanup"); + exotic_add_test(&handle, &exotic_test_adc_message_empty_1, "adc_message_empty_1"); + exotic_add_test(&handle, &exotic_test_adc_message_empty_2, "adc_message_empty_2"); + exotic_add_test(&handle, &exotic_test_adc_message_empty_3, "adc_message_empty_3"); + exotic_add_test(&handle, &exotic_test_adc_message_last, "adc_message_last"); + exotic_add_test(&handle, &exotic_test_is_num_0, "is_num_0"); + exotic_add_test(&handle, &exotic_test_is_num_1, "is_num_1"); + exotic_add_test(&handle, &exotic_test_is_num_2, "is_num_2"); + exotic_add_test(&handle, &exotic_test_is_num_3, "is_num_3"); + exotic_add_test(&handle, &exotic_test_is_num_4, "is_num_4"); + exotic_add_test(&handle, &exotic_test_is_num_5, "is_num_5"); + exotic_add_test(&handle, &exotic_test_is_num_6, "is_num_6"); + exotic_add_test(&handle, &exotic_test_is_num_7, "is_num_7"); + exotic_add_test(&handle, &exotic_test_is_num_8, "is_num_8"); + exotic_add_test(&handle, &exotic_test_is_num_9, "is_num_9"); + exotic_add_test(&handle, &exotic_test_is_num_10, "is_num_10"); + exotic_add_test(&handle, &exotic_test_is_num_11, "is_num_11"); + exotic_add_test(&handle, &exotic_test_is_space_1, "is_space_1"); + exotic_add_test(&handle, &exotic_test_is_space_2, "is_space_2"); + exotic_add_test(&handle, &exotic_test_is_white_space_1, "is_white_space_1"); + exotic_add_test(&handle, &exotic_test_is_white_space_2, "is_white_space_2"); + exotic_add_test(&handle, &exotic_test_is_white_space_3, "is_white_space_3"); + exotic_add_test(&handle, &exotic_test_is_white_space_4, "is_white_space_4"); + exotic_add_test(&handle, &exotic_test_itoa_1, "itoa_1"); + exotic_add_test(&handle, &exotic_test_itoa_2, "itoa_2"); + exotic_add_test(&handle, &exotic_test_itoa_3, "itoa_3"); + exotic_add_test(&handle, &exotic_test_itoa_4, "itoa_4"); + exotic_add_test(&handle, &exotic_test_itoa_5, "itoa_5"); + exotic_add_test(&handle, &exotic_test_itoa_6, "itoa_6"); + exotic_add_test(&handle, &exotic_test_itoa_7, "itoa_7"); + exotic_add_test(&handle, &exotic_test_itoa_8, "itoa_8"); + exotic_add_test(&handle, &exotic_test_base32_valid_1, "base32_valid_1"); + exotic_add_test(&handle, &exotic_test_base32_valid_2, "base32_valid_2"); + exotic_add_test(&handle, &exotic_test_base32_valid_3, "base32_valid_3"); + exotic_add_test(&handle, &exotic_test_base32_valid_4, "base32_valid_4"); + exotic_add_test(&handle, &exotic_test_base32_valid_5, "base32_valid_5"); + exotic_add_test(&handle, &exotic_test_base32_valid_6, "base32_valid_6"); + exotic_add_test(&handle, &exotic_test_base32_valid_7, "base32_valid_7"); + exotic_add_test(&handle, &exotic_test_base32_valid_8, "base32_valid_8"); + exotic_add_test(&handle, &exotic_test_base32_valid_9, "base32_valid_9"); + exotic_add_test(&handle, &exotic_test_base32_valid_10, "base32_valid_10"); + exotic_add_test(&handle, &exotic_test_base32_valid_11, "base32_valid_11"); + exotic_add_test(&handle, &exotic_test_base32_valid_12, "base32_valid_12"); + exotic_add_test(&handle, &exotic_test_base32_valid_13, "base32_valid_13"); + exotic_add_test(&handle, &exotic_test_base32_valid_14, "base32_valid_14"); + exotic_add_test(&handle, &exotic_test_base32_valid_15, "base32_valid_15"); + exotic_add_test(&handle, &exotic_test_base32_valid_16, "base32_valid_16"); + exotic_add_test(&handle, &exotic_test_base32_valid_17, "base32_valid_17"); + exotic_add_test(&handle, &exotic_test_base32_valid_18, "base32_valid_18"); + exotic_add_test(&handle, &exotic_test_base32_valid_19, "base32_valid_19"); + exotic_add_test(&handle, &exotic_test_base32_valid_20, "base32_valid_20"); + exotic_add_test(&handle, &exotic_test_base32_valid_21, "base32_valid_21"); + exotic_add_test(&handle, &exotic_test_base32_valid_22, "base32_valid_22"); + exotic_add_test(&handle, &exotic_test_base32_valid_23, "base32_valid_23"); + exotic_add_test(&handle, &exotic_test_base32_valid_24, "base32_valid_24"); + exotic_add_test(&handle, &exotic_test_base32_valid_25, "base32_valid_25"); + exotic_add_test(&handle, &exotic_test_base32_valid_26, "base32_valid_26"); + exotic_add_test(&handle, &exotic_test_base32_valid_27, "base32_valid_27"); + exotic_add_test(&handle, &exotic_test_base32_valid_28, "base32_valid_28"); + exotic_add_test(&handle, &exotic_test_base32_valid_29, "base32_valid_29"); + exotic_add_test(&handle, &exotic_test_base32_valid_30, "base32_valid_30"); + exotic_add_test(&handle, &exotic_test_base32_valid_31, "base32_valid_31"); + exotic_add_test(&handle, &exotic_test_base32_valid_32, "base32_valid_32"); + exotic_add_test(&handle, &exotic_test_base32_invalid_1, "base32_invalid_1"); + exotic_add_test(&handle, &exotic_test_base32_invalid_2, "base32_invalid_2"); + exotic_add_test(&handle, &exotic_test_base32_invalid_3, "base32_invalid_3"); + exotic_add_test(&handle, &exotic_test_base32_invalid_4, "base32_invalid_4"); + exotic_add_test(&handle, &exotic_test_base32_invalid_5, "base32_invalid_5"); + exotic_add_test(&handle, &exotic_test_base32_invalid_6, "base32_invalid_6"); + exotic_add_test(&handle, &exotic_test_base32_invalid_7, "base32_invalid_7"); + exotic_add_test(&handle, &exotic_test_base32_invalid_8, "base32_invalid_8"); + exotic_add_test(&handle, &exotic_test_base32_invalid_9, "base32_invalid_9"); + exotic_add_test(&handle, &exotic_test_base32_invalid_10, "base32_invalid_10"); + exotic_add_test(&handle, &exotic_test_base32_invalid_11, "base32_invalid_11"); + exotic_add_test(&handle, &exotic_test_base32_invalid_12, "base32_invalid_12"); + exotic_add_test(&handle, &exotic_test_base32_invalid_13, "base32_invalid_13"); + exotic_add_test(&handle, &exotic_test_base32_invalid_14, "base32_invalid_14"); + exotic_add_test(&handle, &exotic_test_base32_invalid_15, "base32_invalid_15"); + exotic_add_test(&handle, &exotic_test_base32_invalid_16, "base32_invalid_16"); + exotic_add_test(&handle, &exotic_test_base32_invalid_17, "base32_invalid_17"); + exotic_add_test(&handle, &exotic_test_base32_invalid_18, "base32_invalid_18"); + exotic_add_test(&handle, &exotic_test_base32_invalid_19, "base32_invalid_19"); + exotic_add_test(&handle, &exotic_test_base32_invalid_20, "base32_invalid_20"); + exotic_add_test(&handle, &exotic_test_base32_invalid_21, "base32_invalid_21"); + exotic_add_test(&handle, &exotic_test_base32_invalid_22, "base32_invalid_22"); + exotic_add_test(&handle, &exotic_test_base32_invalid_23, "base32_invalid_23"); + exotic_add_test(&handle, &exotic_test_base32_invalid_24, "base32_invalid_24"); + exotic_add_test(&handle, &exotic_test_base32_invalid_25, "base32_invalid_25"); + exotic_add_test(&handle, &exotic_test_base32_invalid_26, "base32_invalid_26"); + exotic_add_test(&handle, &exotic_test_base32_invalid_27, "base32_invalid_27"); + exotic_add_test(&handle, &exotic_test_base32_invalid_28, "base32_invalid_28"); + exotic_add_test(&handle, &exotic_test_base32_invalid_29, "base32_invalid_29"); + exotic_add_test(&handle, &exotic_test_base32_invalid_30, "base32_invalid_30"); + exotic_add_test(&handle, &exotic_test_base32_invalid_31, "base32_invalid_31"); + exotic_add_test(&handle, &exotic_test_utf8_valid_1, "utf8_valid_1"); + exotic_add_test(&handle, &exotic_test_utf8_valid_2, "utf8_valid_2"); + exotic_add_test(&handle, &exotic_test_utf8_valid_3, "utf8_valid_3"); + exotic_add_test(&handle, &exotic_test_utf8_valid_4, "utf8_valid_4"); + exotic_add_test(&handle, &exotic_test_utf8_valid_5, "utf8_valid_5"); + exotic_add_test(&handle, &exotic_test_utf8_valid_6, "utf8_valid_6"); + exotic_add_test(&handle, &exotic_test_utf8_valid_7, "utf8_valid_7"); + exotic_add_test(&handle, &exotic_test_utf8_valid_8, "utf8_valid_8"); + exotic_add_test(&handle, &exotic_test_utf8_valid_9, "utf8_valid_9"); + exotic_add_test(&handle, &exotic_test_utf8_valid_10, "utf8_valid_10"); + exotic_add_test(&handle, &exotic_test_utf8_valid_11, "utf8_valid_11"); + exotic_add_test(&handle, &exotic_test_utf8_valid_12, "utf8_valid_12"); + exotic_add_test(&handle, &exotic_test_sid_create_pool, "sid_create_pool"); + exotic_add_test(&handle, &exotic_test_sid_check_0a, "sid_check_0a"); + exotic_add_test(&handle, &exotic_test_sid_check_0b, "sid_check_0b"); + exotic_add_test(&handle, &exotic_test_sid_alloc_1, "sid_alloc_1"); + exotic_add_test(&handle, &exotic_test_sid_check_1a, "sid_check_1a"); + exotic_add_test(&handle, &exotic_test_sid_check_1b, "sid_check_1b"); + exotic_add_test(&handle, &exotic_test_sid_alloc_2, "sid_alloc_2"); + exotic_add_test(&handle, &exotic_test_sid_check_2, "sid_check_2"); + exotic_add_test(&handle, &exotic_test_sid_alloc_3, "sid_alloc_3"); + exotic_add_test(&handle, &exotic_test_sid_check_3, "sid_check_3"); + exotic_add_test(&handle, &exotic_test_sid_alloc_4, "sid_alloc_4"); + exotic_add_test(&handle, &exotic_test_sid_check_4, "sid_check_4"); + exotic_add_test(&handle, &exotic_test_sid_alloc_5, "sid_alloc_5"); + exotic_add_test(&handle, &exotic_test_sid_check_6, "sid_check_6"); + exotic_add_test(&handle, &exotic_test_sid_list_all_1, "sid_list_all_1"); + exotic_add_test(&handle, &exotic_test_sid_remove_1, "sid_remove_1"); + exotic_add_test(&handle, &exotic_test_sid_remove_2, "sid_remove_2"); + exotic_add_test(&handle, &exotic_test_sid_remove_3, "sid_remove_3"); + exotic_add_test(&handle, &exotic_test_sid_remove_4, "sid_remove_4"); + exotic_add_test(&handle, &exotic_test_sid_destroy_pool, "sid_destroy_pool"); + exotic_add_test(&handle, &exotic_test_hash_tiger_1, "hash_tiger_1"); + exotic_add_test(&handle, &exotic_test_hash_tiger_2, "hash_tiger_2"); + exotic_add_test(&handle, &exotic_test_hash_tiger_3, "hash_tiger_3"); + exotic_add_test(&handle, &exotic_test_hash_tiger_4, "hash_tiger_4"); + exotic_add_test(&handle, &exotic_test_hash_tiger_5, "hash_tiger_5"); + exotic_add_test(&handle, &exotic_test_hash_tiger_6, "hash_tiger_6"); + exotic_add_test(&handle, &exotic_test_hash_tiger_7, "hash_tiger_7"); + exotic_add_test(&handle, &exotic_test_timer_setup, "timer_setup"); + exotic_add_test(&handle, &exotic_test_timer_check_timeout_0, "timer_check_timeout_0"); + exotic_add_test(&handle, &exotic_test_timer_add_event_1, "timer_add_event_1"); + exotic_add_test(&handle, &exotic_test_timer_check_timeout_1, "timer_check_timeout_1"); + exotic_add_test(&handle, &exotic_test_timer_remove_event_1, "timer_remove_event_1"); + exotic_add_test(&handle, &exotic_test_timer_check_timeout_2, "timer_check_timeout_2"); + exotic_add_test(&handle, &exotic_test_timer_remove_event_1_no_crash, "timer_remove_event_1_no_crash"); + exotic_add_test(&handle, &exotic_test_timer_add_5_events_1, "timer_add_5_events_1"); + exotic_add_test(&handle, &exotic_test_timer_check_5_events_1, "timer_check_5_events_1"); + exotic_add_test(&handle, &exotic_test_timer_process_5_events_1, "timer_process_5_events_1"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_0, "tokenizer_basic_0"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_1, "tokenizer_basic_1"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_1a, "tokenizer_basic_1a"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_1b, "tokenizer_basic_1b"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_1c, "tokenizer_basic_1c"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_1d, "tokenizer_basic_1d"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_1e, "tokenizer_basic_1e"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_2, "tokenizer_basic_2"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_2a, "tokenizer_basic_2a"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_3, "tokenizer_basic_3"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_3a, "tokenizer_basic_3a"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_3b, "tokenizer_basic_3b"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_3c, "tokenizer_basic_3c"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_3d, "tokenizer_basic_3d"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_compare_0, "tokenizer_basic_compare_0"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_compare_1, "tokenizer_basic_compare_1"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_compare_2, "tokenizer_basic_compare_2"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_compare_3, "tokenizer_basic_compare_3"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_compare_4, "tokenizer_basic_compare_4"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_compare_5, "tokenizer_basic_compare_5"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_compare_6, "tokenizer_basic_compare_6"); + exotic_add_test(&handle, &exotic_test_tokenizer_comment_1, "tokenizer_comment_1"); + exotic_add_test(&handle, &exotic_test_tokenizer_comment_2, "tokenizer_comment_2"); + exotic_add_test(&handle, &exotic_test_tokenizer_comment_3, "tokenizer_comment_3"); + exotic_add_test(&handle, &exotic_test_tokenizer_escape_1, "tokenizer_escape_1"); + exotic_add_test(&handle, &exotic_test_tokenizer_escape_2, "tokenizer_escape_2"); + exotic_add_test(&handle, &exotic_test_tokenizer_escape_3, "tokenizer_escape_3"); + exotic_add_test(&handle, &exotic_test_tokenizer_escape_4, "tokenizer_escape_4"); + exotic_add_test(&handle, &exotic_test_tokenizer_escape_5, "tokenizer_escape_5"); + exotic_add_test(&handle, &exotic_test_tokenizer_escape_6, "tokenizer_escape_6"); + exotic_add_test(&handle, &exotic_test_tokenizer_escape_7, "tokenizer_escape_7"); + exotic_add_test(&handle, &exotic_test_tokenizer_settings_1, "tokenizer_settings_1"); + exotic_add_test(&handle, &exotic_test_tokenizer_settings_2, "tokenizer_settings_2"); + exotic_add_test(&handle, &exotic_test_tokenizer_settings_3, "tokenizer_settings_3"); + exotic_add_test(&handle, &exotic_test_tokenizer_settings_4, "tokenizer_settings_4"); + exotic_add_test(&handle, &exotic_test_tokenizer_settings_5, "tokenizer_settings_5"); + exotic_add_test(&handle, &exotic_test_tokenizer_settings_6, "tokenizer_settings_6"); + exotic_add_test(&handle, &exotic_test_tokenizer_settings_7, "tokenizer_settings_7"); + exotic_add_test(&handle, &exotic_test_tokenizer_settings_8, "tokenizer_settings_8"); + exotic_add_test(&handle, &exotic_test_tokenizer_settings_9, "tokenizer_settings_9"); + exotic_add_test(&handle, &exotic_test_um_init_1, "um_init_1"); + exotic_add_test(&handle, &exotic_test_um_shutdown_1, "um_shutdown_1"); + exotic_add_test(&handle, &exotic_test_um_shutdown_2, "um_shutdown_2"); + exotic_add_test(&handle, &exotic_test_um_init_2, "um_init_2"); + exotic_add_test(&handle, &exotic_test_um_add_1, "um_add_1"); + exotic_add_test(&handle, &exotic_test_um_size_1, "um_size_1"); + exotic_add_test(&handle, &exotic_test_um_remove_1, "um_remove_1"); + exotic_add_test(&handle, &exotic_test_um_size_2, "um_size_2"); + exotic_add_test(&handle, &exotic_test_um_add_2, "um_add_2"); + exotic_add_test(&handle, &exotic_test_um_size_3, "um_size_3"); + exotic_add_test(&handle, &exotic_test_um_remove_2, "um_remove_2"); + exotic_add_test(&handle, &exotic_test_um_shutdown_4, "um_shutdown_4"); + + return exotic_run(&handle); +} + + +/* + * Exotic - C/C++ source code testing + * Copyright (c) 2007, Jan Vidar Krey + */ + +#include +#include +#include +#include + +static void exotic_version(); + +#ifndef __EXOTIC__STANDALONE__ +#include "autotest.h" +static void exotic_version() +{ + printf("Extatic.org Test Infrastructure: exotic " "${version}" "\n\n"); + printf("Copyright (C) 2007 Jan Vidar Krey, janvidar@extatic.org\n"); + printf("This is free software with ABSOLUTELY NO WARRANTY.\n\n"); +} +#endif + +struct exo_test_data +{ + exo_test_t test; + char* name; + struct exo_test_data* next; +}; + + +static void exotic_summary(struct exotic_handle* handle) +{ + int total = handle->pass + handle->fail; + int pass_rate = total ? (100*handle->pass / total) : 0; + int fail_rate = total ? (100*handle->fail / total) : 0; + + printf("\n"); + printf("--------------------------------------------\n"); + printf("Results:\n"); + printf(" * Total tests run: %8d\n", total); + printf(" * Tests passed: %8d (~%d%%)\n", (int) handle->pass, pass_rate); + printf(" * Tests failed: %8d (~%d%%)\n", (int) handle->fail, fail_rate); + printf("--------------------------------------------\n"); +} + + +static void exotic_help(const char* program) +{ + printf("Usage: %s [OPTIONS]\n\n", program); + printf("Options:\n"); + printf(" --help -h Show this message\n"); + printf(" --version -v Show version\n"); + printf(" --summary -s show only summary)\n"); + printf(" --fail -f show only test failures\n"); + printf(" --pass -p show only test passes\n"); + printf("\nExamples:\n"); + printf(" %s -s -f\n\n", program); +} + + +int exotic_initialize(struct exotic_handle* handle, int argc, char** argv) +{ + int n; + if (!handle || !argv) return -1; + + memset(handle, 0, sizeof(struct exotic_handle)); + + for (n = 1; n < argc; n++) + { + if (!strcmp(argv[n], "-h") || !strcmp(argv[n], "--help")) + { + exotic_help(argv[0]); + exit(0); + } + + if (!strcmp(argv[n], "-v") || !strcmp(argv[n], "--version")) + { + exotic_version(); + exit(0); + } + + if (!strcmp(argv[n], "-s") || !strcmp(argv[n], "--summary")) + { + handle->config_show_summary = cfg_on; + continue; + } + + if (!strcmp(argv[n], "-f") || !strcmp(argv[n], "--fail")) + { + handle->config_show_fail = cfg_on; + continue; + } + + if (!strcmp(argv[n], "-p") || !strcmp(argv[n], "--pass")) + { + handle->config_show_pass = cfg_on; + continue; + } + + fprintf(stderr, "Unknown argument: %s\n\n", argv[n]); + exotic_help(argv[0]); + exit(0); + } + + if (handle->config_show_summary == cfg_on) + { + if (handle->config_show_pass == cfg_default) handle->config_show_pass = cfg_off; + if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; + + } + else if (handle->config_show_pass == cfg_on) + { + if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_off; + if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; + } + else if (handle->config_show_fail == cfg_on) + { + if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_off; + if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; + } + else + { + if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_on; + if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_on; + if (handle->config_show_pass == cfg_default) handle->config_show_pass = cfg_on; + } + return 0; +} + + +void exotic_add_test(struct exotic_handle* handle, exo_test_t func, const char* name) +{ + if (!handle) + { + fprintf(stderr, "exotic_add_test: failed, no handle!\n"); + exit(-1); + } + + struct exo_test_data* test = (struct exo_test_data*) malloc(sizeof(struct exo_test_data)); + if (!test) + { + fprintf(stderr, "exotic_add_test: out of memory!\n"); + exit(-1); + } + + /* Create the test */ + memset(test, 0, sizeof(struct exo_test_data)); + test->test = func; + test->name = strdup(name); + + /* Register the test in the handle */ + if (!handle->first) + { + handle->first = test; + handle->current = test; + } + else + { + handle->current->next = test; + handle->current = test; + } +} + + +int exotic_run(struct exotic_handle* handle) +{ + struct exo_test_data* tmp = NULL; + + if (!handle) + { + fprintf(stderr, "Error: exotic is not initialized\n"); + return -1; + } + + handle->current = handle->first; + while (handle->current) + { + tmp = handle->current; + + if (handle->current->test()) { + if (handle->config_show_pass == cfg_on) printf("* PASS test '%s'\n", tmp->name); + handle->pass++; + } else { + if (handle->config_show_fail == cfg_on) printf("* FAIL test '%s'\n", tmp->name); + handle->fail++; + } + + handle->current = handle->current->next; + + free(tmp->name); + free(tmp); + } + + if (!handle->first) + { + printf("(No tests added)\n"); + } + + if (handle->config_show_summary == cfg_on) + exotic_summary(handle); + + return (handle->fail) ? handle->fail : 0; +} + + +static void exotic_version() { + printf("exotic 0.4-standalone\n\n"); + printf("Copyright (C) 2007 Jan Vidar Krey, janvidar@extatic.org\n"); + printf("This is free software with ABSOLUTELY NO WARRANTY.\n\n"); +} diff --git a/autotest/update.sh b/autotest/update.sh new file mode 100755 index 0000000..5b2dba6 --- /dev/null +++ b/autotest/update.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +./exotic *.tcc > test.c +