diff options
author | Mathias Stearn <mathias@10gen.com> | 2017-06-13 17:06:03 -0400 |
---|---|---|
committer | Mathias Stearn <mathias@10gen.com> | 2017-06-19 19:02:31 -0400 |
commit | 8b0121efcdb798c18cc4519594bfa52531623932 (patch) | |
tree | b65e0f78e331e65232f0ae7781fba5b0178b33ac /src/mongo/s | |
parent | 9938d658c44140555245943a292e9e33dc75d9c5 (diff) | |
download | mongo-8b0121efcdb798c18cc4519594bfa52531623932.tar.gz |
SERVER-29319 mongos write commands support document sequences
Diffstat (limited to 'src/mongo/s')
22 files changed, 267 insertions, 249 deletions
diff --git a/src/mongo/s/catalog/dist_lock_catalog_impl_test.cpp b/src/mongo/s/catalog/dist_lock_catalog_impl_test.cpp index f54a806cdec..f60ab000ce6 100644 --- a/src/mongo/s/catalog/dist_lock_catalog_impl_test.cpp +++ b/src/mongo/s/catalog/dist_lock_catalog_impl_test.cpp @@ -1121,9 +1121,8 @@ TEST_F(DistLockCatalogFixture, BasicUnlockAll) { ASSERT_EQUALS(dummyHost, request.target); ASSERT_EQUALS("config", request.dbname); - std::string errmsg; BatchedUpdateRequest batchRequest; - ASSERT(batchRequest.parseBSON("config", request.cmdObj, &errmsg)); + batchRequest.parseRequest(OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj)); ASSERT_EQUALS(LocksType::ConfigNS, batchRequest.getNS().toString()); ASSERT_BSONOBJ_EQ(BSON("w" << 1 << "wtimeout" << 0), batchRequest.getWriteConcern()); auto updates = batchRequest.getUpdates(); diff --git a/src/mongo/s/catalog/sharding_catalog_add_shard_test.cpp b/src/mongo/s/catalog/sharding_catalog_add_shard_test.cpp index 1bbc85e887d..2b018ac7e1a 100644 --- a/src/mongo/s/catalog/sharding_catalog_add_shard_test.cpp +++ b/src/mongo/s/catalog/sharding_catalog_add_shard_test.cpp @@ -157,8 +157,7 @@ protected: // Get the BatchedUpdateRequest from the upsert command. BatchedCommandRequest request(BatchedCommandRequest::BatchType::BatchType_Update); - std::string errMsg; - invariant(request.parseBSON("admin", upsertCmdObj, &errMsg) || !request.isValid(&errMsg)); + request.parseRequest(OpMsgRequest::fromDBAndBody("admin", upsertCmdObj)); expectUpdatesReturnSuccess(expectedHost, NamespaceString(NamespaceString::kServerConfigurationNamespace), @@ -174,8 +173,7 @@ protected: // Get the BatchedUpdateRequest from the upsert command. BatchedCommandRequest request(BatchedCommandRequest::BatchType::BatchType_Update); - std::string errMsg; - invariant(request.parseBSON("admin", upsertCmdObj, &errMsg) || !request.isValid(&errMsg)); + request.parseRequest(OpMsgRequest::fromDBAndBody("admin", upsertCmdObj)); expectUpdatesReturnFailure(expectedHost, NamespaceString(NamespaceString::kServerConfigurationNamespace), @@ -198,8 +196,8 @@ protected: ASSERT_EQUALS(expectedNss.db(), request.dbname); BatchedUpdateRequest actualBatchedUpdates; - std::string errmsg; - ASSERT_TRUE(actualBatchedUpdates.parseBSON(request.dbname, request.cmdObj, &errmsg)); + actualBatchedUpdates.parseRequest( + OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj)); // Check that the db and collection names in the BatchedUpdateRequest match the // expected. @@ -244,8 +242,8 @@ protected: ASSERT_EQUALS(expectedNss.db(), request.dbname); BatchedUpdateRequest actualBatchedUpdates; - std::string errmsg; - ASSERT_TRUE(actualBatchedUpdates.parseBSON(request.dbname, request.cmdObj, &errmsg)); + actualBatchedUpdates.parseRequest( + OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj)); // Check that the db and collection names in the BatchedUpdateRequest match the // expected. diff --git a/src/mongo/s/catalog/sharding_catalog_remove_shard_test.cpp b/src/mongo/s/catalog/sharding_catalog_remove_shard_test.cpp index 2b53cc8c51e..5197b4ba3cd 100644 --- a/src/mongo/s/catalog/sharding_catalog_remove_shard_test.cpp +++ b/src/mongo/s/catalog/sharding_catalog_remove_shard_test.cpp @@ -159,8 +159,8 @@ TEST_F(RemoveShardTest, RemoveShardStartDraining) { rpc::TrackingMetadata::removeTrackingData(request.metadata)); BatchedUpdateRequest actualBatchedUpdate; - std::string errmsg; - ASSERT_TRUE(actualBatchedUpdate.parseBSON(request.dbname, request.cmdObj, &errmsg)); + actualBatchedUpdate.parseRequest( + OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj)); ASSERT_EQUALS(ShardType::ConfigNS, actualBatchedUpdate.getNS().ns()); auto updates = actualBatchedUpdate.getUpdates(); ASSERT_EQUALS(1U, updates.size()); @@ -335,8 +335,8 @@ TEST_F(RemoveShardTest, RemoveShardCompletion) { rpc::TrackingMetadata::removeTrackingData(request.metadata)); BatchedDeleteRequest actualBatchedDelete; - std::string errmsg; - ASSERT_TRUE(actualBatchedDelete.parseBSON(request.dbname, request.cmdObj, &errmsg)); + actualBatchedDelete.parseRequest( + OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj)); ASSERT_EQUALS(ShardType::ConfigNS, actualBatchedDelete.getNS().ns()); auto deletes = actualBatchedDelete.getDeletes(); ASSERT_EQUALS(1U, deletes.size()); diff --git a/src/mongo/s/catalog/sharding_catalog_shard_collection_test.cpp b/src/mongo/s/catalog/sharding_catalog_shard_collection_test.cpp index 2332ee83ed0..23d967020f4 100644 --- a/src/mongo/s/catalog/sharding_catalog_shard_collection_test.cpp +++ b/src/mongo/s/catalog/sharding_catalog_shard_collection_test.cpp @@ -124,8 +124,8 @@ public: rpc::TrackingMetadata::removeTrackingData(request.metadata)); BatchedInsertRequest actualBatchedInsert; - std::string errmsg; - ASSERT_TRUE(actualBatchedInsert.parseBSON(request.dbname, request.cmdObj, &errmsg)); + actualBatchedInsert.parseRequest( + OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj)); ASSERT_EQUALS(ChunkType::ConfigNS, actualBatchedInsert.getNS().ns()); auto inserts = actualBatchedInsert.getDocuments(); ASSERT_EQUALS(1U, inserts.size()); @@ -163,8 +163,8 @@ public: rpc::TrackingMetadata::removeTrackingData(request.metadata)); BatchedUpdateRequest actualBatchedUpdate; - std::string errmsg; - ASSERT_TRUE(actualBatchedUpdate.parseBSON(request.dbname, request.cmdObj, &errmsg)); + actualBatchedUpdate.parseRequest( + OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj)); ASSERT_EQUALS(CollectionType::ConfigNS, actualBatchedUpdate.getNS().ns()); auto updates = actualBatchedUpdate.getUpdates(); ASSERT_EQUALS(1U, updates.size()); diff --git a/src/mongo/s/catalog/sharding_catalog_test.cpp b/src/mongo/s/catalog/sharding_catalog_test.cpp index 23a790ff052..a102171f6a4 100644 --- a/src/mongo/s/catalog/sharding_catalog_test.cpp +++ b/src/mongo/s/catalog/sharding_catalog_test.cpp @@ -1122,8 +1122,8 @@ TEST_F(ShardingCatalogClientTest, UpdateDatabase) { rpc::TrackingMetadata::removeTrackingData(request.metadata)); BatchedUpdateRequest actualBatchedUpdate; - std::string errmsg; - ASSERT_TRUE(actualBatchedUpdate.parseBSON(request.dbname, request.cmdObj, &errmsg)); + actualBatchedUpdate.parseRequest( + OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj)); ASSERT_EQUALS(DatabaseType::ConfigNS, actualBatchedUpdate.getNS().ns()); auto updates = actualBatchedUpdate.getUpdates(); ASSERT_EQUALS(1U, updates.size()); @@ -1432,8 +1432,8 @@ TEST_F(ShardingCatalogClientTest, createDatabaseSuccess) { rpc::TrackingMetadata::removeTrackingData(request.metadata)); BatchedInsertRequest actualBatchedInsert; - std::string errmsg; - ASSERT_TRUE(actualBatchedInsert.parseBSON(request.dbname, request.cmdObj, &errmsg)); + actualBatchedInsert.parseRequest( + OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj)); ASSERT_EQUALS(DatabaseType::ConfigNS, actualBatchedInsert.getNS().ns()); auto inserts = actualBatchedInsert.getDocuments(); ASSERT_EQUALS(1U, inserts.size()); @@ -1719,8 +1719,8 @@ TEST_F(ShardingCatalogClientTest, createDatabaseDuplicateKeyOnInsert) { rpc::TrackingMetadata::removeTrackingData(request.metadata)); BatchedInsertRequest actualBatchedInsert; - std::string errmsg; - ASSERT_TRUE(actualBatchedInsert.parseBSON(request.dbname, request.cmdObj, &errmsg)); + actualBatchedInsert.parseRequest( + OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj)); ASSERT_EQUALS(DatabaseType::ConfigNS, actualBatchedInsert.getNS().ns()); auto inserts = actualBatchedInsert.getDocuments(); ASSERT_EQUALS(1U, inserts.size()); diff --git a/src/mongo/s/catalog/sharding_catalog_write_retry_test.cpp b/src/mongo/s/catalog/sharding_catalog_write_retry_test.cpp index 322ea3b464d..aa64208f387 100644 --- a/src/mongo/s/catalog/sharding_catalog_write_retry_test.cpp +++ b/src/mongo/s/catalog/sharding_catalog_write_retry_test.cpp @@ -275,8 +275,8 @@ TEST_F(InsertRetryTest, DuplicateKeyErrorAfterWriteConcernFailureMatch) { onCommand([&](const RemoteCommandRequest& request) { BatchedInsertRequest actualBatchedInsert; - std::string errmsg; - ASSERT_TRUE(actualBatchedInsert.parseBSON(request.dbname, request.cmdObj, &errmsg)); + actualBatchedInsert.parseRequest( + OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj)); ASSERT_EQUALS(kTestNamespace.ns(), actualBatchedInsert.getNS().ns()); BatchedCommandResponse response; @@ -337,8 +337,8 @@ TEST_F(UpdateRetryTest, Success) { onCommand([&](const RemoteCommandRequest& request) { BatchedUpdateRequest actualBatchedUpdate; - std::string errmsg; - ASSERT_TRUE(actualBatchedUpdate.parseBSON(request.dbname, request.cmdObj, &errmsg)); + actualBatchedUpdate.parseRequest( + OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj)); ASSERT_EQUALS(kTestNamespace.ns(), actualBatchedUpdate.getNS().ns()); BatchedCommandResponse response; @@ -449,8 +449,8 @@ TEST_F(UpdateRetryTest, NotMasterOnceSuccessAfterRetry) { onCommand([&](const RemoteCommandRequest& request) { BatchedUpdateRequest actualBatchedUpdate; - std::string errmsg; - ASSERT_TRUE(actualBatchedUpdate.parseBSON(request.dbname, request.cmdObj, &errmsg)); + actualBatchedUpdate.parseRequest( + OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj)); ASSERT_EQUALS(kTestNamespace.ns(), actualBatchedUpdate.getNS().ns()); BatchedCommandResponse response; @@ -484,8 +484,8 @@ TEST_F(UpdateRetryTest, OperationInterruptedDueToPrimaryStepDown) { onCommand([&](const RemoteCommandRequest& request) { BatchedUpdateRequest actualBatchedUpdate; - std::string errmsg; - ASSERT_TRUE(actualBatchedUpdate.parseBSON(request.dbname, request.cmdObj, &errmsg)); + actualBatchedUpdate.parseRequest( + OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj)); ASSERT_EQUALS(kTestNamespace.ns(), actualBatchedUpdate.getNS().ns()); BatchedCommandResponse response; @@ -501,8 +501,8 @@ TEST_F(UpdateRetryTest, OperationInterruptedDueToPrimaryStepDown) { onCommand([&](const RemoteCommandRequest& request) { BatchedUpdateRequest actualBatchedUpdate; - std::string errmsg; - ASSERT_TRUE(actualBatchedUpdate.parseBSON(request.dbname, request.cmdObj, &errmsg)); + actualBatchedUpdate.parseRequest( + OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj)); ASSERT_EQUALS(kTestNamespace.ns(), actualBatchedUpdate.getNS().ns()); BatchedCommandResponse response; @@ -536,8 +536,8 @@ TEST_F(UpdateRetryTest, WriteConcernFailure) { onCommand([&](const RemoteCommandRequest& request) { BatchedUpdateRequest actualBatchedUpdate; - std::string errmsg; - ASSERT_TRUE(actualBatchedUpdate.parseBSON(request.dbname, request.cmdObj, &errmsg)); + actualBatchedUpdate.parseRequest( + OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj)); ASSERT_EQUALS(kTestNamespace.ns(), actualBatchedUpdate.getNS().ns()); BatchedCommandResponse response; @@ -562,8 +562,8 @@ TEST_F(UpdateRetryTest, WriteConcernFailure) { onCommand([&](const RemoteCommandRequest& request) { BatchedUpdateRequest actualBatchedUpdate; - std::string errmsg; - ASSERT_TRUE(actualBatchedUpdate.parseBSON(request.dbname, request.cmdObj, &errmsg)); + actualBatchedUpdate.parseRequest( + OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj)); ASSERT_EQUALS(kTestNamespace.ns(), actualBatchedUpdate.getNS().ns()); BatchedCommandResponse response; diff --git a/src/mongo/s/commands/cluster_write_cmd.cpp b/src/mongo/s/commands/cluster_write_cmd.cpp index e2aee6e42de..400dc400ce1 100644 --- a/src/mongo/s/commands/cluster_write_cmd.cpp +++ b/src/mongo/s/commands/cluster_write_cmd.cpp @@ -97,15 +97,19 @@ public: const BSONObj& cmdObj, ExplainOptions::Verbosity verbosity, BSONObjBuilder* out) const { - BatchedCommandRequest request(_writeType); - - string errMsg; - if (!request.parseBSON(dbname, cmdObj, &errMsg) || !request.isValid(&errMsg)) { + BatchedCommandRequest batchedRequest(_writeType); + OpMsgRequest request; + request.body = cmdObj; + invariant(request.getDatabase() == dbname); // Ensured by explain command's run() method. + batchedRequest.parseRequest(request); + + std::string errMsg; + if (!batchedRequest.isValid(&errMsg)) { return Status(ErrorCodes::FailedToParse, errMsg); } // We can only explain write batches of size 1. - if (request.sizeWriteOps() != 1U) { + if (batchedRequest.sizeWriteOps() != 1U) { return Status(ErrorCodes::InvalidLength, "explained write batches must be of size 1"); } @@ -115,7 +119,7 @@ public: Timer timer; // Target the command to the shards based on the singleton batch item. - BatchItemRef targetingBatchItem(&request, 0); + BatchItemRef targetingBatchItem(&batchedRequest, 0); vector<Strategy::CommandResult> shardResults; Status status = _commandOpWrite(opCtx, dbname, explainCmd, targetingBatchItem, &shardResults); @@ -127,12 +131,11 @@ public: opCtx, shardResults, ClusterExplain::kWriteOnShards, timer.millis(), out); } - virtual bool run(OperationContext* opCtx, - const string& dbname, - const BSONObj& cmdObj, + bool enhancedRun(OperationContext* opCtx, + const OpMsgRequest& request, string& errmsg, - BSONObjBuilder& result) { - BatchedCommandRequest request(_writeType); + BSONObjBuilder& result) final { + BatchedCommandRequest batchedRequest(_writeType); BatchedCommandResponse response; ClusterWriter writer(true, 0); @@ -142,14 +145,14 @@ public: { // Disable the last error object for the duration of the write LastError::Disabled disableLastError(cmdLastError); - - if (!request.parseBSON(dbname, cmdObj, &errmsg) || !request.isValid(&errmsg)) { + batchedRequest.parseRequest(request); + if (!batchedRequest.isValid(&errmsg)) { // Batch parse failure response.setOk(false); response.setErrCode(ErrorCodes::FailedToParse); response.setErrMessage(errmsg); } else { - writer.write(opCtx, request, &response); + writer.write(opCtx, batchedRequest, &response); } dassert(response.isValid(NULL)); @@ -157,17 +160,17 @@ public: // Populate the lastError object based on the write response cmdLastError->reset(); - batchErrorToLastError(request, response, cmdLastError); + batchErrorToLastError(batchedRequest, response, cmdLastError); size_t numAttempts; if (!response.getOk()) { numAttempts = 0; - } else if (request.getOrdered() && response.isErrDetailsSet()) { + } else if (batchedRequest.getOrdered() && response.isErrDetailsSet()) { // Add one failed attempt numAttempts = response.getErrDetailsAt(0)->getIndex() + 1; } else { - numAttempts = request.sizeWriteOps(); + numAttempts = batchedRequest.sizeWriteOps(); } // TODO: increase opcounters by more than one diff --git a/src/mongo/s/sharding_test_fixture.cpp b/src/mongo/s/sharding_test_fixture.cpp index a203d24d518..c0ed6210782 100644 --- a/src/mongo/s/sharding_test_fixture.cpp +++ b/src/mongo/s/sharding_test_fixture.cpp @@ -328,8 +328,8 @@ void ShardingTestFixture::expectInserts(const NamespaceString& nss, ASSERT_EQUALS(nss.db(), request.dbname); BatchedInsertRequest actualBatchedInsert; - std::string errmsg; - ASSERT_TRUE(actualBatchedInsert.parseBSON(request.dbname, request.cmdObj, &errmsg)); + actualBatchedInsert.parseRequest( + OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj)); ASSERT_EQUALS(nss.toString(), actualBatchedInsert.getNS().toString()); @@ -383,8 +383,8 @@ void ShardingTestFixture::expectConfigCollectionInsert(const HostAndPort& config ASSERT_EQUALS("config", request.dbname); BatchedInsertRequest actualBatchedInsert; - std::string errmsg; - ASSERT_TRUE(actualBatchedInsert.parseBSON(request.dbname, request.cmdObj, &errmsg)); + actualBatchedInsert.parseRequest( + OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj)); ASSERT_EQ("config", actualBatchedInsert.getNS().db()); ASSERT_EQ(collName, actualBatchedInsert.getNS().coll()); @@ -448,8 +448,8 @@ void ShardingTestFixture::expectUpdateCollection(const HostAndPort& expectedHost ASSERT_EQUALS("config", request.dbname); BatchedUpdateRequest actualBatchedUpdate; - std::string errmsg; - ASSERT_TRUE(actualBatchedUpdate.parseBSON(request.dbname, request.cmdObj, &errmsg)); + actualBatchedUpdate.parseRequest( + OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj)); ASSERT_EQUALS(CollectionType::ConfigNS, actualBatchedUpdate.getNS().ns()); auto updates = actualBatchedUpdate.getUpdates(); ASSERT_EQUALS(1U, updates.size()); diff --git a/src/mongo/s/write_ops/SConscript b/src/mongo/s/write_ops/SConscript index 69df543a930..a5f54bb1f3f 100644 --- a/src/mongo/s/write_ops/SConscript +++ b/src/mongo/s/write_ops/SConscript @@ -66,6 +66,7 @@ env.CppUnitTest( ], LIBDEPS=[ 'batch_write_types', + '$BUILD_DIR/mongo/db/ops/write_ops_parsers_test_helpers', ] ) diff --git a/src/mongo/s/write_ops/batch_write_exec_test.cpp b/src/mongo/s/write_ops/batch_write_exec_test.cpp index 290596ceed3..1a063281385 100644 --- a/src/mongo/s/write_ops/batch_write_exec_test.cpp +++ b/src/mongo/s/write_ops/batch_write_exec_test.cpp @@ -98,8 +98,8 @@ public: ASSERT_EQUALS(nss.db(), request.dbname); BatchedInsertRequest actualBatchedInsert; - std::string errmsg; - ASSERT_TRUE(actualBatchedInsert.parseBSON(request.dbname, request.cmdObj, &errmsg)); + actualBatchedInsert.parseRequest( + OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj)); ASSERT_EQUALS(nss.toString(), actualBatchedInsert.getNS().toString()); @@ -128,8 +128,8 @@ public: ASSERT_EQUALS(nss.db(), request.dbname); BatchedInsertRequest actualBatchedInsert; - std::string errmsg; - ASSERT_TRUE(actualBatchedInsert.parseBSON(request.dbname, request.cmdObj, &errmsg)); + actualBatchedInsert.parseRequest( + OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj)); ASSERT_EQUALS(nss.toString(), actualBatchedInsert.getNS().toString()); @@ -235,8 +235,8 @@ TEST_F(BatchWriteExecTest, SingleOpError) { ASSERT_EQUALS(nss.db(), request.dbname); BatchedInsertRequest actualBatchedInsert; - std::string errmsg; - ASSERT_TRUE(actualBatchedInsert.parseBSON(request.dbname, request.cmdObj, &errmsg)); + actualBatchedInsert.parseRequest( + OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj)); ASSERT_EQUALS(nss.toString(), actualBatchedInsert.getNS().toString()); diff --git a/src/mongo/s/write_ops/batched_command_request.cpp b/src/mongo/s/write_ops/batched_command_request.cpp index 48c77723db3..f66e00fa70d 100644 --- a/src/mongo/s/write_ops/batched_command_request.cpp +++ b/src/mongo/s/write_ops/batched_command_request.cpp @@ -162,55 +162,38 @@ BSONObj BatchedCommandRequest::toBSON() const { return builder.obj(); } -bool BatchedCommandRequest::parseBSON(StringData dbName, - const BSONObj& source, - std::string* errMsg) { - bool succeeded; +void BatchedCommandRequest::parseRequest(const OpMsgRequest& request) { switch (getBatchType()) { case BatchedCommandRequest::BatchType_Insert: - succeeded = _insertReq->parseBSON(dbName, source, errMsg); + _insertReq->parseRequest(request); break; case BatchedCommandRequest::BatchType_Update: - succeeded = _updateReq->parseBSON(dbName, source, errMsg); + _updateReq->parseRequest(request); break; case BatchedCommandRequest::BatchType_Delete: - succeeded = _deleteReq->parseBSON(dbName, source, errMsg); + _deleteReq->parseRequest(request); break; default: MONGO_UNREACHABLE; } - if (!succeeded) - return false; - - // Parse the command's shard version - auto chunkVersion = ChunkVersion::parseFromBSONForCommands(source); - if (chunkVersion.isOK()) { - _shardVersion = chunkVersion.getValue(); - } else if (chunkVersion != ErrorCodes::NoSuchKey) { - *errMsg = chunkVersion.getStatus().toString(); - return false; + // Now parse out the chunk version and optime. + auto chunkVersion = ChunkVersion::parseFromBSONForCommands(request.body); + if (chunkVersion != ErrorCodes::NoSuchKey) { + _shardVersion = uassertStatusOK(chunkVersion); } // Parse the command's transaction info and do extra validation not done by the parser - try { - _txnInfo = WriteOpTxnInfo::parse(IDLParserErrorContext("WriteOpTxnInfo"), source); - - const auto& stmtIds = _txnInfo.getStmtIds(); - uassert(ErrorCodes::BadValue, - str::stream() << "The size of the statement ids array (" << stmtIds->size() - << ") does not match the number of operations (" - << sizeWriteOps() - << ")", - !stmtIds || stmtIds->size() == sizeWriteOps()); - } catch (const DBException& ex) { - *errMsg = str::stream() << "Failed to parse the write op retriability information due to " - << ex.toString(); - return false; - } + _txnInfo = WriteOpTxnInfo::parse(IDLParserErrorContext("WriteOpTxnInfo"), request.body); - return true; + const auto& stmtIds = _txnInfo.getStmtIds(); + uassert(ErrorCodes::BadValue, + str::stream() << "The size of the statement ids array (" << stmtIds->size() + << ") does not match the number of operations (" + << sizeWriteOps() + << ")", + !stmtIds || stmtIds->size() == sizeWriteOps()); } std::string BatchedCommandRequest::toString() const { diff --git a/src/mongo/s/write_ops/batched_command_request.h b/src/mongo/s/write_ops/batched_command_request.h index 036f9362494..ea0c4c43aae 100644 --- a/src/mongo/s/write_ops/batched_command_request.h +++ b/src/mongo/s/write_ops/batched_command_request.h @@ -36,6 +36,7 @@ #include "mongo/s/write_ops/batched_insert_request.h" #include "mongo/s/write_ops/batched_update_request.h" #include "mongo/s/write_ops/write_ops_gen.h" +#include "mongo/util/net/op_msg.h" namespace mongo { @@ -79,7 +80,7 @@ public: bool isValid(std::string* errMsg) const; BSONObj toBSON() const; - bool parseBSON(StringData dbName, const BSONObj& source, std::string* errMsg); + void parseRequest(const OpMsgRequest& request); std::string toString() const; // diff --git a/src/mongo/s/write_ops/batched_command_request_test.cpp b/src/mongo/s/write_ops/batched_command_request_test.cpp index 6bbd024f4df..82bbd4a3172 100644 --- a/src/mongo/s/write_ops/batched_command_request_test.cpp +++ b/src/mongo/s/write_ops/batched_command_request_test.cpp @@ -29,6 +29,7 @@ #include "mongo/platform/basic.h" #include "mongo/bson/json.h" +#include "mongo/db/ops/write_ops_parsers_test_helpers.h" #include "mongo/s/write_ops/batched_command_request.h" #include "mongo/stdx/memory.h" #include "mongo/unittest/unittest.h" @@ -48,12 +49,13 @@ TEST(BatchedCommandRequest, BasicInsert) { << "ordered" << true); - std::string errMsg; - BatchedCommandRequest insertRequest(BatchedCommandRequest::BatchType_Insert); - ASSERT_TRUE(insertRequest.parseBSON("TestDB", origInsertRequestObj, &errMsg)); + for (auto docSeq : {false, true}) { + BatchedCommandRequest insertRequest(BatchedCommandRequest::BatchType_Insert); + insertRequest.parseRequest(toOpMsg("TestDB", origInsertRequestObj, docSeq)); - ASSERT_EQ("TestDB.test", insertRequest.getInsertRequest()->getNS().toString()); - ASSERT(!insertRequest.hasShardVersion()); + ASSERT_EQ("TestDB.test", insertRequest.getInsertRequest()->getNS().toString()); + ASSERT(!insertRequest.hasShardVersion()); + } } TEST(BatchedCommandRequest, InsertWithShardVersion) { @@ -72,13 +74,14 @@ TEST(BatchedCommandRequest, InsertWithShardVersion) { << "shardVersion" << BSON_ARRAY(Timestamp(1, 2) << epoch)); - std::string errMsg; - BatchedCommandRequest insertRequest(BatchedCommandRequest::BatchType_Insert); - ASSERT_TRUE(insertRequest.parseBSON("TestDB", origInsertRequestObj, &errMsg)); + for (auto docSeq : {false, true}) { + BatchedCommandRequest insertRequest(BatchedCommandRequest::BatchType_Insert); + insertRequest.parseRequest(toOpMsg("TestDB", origInsertRequestObj, docSeq)); - ASSERT_EQ("TestDB.test", insertRequest.getInsertRequest()->getNS().toString()); - ASSERT(insertRequest.hasShardVersion()); - ASSERT_EQ(ChunkVersion(1, 2, epoch).toString(), insertRequest.getShardVersion().toString()); + ASSERT_EQ("TestDB.test", insertRequest.getInsertRequest()->getNS().toString()); + ASSERT(insertRequest.hasShardVersion()); + ASSERT_EQ(ChunkVersion(1, 2, epoch).toString(), insertRequest.getShardVersion().toString()); + } } TEST(BatchedCommandRequest, InsertCloneWithId) { diff --git a/src/mongo/s/write_ops/batched_delete_request.cpp b/src/mongo/s/write_ops/batched_delete_request.cpp index 58a4f47fff2..ae5f22d24da 100644 --- a/src/mongo/s/write_ops/batched_delete_request.cpp +++ b/src/mongo/s/write_ops/batched_delete_request.cpp @@ -99,48 +99,59 @@ BSONObj BatchedDeleteRequest::toBSON() const { return builder.obj(); } -bool BatchedDeleteRequest::parseBSON(StringData dbName, const BSONObj& source, string* errMsg) { +void BatchedDeleteRequest::parseRequest(const OpMsgRequest& request) { clear(); - std::string dummy; - if (!errMsg) - errMsg = &dummy; + for (BSONElement field : request.body) { + auto extractField = [&](const auto& fieldDesc, auto* valOut, auto* isSetOut) { + std::string errMsg; + FieldParser::FieldState fieldState = + FieldParser::extract(field, fieldDesc, valOut, &errMsg); + if (fieldState == FieldParser::FIELD_INVALID) { + uasserted(ErrorCodes::FailedToParse, errMsg); + } + *isSetOut = fieldState == FieldParser::FIELD_SET; + }; - FieldParser::FieldState fieldState; - for (BSONElement field : source) { const StringData fieldName = field.fieldNameStringData(); if (fieldName == collName.name()) { std::string collNameTemp; - fieldState = FieldParser::extract(field, collName, &collNameTemp, errMsg); - if (fieldState == FieldParser::FIELD_INVALID) - return false; - _ns = NamespaceString(dbName, collNameTemp); + extractField(collName, &collNameTemp, &_isNSSet); + _ns = NamespaceString(request.getDatabase(), collNameTemp); uassert(ErrorCodes::InvalidNamespace, str::stream() << "Invalid namespace: " << _ns.ns(), _ns.isValid()); - _isNSSet = fieldState == FieldParser::FIELD_SET; } else if (fieldName == deletes.name()) { - fieldState = FieldParser::extract(field, deletes, &_deletes, errMsg); - if (fieldState == FieldParser::FIELD_INVALID) - return false; - _isDeletesSet = fieldState == FieldParser::FIELD_SET; + extractField(deletes, &_deletes, &_isDeletesSet); } else if (fieldName == writeConcern.name()) { - fieldState = FieldParser::extract(field, writeConcern, &_writeConcern, errMsg); - if (fieldState == FieldParser::FIELD_INVALID) - return false; - _isWriteConcernSet = fieldState == FieldParser::FIELD_SET; + extractField(writeConcern, &_writeConcern, &_isWriteConcernSet); } else if (fieldName == ordered.name()) { - fieldState = FieldParser::extract(field, ordered, &_ordered, errMsg); - if (fieldState == FieldParser::FIELD_INVALID) - return false; - _isOrderedSet = fieldState == FieldParser::FIELD_SET; + extractField(ordered, &_ordered, &_isOrderedSet); } else if (!Command::isGenericArgument(fieldName)) { - *errMsg = str::stream() << "Unknown option to delete command: " << fieldName; - return false; + uasserted(ErrorCodes::FailedToParse, + str::stream() << "Unknown option to delete command: " << fieldName); } } - return true; + for (auto&& seq : request.sequences) { + uassert(ErrorCodes::FailedToParse, + str::stream() << "Unknown document sequence option to " << request.getCommandName() + << " command: " + << seq.name, + seq.name == deletes()); + uassert(ErrorCodes::FailedToParse, + str::stream() << "Duplicate document sequence " << deletes(), + !_isDeletesSet); + _isDeletesSet = true; + + for (auto&& obj : seq.objs) { + _deletes.push_back(new BatchedDeleteDocument()); // _deletes takes ownership. + std::string errMsg; + uassert(ErrorCodes::FailedToParse, + errMsg, + _deletes.back()->parseBSON(obj, &errMsg) && _deletes.back()->isValid(&errMsg)); + } + } } void BatchedDeleteRequest::clear() { diff --git a/src/mongo/s/write_ops/batched_delete_request.h b/src/mongo/s/write_ops/batched_delete_request.h index c539ad7d766..cb8cae589f9 100644 --- a/src/mongo/s/write_ops/batched_delete_request.h +++ b/src/mongo/s/write_ops/batched_delete_request.h @@ -35,6 +35,7 @@ #include "mongo/db/jsobj.h" #include "mongo/db/namespace_string.h" #include "mongo/s/write_ops/batched_delete_document.h" +#include "mongo/util/net/op_msg.h" namespace mongo { @@ -68,7 +69,7 @@ public: bool isValid(std::string* errMsg) const; BSONObj toBSON() const; - bool parseBSON(StringData dbName, const BSONObj& source, std::string* errMsg); + void parseRequest(const OpMsgRequest& request); void clear(); std::string toString() const; diff --git a/src/mongo/s/write_ops/batched_delete_request_test.cpp b/src/mongo/s/write_ops/batched_delete_request_test.cpp index 24b6edbdb9a..5ec55960020 100644 --- a/src/mongo/s/write_ops/batched_delete_request_test.cpp +++ b/src/mongo/s/write_ops/batched_delete_request_test.cpp @@ -31,6 +31,7 @@ #include <string> #include "mongo/db/jsobj.h" +#include "mongo/db/ops/write_ops_parsers_test_helpers.h" #include "mongo/s/write_ops/batched_delete_document.h" #include "mongo/s/write_ops/batched_delete_request.h" #include "mongo/unittest/unittest.h" @@ -52,12 +53,14 @@ TEST(BatchedDeleteRequest, Basic) { << BatchedDeleteRequest::ordered(true)); string errMsg; - BatchedDeleteRequest request; - ASSERT_TRUE(request.parseBSON("foo", origDeleteRequestObj, &errMsg)); + for (auto docSeq : {false, true}) { + BatchedDeleteRequest request; + request.parseRequest(toOpMsg("foo", origDeleteRequestObj, docSeq)); - ASSERT_EQ("foo.test", request.getNS().ns()); + ASSERT_EQ("foo.test", request.getNS().ns()); - ASSERT_BSONOBJ_EQ(origDeleteRequestObj, request.toBSON()); + ASSERT_BSONOBJ_EQ(origDeleteRequestObj, request.toBSON()); + } } TEST(BatchedDeleteRequest, CloneBatchedDeleteDocCopiesAllFields) { @@ -130,18 +133,19 @@ TEST(BatchedDeleteRequest, CollationFieldParsesFromBSONCorrectly) { BSONObj origDeleteRequestObj = BSON( BatchedDeleteRequest::collName("test") << BatchedDeleteRequest::deletes() << deleteArray); - std::string errMsg; - BatchedDeleteRequest request; - ASSERT_TRUE(request.parseBSON("foo", origDeleteRequestObj, &errMsg)); + for (auto docSeq : {false, true}) { + BatchedDeleteRequest request; + request.parseRequest(toOpMsg("foo", origDeleteRequestObj, docSeq)); - ASSERT_EQ(1U, request.sizeDeletes()); - ASSERT_TRUE(request.getDeletesAt(0)->isCollationSet()); - ASSERT_BSONOBJ_EQ(BSON("locale" - << "en_US"), - request.getDeletesAt(0)->getCollation()); + ASSERT_EQ(1U, request.sizeDeletes()); + ASSERT_TRUE(request.getDeletesAt(0)->isCollationSet()); + ASSERT_BSONOBJ_EQ(BSON("locale" + << "en_US"), + request.getDeletesAt(0)->getCollation()); - // Ensure we re-serialize to the original BSON request. - ASSERT_BSONOBJ_EQ(origDeleteRequestObj, request.toBSON()); + // Ensure we re-serialize to the original BSON request. + ASSERT_BSONOBJ_EQ(origDeleteRequestObj, request.toBSON()); + } } } // namespace diff --git a/src/mongo/s/write_ops/batched_insert_request.cpp b/src/mongo/s/write_ops/batched_insert_request.cpp index 39849a45fd9..c8a6de58766 100644 --- a/src/mongo/s/write_ops/batched_insert_request.cpp +++ b/src/mongo/s/write_ops/batched_insert_request.cpp @@ -100,59 +100,57 @@ static void extractIndexNSS(const BSONObj& indexDesc, NamespaceString* indexNSS) *indexNSS = NamespaceString(indexDesc["ns"].str()); } -bool BatchedInsertRequest::parseBSON(StringData dbName, const BSONObj& source, string* errMsg) { +void BatchedInsertRequest::parseRequest(const OpMsgRequest& request) { clear(); - std::string dummy; - if (!errMsg) - errMsg = &dummy; - - BSONObjIterator sourceIt(source); - - while (sourceIt.more()) { - BSONElement sourceEl = sourceIt.next(); + for (auto&& sourceEl : request.body) { const auto fieldName = sourceEl.fieldNameStringData(); + auto extractField = [&](const auto& field, auto* valOut, auto* isSetOut) { + std::string errMsg; + FieldParser::FieldState fieldState = + FieldParser::extract(sourceEl, field, valOut, &errMsg); + if (fieldState == FieldParser::FIELD_INVALID) { + uasserted(ErrorCodes::FailedToParse, errMsg); + } + *isSetOut = fieldState == FieldParser::FIELD_SET; + }; + if (fieldName == collName()) { std::string temp; - FieldParser::FieldState fieldState = - FieldParser::extract(sourceEl, collName, &temp, errMsg); - if (fieldState == FieldParser::FIELD_INVALID) - return false; - _ns = NamespaceString(dbName, temp); + extractField(collName, &temp, &_isNSSet); + _ns = NamespaceString(request.getDatabase(), temp); uassert(ErrorCodes::InvalidNamespace, str::stream() << "Invalid namespace: " << _ns.ns(), _ns.isValid()); - _isNSSet = fieldState == FieldParser::FIELD_SET; } else if (fieldName == documents()) { - FieldParser::FieldState fieldState = - FieldParser::extract(sourceEl, documents, &_documents, errMsg); - if (fieldState == FieldParser::FIELD_INVALID) - return false; - _isDocumentsSet = fieldState == FieldParser::FIELD_SET; + extractField(documents, &_documents, &_isDocumentsSet); if (_documents.size() >= 1) extractIndexNSS(_documents.at(0), &_targetNSS); } else if (fieldName == writeConcern()) { - FieldParser::FieldState fieldState = - FieldParser::extract(sourceEl, writeConcern, &_writeConcern, errMsg); - if (fieldState == FieldParser::FIELD_INVALID) - return false; - _isWriteConcernSet = fieldState == FieldParser::FIELD_SET; + extractField(writeConcern, &_writeConcern, &_isWriteConcernSet); } else if (fieldName == ordered()) { - FieldParser::FieldState fieldState = - FieldParser::extract(sourceEl, ordered, &_ordered, errMsg); - if (fieldState == FieldParser::FIELD_INVALID) - return false; - _isOrderedSet = fieldState == FieldParser::FIELD_SET; + extractField(ordered, &_ordered, &_isOrderedSet); } else if (fieldName == bypassDocumentValidationCommandOption()) { _shouldBypassValidation = sourceEl.trueValue(); } else if (!Command::isGenericArgument(fieldName)) { - *errMsg = str::stream() << "Unknown option to insert command: " << sourceEl.fieldName(); - return false; + uasserted(ErrorCodes::FailedToParse, + str::stream() << "Unknown option to insert command: " << fieldName); } } - return true; + for (auto&& seq : request.sequences) { + uassert(ErrorCodes::FailedToParse, + str::stream() << "Unknown document sequence option to " << request.getCommandName() + << " command: " + << seq.name, + seq.name == documents()); + uassert(ErrorCodes::FailedToParse, + str::stream() << "Duplicate document sequence " << documents(), + !_isDocumentsSet); + _isDocumentsSet = true; + _documents = seq.objs; + } } void BatchedInsertRequest::clear() { diff --git a/src/mongo/s/write_ops/batched_insert_request.h b/src/mongo/s/write_ops/batched_insert_request.h index 6d642f248e1..18b45a2d241 100644 --- a/src/mongo/s/write_ops/batched_insert_request.h +++ b/src/mongo/s/write_ops/batched_insert_request.h @@ -34,6 +34,7 @@ #include "mongo/base/string_data.h" #include "mongo/db/jsobj.h" #include "mongo/db/namespace_string.h" +#include "mongo/util/net/op_msg.h" namespace mongo { @@ -69,7 +70,7 @@ public: bool isValid(std::string* errMsg) const; BSONObj toBSON() const; - bool parseBSON(StringData dbName, const BSONObj& source, std::string* errMsg); + void parseRequest(const OpMsgRequest& request); void clear(); std::string toString() const; diff --git a/src/mongo/s/write_ops/batched_insert_request_test.cpp b/src/mongo/s/write_ops/batched_insert_request_test.cpp index 94976195c59..e9dc7c01963 100644 --- a/src/mongo/s/write_ops/batched_insert_request_test.cpp +++ b/src/mongo/s/write_ops/batched_insert_request_test.cpp @@ -31,6 +31,7 @@ #include <string> #include "mongo/db/jsobj.h" +#include "mongo/db/ops/write_ops_parsers_test_helpers.h" #include "mongo/s/write_ops/batched_command_request.h" #include "mongo/s/write_ops/batched_insert_request.h" #include "mongo/unittest/unittest.h" @@ -50,13 +51,14 @@ TEST(BatchedInsertRequest, Basic) { << BatchedInsertRequest::writeConcern(BSON("w" << 1)) << BatchedInsertRequest::ordered(true)); - string errMsg; - BatchedInsertRequest request; - ASSERT_TRUE(request.parseBSON("foo", origInsertRequestObj, &errMsg)); + for (auto docSeq : {false, true}) { + BatchedInsertRequest request; + request.parseRequest(toOpMsg("foo", origInsertRequestObj, docSeq)); - ASSERT_EQ("foo.test", request.getNS().ns()); + ASSERT_EQ("foo.test", request.getNS().ns()); - ASSERT_BSONOBJ_EQ(origInsertRequestObj, request.toBSON()); + ASSERT_BSONOBJ_EQ(origInsertRequestObj, request.toBSON()); + } } TEST(BatchedInsertRequest, GenIDAll) { diff --git a/src/mongo/s/write_ops/batched_update_request.cpp b/src/mongo/s/write_ops/batched_update_request.cpp index 6da2498ec14..3740d0e3531 100644 --- a/src/mongo/s/write_ops/batched_update_request.cpp +++ b/src/mongo/s/write_ops/batched_update_request.cpp @@ -103,53 +103,61 @@ BSONObj BatchedUpdateRequest::toBSON() const { return builder.obj(); } -bool BatchedUpdateRequest::parseBSON(StringData dbName, const BSONObj& source, string* errMsg) { +void BatchedUpdateRequest::parseRequest(const OpMsgRequest& request) { clear(); - std::string dummy; - if (!errMsg) - errMsg = &dummy; - - FieldParser::FieldState fieldState; - - BSONObjIterator it(source); - while (it.more()) { - const BSONElement& elem = it.next(); - StringData fieldName = elem.fieldNameStringData(); - + for (auto&& elem : request.body) { + auto extractField = [&](const auto& fieldDesc, auto* valOut, auto* isSetOut) { + std::string errMsg; + FieldParser::FieldState fieldState = + FieldParser::extract(elem, fieldDesc, valOut, &errMsg); + if (fieldState == FieldParser::FIELD_INVALID) { + uasserted(ErrorCodes::FailedToParse, errMsg); + } + *isSetOut = fieldState == FieldParser::FIELD_SET; + }; + + const StringData fieldName = elem.fieldNameStringData(); if (fieldName == collName.name()) { std::string collNameTemp; - fieldState = FieldParser::extract(elem, collName, &collNameTemp, errMsg); - if (fieldState == FieldParser::FIELD_INVALID) - return false; - _ns = NamespaceString(dbName, collNameTemp); + extractField(collName, &collNameTemp, &_isNSSet); + _ns = NamespaceString(request.getDatabase(), collNameTemp); uassert(ErrorCodes::InvalidNamespace, str::stream() << "Invalid namespace: " << _ns.ns(), _ns.isValid()); - _isNSSet = fieldState == FieldParser::FIELD_SET; } else if (fieldName == updates.name()) { - fieldState = FieldParser::extract(elem, updates, &_updates, errMsg); - if (fieldState == FieldParser::FIELD_INVALID) - return false; - _isUpdatesSet = fieldState == FieldParser::FIELD_SET; + extractField(updates, &_updates, &_isUpdatesSet); } else if (fieldName == writeConcern.name()) { - fieldState = FieldParser::extract(elem, writeConcern, &_writeConcern, errMsg); - if (fieldState == FieldParser::FIELD_INVALID) - return false; - _isWriteConcernSet = fieldState == FieldParser::FIELD_SET; + extractField(writeConcern, &_writeConcern, &_isWriteConcernSet); } else if (fieldName == ordered.name()) { - fieldState = FieldParser::extract(elem, ordered, &_ordered, errMsg); - if (fieldState == FieldParser::FIELD_INVALID) - return false; - _isOrderedSet = fieldState == FieldParser::FIELD_SET; + extractField(ordered, &_ordered, &_isOrderedSet); } else if (fieldName == bypassDocumentValidationCommandOption()) { _shouldBypassValidation = elem.trueValue(); } else if (!Command::isGenericArgument(fieldName)) { - *errMsg = str::stream() << "Unknown option to update command: " << fieldName; - return false; + uasserted(ErrorCodes::FailedToParse, + str::stream() << "Unknown option to update command: " << fieldName); + } + } + + for (auto&& seq : request.sequences) { + uassert(ErrorCodes::FailedToParse, + str::stream() << "Unknown document sequence option to " << request.getCommandName() + << " command: " + << seq.name, + seq.name == updates()); + uassert(ErrorCodes::FailedToParse, + str::stream() << "Duplicate document sequence " << updates(), + !_isUpdatesSet); + _isUpdatesSet = true; + + for (auto&& obj : seq.objs) { + _updates.push_back(new BatchedUpdateDocument()); // _updates takes ownership. + std::string errMsg; + uassert(ErrorCodes::FailedToParse, + errMsg, + _updates.back()->parseBSON(obj, &errMsg) && _updates.back()->isValid(&errMsg)); } } - return true; } void BatchedUpdateRequest::clear() { diff --git a/src/mongo/s/write_ops/batched_update_request.h b/src/mongo/s/write_ops/batched_update_request.h index 88a8f1ef929..ebfcf1902c0 100644 --- a/src/mongo/s/write_ops/batched_update_request.h +++ b/src/mongo/s/write_ops/batched_update_request.h @@ -35,6 +35,7 @@ #include "mongo/db/jsobj.h" #include "mongo/db/namespace_string.h" #include "mongo/s/write_ops/batched_update_document.h" +#include "mongo/util/net/op_msg.h" namespace mongo { @@ -68,7 +69,7 @@ public: bool isValid(std::string* errMsg) const; BSONObj toBSON() const; - bool parseBSON(StringData dbName, const BSONObj& source, std::string* errMsg); + void parseRequest(const OpMsgRequest& request); void clear(); std::string toString() const; diff --git a/src/mongo/s/write_ops/batched_update_request_test.cpp b/src/mongo/s/write_ops/batched_update_request_test.cpp index c198584e317..da1ab6f9a04 100644 --- a/src/mongo/s/write_ops/batched_update_request_test.cpp +++ b/src/mongo/s/write_ops/batched_update_request_test.cpp @@ -31,6 +31,7 @@ #include <string> #include "mongo/db/jsobj.h" +#include "mongo/db/ops/write_ops_parsers_test_helpers.h" #include "mongo/s/write_ops/batched_update_document.h" #include "mongo/s/write_ops/batched_update_request.h" #include "mongo/unittest/unittest.h" @@ -57,13 +58,14 @@ TEST(BatchedUpdateRequest, Basic) { << BatchedUpdateRequest::writeConcern(BSON("w" << 1)) << BatchedUpdateRequest::ordered(true)); - string errMsg; - BatchedUpdateRequest request; - ASSERT_TRUE(request.parseBSON("foo", origUpdateRequestObj, &errMsg)); + for (auto docSeq : {false, true}) { + BatchedUpdateRequest request; + request.parseRequest(toOpMsg("foo", origUpdateRequestObj, docSeq)); - ASSERT_EQ("foo.test", request.getNS().ns()); + ASSERT_EQ("foo.test", request.getNS().ns()); - ASSERT_BSONOBJ_EQ(origUpdateRequestObj, request.toBSON()); + ASSERT_BSONOBJ_EQ(origUpdateRequestObj, request.toBSON()); + } } TEST(BatchedUpdateRequest, CloneBatchedUpdateDocCopiesAllFields) { @@ -150,18 +152,19 @@ TEST(BatchedUpdateRequest, CollationFieldParsesFromBSONCorrectly) { BSONObj origUpdateRequestObj = BSON( BatchedUpdateRequest::collName("test") << BatchedUpdateRequest::updates() << updateArray); - std::string errMsg; - BatchedUpdateRequest request; - ASSERT_TRUE(request.parseBSON("foo", origUpdateRequestObj, &errMsg)); + for (auto docSeq : {false, true}) { + BatchedUpdateRequest request; + request.parseRequest(toOpMsg("foo", origUpdateRequestObj, docSeq)); - ASSERT_EQ(1U, request.sizeUpdates()); - ASSERT_TRUE(request.getUpdatesAt(0)->isCollationSet()); - ASSERT_BSONOBJ_EQ(BSON("locale" - << "en_US"), - request.getUpdatesAt(0)->getCollation()); + ASSERT_EQ(1U, request.sizeUpdates()); + ASSERT_TRUE(request.getUpdatesAt(0)->isCollationSet()); + ASSERT_BSONOBJ_EQ(BSON("locale" + << "en_US"), + request.getUpdatesAt(0)->getCollation()); - // Ensure we re-serialize to the original BSON request. - ASSERT_BSONOBJ_EQ(origUpdateRequestObj, request.toBSON()); + // Ensure we re-serialize to the original BSON request. + ASSERT_BSONOBJ_EQ(origUpdateRequestObj, request.toBSON()); + } } TEST(BatchedUpdateRequest, CanSetAndRetrieveArrayFiltersField) { @@ -214,17 +217,18 @@ TEST(BatchedUpdateRequest, ArrayFiltersFieldParsesFromBSONCorrectly) { BSONObj origUpdateRequestObj = BSON( BatchedUpdateRequest::collName("test") << BatchedUpdateRequest::updates() << updateArray); - std::string errMsg; - BatchedUpdateRequest request; - ASSERT_TRUE(request.parseBSON("foo", origUpdateRequestObj, &errMsg)); + for (auto docSeq : {false, true}) { + BatchedUpdateRequest request; + request.parseRequest(toOpMsg("foo", origUpdateRequestObj, docSeq)); - ASSERT_EQ(1U, request.sizeUpdates()); - ASSERT_TRUE(request.getUpdatesAt(0)->isArrayFiltersSet()); - ASSERT_EQ(1U, request.getUpdatesAt(0)->getArrayFilters().size()); - ASSERT_BSONOBJ_EQ(BSON("i" << 5), request.getUpdatesAt(0)->getArrayFilters()[0]); + ASSERT_EQ(1U, request.sizeUpdates()); + ASSERT_TRUE(request.getUpdatesAt(0)->isArrayFiltersSet()); + ASSERT_EQ(1U, request.getUpdatesAt(0)->getArrayFilters().size()); + ASSERT_BSONOBJ_EQ(BSON("i" << 5), request.getUpdatesAt(0)->getArrayFilters()[0]); - // Ensure we re-serialize to the original BSON request. - ASSERT_BSONOBJ_EQ(origUpdateRequestObj, request.toBSON()); + // Ensure we re-serialize to the original BSON request. + ASSERT_BSONOBJ_EQ(origUpdateRequestObj, request.toBSON()); + } } } // namespace |