diff options
author | David Storch <david.storch@10gen.com> | 2016-08-12 15:58:56 -0400 |
---|---|---|
committer | David Storch <david.storch@10gen.com> | 2016-08-18 11:14:17 -0400 |
commit | 26543060c852aac22f26143a04bf7789ec8fec53 (patch) | |
tree | df3ae49e5c4745058be29b7ec8a8e4b528b50a9a /src/mongo/db/pipeline | |
parent | 13fa28982d008568f7620d73ddec0c61fad7cbc8 (diff) | |
download | mongo-26543060c852aac22f26143a04bf7789ec8fec53.tar.gz |
SERVER-24508 BSONObj::ComparatorInterface
BSONObj instances should now be compared via the comparator
interface's evaluate() method. This preferred over using
BSONObj::woCompare() directly. If the comparison doesn't
require any database semantics (e.g. there is no collation),
there is a global instance of the SimpleBSONObjComparator
which should be used for BSONObj comparisons. If the
comparison requires special semantics, then callers must
instantiate their own comparator object.
Diffstat (limited to 'src/mongo/db/pipeline')
-rw-r--r-- | src/mongo/db/pipeline/aggregation_request_test.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/pipeline/document_source_test.cpp | 104 | ||||
-rw-r--r-- | src/mongo/db/pipeline/document_value_test.cpp | 14 | ||||
-rw-r--r-- | src/mongo/db/pipeline/expression_test.cpp | 72 | ||||
-rw-r--r-- | src/mongo/db/pipeline/lookup_set_cache_test.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/pipeline/pipeline_d.cpp | 12 | ||||
-rw-r--r-- | src/mongo/db/pipeline/pipeline_test.cpp | 4 |
7 files changed, 115 insertions, 101 deletions
diff --git a/src/mongo/db/pipeline/aggregation_request_test.cpp b/src/mongo/db/pipeline/aggregation_request_test.cpp index b9fe685961f..acd38732522 100644 --- a/src/mongo/db/pipeline/aggregation_request_test.cpp +++ b/src/mongo/db/pipeline/aggregation_request_test.cpp @@ -60,9 +60,9 @@ TEST(AggregationRequestTest, ShouldParseAllKnownOptions) { ASSERT_TRUE(request.shouldBypassDocumentValidation()); ASSERT_TRUE(request.isCursorCommand()); ASSERT_EQ(request.getBatchSize().get(), 10); - ASSERT_EQ(request.getCollation(), - BSON("locale" - << "en_US")); + ASSERT_BSONOBJ_EQ(request.getCollation(), + BSON("locale" + << "en_US")); } // diff --git a/src/mongo/db/pipeline/document_source_test.cpp b/src/mongo/db/pipeline/document_source_test.cpp index 7b2a0e72c12..ba326b9c82d 100644 --- a/src/mongo/db/pipeline/document_source_test.cpp +++ b/src/mongo/db/pipeline/document_source_test.cpp @@ -134,50 +134,50 @@ public: const char* array[] = {"a", "b"}; // basic DepsTracker deps; deps.fields = arrayToSet(array); - ASSERT_EQUALS(deps.toProjection(), BSON("a" << 1 << "b" << 1 << "_id" << 0)); + ASSERT_BSONOBJ_EQ(deps.toProjection(), BSON("a" << 1 << "b" << 1 << "_id" << 0)); } { const char* array[] = {"a", "ab"}; // prefixed but not subfield DepsTracker deps; deps.fields = arrayToSet(array); - ASSERT_EQUALS(deps.toProjection(), BSON("a" << 1 << "ab" << 1 << "_id" << 0)); + ASSERT_BSONOBJ_EQ(deps.toProjection(), BSON("a" << 1 << "ab" << 1 << "_id" << 0)); } { const char* array[] = {"a", "b", "a.b"}; // a.b included by a DepsTracker deps; deps.fields = arrayToSet(array); - ASSERT_EQUALS(deps.toProjection(), BSON("a" << 1 << "b" << 1 << "_id" << 0)); + ASSERT_BSONOBJ_EQ(deps.toProjection(), BSON("a" << 1 << "b" << 1 << "_id" << 0)); } { const char* array[] = {"a", "_id"}; // _id now included DepsTracker deps; deps.fields = arrayToSet(array); - ASSERT_EQUALS(deps.toProjection(), BSON("a" << 1 << "_id" << 1)); + ASSERT_BSONOBJ_EQ(deps.toProjection(), BSON("a" << 1 << "_id" << 1)); } { const char* array[] = {"a", "_id.a"}; // still include whole _id (SERVER-7502) DepsTracker deps; deps.fields = arrayToSet(array); - ASSERT_EQUALS(deps.toProjection(), BSON("a" << 1 << "_id" << 1)); + ASSERT_BSONOBJ_EQ(deps.toProjection(), BSON("a" << 1 << "_id" << 1)); } { const char* array[] = {"a", "_id", "_id.a"}; // handle both _id and subfield DepsTracker deps; deps.fields = arrayToSet(array); - ASSERT_EQUALS(deps.toProjection(), BSON("a" << 1 << "_id" << 1)); + ASSERT_BSONOBJ_EQ(deps.toProjection(), BSON("a" << 1 << "_id" << 1)); } { const char* array[] = {"a", "_id", "_id_a"}; // _id prefixed but non-subfield DepsTracker deps; deps.fields = arrayToSet(array); - ASSERT_EQUALS(deps.toProjection(), BSON("_id_a" << 1 << "a" << 1 << "_id" << 1)); + ASSERT_BSONOBJ_EQ(deps.toProjection(), BSON("_id_a" << 1 << "a" << 1 << "_id" << 1)); } { const char* array[] = {"a"}; // fields ignored with needWholeDocument DepsTracker deps; deps.fields = arrayToSet(array); deps.needWholeDocument = true; - ASSERT_EQUALS(deps.toProjection(), BSONObj()); + ASSERT_BSONOBJ_EQ(deps.toProjection(), BSONObj()); } { const char* array[] = {"a"}; // needTextScore with needWholeDocument @@ -185,14 +185,15 @@ public: deps.fields = arrayToSet(array); deps.needWholeDocument = true; deps.setNeedTextScore(true); - ASSERT_EQUALS(deps.toProjection(), BSON(Document::metaFieldTextScore << metaTextScore)); + ASSERT_BSONOBJ_EQ(deps.toProjection(), + BSON(Document::metaFieldTextScore << metaTextScore)); } { const char* array[] = {"a"}; // needTextScore without needWholeDocument DepsTracker deps(DepsTracker::MetadataAvailable::kTextScore); deps.fields = arrayToSet(array); deps.setNeedTextScore(true); - ASSERT_EQUALS( + ASSERT_BSONOBJ_EQ( deps.toProjection(), BSON(Document::metaFieldTextScore << metaTextScore << "a" << 1 << "_id" << 0)); } @@ -402,7 +403,7 @@ TEST(MakeMatchStageFromInput, NonArrayValueUsesEqQuery) { Document input = DOC("local" << 1); BSONObj matchStage = DocumentSourceLookUp::makeMatchStageFromInput( input, FieldPath("local"), "foreign", BSONObj()); - ASSERT_EQ(matchStage, fromjson("{$match: {$and: [{foreign: {$eq: 1}}, {}]}}")); + ASSERT_BSONOBJ_EQ(matchStage, fromjson("{$match: {$and: [{foreign: {$eq: 1}}, {}]}}")); } TEST(MakeMatchStageFromInput, RegexValueUsesEqQuery) { @@ -410,9 +411,10 @@ TEST(MakeMatchStageFromInput, RegexValueUsesEqQuery) { Document input = DOC("local" << Value(regex)); BSONObj matchStage = DocumentSourceLookUp::makeMatchStageFromInput( input, FieldPath("local"), "foreign", BSONObj()); - ASSERT_EQ(matchStage, - BSON("$match" << BSON("$and" << BSON_ARRAY(BSON("foreign" << BSON("$eq" << regex)) - << BSONObj())))); + ASSERT_BSONOBJ_EQ( + matchStage, + BSON("$match" << BSON( + "$and" << BSON_ARRAY(BSON("foreign" << BSON("$eq" << regex)) << BSONObj())))); } TEST(MakeMatchStageFromInput, ArrayValueUsesInQuery) { @@ -420,7 +422,7 @@ TEST(MakeMatchStageFromInput, ArrayValueUsesInQuery) { Document input = DOC("local" << Value(inputArray)); BSONObj matchStage = DocumentSourceLookUp::makeMatchStageFromInput( input, FieldPath("local"), "foreign", BSONObj()); - ASSERT_EQ(matchStage, fromjson("{$match: {$and: [{foreign: {$in: [1, 2]}}, {}]}}")); + ASSERT_BSONOBJ_EQ(matchStage, fromjson("{$match: {$and: [{foreign: {$in: [1, 2]}}, {}]}}")); } TEST(MakeMatchStageFromInput, ArrayValueWithRegexUsesOrQuery) { @@ -429,13 +431,14 @@ TEST(MakeMatchStageFromInput, ArrayValueWithRegexUsesOrQuery) { Document input = DOC("local" << Value(inputArray)); BSONObj matchStage = DocumentSourceLookUp::makeMatchStageFromInput( input, FieldPath("local"), "foreign", BSONObj()); - ASSERT_EQ(matchStage, - BSON("$match" << BSON( - "$and" << BSON_ARRAY( - BSON("$or" << BSON_ARRAY(BSON("foreign" << BSON("$eq" << Value(1))) - << BSON("foreign" << BSON("$eq" << regex)) - << BSON("foreign" << BSON("$eq" << Value(2))))) - << BSONObj())))); + ASSERT_BSONOBJ_EQ( + matchStage, + BSON("$match" << BSON( + "$and" << BSON_ARRAY( + BSON("$or" << BSON_ARRAY(BSON("foreign" << BSON("$eq" << Value(1))) + << BSON("foreign" << BSON("$eq" << regex)) + << BSON("foreign" << BSON("$eq" << Value(2))))) + << BSONObj())))); } } // namespace DocumentSourceLookUp @@ -485,7 +488,7 @@ private: BSONElement specElement = spec.firstElement(); intrusive_ptr<DocumentSource> generated = DocumentSourceGroup::createFromBson(specElement, ctx()); - ASSERT_EQUALS(spec, toBson(generated)); + ASSERT_BSONOBJ_EQ(spec, toBson(generated)); } intrusive_ptr<DocumentSource> _group; TempDir _tempDir; @@ -513,7 +516,7 @@ public: boost::optional<Document> next = group()->getNext(); ASSERT(bool(next)); // The constant _id value from the $group spec is passed through. - ASSERT_EQUALS(expected(), next->toBson()); + ASSERT_BSONOBJ_EQ(expected(), next->toBson()); } protected: @@ -803,7 +806,7 @@ protected: bsonResultSet << i->second; } // Check the result set. - ASSERT_EQUALS(expectedResultSet(), bsonResultSet.arr()); + ASSERT_BSONOBJ_EQ(expectedResultSet(), bsonResultSet.arr()); } }; @@ -1419,8 +1422,8 @@ TEST_F(ProjectStageTest, ShouldOptimizeInnerExpressions) { // The $and should have been replaced with its only argument. vector<Value> serializedArray; project()->serializeToArray(serializedArray); - ASSERT_EQUALS(serializedArray[0].getDocument().toBson(), - fromjson("{$project: {_id: true, a: {$const: true}}}")); + ASSERT_BSONOBJ_EQ(serializedArray[0].getDocument().toBson(), + fromjson("{$project: {_id: true, a: {$const: true}}}")); }; TEST_F(ProjectStageTest, ShouldErrorOnNonObjectSpec) { @@ -1882,7 +1885,7 @@ private: void checkBsonRepresentation(const BSONObj& spec) { Value serialized = static_cast<DocumentSourceSample*>(sample())->serialize(false); auto generatedSpec = serialized.getDocument().toBson(); - ASSERT_EQUALS(spec, generatedSpec); + ASSERT_BSONOBJ_EQ(spec, generatedSpec); } }; @@ -2161,7 +2164,7 @@ private: vector<Value> arr; _sort->serializeToArray(arr); BSONObj generatedSpec = arr[0].getDocument().toBson(); - ASSERT_EQUALS(spec, generatedSpec); + ASSERT_BSONOBJ_EQ(spec, generatedSpec); } intrusive_ptr<DocumentSource> _sort; }; @@ -2178,7 +2181,7 @@ public: { // pre-limit checks vector<Value> arr; sort()->serializeToArray(arr); - ASSERT_EQUALS(arr[0].getDocument().toBson(), BSON("$sort" << BSON("a" << 1))); + ASSERT_BSONOBJ_EQ(arr[0].getDocument().toBson(), BSON("$sort" << BSON("a" << 1))); ASSERT(sort()->getShardSource() == NULL); ASSERT(sort()->getMergeSource() != NULL); @@ -2242,7 +2245,7 @@ public: bsonResultSet << *i; } // Check the result set. - ASSERT_EQUALS(expectedResultSet(), bsonResultSet.arr()); + ASSERT_BSONOBJ_EQ(expectedResultSet(), bsonResultSet.arr()); } protected: @@ -2695,7 +2698,7 @@ private: bsonResultSet << *i; } // Check the result set. - ASSERT_EQUALS(expectedResults, bsonResultSet.arr()); + ASSERT_BSONOBJ_EQ(expectedResults, bsonResultSet.arr()); } /** @@ -2706,8 +2709,8 @@ private: vector<Value> arr; _unwind->serializeToArray(arr); BSONObj generatedSpec = Value(arr[0]).getDocument().toBson(); - ASSERT_EQUALS(expectedSerialization(preserveNullAndEmptyArrays, includeArrayIndex), - generatedSpec); + ASSERT_BSONOBJ_EQ(expectedSerialization(preserveNullAndEmptyArrays, includeArrayIndex), + generatedSpec); } BSONObj expectedSerialization(bool preserveNullAndEmptyArrays, bool includeArrayIndex) const { @@ -3356,7 +3359,7 @@ public: void test(string input, string safePortion) { try { intrusive_ptr<DocumentSourceMatch> match = makeMatch(input); - ASSERT_EQUALS(match->redactSafePortion(), fromjson(safePortion)); + ASSERT_BSONOBJ_EQ(match->redactSafePortion(), fromjson(safePortion)); } catch (...) { unittest::log() << "Problem with redactSafePortion() of: " << input; throw; @@ -3612,60 +3615,61 @@ public: Pipeline::SourceContainer container; // Check initial state - ASSERT_EQUALS(match1->getQuery(), BSON("a" << 1)); - ASSERT_EQUALS(match2->getQuery(), BSON("b" << 1)); - ASSERT_EQUALS(match3->getQuery(), BSON("c" << 1)); + ASSERT_BSONOBJ_EQ(match1->getQuery(), BSON("a" << 1)); + ASSERT_BSONOBJ_EQ(match2->getQuery(), BSON("b" << 1)); + ASSERT_BSONOBJ_EQ(match3->getQuery(), BSON("c" << 1)); container.push_back(match1); container.push_back(match2); match1->optimizeAt(container.begin(), &container); ASSERT_EQUALS(container.size(), 1U); - ASSERT_EQUALS(match1->getQuery(), fromjson("{'$and': [{a:1}, {b:1}]}")); + ASSERT_BSONOBJ_EQ(match1->getQuery(), fromjson("{'$and': [{a:1}, {b:1}]}")); container.push_back(match3); match1->optimizeAt(container.begin(), &container); ASSERT_EQUALS(container.size(), 1U); - ASSERT_EQUALS(match1->getQuery(), - fromjson("{'$and': [{'$and': [{a:1}, {b:1}]}," - "{c:1}]}")); + ASSERT_BSONOBJ_EQ(match1->getQuery(), + fromjson("{'$and': [{'$and': [{a:1}, {b:1}]}," + "{c:1}]}")); } }; TEST(ObjectForMatch, ShouldExtractTopLevelFieldIfDottedFieldNeeded) { Document input(fromjson("{a: 1, b: {c: 1, d: 1}}")); BSONObj expected = fromjson("{b: {c: 1, d: 1}}"); - ASSERT_EQUALS(expected, DocumentSourceMatch::getObjectForMatch(input, {"b.c"})); + ASSERT_BSONOBJ_EQ(expected, DocumentSourceMatch::getObjectForMatch(input, {"b.c"})); } TEST(ObjectForMatch, ShouldExtractEntireArray) { Document input(fromjson("{a: [1, 2, 3], b: 1}")); BSONObj expected = fromjson("{a: [1, 2, 3]}"); - ASSERT_EQUALS(expected, DocumentSourceMatch::getObjectForMatch(input, {"a"})); + ASSERT_BSONOBJ_EQ(expected, DocumentSourceMatch::getObjectForMatch(input, {"a"})); } TEST(ObjectForMatch, ShouldOnlyAddPrefixedFieldOnceIfTwoDottedSubfields) { Document input(fromjson("{a: 1, b: {c: 1, f: {d: {e: 1}}}}")); BSONObj expected = fromjson("{b: {c: 1, f: {d: {e: 1}}}}"); - ASSERT_EQUALS(expected, DocumentSourceMatch::getObjectForMatch(input, {"b.f", "b.f.d.e"})); + ASSERT_BSONOBJ_EQ(expected, DocumentSourceMatch::getObjectForMatch(input, {"b.f", "b.f.d.e"})); } TEST(ObjectForMatch, MissingFieldShouldNotAppearInResult) { Document input(fromjson("{a: 1}")); BSONObj expected; - ASSERT_EQUALS(expected, DocumentSourceMatch::getObjectForMatch(input, {"b", "c"})); + ASSERT_BSONOBJ_EQ(expected, DocumentSourceMatch::getObjectForMatch(input, {"b", "c"})); } TEST(ObjectForMatch, ShouldSerializeNothingIfNothingIsNeeded) { Document input(fromjson("{a: 1, b: {c: 1}}")); BSONObj expected; - ASSERT_EQUALS(expected, DocumentSourceMatch::getObjectForMatch(input, std::set<std::string>{})); + ASSERT_BSONOBJ_EQ(expected, + DocumentSourceMatch::getObjectForMatch(input, std::set<std::string>{})); } TEST(ObjectForMatch, ShouldExtractEntireArrayFromPrefixOfDottedField) { Document input(fromjson("{a: [{b: 1}, {b: 2}], c: 1}")); BSONObj expected = fromjson("{a: [{b: 1}, {b: 2}]}"); - ASSERT_EQUALS(expected, DocumentSourceMatch::getObjectForMatch(input, {"a.b"})); + ASSERT_BSONOBJ_EQ(expected, DocumentSourceMatch::getObjectForMatch(input, {"a.b"})); } @@ -4812,8 +4816,8 @@ TEST_F(AddFieldsTest, OptimizesInnerExpressions) { // The $and should have been replaced with its only argument. vector<Value> serializedArray; addFields()->serializeToArray(serializedArray); - ASSERT_EQUALS(serializedArray[0].getDocument().toBson(), - fromjson("{$addFields: {a: {$const: true}}}")); + ASSERT_BSONOBJ_EQ(serializedArray[0].getDocument().toBson(), + fromjson("{$addFields: {a: {$const: true}}}")); } // Verify that the addFields stage requires a valid object specification. diff --git a/src/mongo/db/pipeline/document_value_test.cpp b/src/mongo/db/pipeline/document_value_test.cpp index 8c5f9a755c0..adec442f7b8 100644 --- a/src/mongo/db/pipeline/document_value_test.cpp +++ b/src/mongo/db/pipeline/document_value_test.cpp @@ -69,7 +69,7 @@ void assertRoundTrips(const Document& document1) { BSONObj obj1 = toBson(document1); Document document2 = fromBson(obj1); BSONObj obj2 = toBson(document2); - ASSERT_EQUALS(obj1, obj2); + ASSERT_BSONOBJ_EQ(obj1, obj2); ASSERT_DOCUMENT_EQ(document1, document2); } @@ -407,7 +407,7 @@ public: const Document doc2 = fromBson(obj); // logical equality - ASSERT_EQUALS(obj, obj2); + ASSERT_BSONOBJ_EQ(obj, obj2); ASSERT_DOCUMENT_EQ(doc, doc2); // binary equality @@ -567,7 +567,7 @@ void assertRoundTrips(const Value& value1) { BSONObj obj1 = toBson(value1); Value value2 = fromBson(obj1); BSONObj obj2 = toBson(value2); - ASSERT_EQUALS(obj1, obj2); + ASSERT_BSONOBJ_EQ(obj1, obj2); ASSERT_VALUE_EQ(value1, value2); ASSERT_EQUALS(value1.getType(), value2.getType()); } @@ -1428,9 +1428,9 @@ public: Value(4.4).addToBsonObj(&bob, "a"); Value(22).addToBsonObj(&bob, "b"); Value("astring").addToBsonObj(&bob, "c"); - ASSERT_EQUALS(BSON("a" << 4.4 << "b" << 22 << "c" - << "astring"), - bob.obj()); + ASSERT_BSONOBJ_EQ(BSON("a" << 4.4 << "b" << 22 << "c" + << "astring"), + bob.obj()); } }; @@ -1442,7 +1442,7 @@ public: Value(4.4).addToBsonArray(&bab); Value(22).addToBsonArray(&bab); Value("astring").addToBsonArray(&bab); - ASSERT_EQUALS(BSON_ARRAY(4.4 << 22 << "astring"), bab.arr()); + ASSERT_BSONOBJ_EQ(BSON_ARRAY(4.4 << 22 << "astring"), bab.arr()); } }; diff --git a/src/mongo/db/pipeline/expression_test.cpp b/src/mongo/db/pipeline/expression_test.cpp index 144f2538723..ed579bd3bc3 100644 --- a/src/mongo/db/pipeline/expression_test.cpp +++ b/src/mongo/db/pipeline/expression_test.cpp @@ -99,7 +99,7 @@ static BSONObj constify(const BSONObj& obj, bool parentIsArray = false) { /** Check binary equality, ensuring use of the same numeric types. */ static void assertBinaryEqual(const BSONObj& expected, const BSONObj& actual) { - ASSERT_EQUALS(expected, actual); + ASSERT_BSONOBJ_EQ(expected, actual); ASSERT(expected.binaryEqual(actual)); } @@ -212,13 +212,13 @@ protected: ++i) { dependenciesBson << *i; } - ASSERT_EQUALS(expectedDependencies, dependenciesBson.arr()); + ASSERT_BSONOBJ_EQ(expectedDependencies, dependenciesBson.arr()); ASSERT_EQUALS(false, dependencies.needWholeDocument); ASSERT_EQUALS(false, dependencies.getNeedTextScore()); } void assertContents(const intrusive_ptr<Testable>& expr, const BSONArray& expectedContents) { - ASSERT_EQUALS(constify(BSON("$testable" << expectedContents)), expressionToBson(expr)); + ASSERT_BSONOBJ_EQ(constify(BSON("$testable" << expectedContents)), expressionToBson(expr)); } void addOperandArrayToExpr(const intrusive_ptr<Testable>& expr, const BSONArray& operands) { @@ -276,14 +276,14 @@ TEST_F(ExpressionNaryTest, ValidateObjectExpressionDependency) { TEST_F(ExpressionNaryTest, SerializationToBsonObj) { _notAssociativeNorCommutative->addOperand(ExpressionConstant::create(nullptr, Value(5))); - ASSERT_EQUALS(BSON("foo" << BSON("$testable" << BSON_ARRAY(BSON("$const" << 5)))), - BSON("foo" << _notAssociativeNorCommutative->serialize(false))); + ASSERT_BSONOBJ_EQ(BSON("foo" << BSON("$testable" << BSON_ARRAY(BSON("$const" << 5)))), + BSON("foo" << _notAssociativeNorCommutative->serialize(false))); } TEST_F(ExpressionNaryTest, SerializationToBsonArr) { _notAssociativeNorCommutative->addOperand(ExpressionConstant::create(nullptr, Value(5))); - ASSERT_EQUALS(constify(BSON_ARRAY(BSON("$testable" << BSON_ARRAY(5)))), - BSON_ARRAY(_notAssociativeNorCommutative->serialize(false))); + ASSERT_BSONOBJ_EQ(constify(BSON_ARRAY(BSON("$testable" << BSON_ARRAY(5)))), + BSON_ARRAY(_notAssociativeNorCommutative->serialize(false))); } // Verify that the internal operands are optimized @@ -303,7 +303,7 @@ TEST_F(ExpressionNaryTest, AllConstantOperandOptimization) { assertContents(_notAssociativeNorCommutative, spec); intrusive_ptr<Expression> optimized = _notAssociativeNorCommutative->optimize(); ASSERT(_notAssociativeNorCommutative != optimized); - ASSERT_EQUALS(BSON("$const" << BSON_ARRAY(1 << 2)), expressionToBson(optimized)); + ASSERT_BSONOBJ_EQ(BSON("$const" << BSON_ARRAY(1 << 2)), expressionToBson(optimized)); } // Verify that the optimization of grouping constant and non-constant operands @@ -917,7 +917,7 @@ public: void run() { intrusive_ptr<ExpressionNary> expression = new ExpressionAdd(); populateOperands(expression); - ASSERT_EQUALS(expectedResult(), toBson(expression->evaluate(Document()))); + ASSERT_BSONOBJ_EQ(expectedResult(), toBson(expression->evaluate(Document()))); } protected: @@ -932,7 +932,7 @@ public: void run() { intrusive_ptr<ExpressionNary> expression = new ExpressionAdd(); expression->addOperand(ExpressionConstant::create(nullptr, Value(2))); - ASSERT_EQUALS(BSON("" << 2), toBson(expression->evaluate(Document()))); + ASSERT_BSONOBJ_EQ(BSON("" << 2), toBson(expression->evaluate(Document()))); } }; @@ -1198,12 +1198,12 @@ public: VariablesParseState vps(&idGenerator); intrusive_ptr<Expression> expression = Expression::parseOperand(specElement, vps); expression->injectExpressionContext(expCtx); - ASSERT_EQUALS(constify(spec()), expressionToBson(expression)); - ASSERT_EQUALS(BSON("" << expectedResult()), - toBson(expression->evaluate(fromBson(BSON("a" << 1))))); + ASSERT_BSONOBJ_EQ(constify(spec()), expressionToBson(expression)); + ASSERT_BSONOBJ_EQ(BSON("" << expectedResult()), + toBson(expression->evaluate(fromBson(BSON("a" << 1))))); intrusive_ptr<Expression> optimized = expression->optimize(); - ASSERT_EQUALS(BSON("" << expectedResult()), - toBson(optimized->evaluate(fromBson(BSON("a" << 1))))); + ASSERT_BSONOBJ_EQ(BSON("" << expectedResult()), + toBson(optimized->evaluate(fromBson(BSON("a" << 1))))); } protected: @@ -1222,9 +1222,9 @@ public: VariablesParseState vps(&idGenerator); intrusive_ptr<Expression> expression = Expression::parseOperand(specElement, vps); expression->injectExpressionContext(expCtx); - ASSERT_EQUALS(constify(spec()), expressionToBson(expression)); + ASSERT_BSONOBJ_EQ(constify(spec()), expressionToBson(expression)); intrusive_ptr<Expression> optimized = expression->optimize(); - ASSERT_EQUALS(expectedOptimized(), expressionToBson(optimized)); + ASSERT_BSONOBJ_EQ(expectedOptimized(), expressionToBson(optimized)); } protected: @@ -1579,7 +1579,7 @@ public: intrusive_ptr<Expression> expression = Expression::parseOperand(specElement, vps); expression->injectExpressionContext(expCtx); intrusive_ptr<Expression> optimized = expression->optimize(); - ASSERT_EQUALS(constify(expectedOptimized()), expressionToBson(optimized)); + ASSERT_BSONOBJ_EQ(constify(expectedOptimized()), expressionToBson(optimized)); } protected: @@ -1612,12 +1612,12 @@ public: intrusive_ptr<Expression> expression = Expression::parseOperand(specElement, vps); expression->injectExpressionContext(expCtx); // Check expression spec round trip. - ASSERT_EQUALS(constify(spec()), expressionToBson(expression)); + ASSERT_BSONOBJ_EQ(constify(spec()), expressionToBson(expression)); // Check evaluation result. - ASSERT_EQUALS(expectedResult(), toBson(expression->evaluate(Document()))); + ASSERT_BSONOBJ_EQ(expectedResult(), toBson(expression->evaluate(Document()))); // Check that the result is the same after optimizing. intrusive_ptr<Expression> optimized = expression->optimize(); - ASSERT_EQUALS(expectedResult(), toBson(optimized->evaluate(Document()))); + ASSERT_BSONOBJ_EQ(expectedResult(), toBson(optimized->evaluate(Document()))); } protected: @@ -2575,12 +2575,12 @@ public: VariablesIdGenerator idGenerator; VariablesParseState vps(&idGenerator); intrusive_ptr<Expression> expression = Expression::parseOperand(specElement, vps); - ASSERT_EQUALS(constify(spec()), expressionToBson(expression)); - ASSERT_EQUALS(BSON("" << expectedResult()), - toBson(expression->evaluate(fromBson(BSON("a" << 1))))); + ASSERT_BSONOBJ_EQ(constify(spec()), expressionToBson(expression)); + ASSERT_BSONOBJ_EQ(BSON("" << expectedResult()), + toBson(expression->evaluate(fromBson(BSON("a" << 1))))); intrusive_ptr<Expression> optimized = expression->optimize(); - ASSERT_EQUALS(BSON("" << expectedResult()), - toBson(optimized->evaluate(fromBson(BSON("a" << 1))))); + ASSERT_BSONOBJ_EQ(BSON("" << expectedResult()), + toBson(optimized->evaluate(fromBson(BSON("a" << 1))))); } protected: @@ -2597,9 +2597,9 @@ public: VariablesIdGenerator idGenerator; VariablesParseState vps(&idGenerator); intrusive_ptr<Expression> expression = Expression::parseOperand(specElement, vps); - ASSERT_EQUALS(constify(spec()), expressionToBson(expression)); + ASSERT_BSONOBJ_EQ(constify(spec()), expressionToBson(expression)); intrusive_ptr<Expression> optimized = expression->optimize(); - ASSERT_EQUALS(expectedOptimized(), expressionToBson(optimized)); + ASSERT_BSONOBJ_EQ(expectedOptimized(), expressionToBson(optimized)); } protected: @@ -3400,8 +3400,8 @@ private: VariablesParseState vps(&idGenerator); intrusive_ptr<Expression> expression = Expression::parseOperand(specElement, vps); expression->injectExpressionContext(expCtx); - ASSERT_EQUALS(constify(spec), expressionToBson(expression)); - ASSERT_EQUALS(BSON("" << expectedResult), toBson(expression->evaluate(Document()))); + ASSERT_BSONOBJ_EQ(constify(spec), expressionToBson(expression)); + ASSERT_BSONOBJ_EQ(BSON("" << expectedResult), toBson(expression->evaluate(Document()))); } }; @@ -3528,8 +3528,8 @@ public: VariablesParseState vps(&idGenerator); intrusive_ptr<Expression> expression = Expression::parseOperand(specElement, vps); expression->injectExpressionContext(expCtx); - ASSERT_EQUALS(constify(spec()), expressionToBson(expression)); - ASSERT_EQUALS(BSON("" << expectedResult()), toBson(expression->evaluate(Document()))); + ASSERT_BSONOBJ_EQ(constify(spec()), expressionToBson(expression)); + ASSERT_BSONOBJ_EQ(BSON("" << expectedResult()), toBson(expression->evaluate(Document()))); } protected: @@ -3785,8 +3785,8 @@ public: VariablesParseState vps(&idGenerator); intrusive_ptr<Expression> expression = Expression::parseOperand(specElement, vps); expression->injectExpressionContext(expCtx); - ASSERT_EQUALS(constify(spec()), expressionToBson(expression)); - ASSERT_EQUALS(BSON("" << expectedResult()), toBson(expression->evaluate(Document()))); + ASSERT_BSONOBJ_EQ(constify(spec()), expressionToBson(expression)); + ASSERT_BSONOBJ_EQ(BSON("" << expectedResult()), toBson(expression->evaluate(Document()))); } protected: @@ -3844,8 +3844,8 @@ public: VariablesParseState vps(&idGenerator); intrusive_ptr<Expression> expression = Expression::parseOperand(specElement, vps); expression->injectExpressionContext(expCtx); - ASSERT_EQUALS(constify(spec()), expressionToBson(expression)); - ASSERT_EQUALS(BSON("" << expectedResult()), toBson(expression->evaluate(Document()))); + ASSERT_BSONOBJ_EQ(constify(spec()), expressionToBson(expression)); + ASSERT_BSONOBJ_EQ(BSON("" << expectedResult()), toBson(expression->evaluate(Document()))); } protected: diff --git a/src/mongo/db/pipeline/lookup_set_cache_test.cpp b/src/mongo/db/pipeline/lookup_set_cache_test.cpp index 13f445e67c3..cd27aab99a9 100644 --- a/src/mongo/db/pipeline/lookup_set_cache_test.cpp +++ b/src/mongo/db/pipeline/lookup_set_cache_test.cpp @@ -43,7 +43,9 @@ namespace mongo { bool vectorContains(const boost::optional<std::vector<BSONObj>>& vector, const BSONObj& expectedObj) { ASSERT_TRUE(vector); - return std::find(vector->begin(), vector->end(), expectedObj) != vector->end(); + return std::find_if(vector->begin(), vector->end(), [&expectedObj](const BSONObj& obj) { + return SimpleBSONObjComparator::kInstance.evaluate(expectedObj == obj); + }) != vector->end(); } BSONObj intToObj(int value) { diff --git a/src/mongo/db/pipeline/pipeline_d.cpp b/src/mongo/db/pipeline/pipeline_d.cpp index e4e2e6bb67c..5dd74393a92 100644 --- a/src/mongo/db/pipeline/pipeline_d.cpp +++ b/src/mongo/db/pipeline/pipeline_d.cpp @@ -32,6 +32,7 @@ #include "mongo/db/pipeline/pipeline_d.h" +#include "mongo/bson/simple_bsonobj_comparator.h" #include "mongo/client/dbclientinterface.h" #include "mongo/db/catalog/collection.h" #include "mongo/db/catalog/database.h" @@ -138,7 +139,8 @@ public: const std::list<BSONObj>& originalIndexes) final { Lock::GlobalWrite globalLock(_ctx->opCtx->lockState()); - if (originalCollectionOptions != getCollectionOptions(targetNs)) { + if (SimpleBSONObjComparator::kInstance.evaluate(originalCollectionOptions != + getCollectionOptions(targetNs))) { return {ErrorCodes::CommandFailed, str::stream() << "collection options of target collection " << targetNs.ns() << " changed during processing. Original options: " @@ -146,7 +148,13 @@ public: << ", new options: " << getCollectionOptions(targetNs)}; } - if (originalIndexes != _client.getIndexSpecs(targetNs.ns())) { + + auto currentIndexes = _client.getIndexSpecs(targetNs.ns()); + if (originalIndexes.size() != currentIndexes.size() || + !std::equal(originalIndexes.begin(), + originalIndexes.end(), + currentIndexes.begin(), + SimpleBSONObjComparator::kInstance.makeEqualTo())) { return {ErrorCodes::CommandFailed, str::stream() << "indexes of target collection " << targetNs.ns() << " changed during processing."}; diff --git a/src/mongo/db/pipeline/pipeline_test.cpp b/src/mongo/db/pipeline/pipeline_test.cpp index 864680bcbb9..16625527383 100644 --- a/src/mongo/db/pipeline/pipeline_test.cpp +++ b/src/mongo/db/pipeline/pipeline_test.cpp @@ -1071,7 +1071,7 @@ TEST(PipelineInitialSource, GeoNearInitialQuery) { intrusive_ptr<ExpressionContext> ctx = new ExpressionContext( &_opCtx, AggregationRequest(NamespaceString("a.collection"), rawPipeline)); auto pipe = uassertStatusOK(Pipeline::parse(rawPipeline, ctx)); - ASSERT_EQ(pipe->getInitialQuery(), BSON("a" << 1)); + ASSERT_BSONOBJ_EQ(pipe->getInitialQuery(), BSON("a" << 1)); } TEST(PipelineInitialSource, MatchInitialQuery) { @@ -1081,7 +1081,7 @@ TEST(PipelineInitialSource, MatchInitialQuery) { &_opCtx, AggregationRequest(NamespaceString("a.collection"), rawPipeline)); auto pipe = uassertStatusOK(Pipeline::parse(rawPipeline, ctx)); - ASSERT_EQ(pipe->getInitialQuery(), BSON("a" << 4)); + ASSERT_BSONOBJ_EQ(pipe->getInitialQuery(), BSON("a" << 4)); } TEST(PipelineInitialSource, ParseCollation) { |