#include <pslib.h>

#include "tap.h"

#define done() ok(psMemCheckLeaks(0, NULL, stdout, false) == 0, "Memory Leaks"); \
return exit_status()

       # define mem() ok(psMemCheckLeaks(psMemGetLastId(), NULL, stdout, false) == 0, "Memory Leaks")

       # define checkLeaks false

       # define checkMem() if(checkLeaks) mem()

           # ifdef __GNUC__

           // write a comment which is counted as a test (and swallowed by prove)
           # define note(A, ...){ \
           fprintf(stdout, A, ## __VA_ARGS__); \
           fprintf(stdout, "\n[%s:%d in %s]\n", __FILE__, __LINE__, __func__); }

       // write a comment which is counted as a test (and swallowed by prove)
       # define noted(A, ...) _gen_result(1, __func__, __FILE__, __LINE__, A, ## __VA_ARGS__);

// use to test the value of a float
# define ok_float(VALUE,EXPECT,COMMENT, ...)\
ok((fabsf((VALUE)-(EXPECT)) < FLT_EPSILON), COMMENT, ## __VA_ARGS__);

// use to test the value of a double
# define ok_double(VALUE,EXPECT,COMMENT, ...)\
ok((fabs((VALUE)-(EXPECT)) < DBL_EPSILON), COMMENT, ## __VA_ARGS__);

// use to test the value of a float within a defined tolerance
# define ok_float_tol(VALUE,EXPECT,TOL,COMMENT, ...)\
{ \
    bool status = (fabsf((VALUE) - (EXPECT)) < (TOL)); \
    ok(status, COMMENT, ## __VA_ARGS__); \
    if (!status) { \
        diag("         got: '%f'", VALUE); \
        diag("    expected: '%f' +/- %f", EXPECT, TOL); \
    } \
}

// use to test the value of a double within a defined tolerance
# define ok_double_tol(VALUE,EXPECT,TOL,COMMENT, ...)\
{ \
    bool status = (fabs((VALUE) - (EXPECT)) < (TOL)); \
    ok(status, COMMENT, ## __VA_ARGS__); \
    if (!status) { \
        diag("         got: '%f'", VALUE); \
        diag("    expected: '%f' +/- %f", EXPECT, TOL); \
    } \
}

# define ok_str(VALUE, EXPECT, COMMENT, ...) \
{ \
    int cmp = (strcmp(VALUE, EXPECT) == 0); \
    ok(cmp, COMMENT, ## __VA_ARGS__); \
    if (!cmp) { \
        diag("         got: '%s'", VALUE); \
        diag("    expected: '%s'", EXPECT); \
    } \
}

# define ok_strn(VALUE, EXPECT, N, COMMENT, ...)\
{ \
    int cmp = (strncmp(VALUE, EXPECT, N) == 0); \
    ok(cmp, COMMENT, ## __VA_ARGS__); \
    if (!cmp) { \
        diag("         got: '%s'", VALUE); \
        diag("    expected: '%s'", EXPECT); \
    } \
}

#elif __STDC_VERSION__ >= 199901L /* __GNUC__ */

// write a comment which is counted as a test (and swallowed by prove)
// write a comment which is counted as a test (and swallowed by prove)
# define note(A, ...){ \
    fprintf(stdout, A, ...); \
    fprintf(stdout, "\n[%s:%d in %s]\n", __FILE__, __LINE__, __func__); }

// use to test the value of a float
# define ok_float(VALUE,EXPECT, ...)\
ok((fabsf((VALUE)-(EXPECT)) < FLT_EPSILON), __VA_ARGS__);

// use to test the value of a double
# define ok_double(VALUE,EXPECT, ...)\
ok((fabs((VALUE)-(EXPECT)) < DBL_EPSILON), __VA_ARGS__);

// use to test the value of a float
# define ok_float_tol(VALUE,EXPECT,TOL, ...)\
{ \
    bool status = (fabsf((VALUE) - (EXPECT)) < (TOL)); \
    ok(status, __VA_ARGS__); \
    if (!status) { \
        diag("         got: '%f'", VALUE); \
        diag("    expected: '%f' +/- %f", EXPECT, TOL); \
    } \
}

// use to test the value of a double
# define ok_double_tol(VALUE,EXPECT,TOL, ...)\
{ \
    bool status = (fabs((VALUE) - (EXPECT)) < (TOL)); \
    ok(status, __VA_ARGS__); \
    if (!status) { \
        diag("         got: '%f'", VALUE); \
        diag("    expected: '%f' +/- %f", EXPECT, TOL); \
    } \
}

# define ok_str(VALUE, EXPECT, ...) \
{ \
    int cmp = (strcmp(VALUE, EXPECT) == 0); \
    ok(cmp, COMMENT,  __VA_ARGS__); \
    if (!cmp) { \
        diag("         got: '%s'", VALUE); \
        diag("    expected: '%s'", EXPECT); \
    } \
}

# define ok_strn(VALUE, EXPECT, N, ...)\
{ \
    int cmp = (strncmp(VALUE, EXPECT, N) == 0); \
    ok(cmp, COMMENT,  __VA_ARGS__); \
    if (!cmp) { \
        diag("         got: '%s'", VALUE); \
        diag("    expected: '%s'", EXPECT); \
    } \
}

#else /* __STDC_VERSION__ */
# error "Needs gcc or C99 compiler for variadic macros."
#endif /* __STDC_VERSION__ */
