Make SANITY_CHECK required for all performance tests
authorAndrey Kamaev <andrey.kamaev@itseez.com>
Mon, 8 Oct 2012 13:17:42 +0000 (17:17 +0400)
committerAndrey Kamaev <andrey.kamaev@itseez.com>
Mon, 8 Oct 2012 13:17:42 +0000 (17:17 +0400)
modules/ts/include/opencv2/ts/ts_perf.hpp
modules/ts/src/ts_perf.cpp

index ed949ea..0b5f0b7 100644 (file)
-#ifndef __OPENCV_TS_PERF_HPP__\r
-#define __OPENCV_TS_PERF_HPP__\r
-\r
-#include "opencv2/core/core.hpp"\r
-#include "ts_gtest.h"\r
-\r
-#ifdef HAVE_TBB\r
-#include "tbb/task_scheduler_init.h"\r
-#endif\r
-\r
-#if !(defined(LOGD) || defined(LOGI) || defined(LOGW) || defined(LOGE))\r
-# if defined(ANDROID) && defined(USE_ANDROID_LOGGING)\r
-#  include <android/log.h>\r
-\r
-#  define PERF_TESTS_LOG_TAG "OpenCV_perf"\r
-#  define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, PERF_TESTS_LOG_TAG, __VA_ARGS__))\r
-#  define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, PERF_TESTS_LOG_TAG, __VA_ARGS__))\r
-#  define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, PERF_TESTS_LOG_TAG, __VA_ARGS__))\r
-#  define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, PERF_TESTS_LOG_TAG, __VA_ARGS__))\r
-# else\r
-#  define LOGD(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0)\r
-#  define LOGI(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0)\r
-#  define LOGW(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0)\r
-#  define LOGE(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0)\r
-# endif\r
-#endif\r
-\r
-namespace perf\r
-{\r
-\r
-/*****************************************************************************************\\r
-*                Predefined typical frame sizes and typical test parameters               *\r
-\*****************************************************************************************/\r
-const cv::Size szQVGA = cv::Size(320, 240);\r
-const cv::Size szVGA = cv::Size(640, 480);\r
-const cv::Size szSVGA = cv::Size(800, 600);\r
-const cv::Size szXGA = cv::Size(1024, 768);\r
-const cv::Size szSXGA = cv::Size(1280, 1024);\r
-const cv::Size szWQHD = cv::Size(2560, 1440);\r
-\r
-const cv::Size sznHD = cv::Size(640, 360);\r
-const cv::Size szqHD = cv::Size(960, 540);\r
-const cv::Size sz240p = szQVGA;\r
-const cv::Size sz720p = cv::Size(1280, 720);\r
-const cv::Size sz1080p = cv::Size(1920, 1080);\r
-const cv::Size sz1440p = szWQHD;\r
-const cv::Size sz2160p = cv::Size(3840, 2160);//UHDTV1 4K\r
-const cv::Size sz4320p = cv::Size(7680, 4320);//UHDTV2 8K\r
-\r
-const cv::Size sz2K = cv::Size(2048, 2048);\r
-\r
-const cv::Size szODD = cv::Size(127, 61);\r
-\r
-const cv::Size szSmall24 = cv::Size(24, 24);\r
-const cv::Size szSmall32 = cv::Size(32, 32);\r
-const cv::Size szSmall64 = cv::Size(64, 64);\r
-const cv::Size szSmall128 = cv::Size(128, 128);\r
-\r
-#define SZ_ALL_VGA ::testing::Values(::perf::szQVGA, ::perf::szVGA, ::perf::szSVGA)\r
-#define SZ_ALL_GA  ::testing::Values(::perf::szQVGA, ::perf::szVGA, ::perf::szSVGA, ::perf::szXGA, ::perf::szSXGA)\r
-#define SZ_ALL_HD  ::testing::Values(::perf::sznHD, ::perf::szqHD, ::perf::sz720p, ::perf::sz1080p)\r
-#define SZ_ALL_SMALL ::testing::Values(::perf::szSmall24, ::perf::szSmall32, ::perf::szSmall64, ::perf::szSmall128)\r
-#define SZ_ALL  ::testing::Values(::perf::szQVGA, ::perf::szVGA, ::perf::szSVGA, ::perf::szXGA, ::perf::szSXGA, ::perf::sznHD, ::perf::szqHD, ::perf::sz720p, ::perf::sz1080p)\r
-#define SZ_TYPICAL  ::testing::Values(::perf::szVGA, ::perf::szqHD, ::perf::sz720p, ::perf::szODD)\r
-\r
-\r
-#define TYPICAL_MAT_SIZES ::perf::szVGA, ::perf::sz720p, ::perf::sz1080p, ::perf::szODD\r
-#define TYPICAL_MAT_TYPES CV_8UC1, CV_8UC4, CV_32FC1\r
-#define TYPICAL_MATS testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( TYPICAL_MAT_TYPES ) )\r
-#define TYPICAL_MATS_C1 testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( CV_8UC1, CV_32FC1 ) )\r
-#define TYPICAL_MATS_C4 testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( CV_8UC4 ) )\r
-\r
-\r
-/*****************************************************************************************\\r
-*                MatType - printable wrapper over integer 'type' of Mat                   *\r
-\*****************************************************************************************/\r
-class MatType\r
-{\r
-public:\r
-    MatType(int val=0) : _type(val) {}\r
-    operator int() const {return _type;}\r
-\r
-private:\r
-    int _type;\r
-};\r
-\r
-/*****************************************************************************************\\r
-*     CV_ENUM and CV_FLAGS - macro to create printable wrappers for defines and enums     *\r
-\*****************************************************************************************/\r
-\r
-#define CV_ENUM(class_name, ...) \\r
-class CV_EXPORTS class_name {\\r
-public:\\r
-  class_name(int val = 0) : _val(val) {}\\r
-  operator int() const {return _val;}\\r
-  void PrintTo(std::ostream* os) const {\\r
-    const int vals[] = {__VA_ARGS__};\\r
-    const char* svals = #__VA_ARGS__;\\r
-    for(int i = 0, pos = 0; i < (int)(sizeof(vals)/sizeof(int)); ++i){\\r
-      while(isspace(svals[pos]) || svals[pos] == ',') ++pos;\\r
-      int start = pos;\\r
-      while(!(isspace(svals[pos]) || svals[pos] == ',' || svals[pos] == 0)) ++pos;\\r
-      if (_val == vals[i]) {\\r
-        *os << std::string(svals + start, svals + pos);\\r
-        return;\\r
-      }\\r
-    }\\r
-    *os << "UNKNOWN";\\r
-  }\\r
-  struct Container{\\r
-    typedef class_name value_type;\\r
-      Container(class_name* first, size_t len): _begin(first), _end(first+len){}\\r
-      const class_name* begin() const {return _begin;}\\r
-      const class_name* end() const {return _end;}\\r
-    private: class_name *_begin, *_end;\\r
-  };\\r
-  static Container all(){\\r
-    static class_name vals[] = {__VA_ARGS__};\\r
-    return Container(vals, sizeof(vals)/sizeof(vals[0]));\\r
-  }\\r
-private: int _val;\\r
-};\\r
-inline void PrintTo(const class_name& t, std::ostream* os) { t.PrintTo(os); }\r
-\r
-#define CV_FLAGS(class_name, ...) \\r
-class CV_EXPORTS class_name {\\r
-public:\\r
-  class_name(int val = 0) : _val(val) {}\\r
-  operator int() const {return _val;}\\r
-  void PrintTo(std::ostream* os) const {\\r
-    const int vals[] = {__VA_ARGS__};\\r
-    const char* svals = #__VA_ARGS__;\\r
-    int value = _val;\\r
-    bool first = true;\\r
-    for(int i = 0, pos = 0; i < (int)(sizeof(vals)/sizeof(int)); ++i){\\r
-      while(isspace(svals[pos]) || svals[pos] == ',') ++pos;\\r
-      int start = pos;\\r
-      while(!(isspace(svals[pos]) || svals[pos] == ',' || svals[pos] == 0)) ++pos;\\r
-      if ((value & vals[i]) == vals[i]) {\\r
-        value &= ~vals[i]; \\r
-        if (first) first = false; else *os << "|"; \\r
-        *os << std::string(svals + start, svals + pos);\\r
-        if (!value) return;\\r
-      }\\r
-    }\\r
-    if (first) *os << "UNKNOWN";\\r
-  }\\r
-private: int _val;\\r
-};\\r
-inline void PrintTo(const class_name& t, std::ostream* os) { t.PrintTo(os); }\r
-\r
-CV_ENUM(MatDepth, CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F, CV_USRTYPE1)\r
-\r
-/*****************************************************************************************\\r
-*                 Regression control utility for performance testing                      *\r
-\*****************************************************************************************/\r
-enum ERROR_TYPE\r
-{\r
-    ERROR_ABSOLUTE = 0,\r
-    ERROR_RELATIVE = 1\r
-};\r
-\r
-class CV_EXPORTS Regression\r
-{\r
-public:\r
-    static Regression& add(const std::string& name, cv::InputArray array, double eps = DBL_EPSILON, ERROR_TYPE err = ERROR_ABSOLUTE);\r
-    static void Init(const std::string& testSuitName, const std::string& ext = ".xml");\r
-\r
-    Regression& operator() (const std::string& name, cv::InputArray array, double eps = DBL_EPSILON, ERROR_TYPE err = ERROR_ABSOLUTE);\r
-\r
-private:\r
-    static Regression& instance();\r
-    Regression();\r
-    ~Regression();\r
-\r
-    Regression(const Regression&);\r
-    Regression& operator=(const Regression&);\r
-\r
-    cv::RNG regRNG;//own random numbers generator to make collection and verification work identical\r
-    std::string storageInPath;\r
-    std::string storageOutPath;\r
-    cv::FileStorage storageIn;\r
-    cv::FileStorage storageOut;\r
-    cv::FileNode rootIn;\r
-    std::string currentTestNodeName;\r
-    cv::FileStorage& write();\r
-\r
-    static std::string getCurrentTestNodeName();\r
-    static bool isVector(cv::InputArray a);\r
-    static double getElem(cv::Mat& m, int x, int y, int cn = 0);\r
-\r
-    void init(const std::string& testSuitName, const std::string& ext);\r
-    void write(cv::InputArray array);\r
-    void write(cv::Mat m);\r
-    void verify(cv::FileNode node, cv::InputArray array, double eps, ERROR_TYPE err);\r
-    void verify(cv::FileNode node, cv::Mat actual, double eps, std::string argname, ERROR_TYPE err);\r
-};\r
-\r
-#define SANITY_CHECK(array, ...) ::perf::Regression::add(#array, array , ## __VA_ARGS__)\r
-\r
-\r
-/*****************************************************************************************\\r
-*                            Container for performance metrics                            *\r
-\*****************************************************************************************/\r
-typedef struct CV_EXPORTS performance_metrics\r
-{\r
-    size_t bytesIn;\r
-    size_t bytesOut;\r
-    unsigned int samples;\r
-    unsigned int outliers;\r
-    double gmean;\r
-    double gstddev;//stddev for log(time)\r
-    double mean;\r
-    double stddev;\r
-    double median;\r
-    double min;\r
-    double frequency;\r
-    int terminationReason;\r
-\r
-    enum\r
-    {\r
-        TERM_ITERATIONS = 0,\r
-        TERM_TIME = 1,\r
-        TERM_INTERRUPT = 2,\r
-        TERM_EXCEPTION = 3,\r
-        TERM_UNKNOWN = -1\r
-    };\r
-\r
-    performance_metrics();\r
-} performance_metrics;\r
-\r
-\r
-/*****************************************************************************************\\r
-*                           Base fixture for performance tests                            *\r
-\*****************************************************************************************/\r
-class CV_EXPORTS TestBase: public ::testing::Test\r
-{\r
-public:\r
-    TestBase();\r
-\r
-    static void Init(int argc, const char* const argv[]);\r
-    static std::string getDataPath(const std::string& relativePath);\r
-\r
-protected:\r
-    virtual void PerfTestBody() = 0;\r
-\r
-    virtual void SetUp();\r
-    virtual void TearDown();\r
-\r
-    void startTimer();\r
-    void stopTimer();\r
-    bool next();\r
-\r
-    //_declareHelper declare;\r
-\r
-    enum\r
-    {\r
-        WARMUP_READ,\r
-        WARMUP_WRITE,\r
-        WARMUP_RNG,\r
-        WARMUP_NONE\r
-    };\r
-\r
-    void reportMetrics(bool toJUnitXML = false);\r
-    static void warmup(cv::InputOutputArray a, int wtype = WARMUP_READ);\r
-\r
-    performance_metrics& calcMetrics();\r
-    void RunPerfTestBody();\r
-private:\r
-    typedef std::vector<std::pair<int, cv::Size> > SizeVector;\r
-    typedef std::vector<int64> TimeVector;\r
-\r
-    SizeVector inputData;\r
-    SizeVector outputData;\r
-    unsigned int getTotalInputSize() const;\r
-    unsigned int getTotalOutputSize() const;\r
-\r
-    TimeVector times;\r
-    int64 lastTime;\r
-    int64 totalTime;\r
-    int64 timeLimit;\r
-    static int64 timeLimitDefault;\r
-    static unsigned int iterationsLimitDefault;\r
-\r
-    unsigned int nIters;\r
-    unsigned int currentIter;\r
-    unsigned int runsPerIteration;\r
-\r
-    performance_metrics metrics;\r
-    void validateMetrics();\r
-\r
-    static int64 _timeadjustment;\r
-    static int64 _calibrate();\r
-\r
-    static void warmup_impl(cv::Mat m, int wtype);\r
-    static int getSizeInBytes(cv::InputArray a);\r
-    static cv::Size getSize(cv::InputArray a);\r
-    static void declareArray(SizeVector& sizes, cv::InputOutputArray a, int wtype = 0);\r
-\r
-    class CV_EXPORTS _declareHelper\r
-    {\r
-    public:\r
-        _declareHelper& in(cv::InputOutputArray a1, int wtype = WARMUP_READ);\r
-        _declareHelper& in(cv::InputOutputArray a1, cv::InputOutputArray a2, int wtype = WARMUP_READ);\r
-        _declareHelper& in(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, int wtype = WARMUP_READ);\r
-        _declareHelper& in(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, cv::InputOutputArray a4, int wtype = WARMUP_READ);\r
-\r
-        _declareHelper& out(cv::InputOutputArray a1, int wtype = WARMUP_WRITE);\r
-        _declareHelper& out(cv::InputOutputArray a1, cv::InputOutputArray a2, int wtype = WARMUP_WRITE);\r
-        _declareHelper& out(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, int wtype = WARMUP_WRITE);\r
-        _declareHelper& out(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, cv::InputOutputArray a4, int wtype = WARMUP_WRITE);\r
-\r
-        _declareHelper& iterations(unsigned int n);\r
-        _declareHelper& time(double timeLimitSecs);\r
-        _declareHelper& tbb_threads(int n = -1);\r
-        _declareHelper& runs(unsigned int runsNumber);\r
-    private:\r
-        TestBase* test;\r
-        _declareHelper(TestBase* t);\r
-        _declareHelper(const _declareHelper&);\r
-        _declareHelper& operator=(const _declareHelper&);\r
-        friend class TestBase;\r
-    };\r
-    friend class _declareHelper;\r
-\r
-#ifdef HAVE_TBB\r
-    cv::Ptr<tbb::task_scheduler_init> p_tbb_initializer;\r
-#else\r
-    cv::Ptr<int> fixme;\r
-#endif\r
-\r
-public:\r
-    _declareHelper declare;\r
-};\r
-\r
-template<typename T> class TestBaseWithParam: public TestBase, public ::testing::WithParamInterface<T> {};\r
-\r
-typedef std::tr1::tuple<cv::Size, MatType> Size_MatType_t;\r
-typedef TestBaseWithParam<Size_MatType_t> Size_MatType;\r
-\r
-/*****************************************************************************************\\r
-*                              Print functions for googletest                             *\r
-\*****************************************************************************************/\r
-CV_EXPORTS void PrintTo(const MatType& t, std::ostream* os);\r
-\r
-} //namespace perf\r
-\r
-namespace cv\r
-{\r
-\r
-CV_EXPORTS void PrintTo(const Size& sz, ::std::ostream* os);\r
-\r
-} //namespace cv\r
-\r
-\r
-/*****************************************************************************************\\r
-*                        Macro definitions for performance tests                          *\r
-\*****************************************************************************************/\r
-#define PERF_PROXY_NAMESPACE_NAME_(test_case_name, test_name) \\r
-  test_case_name##_##test_name##_perf_namespace_proxy\r
-\r
-// Defines a performance test.\r
-//\r
-// The first parameter is the name of the test case, and the second\r
-// parameter is the name of the test within the test case.\r
-//\r
-// The user should put his test code between braces after using this\r
-// macro.  Example:\r
-//\r
-//   PERF_TEST(FooTest, InitializesCorrectly) {\r
-//     Foo foo;\r
-//     EXPECT_TRUE(foo.StatusIsOK());\r
-//   }\r
-#define PERF_TEST(test_case_name, test_name)\\r
-    namespace PERF_PROXY_NAMESPACE_NAME_(test_case_name, test_name) {\\r
-     class TestBase {/*compile error for this class means that you are trying to use perf::TestBase as a fixture*/};\\r
-     class test_case_name : public ::perf::TestBase {\\r
-      public:\\r
-       test_case_name() {}\\r
-      protected:\\r
-       virtual void PerfTestBody();\\r
-     };\\r
-     TEST_F(test_case_name, test_name){ RunPerfTestBody(); }\\r
-    }\\r
-    void PERF_PROXY_NAMESPACE_NAME_(test_case_name, test_name)::test_case_name::PerfTestBody()\r
-\r
-// Defines a performance test that uses a test fixture.\r
-//\r
-// The first parameter is the name of the test fixture class, which\r
-// also doubles as the test case name.  The second parameter is the\r
-// name of the test within the test case.\r
-//\r
-// A test fixture class must be declared earlier.  The user should put\r
-// his test code between braces after using this macro.  Example:\r
-//\r
-//   class FooTest : public ::perf::TestBase {\r
-//    protected:\r
-//     virtual void SetUp() { TestBase::SetUp(); b_.AddElement(3); }\r
-//\r
-//     Foo a_;\r
-//     Foo b_;\r
-//   };\r
-//\r
-//   PERF_TEST_F(FooTest, InitializesCorrectly) {\r
-//     EXPECT_TRUE(a_.StatusIsOK());\r
-//   }\r
-//\r
-//   PERF_TEST_F(FooTest, ReturnsElementCountCorrectly) {\r
-//     EXPECT_EQ(0, a_.size());\r
-//     EXPECT_EQ(1, b_.size());\r
-//   }\r
-#define PERF_TEST_F(fixture, testname) \\r
-    namespace PERF_PROXY_NAMESPACE_NAME_(fixture, testname) {\\r
-     class TestBase {/*compile error for this class means that you are trying to use perf::TestBase as a fixture*/};\\r
-     class fixture : public ::fixture {\\r
-      public:\\r
-       fixture() {}\\r
-      protected:\\r
-       virtual void PerfTestBody();\\r
-     };\\r
-     TEST_F(fixture, testname){ RunPerfTestBody(); }\\r
-    }\\r
-    void PERF_PROXY_NAMESPACE_NAME_(fixture, testname)::fixture::PerfTestBody()\r
-\r
-// Defines a parametrized performance test.\r
-//\r
-// The first parameter is the name of the test fixture class, which\r
-// also doubles as the test case name.  The second parameter is the\r
-// name of the test within the test case.\r
-//\r
-// The user should put his test code between braces after using this\r
-// macro.  Example:\r
-//\r
-//   typedef ::perf::TestBaseWithParam<cv::Size> FooTest;\r
-//\r
-//   PERF_TEST_P(FooTest, DoTestingRight, ::testing::Values(::perf::szVGA, ::perf::sz720p) {\r
-//     cv::Mat b(GetParam(), CV_8U, cv::Scalar(10));\r
-//     cv::Mat a(GetParam(), CV_8U, cv::Scalar(20));\r
-//     cv::Mat c(GetParam(), CV_8U, cv::Scalar(0));\r
-//\r
-//     declare.in(a, b).out(c).time(0.5);\r
-//\r
-//     TEST_CYCLE() cv::add(a, b, c);\r
-//\r
-//     SANITY_CHECK(c);\r
-//   }\r
-#define PERF_TEST_P(fixture, name, params)  \\r
-    class fixture##_##name : public fixture {\\r
-     public:\\r
-      fixture##_##name() {}\\r
-     protected:\\r
-      virtual void PerfTestBody();\\r
-    };\\r
-    TEST_P(fixture##_##name, name /*perf*/){ RunPerfTestBody(); }\\r
-    INSTANTIATE_TEST_CASE_P(/*none*/, fixture##_##name, params);\\r
-    void fixture##_##name::PerfTestBody()\r
-\r
-\r
-#define CV_PERF_TEST_MAIN(testsuitname) \\r
-int main(int argc, char **argv)\\r
-{\\r
-    ::perf::Regression::Init(#testsuitname);\\r
-    ::perf::TestBase::Init(argc, argv);\\r
-    ::testing::InitGoogleTest(&argc, argv);\\r
-    return RUN_ALL_TESTS();\\r
-}\r
-\r
-#define TEST_CYCLE_N(n) for(declare.iterations(n); startTimer(), next(); stopTimer())\r
-#define TEST_CYCLE() for(; startTimer(), next(); stopTimer())\r
-#define TEST_CYCLE_MULTIRUN(runsNum) for(declare.runs(runsNum); startTimer(), next(); stopTimer()) for(int r = 0; r < runsNum; ++r)\r
-\r
-//flags\r
-namespace perf\r
-{\r
-//GTEST_DECLARE_int32_(allowed_outliers);\r
-} //namespace perf\r
-\r
-#endif //__OPENCV_TS_PERF_HPP__\r
+#ifndef __OPENCV_TS_PERF_HPP__
+#define __OPENCV_TS_PERF_HPP__
+
+#include "opencv2/core/core.hpp"
+#include "ts_gtest.h"
+
+#ifdef HAVE_TBB
+#include "tbb/task_scheduler_init.h"
+#endif
+
+#if !(defined(LOGD) || defined(LOGI) || defined(LOGW) || defined(LOGE))
+# if defined(ANDROID) && defined(USE_ANDROID_LOGGING)
+#  include <android/log.h>
+
+#  define PERF_TESTS_LOG_TAG "OpenCV_perf"
+#  define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, PERF_TESTS_LOG_TAG, __VA_ARGS__))
+#  define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, PERF_TESTS_LOG_TAG, __VA_ARGS__))
+#  define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, PERF_TESTS_LOG_TAG, __VA_ARGS__))
+#  define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, PERF_TESTS_LOG_TAG, __VA_ARGS__))
+# else
+#  define LOGD(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0)
+#  define LOGI(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0)
+#  define LOGW(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0)
+#  define LOGE(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0)
+# endif
+#endif
+
+namespace perf
+{
+class TestBase;
+
+/*****************************************************************************************\
+*                Predefined typical frame sizes and typical test parameters               *
+\*****************************************************************************************/
+const cv::Size szQVGA = cv::Size(320, 240);
+const cv::Size szVGA = cv::Size(640, 480);
+const cv::Size szSVGA = cv::Size(800, 600);
+const cv::Size szXGA = cv::Size(1024, 768);
+const cv::Size szSXGA = cv::Size(1280, 1024);
+const cv::Size szWQHD = cv::Size(2560, 1440);
+
+const cv::Size sznHD = cv::Size(640, 360);
+const cv::Size szqHD = cv::Size(960, 540);
+const cv::Size sz240p = szQVGA;
+const cv::Size sz720p = cv::Size(1280, 720);
+const cv::Size sz1080p = cv::Size(1920, 1080);
+const cv::Size sz1440p = szWQHD;
+const cv::Size sz2160p = cv::Size(3840, 2160);//UHDTV1 4K
+const cv::Size sz4320p = cv::Size(7680, 4320);//UHDTV2 8K
+
+const cv::Size sz2K = cv::Size(2048, 2048);
+
+const cv::Size szODD = cv::Size(127, 61);
+
+const cv::Size szSmall24 = cv::Size(24, 24);
+const cv::Size szSmall32 = cv::Size(32, 32);
+const cv::Size szSmall64 = cv::Size(64, 64);
+const cv::Size szSmall128 = cv::Size(128, 128);
+
+#define SZ_ALL_VGA ::testing::Values(::perf::szQVGA, ::perf::szVGA, ::perf::szSVGA)
+#define SZ_ALL_GA  ::testing::Values(::perf::szQVGA, ::perf::szVGA, ::perf::szSVGA, ::perf::szXGA, ::perf::szSXGA)
+#define SZ_ALL_HD  ::testing::Values(::perf::sznHD, ::perf::szqHD, ::perf::sz720p, ::perf::sz1080p)
+#define SZ_ALL_SMALL ::testing::Values(::perf::szSmall24, ::perf::szSmall32, ::perf::szSmall64, ::perf::szSmall128)
+#define SZ_ALL  ::testing::Values(::perf::szQVGA, ::perf::szVGA, ::perf::szSVGA, ::perf::szXGA, ::perf::szSXGA, ::perf::sznHD, ::perf::szqHD, ::perf::sz720p, ::perf::sz1080p)
+#define SZ_TYPICAL  ::testing::Values(::perf::szVGA, ::perf::szqHD, ::perf::sz720p, ::perf::szODD)
+
+
+#define TYPICAL_MAT_SIZES ::perf::szVGA, ::perf::sz720p, ::perf::sz1080p, ::perf::szODD
+#define TYPICAL_MAT_TYPES CV_8UC1, CV_8UC4, CV_32FC1
+#define TYPICAL_MATS testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( TYPICAL_MAT_TYPES ) )
+#define TYPICAL_MATS_C1 testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( CV_8UC1, CV_32FC1 ) )
+#define TYPICAL_MATS_C4 testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( CV_8UC4 ) )
+
+
+/*****************************************************************************************\
+*                MatType - printable wrapper over integer 'type' of Mat                   *
+\*****************************************************************************************/
+class MatType
+{
+public:
+    MatType(int val=0) : _type(val) {}
+    operator int() const {return _type;}
+
+private:
+    int _type;
+};
+
+/*****************************************************************************************\
+*     CV_ENUM and CV_FLAGS - macro to create printable wrappers for defines and enums     *
+\*****************************************************************************************/
+
+#define CV_ENUM(class_name, ...) \
+class CV_EXPORTS class_name {\
+public:\
+  class_name(int val = 0) : _val(val) {}\
+  operator int() const {return _val;}\
+  void PrintTo(std::ostream* os) const {\
+    const int vals[] = {__VA_ARGS__};\
+    const char* svals = #__VA_ARGS__;\
+    for(int i = 0, pos = 0; i < (int)(sizeof(vals)/sizeof(int)); ++i){\
+      while(isspace(svals[pos]) || svals[pos] == ',') ++pos;\
+      int start = pos;\
+      while(!(isspace(svals[pos]) || svals[pos] == ',' || svals[pos] == 0)) ++pos;\
+      if (_val == vals[i]) {\
+        *os << std::string(svals + start, svals + pos);\
+        return;\
+      }\
+    }\
+    *os << "UNKNOWN";\
+  }\
+  struct Container{\
+    typedef class_name value_type;\
+      Container(class_name* first, size_t len): _begin(first), _end(first+len){}\
+      const class_name* begin() const {return _begin;}\
+      const class_name* end() const {return _end;}\
+    private: class_name *_begin, *_end;\
+  };\
+  static Container all(){\
+    static class_name vals[] = {__VA_ARGS__};\
+    return Container(vals, sizeof(vals)/sizeof(vals[0]));\
+  }\
+private: int _val;\
+};\
+inline void PrintTo(const class_name& t, std::ostream* os) { t.PrintTo(os); }
+
+#define CV_FLAGS(class_name, ...) \
+class CV_EXPORTS class_name {\
+public:\
+  class_name(int val = 0) : _val(val) {}\
+  operator int() const {return _val;}\
+  void PrintTo(std::ostream* os) const {\
+    const int vals[] = {__VA_ARGS__};\
+    const char* svals = #__VA_ARGS__;\
+    int value = _val;\
+    bool first = true;\
+    for(int i = 0, pos = 0; i < (int)(sizeof(vals)/sizeof(int)); ++i){\
+      while(isspace(svals[pos]) || svals[pos] == ',') ++pos;\
+      int start = pos;\
+      while(!(isspace(svals[pos]) || svals[pos] == ',' || svals[pos] == 0)) ++pos;\
+      if ((value & vals[i]) == vals[i]) {\
+        value &= ~vals[i]; \
+        if (first) first = false; else *os << "|"; \
+        *os << std::string(svals + start, svals + pos);\
+        if (!value) return;\
+      }\
+    }\
+    if (first) *os << "UNKNOWN";\
+  }\
+private: int _val;\
+};\
+inline void PrintTo(const class_name& t, std::ostream* os) { t.PrintTo(os); }
+
+CV_ENUM(MatDepth, CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F, CV_USRTYPE1)
+
+/*****************************************************************************************\
+*                 Regression control utility for performance testing                      *
+\*****************************************************************************************/
+enum ERROR_TYPE
+{
+    ERROR_ABSOLUTE = 0,
+    ERROR_RELATIVE = 1
+};
+
+class CV_EXPORTS Regression
+{
+public:
+    static Regression& add(TestBase* test, const std::string& name, cv::InputArray array, double eps = DBL_EPSILON, ERROR_TYPE err = ERROR_ABSOLUTE);
+    static void Init(const std::string& testSuitName, const std::string& ext = ".xml");
+
+    Regression& operator() (const std::string& name, cv::InputArray array, double eps = DBL_EPSILON, ERROR_TYPE err = ERROR_ABSOLUTE);
+
+private:
+    static Regression& instance();
+    Regression();
+    ~Regression();
+
+    Regression(const Regression&);
+    Regression& operator=(const Regression&);
+
+    cv::RNG regRNG;//own random numbers generator to make collection and verification work identical
+    std::string storageInPath;
+    std::string storageOutPath;
+    cv::FileStorage storageIn;
+    cv::FileStorage storageOut;
+    cv::FileNode rootIn;
+    std::string currentTestNodeName;
+
+    cv::FileStorage& write();
+
+    static std::string getCurrentTestNodeName();
+    static bool isVector(cv::InputArray a);
+    static double getElem(cv::Mat& m, int x, int y, int cn = 0);
+
+    void init(const std::string& testSuitName, const std::string& ext);
+    void write(cv::InputArray array);
+    void write(cv::Mat m);
+    void verify(cv::FileNode node, cv::InputArray array, double eps, ERROR_TYPE err);
+    void verify(cv::FileNode node, cv::Mat actual, double eps, std::string argname, ERROR_TYPE err);
+};
+
+#define SANITY_CHECK(array, ...) ::perf::Regression::add(this, #array, array , ## __VA_ARGS__)
+
+
+/*****************************************************************************************\
+*                            Container for performance metrics                            *
+\*****************************************************************************************/
+typedef struct CV_EXPORTS performance_metrics
+{
+    size_t bytesIn;
+    size_t bytesOut;
+    unsigned int samples;
+    unsigned int outliers;
+    double gmean;
+    double gstddev;//stddev for log(time)
+    double mean;
+    double stddev;
+    double median;
+    double min;
+    double frequency;
+    int terminationReason;
+
+    enum
+    {
+        TERM_ITERATIONS = 0,
+        TERM_TIME = 1,
+        TERM_INTERRUPT = 2,
+        TERM_EXCEPTION = 3,
+        TERM_UNKNOWN = -1
+    };
+
+    performance_metrics();
+} performance_metrics;
+
+
+/*****************************************************************************************\
+*                           Base fixture for performance tests                            *
+\*****************************************************************************************/
+class CV_EXPORTS TestBase: public ::testing::Test
+{
+public:
+    TestBase();
+
+    static void Init(int argc, const char* const argv[]);
+    static std::string getDataPath(const std::string& relativePath);
+
+protected:
+    virtual void PerfTestBody() = 0;
+
+    virtual void SetUp();
+    virtual void TearDown();
+
+    void startTimer();
+    void stopTimer();
+    bool next();
+
+    //_declareHelper declare;
+
+    enum
+    {
+        WARMUP_READ,
+        WARMUP_WRITE,
+        WARMUP_RNG,
+        WARMUP_NONE
+    };
+
+    void reportMetrics(bool toJUnitXML = false);
+    static void warmup(cv::InputOutputArray a, int wtype = WARMUP_READ);
+
+    performance_metrics& calcMetrics();
+    void RunPerfTestBody();
+private:
+    typedef std::vector<std::pair<int, cv::Size> > SizeVector;
+    typedef std::vector<int64> TimeVector;
+
+    SizeVector inputData;
+    SizeVector outputData;
+    unsigned int getTotalInputSize() const;
+    unsigned int getTotalOutputSize() const;
+
+    TimeVector times;
+    int64 lastTime;
+    int64 totalTime;
+    int64 timeLimit;
+    static int64 timeLimitDefault;
+    static unsigned int iterationsLimitDefault;
+
+    unsigned int nIters;
+    unsigned int currentIter;
+    unsigned int runsPerIteration;
+
+    performance_metrics metrics;
+    void validateMetrics();
+
+    static int64 _timeadjustment;
+    static int64 _calibrate();
+
+    static void warmup_impl(cv::Mat m, int wtype);
+    static int getSizeInBytes(cv::InputArray a);
+    static cv::Size getSize(cv::InputArray a);
+    static void declareArray(SizeVector& sizes, cv::InputOutputArray a, int wtype = 0);
+
+    class CV_EXPORTS _declareHelper
+    {
+    public:
+        _declareHelper& in(cv::InputOutputArray a1, int wtype = WARMUP_READ);
+        _declareHelper& in(cv::InputOutputArray a1, cv::InputOutputArray a2, int wtype = WARMUP_READ);
+        _declareHelper& in(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, int wtype = WARMUP_READ);
+        _declareHelper& in(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, cv::InputOutputArray a4, int wtype = WARMUP_READ);
+
+        _declareHelper& out(cv::InputOutputArray a1, int wtype = WARMUP_WRITE);
+        _declareHelper& out(cv::InputOutputArray a1, cv::InputOutputArray a2, int wtype = WARMUP_WRITE);
+        _declareHelper& out(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, int wtype = WARMUP_WRITE);
+        _declareHelper& out(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, cv::InputOutputArray a4, int wtype = WARMUP_WRITE);
+
+        _declareHelper& iterations(unsigned int n);
+        _declareHelper& time(double timeLimitSecs);
+        _declareHelper& tbb_threads(int n = -1);
+        _declareHelper& runs(unsigned int runsNumber);
+    private:
+        TestBase* test;
+        _declareHelper(TestBase* t);
+        _declareHelper(const _declareHelper&);
+        _declareHelper& operator=(const _declareHelper&);
+        friend class TestBase;
+    };
+    friend class _declareHelper;
+    friend class Regression;
+
+#ifdef HAVE_TBB
+    cv::Ptr<tbb::task_scheduler_init> p_tbb_initializer;
+#else
+    cv::Ptr<int> fixme;
+#endif
+    bool verified;
+
+public:
+    _declareHelper declare;
+};
+
+template<typename T> class TestBaseWithParam: public TestBase, public ::testing::WithParamInterface<T> {};
+
+typedef std::tr1::tuple<cv::Size, MatType> Size_MatType_t;
+typedef TestBaseWithParam<Size_MatType_t> Size_MatType;
+
+/*****************************************************************************************\
+*                              Print functions for googletest                             *
+\*****************************************************************************************/
+CV_EXPORTS void PrintTo(const MatType& t, std::ostream* os);
+
+} //namespace perf
+
+namespace cv
+{
+
+CV_EXPORTS void PrintTo(const Size& sz, ::std::ostream* os);
+
+} //namespace cv
+
+
+/*****************************************************************************************\
+*                        Macro definitions for performance tests                          *
+\*****************************************************************************************/
+#define PERF_PROXY_NAMESPACE_NAME_(test_case_name, test_name) \
+  test_case_name##_##test_name##_perf_namespace_proxy
+
+// Defines a performance test.
+//
+// The first parameter is the name of the test case, and the second
+// parameter is the name of the test within the test case.
+//
+// The user should put his test code between braces after using this
+// macro.  Example:
+//
+//   PERF_TEST(FooTest, InitializesCorrectly) {
+//     Foo foo;
+//     EXPECT_TRUE(foo.StatusIsOK());
+//   }
+#define PERF_TEST(test_case_name, test_name)\
+    namespace PERF_PROXY_NAMESPACE_NAME_(test_case_name, test_name) {\
+     class TestBase {/*compile error for this class means that you are trying to use perf::TestBase as a fixture*/};\
+     class test_case_name : public ::perf::TestBase {\
+      public:\
+       test_case_name() {}\
+      protected:\
+       virtual void PerfTestBody();\
+     };\
+     TEST_F(test_case_name, test_name){ RunPerfTestBody(); }\
+    }\
+    void PERF_PROXY_NAMESPACE_NAME_(test_case_name, test_name)::test_case_name::PerfTestBody()
+
+// Defines a performance test that uses a test fixture.
+//
+// The first parameter is the name of the test fixture class, which
+// also doubles as the test case name.  The second parameter is the
+// name of the test within the test case.
+//
+// A test fixture class must be declared earlier.  The user should put
+// his test code between braces after using this macro.  Example:
+//
+//   class FooTest : public ::perf::TestBase {
+//    protected:
+//     virtual void SetUp() { TestBase::SetUp(); b_.AddElement(3); }
+//
+//     Foo a_;
+//     Foo b_;
+//   };
+//
+//   PERF_TEST_F(FooTest, InitializesCorrectly) {
+//     EXPECT_TRUE(a_.StatusIsOK());
+//   }
+//
+//   PERF_TEST_F(FooTest, ReturnsElementCountCorrectly) {
+//     EXPECT_EQ(0, a_.size());
+//     EXPECT_EQ(1, b_.size());
+//   }
+#define PERF_TEST_F(fixture, testname) \
+    namespace PERF_PROXY_NAMESPACE_NAME_(fixture, testname) {\
+     class TestBase {/*compile error for this class means that you are trying to use perf::TestBase as a fixture*/};\
+     class fixture : public ::fixture {\
+      public:\
+       fixture() {}\
+      protected:\
+       virtual void PerfTestBody();\
+     };\
+     TEST_F(fixture, testname){ RunPerfTestBody(); }\
+    }\
+    void PERF_PROXY_NAMESPACE_NAME_(fixture, testname)::fixture::PerfTestBody()
+
+// Defines a parametrized performance test.
+//
+// The first parameter is the name of the test fixture class, which
+// also doubles as the test case name.  The second parameter is the
+// name of the test within the test case.
+//
+// The user should put his test code between braces after using this
+// macro.  Example:
+//
+//   typedef ::perf::TestBaseWithParam<cv::Size> FooTest;
+//
+//   PERF_TEST_P(FooTest, DoTestingRight, ::testing::Values(::perf::szVGA, ::perf::sz720p) {
+//     cv::Mat b(GetParam(), CV_8U, cv::Scalar(10));
+//     cv::Mat a(GetParam(), CV_8U, cv::Scalar(20));
+//     cv::Mat c(GetParam(), CV_8U, cv::Scalar(0));
+//
+//     declare.in(a, b).out(c).time(0.5);
+//
+//     TEST_CYCLE() cv::add(a, b, c);
+//
+//     SANITY_CHECK(c);
+//   }
+#define PERF_TEST_P(fixture, name, params)  \
+    class fixture##_##name : public fixture {\
+     public:\
+      fixture##_##name() {}\
+     protected:\
+      virtual void PerfTestBody();\
+    };\
+    TEST_P(fixture##_##name, name /*perf*/){ RunPerfTestBody(); }\
+    INSTANTIATE_TEST_CASE_P(/*none*/, fixture##_##name, params);\
+    void fixture##_##name::PerfTestBody()
+
+
+#define CV_PERF_TEST_MAIN(testsuitname) \
+int main(int argc, char **argv)\
+{\
+    ::perf::Regression::Init(#testsuitname);\
+    ::perf::TestBase::Init(argc, argv);\
+    ::testing::InitGoogleTest(&argc, argv);\
+    return RUN_ALL_TESTS();\
+}
+
+#define TEST_CYCLE_N(n) for(declare.iterations(n); startTimer(), next(); stopTimer())
+#define TEST_CYCLE() for(; startTimer(), next(); stopTimer())
+#define TEST_CYCLE_MULTIRUN(runsNum) for(declare.runs(runsNum); startTimer(), next(); stopTimer()) for(int r = 0; r < runsNum; ++r)
+
+//flags
+namespace perf
+{
+//GTEST_DECLARE_int32_(allowed_outliers);
+} //namespace perf
+
+#endif //__OPENCV_TS_PERF_HPP__
index 84f414a..180a237 100644 (file)
@@ -97,8 +97,9 @@ Regression& Regression::instance()
     return single;
 }
 
-Regression& Regression::add(const std::string& name, cv::InputArray array, double eps, ERROR_TYPE err)
+Regression& Regression::add(TestBase* test, const std::string& name, cv::InputArray array, double eps, ERROR_TYPE err)
 {
+    if(test) test->verified = true;
     return instance()(name, array, eps, err);
 }
 
@@ -493,6 +494,7 @@ Regression& Regression::operator() (const std::string& name, cv::InputArray arra
         else
             verify(this_arg, array, eps, err);
     }
+
     return *this;
 }
 
@@ -914,6 +916,7 @@ void TestBase::SetUp()
     if (param_affinity_mask)
         setCurrentThreadAffinityMask(param_affinity_mask);
 #endif
+    verified = false;
     lastTime = 0;
     totalTime = 0;
     runsPerIteration = 1;
@@ -926,6 +929,9 @@ void TestBase::SetUp()
 
 void TestBase::TearDown()
 {
+    if (!HasFailure() && !verified)
+        ADD_FAILURE() << "The test has no sanity checks. There should be at least one check at the end of performance test.";
+
     validateMetrics();
     if (HasFailure())
         reportMetrics(false);