/*
 * This file is part of Beastie <https://purl.org/nxg/dist/beastie>
 * SPDX-FileCopyrightText: 2024 Norman Gray <https://nxg.me.uk>
 * SPDX-License-Identifier: BSD-2-Clause
 */

#ifndef CUNIT_H_LOADED
#define CUNIT_H_LOADED 1

#include <string.h>
#include <stdint.h>

#define xstr(s) str(s)
#define str(s) #s

void assert_equal_int_fn(const char* label, int actual, int expected);
#define assert_equal_int(actual, expected)                     \
    do {                                                        \
        assert_equal_int_fn(#actual ":" xstr(__LINE__), (actual), (expected)); \
    } while(0)

void assert_equal_uint_fn(const char* label, unsigned int actual, unsigned int expected);
#define assert_equal_uint(actual, expected)                     \
    do {                                                        \
        assert_equal_uint_fn(#actual ":" xstr(__LINE__), (actual), (expected)); \
    } while(0)

void assert_equal_int32_array_fn(const char* label,
                                 const int32_t* actual,
                                 const int32_t* expected,
                                 size_t n);
#define assert_equal_int32_array(actual, expected, n)            \
    do {                                                                \
        assert_equal_int32_array_fn(#actual ":" xstr(__LINE__), (actual), (expected), (n)); \
    } while(0)

void assert_equal_uint32_array_fn(const char* label,
                                  const uint32_t* actual,
                                  const uint32_t* expected,
                                  size_t n);
#define assert_equal_uint32_array(actual, expected, n)            \
    do {                                                                \
        assert_equal_uint32_array_fn(#actual ":" xstr(__LINE__), (actual), (expected), (n)); \
    } while(0)

void assert_equal_uint16_array_fn(const char* label,
                                  const uint16_t* actual,
                                  const uint16_t* expected,
                                  size_t n);
#define assert_equal_uint16_array(actual, expected, n)            \
    do {                                                                \
        assert_equal_uint16_array_fn(#actual ":" xstr(__LINE__), (actual), (expected), (n)); \
    } while(0)

void assert_equal_uint8_array_fn(const char* label,
                                  const uint8_t* actual,
                                  const uint8_t* expected,
                                  size_t n);
#define assert_equal_uint8_array(actual, expected, n)            \
    do {                                                                \
        assert_equal_uint8_array_fn(#actual ":" xstr(__LINE__), (actual), (expected), (n)); \
    } while(0)

void assert_equal_sn_fn(const char* label,
                        const unsigned char* actual, int actual_len,
                        const char* expected);
#define assert_equal_sn(actual, actual_len, expected)                   \
    do {                                                                \
        assert_equal_sn_fn(#actual ":" xstr(__LINE__), (const unsigned char*)actual, actual_len, expected); \
    } while (0)
#define assert_equal_s(actual, expected)                                \
    do {                                                                \
        assert_equal_sn_fn(#actual ":" xstr(__LINE__), (const unsigned char*)actual, strlen(actual), expected);  \
    } while (0)
// test a byte-string
#define assert_equal_bn(actual, actual_len, expected)                   \
    do {                                                                \
        assert_equal_sn_fn(#actual ":" xstr(__LINE__), actual, actual_len, expected); \
    } while (0)

void assert_equal_ptr_fn(const char* label,
                         const void* actual,
                         const void* expected);
#define assert_equal_ptr(actual, expected)              \
    do {                                                \
        assert_equal_ptr_fn(#actual ":" xstr(__LINE__), (actual), (expected)); \
    } while (0)
#define assert_null(actual)\
    do { assert_equal_ptr_fn(#actual ":" xstr(__LINE__), (actual), NULL); } while (0)
#define assert_not_null(actual)\
    do { assert_true_fn(#actual ":" xstr(__LINE__), (actual != NULL)); } while (0)

#define assert_true(actual)\
    do { assert_true_fn(#actual ":" xstr(__LINE__), (actual)); } while (0)
#define assert_false(actual)\
    do { assert_false_fn(#actual ":" xstr(__LINE__), (actual)); } while (0)
void assert_true_fn(const char* label, int actual);
void assert_false_fn(const char* label, int actual);

void assert_success(const char* label);
void assert_fail(const char* label);

void run_test_suite(const char* name, void(*fn)(void));
int report_status(void);

#endif /* CUNIT_H_LOADED */
