/*
 * 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 "opal_config.h"

typedef int (*opal_btl_usnic_test_fn_t)(void *ctx);

#if OPAL_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 opal_btl_usnic_num_tests_run;
extern int opal_btl_usnic_num_tests_passed;
extern int opal_btl_usnic_num_tests_failed;
extern int opal_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) \
        {                                                                                         \
            opal_btl_usnic_register_test(name, test_fn, ctx);                                     \
        }

#else /* !OPAL_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 opal_btl_usnic_run_tests(void);

void opal_btl_usnic_register_test(const char *name, opal_btl_usnic_test_fn_t test_fn, void *ctx);

/* should be called once, at component close time */
void opal_btl_usnic_cleanup_tests(void);

#endif /* BTL_USNIC_TEST_H */
