github.com/platonnetwork/platon-go@v0.7.6/cases/tool/win/bls_win/include/cybozu/test.hpp (about)

     1  #pragma once
     2  /**
     3  	@file
     4  	@brief unit test class
     5  
     6  	@author MITSUNARI Shigeo(@herumi)
     7  */
     8  
     9  #include <stdio.h>
    10  #include <string.h>
    11  #include <string>
    12  #include <list>
    13  #include <iostream>
    14  #include <utility>
    15  #if defined(_MSC_VER) && (MSC_VER <= 1500)
    16  	#include <cybozu/inttype.hpp>
    17  #else
    18  	#include <stdint.h>
    19  #endif
    20  
    21  namespace cybozu { namespace test {
    22  
    23  class AutoRun {
    24  	typedef void (*Func)();
    25  	typedef std::list<std::pair<const char*, Func> > UnitTestList;
    26  public:
    27  	AutoRun()
    28  		: init_(0)
    29  		, term_(0)
    30  		, okCount_(0)
    31  		, ngCount_(0)
    32  		, exceptionCount_(0)
    33  	{
    34  	}
    35  	void setup(Func init, Func term)
    36  	{
    37  		init_ = init;
    38  		term_ = term;
    39  	}
    40  	void append(const char *name, Func func)
    41  	{
    42  		list_.push_back(std::make_pair(name, func));
    43  	}
    44  	void set(bool isOK)
    45  	{
    46  		if (isOK) {
    47  			okCount_++;
    48  		} else {
    49  			ngCount_++;
    50  		}
    51  	}
    52  	std::string getBaseName(const std::string& name) const
    53  	{
    54  #ifdef _WIN32
    55  		const char sep = '\\';
    56  #else
    57  		const char sep = '/';
    58  #endif
    59  		size_t pos = name.find_last_of(sep);
    60  		std::string ret = name.substr(pos + 1);
    61  		pos = ret.find('.');
    62  		return ret.substr(0, pos);
    63  	}
    64  	int run(int, char *argv[])
    65  	{
    66  		std::string msg;
    67  		try {
    68  			if (init_) init_();
    69  			for (UnitTestList::const_iterator i = list_.begin(), ie = list_.end(); i != ie; ++i) {
    70  				std::cout << "ctest:module=" << i->first << std::endl;
    71  				try {
    72  					(i->second)();
    73  				} catch (std::exception& e) {
    74  					exceptionCount_++;
    75  					std::cout << "ctest:  " << i->first << " is stopped by exception " << e.what() << std::endl;
    76  				} catch (...) {
    77  					exceptionCount_++;
    78  					std::cout << "ctest:  " << i->first << " is stopped by unknown exception" << std::endl;
    79  				}
    80  			}
    81  			if (term_) term_();
    82  		} catch (std::exception& e) {
    83  			msg = std::string("ctest:err:") + e.what();
    84  		} catch (...) {
    85  			msg = "ctest:err: catch unknown exception";
    86  		}
    87  		fflush(stdout);
    88  		if (msg.empty()) {
    89  			int err = ngCount_ + exceptionCount_;
    90  			int total = okCount_ + err;
    91  			std::cout << "ctest:name=" << getBaseName(*argv)
    92  					  << ", module=" << list_.size()
    93  					  << ", total=" << total
    94  					  << ", ok=" << okCount_
    95  					  << ", ng=" << ngCount_
    96  					  << ", exception=" << exceptionCount_ << std::endl;
    97  			return err > 0 ? 1 : 0;
    98  		} else {
    99  			std::cout << msg << std::endl;
   100  			return 1;
   101  		}
   102  	}
   103  	static inline AutoRun& getInstance()
   104  	{
   105  		static AutoRun instance;
   106  		return instance;
   107  	}
   108  private:
   109  	Func init_;
   110  	Func term_;
   111  	int okCount_;
   112  	int ngCount_;
   113  	int exceptionCount_;
   114  	UnitTestList list_;
   115  };
   116  
   117  static AutoRun& autoRun = AutoRun::getInstance();
   118  
   119  inline void test(bool ret, const std::string& msg, const std::string& param, const char *file, int line)
   120  {
   121  	autoRun.set(ret);
   122  	if (!ret) {
   123  		printf("%s(%d):ctest:%s(%s);\n", file, line, msg.c_str(), param.c_str());
   124  	}
   125  }
   126  
   127  template<typename T, typename U>
   128  bool isEqual(const T& lhs, const U& rhs)
   129  {
   130  	return lhs == rhs;
   131  }
   132  
   133  // avoid warning of comparision of integers of different signs
   134  inline bool isEqual(size_t lhs, int rhs)
   135  {
   136  	return lhs == size_t(rhs);
   137  }
   138  inline bool isEqual(int lhs, size_t rhs)
   139  {
   140  	return size_t(lhs) == rhs;
   141  }
   142  inline bool isEqual(const char *lhs, const char *rhs)
   143  {
   144  	return strcmp(lhs, rhs) == 0;
   145  }
   146  inline bool isEqual(char *lhs, const char *rhs)
   147  {
   148  	return strcmp(lhs, rhs) == 0;
   149  }
   150  inline bool isEqual(const char *lhs, char *rhs)
   151  {
   152  	return strcmp(lhs, rhs) == 0;
   153  }
   154  inline bool isEqual(char *lhs, char *rhs)
   155  {
   156  	return strcmp(lhs, rhs) == 0;
   157  }
   158  // avoid to compare float directly
   159  inline bool isEqual(float lhs, float rhs)
   160  {
   161  	union fi {
   162  		float f;
   163  		uint32_t i;
   164  	} lfi, rfi;
   165  	lfi.f = lhs;
   166  	rfi.f = rhs;
   167  	return lfi.i == rfi.i;
   168  }
   169  // avoid to compare double directly
   170  inline bool isEqual(double lhs, double rhs)
   171  {
   172  	union di {
   173  		double d;
   174  		uint64_t i;
   175  	} ldi, rdi;
   176  	ldi.d = lhs;
   177  	rdi.d = rhs;
   178  	return ldi.i == rdi.i;
   179  }
   180  
   181  } } // cybozu::test
   182  
   183  #ifndef CYBOZU_TEST_DISABLE_AUTO_RUN
   184  int main(int argc, char *argv[])
   185  {
   186  	return cybozu::test::autoRun.run(argc, argv);
   187  }
   188  #endif
   189  
   190  /**
   191  	alert if !x
   192  	@param x [in]
   193  */
   194  #define CYBOZU_TEST_ASSERT(x) cybozu::test::test(!!(x), "CYBOZU_TEST_ASSERT", #x, __FILE__, __LINE__)
   195  
   196  /**
   197  	alert if x != y
   198  	@param x [in]
   199  	@param y [in]
   200  */
   201  #define CYBOZU_TEST_EQUAL(x, y) { \
   202  	bool _cybozu_eq = cybozu::test::isEqual(x, y); \
   203  	cybozu::test::test(_cybozu_eq, "CYBOZU_TEST_EQUAL", #x ", " #y, __FILE__, __LINE__); \
   204  	if (!_cybozu_eq) { \
   205  		std::cout << "ctest:  lhs=" << (x) << std::endl; \
   206  		std::cout << "ctest:  rhs=" << (y) << std::endl; \
   207  	} \
   208  }
   209  /**
   210  	alert if fabs(x, y) >= eps
   211  	@param x [in]
   212  	@param y [in]
   213  */
   214  #define CYBOZU_TEST_NEAR(x, y, eps) { \
   215  	bool _cybozu_isNear = fabs((x) - (y)) < eps; \
   216  	cybozu::test::test(_cybozu_isNear, "CYBOZU_TEST_NEAR", #x ", " #y, __FILE__, __LINE__); \
   217  	if (!_cybozu_isNear) { \
   218  		std::cout << "ctest:  lhs=" << (x) << std::endl; \
   219  		std::cout << "ctest:  rhs=" << (y) << std::endl; \
   220  	} \
   221  }
   222  
   223  #define CYBOZU_TEST_EQUAL_POINTER(x, y) { \
   224  	bool _cybozu_eq = x == y; \
   225  	cybozu::test::test(_cybozu_eq, "CYBOZU_TEST_EQUAL_POINTER", #x ", " #y, __FILE__, __LINE__); \
   226  	if (!_cybozu_eq) { \
   227  		std::cout << "ctest:  lhs=" << static_cast<const void*>(x) << std::endl; \
   228  		std::cout << "ctest:  rhs=" << static_cast<const void*>(y) << std::endl; \
   229  	} \
   230  }
   231  /**
   232  	alert if x[] != y[]
   233  	@param x [in]
   234  	@param y [in]
   235  	@param n [in]
   236  */
   237  #define CYBOZU_TEST_EQUAL_ARRAY(x, y, n) { \
   238  	for (size_t _cybozu_test_i = 0, _cybozu_ie = (size_t)(n); _cybozu_test_i < _cybozu_ie; _cybozu_test_i++) { \
   239  		bool _cybozu_eq = cybozu::test::isEqual((x)[_cybozu_test_i], (y)[_cybozu_test_i]); \
   240  		cybozu::test::test(_cybozu_eq, "CYBOZU_TEST_EQUAL_ARRAY", #x ", " #y ", " #n, __FILE__, __LINE__); \
   241  		if (!_cybozu_eq) { \
   242  			std::cout << "ctest:  i=" << _cybozu_test_i << std::endl; \
   243  			std::cout << "ctest:  lhs=" << (x)[_cybozu_test_i] << std::endl; \
   244  			std::cout << "ctest:  rhs=" << (y)[_cybozu_test_i] << std::endl; \
   245  		} \
   246  	} \
   247  }
   248  
   249  /**
   250  	always alert
   251  	@param msg [in]
   252  */
   253  #define CYBOZU_TEST_FAIL(msg) cybozu::test::test(false, "CYBOZU_TEST_FAIL", msg, __FILE__, __LINE__)
   254  
   255  /**
   256  	verify message in exception
   257  */
   258  #define CYBOZU_TEST_EXCEPTION_MESSAGE(statement, Exception, msg) \
   259  { \
   260  	int _cybozu_ret = 0; \
   261  	std::string _cybozu_errMsg; \
   262  	try { \
   263  		statement; \
   264  		_cybozu_ret = 1; \
   265  	} catch (const Exception& _cybozu_e) { \
   266  		_cybozu_errMsg = _cybozu_e.what(); \
   267  		if (_cybozu_errMsg.find(msg) == std::string::npos) { \
   268  			_cybozu_ret = 2; \
   269  		} \
   270  	} catch (...) { \
   271  		_cybozu_ret = 3; \
   272  	} \
   273  	if (_cybozu_ret) { \
   274  		cybozu::test::test(false, "CYBOZU_TEST_EXCEPTION_MESSAGE", #statement ", " #Exception ", " #msg, __FILE__, __LINE__); \
   275  		if (_cybozu_ret == 1) { \
   276  			std::cout << "ctest:  no exception" << std::endl; \
   277  		} else if (_cybozu_ret == 2) { \
   278  			std::cout << "ctest:  bad exception msg:" << _cybozu_errMsg << std::endl; \
   279  		} else { \
   280  			std::cout << "ctest:  unexpected exception" << std::endl; \
   281  		} \
   282  	} else { \
   283  		cybozu::test::autoRun.set(true); \
   284  	} \
   285  }
   286  
   287  #define CYBOZU_TEST_EXCEPTION(statement, Exception) \
   288  { \
   289  	int _cybozu_ret = 0; \
   290  	try { \
   291  		statement; \
   292  		_cybozu_ret = 1; \
   293  	} catch (const Exception&) { \
   294  	} catch (...) { \
   295  		_cybozu_ret = 2; \
   296  	} \
   297  	if (_cybozu_ret) { \
   298  		cybozu::test::test(false, "CYBOZU_TEST_EXCEPTION", #statement ", " #Exception, __FILE__, __LINE__); \
   299  		if (_cybozu_ret == 1) { \
   300  			std::cout << "ctest:  no exception" << std::endl; \
   301  		} else { \
   302  			std::cout << "ctest:  unexpected exception" << std::endl; \
   303  		} \
   304  	} else { \
   305  		cybozu::test::autoRun.set(true); \
   306  	} \
   307  }
   308  
   309  /**
   310  	verify statement does not throw
   311  */
   312  #define CYBOZU_TEST_NO_EXCEPTION(statement) \
   313  try { \
   314  	statement; \
   315  	cybozu::test::autoRun.set(true); \
   316  } catch (...) { \
   317  	cybozu::test::test(false, "CYBOZU_TEST_NO_EXCEPTION", #statement, __FILE__, __LINE__); \
   318  }
   319  
   320  /**
   321  	append auto unit test
   322  	@param name [in] module name
   323  */
   324  #define CYBOZU_TEST_AUTO(name) \
   325  void cybozu_test_ ## name(); \
   326  struct cybozu_test_local_ ## name { \
   327  	cybozu_test_local_ ## name() \
   328  	{ \
   329  		cybozu::test::autoRun.append(#name, cybozu_test_ ## name); \
   330  	} \
   331  } cybozu_test_local_instance_ ## name; \
   332  void cybozu_test_ ## name()
   333  
   334  /**
   335  	append auto unit test with fixture
   336  	@param name [in] module name
   337  */
   338  #define CYBOZU_TEST_AUTO_WITH_FIXTURE(name, Fixture) \
   339  void cybozu_test_ ## name(); \
   340  void cybozu_test_real_ ## name() \
   341  { \
   342  	Fixture f; \
   343  	cybozu_test_ ## name(); \
   344  } \
   345  struct cybozu_test_local_ ## name { \
   346  	cybozu_test_local_ ## name() \
   347  	{ \
   348  		cybozu::test::autoRun.append(#name, cybozu_test_real_ ## name); \
   349  	} \
   350  } cybozu_test_local_instance_ ## name; \
   351  void cybozu_test_ ## name()
   352  
   353  /**
   354  	setup fixture
   355  	@param Fixture [in] class name of fixture
   356  	@note cstr of Fixture is called before test and dstr of Fixture is called after test
   357  */
   358  #define CYBOZU_TEST_SETUP_FIXTURE(Fixture) \
   359  Fixture *cybozu_test_local_fixture; \
   360  void cybozu_test_local_init() \
   361  { \
   362  	cybozu_test_local_fixture = new Fixture(); \
   363  } \
   364  void cybozu_test_local_term() \
   365  { \
   366  	delete cybozu_test_local_fixture; \
   367  } \
   368  struct cybozu_test_local_fixture_setup_ { \
   369  	cybozu_test_local_fixture_setup_() \
   370  	{ \
   371  		cybozu::test::autoRun.setup(cybozu_test_local_init, cybozu_test_local_term); \
   372  	} \
   373  } cybozu_test_local_fixture_setup_instance_;