<commit_before>/* 
 * bfc-testsuite

  Copyright (C) 2005-2008 <NAME>, www.crupp.de

  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the authors be held liable for any damages
  arising from the use of this software.

  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
  freely, subject to the following restrictions:

  1. The origin of this software must not be misrepresented; you must not
     claim that you wrote the original software. If you use this software
     in a product, an acknowledgment in the product documentation would be
     appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not be
     misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.
 *
 */

#ifndef BFC_TESTSUITE_HPP__
#define BFC_TESTSUITE_HPP__

#include <vector>
#include <string>
#include <iostream>
#include <stdarg.h>

#if defined(_MSC_VER)
#include <windows.h>    // __try/__except support API
#endif

namespace bfc {

// forward declarations
class fixture;
class testrunner;

typedef void (fixture::*method)();

#define BFC_REGISTER_TEST(cls, mthd)  register_test(#mthd, (method)&cls::mthd)

#define BFC_REGISTER_FIXTURE(fix)     static fix __the_fixture##fix

#define BFC_ASSERT(expr)  \
                        while ((expr)==0) { \
                            throw error(__FILE__, __LINE__, \
                            get_name(), __FUNCTION__, \
                            "assertion failed in expr "#expr); }

#define BFC_ASSERT_EQUAL(exp, act) \
                        while ((exp)!=(act)) { \
                            throw error(__FILE__, __LINE__, \
                            get_name(), __FUNCTION__, \
                            "assertion failed in expr "#exp" == "#act); }

#define BFC_ASSERT_NOTEQUAL(exp, act) \
                        while ((exp)==(act)) { \
                            throw error(__FILE__, __LINE__, \
                            get_name(), __FUNCTION__, \
                            "assertion failed in expr "#exp" != "#act); }

#define BFC_ASSERT_NULL(expr)  \
                        while ((expr)!=0) { \
                            throw error(__FILE__, __LINE__, \
                            get_name(), __FUNCTION__, \
                            "assertion failed in expr "#expr" == NULL"); }

#define BFC_ASSERT_NOTNULL(expr)  \
                        while ((expr)==0) { \
                            throw error(__FILE__, __LINE__, \
                            get_name(), __FUNCTION__, \
                            "assertion failed in expr "#expr" != NULL"); }

// for checks within loops: report round # as 'scenario #'
#define BFC_ASSERT_I(expr, scenario)  \
                        while ((expr)==0) { \
                            throw error(__FILE__, __LINE__, \
                            get_name(), __FUNCTION__, \
							"assertion failed in expr "#expr " for scenario #%d", int(scenario)); }

#define BFC_ASSERT_EQUAL_I(exp, act, scenario) \
                        while ((exp)!=(act)) { \
                            throw error(__FILE__, __LINE__, \
                            get_name(), __FUNCTION__, \
							"assertion failed in expr "#exp" == "#act " for scenario #%d", int(scenario)); }

#define BFC_ASSERT_NOTEQUAL_I(exp, act, scenario) \
                        while ((exp)==(act)) { \
                            throw error(__FILE__, __LINE__, \
                            get_name(), __FUNCTION__, \
							"assertion failed in expr "#exp" != "#act " for scenario #%d", int(scenario)); }

#define BFC_ASSERT_NULL_I(expr, scenario)  \
                        while ((expr)!=0) { \
                            throw error(__FILE__, __LINE__, \
                            get_name(), __FUNCTION__, \
							"assertion failed in expr "#expr" == NULL for scenario #%d", int(scenario)); }

#define BFC_ASSERT_NOTNULL_I(expr, scenario)  \
                        while ((expr)==0) { \
                            throw error(__FILE__, __LINE__, \
                            get_name(), __FUNCTION__, \
							"assertion failed in expr "#expr" != NULL for scenario #%d", int(scenario)); }

struct test
{
	std::string name;
    method foo;
};

struct error
{
    error(const char *f, int l, const char *fix, const char *t, const char *m, ...) 
    :   file(f), line(l), fixture(fix), test(t)
    {
	va_list a;
	va_start(a, m);
	char buf[2048];
	if (!m) m = "";
#if 0 // general use, so no direct dependency on hamster:util.h
	util_vsnprintf(buf, sizeof(buf), m, a);
#else
#if defined(HAM_OS_POSIX)
    vsnprintf(buf, sizeof(buf), m, a);
#elif defined(HAM_OS_WIN32)
    _vsnprintf(buf, sizeof(buf), m, a);
#elif defined(_MSC_VER)
    _vsnprintf(buf, sizeof(buf), m, a);
#else
    vsprintf(buf, m, a); // unsafe
#endif
#endif
	va_end(a);
	buf[sizeof(buf)-1] = 0;
	message = buf;
	}

    std::string file;
    int line;
    std::string fixture;
    std::string test;
    std::string message;
};

class fixture
{
public:
    fixture(const char *name)
        : m_name(name)
    { }

    virtual ~fixture()
    { }

    const char *get_name() const
    { return m_name; }

    virtual void setup() { }
    virtual void teardown() { }

	/*
	   Invoke the Function Under Test

	   implement this one when you want to catch custom C++ exceptions;
	   these must be converted to bfc::error class throwing exceptions 
	   to work best with BFC.
	   
	   If you don't do this, your exceptions may be either caught by the
	   platform-specific SEH handler or fall through the test rig and
	   out the other side, losing information on the way, leading to
	   harder to analyze output.

	   @return
		Return TRUE when an exception occurred and the bfc::error ex
	    instance is filled accordingly, FALSE otherwise (~ successful test).
	*/
	virtual bool FUT_invoker(testrunner *me, method m, const char *funcname, error &ex)
	{
		(this->*m)();
		return false;
	}

	// clear all tests
    void clear_tests() {
        m_tests.resize(0);
    }

    // register a new test function
    void register_test(const char *name, method foo) {
		static method *m;<commit_msg>bfc exceptions are no longer getting lost<commit_after>/* 
 * bfc-testsuite

  Copyright (C) 2005-2008 <NAME>, www.crupp.de

  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the authors be held liable for any damages
  arising from the use of this software.

  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
  freely, subject to the following restrictions:

  1. The origin of this software must not be misrepresented; you must not
     claim that you wrote the original software. If you use this software
     in a product, an acknowledgment in the product documentation would be
     appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not be
     misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.
 *
 */

#ifndef BFC_TESTSUITE_HPP__
#define BFC_TESTSUITE_HPP__

#include <vector>
#include <string>
#include <iostream>
#include <stdarg.h>

#if defined(_MSC_VER)
#include <windows.h>    // __try/__except support API
#endif

namespace bfc {

// forward declarations
class fixture;
class testrunner;

typedef void (fixture::*method)();

#define BFC_REGISTER_TEST(cls, mthd)  register_test(#mthd, (method)&cls::mthd)

#define BFC_REGISTER_FIXTURE(fix)     static fix __the_fixture##fix

#define BFC_ASSERT(expr)  \
                        while ((expr)==0) { \
                            throw error(__FILE__, __LINE__, \
                            get_name(), __FUNCTION__, \
                            "assertion failed in expr "#expr); }

#define BFC_ASSERT_EQUAL(exp, act) \
                        while ((exp)!=(act)) { \
                            throw error(__FILE__, __LINE__, \
                            get_name(), __FUNCTION__, \
                            "assertion failed in expr "#exp" == "#act); }

#define BFC_ASSERT_NOTEQUAL(exp, act) \
                        while ((exp)==(act)) { \
                            throw error(__FILE__, __LINE__, \
                            get_name(), __FUNCTION__, \
                            "assertion failed in expr "#exp" != "#act); }

#define BFC_ASSERT_NULL(expr)  \
                        while ((expr)!=0) { \
                            throw error(__FILE__, __LINE__, \
                            get_name(), __FUNCTION__, \
                            "assertion failed in expr "#expr" == NULL"); }

#define BFC_ASSERT_NOTNULL(expr)  \
                        while ((expr)==0) { \
                            throw error(__FILE__, __LINE__, \
                            get_name(), __FUNCTION__, \
                            "assertion failed in expr "#expr" != NULL"); }

// for checks within loops: report round # as 'scenario #'
#define BFC_ASSERT_I(expr, scenario)  \
                        while ((expr)==0) { \
                            throw error(__FILE__, __LINE__, \
                            get_name(), __FUNCTION__, \
							"assertion failed in expr "#expr " for scenario #%d", int(scenario)); }

#define BFC_ASSERT_EQUAL_I(exp, act, scenario) \
                        while ((exp)!=(act)) { \
                            throw error(__FILE__, __LINE__, \
                            get_name(), __FUNCTION__, \
							"assertion failed in expr "#exp" == "#act " for scenario #%d", int(scenario)); }

#define BFC_ASSERT_NOTEQUAL_I(exp, act, scenario) \
                        while ((exp)==(act)) { \
                            throw error(__FILE__, __LINE__, \
                            get_name(), __FUNCTION__, \
							"assertion failed in expr "#exp" != "#act " for scenario #%d", int(scenario)); }

#define BFC_ASSERT_NULL_I(expr, scenario)  \
                        while ((expr)!=0) { \
                            throw error(__FILE__, __LINE__, \
                            get_name(), __FUNCTION__, \
							"assertion failed in expr "#expr" == NULL for scenario #%d", int(scenario)); }

#define BFC_ASSERT_NOTNULL_I(expr, scenario)  \
                        while ((expr)==0) { \
                            throw error(__FILE__, __LINE__, \
                            get_name(), __FUNCTION__, \
							"assertion failed in expr "#expr" != NULL for scenario #%d", int(scenario)); }

struct test
{
	std::string name;
    method foo;
};

struct error
{
    error(const char *f, int l, const char *fix, const char *t, const char *m, ...) 
    :   file(f), line(l), fixture(fix), test(t)
    {
	va_list a;
	va_start(a, m);
	char buf[2048];
	if (!m) m = "";
#if 0 // general use, so no direct dependency on hamster:util.h
	util_vsnprintf(buf, sizeof(buf), m, a);
#else
#if defined(HAM_OS_POSIX)
    vsnprintf(buf, sizeof(buf), m, a);
#elif defined(HAM_OS_WIN32)
    _vsnprintf(buf, sizeof(buf), m, a);
#elif defined(_MSC_VER)
    _vsnprintf(buf, sizeof(buf), m, a);
#else
    vsprintf(buf, m, a); // unsafe
#endif
#endif
	va_end(a);
	buf[sizeof(buf)-1] = 0;
	message = buf;
	}

    std::string file;
    int line;
    std::string fixture;
    std::string test;
    std::string message;
};

class fixture
{
public:
    fixture(const char *name)
        : m_name(name)
    { }

    virtual ~fixture()
    { }

    const char *get_name() const
    { return m_name; }

    virtual void setup() { }
    virtual void teardown() { }

	/*
	   Invoke the Function Under Test

	   implement this one when you want to catch custom C++ exceptions;
	   these must be converted to bfc::error class throwing exceptions 
	   to work best with BFC.
	   
	   If you don't do this, your exceptions may be either caught by the
	   platform-specific SEH handler or fall through the test rig and
	   out the other side, losing information on the way, leading to
	   harder to analyze output.

	   @return
		Return TRUE when an exception occurred and the bfc::error ex
	    instance is filled accordingly, FALSE otherwise (~ successful test).
	*/
	virtual bool FUT_invoker(testrunner *me, method m, const char *funcname, error &ex)
	{
        try {
		    (this->*m)();
        }
        catch (bfc::error &e) {
			ex = e;
            return (true);
        }
		return (false);
	}

	// clear all tests
    void clear_tests() {
        m_tests.resize(0);
    }

    // register a new test function
    void register_test(const char *name, method foo) {
		static method *m;
{'fraction_non_alphanumeric': 0.10856245090337785, 'fraction_numerical': 0.004241948153967007, 'mean_word_length': 2.043509442983505, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '5496782', 'n_tokens_mistral': 3830, 'n_tokens_neox': 3629, 'n_words': 1207}