1 #ifndef __OPENCV_GTESTCV_HPP__ 2 #define __OPENCV_GTESTCV_HPP__ 3 4 #include "opencv2/core/cvdef.h" 5 #include <stdarg.h> // for va_list 6 7 #include "cvconfig.h" 8 9 #ifdef WINRT 10 #pragma warning(disable:4447) // Disable warning 'main' signature found without threading model 11 #endif 12 13 #ifdef _MSC_VER 14 #pragma warning( disable: 4127 ) // conditional expression is constant 15 #pragma warning( disable: 4503 ) // decorated name length exceeded, name was truncated 16 #endif 17 18 #define GTEST_DONT_DEFINE_FAIL 0 19 #define GTEST_DONT_DEFINE_SUCCEED 0 20 #define GTEST_DONT_DEFINE_ASSERT_EQ 0 21 #define GTEST_DONT_DEFINE_ASSERT_NE 0 22 #define GTEST_DONT_DEFINE_ASSERT_LE 0 23 #define GTEST_DONT_DEFINE_ASSERT_LT 0 24 #define GTEST_DONT_DEFINE_ASSERT_GE 0 25 #define GTEST_DONT_DEFINE_ASSERT_GT 0 26 #define GTEST_DONT_DEFINE_TEST 0 27 28 #include "opencv2/ts/ts_gtest.h" 29 #include "opencv2/ts/ts_ext.hpp" 30 31 #ifndef GTEST_USES_SIMPLE_RE 32 # define GTEST_USES_SIMPLE_RE 0 33 #endif 34 #ifndef GTEST_USES_POSIX_RE 35 # define GTEST_USES_POSIX_RE 0 36 #endif 37 38 #include "opencv2/core.hpp" 39 #include "opencv2/core/utility.hpp" 40 41 namespace cvtest 42 { 43 44 using std::vector; 45 using std::string; 46 using cv::RNG; 47 using cv::Mat; 48 using cv::Scalar; 49 using cv::Size; 50 using cv::Point; 51 using cv::Rect; 52 using cv::InputArray; 53 using cv::noArray; 54 55 class CV_EXPORTS TS; 56 57 CV_EXPORTS int64 readSeed(const char* str); 58 59 CV_EXPORTS void randUni( RNG& rng, Mat& a, const Scalar& param1, const Scalar& param2 ); 60 61 inline unsigned randInt( RNG& rng ) 62 { 63 return (unsigned)rng; 64 } 65 66 inline double randReal( RNG& rng ) 67 { 68 return (double)rng; 69 } 70 71 72 CV_EXPORTS const char* getTypeName( int type ); 73 CV_EXPORTS int typeByName( const char* type_name ); 74 75 CV_EXPORTS string vec2str(const string& sep, const int* v, size_t nelems); 76 77 inline int clipInt( int val, int min_val, int max_val ) 78 { 79 if( val < min_val ) 80 val = min_val; 81 if( val > max_val ) 82 val = max_val; 83 return val; 84 } 85 86 CV_EXPORTS double getMinVal(int depth); 87 CV_EXPORTS double getMaxVal(int depth); 88 89 CV_EXPORTS Size randomSize(RNG& rng, double maxSizeLog); 90 CV_EXPORTS void randomSize(RNG& rng, int minDims, int maxDims, double maxSizeLog, vector<int>& sz); 91 CV_EXPORTS int randomType(RNG& rng, int typeMask, int minChannels, int maxChannels); 92 CV_EXPORTS Mat randomMat(RNG& rng, Size size, int type, double minVal, double maxVal, bool useRoi); 93 CV_EXPORTS Mat randomMat(RNG& rng, const vector<int>& size, int type, double minVal, double maxVal, bool useRoi); 94 CV_EXPORTS void add(const Mat& a, double alpha, const Mat& b, double beta, 95 Scalar gamma, Mat& c, int ctype, bool calcAbs=false); 96 CV_EXPORTS void multiply(const Mat& a, const Mat& b, Mat& c, double alpha=1); 97 CV_EXPORTS void divide(const Mat& a, const Mat& b, Mat& c, double alpha=1); 98 99 CV_EXPORTS void convert(const Mat& src, cv::OutputArray dst, int dtype, double alpha=1, double beta=0); 100 CV_EXPORTS void copy(const Mat& src, Mat& dst, const Mat& mask=Mat(), bool invertMask=false); 101 CV_EXPORTS void set(Mat& dst, const Scalar& gamma, const Mat& mask=Mat()); 102 103 // working with multi-channel arrays 104 CV_EXPORTS void extract( const Mat& a, Mat& plane, int coi ); 105 CV_EXPORTS void insert( const Mat& plane, Mat& a, int coi ); 106 107 // checks that the array does not have NaNs and/or Infs and all the elements are 108 // within [min_val,max_val). idx is the index of the first "bad" element. 109 CV_EXPORTS int check( const Mat& data, double min_val, double max_val, vector<int>* idx ); 110 111 // modifies values that are close to zero 112 CV_EXPORTS void patchZeros( Mat& mat, double level ); 113 114 CV_EXPORTS void transpose(const Mat& src, Mat& dst); 115 CV_EXPORTS void erode(const Mat& src, Mat& dst, const Mat& _kernel, Point anchor=Point(-1,-1), 116 int borderType=0, const Scalar& borderValue=Scalar()); 117 CV_EXPORTS void dilate(const Mat& src, Mat& dst, const Mat& _kernel, Point anchor=Point(-1,-1), 118 int borderType=0, const Scalar& borderValue=Scalar()); 119 CV_EXPORTS void filter2D(const Mat& src, Mat& dst, int ddepth, const Mat& kernel, 120 Point anchor, double delta, int borderType, 121 const Scalar& borderValue=Scalar()); 122 CV_EXPORTS void copyMakeBorder(const Mat& src, Mat& dst, int top, int bottom, int left, int right, 123 int borderType, const Scalar& borderValue=Scalar()); 124 CV_EXPORTS Mat calcSobelKernel2D( int dx, int dy, int apertureSize, int origin=0 ); 125 CV_EXPORTS Mat calcLaplaceKernel2D( int aperture_size ); 126 127 CV_EXPORTS void initUndistortMap( const Mat& a, const Mat& k, Size sz, Mat& mapx, Mat& mapy ); 128 129 CV_EXPORTS void minMaxLoc(const Mat& src, double* minval, double* maxval, 130 vector<int>* minloc, vector<int>* maxloc, const Mat& mask=Mat()); 131 CV_EXPORTS double norm(InputArray src, int normType, InputArray mask=noArray()); 132 CV_EXPORTS double norm(InputArray src1, InputArray src2, int normType, InputArray mask=noArray()); 133 CV_EXPORTS Scalar mean(const Mat& src, const Mat& mask=Mat()); 134 CV_EXPORTS double PSNR(InputArray src1, InputArray src2); 135 136 CV_EXPORTS bool cmpUlps(const Mat& data, const Mat& refdata, int expMaxDiff, double* realMaxDiff, vector<int>* idx); 137 138 // compares two arrays. max_diff is the maximum actual difference, 139 // success_err_level is maximum allowed difference, idx is the index of the first 140 // element for which difference is >success_err_level 141 // (or index of element with the maximum difference) 142 CV_EXPORTS int cmpEps( const Mat& data, const Mat& refdata, double* max_diff, 143 double success_err_level, vector<int>* idx, 144 bool element_wise_relative_error ); 145 146 // a wrapper for the previous function. in case of error prints the message to log file. 147 CV_EXPORTS int cmpEps2( TS* ts, const Mat& data, const Mat& refdata, double success_err_level, 148 bool element_wise_relative_error, const char* desc ); 149 150 CV_EXPORTS int cmpEps2_64f( TS* ts, const double* val, const double* refval, int len, 151 double eps, const char* param_name ); 152 153 CV_EXPORTS void logicOp(const Mat& src1, const Mat& src2, Mat& dst, char c); 154 CV_EXPORTS void logicOp(const Mat& src, const Scalar& s, Mat& dst, char c); 155 CV_EXPORTS void min(const Mat& src1, const Mat& src2, Mat& dst); 156 CV_EXPORTS void min(const Mat& src, double s, Mat& dst); 157 CV_EXPORTS void max(const Mat& src1, const Mat& src2, Mat& dst); 158 CV_EXPORTS void max(const Mat& src, double s, Mat& dst); 159 160 CV_EXPORTS void compare(const Mat& src1, const Mat& src2, Mat& dst, int cmpop); 161 CV_EXPORTS void compare(const Mat& src, double s, Mat& dst, int cmpop); 162 CV_EXPORTS void gemm(const Mat& src1, const Mat& src2, double alpha, 163 const Mat& src3, double beta, Mat& dst, int flags); 164 CV_EXPORTS void transform( const Mat& src, Mat& dst, const Mat& transmat, const Mat& shift ); 165 CV_EXPORTS double crossCorr(const Mat& src1, const Mat& src2); 166 167 struct CV_EXPORTS MatInfo 168 { 169 MatInfo(const Mat& _m) : m(&_m) {} 170 const Mat* m; 171 }; 172 173 CV_EXPORTS std::ostream& operator << (std::ostream& out, const MatInfo& m); 174 175 struct CV_EXPORTS MatComparator 176 { 177 public: 178 MatComparator(double maxdiff, int context); 179 180 ::testing::AssertionResult operator()(const char* expr1, const char* expr2, 181 const Mat& m1, const Mat& m2); 182 183 double maxdiff; 184 double realmaxdiff; 185 vector<int> loc0; 186 int context; 187 }; 188 189 190 191 class BaseTest; 192 class TS; 193 194 class CV_EXPORTS BaseTest 195 { 196 public: 197 // constructor(s) and destructor 198 BaseTest(); 199 virtual ~BaseTest(); 200 201 // the main procedure of the test 202 virtual void run( int start_from ); 203 204 // the wrapper for run that cares of exceptions 205 virtual void safe_run( int start_from=0 ); 206 207 const string& get_name() const { return name; } 208 209 // returns true if and only if the different test cases do not depend on each other 210 // (so that test system could get right to a problematic test case) 211 virtual bool can_do_fast_forward(); 212 213 // deallocates all the memory. 214 // called by init() (before initialization) and by the destructor 215 virtual void clear(); 216 217 protected: 218 int test_case_count; // the total number of test cases 219 220 // read test params 221 virtual int read_params( CvFileStorage* fs ); 222 223 // returns the number of tests or -1 if it is unknown a-priori 224 virtual int get_test_case_count(); 225 226 // prepares data for the next test case. rng seed is updated by the function 227 virtual int prepare_test_case( int test_case_idx ); 228 229 // checks if the test output is valid and accurate 230 virtual int validate_test_results( int test_case_idx ); 231 232 // calls the tested function. the method is called from run_test_case() 233 virtual void run_func(); // runs tested func(s) 234 235 // updates progress bar 236 virtual int update_progress( int progress, int test_case_idx, int count, double dt ); 237 238 // finds test parameter 239 const CvFileNode* find_param( CvFileStorage* fs, const char* param_name ); 240 241 // name of the test (it is possible to locate a test by its name) 242 string name; 243 244 // pointer to the system that includes the test 245 TS* ts; 246 }; 247 248 249 /*****************************************************************************************\ 250 * Information about a failed test * 251 \*****************************************************************************************/ 252 253 struct TestInfo 254 { 255 TestInfo(); 256 257 // pointer to the test 258 BaseTest* test; 259 260 // failure code (TS::FAIL_*) 261 int code; 262 263 // seed value right before the data for the failed test case is prepared. 264 uint64 rng_seed; 265 266 // seed value right before running the test 267 uint64 rng_seed0; 268 269 // index of test case, can be then passed to BaseTest::proceed_to_test_case() 270 int test_case_idx; 271 }; 272 273 /*****************************************************************************************\ 274 * Base Class for test system * 275 \*****************************************************************************************/ 276 277 // common parameters: 278 struct CV_EXPORTS TSParams 279 { 280 TSParams(); 281 282 // RNG seed, passed to and updated by every test executed. 283 uint64 rng_seed; 284 285 // whether to use IPP, MKL etc. or not 286 bool use_optimized; 287 288 // extensivity of the tests, scale factor for test_case_count 289 double test_case_count_scale; 290 }; 291 292 293 class CV_EXPORTS TS 294 { 295 public: 296 // constructor(s) and destructor 297 TS(); 298 virtual ~TS(); 299 300 enum 301 { 302 NUL=0, 303 SUMMARY_IDX=0, 304 SUMMARY=1 << SUMMARY_IDX, 305 LOG_IDX=1, 306 LOG=1 << LOG_IDX, 307 CSV_IDX=2, 308 CSV=1 << CSV_IDX, 309 CONSOLE_IDX=3, 310 CONSOLE=1 << CONSOLE_IDX, 311 MAX_IDX=4 312 }; 313 314 static TS* ptr(); 315 316 // initialize test system before running the first test 317 virtual void init( const string& modulename ); 318 319 // low-level printing functions that are used by individual tests and by the system itself 320 virtual void printf( int streams, const char* fmt, ... ); 321 virtual void vprintf( int streams, const char* fmt, va_list arglist ); 322 323 // updates the context: current test, test case, rng state 324 virtual void update_context( BaseTest* test, int test_case_idx, bool update_ts_context ); 325 326 const TestInfo* get_current_test_info() { return ¤t_test_info; } 327 328 // sets information about a failed test 329 virtual void set_failed_test_info( int fail_code ); 330 331 virtual void set_gtest_status(); 332 333 // test error codes 334 enum FailureCode 335 { 336 // everything is Ok 337 OK=0, 338 339 // generic error: stub value to be used 340 // temporarily if the error's cause is unknown 341 FAIL_GENERIC=-1, 342 343 // the test is missing some essential data to proceed further 344 FAIL_MISSING_TEST_DATA=-2, 345 346 // the tested function raised an error via cxcore error handler 347 FAIL_ERROR_IN_CALLED_FUNC=-3, 348 349 // an exception has been raised; 350 // for memory and arithmetic exception 351 // there are two specialized codes (see below...) 352 FAIL_EXCEPTION=-4, 353 354 // a memory exception 355 // (access violation, access to missed page, stack overflow etc.) 356 FAIL_MEMORY_EXCEPTION=-5, 357 358 // arithmetic exception (overflow, division by zero etc.) 359 FAIL_ARITHM_EXCEPTION=-6, 360 361 // the tested function corrupted memory (no exception have been raised) 362 FAIL_MEMORY_CORRUPTION_BEGIN=-7, 363 FAIL_MEMORY_CORRUPTION_END=-8, 364 365 // the tested function (or test ifself) do not deallocate some memory 366 FAIL_MEMORY_LEAK=-9, 367 368 // the tested function returned invalid object, e.g. matrix, containing NaNs, 369 // structure with NULL or out-of-range fields (while it should not) 370 FAIL_INVALID_OUTPUT=-10, 371 372 // the tested function returned valid object, but it does not match to 373 // the original (or produced by the test) object 374 FAIL_MISMATCH=-11, 375 376 // the tested function returned valid object (a single number or numerical array), 377 // but it differs too much from the original (or produced by the test) object 378 FAIL_BAD_ACCURACY=-12, 379 380 // the tested function hung. Sometimes, can be determined by unexpectedly long 381 // processing time (in this case there should be possibility to interrupt such a function 382 FAIL_HANG=-13, 383 384 // unexpected response on passing bad arguments to the tested function 385 // (the function crashed, proceed successfully (while it should not), or returned 386 // error code that is different from what is expected) 387 FAIL_BAD_ARG_CHECK=-14, 388 389 // the test data (in whole or for the particular test case) is invalid 390 FAIL_INVALID_TEST_DATA=-15, 391 392 // the test has been skipped because it is not in the selected subset of the tests to run, 393 // because it has been run already within the same run with the same parameters, or because 394 // of some other reason and this is not considered as an error. 395 // Normally TS::run() (or overridden method in the derived class) takes care of what 396 // needs to be run, so this code should not occur. 397 SKIPPED=1 398 }; 399 400 // get file storage 401 CvFileStorage* get_file_storage(); 402 403 // get RNG to generate random input data for a test 404 RNG& get_rng() { return rng; } 405 406 // returns the current error code 407 TS::FailureCode get_err_code() { return TS::FailureCode(current_test_info.code); } 408 409 // returns the test extensivity scale 410 double get_test_case_count_scale() { return params.test_case_count_scale; } 411 412 const string& get_data_path() const { return data_path; } 413 414 // returns textual description of failure code 415 static string str_from_code( const TS::FailureCode code ); 416 417 protected: 418 419 // these are allocated within a test to try keep them valid in case of stack corruption 420 RNG rng; 421 422 // information about the current test 423 TestInfo current_test_info; 424 425 // the path to data files used by tests 426 string data_path; 427 428 TSParams params; 429 std::string output_buf[MAX_IDX]; 430 }; 431 432 433 /*****************************************************************************************\ 434 * Subclass of BaseTest for testing functions that process dense arrays * 435 \*****************************************************************************************/ 436 437 class CV_EXPORTS ArrayTest : public BaseTest 438 { 439 public: 440 // constructor(s) and destructor 441 ArrayTest(); 442 virtual ~ArrayTest(); 443 444 virtual void clear(); 445 446 protected: 447 448 virtual int read_params( CvFileStorage* fs ); 449 virtual int prepare_test_case( int test_case_idx ); 450 virtual int validate_test_results( int test_case_idx ); 451 452 virtual void prepare_to_validation( int test_case_idx ); 453 virtual void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 454 virtual void fill_array( int test_case_idx, int i, int j, Mat& arr ); 455 virtual void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high ); 456 virtual double get_success_error_level( int test_case_idx, int i, int j ); 457 458 bool cvmat_allowed; 459 bool iplimage_allowed; 460 bool optional_mask; 461 bool element_wise_relative_error; 462 463 int min_log_array_size; 464 int max_log_array_size; 465 466 enum { INPUT, INPUT_OUTPUT, OUTPUT, REF_INPUT_OUTPUT, REF_OUTPUT, TEMP, MASK, MAX_ARR }; 467 468 vector<vector<void*> > test_array; 469 vector<vector<Mat> > test_mat; 470 float buf[4]; 471 }; 472 473 474 class CV_EXPORTS BadArgTest : public BaseTest 475 { 476 public: 477 // constructor(s) and destructor 478 BadArgTest(); 479 virtual ~BadArgTest(); 480 481 protected: 482 virtual int run_test_case( int expected_code, const string& descr ); 483 virtual void run_func(void) = 0; 484 int test_case_idx; 485 486 template<class F> 487 int run_test_case( int expected_code, const string& _descr, F f) 488 { 489 int errcount = 0; 490 bool thrown = false; 491 const char* descr = _descr.c_str() ? _descr.c_str() : ""; 492 493 try 494 { 495 f(); 496 } 497 catch(const cv::Exception& e) 498 { 499 thrown = true; 500 if( e.code != expected_code ) 501 { 502 ts->printf(TS::LOG, "%s (test case #%d): the error code %d is different from the expected %d\n", 503 descr, test_case_idx, e.code, expected_code); 504 errcount = 1; 505 } 506 } 507 catch(...) 508 { 509 thrown = true; 510 ts->printf(TS::LOG, "%s (test case #%d): unknown exception was thrown (the function has likely crashed)\n", 511 descr, test_case_idx); 512 errcount = 1; 513 } 514 if(!thrown) 515 { 516 ts->printf(TS::LOG, "%s (test case #%d): no expected exception was thrown\n", 517 descr, test_case_idx); 518 errcount = 1; 519 } 520 test_case_idx++; 521 522 return errcount; 523 } 524 }; 525 526 struct CV_EXPORTS DefaultRngAuto 527 { 528 const uint64 old_state; 529 530 DefaultRngAuto() : old_state(cv::theRNG().state) { cv::theRNG().state = (uint64)-1; } 531 ~DefaultRngAuto() { cv::theRNG().state = old_state; } 532 533 DefaultRngAuto& operator=(const DefaultRngAuto&); 534 }; 535 536 } 537 538 namespace cvtest 539 { 540 541 // test images generation functions 542 CV_EXPORTS void fillGradient(Mat& img, int delta = 5); 543 CV_EXPORTS void smoothBorder(Mat& img, const Scalar& color, int delta = 3); 544 545 CV_EXPORTS void printVersionInfo(bool useStdOut = true); 546 } //namespace cvtest 547 548 #ifndef __CV_TEST_EXEC_ARGS 549 #if defined(_MSC_VER) && (_MSC_VER <= 1400) 550 #define __CV_TEST_EXEC_ARGS(...) \ 551 while (++argc >= (--argc,-1)) {__VA_ARGS__; break;} /*this ugly construction is needed for VS 2005*/ 552 #else 553 #define __CV_TEST_EXEC_ARGS(...) \ 554 __VA_ARGS__; 555 #endif 556 #endif 557 558 #ifdef HAVE_OPENCL 559 namespace cvtest { namespace ocl { 560 void dumpOpenCLDevice(); 561 } } 562 #define TEST_DUMP_OCL_INFO cvtest::ocl::dumpOpenCLDevice(); 563 #else 564 #define TEST_DUMP_OCL_INFO 565 #endif 566 567 void parseCustomOptions(int argc, char **argv); 568 569 #define CV_TEST_MAIN(resourcesubdir, ...) \ 570 int main(int argc, char **argv) \ 571 { \ 572 __CV_TEST_EXEC_ARGS(__VA_ARGS__) \ 573 cvtest::TS::ptr()->init(resourcesubdir); \ 574 ::testing::InitGoogleTest(&argc, argv); \ 575 cvtest::printVersionInfo(); \ 576 TEST_DUMP_OCL_INFO \ 577 parseCustomOptions(argc, argv); \ 578 return RUN_ALL_TESTS(); \ 579 } 580 581 // This usually only makes sense in perf tests with several implementations, 582 // some of which are not available. 583 #define CV_TEST_FAIL_NO_IMPL() do { \ 584 ::testing::Test::RecordProperty("custom_status", "noimpl"); \ 585 FAIL() << "No equivalent implementation."; \ 586 } while (0) 587 588 #endif 589 590 #include "opencv2/ts/ts_perf.hpp" 591