diff options
Diffstat (limited to 'src/mongo/db/matcher/expression_serialization_test.cpp')
| -rw-r--r-- | src/mongo/db/matcher/expression_serialization_test.cpp | 352 |
1 files changed, 7 insertions, 345 deletions
diff --git a/src/mongo/db/matcher/expression_serialization_test.cpp b/src/mongo/db/matcher/expression_serialization_test.cpp index 3b25631cd0f..78517a52634 100644 --- a/src/mongo/db/matcher/expression_serialization_test.cpp +++ b/src/mongo/db/matcher/expression_serialization_test.cpp @@ -37,16 +37,7 @@ #include "mongo/db/matcher/expression_parser.h" #include "mongo/db/matcher/extensions_callback_noop.h" #include "mongo/db/matcher/matcher.h" -#include "mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index.h" -#include "mongo/db/matcher/schema/expression_internal_schema_cond.h" -#include "mongo/db/matcher/schema/expression_internal_schema_eq.h" -#include "mongo/db/matcher/schema/expression_internal_schema_fmod.h" -#include "mongo/db/matcher/schema/expression_internal_schema_max_items.h" #include "mongo/db/matcher/schema/expression_internal_schema_max_length.h" -#include "mongo/db/matcher/schema/expression_internal_schema_max_properties.h" -#include "mongo/db/matcher/schema/expression_internal_schema_min_items.h" -#include "mongo/db/matcher/schema/expression_internal_schema_min_length.h" -#include "mongo/db/matcher/schema/expression_internal_schema_min_properties.h" #include "mongo/db/pipeline/expression_context_for_test.h" #include "mongo/unittest/unittest.h" @@ -58,7 +49,9 @@ using std::string; using std::unique_ptr; BSONObj serialize(MatchExpression* match) { - return match->serialize(); + BSONObjBuilder bob; + match->serialize(&bob, true); + return bob.obj(); } TEST(SerializeBasic, AndExpressionWithOneChildSerializesCorrectly) { @@ -362,6 +355,7 @@ TEST(SerializeBasic, ExpressionElemMatchValueWithTripleNotSerializesCorrectly) { ASSERT_EQ(original.matches(obj), reserialized.matches(obj)); } + TEST(SerializeBasic, ExpressionSizeSerializesCorrectly) { boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); Matcher original(fromjson("{x: {$size: 2}}"), @@ -636,32 +630,6 @@ TEST(SerializeBasic, ExpressionRegexWithValueAndOptionsSerializesCorrectly) { ASSERT_EQ(original.matches(obj), reserialized.matches(obj)); } -TEST(SerializeBasic, ExpressionRegexWithoutOptionsSerializesShapeCorrectly) { - auto query = fromjson(R"({x: {$regex: ".*"}})"); - boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto objMatch = MatchExpressionParser::parse(query, expCtx); - ASSERT_OK(objMatch.getStatus()); - SerializationOptions opts; - opts.literalPolicy = LiteralSerializationPolicy::kToRepresentativeParseableValue; - ASSERT_BSONOBJ_EQ(BSON("x" << BSON("$regex" - << "\\?")), - objMatch.getValue()->serialize(opts)); -} - -TEST(SerializeBasic, ExpressionRegexWithOptionsSerializesShapeCorrectly) { - auto query = fromjson(R"({x: {$regex: ".*", $options: "m"}})"); - boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto objMatch = MatchExpressionParser::parse(query, expCtx); - ASSERT_OK(objMatch.getStatus()); - SerializationOptions opts; - opts.literalPolicy = LiteralSerializationPolicy::kToRepresentativeParseableValue; - ASSERT_BSONOBJ_EQ(BSON("x" << BSON("$regex" - << "\\?" - << "$options" - << "i")), - objMatch.getValue()->serialize(opts)); -} - TEST(SerializeBasic, ExpressionRegexWithValueSerializesCorrectly) { boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); Matcher original(fromjson("{x: /a.b/}"), @@ -1125,7 +1093,7 @@ TEST(SerializeBasic, ExpressionNotWithDirectPathExpSerializesCorrectly) { // direct path expression child, instead creating a NOT -> AND -> path expression. This test // manually constructs such an expression in case it ever turns up, since that should still be // able to serialize. - auto originalBSON = fromjson("{a: {$not: {$eq: 2}}}"); + auto originalBSON = fromjson("{a: {$not: {$eq: 2}}}}"); auto equalityRHSElem = originalBSON["a"]["$not"]["$eq"]; auto equalityExpression = std::make_unique<EqualityMatchExpression>("a"_sd, equalityRHSElem); @@ -1711,7 +1679,7 @@ TEST(SerializeInternalSchema, ExpressionInternalSchemaMaxLengthSerializesCorrect TEST(SerializeInternalSchema, ExpressionInternalSchemaCondSerializesCorrectly) { boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - Matcher original(fromjson("{$_internalSchemaCond: [{a: 1}, {b: 2}, {c: 3}]}"), + Matcher original(fromjson("{$_internalSchemaCond: [{a: 1}, {b: 2}, {c: 3}]}}"), expCtx, ExtensionsCallbackNoop(), MatchExpressionParser::kAllowAllSpecialFeatures); @@ -1722,7 +1690,7 @@ TEST(SerializeInternalSchema, ExpressionInternalSchemaCondSerializesCorrectly) { BSONObjBuilder builder; ASSERT_BSONOBJ_EQ( *reserialized.getQuery(), - fromjson("{$_internalSchemaCond: [{a: {$eq: 1}}, {b: {$eq: 2}}, {c: {$eq: 3}}]}")); + fromjson("{$_internalSchemaCond: [{a: {$eq: 1}}, {b: {$eq: 2}}, {c: {$eq: 3}}]}}")); ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression())); } @@ -1880,311 +1848,5 @@ TEST(SerializeInternalBinDataSubType, ExpressionBinDataSubTypeSerializesCorrectl ASSERT_TRUE(original.matches(obj)); } -TEST(SerializeInternalSchema, AllowedPropertiesRedactsCorrectly) { - - auto query = fromjson( - "{$_internalSchemaAllowedProperties: {properties: ['a', 'b']," - "namePlaceholder: 'i', patternProperties: [], otherwise: {i: 0}}}"); - boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto objMatch = MatchExpressionParser::parse(query, expCtx); - ASSERT_OK(objMatch.getStatus()); - - SerializationOptions opts = SerializationOptions::kDebugShapeAndMarkIdentifiers_FOR_TEST; - - ASSERT_BSONOBJ_EQ_AUTO( // NOLINT - R"({ - "$_internalSchemaAllowedProperties": { - "properties": "?array<?string>", - "namePlaceholder": "i", - "patternProperties": [], - "otherwise": { - "HASH<i>": { - "$eq": "?number" - } - } - } - })", - objMatch.getValue()->serialize(opts)); -} - -/** - * Helper function for parsing and creating MatchExpressions. - */ -std::unique_ptr<InternalSchemaCondMatchExpression> createCondMatchExpression(BSONObj condition, - BSONObj thenBranch, - BSONObj elseBranch) { - boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto conditionExpr = MatchExpressionParser::parse(condition, expCtx); - ASSERT_OK(conditionExpr.getStatus()); - auto thenBranchExpr = MatchExpressionParser::parse(thenBranch, expCtx); - ASSERT_OK(thenBranchExpr.getStatus()); - auto elseBranchExpr = MatchExpressionParser::parse(elseBranch, expCtx); - - std::array<std::unique_ptr<MatchExpression>, 3> expressions = { - {std::move(conditionExpr.getValue()), - std::move(thenBranchExpr.getValue()), - std::move(elseBranchExpr.getValue())}}; - - auto cond = std::make_unique<InternalSchemaCondMatchExpression>(std::move(expressions)); - - return cond; -} - -TEST(SerializeInternalSchema, CondMatchRedactsCorrectly) { - auto opts = SerializationOptions::kDebugShapeAndMarkIdentifiers_FOR_TEST; - auto conditionQuery = BSON("age" << BSON("$lt" << 18)); - auto thenQuery = BSON("job" - << "student"); - auto elseQuery = BSON("job" - << "engineer"); - auto cond = createCondMatchExpression(conditionQuery, thenQuery, elseQuery); - BSONObjBuilder bob; - cond->serialize(&bob, opts); - ASSERT_BSONOBJ_EQ_AUTO( // NOLINT - R"({ - "$_internalSchemaCond": [ - { - "HASH<age>": { - "$lt": "?number" - } - }, - { - "HASH<job>": { - "$eq": "?string" - } - }, - { - "HASH<job>": { - "$eq": "?string" - } - } - ] - })", - bob.done()); -} - -TEST(SerializeInternalSchema, FmodMatchRedactsCorrectly) { - InternalSchemaFmodMatchExpression m("a"_sd, Decimal128(1.7), Decimal128(2)); - auto opts = SerializationOptions{LiteralSerializationPolicy::kToDebugTypeString}; - BSONObjBuilder bob; - m.serialize(&bob, opts); - ASSERT_BSONOBJ_EQ_AUTO( // NOLINT - R"({"a":{"$_internalSchemaFmod":["?number","?number"]}})", - bob.done()); -} - -TEST(SerializeInternalSchema, MatchArrayIndexRedactsCorrectly) { - auto query = fromjson( - "{foo: {$_internalSchemaMatchArrayIndex:" - "{index: 0, namePlaceholder: 'i', expression: {i: {$type: 'number'}}}}}"); - boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto objMatch = MatchExpressionParser::parse(query, expCtx); - ASSERT_OK(objMatch.getStatus()); - - BSONObjBuilder bob; - auto opts = SerializationOptions::kDebugShapeAndMarkIdentifiers_FOR_TEST; - objMatch.getValue()->serialize(&bob, opts); - ASSERT_BSONOBJ_EQ_AUTO( // NOLINT - R"({ - "HASH<foo>": { - "$_internalSchemaMatchArrayIndex": { - "index": "?number", - "namePlaceholder": "HASH<i>", - "expression": { - "HASH<i>": { - "$type": ['number'] - } - } - } - } - })", - bob.done()); -} - -TEST(SerializeInternalSchema, MaxItemsRedactsCorrectly) { - InternalSchemaMaxItemsMatchExpression maxItems("a.b"_sd, 2); - auto opts = SerializationOptions::kDebugShapeAndMarkIdentifiers_FOR_TEST; - ASSERT_BSONOBJ_EQ_AUTO( // NOLINT - R"({"$_internalSchemaMaxItems":"?number"})", - maxItems.getSerializedRightHandSide(opts)); -} - -TEST(SerializeInternalSchema, MaxLengthRedactsCorrectly) { - InternalSchemaMaxLengthMatchExpression maxLength("a"_sd, 2); - auto opts = SerializationOptions::kDebugShapeAndMarkIdentifiers_FOR_TEST; - ASSERT_BSONOBJ_EQ_AUTO( // NOLINT - R"({"$_internalSchemaMaxLength":"?number"})", - maxLength.getSerializedRightHandSide(opts)); -} - -TEST(SerializeInternalSchema, MinItemsRedactsCorrectly) { - InternalSchemaMinItemsMatchExpression minItems("a.b"_sd, 2); - auto opts = SerializationOptions::kDebugShapeAndMarkIdentifiers_FOR_TEST; - - ASSERT_BSONOBJ_EQ_AUTO( // NOLINT - R"({"$_internalSchemaMinItems":"?number"})", - minItems.getSerializedRightHandSide(opts)); -} - -TEST(SerializeInternalSchema, MinLengthRedactsCorrectly) { - InternalSchemaMinLengthMatchExpression minLength("a"_sd, 2); - auto opts = SerializationOptions{LiteralSerializationPolicy::kToDebugTypeString}; - ASSERT_BSONOBJ_EQ_AUTO( // NOLINT - R"({"$_internalSchemaMinLength":"?number"})", - minLength.getSerializedRightHandSide(opts)); -} - -TEST(SerializeInternalSchema, MinPropertiesRedactsCorrectly) { - InternalSchemaMinPropertiesMatchExpression minProperties(5); - auto opts = SerializationOptions{LiteralSerializationPolicy::kToDebugTypeString}; - - BSONObjBuilder bob; - minProperties.serialize(&bob, opts); - ASSERT_BSONOBJ_EQ_AUTO( // NOLINT - R"({"$_internalSchemaMinProperties":"?number"})", - bob.done()); -} - -TEST(SerializeInternalSchema, ObjectMatchRedactsCorrectly) { - auto opts = SerializationOptions::kDebugShapeAndMarkIdentifiers_FOR_TEST; - auto query = fromjson( - " {a: {$_internalSchemaObjectMatch: {" - " c: {$eq: 3}" - " }}}"); - boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto objMatch = MatchExpressionParser::parse(query, expCtx); - ASSERT_OK(objMatch.getStatus()); - - ASSERT_BSONOBJ_EQ_AUTO( // NOLINT - R"({"HASH<a>":{"$_internalSchemaObjectMatch":{"HASH<c>":{"$eq":"?number"}}}})", - objMatch.getValue()->serialize(opts)); -} - -TEST(SerializeInternalSchema, RootDocEqRedactsCorrectly) { - auto query = fromjson("{$_internalSchemaRootDocEq: {a:1, b: {c: 1, d: [1]}}}"); - boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto opts = SerializationOptions::kDebugShapeAndMarkIdentifiers_FOR_TEST; - auto objMatch = MatchExpressionParser::parse(query, expCtx); - ASSERT_BSONOBJ_EQ_AUTO( // NOLINT - R"({ - "$_internalSchemaRootDocEq": { - "HASH<a>": "?number", - "HASH<b>": { - "HASH<c>": "?number", - "HASH<d>": [ - "?number" - ] - } - } - })", - objMatch.getValue()->serialize(opts)); -} - -TEST(SerializeInternalSchema, BinDataEncryptedTypeRedactsCorrectly) { - MatcherTypeSet typeSet; - typeSet.bsonTypes.insert(BSONType::String); - typeSet.bsonTypes.insert(BSONType::Date); - InternalSchemaBinDataEncryptedTypeExpression e("a"_sd, std::move(typeSet)); - auto opts = SerializationOptions{LiteralSerializationPolicy::kToDebugTypeString}; - ASSERT_BSONOBJ_EQ_AUTO( // NOLINT - R"({"$_internalSchemaBinDataEncryptedType":[2,9]})", - e.getSerializedRightHandSide(opts)); -} - -TEST(SerializeInternalSchema, BinDataFLE2EncryptedTypeRedactsCorrectly) { - InternalSchemaBinDataFLE2EncryptedTypeExpression e("ssn"_sd, BSONType::String); - auto opts = SerializationOptions{LiteralSerializationPolicy::kToDebugTypeString}; - ASSERT_BSONOBJ_EQ_AUTO( // NOLINT - R"({"$_internalSchemaBinDataFLE2EncryptedType":[2]})", - e.getSerializedRightHandSide(opts)); -} - -TEST(SerializesInternalSchema, MaxPropertiesRedactsCorrectly) { - InternalSchemaMaxPropertiesMatchExpression maxProperties(5); - auto opts = SerializationOptions{LiteralSerializationPolicy::kToDebugTypeString}; - - BSONObjBuilder bob; - maxProperties.serialize(&bob, opts); - ASSERT_BSONOBJ_EQ_AUTO( // NOLINT - R"({"$_internalSchemaMaxProperties":"?number"})", - bob.done()); -} - -TEST(SerializesInternalSchema, EqRedactsCorrectly) { - auto opts = SerializationOptions::kDebugShapeAndMarkIdentifiers_FOR_TEST; - auto query = fromjson("{$_internalSchemaEq: {a:1, b: {c: 1, d: [1]}}}"); - BSONObjBuilder bob; - InternalSchemaEqMatchExpression e("a"_sd, query.firstElement()); - e.serialize(&bob, opts); - ASSERT_BSONOBJ_EQ_AUTO( // NOLINT - R"({ - "HASH<a>": { - "$_internalSchemaEq": { - "HASH<a>": "?number", - "HASH<b>": { - "HASH<c>": "?number", - "HASH<d>": [ - "?number" - ] - } - } - } - })", - bob.done()); -} - -TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, RedactsExpressionCorrectly) { - auto query = fromjson("{a: {$_internalSchemaAllElemMatchFromIndex: [2, {a: {$lt: 5}}]}}"); - boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto expr = MatchExpressionParser::parse(query, expCtx); - ASSERT_OK(expr.getStatus()); - auto elemMatchExpr = dynamic_cast<const InternalSchemaAllElemMatchFromIndexMatchExpression*>( - expr.getValue().get()); - - auto opts = SerializationOptions::kDebugShapeAndMarkIdentifiers_FOR_TEST; - - ASSERT_BSONOBJ_EQ_AUTO( // NOLINT - R"({ - "$_internalSchemaAllElemMatchFromIndex": [ - "?number", - { - "HASH<a>": { - "$lt": "?number" - } - } - ] - })", - elemMatchExpr->getSerializedRightHandSide(opts)); -} - -TEST(SerializeBasic, SerializesNestedElemMatchCorrectly) { - auto query = fromjson(R"({a: {$elemMatch: {$elemMatch: {b: {$lt: 6, $gt: 4}}}}})"); - boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto objMatch = MatchExpressionParser::parse(query, expCtx); - ASSERT_OK(objMatch.getStatus()); - SerializationOptions opts; - opts.literalPolicy = LiteralSerializationPolicy::kToDebugTypeString; - ASSERT_BSONOBJ_EQ_AUTO( - R"({"a": { - "$elemMatch": { - "$elemMatch": { - "$and": [ - { - "b": { - "$lt": "?number" - } - }, - { - "b": { - "$gt": "?number" - } - } - ] - } - } - } - })", - objMatch.getValue()->serialize(opts)); -} } // namespace } // namespace mongo |
