usnic: add simple unit testing infrastructure
This commit adds mechanisms for writing and running unit tests in the usnic BTL. The short version of how to run the tests is: 1. Configure with `--enable-ompi-btl-usnic-unit-tests`. This will cause the unit testing code and test runner utility to be built. 2. Run the tests by running `ompi_btl_usnic_run_tests`. See `README.test` for full details. Reviewed-by: Jeff Squyres <jsquyres@cisco.com> cmr=v1.7.5:ticket=trac:4253 This commit was SVN r30845. The following Trac tickets were found above: Ticket 4253 --> https://svn.open-mpi.org/trac/ompi/ticket/4253
Этот коммит содержится в:
родитель
044a190cac
Коммит
921a29e41f
@ -11,7 +11,7 @@
|
||||
# All rights reserved.
|
||||
# Copyright (c) 2006 Sandia National Laboratories. All rights
|
||||
# reserved.
|
||||
# Copyright (c) 2010-2013 Cisco Systems, Inc. All rights reserved.
|
||||
# Copyright (c) 2010-2014 Cisco Systems, Inc. All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
@ -22,6 +22,8 @@
|
||||
AM_CPPFLAGS = $(btl_usnic_CPPFLAGS)
|
||||
AM_CFLAGS = $(btl_usnic_CFLAGS)
|
||||
|
||||
EXTRA_DIST = README.txt README.test
|
||||
|
||||
dist_ompidata_DATA = \
|
||||
help-mpi-btl-usnic.txt
|
||||
|
||||
@ -48,7 +50,9 @@ sources = \
|
||||
btl_usnic_stats.h \
|
||||
btl_usnic_stats.c \
|
||||
btl_usnic_util.c \
|
||||
btl_usnic_util.h
|
||||
btl_usnic_util.h \
|
||||
btl_usnic_test.c \
|
||||
btl_usnic_test.h
|
||||
|
||||
if OPAL_HAVE_HWLOC
|
||||
sources += btl_usnic_hwloc.c
|
||||
@ -81,3 +85,9 @@ noinst_LTLIBRARIES = $(lib)
|
||||
libmca_btl_usnic_la_SOURCES = $(lib_sources)
|
||||
libmca_btl_usnic_la_LDFLAGS= -module -avoid-version $(btl_usnic_LDFLAGS)
|
||||
libmca_btl_usnic_la_LIBADD = $(btl_usnic_LIBS)
|
||||
|
||||
if OMPI_BTL_USNIC_BUILD_UNIT_TESTS
|
||||
ompi_btl_usnic_run_tests_SOURCES = test/ompi_btl_usnic_run_tests.c
|
||||
ompi_btl_usnic_run_tests_LDADD = -ldl
|
||||
bin_PROGRAMS = ompi_btl_usnic_run_tests
|
||||
endif OMPI_BTL_USNIC_BUILD_UNIT_TESTS
|
||||
|
74
ompi/mca/btl/usnic/README.test
Обычный файл
74
ompi/mca/btl/usnic/README.test
Обычный файл
@ -0,0 +1,74 @@
|
||||
usnic BTL Unit Testing Information
|
||||
==================================
|
||||
This document briefly describes the scheme put in place for usnic BTL unit
|
||||
testing. This system was very quickly tossed together and warrants a proper
|
||||
revisiting at some point in the future. There are lots of ways to solve these
|
||||
problems and this is just one of them. Future improvement is welcome.
|
||||
|
||||
Goals
|
||||
-----
|
||||
* To enable _unit_ testing of isolated functions or sets of functions. This
|
||||
has all sorts of benefits, including:
|
||||
- greater confidence that corner cases work as expected
|
||||
- faster, lower-stress refactoring in the future
|
||||
- influencing future interfaces to have less implicit coupling/state (unit
|
||||
testing is harder otherwise)
|
||||
* To be able to test *static* functions as well as non-static ones.
|
||||
* To avoid cluttering the normal code base with excessive test-related
|
||||
macros/code.
|
||||
* The tests should be easy to run under Valgrind and GDB to facilitate:
|
||||
- automated leak/memory checking
|
||||
- easy debugging compared to a parallel MPI environment
|
||||
|
||||
Anti-Goals
|
||||
----------
|
||||
* Testing the low level networking API (e.g., verbs).
|
||||
* Testing inter-process interaction, such as ORTE-related functionality.
|
||||
|
||||
Constraints
|
||||
-----------
|
||||
* our unit tests should never perturb a normal build in terms of performance
|
||||
or correctness
|
||||
- also should not affect other non-usNIC developers in any way (don't
|
||||
break Ralph's `make check`)
|
||||
* static functions are difficult to test from outside the same source file
|
||||
|
||||
Design Notes
|
||||
------------
|
||||
* Source files named `X.c` include a header at the end named `test/X_test.h`
|
||||
- Rationale: gives tests access to the static functions in `X.c`
|
||||
- Rationale: keeps `X.c` clutter-free
|
||||
* unit test infrastructure lives in `btl_usnic_test.c` and `btl_usnic_test.h`
|
||||
* unit test functionality is built and enabled by passing
|
||||
`--enable-ompi-btl-usnic-unit-tests` to configure
|
||||
- Rationale: default state disables all unit test logic, achieving our
|
||||
"non-interference" goals
|
||||
* The tests are run by a new executable that gets built when unit tests are
|
||||
enabled: `ompi_btl_usnic_run_tests`.
|
||||
* Tests are registered at dlopen time via an
|
||||
`__attribute__((__constructor__))` function that is generated by invocations
|
||||
of the `USNIC_REGISTER_TEST` macro.
|
||||
- Rationale: add tests in one spot, no need to centralize the list of
|
||||
tests to run separately from the tests themselves.
|
||||
* Tests only use a simple `check()` macro right now that has `assert`-like
|
||||
semantics.
|
||||
- this could easily be expanded in the future, using the check docs as
|
||||
inspiration:
|
||||
http://check.sourceforge.net/doc/check_html/check_4.html#Convenience-Test-Functions
|
||||
|
||||
Worthy Future Goals/Features
|
||||
----------------------------
|
||||
* Add some mocking capabilities.
|
||||
- could use the preprocessor to replace regular function/macro calls with
|
||||
calls to functions/macros that dispatch to changeable function pointers
|
||||
- will require some reorganization of some of the existing code...
|
||||
* Output test results in a format that Jenkins and other tools can understand.
|
||||
- TAP
|
||||
- jUnit XML
|
||||
* Possibly utilize part or all of an existing unit testing framework, e.g.:
|
||||
- check: http://check.sourceforge.net/ (LGPLed)
|
||||
- cUnit: http://cunit.sourceforge.net/ (unfortunately GPLed...)
|
||||
* Re-examine test grouping and numbering. Right now there's no real concept
|
||||
of "suites" or multiple cases within a single test function. Once the
|
||||
number of tests grows to a certain point it will probably make sense to
|
||||
revisit this decision.
|
@ -73,6 +73,7 @@
|
||||
#include "btl_usnic_send.h"
|
||||
#include "btl_usnic_recv.h"
|
||||
#include "btl_usnic_proc.h"
|
||||
#include "btl_usnic_test.h"
|
||||
|
||||
#define OMPI_BTL_USNIC_NUM_WC 500
|
||||
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||||
@ -213,6 +214,11 @@ static int usnic_component_close(void)
|
||||
mca_btl_usnic_component.vendor_part_ids = NULL;
|
||||
}
|
||||
|
||||
#if OMPI_BTL_USNIC_UNIT_TESTS
|
||||
/* clean up the unit test infrastructure */
|
||||
ompi_btl_usnic_cleanup_tests();
|
||||
#endif
|
||||
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
|
127
ompi/mca/btl/usnic/btl_usnic_test.c
Обычный файл
127
ompi/mca/btl/usnic/btl_usnic_test.c
Обычный файл
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Cisco Systems, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "opal/class/opal_list.h"
|
||||
|
||||
#include "btl_usnic.h"
|
||||
#include "btl_usnic_test.h"
|
||||
|
||||
int ompi_btl_usnic_num_tests_run = 0;
|
||||
int ompi_btl_usnic_num_tests_passed = 0;
|
||||
int ompi_btl_usnic_num_tests_failed = 0;
|
||||
int ompi_btl_usnic_num_tests_skipped = 0;
|
||||
|
||||
struct test_info {
|
||||
opal_list_item_t li;
|
||||
char *name;
|
||||
ompi_btl_usnic_test_fn_t test_fn;
|
||||
void *ctx;
|
||||
};
|
||||
|
||||
#if OMPI_BTL_USNIC_UNIT_TESTS
|
||||
static bool initialized = false;
|
||||
static opal_list_t all_tests;
|
||||
|
||||
void ompi_btl_usnic_cleanup_tests(void)
|
||||
{
|
||||
opal_list_item_t *li;
|
||||
struct test_info *info;
|
||||
|
||||
if (initialized) {
|
||||
while (NULL != (li = opal_list_remove_first(&all_tests))) {
|
||||
info = container_of(li, struct test_info, li);
|
||||
free(info);
|
||||
}
|
||||
OBJ_DESTRUCT(&all_tests);
|
||||
}
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
static void init_test_infra(void)
|
||||
{
|
||||
if (!initialized) {
|
||||
OBJ_CONSTRUCT(&all_tests, opal_list_t);
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ompi_btl_usnic_register_test(const char *name,
|
||||
ompi_btl_usnic_test_fn_t test_fn,
|
||||
void *ctx)
|
||||
{
|
||||
struct test_info *info = malloc(sizeof(*info));
|
||||
assert(info != NULL);
|
||||
|
||||
OBJ_CONSTRUCT(&info->li, opal_list_item_t);
|
||||
|
||||
init_test_infra();
|
||||
|
||||
info->name = strdup(name);
|
||||
info->test_fn = test_fn;
|
||||
info->ctx = ctx;
|
||||
|
||||
opal_list_append(&all_tests, &info->li);
|
||||
}
|
||||
|
||||
void ompi_btl_usnic_run_tests(void)
|
||||
{
|
||||
struct test_info *info;
|
||||
enum test_result result;
|
||||
|
||||
if (!OMPI_BTL_USNIC_UNIT_TESTS) {
|
||||
test_out("unit tests disabled in this build, doing nothing!\n");
|
||||
return;
|
||||
}
|
||||
test_out("STARTING TESTS\n");
|
||||
|
||||
OPAL_LIST_FOREACH(info, &all_tests, struct test_info) {
|
||||
test_out("running test '%s'... ", info->name);
|
||||
result = info->test_fn(info->ctx);
|
||||
|
||||
++ompi_btl_usnic_num_tests_run;
|
||||
switch (result) {
|
||||
case TEST_PASSED:
|
||||
++ompi_btl_usnic_num_tests_passed;
|
||||
test_out("PASSED\n");
|
||||
break;
|
||||
case TEST_FAILED:
|
||||
++ompi_btl_usnic_num_tests_failed;
|
||||
test_out("FAILED\n");
|
||||
break;
|
||||
case TEST_SKIPPED:
|
||||
++ompi_btl_usnic_num_tests_skipped;
|
||||
test_out("SKIPPED\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
test_out("FINISHED TESTS (%d passed, %d failed, %d skipped)\n",
|
||||
ompi_btl_usnic_num_tests_passed,
|
||||
ompi_btl_usnic_num_tests_failed,
|
||||
ompi_btl_usnic_num_tests_skipped);
|
||||
}
|
||||
|
||||
#else /* !OMPI_BTL_USNIC_UNIT_TESTS */
|
||||
|
||||
void ompi_btl_usnic_register_test(const char *name,
|
||||
ompi_btl_usnic_test_fn_t test_fn,
|
||||
void *ctx)
|
||||
{
|
||||
abort(); /* never should be called */
|
||||
}
|
||||
|
||||
void ompi_btl_usnic_run_tests(void)
|
||||
{
|
||||
test_out("unit tests disabled in this build, doing nothing!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* !OMPI_BTL_USNIC_UNIT_TESTS */
|
95
ompi/mca/btl/usnic/btl_usnic_test.h
Обычный файл
95
ompi/mca/btl/usnic/btl_usnic_test.h
Обычный файл
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Cisco Systems, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#ifndef BTL_USNIC_TEST_H
|
||||
#define BTL_USNIC_TEST_H
|
||||
|
||||
#include "ompi_config.h"
|
||||
|
||||
typedef int (*ompi_btl_usnic_test_fn_t)(void *ctx);
|
||||
|
||||
#if OMPI_BTL_USNIC_UNIT_TESTS
|
||||
# define test_out(...) fprintf(stderr, __VA_ARGS__)
|
||||
# define check(a) \
|
||||
do { \
|
||||
if (!(a)) { \
|
||||
test_out("%s:%d: check failed, '%s'\n", __func__, __LINE__, #a); \
|
||||
return TEST_FAILED; \
|
||||
} \
|
||||
} while (0)
|
||||
# define check_str_eq(a,b) \
|
||||
do { \
|
||||
const char *a_ = (a); \
|
||||
const char *b_ = (b); \
|
||||
if (0 != strcmp(a_,b_)) { \
|
||||
test_out("%s:%d: check failed, \"%s\" != \"%s\"\n", \
|
||||
__func__, __LINE__, a_, b_); \
|
||||
return TEST_FAILED; \
|
||||
} \
|
||||
} while (0)
|
||||
# define check_int_eq(got, expected) \
|
||||
do { \
|
||||
if ((got) != (expected)) { \
|
||||
test_out("%s:%d: check failed, \"%s\" != \"%s\", got %d\n", \
|
||||
__func__, __LINE__, #got, #expected, (got)); \
|
||||
return TEST_FAILED; \
|
||||
} \
|
||||
} while (0)
|
||||
/* just use check_int_eq for now, no public error code to string routine
|
||||
* exists (opal_err2str is static) */
|
||||
# define check_err_code(got, expected) \
|
||||
check_int_eq(got, expected)
|
||||
# define check_msg(a, msg) \
|
||||
do { \
|
||||
if (!(a)) { \
|
||||
test_out("%s:%d: check failed, \"%s\" (%s)\n", \
|
||||
__func__, __LINE__, #a, (msg)); \
|
||||
return TEST_FAILED; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
extern int ompi_btl_usnic_num_tests_run;
|
||||
extern int ompi_btl_usnic_num_tests_passed;
|
||||
extern int ompi_btl_usnic_num_tests_failed;
|
||||
extern int ompi_btl_usnic_num_tests_skipped;
|
||||
|
||||
enum test_result {
|
||||
TEST_PASSED = 0,
|
||||
TEST_FAILED,
|
||||
TEST_SKIPPED
|
||||
};
|
||||
|
||||
/* let us actually paste __LINE__ with other tokens */
|
||||
# define USNIC_PASTE(a,b) USNIC_PASTE2(a,b)
|
||||
# define USNIC_PASTE2(a,b) a ## b
|
||||
/* A helper macro to de-clutter test registration. */
|
||||
# define USNIC_REGISTER_TEST(name, test_fn, ctx) \
|
||||
__attribute__((__constructor__)) \
|
||||
static void USNIC_PASTE(usnic_reg_ctor_,__LINE__)(void) \
|
||||
{ \
|
||||
ompi_btl_usnic_register_test(name, test_fn, ctx); \
|
||||
} \
|
||||
|
||||
#else /* !OMPI_BTL_USNIC_UNIT_TESTS */
|
||||
# define test_out(...) do {} while(0)
|
||||
# define USNIC_REGISTER_TEST(name, test_fn, ctx)
|
||||
#endif
|
||||
|
||||
/* Run all registered tests. Typically called by an external utility that
|
||||
* dlopens the usnic BTL shared object. See run_usnic_tests.c. */
|
||||
void ompi_btl_usnic_run_tests(void);
|
||||
|
||||
void ompi_btl_usnic_register_test(const char *name,
|
||||
ompi_btl_usnic_test_fn_t test_fn,
|
||||
void *ctx);
|
||||
|
||||
/* should be called once, at component close time */
|
||||
void ompi_btl_usnic_cleanup_tests(void);
|
||||
|
||||
#endif /* BTL_USNIC_TEST_H */
|
@ -20,6 +20,88 @@
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
# OMPI_CHECK_LIBNL3(prefix, [action-if-found], [action-if-not-found])
|
||||
# --------------------------------------------------------
|
||||
# check if libnl3 support can be found. sets prefix_{CPPFLAGS,
|
||||
# LDFLAGS, LIBS} as needed and runs action-if-found if there is
|
||||
# support, otherwise executes action-if-not-found
|
||||
#
|
||||
# libnl3 changed its default header location as of v3.2 (released ca. September
|
||||
# 2011). It was previously "${prefix}/include/netlink/...". It now is
|
||||
# "${prefix}/libnl3/include/netlink/...". The logic below only supports
|
||||
# >=v3.2, under the assumption that it is not widely deployed.
|
||||
AC_DEFUN([OMPI_CHECK_LIBNL3],[
|
||||
AC_ARG_WITH([libnl3],
|
||||
[AC_HELP_STRING([--with-libnl3(=DIR)],
|
||||
[Build libnl3 support])])
|
||||
OMPI_CHECK_WITHDIR([libnl3], [$with_libnl3], [include/libnl3/netlink/netlink.h])
|
||||
AC_ARG_WITH([libnl3-libdir],
|
||||
[AC_HELP_STRING([--with-libnl3-libdir=DIR],
|
||||
[Search for libnl3 libraries in DIR])])
|
||||
OMPI_CHECK_WITHDIR([libnl3-libdir], [$with_libnl3_libdir], [libnl-3.*])
|
||||
|
||||
ompi_check_libnl3_$1_save_CPPFLAGS="$CPPFLAGS"
|
||||
ompi_check_libnl3_$1_save_LDFLAGS="$LDFLAGS"
|
||||
ompi_check_libnl3_$1_save_LIBS="$LIBS"
|
||||
|
||||
ompi_check_libnl3_$1_orig_CPPFLAGS="$$1_CPPFLAGS"
|
||||
ompi_check_libnl3_$1_orig_LDFLAGS="$$1_LDFLAGS"
|
||||
ompi_check_libnl3_$1_orig_LIBS="$$1_LIBS"
|
||||
|
||||
AS_IF([test "$with_libnl3" != "no"],
|
||||
[AS_IF([test ! -z "$with_libnl3" -a "$with_libnl3" != "yes"],
|
||||
[ompi_check_libnl3_dir="$with_libnl3"])
|
||||
AS_IF([test ! -z "$with_libnl3_libdir" -a "$with_libnl3_libdir" != "yes"],
|
||||
[ompi_check_libnl3_libdir="$with_libnl3_libdir"])
|
||||
|
||||
# OMPI_CHECK_PACKAGE unfortunately can't handle this weird include
|
||||
# dir layout
|
||||
AS_IF([test -n "$ompi_check_libnl3_dir"],
|
||||
[ompi_check_libnl3_includedir="$ompi_check_libnl3_dir/include/libnl3"],
|
||||
[ompi_check_libnl3_includedir="/usr/include/libnl3"])
|
||||
$1_CPPFLAGS="$$1_CPPFLAGS -I$ompi_check_libnl3_includedir"
|
||||
CPPFLAGS="$CPPFLAGS -I$ompi_check_libnl3_includedir"
|
||||
|
||||
AC_CHECK_HEADER([netlink/netlink.h],
|
||||
[# nl_recvmsgs_report appears to be a symbol which
|
||||
# is present in libnl-3 but not libnl (v1)
|
||||
_OMPI_CHECK_PACKAGE_LIB([$1],
|
||||
[nl-3],
|
||||
[nl_recvmsgs_report],
|
||||
[],
|
||||
[$ompi_check_libnl3_dir],
|
||||
[$ompi_check_libnl3_libdir],
|
||||
[ompi_check_libnl3_happy="yes"],
|
||||
[ompi_check_libnl3_happy="no"])],
|
||||
[ompi_check_libnl3_happy=no])
|
||||
|
||||
# make sure that we don't pollute the cache with the results of a
|
||||
# test performed under different CPPFLAGS
|
||||
AS_UNSET([ac_cv_header_netlink_netlink_h])],
|
||||
[ompi_check_libnl3_happy="no"])
|
||||
|
||||
# restore global flags
|
||||
CPPFLAGS="$ompi_check_libnl3_$1_save_CPPFLAGS"
|
||||
LDFLAGS="$ompi_check_libnl3_$1_save_LDFLAGS"
|
||||
LIBS="$ompi_check_libnl3_$1_save_LIBS"
|
||||
|
||||
AS_IF([test "$ompi_check_libnl3_happy" = "yes"],
|
||||
[$2],
|
||||
[AS_IF([test ! -z "$with_libnl3" -a "$with_libnl3" != "no"],
|
||||
[AC_MSG_ERROR([libnl3 support requested but not found. Aborting])])
|
||||
# restore prefixed flags on failure
|
||||
$1_CPPFLAGS="$ompi_check_package_$1_orig_CPPFLAGS"
|
||||
$1_LDFLAGS="$ompi_check_package_$1_orig_LDFLAGS"
|
||||
$1_LIBS="$ompi_check_package_$1_orig_LIBS"
|
||||
$3])
|
||||
])
|
||||
|
||||
# MCA_ompi_btl_usnic_POST_CONFIG([should_build])
|
||||
# ------------------------------------------
|
||||
AC_DEFUN([MCA_ompi_btl_usnic_POST_CONFIG], [
|
||||
AM_CONDITIONAL([OMPI_BTL_USNIC_BUILD_UNIT_TESTS],
|
||||
[test "$1" -eq 1 && test "X$enable_ompi_btl_usnic_unit_tests" = "Xyes"])
|
||||
])
|
||||
|
||||
# MCA_btl_usnic_CONFIG([action-if-can-compile],
|
||||
# [action-if-cant-compile])
|
||||
@ -27,6 +109,20 @@
|
||||
AC_DEFUN([MCA_ompi_btl_usnic_CONFIG],[
|
||||
AC_CONFIG_FILES([ompi/mca/btl/usnic/Makefile])
|
||||
|
||||
# see README.test for information about this scheme
|
||||
AC_ARG_ENABLE([ompi-btl-usnic-unit-tests],
|
||||
[AS_HELP_STRING([--enable-ompi-btl-usnic-unit-tests],
|
||||
[build unit tests for the usnic BTL,
|
||||
including the test runner program,
|
||||
ompi_btl_usnic_run_tests])])
|
||||
AS_IF([test "X$enable_ompi_btl_usnic_unit_tests" = "Xyes"],
|
||||
[unit_tests=1
|
||||
AC_MSG_NOTICE([enabling usnic BTL unit tests])],
|
||||
[unit_tests=0])
|
||||
AC_DEFINE_UNQUOTED([OMPI_BTL_USNIC_UNIT_TESTS], [$unit_tests],
|
||||
[define to 1 if usnic BTL unit tests are enabled, 0 otherwise])
|
||||
unset unit_tests
|
||||
|
||||
OMPI_CHECK_OPENFABRICS([btl_usnic],
|
||||
[btl_usnic_happy="yes"],
|
||||
[btl_usnic_happy="no"])
|
||||
|
101
ompi/mca/btl/usnic/test/ompi_btl_usnic_run_tests.c
Обычный файл
101
ompi/mca/btl/usnic/test/ompi_btl_usnic_run_tests.c
Обычный файл
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Cisco Systems, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
/* A simple test runner program for the usnic BTL unit tests. See README.test
|
||||
* for more information. */
|
||||
|
||||
/* for dladdr() */
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <libgen.h> /* for dirname() */
|
||||
#include <mpi.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#define MCA_BTL_USNIC_SO "mca_btl_usnic.so"
|
||||
|
||||
typedef void (*run_tests_fn_t)(void);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *mpi_handle;
|
||||
void *usnic_handle;
|
||||
void (*run_tests)(void);
|
||||
int (*init)(int *, char ***);
|
||||
int (*finalize)(void);
|
||||
Dl_info info;
|
||||
char *libmpi_path;
|
||||
char *path;
|
||||
char *to;
|
||||
int path_len;
|
||||
|
||||
mpi_handle = dlopen("libmpi.so", RTLD_NOW|RTLD_GLOBAL);
|
||||
if (mpi_handle == NULL) {
|
||||
fprintf(stderr, "mpi_handle=NULL dlerror()=%s\n", dlerror());
|
||||
abort();
|
||||
}
|
||||
|
||||
/* casting awfulness needed for GCC's "-pedantic" option :( */
|
||||
*(void **)(&init) = dlsym(mpi_handle, "MPI_Init");
|
||||
if (init == NULL) {
|
||||
fprintf(stderr, "init=NULL dlerror()=%s\n", dlerror());
|
||||
abort();
|
||||
}
|
||||
/* casting awfulness needed for GCC's "-pedantic" option :( */
|
||||
*(void **)(&finalize) = dlsym(mpi_handle, "MPI_Finalize");
|
||||
if (finalize == NULL) {
|
||||
fprintf(stderr, "finalize=%p dlerror()=%s\n", *(void **)(&finalize), dlerror());
|
||||
abort();
|
||||
}
|
||||
|
||||
/* call MPI_Init this way to avoid build-time dependency issues */
|
||||
init(&argc, &argv);
|
||||
|
||||
/* figure out where the usnic BTL shared object is relative to libmpi.so */
|
||||
if (!dladdr(*(void **)(&init), &info)) {
|
||||
fprintf(stderr, "ERROR: unable to dladdr(init,...)\n");
|
||||
abort();
|
||||
}
|
||||
libmpi_path = strdup(info.dli_fname);
|
||||
assert(libmpi_path != NULL);
|
||||
path_len = strlen(libmpi_path) + strlen("/openmpi/") + strlen(MCA_BTL_USNIC_SO);
|
||||
path = calloc(path_len+1, 1);
|
||||
to = path;
|
||||
to = stpcpy(to, dirname(libmpi_path));
|
||||
to = stpcpy(to, "/openmpi/");
|
||||
to = stpcpy(to, MCA_BTL_USNIC_SO);
|
||||
|
||||
usnic_handle = dlopen(path, RTLD_NOW|RTLD_LOCAL);
|
||||
if (usnic_handle == NULL) {
|
||||
fprintf(stderr, "usnic_handle=%p dlerror()=%s\n", (void *)usnic_handle, dlerror());
|
||||
abort();
|
||||
}
|
||||
|
||||
free(libmpi_path);
|
||||
free(path);
|
||||
|
||||
/* casting awfulness needed for GCC's "-pedantic" option :( */
|
||||
*(void **)(&run_tests) = dlsym(usnic_handle, "ompi_btl_usnic_run_tests");
|
||||
if (run_tests == NULL) {
|
||||
fprintf(stderr, "run_tests=%p dlerror()=%s\n", *(void **)(&run_tests), dlerror());
|
||||
abort();
|
||||
}
|
||||
run_tests();
|
||||
|
||||
finalize();
|
||||
|
||||
/* deliberately do not dlclose() either handle so that any valgrind stack
|
||||
* traces are more useful */
|
||||
|
||||
return 0;
|
||||
}
|
Загрузка…
x
Ссылка в новой задаче
Block a user