From 92fc2a914c7938b1135192ed55e984b346db2c3e Mon Sep 17 00:00:00 2001 From: Lingzhi Deng Date: Mon, 15 Jul 2019 18:52:37 -0400 Subject: parseBSON --- src/mongo/util/fail_point.cpp | 36 +++++++++++++++++++++ src/mongo/util/fail_point.h | 7 ++-- src/mongo/util/fail_point_test.cpp | 65 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+), 3 deletions(-) diff --git a/src/mongo/util/fail_point.cpp b/src/mongo/util/fail_point.cpp index 5755620be7a..b705e6a01bf 100644 --- a/src/mongo/util/fail_point.cpp +++ b/src/mongo/util/fail_point.cpp @@ -296,6 +296,42 @@ FailPoint::parseBSON(const BSONObj& obj) { } SyncConfig syncConfig; + const BSONElement syncElem(obj["sync"]); + if (!syncElem.eoo()) { + if (syncElem.type() != Object) { + return {ErrorCodes::TypeMismatch, "'sync' must be a JSON object"}; + } + const BSONObj syncObj(syncElem.Obj()); + if (syncObj.hasField("signals")) { + const BSONElement signals(syncObj["signals"]); + if (!signals.ok() || signals.type() != Array) { + return {ErrorCodes::TypeMismatch, "'sync.signals' must be an array of strings"}; + } + auto it = BSONObjIterator(signals.Obj()); + while (it.more()) { + auto e = it.next(); + if (e.type() != String) { + return {ErrorCodes::TypeMismatch, "'sync.signals' must be an array of strings"}; + } + syncConfig.signals.insert(e.String()); + } + } + if (syncObj.hasField("waitFor")) { + const BSONElement waitFor(syncObj["waitFor"]); + if (!waitFor.ok() || waitFor.type() != Array) { + return {ErrorCodes::TypeMismatch, "'sync.waitFor' must be an array of strings"}; + } + auto it = BSONObjIterator(waitFor.Obj()); + while (it.more()) { + auto e = it.next(); + if (e.type() != String) { + return {ErrorCodes::TypeMismatch, "'sync.waitFor' must be an array of strings"}; + } + syncConfig.waitFor.insert(e.String()); + } + } + syncConfig.enabled = true; + } return std::make_tuple(mode, val, data, syncConfig); } diff --git a/src/mongo/util/fail_point.h b/src/mongo/util/fail_point.h index fbabb169ffc..832d90349ef 100644 --- a/src/mongo/util/fail_point.h +++ b/src/mongo/util/fail_point.h @@ -78,8 +78,9 @@ public: enum RetCode { fastOff = 0, slowOff, slowOn, userIgnored }; struct SyncConfig { + SyncConfig() {} // Is this failpoint configured for failpoints synchronization. - bool enabled; + bool enabled = false; // Signals to emit when the failpoint is reached. std::unordered_set signals; // Signals to wait for when the failpoint is reached. @@ -146,8 +147,6 @@ public: void sync() const; - bool isSynced() const; - bool syncEnabled() const; /** @@ -215,6 +214,8 @@ private: */ void disableFailPoint(); + bool isSynced() const; + /** * slow path for #shouldFailOpenBlock * diff --git a/src/mongo/util/fail_point_test.cpp b/src/mongo/util/fail_point_test.cpp index 2a759a5216a..823c83eb763 100644 --- a/src/mongo/util/fail_point_test.cpp +++ b/src/mongo/util/fail_point_test.cpp @@ -403,6 +403,71 @@ TEST(FailPoint, parseBSONValidDataSucceeds) { ASSERT_TRUE(swTuple.isOK()); } +TEST(FailPoint, parseBSONValidSync) { + auto swTuple = FailPoint::parseBSON(BSON("mode" + << "alwaysOn" + << "sync" + << BSON("signals" << BSON_ARRAY("a" + << "b" + << "c")))); + std::cout << swTuple.getStatus() << std::endl; + ASSERT_TRUE(swTuple.isOK()); + + swTuple = FailPoint::parseBSON(BSON("mode" + << "alwaysOn" + << "sync" + << BSON("waitFor" << BSON_ARRAY("a" + << "b" + << "c")))); + std::cout << swTuple.getStatus() << std::endl; + ASSERT_TRUE(swTuple.isOK()); + + swTuple = FailPoint::parseBSON(BSON("mode" + << "alwaysOn" + << "sync" + << BSON("signals" << BSON_ARRAY("a" + << "b" + << "c") + << "waitFor" + << BSON_ARRAY("c" + << "d" + << "e")))); + std::cout << swTuple.getStatus() << std::endl; + ASSERT_TRUE(swTuple.isOK()); +} + +TEST(FailPoint, parseBSONInvalidSyncFails) { + auto swTuple = FailPoint::parseBSON(BSON("mode" + << "alwaysOn" + << "sync" + << BSON("signals" + << "a"))); + std::cout << swTuple.getStatus() << std::endl; + ASSERT_FALSE(swTuple.isOK()); + + swTuple = FailPoint::parseBSON(BSON("mode" + << "alwaysOn" + << "sync" + << BSON("signals" << BSON_ARRAY(1 << 2)))); + std::cout << swTuple.getStatus() << std::endl; + ASSERT_FALSE(swTuple.isOK()); + + swTuple = FailPoint::parseBSON(BSON("mode" + << "alwaysOn" + << "sync" + << BSON("waitFor" + << "a"))); + std::cout << swTuple.getStatus() << std::endl; + ASSERT_FALSE(swTuple.isOK()); + + swTuple = FailPoint::parseBSON(BSON("mode" + << "alwaysOn" + << "sync" + << BSON("waitFor" << BSON_ARRAY(1 << 2)))); + std::cout << swTuple.getStatus() << std::endl; + ASSERT_FALSE(swTuple.isOK()); +} + TEST(FailPoint, FailPointBlockBasicTest) { auto failPoint = getGlobalFailPointRegistry()->getFailPoint("dummy"); -- cgit v1.2.1