summaryrefslogtreecommitdiff
path: root/src/mongo/db/update
diff options
context:
space:
mode:
authorIan Boros <ian.boros@mongodb.com>2020-08-13 14:08:58 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-08-27 03:08:04 +0000
commit3a32dd0a25105ba547712190ff503a46e91f392e (patch)
tree3bf333229d495a35ffde62aa0ace0e312a720352 /src/mongo/db/update
parent6791200c0513187dc193895af70cc170db9afc78 (diff)
downloadmongo-3a32dd0a25105ba547712190ff503a46e91f392e.tar.gz
SERVER-50217 change auth op observer to handle $v:1 and $v:2 updates
This commit also removes an implicit constructor for write_ops::UpdateModification.
Diffstat (limited to 'src/mongo/db/update')
-rw-r--r--src/mongo/db/update/update_driver_test.cpp86
-rw-r--r--src/mongo/db/update/update_serialization_test.cpp2
2 files changed, 55 insertions, 33 deletions
diff --git a/src/mongo/db/update/update_driver_test.cpp b/src/mongo/db/update/update_driver_test.cpp
index f490fec9a24..f93d5343661 100644
--- a/src/mongo/db/update/update_driver_test.cpp
+++ b/src/mongo/db/update/update_driver_test.cpp
@@ -62,11 +62,15 @@ namespace {
using str::stream;
using unittest::assertGet;
+write_ops::UpdateModification makeUpdateMod(const BSONObj& bson) {
+ return write_ops::UpdateModification::parseFromClassicUpdate(bson);
+}
+
TEST(Parse, Normal) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UpdateDriver driver(expCtx);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- ASSERT_DOES_NOT_THROW(driver.parse(fromjson("{$set:{a:1}}"), arrayFilters));
+ ASSERT_DOES_NOT_THROW(driver.parse(makeUpdateMod(fromjson("{$set:{a:1}}")), arrayFilters));
ASSERT_FALSE(driver.type() == UpdateDriver::UpdateType::kReplacement);
}
@@ -74,7 +78,7 @@ TEST(Parse, MultiMods) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UpdateDriver driver(expCtx);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- ASSERT_DOES_NOT_THROW(driver.parse(fromjson("{$set:{a:1, b:1}}"), arrayFilters));
+ ASSERT_DOES_NOT_THROW(driver.parse(makeUpdateMod(fromjson("{$set:{a:1, b:1}}")), arrayFilters));
ASSERT_FALSE(driver.type() == UpdateDriver::UpdateType::kReplacement);
}
@@ -82,7 +86,8 @@ TEST(Parse, MixingMods) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UpdateDriver driver(expCtx);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- ASSERT_DOES_NOT_THROW(driver.parse(fromjson("{$set:{a:1}, $unset:{b:1}}"), arrayFilters));
+ ASSERT_DOES_NOT_THROW(
+ driver.parse(makeUpdateMod(fromjson("{$set:{a:1}, $unset:{b:1}}")), arrayFilters));
ASSERT_FALSE(driver.type() == UpdateDriver::UpdateType::kReplacement);
}
@@ -90,7 +95,8 @@ TEST(Parse, ObjectReplacment) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UpdateDriver driver(expCtx);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- ASSERT_DOES_NOT_THROW(driver.parse(fromjson("{obj: \"obj replacement\"}"), arrayFilters));
+ ASSERT_DOES_NOT_THROW(
+ driver.parse(makeUpdateMod(fromjson("{obj: \"obj replacement\"}")), arrayFilters));
ASSERT_TRUE(driver.type() == UpdateDriver::UpdateType::kReplacement);
}
@@ -122,14 +128,14 @@ TEST(Parse, EmptyMod) {
UpdateDriver driver(expCtx);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
// Verifies that {$set: {}} is accepted.
- ASSERT_DOES_NOT_THROW(driver.parse(fromjson("{$set: {}}"), arrayFilters));
+ ASSERT_DOES_NOT_THROW(driver.parse(makeUpdateMod(fromjson("{$set: {}}")), arrayFilters));
}
TEST(Parse, WrongMod) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UpdateDriver driver(expCtx);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- ASSERT_THROWS_CODE_AND_WHAT(driver.parse(fromjson("{$xyz:{a:1}}"), arrayFilters),
+ ASSERT_THROWS_CODE_AND_WHAT(driver.parse(makeUpdateMod(fromjson("{$xyz:{a:1}}")), arrayFilters),
AssertionException,
ErrorCodes::FailedToParse,
"Unknown modifier: $xyz. Expected a valid update modifier or "
@@ -140,11 +146,12 @@ TEST(Parse, WrongType) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UpdateDriver driver(expCtx);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- ASSERT_THROWS_CODE_AND_WHAT(driver.parse(fromjson("{$set:[{a:1}]}"), arrayFilters),
- AssertionException,
- ErrorCodes::FailedToParse,
- "Modifiers operate on fields but we found type array instead. For "
- "example: {$mod: {<field>: ...}} not {$set: [ { a: 1 } ]}");
+ ASSERT_THROWS_CODE_AND_WHAT(
+ driver.parse(makeUpdateMod(fromjson("{$set:[{a:1}]}")), arrayFilters),
+ AssertionException,
+ ErrorCodes::FailedToParse,
+ "Modifiers operate on fields but we found type array instead. For "
+ "example: {$mod: {<field>: ...}} not {$set: [ { a: 1 } ]}");
}
TEST(Parse, ModsWithLaterObjReplacement) {
@@ -152,7 +159,8 @@ TEST(Parse, ModsWithLaterObjReplacement) {
UpdateDriver driver(expCtx);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
ASSERT_THROWS_CODE_AND_WHAT(
- driver.parse(fromjson("{$set:{a:1}, obj: \"obj replacement\"}"), arrayFilters),
+ driver.parse(makeUpdateMod(fromjson("{$set:{a:1}, obj: \"obj replacement\"}")),
+ arrayFilters),
AssertionException,
ErrorCodes::FailedToParse,
"Unknown modifier: obj. Expected a valid update modifier or pipeline-style update "
@@ -163,7 +171,8 @@ TEST(Parse, SetOnInsert) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UpdateDriver driver(expCtx);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- ASSERT_DOES_NOT_THROW(driver.parse(fromjson("{$setOnInsert:{a:1}}"), arrayFilters));
+ ASSERT_DOES_NOT_THROW(
+ driver.parse(makeUpdateMod(fromjson("{$setOnInsert:{a:1}}")), arrayFilters));
ASSERT_FALSE(driver.type() == UpdateDriver::UpdateType::kReplacement);
}
@@ -174,7 +183,7 @@ TEST(Collator, SetCollationUpdatesModifierInterfaces) {
UpdateDriver driver(expCtx);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- ASSERT_DOES_NOT_THROW(driver.parse(updateDocument, arrayFilters));
+ ASSERT_DOES_NOT_THROW(driver.parse(makeUpdateMod(updateDocument), arrayFilters));
const bool validateForStorage = true;
const FieldRefSet emptyImmutablePaths;
@@ -209,8 +218,8 @@ public:
new ExpressionContext(_opCtx.get(), nullptr, NamespaceString("foo")))),
_driverRepl(new UpdateDriver(
new ExpressionContext(_opCtx.get(), nullptr, NamespaceString("foo")))) {
- _driverOps->parse(fromjson("{$set:{'_':1}}"), _arrayFilters);
- _driverRepl->parse(fromjson("{}"), _arrayFilters);
+ _driverOps->parse(makeUpdateMod(fromjson("{$set:{'_':1}}")), _arrayFilters);
+ _driverRepl->parse(makeUpdateMod(fromjson("{}")), _arrayFilters);
}
mutablebson::Document& doc() {
@@ -578,6 +587,7 @@ public:
ASSERT(expr->getPlaceholder());
arrayFilters[expr->getPlaceholder().get()] = std::move(expr);
}
+
_driver->setFromOplogApplication(fromOplog);
_driver->refreshIndexKeys(indexData);
_driver->parse(updateSpec, arrayFilters);
@@ -607,61 +617,61 @@ public:
TEST_F(ModifiedPathsTestFixture, SetFieldInRoot) {
BSONObj spec = fromjson("{$set: {a: 1}}");
mutablebson::Document doc(fromjson("{a: 0}"));
- runUpdate(&doc, spec);
+ runUpdate(&doc, makeUpdateMod(spec));
ASSERT_EQ(_modifiedPaths, "{a}");
}
TEST_F(ModifiedPathsTestFixture, IncFieldInRoot) {
BSONObj spec = fromjson("{$inc: {a: 1}}");
mutablebson::Document doc(fromjson("{a: 0}"));
- runUpdate(&doc, spec);
+ runUpdate(&doc, makeUpdateMod(spec));
ASSERT_EQ(_modifiedPaths, "{a}");
}
TEST_F(ModifiedPathsTestFixture, UnsetFieldInRoot) {
BSONObj spec = fromjson("{$unset: {a: ''}}");
mutablebson::Document doc(fromjson("{a: 0}"));
- runUpdate(&doc, spec);
+ runUpdate(&doc, makeUpdateMod(spec));
ASSERT_EQ(_modifiedPaths, "{a}");
}
TEST_F(ModifiedPathsTestFixture, UpdateArrayElement) {
BSONObj spec = fromjson("{$set: {'a.0.b': 1}}");
mutablebson::Document doc(fromjson("{a: [{b: 0}]}"));
- runUpdate(&doc, spec);
+ runUpdate(&doc, makeUpdateMod(spec));
ASSERT_EQ(_modifiedPaths, "{a.0.b}");
}
TEST_F(ModifiedPathsTestFixture, SetBeyondTheEndOfArrayShouldReturnPathToArray) {
BSONObj spec = fromjson("{$set: {'a.1.b': 1}}");
mutablebson::Document doc(fromjson("{a: [{b: 0}]}"));
- runUpdate(&doc, spec);
+ runUpdate(&doc, makeUpdateMod(spec));
ASSERT_EQ(_modifiedPaths, "{a}");
}
TEST_F(ModifiedPathsTestFixture, InsertingAndUpdatingArrayShouldReturnPathToArray) {
BSONObj spec = fromjson("{$set: {'a.0.b': 1, 'a.1.c': 2}}");
mutablebson::Document doc(fromjson("{a: [{b: 0}]}"));
- runUpdate(&doc, spec);
+ runUpdate(&doc, makeUpdateMod(spec));
ASSERT_EQ(_modifiedPaths, "{a}");
spec = fromjson("{$set: {'a.10.b': 1, 'a.1.c': 2}}");
mutablebson::Document doc2(fromjson("{a: [{b: 0}, {b: 0}]}"));
- runUpdate(&doc2, spec);
+ runUpdate(&doc2, makeUpdateMod(spec));
ASSERT_EQ(_modifiedPaths, "{a}");
}
TEST_F(ModifiedPathsTestFixture, UpdateWithPositionalOperator) {
BSONObj spec = fromjson("{$set: {'a.$': 1}}");
mutablebson::Document doc(fromjson("{a: [0, 1, 2]}"));
- runUpdate(&doc, spec, "0"_sd);
+ runUpdate(&doc, makeUpdateMod(spec), "0"_sd);
ASSERT_EQ(_modifiedPaths, "{a.0}");
}
TEST_F(ModifiedPathsTestFixture, UpdateWithPositionalOperatorToNestedField) {
BSONObj spec = fromjson("{$set: {'a.$.b': 1}}");
mutablebson::Document doc(fromjson("{a: [{b: 1}, {b: 2}]}"));
- runUpdate(&doc, spec, "1"_sd);
+ runUpdate(&doc, makeUpdateMod(spec), "1"_sd);
ASSERT_EQ(_modifiedPaths, "{a.1.b}");
}
@@ -669,7 +679,7 @@ TEST_F(ModifiedPathsTestFixture, ArrayFilterThatMatchesNoElements) {
BSONObj spec = fromjson("{$set: {'a.$[i]': 1}}");
BSONObj arrayFilter = fromjson("{i: 0}");
mutablebson::Document doc(fromjson("{a: [1, 2, 3]}"));
- runUpdate(&doc, spec, ""_sd, {arrayFilter});
+ runUpdate(&doc, makeUpdateMod(spec), ""_sd, {arrayFilter});
ASSERT_EQ(_modifiedPaths, "{a}");
}
@@ -677,7 +687,7 @@ TEST_F(ModifiedPathsTestFixture, ArrayFilterThatMatchesNoElements) {
TEST_F(ModifiedPathsTestFixture, ReplaceFullDocumentAlwaysAffectsIndex) {
BSONObj spec = fromjson("{a: 1, b: 1}}");
mutablebson::Document doc(fromjson("{a: 0, b: 0}"));
- runUpdate(&doc, spec);
+ runUpdate(&doc, makeUpdateMod(spec));
ASSERT_EQ(_modifiedPaths, "{}");
}
@@ -692,13 +702,21 @@ TEST_F(ModifiedPathsTestFixture, PipelineUpdatesAlwaysAffectsIndex) {
TEST_F(ModifiedPathsTestFixture, DeltaUpdateNotAffectingIndex) {
BSONObj spec = fromjson("{d: {a: false}}");
mutablebson::Document doc(fromjson("{a: [{b: 0}]}"));
- runUpdate(&doc, write_ops::UpdateModification(spec, {}), ""_sd, {}, true /* fromOplog */);
+ runUpdate(&doc,
+ write_ops::UpdateModification::parseFromV2Delta(spec),
+ ""_sd,
+ {},
+ true /* fromOplog */);
ASSERT(!_driver->modsAffectIndices());
UpdateIndexData indexData;
indexData.addPath(FieldRef("p"));
- runUpdate(
- &doc, write_ops::UpdateModification(spec, {}), ""_sd, {}, true /* fromOplog */, &indexData);
+ runUpdate(&doc,
+ write_ops::UpdateModification::parseFromV2Delta(spec),
+ ""_sd,
+ {},
+ true /* fromOplog */,
+ &indexData);
ASSERT(!_driver->modsAffectIndices());
}
@@ -708,8 +726,12 @@ TEST_F(ModifiedPathsTestFixture, DeltaUpdateAffectingIndex) {
UpdateIndexData indexData;
indexData.addPath(FieldRef("q"));
indexData.addPath(FieldRef("a.p"));
- runUpdate(
- &doc, write_ops::UpdateModification(spec, {}), ""_sd, {}, true /* fromOplog */, &indexData);
+ runUpdate(&doc,
+ write_ops::UpdateModification::parseFromV2Delta(spec),
+ ""_sd,
+ {},
+ true /* fromOplog */,
+ &indexData);
ASSERT(_driver->modsAffectIndices());
}
diff --git a/src/mongo/db/update/update_serialization_test.cpp b/src/mongo/db/update/update_serialization_test.cpp
index 734d8c19e6a..8fa262ab46a 100644
--- a/src/mongo/db/update/update_serialization_test.cpp
+++ b/src/mongo/db/update/update_serialization_test.cpp
@@ -55,7 +55,7 @@ auto updateRoundTrip(const char* json, const std::vector<std::string> filterName
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> filters;
for (const auto& name : filterNames)
filters[name] = nullptr;
- driver.parse(bson, filters);
+ driver.parse(write_ops::UpdateModification::parseFromClassicUpdate(bson), filters);
return mongo::tojson(driver.serialize().getDocument().toBson(),
mongo::JsonStringFormat::LegacyStrict);
}