//M*/
#include "precomp.hpp"
+#include <opencv2/core/utils/configuration.private.hpp>
+
#include "opencv2/core/core_c.h"
#include <ctype.h>
#include "opencv2/core/opencl/opencl_info.hpp"
+#include "opencv2/core/utils/allocator_stats.hpp"
+namespace cv { namespace ocl {
+cv::utils::AllocatorStatisticsInterface& getOpenCLAllocatorStatistics();
+}}
#endif // HAVE_OPENCL
-#include "opencv2/core/utility.hpp"
+#include "opencv2/core/utils/allocator_stats.hpp"
+namespace cv {
+CV_EXPORTS cv::utils::AllocatorStatisticsInterface& getAllocatorStatistics();
+}
+
#include "opencv_tests_config.hpp"
+#include "ts_tags.hpp"
+
+#if defined(__GNUC__) && defined(__linux__)
+extern "C" {
+size_t malloc_peak(void) __attribute__((weak));
+void malloc_reset_peak(void) __attribute__((weak));
+} // extern "C"
+#else // stubs
+static size_t (*malloc_peak)(void) = 0;
+static void (*malloc_reset_peak)(void) = 0;
+#endif
+
namespace opencv_test {
bool required_opencv_test_namespace = false; // compilation check for non-refactored tests
}
}
}
-static bool checkTestData = false;
+static bool checkTestData = cv::utils::getConfigurationParameterBool("OPENCV_TEST_REQUIRE_DATA", false);
bool skipUnstableTests = false;
bool runBigDataTests = false;
int testThreads = 0;
+
+static size_t memory_usage_base = 0;
+static uint64_t memory_usage_base_opencv = 0;
+#ifdef HAVE_OPENCL
+static uint64_t memory_usage_base_opencl = 0;
+#endif
+
+void testSetUp()
+{
+ fflush(stdout); fflush(stderr);
+ cv::ipp::setIppStatus(0);
+ cv::theRNG().state = cvtest::param_seed;
+ cv::setNumThreads(cvtest::testThreads);
+ if (malloc_peak) // if memory profiler is available
+ {
+ malloc_reset_peak();
+ memory_usage_base = malloc_peak(); // equal to malloc_current()
+ }
+ {
+ cv::utils::AllocatorStatisticsInterface& ocv_stats = cv::getAllocatorStatistics();
+ ocv_stats.resetPeakUsage();
+ memory_usage_base_opencv = ocv_stats.getCurrentUsage();
+ }
+#ifdef HAVE_OPENCL
+ {
+ cv::utils::AllocatorStatisticsInterface& ocl_stats = cv::ocl::getOpenCLAllocatorStatistics();
+ ocl_stats.resetPeakUsage();
+ memory_usage_base_opencl = ocl_stats.getCurrentUsage();
+ }
+#endif
+ checkTestTags();
+}
+
+void testTearDown()
+{
+ ::cvtest::checkIppStatus();
+ uint64_t memory_usage = 0;
+ uint64_t ocv_memory_usage = 0, ocv_peak = 0;
+ if (malloc_peak) // if memory profiler is available
+ {
+ size_t peak = malloc_peak();
+ memory_usage = peak - memory_usage_base;
+ if (peak > 0)
+ {
+ CV_LOG_INFO(NULL, "Memory_usage (malloc): " << memory_usage << " (base=" << memory_usage_base << ")");
+ }
+ }
+ {
+ // core/src/alloc.cpp: #define OPENCV_ALLOC_ENABLE_STATISTICS
+ // handle large buffers via fastAlloc()
+ // (not always accurate on heavy 3rdparty usage, like protobuf)
+ cv::utils::AllocatorStatisticsInterface& ocv_stats = cv::getAllocatorStatistics();
+ ocv_peak = ocv_stats.getPeakUsage();
+ ocv_memory_usage = ocv_peak - memory_usage_base_opencv;
+ if (ocv_peak)
+ {
+ CV_LOG_INFO(NULL, "Memory_usage (OpenCV): " << ocv_memory_usage << " (base=" << memory_usage_base_opencv << " current=" << ocv_stats.getCurrentUsage() << ")");
+ }
+ if (memory_usage == 0) // external profiler has higher priority (and accuracy)
+ memory_usage = ocv_memory_usage;
+ }
+#ifdef HAVE_OPENCL
+ uint64_t ocl_memory_usage = 0, ocl_peak = 0;
+ {
+ cv::utils::AllocatorStatisticsInterface& ocl_stats = cv::ocl::getOpenCLAllocatorStatistics();
+ ocl_peak = ocl_stats.getPeakUsage();
+ ocl_memory_usage = ocl_peak - memory_usage_base_opencl;
+ if (ocl_memory_usage > 0)
+ {
+ CV_LOG_INFO(NULL, "Memory_usage (OpenCL): " << ocl_memory_usage << " (base=" << memory_usage_base_opencl << " current=" << ocl_stats.getCurrentUsage() << ")");
+ }
+ ::testing::Test::RecordProperty("ocl_memory_usage",
+ cv::format("%llu", (unsigned long long)ocl_memory_usage));
+ }
+#else
+ uint64_t ocl_memory_usage = 0;
+#endif
+ if (malloc_peak // external memory profiler is available
+ || ocv_peak > 0 // or enabled OpenCV builtin allocation statistics
+ )
+ {
+ CV_LOG_INFO(NULL, "Memory usage total: " << (memory_usage + ocl_memory_usage));
+ ::testing::Test::RecordProperty("memory_usage",
+ cv::format("%llu", (unsigned long long)memory_usage));
+ ::testing::Test::RecordProperty("total_memory_usage",
+ cv::format("%llu", (unsigned long long)(memory_usage + ocl_memory_usage)));
+ }
+}
+
void parseCustomOptions(int argc, char **argv)
{
- const char * const command_line_keys =
+ const string command_line_keys = string(
"{ ipp test_ipp_check |false |check whether IPP works without failures }"
"{ test_seed |809564 |seed for random numbers generator }"
"{ test_threads |-1 |the number of worker threads, if parallel execution is enabled}"
"{ skip_unstable |false |skip unstable tests }"
"{ test_bigdata |false |run BigData tests (>=2Gb) }"
- "{ test_require_data |false |fail on missing non-required test data instead of skip}"
- "{ h help |false |print help info }";
+ "{ test_require_data |") + (checkTestData ? "true" : "false") + string("|fail on missing non-required test data instead of skip (env:OPENCV_TEST_REQUIRE_DATA)}"
+ CV_TEST_TAGS_PARAMS
+ "{ h help |false |print help info }"
+ );
cv::CommandLineParser parser(argc, argv, command_line_keys);
if (parser.get<bool>("help"))
skipUnstableTests = parser.get<bool>("skip_unstable");
runBigDataTests = parser.get<bool>("test_bigdata");
- checkTestData = parser.get<bool>("test_require_data");
-}
+ if (parser.has("test_require_data"))
+ checkTestData = parser.get<bool>("test_require_data");
+ activateTestTags(parser);
+}
static bool isDirectory(const std::string& path)
{
static std::string findData(const std::string& relative_path, bool required, bool findDirectory)
{
-#define TEST_TRY_FILE_WITH_PREFIX(prefix) \
+#define CHECK_FILE_WITH_PREFIX(prefix, result) \
{ \
+ result.clear(); \
std::string path = path_join(prefix, relative_path); \
/*printf("Trying %s\n", path.c_str());*/ \
if (findDirectory) \
{ \
if (isDirectory(path)) \
- return path; \
+ result = path; \
} \
else \
{ \
FILE* f = fopen(path.c_str(), "rb"); \
if(f) { \
fclose(f); \
- return path; \
+ result = path; \
} \
} \
}
+#define TEST_TRY_FILE_WITH_PREFIX(prefix) \
+{ \
+ std::string result__; \
+ CHECK_FILE_WITH_PREFIX(prefix, result__); \
+ if (!result__.empty()) \
+ return result__; \
+}
+
+
const std::vector<std::string>& search_path = TS::ptr()->data_search_path;
for(size_t i = search_path.size(); i > 0; i--)
{
{
const std::string& subdir = search_subdir[i - 1];
std::string prefix = path_join(datapath, subdir);
- TEST_TRY_FILE_WITH_PREFIX(prefix);
+ std::string result_;
+ CHECK_FILE_WITH_PREFIX(prefix, result_);
+ if (!required && !result_.empty())
+ {
+ std::cout << "TEST ERROR: Don't use 'optional' findData() for " << relative_path << std::endl;
+ static bool checkOptionalFlag = cv::utils::getConfigurationParameterBool("OPENCV_TEST_CHECK_OPTIONAL_DATA", false);
+ if (checkOptionalFlag)
+ {
+ CV_Assert(required || result_.empty());
+ }
+ }
+ if (!result_.empty())
+ return result_;
}
}
}