/* Charmonizer/Test.h - test Charmonizer's output.
 */

#ifndef H_CHAZ_TEST
#define H_CHAZ_TEST

#include "Charmonizer/Core/Defines.h"

typedef struct chaz_TestBatch chaz_TestBatch;

/* Destructor.
 */
typedef void
(*chaz_TestBatch_destroy_t)(chaz_TestBatch *batch);

/* This function, which is unique to each TestBatch, actually runs the test
 * sequence.
 */
typedef void
(*chaz_TestBatch_test_func_t)(chaz_TestBatch *batch);

/* Print a header, execute the test sequence, print a report.
 */
typedef void
(*chaz_TestBatch_run_test_t)(chaz_TestBatch *batch);

struct chaz_TestBatch {
    char         *name;
    unsigned      test_num;
    unsigned      num_tests;
    unsigned      num_passed;
    unsigned      num_failed; 
    unsigned      num_skipped;
    chaz_TestBatch_destroy_t      destroy;
    chaz_TestBatch_test_func_t    test_func;
    chaz_TestBatch_run_test_t     run_test;
};

/* Unbuffer stdout.  Perform any other setup needed.
 */
void
chaz_Test_init(void);

/* Constructor for TestBatch.
 */
chaz_TestBatch* 
chaz_Test_new_batch(const char *batch_name, unsigned num_tests,
				    chaz_TestBatch_test_func_t test_func);

/* Note: maybe add line numbers later.
 */
#define CHAZ_TEST_ASSERT_TRUE       chaz_Test_assert_true
#define CHAZ_TEST_ASSERT_FALSE      chaz_Test_assert_false
#define CHAZ_TEST_ASSERT_STR_EQ     chaz_Test_assert_str_eq
#define CHAZ_TEST_ASSERT_STR_NEQ    chaz_Test_assert_str_neq
#define CHAZ_TEST_PASS              chaz_Test_pass
#define CHAZ_TEST_FAIL              chaz_Test_fail
#define CHAZ_TEST_ASSERT_INT_EQ     chaz_Test_assert_int_eq
#define CHAZ_TEST_ASSERT_FLOAT_EQ   chaz_Test_assert_float_eq

/* Print a message indicating that a test was skipped and update batch.
 */
#define CHAZ_TEST_SKIP(batch, message) \
        chaz_Test_skip(batch, message)

/* Print a message indicating that all remaining tests will be skipped and
 * return.
 */
#define CHAZ_TEST_SKIP_REMAINING(batch, message) \
    do { \
        chaz_Test_report_skip_remaining(batch, message); \
        return; \
    } while (0)


void 
chaz_Test_assert_true(chaz_TestBatch *batch, int expression, 
                          const char *pat, ...);

void 
chaz_Test_assert_false(chaz_TestBatch *batch, int expression, 
                           const char *pat, ...);

void 
chaz_Test_assert_str_eq(chaz_TestBatch *batch, const char *expected, 
                            const char *got, const char *pat, ...);

void 
chaz_Test_assert_str_neq(chaz_TestBatch *batch, const char *expected,
                             const char *got, const char *pat, ...);

void 
chaz_Test_pass(chaz_TestBatch *batch, const char *pat, ...);

void 
chaz_Test_fail(chaz_TestBatch *batch, const char *pat, ...);

void 
chaz_Test_assert_int_eq(chaz_TestBatch *batch, long expected, long got, 
                            const char *pat, ...);

void 
chaz_Test_assert_float_eq(chaz_TestBatch *batch, double expected, 
                              double got, const char *pat, ...);

void
chaz_Test_skip(chaz_TestBatch *batch, const char *pat, ...);

void
chaz_Test_report_skip_remaining(chaz_TestBatch* batch, 
                                    const char *pat, ...);

#ifdef CHAZ_USE_SHORT_NAMES
  #define TestBatch_destroy_t          chaz_TestBatch_destroy_t
  #define TestBatch_test_func_t        chaz_TestBatch_test_func_t
  #define TestBatch_run_test_t         chaz_TestBatch_run_test_t
  #define TestBatch                    chaz_TestBatch
  #define Test_init                    chaz_Test_init
  #define Test_new_batch               chaz_Test_new_batch
  #define ASSERT_TRUE                  CHAZ_TEST_ASSERT_TRUE
  #define ASSERT_FALSE                 CHAZ_TEST_ASSERT_FALSE
  #define ASSERT_STR_EQ                CHAZ_TEST_ASSERT_STR_EQ
  #define ASSERT_STR_NEQ               CHAZ_TEST_ASSERT_STR_NEQ
  #define PASS                         CHAZ_TEST_PASS
  #define FAIL                         CHAZ_TEST_FAIL
  #define ASSERT_INT_EQ                CHAZ_TEST_ASSERT_INT_EQ
  #define ASSERT_FLOAT_EQ              CHAZ_TEST_ASSERT_FLOAT_EQ
  #define SKIP                         CHAZ_TEST_SKIP
  #define SKIP_REMAINING               CHAZ_TEST_SKIP_REMAINING
#endif

#endif /* H_CHAZ_TEST */


/* Copyright 2006-2007 Marvin Humphrey
 *
 * This program is free software; you can redistribute it and/or modify
 * under the same terms as Perl itself.
 */