<commit_before>//
// Copyright (c) 2010, <NAME>
// This software licensed under terms described in LICENSE.txt
//

#ifndef tinfra_test_macros_h_included
#define tinfra_test_macros_h_included

#include "fmt.h"
#include "tstring.h" 
#include "trace.h" // for tinfra::trace::location, TINFRA_SOURCE_LOCATION

namespace tinfra { 
namespace test {

/// Report test failure.
///
/// Reports a test failure described by message and source code location.
void report_test_failure(const char* filename, int line, const char* message);

#define SUITE(name) \
	namespace test_suite_##name { \
		inline const char* tinfra_test_suite_name() { return #name; } \
	} \
	namespace test_suite_##name

struct test_info {
	const char* name;
	const char* suite;
};

struct test_run_summary {
	int executed_test_count;
	int failed_test_count;
	int failure_count;
    float seconds_elapsed;
};

class test_result_sink {
public:
	virtual ~test_result_sink();

	virtual void report_test_start(test_info  const&) = 0;
	virtual void report_failure(test_info const& info, tinfra::trace::location const& location, tstring const& message) = 0;
	virtual void report_test_finish(test_info const&) = 0;
	virtual void report_summary(test_run_summary const&) = 0;
};

class default_test_result_sink: public test_result_sink {
public:
	default_test_result_sink();
	~default_test_result_sink();

	// test_result_sink interface
	void report_test_start(test_info  const&);
	void report_failure(test_info const& info, tinfra::trace::location const& location, tstring const& message);
	void report_test_finish(test_info const&);
	void report_summary(test_run_summary const&);
};

class test_base {
public:
	test_base(const char* suite_name, const char* test_name, tinfra::trace::location const& source_location);
	~test_base();
	void run(test_result_sink& result);
protected:
	virtual void run_impl() = 0;
public:
	const char* name;
	const char* suite;
	tinfra::trace::location source_location;
};

#define TEST(name) \
	class test_##name: public tinfra::test::test_base { \
	public: \
		test_##name(); \
	private: \
		virtual void run_impl(); \
	};\
	test_##name::test_##name(): \
	    tinfra::test::test_base(tinfra_test_suite_name(), #name, TINFRA_SOURCE_LOCATION()) \
    { } \
	test_##name test_instance_##name; \
	void test_##name::run_impl()

//
// equals
// equality_helper
//
template <typename T1, typename T2>
struct equality_helper {
	bool operator()(T1 const& a, T2 const& b) {
		return a == b;
	}
};

template <>
struct equality_helper<int, unsigned> {
	bool operator()(int a, unsigned b) {
		if( a < 0 ) {
			return false;
		} else {
			return unsigned(a) == b;
		}
	}
};

template <>
struct equality_helper<unsigned, int> {
	bool operator()(unsigned a, int b) {
		if( b < 0 ) {
			return false;
		} else {
			return unsigned(b) == a;
		}
	}
};

template <typename T1, typename T2>
bool equals(T1 const& a, T2 const& b)
{
	equality_helper<T1, T2> helper;
	return helper(a,b);
}

inline
bool equals(const char* a, const char* b)
{
	return tinfra::tstring(a) == tinfra::tstring(b);
}

//
// Check macros
//

/// Check basic equality
#define CHECK(predicate) \
	do {  if( !(predicate) ) { \
			std::string msg = tinfra::fmt("predicate %s failed") % #predicate; \
            ::tinfra::test::report_test_failure(__FILE__, __LINE__, msg.c_str()); \
		} \
	} while ( 0 );

/// Check basic equality
#define CHECK_EQUAL(expected, actual) \
	do {  if( !tinfra::test::equals(expected,actual) ) { \
			std::string msg = tinfra::fmt("expected '%s', but found '%s'") % expected % actual; \
            ::tinfra::test::report_test_failure(__FILE__, __LINE__, msg.c_str()); \
		} \
	} while ( 0 )

#define CHECK_THROW(statement, exception_type) \
	do {  bool expected_exception_caught = false; \
		  try { statement; } \
		  catch( exception_type&) { \
			  expected_exception_caught = true; \
		  } \
		  catch( ... ) { \
			  std::string msg = "unexpected exception caught"; \
              ::tinfra::test::report_test_failure(__FILE__, __LINE__, msg.c_str()); \
			  throw; \
		  } \
		  if( !expected_exception_caught ) { \
			  std::string msg = tinfra::fmt("expected exception %s not caught") % #exception_type; \
              ::tinfra::test::report_test_failure(__FILE__, __LINE__, msg.c_str()); \
		  } \
	} while ( 0 )<commit_msg>* test_macros.h: CHECK_CLOSE macro added<commit_after>//
// Copyright (c) 2010, <NAME>
// This software licensed under terms described in LICENSE.txt
//

#ifndef tinfra_test_macros_h_included
#define tinfra_test_macros_h_included

#include "fmt.h"
#include "tstring.h" 
#include "trace.h" // for tinfra::trace::location, TINFRA_SOURCE_LOCATION

namespace tinfra { 
namespace test {

/// Report test failure.
///
/// Reports a test failure described by message and source code location.
void report_test_failure(const char* filename, int line, const char* message);

#define SUITE(name) \
	namespace test_suite_##name { \
		inline const char* tinfra_test_suite_name() { return #name; } \
	} \
	namespace test_suite_##name

struct test_info {
	const char* name;
	const char* suite;
};

struct test_run_summary {
	int executed_test_count;
	int failed_test_count;
	int failure_count;
    float seconds_elapsed;
};

class test_result_sink {
public:
	virtual ~test_result_sink();

	virtual void report_test_start(test_info  const&) = 0;
	virtual void report_failure(test_info const& info, tinfra::trace::location const& location, tstring const& message) = 0;
	virtual void report_test_finish(test_info const&) = 0;
	virtual void report_summary(test_run_summary const&) = 0;
};

class default_test_result_sink: public test_result_sink {
public:
	default_test_result_sink();
	~default_test_result_sink();

	// test_result_sink interface
	void report_test_start(test_info  const&);
	void report_failure(test_info const& info, tinfra::trace::location const& location, tstring const& message);
	void report_test_finish(test_info const&);
	void report_summary(test_run_summary const&);
};

class test_base {
public:
	test_base(const char* suite_name, const char* test_name, tinfra::trace::location const& source_location);
	~test_base();
	void run(test_result_sink& result);
protected:
	virtual void run_impl() = 0;
public:
	const char* name;
	const char* suite;
	tinfra::trace::location source_location;
};

#define TEST(name) \
	class test_##name: public tinfra::test::test_base { \
	public: \
		test_##name(); \
	private: \
		virtual void run_impl(); \
	};\
	test_##name::test_##name(): \
	    tinfra::test::test_base(tinfra_test_suite_name(), #name, TINFRA_SOURCE_LOCATION()) \
    { } \
	test_##name test_instance_##name; \
	void test_##name::run_impl()

//
// equals
// equality_helper
//
template <typename T1, typename T2>
struct equality_helper {
	bool operator()(T1 const& a, T2 const& b) {
		return a == b;
	}
};

template <>
struct equality_helper<int, unsigned> {
	bool operator()(int a, unsigned b) {
		if( a < 0 ) {
			return false;
		} else {
			return unsigned(a) == b;
		}
	}
};

template <>
struct equality_helper<unsigned, int> {
	bool operator()(unsigned a, int b) {
		if( b < 0 ) {
			return false;
		} else {
			return unsigned(b) == a;
		}
	}
};

template <typename T1, typename T2>
bool equals(T1 const& a, T2 const& b)
{
	equality_helper<T1, T2> helper;
	return helper(a,b);
}

inline
bool equals(const char* a, const char* b)
{
	return tinfra::tstring(a) == tinfra::tstring(b);
}

//
// Check macros
//

/// Check basic equality
#define CHECK(predicate) \
	do {  if( !(predicate) ) { \
			std::string msg = tinfra::fmt("predicate %s failed") % #predicate; \
            ::tinfra::test::report_test_failure(__FILE__, __LINE__, msg.c_str()); \
		} \
	} while ( 0 );

/// Check basic equality
#define CHECK_EQUAL(expected, actual) \
	do {  if( !tinfra::test::equals(expected,actual) ) { \
			std::string msg = tinfra::fmt("expected '%s', but found '%s'") % expected % actual; \
            ::tinfra::test::report_test_failure(__FILE__, __LINE__, msg.c_str()); \
		} \
	} while ( 0 )

/// Check value equality with tolerance
/// 
/// Checks if distance of between actual and expected is less or equal tollerancy.
/// 
/// TBD, the expressions are repeated, need to fix this in all
/// CHECK_... macros (see http://unittest-cpp.sourceforge.net/UnitTest++.html, Simple check macros)
// they have to be revamped as templates

#define CHECK_CLOSE(expected, actual, tollerancy) \
	do { if( ((expected) - (actual)) > (tollerancy) ) { \
		std::string msg = tinfra::fmt("expected %s (+/i %s) but found %s") % (expected) % (tollerancy) % (actual); \
		::tinfra::test::report_test_failure(__FILE__, __LINE__, msg.c_str()); \
	} }  while ( 0 )

#define CHECK_THROW(statement, exception_type) \
	do {  bool expected_exception_caught = false; \
		  try { statement; } \
		  catch( exception_type&) { \
			  expected_exception_caught = true; \
		  } \
		  catch( ... ) { \
			  std::string msg = "unexpected exception caught"; \
              ::tinfra::test::report_test_failure(__FILE__, __LINE__, msg.c_str()); \
			  throw; \
		  } \
		  if( !expected_exception_caught ) { \
			  std::string msg = tinfra::fmt("expected exception %s not caught") % #exception_type; \
              ::tinfra::test::report_test_failure(__FILE__, __LINE__, msg.c_str()); \
		  } \
	} while ( 0 )
{'fraction_non_alphanumeric': 0.1420099202070304, 'fraction_numerical': 0.005283588527064913, 'mean_word_length': 4.084978070175438, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '313189', 'n_tokens_mistral': 3371, 'n_tokens_neox': 3166, 'n_words': 789}