#ifndef TEST_H
#define TEST_H

//   correctness
//   performance
//   demo
//   temporary

#ifndef DBC_H
#include "DbC.h"
#endif

#define TEST(assertion, condition) \
    test (assertion, condition, #condition, __FILE__, __LINE__)

#define DOUBLES_EQUAL(expected, actual, threshold)   \
	double_equal (expected, actual, threshold, __FILE__, __LINE__) 

#define FAIL(assertion) \
    fail (assertion, __FILE__, __LINE__)

namespace MM
{

class Text_output;

class Test : protected DbC
{
    Text_output     *out_;

    int             passed_;
    int             failed_;
    int             counter_;
    bool            no_testing_;
    double          duration_;

public:
                    Test ();
    explicit        Test (const Text & suite_name);
    virtual        ~Test();

    void            set_output (Text_output & output) {out_= &output;}

    void            run_test ();

    int             passed () const          {return passed_;}
    int             failed () const          {return failed_;}

protected:
    virtual void    run () = 0;
    void            count_tests ();
    void            report () const;

    void            test         (const Text& assertion,
                                  bool        condition, 
                                  const Text& condition_str,
                                  const char* file_name, 
                                  int         line_number );

    void            fail         (const Text& condition_str,
                                  const char* file_name, 
                                  int         line_number);

    void            double_equal (double      expected, 
                                  double      actual, 
                                  double      threshold,
                                  const char* file_name, 
                                  int         line_number);

    void            crash();

private:
    Test(const Test&);
    Test& operator=(const Test&);
};

}//MM

#endif //TEST_H

