diff --git a/modules/core/test/test_rand.cpp b/modules/core/test/test_rand.cpp index 63b9094177..b687a8f4e0 100644 --- a/modules/core/test/test_rand.cpp +++ b/modules/core/test/test_rand.cpp @@ -382,3 +382,39 @@ TEST(Core_Rand, Regression_Stack_Corruption) ASSERT_EQ(param1, -9); ASSERT_EQ(param2, 2); } + +namespace { + +class RandRowFillParallelLoopBody : public cv::ParallelLoopBody +{ +public: + RandRowFillParallelLoopBody(Mat& dst) : dst_(dst) {} + ~RandRowFillParallelLoopBody() {} + void operator()(const cv::Range& r) const + { + cv::RNG rng = cv::theRNG(); // copy state + for (int y = r.start; y < r.end; y++) + { + cv::theRNG() = cv::RNG(rng.state + y); // seed is based on processed row + cv::randu(dst_.row(y), Scalar(-100), Scalar(100)); + } + // theRNG() state is changed here (but state collision has low probability, so we don't check this) + } +protected: + Mat& dst_; +}; + +TEST(Core_Rand, parallel_for_stable_results) +{ + cv::RNG rng = cv::theRNG(); // save rng state + Mat dst1(1000, 100, CV_8SC1); + parallel_for_(cv::Range(0, dst1.rows), RandRowFillParallelLoopBody(dst1)); + + cv::theRNG() = rng; // restore rng state + Mat dst2(1000, 100, CV_8SC1); + parallel_for_(cv::Range(0, dst2.rows), RandRowFillParallelLoopBody(dst2)); + + ASSERT_EQ(0, countNonZero(dst1 != dst2)); +} + +} // namespace