diff options
author | Tess Avitabile <tess.avitabile@mongodb.com> | 2017-07-27 11:06:55 -0400 |
---|---|---|
committer | Tess Avitabile <tess.avitabile@mongodb.com> | 2017-07-31 14:42:24 -0400 |
commit | 3867d603a00888a4cd16d52380233f585db5c0fb (patch) | |
tree | 1f1f0485c1348700b2f30531e2fc9039473bdf90 /src/mongo/db/update/set_node_test.cpp | |
parent | 0a55ace0a362a5944fedbaec2d95b2d7cda750d6 (diff) | |
download | mongo-3867d603a00888a4cd16d52380233f585db5c0fb.tar.gz |
SERVER-28773 UpdateNode::apply should take a parameter struct
Diffstat (limited to 'src/mongo/db/update/set_node_test.cpp')
-rw-r--r-- | src/mongo/db/update/set_node_test.cpp | 2288 |
1 files changed, 463 insertions, 1825 deletions
diff --git a/src/mongo/db/update/set_node_test.cpp b/src/mongo/db/update/set_node_test.cpp index 0df17390b0b..932798e61e7 100644 --- a/src/mongo/db/update/set_node_test.cpp +++ b/src/mongo/db/update/set_node_test.cpp @@ -33,12 +33,14 @@ #include "mongo/bson/mutable/algorithm.h" #include "mongo/bson/mutable/mutable_bson_test_utils.h" #include "mongo/db/json.h" +#include "mongo/db/update/update_node_test_fixture.h" #include "mongo/unittest/death_test.h" #include "mongo/unittest/unittest.h" +namespace mongo { namespace { -using namespace mongo; +using SetNodeTest = UpdateNodeTest; using mongo::mutablebson::Document; using mongo::mutablebson::Element; using mongo::mutablebson::countChildren; @@ -57,368 +59,177 @@ TEST(SetNodeTest, InitSucceedsForNonemptyElement) { ASSERT_OK(node.init(update["$set"]["a"], collator)); } -TEST(SetNodeTest, ApplyNoOp) { +TEST_F(SetNodeTest, ApplyNoOp) { auto update = fromjson("{$set: {a: 5}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); Document doc(fromjson("{a: 5}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a"); - Document logDoc; - LogBuilder logBuilder(logDoc.root()); - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - &logBuilder, - &indexesAffected, - &noop); - ASSERT_TRUE(noop); - ASSERT_FALSE(indexesAffected); + setPathTaken("a"); + addIndexedPath("a"); + auto result = node.apply(getApplyParams(doc.root()["a"])); + ASSERT_TRUE(result.noop); + ASSERT_FALSE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: 5}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); - ASSERT_EQUALS(fromjson("{}"), logDoc); + ASSERT_EQUALS(fromjson("{}"), getLogDoc()); } -TEST(SetNodeTest, ApplyEmptyPathToCreate) { +TEST_F(SetNodeTest, ApplyEmptyPathToCreate) { auto update = fromjson("{$set: {a: 6}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); Document doc(fromjson("{a: 5}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a"); - Document logDoc; - LogBuilder logBuilder(logDoc.root()); - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - &logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathTaken("a"); + addIndexedPath("a"); + auto result = node.apply(getApplyParams(doc.root()["a"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: 6}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); - ASSERT_EQUALS(fromjson("{$set: {a: 6}}"), logDoc); + ASSERT_EQUALS(fromjson("{$set: {a: 6}}"), getLogDoc()); } -TEST(SetNodeTest, ApplyCreatePath) { +TEST_F(SetNodeTest, ApplyCreatePath) { auto update = fromjson("{$set: {'a.b.c': 6}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.b.c"], collator)); Document doc(fromjson("{a: {d: 5}}")); - FieldRef pathToCreate("b.c"); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a"); - Document logDoc; - LogBuilder logBuilder(logDoc.root()); - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - &logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathToCreate("b.c"); + setPathTaken("a"); + addIndexedPath("a"); + auto result = node.apply(getApplyParams(doc.root()["a"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: {d: 5, b: {c: 6}}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); - ASSERT_EQUALS(fromjson("{$set: {'a.b.c': 6}}"), logDoc); + ASSERT_EQUALS(fromjson("{$set: {'a.b.c': 6}}"), getLogDoc()); } -TEST(SetNodeTest, ApplyCreatePathFromRoot) { +TEST_F(SetNodeTest, ApplyCreatePathFromRoot) { auto update = fromjson("{$set: {'a.b': 6}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); Document doc(fromjson("{c: 5}")); - FieldRef pathToCreate("a.b"); - FieldRef pathTaken(""); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a"); - Document logDoc; - LogBuilder logBuilder(logDoc.root()); - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root(), - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - &logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathToCreate("a.b"); + addIndexedPath("a"); + auto result = node.apply(getApplyParams(doc.root())); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{c: 5, a: {b: 6}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); - ASSERT_EQUALS(fromjson("{$set: {'a.b': 6}}"), logDoc); + ASSERT_EQUALS(fromjson("{$set: {'a.b': 6}}"), getLogDoc()); } -TEST(SetNodeTest, ApplyPositional) { +TEST_F(SetNodeTest, ApplyPositional) { auto update = fromjson("{$set: {'a.$': 6}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.$"], collator)); Document doc(fromjson("{a: [0, 1, 2]}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a.1"); - StringData matchedField("1"); - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a"); - Document logDoc; - LogBuilder logBuilder(logDoc.root()); - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"]["1"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - &logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathTaken("a.1"); + setMatchedField("1"); + addIndexedPath("a"); + auto result = node.apply(getApplyParams(doc.root()["a"]["1"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: [0, 6, 2]}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); - ASSERT_EQUALS(fromjson("{$set: {'a.1': 6}}"), logDoc); + ASSERT_EQUALS(fromjson("{$set: {'a.1': 6}}"), getLogDoc()); } -TEST(SetNodeTest, ApplyNonViablePathToCreate) { +TEST_F(SetNodeTest, ApplyNonViablePathToCreate) { auto update = fromjson("{$set: {'a.b': 5}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); Document doc(fromjson("{a: 5}")); - FieldRef pathToCreate("b"); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a"); - Document logDoc; - LogBuilder logBuilder(logDoc.root()); - auto indexesAffected = false; - auto noop = false; - ASSERT_THROWS_CODE_AND_WHAT(node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - &logBuilder, - &indexesAffected, - &noop), + setPathToCreate("b"); + setPathTaken("a"); + addIndexedPath("a"); + ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"])), UserException, ErrorCodes::PathNotViable, "Cannot create field 'b' in element {a: 5}"); } -TEST(SetNodeTest, ApplyNonViablePathToCreateFromReplicationIsNoOp) { +TEST_F(SetNodeTest, ApplyNonViablePathToCreateFromReplicationIsNoOp) { auto update = fromjson("{$set: {'a.b': 5}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); Document doc(fromjson("{a: 5}")); - FieldRef pathToCreate("b"); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = true; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a"); - Document logDoc; - LogBuilder logBuilder(logDoc.root()); - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - &logBuilder, - &indexesAffected, - &noop); - ASSERT_TRUE(noop); - ASSERT_FALSE(indexesAffected); + setPathToCreate("b"); + setPathTaken("a"); + addIndexedPath("a"); + setFromReplication(true); + auto result = node.apply(getApplyParams(doc.root()["a"])); + ASSERT_TRUE(result.noop); + ASSERT_FALSE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: 5}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); - ASSERT_EQUALS(fromjson("{}"), logDoc); + ASSERT_EQUALS(fromjson("{}"), getLogDoc()); } -TEST(SetNodeTest, ApplyNoIndexDataNoLogBuilder) { +TEST_F(SetNodeTest, ApplyNoIndexDataNoLogBuilder) { auto update = fromjson("{$set: {a: 6}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); Document doc(fromjson("{a: 5}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - const UpdateIndexData* indexData = nullptr; - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_FALSE(indexesAffected); + setPathTaken("a"); + setLogBuilderToNull(); + auto result = node.apply(getApplyParams(doc.root()["a"])); + ASSERT_FALSE(result.noop); + ASSERT_FALSE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: 6}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyDoesNotAffectIndexes) { +TEST_F(SetNodeTest, ApplyDoesNotAffectIndexes) { auto update = fromjson("{$set: {a: 6}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); Document doc(fromjson("{a: 5}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_FALSE(indexesAffected); + setPathTaken("a"); + addIndexedPath("b"); + auto result = node.apply(getApplyParams(doc.root()["a"])); + ASSERT_FALSE(result.noop); + ASSERT_FALSE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: 6}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, TypeChangeIsNotANoop) { +TEST_F(SetNodeTest, TypeChangeIsNotANoop) { auto update = fromjson("{$set: {a: NumberLong(2)}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); Document doc(fromjson("{a: NumberInt(2)}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathTaken("a"); + addIndexedPath("a"); + auto result = node.apply(getApplyParams(doc.root()["a"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: NumberLong(2)}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, IdentityOpOnDeserializedIsNotANoOp) { +TEST_F(SetNodeTest, IdentityOpOnDeserializedIsNotANoOp) { // Apply an op that would be a no-op. auto update = fromjson("{$set: {a: {b : NumberInt(2)}}}"); const CollatorInterface* collator = nullptr; @@ -429,1503 +240,707 @@ TEST(SetNodeTest, IdentityOpOnDeserializedIsNotANoOp) { // Apply a mutation to the document that will make it non-serialized. doc.root()["a"]["b"].setValueInt(2).transitional_ignore(); - FieldRef pathToCreate(""); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathTaken("a"); + addIndexedPath("a"); + auto result = node.apply(getApplyParams(doc.root()["a"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: {b : NumberInt(2)}}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyEmptyDocument) { +TEST_F(SetNodeTest, ApplyEmptyDocument) { auto update = fromjson("{$set: {a: 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); Document doc(fromjson("{}")); - FieldRef pathToCreate("a"); - FieldRef pathTaken(""); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root(), - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathToCreate("a"); + addIndexedPath("a"); + auto result = node.apply(getApplyParams(doc.root())); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: 2}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyInPlace) { +TEST_F(SetNodeTest, ApplyInPlace) { auto update = fromjson("{$set: {a: 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); Document doc(fromjson("{a: 1}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathTaken("a"); + addIndexedPath("a"); + auto result = node.apply(getApplyParams(doc.root()["a"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: 2}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyOverridePath) { +TEST_F(SetNodeTest, ApplyOverridePath) { auto update = fromjson("{$set: {a: 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); Document doc(fromjson("{a: {b: 1}}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathTaken("a"); + addIndexedPath("a"); + auto result = node.apply(getApplyParams(doc.root()["a"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: 2}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyChangeType) { +TEST_F(SetNodeTest, ApplyChangeType) { auto update = fromjson("{$set: {a: 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); Document doc(fromjson("{a: 'str'}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathTaken("a"); + addIndexedPath("a"); + auto result = node.apply(getApplyParams(doc.root()["a"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: 2}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyNewPath) { +TEST_F(SetNodeTest, ApplyNewPath) { auto update = fromjson("{$set: {a: 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); Document doc(fromjson("{b: 1}")); - FieldRef pathToCreate("a"); - FieldRef pathTaken(""); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root(), - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathToCreate("a"); + addIndexedPath("a"); + auto result = node.apply(getApplyParams(doc.root())); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{b: 1, a: 2}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyLog) { +TEST_F(SetNodeTest, ApplyLog) { auto update = fromjson("{$set: {a: 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); Document doc(fromjson("{a: 1}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - const UpdateIndexData* indexData = nullptr; - Document logDoc; - LogBuilder logBuilder(logDoc.root()); - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - indexData, - &logBuilder, - &indexesAffected, - &noop); + setPathTaken("a"); + node.apply(getApplyParams(doc.root()["a"])); ASSERT_EQUALS(fromjson("{a: 2}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); - ASSERT_EQUALS(countChildren(logDoc.root()), 1u); - ASSERT_EQUALS(fromjson("{$set: {a: 2}}"), logDoc); + ASSERT_EQUALS(countChildren(getLogDoc().root()), 1u); + ASSERT_EQUALS(fromjson("{$set: {a: 2}}"), getLogDoc()); } -TEST(SetNodeTest, ApplyNoOpDottedPath) { +TEST_F(SetNodeTest, ApplyNoOpDottedPath) { auto update = fromjson("{$set: {'a.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); Document doc(fromjson("{a: {b: 2}}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a.b"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"]["b"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_TRUE(noop); - ASSERT_FALSE(indexesAffected); + setPathTaken("a.b"); + addIndexedPath("a.b"); + auto result = node.apply(getApplyParams(doc.root()["a"]["b"])); + ASSERT_TRUE(result.noop); + ASSERT_FALSE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: {b : 2}}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, TypeChangeOnDottedPathIsNotANoOp) { +TEST_F(SetNodeTest, TypeChangeOnDottedPathIsNotANoOp) { auto update = fromjson("{$set: {'a.b': NumberInt(2)}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); Document doc(fromjson("{a: {b: NumberLong(2)}}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a.b"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"]["b"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathTaken("a.b"); + addIndexedPath("a.b"); + auto result = node.apply(getApplyParams(doc.root()["a"]["b"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: {b : NumberLong(2)}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyPathNotViable) { +TEST_F(SetNodeTest, ApplyPathNotViable) { auto update = fromjson("{$set: {'a.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); Document doc(fromjson("{a:1}")); - FieldRef pathToCreate("b"); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - const UpdateIndexData* indexData = nullptr; - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - ASSERT_THROWS_CODE_AND_WHAT(node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - indexData, - logBuilder, - &indexesAffected, - &noop), + setPathToCreate("b"); + setPathTaken("a"); + ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"])), UserException, ErrorCodes::PathNotViable, "Cannot create field 'b' in element {a: 1}"); } -TEST(SetNodeTest, ApplyPathNotViableArrray) { +TEST_F(SetNodeTest, ApplyPathNotViableArrray) { auto update = fromjson("{$set: {'a.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); Document doc(fromjson("{a:[{b:1}]}")); - FieldRef pathToCreate("b"); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - const UpdateIndexData* indexData = nullptr; - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - ASSERT_THROWS_CODE_AND_WHAT(node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - indexData, - logBuilder, - &indexesAffected, - &noop), + setPathToCreate("b"); + setPathTaken("a"); + ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"])), UserException, ErrorCodes::PathNotViable, "Cannot create field 'b' in element {a: [ { b: 1 } ]}"); } -TEST(SetNodeTest, ApplyInPlaceDottedPath) { +TEST_F(SetNodeTest, ApplyInPlaceDottedPath) { auto update = fromjson("{$set: {'a.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); Document doc(fromjson("{a: {b: 1}}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a.b"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"]["b"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathTaken("a.b"); + addIndexedPath("a.b"); + auto result = node.apply(getApplyParams(doc.root()["a"]["b"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: {b: 2}}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyChangeTypeDottedPath) { +TEST_F(SetNodeTest, ApplyChangeTypeDottedPath) { auto update = fromjson("{$set: {'a.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); Document doc(fromjson("{a: {b: 'str'}}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a.b"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"]["b"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathTaken("a.b"); + addIndexedPath("a.b"); + auto result = node.apply(getApplyParams(doc.root()["a"]["b"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: {b: 2}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyChangePath) { +TEST_F(SetNodeTest, ApplyChangePath) { auto update = fromjson("{$set: {'a.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); Document doc(fromjson("{a: {b: {c: 1}}}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a.b"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"]["b"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathTaken("a.b"); + addIndexedPath("a.b"); + auto result = node.apply(getApplyParams(doc.root()["a"]["b"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: {b: 2}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyExtendPath) { +TEST_F(SetNodeTest, ApplyExtendPath) { auto update = fromjson("{$set: {'a.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); Document doc(fromjson("{a: {c: 1}}")); - FieldRef pathToCreate("b"); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathToCreate("b"); + setPathTaken("a"); + addIndexedPath("a.b"); + auto result = node.apply(getApplyParams(doc.root()["a"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: {c: 1, b: 2}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyNewDottedPath) { +TEST_F(SetNodeTest, ApplyNewDottedPath) { auto update = fromjson("{$set: {'a.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); Document doc(fromjson("{c: 1}")); - FieldRef pathToCreate("a.b"); - FieldRef pathTaken(""); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root(), - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathToCreate("a.b"); + addIndexedPath("a.b"); + auto result = node.apply(getApplyParams(doc.root())); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{c: 1, a: {b: 2}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyEmptyDoc) { +TEST_F(SetNodeTest, ApplyEmptyDoc) { auto update = fromjson("{$set: {'a.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); Document doc(fromjson("{}")); - FieldRef pathToCreate("a.b"); - FieldRef pathTaken(""); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root(), - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathToCreate("a.b"); + addIndexedPath("a.b"); + auto result = node.apply(getApplyParams(doc.root())); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: {b: 2}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyFieldWithDot) { +TEST_F(SetNodeTest, ApplyFieldWithDot) { auto update = fromjson("{$set: {'a.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); Document doc(fromjson("{'a.b':4}")); - FieldRef pathToCreate("a.b"); - FieldRef pathTaken(""); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root(), - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathToCreate("a.b"); + addIndexedPath("a.b"); + auto result = node.apply(getApplyParams(doc.root())); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{'a.b':4, a: {b: 2}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyNoOpArrayIndex) { +TEST_F(SetNodeTest, ApplyNoOpArrayIndex) { auto update = fromjson("{$set: {'a.2.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); Document doc(fromjson("{a: [{b: 0},{b: 1},{b: 2}]}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a.2.b"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.2.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"]["2"]["b"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_TRUE(noop); - ASSERT_FALSE(indexesAffected); + setPathTaken("a.2.b"); + addIndexedPath("a.2.b"); + auto result = node.apply(getApplyParams(doc.root()["a"]["2"]["b"])); + ASSERT_TRUE(result.noop); + ASSERT_FALSE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: [{b: 0},{b: 1},{b: 2}]}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, TypeChangeInArrayIsNotANoOp) { +TEST_F(SetNodeTest, TypeChangeInArrayIsNotANoOp) { auto update = fromjson("{$set: {'a.2.b': NumberInt(2)}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); Document doc(fromjson("{a: [{b: 0},{b: 1},{b: 2.0}]}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a.2.b"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.2.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"]["2"]["b"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathTaken("a.2.b"); + addIndexedPath("a.2.b"); + auto result = node.apply(getApplyParams(doc.root()["a"]["2"]["b"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: [{b: 0},{b: 1},{b: NumberInt(2)}]}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyNonViablePath) { +TEST_F(SetNodeTest, ApplyNonViablePath) { auto update = fromjson("{$set: {'a.2.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); Document doc(fromjson("{a: 0}")); - FieldRef pathToCreate("2.b"); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - const UpdateIndexData* indexData = nullptr; - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - ASSERT_THROWS_CODE_AND_WHAT(node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - indexData, - logBuilder, - &indexesAffected, - &noop), + setPathToCreate("2.b"); + setPathTaken("a"); + ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"])), UserException, ErrorCodes::PathNotViable, "Cannot create field '2' in element {a: 0}"); } -TEST(SetNodeTest, ApplyInPlaceArrayIndex) { +TEST_F(SetNodeTest, ApplyInPlaceArrayIndex) { auto update = fromjson("{$set: {'a.2.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); Document doc(fromjson("{a: [{b: 0},{b: 1},{b: 1}]}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a.2.b"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.2.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"]["2"]["b"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathTaken("a.2.b"); + addIndexedPath("a.2.b"); + auto result = node.apply(getApplyParams(doc.root()["a"]["2"]["b"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: [{b: 0},{b: 1},{b: 2}]}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyNormalArray) { +TEST_F(SetNodeTest, ApplyNormalArray) { auto update = fromjson("{$set: {'a.2.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); Document doc(fromjson("{a: [{b: 0},{b: 1}]}")); - FieldRef pathToCreate("2.b"); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.2.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathToCreate("2.b"); + setPathTaken("a"); + addIndexedPath("a.2.b"); + auto result = node.apply(getApplyParams(doc.root()["a"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: [{b: 0},{b: 1},{b: 2}]}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyPaddingArray) { +TEST_F(SetNodeTest, ApplyPaddingArray) { auto update = fromjson("{$set: {'a.2.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); Document doc(fromjson("{a: [{b: 0}]}")); - FieldRef pathToCreate("2.b"); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.2.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathToCreate("2.b"); + setPathTaken("a"); + addIndexedPath("a.2.b"); + auto result = node.apply(getApplyParams(doc.root()["a"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: [{b: 0},null,{b: 2}]}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyNumericObject) { +TEST_F(SetNodeTest, ApplyNumericObject) { auto update = fromjson("{$set: {'a.2.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); Document doc(fromjson("{a: {b: 0}}")); - FieldRef pathToCreate("2.b"); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.2.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathToCreate("2.b"); + setPathTaken("a"); + addIndexedPath("a.2.b"); + auto result = node.apply(getApplyParams(doc.root()["a"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: {b: 0, '2': {b: 2}}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyNumericField) { +TEST_F(SetNodeTest, ApplyNumericField) { auto update = fromjson("{$set: {'a.2.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); Document doc(fromjson("{a: {'2': {b: 1}}}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a.2.b"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.2.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"]["2"]["b"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathTaken("a.2.b"); + addIndexedPath("a.2.b"); + auto result = node.apply(getApplyParams(doc.root()["a"]["2"]["b"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: {'2': {b: 2}}}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyExtendNumericField) { +TEST_F(SetNodeTest, ApplyExtendNumericField) { auto update = fromjson("{$set: {'a.2.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); Document doc(fromjson("{a: {'2': {c: 1}}}")); - FieldRef pathToCreate("b"); - FieldRef pathTaken("a.2"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.2.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"]["2"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathToCreate("b"); + setPathTaken("a.2"); + addIndexedPath("a.2.b"); + auto result = node.apply(getApplyParams(doc.root()["a"]["2"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: {'2': {c: 1, b: 2}}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyEmptyObject) { +TEST_F(SetNodeTest, ApplyEmptyObject) { auto update = fromjson("{$set: {'a.2.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); Document doc(fromjson("{a: {}}")); - FieldRef pathToCreate("2.b"); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.2.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathToCreate("2.b"); + setPathTaken("a"); + addIndexedPath("a.2.b"); + auto result = node.apply(getApplyParams(doc.root()["a"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: {'2': {b: 2}}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyEmptyArray) { +TEST_F(SetNodeTest, ApplyEmptyArray) { auto update = fromjson("{$set: {'a.2.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); Document doc(fromjson("{a: []}")); - FieldRef pathToCreate("2.b"); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.2.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathToCreate("2.b"); + setPathTaken("a"); + addIndexedPath("a.2.b"); + auto result = node.apply(getApplyParams(doc.root()["a"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: [null, null, {b: 2}]}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyLogDottedPath) { +TEST_F(SetNodeTest, ApplyLogDottedPath) { auto update = fromjson("{$set: {'a.2.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); Document doc(fromjson("{a: [{b:0}, {b:1}]}")); - FieldRef pathToCreate("2.b"); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - const UpdateIndexData* indexData = nullptr; - Document logDoc; - LogBuilder logBuilder(logDoc.root()); - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - indexData, - &logBuilder, - &indexesAffected, - &noop); + setPathToCreate("2.b"); + setPathTaken("a"); + node.apply(getApplyParams(doc.root()["a"])); ASSERT_EQUALS(fromjson("{a: [{b:0}, {b:1}, {b:2}]}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); - ASSERT_EQUALS(countChildren(logDoc.root()), 1u); - ASSERT_EQUALS(fromjson("{$set: {'a.2.b': 2}}"), logDoc); + ASSERT_EQUALS(countChildren(getLogDoc().root()), 1u); + ASSERT_EQUALS(fromjson("{$set: {'a.2.b': 2}}"), getLogDoc()); } -TEST(SetNodeTest, LogEmptyArray) { +TEST_F(SetNodeTest, LogEmptyArray) { auto update = fromjson("{$set: {'a.2.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); Document doc(fromjson("{a: []}")); - FieldRef pathToCreate("2.b"); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - const UpdateIndexData* indexData = nullptr; - Document logDoc; - LogBuilder logBuilder(logDoc.root()); - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - indexData, - &logBuilder, - &indexesAffected, - &noop); + setPathToCreate("2.b"); + setPathTaken("a"); + node.apply(getApplyParams(doc.root()["a"])); ASSERT_EQUALS(fromjson("{a: [null, null, {b:2}]}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); - ASSERT_EQUALS(countChildren(logDoc.root()), 1u); - ASSERT_EQUALS(fromjson("{$set: {'a.2.b': 2}}"), logDoc); + ASSERT_EQUALS(countChildren(getLogDoc().root()), 1u); + ASSERT_EQUALS(fromjson("{$set: {'a.2.b': 2}}"), getLogDoc()); } -TEST(SetNodeTest, LogEmptyObject) { +TEST_F(SetNodeTest, LogEmptyObject) { auto update = fromjson("{$set: {'a.2.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); Document doc(fromjson("{a: {}}")); - FieldRef pathToCreate("2.b"); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - const UpdateIndexData* indexData = nullptr; - Document logDoc; - LogBuilder logBuilder(logDoc.root()); - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - indexData, - &logBuilder, - &indexesAffected, - &noop); + setPathToCreate("2.b"); + setPathTaken("a"); + node.apply(getApplyParams(doc.root()["a"])); ASSERT_EQUALS(fromjson("{a: {'2': {b: 2}}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); - ASSERT_EQUALS(countChildren(logDoc.root()), 1u); - ASSERT_EQUALS(fromjson("{$set: {'a.2.b': 2}}"), logDoc); + ASSERT_EQUALS(countChildren(getLogDoc().root()), 1u); + ASSERT_EQUALS(fromjson("{$set: {'a.2.b': 2}}"), getLogDoc()); } -TEST(SetNodeTest, ApplyNoOpComplex) { +TEST_F(SetNodeTest, ApplyNoOpComplex) { auto update = fromjson("{$set: {'a.1.b': {c: 1, d: 1}}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.1.b"], collator)); Document doc(fromjson("{a: [{b: {c: 0, d: 0}}, {b: {c: 1, d: 1}}]}}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a.1.b"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.1.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"]["1"]["b"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_TRUE(noop); - ASSERT_FALSE(indexesAffected); + setPathTaken("a.1.b"); + addIndexedPath("a.1.b"); + auto result = node.apply(getApplyParams(doc.root()["a"]["1"]["b"])); + ASSERT_TRUE(result.noop); + ASSERT_FALSE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: [{b: {c: 0, d: 0}}, {b: {c: 1, d: 1}}]}}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplySameStructure) { +TEST_F(SetNodeTest, ApplySameStructure) { auto update = fromjson("{$set: {'a.1.b': {c: 1, d: 1}}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.1.b"], collator)); Document doc(fromjson("{a: [{b: {c: 0, d: 0}}, {b: {c: 1, xxx: 1}}]}}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a.1.b"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.1.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"]["1"]["b"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathTaken("a.1.b"); + addIndexedPath("a.1.b"); + auto result = node.apply(getApplyParams(doc.root()["a"]["1"]["b"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: [{b: {c: 0, d: 0}}, {b: {c: 1, d: 1}}]}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, NonViablePathWithoutRepl) { +TEST_F(SetNodeTest, NonViablePathWithoutRepl) { auto update = fromjson("{$set: {'a.1.b': 1}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.1.b"], collator)); Document doc(fromjson("{a: 1}")); - FieldRef pathToCreate("1.b"); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - const UpdateIndexData* indexData = nullptr; - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - ASSERT_THROWS_CODE_AND_WHAT(node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - indexData, - logBuilder, - &indexesAffected, - &noop), + setPathToCreate("1.b"); + setPathTaken("a"); + ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"])), UserException, ErrorCodes::PathNotViable, "Cannot create field '1' in element {a: 1}"); } -TEST(SetNodeTest, SingleFieldFromReplication) { +TEST_F(SetNodeTest, SingleFieldFromReplication) { auto update = fromjson("{$set: {'a.1.b': 1}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.1.b"], collator)); Document doc(fromjson("{_id:1, a: 1}")); - FieldRef pathToCreate("1.b"); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = true; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.1.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_TRUE(noop); - ASSERT_FALSE(indexesAffected); + setPathToCreate("1.b"); + setPathTaken("a"); + addIndexedPath("a.1.b"); + setFromReplication(true); + auto result = node.apply(getApplyParams(doc.root()["a"])); + ASSERT_TRUE(result.noop); + ASSERT_FALSE(result.indexesAffected); ASSERT_EQUALS(fromjson("{_id:1, a: 1}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, SingleFieldNoIdFromReplication) { +TEST_F(SetNodeTest, SingleFieldNoIdFromReplication) { auto update = fromjson("{$set: {'a.1.b': 1}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.1.b"], collator)); Document doc(fromjson("{a: 1}")); - FieldRef pathToCreate("1.b"); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = true; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.1.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_TRUE(noop); - ASSERT_FALSE(indexesAffected); + setPathToCreate("1.b"); + setPathTaken("a"); + addIndexedPath("a.1.b"); + setFromReplication(true); + auto result = node.apply(getApplyParams(doc.root()["a"])); + ASSERT_TRUE(result.noop); + ASSERT_FALSE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: 1}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, NestedFieldFromReplication) { +TEST_F(SetNodeTest, NestedFieldFromReplication) { auto update = fromjson("{$set: {'a.a.1.b': 1}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.a.1.b"], collator)); Document doc(fromjson("{_id:1, a: {a: 1}}")); - FieldRef pathToCreate("1.b"); - FieldRef pathTaken("a.a"); - StringData matchedField; - auto fromReplication = true; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.a.1.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"]["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_TRUE(noop); - ASSERT_FALSE(indexesAffected); + setPathToCreate("1.b"); + setPathTaken("a.a"); + addIndexedPath("a.a.1.b"); + setFromReplication(true); + auto result = node.apply(getApplyParams(doc.root()["a"]["a"])); + ASSERT_TRUE(result.noop); + ASSERT_FALSE(result.indexesAffected); ASSERT_EQUALS(fromjson("{_id:1, a: {a: 1}}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, DoubleNestedFieldFromReplication) { +TEST_F(SetNodeTest, DoubleNestedFieldFromReplication) { auto update = fromjson("{$set: {'a.b.c.d': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.b.c.d"], collator)); Document doc(fromjson("{_id:1, a: {b: {c: 1}}}")); - FieldRef pathToCreate("d"); - FieldRef pathTaken("a.b.c"); - StringData matchedField; - auto fromReplication = true; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.b.c.d"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"]["b"]["c"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_TRUE(noop); - ASSERT_FALSE(indexesAffected); + setPathToCreate("d"); + setPathTaken("a.b.c"); + addIndexedPath("a.b.c.d"); + setFromReplication(true); + auto result = node.apply(getApplyParams(doc.root()["a"]["b"]["c"])); + ASSERT_TRUE(result.noop); + ASSERT_FALSE(result.indexesAffected); ASSERT_EQUALS(fromjson("{_id:1, a: {b: {c: 1}}}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, NestedFieldNoIdFromReplication) { +TEST_F(SetNodeTest, NestedFieldNoIdFromReplication) { auto update = fromjson("{$set: {'a.a.1.b': 1}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.a.1.b"], collator)); Document doc(fromjson("{a: {a: 1}}")); - FieldRef pathToCreate("1.b"); - FieldRef pathTaken("a.a"); - StringData matchedField; - auto fromReplication = true; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.a.1.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"]["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_TRUE(noop); - ASSERT_FALSE(indexesAffected); + setPathToCreate("1.b"); + setPathTaken("a.a"); + addIndexedPath("a.a.1.b"); + setFromReplication(true); + auto result = node.apply(getApplyParams(doc.root()["a"]["a"])); + ASSERT_TRUE(result.noop); + ASSERT_FALSE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: {a: 1}}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ReplayArrayFieldNotAppendedIntermediateFromReplication) { +TEST_F(SetNodeTest, ReplayArrayFieldNotAppendedIntermediateFromReplication) { auto update = fromjson("{$set: {'a.0.b': [0,2]}}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.0.b"], collator)); Document doc(fromjson("{_id: 0, a: [1, {b: [1]}]}")); - FieldRef pathToCreate("b"); - FieldRef pathTaken("a.0"); - StringData matchedField; - auto fromReplication = true; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("a.0.b"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"]["0"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_TRUE(noop); - ASSERT_FALSE(indexesAffected); + setPathToCreate("b"); + setPathTaken("a.0"); + addIndexedPath("a.1.b"); + setFromReplication(true); + auto result = node.apply(getApplyParams(doc.root()["a"]["0"])); + ASSERT_TRUE(result.noop); + ASSERT_FALSE(result.indexesAffected); ASSERT_EQUALS(fromjson("{_id: 0, a: [1, {b: [1]}]}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, Set6) { +TEST_F(SetNodeTest, Set6) { auto update = fromjson("{$set: {'r.a': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["r.a"], collator)); Document doc(fromjson("{_id: 1, r: {a:1, b:2}}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("r.a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("r.a"); - Document logDoc; - LogBuilder logBuilder(logDoc.root()); - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["r"]["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - &logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathTaken("r.a"); + addIndexedPath("r.a"); + auto result = node.apply(getApplyParams(doc.root()["r"]["a"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{_id: 1, r: {a:2, b:2}}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); - ASSERT_EQUALS(countChildren(logDoc.root()), 1u); - ASSERT_EQUALS(fromjson("{$set: {'r.a': 2}}"), logDoc); + ASSERT_EQUALS(countChildren(getLogDoc().root()), 1u); + ASSERT_EQUALS(fromjson("{$set: {'r.a': 2}}"), getLogDoc()); } -TEST(SetNodeTest, Set6FromRepl) { +TEST_F(SetNodeTest, Set6FromRepl) { auto update = fromjson("{$set: { 'r.a': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["r.a"], collator)); Document doc(fromjson("{_id: 1, r: {a:1, b:2}}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("r.a"); - StringData matchedField; - auto fromReplication = true; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("r.a"); - Document logDoc; - LogBuilder logBuilder(logDoc.root()); - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["r"]["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - &logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathTaken("r.a"); + addIndexedPath("r.a"); + setFromReplication(true); + auto result = node.apply(getApplyParams(doc.root()["r"]["a"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{_id: 1, r: {a:2, b:2} }"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); - ASSERT_EQUALS(countChildren(logDoc.root()), 1u); - ASSERT_EQUALS(fromjson("{$set: {'r.a': 2}}"), logDoc); + ASSERT_EQUALS(countChildren(getLogDoc().root()), 1u); + ASSERT_EQUALS(fromjson("{$set: {'r.a': 2}}"), getLogDoc()); } -TEST(SetNodeTest, ApplySetModToEphemeralDocument) { +TEST_F(SetNodeTest, ApplySetModToEphemeralDocument) { // The following mod when applied to a document constructed node by node exposed a // latent debug only defect in mutable BSON, so this is more a test of mutable than // $set. @@ -1940,702 +955,325 @@ TEST(SetNodeTest, ApplySetModToEphemeralDocument) { Element a = doc.makeElementInt("a", 100); x.pushBack(a).transitional_ignore(); - FieldRef pathToCreate(""); - FieldRef pathTaken("x"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("x"); - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["x"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathTaken("x"); + addIndexedPath("x"); + auto result = node.apply(getApplyParams(doc.root()["x"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{ x : { a : 100, b : 2 } }"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); } -TEST(SetNodeTest, ApplyCannotCreateDollarPrefixedFieldInsideSetElement) { +TEST_F(SetNodeTest, ApplyCannotCreateDollarPrefixedFieldInsideSetElement) { auto update = fromjson("{$set: {a: {$bad: 1}}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); Document doc(fromjson("{a: 5}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - const UpdateIndexData* indexData = nullptr; - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; + setPathTaken("a"); ASSERT_THROWS_CODE_AND_WHAT( - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - indexData, - logBuilder, - &indexesAffected, - &noop), + node.apply(getApplyParams(doc.root()["a"])), UserException, ErrorCodes::DollarPrefixedFieldName, "The dollar ($) prefixed field '$bad' in 'a.$bad' is not valid for storage."); } -TEST(SetNodeTest, ApplyCannotCreateDollarPrefixedFieldAtStartOfPath) { +TEST_F(SetNodeTest, ApplyCannotCreateDollarPrefixedFieldAtStartOfPath) { auto update = fromjson("{$set: {'$bad.a': 1}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["$bad.a"], collator)); Document doc(fromjson("{}")); - FieldRef pathToCreate("$bad.a"); - FieldRef pathTaken(""); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - const UpdateIndexData* indexData = nullptr; - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; + setPathToCreate("$bad.a"); ASSERT_THROWS_CODE_AND_WHAT( - node.apply(doc.root(), - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - indexData, - logBuilder, - &indexesAffected, - &noop), + node.apply(getApplyParams(doc.root())), UserException, ErrorCodes::DollarPrefixedFieldName, "The dollar ($) prefixed field '$bad' in '$bad' is not valid for storage."); } -TEST(SetNodeTest, ApplyCannotCreateDollarPrefixedFieldInMiddleOfPath) { +TEST_F(SetNodeTest, ApplyCannotCreateDollarPrefixedFieldInMiddleOfPath) { auto update = fromjson("{$set: {'a.$bad.b': 1}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.$bad.b"], collator)); Document doc(fromjson("{}")); - FieldRef pathToCreate("a.$bad.b"); - FieldRef pathTaken(""); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - const UpdateIndexData* indexData = nullptr; - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; + setPathToCreate("a.$bad.b"); ASSERT_THROWS_CODE_AND_WHAT( - node.apply(doc.root(), - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - indexData, - logBuilder, - &indexesAffected, - &noop), + node.apply(getApplyParams(doc.root())), UserException, ErrorCodes::DollarPrefixedFieldName, "The dollar ($) prefixed field '$bad' in 'a.$bad' is not valid for storage."); } -TEST(SetNodeTest, ApplyCannotCreateDollarPrefixedFieldAtEndOfPath) { +TEST_F(SetNodeTest, ApplyCannotCreateDollarPrefixedFieldAtEndOfPath) { auto update = fromjson("{$set: {'a.$bad': 1}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.$bad"], collator)); Document doc(fromjson("{}")); - FieldRef pathToCreate("a.$bad"); - FieldRef pathTaken(""); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - const UpdateIndexData* indexData = nullptr; - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; + setPathToCreate("a.$bad"); ASSERT_THROWS_CODE_AND_WHAT( - node.apply(doc.root(), - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - indexData, - logBuilder, - &indexesAffected, - &noop), + node.apply(getApplyParams(doc.root())), UserException, ErrorCodes::DollarPrefixedFieldName, "The dollar ($) prefixed field '$bad' in 'a.$bad' is not valid for storage."); } -TEST(SetNodeTest, ApplyCanCreateDollarPrefixedFieldNameWhenValidateForStorageIsFalse) { +TEST_F(SetNodeTest, ApplyCanCreateDollarPrefixedFieldNameWhenValidateForStorageIsFalse) { auto update = fromjson("{$set: {$bad: 1}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["$bad"], collator)); Document doc(fromjson("{}")); - FieldRef pathToCreate("$bad"); - FieldRef pathTaken(""); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = false; - FieldRefSet immutablePaths; - UpdateIndexData indexData; - indexData.addPath("$bad"); - Document logDoc; - LogBuilder logBuilder(logDoc.root()); - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root(), - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - &logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathToCreate("$bad"); + addIndexedPath("$bad"); + setValidateForStorage(false); + auto result = node.apply(getApplyParams(doc.root())); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{$bad: 1}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); - ASSERT_EQUALS(countChildren(logDoc.root()), 1u); - ASSERT_EQUALS(fromjson("{$set: {$bad: 1}}"), logDoc); + ASSERT_EQUALS(countChildren(getLogDoc().root()), 1u); + ASSERT_EQUALS(fromjson("{$set: {$bad: 1}}"), getLogDoc()); } -TEST(SetNodeTest, ApplyCannotOverwriteImmutablePath) { +TEST_F(SetNodeTest, ApplyCannotOverwriteImmutablePath) { auto update = fromjson("{$set: {'a.b': 1}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); Document doc(fromjson("{a: {b: 2}}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a.b"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - FieldRef path("a.b"); - immutablePaths.insert(&path); - const UpdateIndexData* indexData = nullptr; - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; + setPathTaken("a.b"); + addImmutablePath("a.b"); ASSERT_THROWS_CODE_AND_WHAT( - node.apply(doc.root()["a"]["b"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - indexData, - logBuilder, - &indexesAffected, - &noop), + node.apply(getApplyParams(doc.root()["a"]["b"])), UserException, ErrorCodes::ImmutableField, "Updating the path 'a.b' to b: 1 would modify the immutable field 'a.b'"); } -TEST(SetNodeTest, ApplyCanPerformNoopOnImmutablePath) { +TEST_F(SetNodeTest, ApplyCanPerformNoopOnImmutablePath) { auto update = fromjson("{$set: {'a.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); Document doc(fromjson("{a: {b: 2}}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a.b"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - FieldRef path("a.b"); - immutablePaths.insert(&path); - UpdateIndexData indexData; - indexData.addPath("a"); - Document logDoc; - LogBuilder logBuilder(logDoc.root()); - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"]["b"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - &logBuilder, - &indexesAffected, - &noop); - ASSERT_TRUE(noop); - ASSERT_FALSE(indexesAffected); + setPathTaken("a.b"); + addImmutablePath("a.b"); + addIndexedPath("a"); + auto result = node.apply(getApplyParams(doc.root()["a"]["b"])); + ASSERT_TRUE(result.noop); + ASSERT_FALSE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: {b: 2}}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); - ASSERT_EQUALS(countChildren(logDoc.root()), 0u); - ASSERT_EQUALS(fromjson("{}"), logDoc); + ASSERT_EQUALS(countChildren(getLogDoc().root()), 0u); + ASSERT_EQUALS(fromjson("{}"), getLogDoc()); } -TEST(SetNodeTest, ApplyCannotOverwritePrefixToRemoveImmutablePath) { +TEST_F(SetNodeTest, ApplyCannotOverwritePrefixToRemoveImmutablePath) { auto update = fromjson("{$set: {a: 1}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); Document doc(fromjson("{a: {b: 2}}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - FieldRef path("a.b"); - immutablePaths.insert(&path); - const UpdateIndexData* indexData = nullptr; - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; + setPathTaken("a"); + addImmutablePath("a.b"); ASSERT_THROWS_CODE_AND_WHAT( - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - indexData, - logBuilder, - &indexesAffected, - &noop), + node.apply(getApplyParams(doc.root()["a"])), UserException, ErrorCodes::ImmutableField, "After applying the update, the immutable field 'a.b' was found to have been removed."); } -TEST(SetNodeTest, ApplyCannotOverwritePrefixToModifyImmutablePath) { +TEST_F(SetNodeTest, ApplyCannotOverwritePrefixToModifyImmutablePath) { auto update = fromjson("{$set: {a: {b: 1}}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); Document doc(fromjson("{a: {b: 2}}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - FieldRef path("a.b"); - immutablePaths.insert(&path); - const UpdateIndexData* indexData = nullptr; - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; - ASSERT_THROWS_CODE_AND_WHAT(node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - indexData, - logBuilder, - &indexesAffected, - &noop), + setPathTaken("a"); + addImmutablePath("a.b"); + ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"])), UserException, ErrorCodes::ImmutableField, "After applying the update, the immutable field 'a.b' was found to " "have been altered to b: 1"); } -TEST(SetNodeTest, ApplyCanPerformNoopOnPrefixOfImmutablePath) { +TEST_F(SetNodeTest, ApplyCanPerformNoopOnPrefixOfImmutablePath) { auto update = fromjson("{$set: {a: {b: 2}}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); Document doc(fromjson("{a: {b: 2}}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - FieldRef path("a.b"); - immutablePaths.insert(&path); - UpdateIndexData indexData; - indexData.addPath("a"); - Document logDoc; - LogBuilder logBuilder(logDoc.root()); - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - &logBuilder, - &indexesAffected, - &noop); - ASSERT_TRUE(noop); - ASSERT_FALSE(indexesAffected); + setPathTaken("a"); + addImmutablePath("a.b"); + addIndexedPath("a"); + auto result = node.apply(getApplyParams(doc.root()["a"])); + ASSERT_TRUE(result.noop); + ASSERT_FALSE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: {b: 2}}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); - ASSERT_EQUALS(countChildren(logDoc.root()), 0u); - ASSERT_EQUALS(fromjson("{}"), logDoc); + ASSERT_EQUALS(countChildren(getLogDoc().root()), 0u); + ASSERT_EQUALS(fromjson("{}"), getLogDoc()); } -TEST(SetNodeTest, ApplyCanOverwritePrefixToCreateImmutablePath) { +TEST_F(SetNodeTest, ApplyCanOverwritePrefixToCreateImmutablePath) { auto update = fromjson("{$set: {a: {b: 2}}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); Document doc(fromjson("{a: 1}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - FieldRef path("a.b"); - immutablePaths.insert(&path); - UpdateIndexData indexData; - indexData.addPath("a"); - Document logDoc; - LogBuilder logBuilder(logDoc.root()); - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - &logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathTaken("a"); + addImmutablePath("a.b"); + addIndexedPath("a"); + auto result = node.apply(getApplyParams(doc.root()["a"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: {b: 2}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); - ASSERT_EQUALS(countChildren(logDoc.root()), 1u); - ASSERT_EQUALS(fromjson("{$set: {a: {b: 2}}}"), logDoc); + ASSERT_EQUALS(countChildren(getLogDoc().root()), 1u); + ASSERT_EQUALS(fromjson("{$set: {a: {b: 2}}}"), getLogDoc()); } -TEST(SetNodeTest, ApplyCanOverwritePrefixOfImmutablePathIfNoopOnImmutablePath) { +TEST_F(SetNodeTest, ApplyCanOverwritePrefixOfImmutablePathIfNoopOnImmutablePath) { auto update = fromjson("{$set: {a: {b: 2, c: 3}}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); Document doc(fromjson("{a: {b: 2}}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - FieldRef path("a.b"); - immutablePaths.insert(&path); - UpdateIndexData indexData; - indexData.addPath("a"); - Document logDoc; - LogBuilder logBuilder(logDoc.root()); - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - &logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathTaken("a"); + addImmutablePath("a.b"); + addIndexedPath("a"); + auto result = node.apply(getApplyParams(doc.root()["a"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: {b: 2, c: 3}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); - ASSERT_EQUALS(countChildren(logDoc.root()), 1u); - ASSERT_EQUALS(fromjson("{$set: {a: {b: 2, c: 3}}}"), logDoc); + ASSERT_EQUALS(countChildren(getLogDoc().root()), 1u); + ASSERT_EQUALS(fromjson("{$set: {a: {b: 2, c: 3}}}"), getLogDoc()); } -TEST(SetNodeTest, ApplyCannotOverwriteSuffixOfImmutablePath) { +TEST_F(SetNodeTest, ApplyCannotOverwriteSuffixOfImmutablePath) { auto update = fromjson("{$set: {'a.b.c': 1}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.b.c"], collator)); Document doc(fromjson("{a: {b: {c: 2}}}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a.b.c"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - FieldRef path("a.b"); - immutablePaths.insert(&path); - const UpdateIndexData* indexData = nullptr; - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; + setPathTaken("a.b.c"); + addImmutablePath("a.b"); ASSERT_THROWS_CODE_AND_WHAT( - node.apply(doc.root()["a"]["b"]["c"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - indexData, - logBuilder, - &indexesAffected, - &noop), + node.apply(getApplyParams(doc.root()["a"]["b"]["c"])), UserException, ErrorCodes::ImmutableField, "Updating the path 'a.b.c' to c: 1 would modify the immutable field 'a.b'"); } -TEST(SetNodeTest, ApplyCanPerformNoopOnSuffixOfImmutablePath) { +TEST_F(SetNodeTest, ApplyCanPerformNoopOnSuffixOfImmutablePath) { auto update = fromjson("{$set: {'a.b.c': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.b.c"], collator)); Document doc(fromjson("{a: {b: {c: 2}}}")); - FieldRef pathToCreate(""); - FieldRef pathTaken("a.b.c"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - FieldRef path("a.b"); - immutablePaths.insert(&path); - UpdateIndexData indexData; - indexData.addPath("a"); - Document logDoc; - LogBuilder logBuilder(logDoc.root()); - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"]["b"]["c"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - &logBuilder, - &indexesAffected, - &noop); - ASSERT_TRUE(noop); - ASSERT_FALSE(indexesAffected); + setPathTaken("a.b.c"); + addImmutablePath("a.b"); + addIndexedPath("a"); + auto result = node.apply(getApplyParams(doc.root()["a"]["b"]["c"])); + ASSERT_TRUE(result.noop); + ASSERT_FALSE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: {b: {c: 2}}}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); - ASSERT_EQUALS(countChildren(logDoc.root()), 0u); - ASSERT_EQUALS(fromjson("{}"), logDoc); + ASSERT_EQUALS(countChildren(getLogDoc().root()), 0u); + ASSERT_EQUALS(fromjson("{}"), getLogDoc()); } -TEST(SetNodeTest, ApplyCannotCreateFieldAtEndOfImmutablePath) { +TEST_F(SetNodeTest, ApplyCannotCreateFieldAtEndOfImmutablePath) { auto update = fromjson("{$set: {'a.b.c': 1}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.b.c"], collator)); Document doc(fromjson("{a: {b: {}}}")); - FieldRef pathToCreate("c"); - FieldRef pathTaken("a.b"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - FieldRef path("a.b"); - immutablePaths.insert(&path); - const UpdateIndexData* indexData = nullptr; - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; + setPathToCreate("c"); + setPathTaken("a.b"); + addImmutablePath("a.b"); ASSERT_THROWS_CODE_AND_WHAT( - node.apply(doc.root()["a"]["b"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - indexData, - logBuilder, - &indexesAffected, - &noop), + node.apply(getApplyParams(doc.root()["a"]["b"])), UserException, ErrorCodes::ImmutableField, "Updating the path 'a.b' to b: { c: 1 } would modify the immutable field 'a.b'"); } -TEST(SetNodeTest, ApplyCannotCreateFieldBeyondEndOfImmutablePath) { +TEST_F(SetNodeTest, ApplyCannotCreateFieldBeyondEndOfImmutablePath) { auto update = fromjson("{$set: {'a.b.c': 1}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.b.c"], collator)); Document doc(fromjson("{a: {b: {}}}")); - FieldRef pathToCreate("c"); - FieldRef pathTaken("a.b"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - FieldRef path("a"); - immutablePaths.insert(&path); - const UpdateIndexData* indexData = nullptr; - LogBuilder* logBuilder = nullptr; - auto indexesAffected = false; - auto noop = false; + setPathToCreate("c"); + setPathTaken("a.b"); + addImmutablePath("a"); ASSERT_THROWS_CODE_AND_WHAT( - node.apply(doc.root()["a"]["b"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - indexData, - logBuilder, - &indexesAffected, - &noop), + node.apply(getApplyParams(doc.root()["a"]["b"])), UserException, ErrorCodes::ImmutableField, "Updating the path 'a.b' to b: { c: 1 } would modify the immutable field 'a'"); } -TEST(SetNodeTest, ApplyCanCreateImmutablePath) { +TEST_F(SetNodeTest, ApplyCanCreateImmutablePath) { auto update = fromjson("{$set: {'a.b': 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); Document doc(fromjson("{a: {}}")); - FieldRef pathToCreate("b"); - FieldRef pathTaken("a"); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - FieldRef path("a.b"); - immutablePaths.insert(&path); - UpdateIndexData indexData; - indexData.addPath("a"); - Document logDoc; - LogBuilder logBuilder(logDoc.root()); - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root()["a"], - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - &logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathToCreate("b"); + setPathTaken("a"); + addImmutablePath("a.b"); + addIndexedPath("a"); + auto result = node.apply(getApplyParams(doc.root()["a"])); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: {b: 2}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); - ASSERT_EQUALS(countChildren(logDoc.root()), 1u); - ASSERT_EQUALS(fromjson("{$set: {'a.b': 2}}"), logDoc); + ASSERT_EQUALS(countChildren(getLogDoc().root()), 1u); + ASSERT_EQUALS(fromjson("{$set: {'a.b': 2}}"), getLogDoc()); } -TEST(SetNodeTest, ApplyCanCreatePrefixOfImmutablePath) { +TEST_F(SetNodeTest, ApplyCanCreatePrefixOfImmutablePath) { auto update = fromjson("{$set: {a: 2}}"); const CollatorInterface* collator = nullptr; SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); Document doc(fromjson("{}")); - FieldRef pathToCreate("a"); - FieldRef pathTaken(""); - StringData matchedField; - auto fromReplication = false; - auto validateForStorage = true; - FieldRefSet immutablePaths; - FieldRef path("a.b"); - immutablePaths.insert(&path); - UpdateIndexData indexData; - indexData.addPath("a"); - Document logDoc; - LogBuilder logBuilder(logDoc.root()); - auto indexesAffected = false; - auto noop = false; - node.apply(doc.root(), - &pathToCreate, - &pathTaken, - matchedField, - fromReplication, - validateForStorage, - immutablePaths, - &indexData, - &logBuilder, - &indexesAffected, - &noop); - ASSERT_FALSE(noop); - ASSERT_TRUE(indexesAffected); + setPathToCreate("a"); + addImmutablePath("a.b"); + addIndexedPath("a"); + auto result = node.apply(getApplyParams(doc.root())); + ASSERT_FALSE(result.noop); + ASSERT_TRUE(result.indexesAffected); ASSERT_EQUALS(fromjson("{a: 2}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); - ASSERT_EQUALS(countChildren(logDoc.root()), 1u); - ASSERT_EQUALS(fromjson("{$set: {a: 2}}"), logDoc); + ASSERT_EQUALS(countChildren(getLogDoc().root()), 1u); + ASSERT_EQUALS(fromjson("{$set: {a: 2}}"), getLogDoc()); } } // namespace +} // namespace mongo |