diff options
author | Ted Tuckman <ted.tuckman@mongodb.com> | 2023-02-28 15:34:40 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-02-28 17:02:01 +0000 |
commit | d5e281bc80818c7398e1b96af78a53096b6611da (patch) | |
tree | 413377d4439f637cfde8c33e036b8ccf7bc86be0 /src/mongo/db/matcher | |
parent | e4f411f089d825af8aa0d77fe05657cc27e297fe (diff) | |
download | mongo-d5e281bc80818c7398e1b96af78a53096b6611da.tar.gz |
SERVER-73709 Enable redaction for expressions inside $expr
Diffstat (limited to 'src/mongo/db/matcher')
-rw-r--r-- | src/mongo/db/matcher/expression_expr.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/matcher/expression_expr_test.cpp | 113 |
2 files changed, 114 insertions, 2 deletions
diff --git a/src/mongo/db/matcher/expression_expr.cpp b/src/mongo/db/matcher/expression_expr.cpp index cd7f27fa9ba..c8f6a2aad9e 100644 --- a/src/mongo/db/matcher/expression_expr.cpp +++ b/src/mongo/db/matcher/expression_expr.cpp @@ -78,8 +78,7 @@ Value ExprMatchExpression::evaluateExpression(const MatchableDocument* doc) cons } void ExprMatchExpression::serialize(BSONObjBuilder* out, SerializationOptions opts) const { - // TODO aggregation expressions should support some of the new options. - *out << "$expr" << _expression->serialize(false); + *out << "$expr" << _expression->serialize(opts); } bool ExprMatchExpression::equivalent(const MatchExpression* other) const { diff --git a/src/mongo/db/matcher/expression_expr_test.cpp b/src/mongo/db/matcher/expression_expr_test.cpp index 6401357cc61..57d793d27d7 100644 --- a/src/mongo/db/matcher/expression_expr_test.cpp +++ b/src/mongo/db/matcher/expression_expr_test.cpp @@ -38,6 +38,7 @@ #include "mongo/db/pipeline/expression_context_for_test.h" #include "mongo/db/query/collation/collator_interface_mock.h" #include "mongo/unittest/death_test.h" +#include "mongo/unittest/inline_auto_update.h" #include "mongo/unittest/unittest.h" namespace mongo { @@ -86,6 +87,10 @@ public: return checked_cast<ExprMatchExpression*>(_matchExpression.get()); } + BSONObj serialize(SerializationOptions opts) { + return _matchExpression->serialize(opts); + } + private: const boost::intrusive_ptr<ExpressionContextForTest> _expCtx; std::unique_ptr<MatchExpression> _matchExpression; @@ -795,5 +800,113 @@ DEATH_TEST_REGEX(ExprMatchTest, GetChildFailsIndexGreaterThanZero, "Tripwire ass ASSERT_THROWS_CODE(matchExpr->getChild(0), AssertionException, 6400207); } +/** + * A default redaction strategy that generates easy to check results for testing purposes. + */ +std::string redactFieldNameForTest(StringData s) { + return str::stream() << "HASH(" << s << ")"; +} + +TEST_F(ExprMatchTest, ExprRedactsCorrectly) { + boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + createMatcher(fromjson("{$expr: {$sum: [\"$a\", \"$b\"]}}")); + + SerializationOptions opts; + opts.redactFieldNamesStrategy = redactFieldNameForTest; + opts.redactFieldNames = true; + opts.replacementForLiteralArgs = "?"; + + ASSERT_STR_EQ_AUTO( + "{ $expr: { $sum: [ \"$HASH(a)\", \"$HASH(b)\" ] } }", // NOLINT (test auto-update) + serialize(opts).toString()); + + createMatcher(fromjson("{$expr: {$sum: [\"$a\", \"b\"]}}")); + ASSERT_STR_EQ_AUTO( + "{ $expr: { $sum: [ \"$HASH(a)\", { $const: \"?\" } ] } }", // NOLINT (test auto-update) + serialize(opts).toString()); + + createMatcher(fromjson("{$expr: {$sum: [\"$a.b\", \"$b\"]}}")); + ASSERT_STR_EQ_AUTO( + "{ $expr: { $sum: [ \"$HASH(a).HASH(b)\", \"$HASH(b)\" ] } }", // NOLINT (test auto-update) + // auto-update) + // auto-update) + // auto-update) + serialize(opts).toString()); + + createMatcher(fromjson("{$expr: {$eq: [\"$a\", \"$$NOW\"]}}")); + ASSERT_STR_EQ_AUTO( + "{ $and: [ { HASH(a): { $_internalExprEq: \"?\" } }, { $expr: { $eq: [ \"$HASH(a)\", { " + "$const: \"?\" } ] } } ] }", + serialize(opts).toString()); + + createMatcher(fromjson("{$expr: {$eq: [\"$a\", \"$$NOW\"]}}")); + ASSERT_STR_EQ_AUTO( + "{ $and: [ { HASH(a): { $_internalExprEq: \"?\" } }, { $expr: { $eq: [ \"$HASH(a)\", { " + "$const: \"?\" } ] } } ] }", + serialize(opts).toString()); + + createMatcher(fromjson("{$expr: {$getField: {field: \"b\", input: {a: 1, b: 2}}}}")); + ASSERT_STR_EQ_AUTO( + "{ $expr: { $getField: { field: \"HASH(b)\", input: { $const: \"?\" } } } }", // NOLINT + // (test + // auto-update) + serialize(opts).toString()); + + createMatcher(fromjson("{$expr: {$getField: {field: \"b\", input: \"$a\"}}}")); + ASSERT_STR_EQ_AUTO( + "{ $expr: { $getField: { field: \"HASH(b)\", input: \"$HASH(a)\" } } }", // NOLINT (test + // auto-update) + serialize(opts).toString()); + + createMatcher(fromjson("{$expr: {$getField: {field: \"b\", input: {a: 1, b: \"$c\"}}}}")); + ASSERT_STR_EQ_AUTO( + "{ $expr: { $getField: { field: \"HASH(b)\", input: { HASH(a): { $const: \"?\" }, " + "HASH(b): \"$HASH(c)\" } } } }", + serialize(opts).toString()); + + createMatcher(fromjson("{$expr: {$getField: {field: \"b.c\", input: {a: 1, b: \"$c\"}}}}")); + ASSERT_STR_EQ_AUTO( + "{ $expr: { $getField: { field: \"HASH(b).HASH(c)\", input: { HASH(a): { $const: \"?\" }, " + "HASH(b): \"$HASH(c)\" } } } }", + serialize(opts).toString()); + + createMatcher( + fromjson("{$expr: {$setField: {field: \"b\", input: {a: 1, b: \"$c\"}, value: 5}}}")); + ASSERT_STR_EQ_AUTO( + "{ $expr: { $setField: { field: \"HASH(b)\", input: { HASH(a): { $const: \"?\" }, " + "HASH(b): \"$HASH(c)\" }, value: { $const: \"?\" } } } }", + serialize(opts).toString()); + + createMatcher(fromjson( + "{$expr: {$setField: {field: \"b.c\", input: {a: 1, b: \"$c\"}, value: \"$d\"}}}")); + ASSERT_STR_EQ_AUTO( + "{ $expr: { $setField: { field: \"HASH(b).HASH(c)\", input: { HASH(a): { $const: \"?\" }, " + "HASH(b): \"$HASH(c)\" }, value: \"$HASH(d)\" } } }", + serialize(opts).toString()); + + createMatcher(fromjson( + "{$expr: {$setField: {field: \"b.c\", input: {a: 1, b: \"$c\"}, value: \"$d.e\"}}}")); + ASSERT_STR_EQ_AUTO( + "{ $expr: { $setField: { field: \"HASH(b).HASH(c)\", input: { HASH(a): { $const: \"?\" }, " + "HASH(b): \"$HASH(c)\" }, value: \"$HASH(d).HASH(e)\" } } }", + serialize(opts).toString()); + + createMatcher( + fromjson("{$expr: {$setField: {field: \"b\", input: {a: 1, b: \"$c\"}, value: {a: 1, b: 2, " + "c: 3}}}}")); + ASSERT_STR_EQ_AUTO( + "{ $expr: { $setField: { field: \"HASH(b)\", input: { HASH(a): { $const: \"?\" }, " + "HASH(b): \"$HASH(c)\" }, value: { $const: \"?\" } } } }", + serialize(opts).toString()); + + createMatcher( + fromjson("{$expr: {$setField: {field: \"b\", input: {a: 1, b: \"$c\"}, value: {a: 1, b: 2, " + "c: \"$d\"}}}}")); + ASSERT_STR_EQ_AUTO( + "{ $expr: { $setField: { field: \"HASH(b)\", input: { HASH(a): { $const: \"?\" }, " + "HASH(b): \"$HASH(c)\" }, value: { HASH(a): { $const: \"?\" }, HASH(b): { $const: \"?\" " + "}, HASH(c): \"$HASH(d)\" } } } }", + serialize(opts).toString()); +} } // namespace } // namespace mongo |