diff options
Diffstat (limited to 'src/mongo/util/fail_point_test.cpp')
-rw-r--r-- | src/mongo/util/fail_point_test.cpp | 459 |
1 files changed, 222 insertions, 237 deletions
diff --git a/src/mongo/util/fail_point_test.cpp b/src/mongo/util/fail_point_test.cpp index 0b06cb7167d..4abed25d8b5 100644 --- a/src/mongo/util/fail_point_test.cpp +++ b/src/mongo/util/fail_point_test.cpp @@ -45,307 +45,292 @@ using mongo::FailPoint; namespace stdx = mongo::stdx; namespace mongo_test { - TEST(FailPoint, InitialState) { - FailPoint failPoint; - ASSERT_FALSE(failPoint.shouldFail()); +TEST(FailPoint, InitialState) { + FailPoint failPoint; + ASSERT_FALSE(failPoint.shouldFail()); +} + +TEST(FailPoint, AlwaysOn) { + FailPoint failPoint; + failPoint.setMode(FailPoint::alwaysOn); + ASSERT(failPoint.shouldFail()); + + MONGO_FAIL_POINT_BLOCK(failPoint, scopedFp) { + ASSERT(scopedFp.getData().isEmpty()); } - TEST(FailPoint, AlwaysOn) { - FailPoint failPoint; - failPoint.setMode(FailPoint::alwaysOn); + for (size_t x = 0; x < 50; x++) { ASSERT(failPoint.shouldFail()); + } +} - MONGO_FAIL_POINT_BLOCK(failPoint, scopedFp) { - ASSERT(scopedFp.getData().isEmpty()); - } +TEST(FailPoint, NTimes) { + FailPoint failPoint; + failPoint.setMode(FailPoint::nTimes, 4); + ASSERT(failPoint.shouldFail()); + ASSERT(failPoint.shouldFail()); + ASSERT(failPoint.shouldFail()); + ASSERT(failPoint.shouldFail()); - for (size_t x = 0; x < 50; x++) { - ASSERT(failPoint.shouldFail()); - } + for (size_t x = 0; x < 50; x++) { + ASSERT_FALSE(failPoint.shouldFail()); } +} - TEST(FailPoint, NTimes) { - FailPoint failPoint; - failPoint.setMode(FailPoint::nTimes, 4); - ASSERT(failPoint.shouldFail()); - ASSERT(failPoint.shouldFail()); - ASSERT(failPoint.shouldFail()); - ASSERT(failPoint.shouldFail()); +TEST(FailPoint, BlockOff) { + FailPoint failPoint; + bool called = false; - for (size_t x = 0; x < 50; x++) { - ASSERT_FALSE(failPoint.shouldFail()); - } + MONGO_FAIL_POINT_BLOCK(failPoint, scopedFp) { + called = true; } - TEST(FailPoint, BlockOff) { - FailPoint failPoint; - bool called = false; + ASSERT_FALSE(called); +} - MONGO_FAIL_POINT_BLOCK(failPoint, scopedFp) { - called = true; - } +TEST(FailPoint, BlockAlwaysOn) { + FailPoint failPoint; + failPoint.setMode(FailPoint::alwaysOn); + bool called = false; - ASSERT_FALSE(called); + MONGO_FAIL_POINT_BLOCK(failPoint, scopedFp) { + called = true; } - TEST(FailPoint, BlockAlwaysOn) { - FailPoint failPoint; - failPoint.setMode(FailPoint::alwaysOn); - bool called = false; + ASSERT(called); +} + +TEST(FailPoint, BlockNTimes) { + FailPoint failPoint; + failPoint.setMode(FailPoint::nTimes, 1); + size_t counter = 0; + for (size_t x = 0; x < 10; x++) { MONGO_FAIL_POINT_BLOCK(failPoint, scopedFp) { - called = true; + counter++; } - - ASSERT(called); } - TEST(FailPoint, BlockNTimes) { - FailPoint failPoint; - failPoint.setMode(FailPoint::nTimes, 1); - size_t counter = 0; + ASSERT_EQUALS(1U, counter); +} - for (size_t x = 0; x < 10; x++) { - MONGO_FAIL_POINT_BLOCK(failPoint, scopedFp) { - counter++; - } - } +TEST(FailPoint, BlockWithException) { + FailPoint failPoint; + failPoint.setMode(FailPoint::alwaysOn); + bool threw = false; - ASSERT_EQUALS(1U, counter); + try { + MONGO_FAIL_POINT_BLOCK(failPoint, scopedFp) { + throw std::logic_error("BlockWithException threw"); + } + } catch (const std::logic_error&) { + threw = true; } - TEST(FailPoint, BlockWithException) { - FailPoint failPoint; - failPoint.setMode(FailPoint::alwaysOn); - bool threw = false; + ASSERT(threw); + // This will get into an infinite loop if reference counter was not + // properly decremented + failPoint.setMode(FailPoint::off); +} - try { - MONGO_FAIL_POINT_BLOCK(failPoint, scopedFp) { - throw std::logic_error("BlockWithException threw"); - } - } - catch (const std::logic_error &) { - threw = true; - } +TEST(FailPoint, SetGetParam) { + FailPoint failPoint; + failPoint.setMode(FailPoint::alwaysOn, 0, BSON("x" << 20)); - ASSERT(threw); - // This will get into an infinite loop if reference counter was not - // properly decremented - failPoint.setMode(FailPoint::off); + MONGO_FAIL_POINT_BLOCK(failPoint, scopedFp) { + ASSERT_EQUALS(20, scopedFp.getData()["x"].numberInt()); } +} - TEST(FailPoint, SetGetParam) { - FailPoint failPoint; - failPoint.setMode(FailPoint::alwaysOn, 0, BSON("x" << 20)); - - MONGO_FAIL_POINT_BLOCK(failPoint, scopedFp) { - ASSERT_EQUALS(20, scopedFp.getData()["x"].numberInt()); - } - } +TEST(FailPoint, SetInvalidMode) { + FailPoint failPoint; - TEST(FailPoint, SetInvalidMode) { - FailPoint failPoint; + ASSERT_THROWS(failPoint.setMode(static_cast<FailPoint::Mode>(9999)), mongo::UserException); + ASSERT_FALSE(failPoint.shouldFail()); - ASSERT_THROWS(failPoint.setMode(static_cast<FailPoint::Mode>(9999)), - mongo::UserException); - ASSERT_FALSE(failPoint.shouldFail()); + ASSERT_THROWS(failPoint.setMode(static_cast<FailPoint::Mode>(-1)), mongo::UserException); + ASSERT_FALSE(failPoint.shouldFail()); +} - ASSERT_THROWS(failPoint.setMode(static_cast<FailPoint::Mode>(-1)), - mongo::UserException); - ASSERT_FALSE(failPoint.shouldFail()); +class FailPointStress : public mongo::unittest::Test { +public: + void setUp() { + _fp.setMode(FailPoint::alwaysOn, 0, BSON("a" << 44)); } - class FailPointStress: public mongo::unittest::Test { - public: - void setUp() { - _fp.setMode(FailPoint::alwaysOn, 0, BSON("a" << 44)); - } + void tearDown() { + // Note: This can loop indefinitely if reference counter was off + _fp.setMode(FailPoint::off, 0, BSON("a" << 66)); + } - void tearDown() { - // Note: This can loop indefinitely if reference counter was off - _fp.setMode(FailPoint::off, 0, BSON("a" << 66)); - } + void startTest() { + ASSERT_EQUALS(0U, _tasks.size()); - void startTest() { - ASSERT_EQUALS(0U, _tasks.size()); + _tasks.emplace_back(&FailPointStress::blockTask, this); + _tasks.emplace_back(&FailPointStress::blockWithExceptionTask, this); + _tasks.emplace_back(&FailPointStress::simpleTask, this); + _tasks.emplace_back(&FailPointStress::flipTask, this); + } - _tasks.emplace_back(&FailPointStress::blockTask, this); - _tasks.emplace_back(&FailPointStress::blockWithExceptionTask, this); - _tasks.emplace_back(&FailPointStress::simpleTask, this); - _tasks.emplace_back(&FailPointStress::flipTask, this); + void stopTest() { + { + stdx::lock_guard<stdx::mutex> lk(_mutex); + _inShutdown = true; + } + for (auto& t : _tasks) { + t.join(); } + _tasks.clear(); + } - void stopTest() { - { - stdx::lock_guard<stdx::mutex> lk(_mutex); - _inShutdown = true; - } - for (auto& t : _tasks) { - t.join(); +private: + void blockTask() { + while (true) { + MONGO_FAIL_POINT_BLOCK(_fp, scopedFp) { + const mongo::BSONObj& data = scopedFp.getData(); + + // Expanded ASSERT_EQUALS since the error is not being + // printed out properly + if (data["a"].numberInt() != 44) { + mongo::error() << "blockTask thread detected anomaly" + << " - data: " << data << std::endl; + ASSERT(false); + } } - _tasks.clear(); + + stdx::lock_guard<stdx::mutex> lk(_mutex); + if (_inShutdown) + break; } + } - private: - void blockTask() { - while (true) { + void blockWithExceptionTask() { + while (true) { + try { MONGO_FAIL_POINT_BLOCK(_fp, scopedFp) { const mongo::BSONObj& data = scopedFp.getData(); - // Expanded ASSERT_EQUALS since the error is not being - // printed out properly if (data["a"].numberInt() != 44) { - mongo::error() << "blockTask thread detected anomaly" - << " - data: " << data << std::endl; + mongo::error() << "blockWithExceptionTask thread detected anomaly" + << " - data: " << data << std::endl; ASSERT(false); } - } - - stdx::lock_guard<stdx::mutex> lk(_mutex); - if (_inShutdown) - break; - } - } - void blockWithExceptionTask() { - while (true) { - try { - MONGO_FAIL_POINT_BLOCK(_fp, scopedFp) { - const mongo::BSONObj& data = scopedFp.getData(); - - if (data["a"].numberInt() != 44) { - mongo::error() << "blockWithExceptionTask thread detected anomaly" - << " - data: " << data << std::endl; - ASSERT(false); - } - - throw std::logic_error("blockWithExceptionTask threw"); - } - } - catch (const std::logic_error&) { + throw std::logic_error("blockWithExceptionTask threw"); } + } catch (const std::logic_error&) { + } - stdx::lock_guard<stdx::mutex> lk(_mutex); - if (_inShutdown) - break; - } + stdx::lock_guard<stdx::mutex> lk(_mutex); + if (_inShutdown) + break; } + } - void simpleTask() { - while (true) { - static_cast<void>(MONGO_FAIL_POINT(_fp)); - stdx::lock_guard<stdx::mutex> lk(_mutex); - if (_inShutdown) - break; - } + void simpleTask() { + while (true) { + static_cast<void>(MONGO_FAIL_POINT(_fp)); + stdx::lock_guard<stdx::mutex> lk(_mutex); + if (_inShutdown) + break; } + } - void flipTask() { - while (true) { - if(_fp.shouldFail()) { - _fp.setMode(FailPoint::off, 0); - } - else { - _fp.setMode(FailPoint::alwaysOn, 0, BSON("a" << 44)); - } - - stdx::lock_guard<stdx::mutex> lk(_mutex); - if (_inShutdown) - break; + void flipTask() { + while (true) { + if (_fp.shouldFail()) { + _fp.setMode(FailPoint::off, 0); + } else { + _fp.setMode(FailPoint::alwaysOn, 0, BSON("a" << 44)); } + + stdx::lock_guard<stdx::mutex> lk(_mutex); + if (_inShutdown) + break; } + } - FailPoint _fp; - std::vector<stdx::thread> _tasks; - stdx::mutex _mutex; - bool _inShutdown = false; - }; + FailPoint _fp; + std::vector<stdx::thread> _tasks; + stdx::mutex _mutex; + bool _inShutdown = false; +}; - TEST_F(FailPointStress, Basic) { - startTest(); - mongo::sleepsecs(30); - stopTest(); - } +TEST_F(FailPointStress, Basic) { + startTest(); + mongo::sleepsecs(30); + stopTest(); +} - static void parallelFailPointTestThread(FailPoint* fp, - const int64_t numIterations, - const int32_t seed, - int64_t* outNumActivations) { - fp->setThreadPRNGSeed(seed); - int64_t numActivations = 0; - for (int64_t i = 0; i < numIterations; ++i) { - if (fp->shouldFail()) { - ++numActivations; - } +static void parallelFailPointTestThread(FailPoint* fp, + const int64_t numIterations, + const int32_t seed, + int64_t* outNumActivations) { + fp->setThreadPRNGSeed(seed); + int64_t numActivations = 0; + for (int64_t i = 0; i < numIterations; ++i) { + if (fp->shouldFail()) { + ++numActivations; } - *outNumActivations = numActivations; } - /** - * Encounters a failpoint with the given fpMode and fpVal numEncountersPerThread - * times in each of numThreads parallel threads, and returns the number of total - * times that the failpoint was activiated. - */ - static int64_t runParallelFailPointTest( - FailPoint::Mode fpMode, - FailPoint::ValType fpVal, - const int32_t numThreads, - const int32_t numEncountersPerThread) { - - ASSERT_GT(numThreads, 0); - ASSERT_GT(numEncountersPerThread, 0); - FailPoint failPoint; - failPoint.setMode(fpMode, fpVal); - std::vector<stdx::thread*> tasks; - std::vector<int64_t> counts(numThreads, 0); - ASSERT_EQUALS(static_cast<uint32_t>(numThreads), counts.size()); - for (int32_t i = 0; i < numThreads; ++i) { - tasks.push_back(new stdx::thread(parallelFailPointTestThread, - &failPoint, - numEncountersPerThread, - i, // hardcoded seed, different for each thread. - &counts[i])); - } - int64_t totalActivations = 0; - for (int32_t i = 0; i < numThreads; ++i) { - tasks[i]->join(); - delete tasks[i]; - totalActivations += counts[i]; - } - return totalActivations; + *outNumActivations = numActivations; +} +/** + * Encounters a failpoint with the given fpMode and fpVal numEncountersPerThread + * times in each of numThreads parallel threads, and returns the number of total + * times that the failpoint was activiated. + */ +static int64_t runParallelFailPointTest(FailPoint::Mode fpMode, + FailPoint::ValType fpVal, + const int32_t numThreads, + const int32_t numEncountersPerThread) { + ASSERT_GT(numThreads, 0); + ASSERT_GT(numEncountersPerThread, 0); + FailPoint failPoint; + failPoint.setMode(fpMode, fpVal); + std::vector<stdx::thread*> tasks; + std::vector<int64_t> counts(numThreads, 0); + ASSERT_EQUALS(static_cast<uint32_t>(numThreads), counts.size()); + for (int32_t i = 0; i < numThreads; ++i) { + tasks.push_back(new stdx::thread(parallelFailPointTestThread, + &failPoint, + numEncountersPerThread, + i, // hardcoded seed, different for each thread. + &counts[i])); } - - TEST(FailPoint, RandomActivationP0) { - ASSERT_EQUALS(0, runParallelFailPointTest(FailPoint::random, 0, 1, 1000000)); + int64_t totalActivations = 0; + for (int32_t i = 0; i < numThreads; ++i) { + tasks[i]->join(); + delete tasks[i]; + totalActivations += counts[i]; } + return totalActivations; +} - TEST(FailPoint, RandomActivationP5) { - ASSERT_APPROX_EQUAL( - 500000, - runParallelFailPointTest(FailPoint::random, - std::numeric_limits<int32_t>::max() / 2, - 10, - 100000), - 500); - } +TEST(FailPoint, RandomActivationP0) { + ASSERT_EQUALS(0, runParallelFailPointTest(FailPoint::random, 0, 1, 1000000)); +} - TEST(FailPoint, RandomActivationP01) { - ASSERT_APPROX_EQUAL( - 10000, - runParallelFailPointTest(FailPoint::random, - std::numeric_limits<int32_t>::max() / 100, - 10, - 100000), - 500); - } +TEST(FailPoint, RandomActivationP5) { + ASSERT_APPROX_EQUAL(500000, + runParallelFailPointTest( + FailPoint::random, std::numeric_limits<int32_t>::max() / 2, 10, 100000), + 500); +} - TEST(FailPoint, RandomActivationP001) { - ASSERT_APPROX_EQUAL( - 1000, - runParallelFailPointTest(FailPoint::random, - std::numeric_limits<int32_t>::max() / 1000, - 10, - 100000), - 500); - } +TEST(FailPoint, RandomActivationP01) { + ASSERT_APPROX_EQUAL( + 10000, + runParallelFailPointTest( + FailPoint::random, std::numeric_limits<int32_t>::max() / 100, 10, 100000), + 500); +} +TEST(FailPoint, RandomActivationP001) { + ASSERT_APPROX_EQUAL( + 1000, + runParallelFailPointTest( + FailPoint::random, std::numeric_limits<int32_t>::max() / 1000, 10, 100000), + 500); +} } |