summaryrefslogtreecommitdiff
path: root/src/mongo/db/matcher/expression_leaf_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/matcher/expression_leaf_test.cpp')
-rw-r--r--src/mongo/db/matcher/expression_leaf_test.cpp3271
1 files changed, 1658 insertions, 1613 deletions
diff --git a/src/mongo/db/matcher/expression_leaf_test.cpp b/src/mongo/db/matcher/expression_leaf_test.cpp
index ed2f7b259d9..10ae1e8bc10 100644
--- a/src/mongo/db/matcher/expression_leaf_test.cpp
+++ b/src/mongo/db/matcher/expression_leaf_test.cpp
@@ -38,1618 +38,1663 @@
namespace mongo {
- using std::string;
-
- TEST( EqOp, MatchesElement ) {
- BSONObj operand = BSON( "a" << 5 );
- BSONObj match = BSON( "a" << 5.0 );
- BSONObj notMatch = BSON( "a" << 6 );
-
- EqualityMatchExpression eq;
- eq.init( "", operand["a"] );
- ASSERT( eq.matchesSingleElement( match.firstElement() ) );
- ASSERT( !eq.matchesSingleElement( notMatch.firstElement() ) );
-
- ASSERT( eq.equivalent( &eq ) );
- }
-
- TEST( EqOp, InvalidEooOperand ) {
- BSONObj operand;
- EqualityMatchExpression eq;
- ASSERT( !eq.init( "", operand.firstElement() ).isOK() );
- }
-
- TEST( EqOp, MatchesScalar ) {
- BSONObj operand = BSON( "a" << 5 );
- EqualityMatchExpression eq;
- eq.init( "a", operand[ "a" ] );
- ASSERT( eq.matchesBSON( BSON( "a" << 5.0 ), NULL ) );
- ASSERT( !eq.matchesBSON( BSON( "a" << 4 ), NULL ) );
- }
-
- TEST( EqOp, MatchesArrayValue ) {
- BSONObj operand = BSON( "a" << 5 );
- EqualityMatchExpression eq;
- eq.init( "a", operand[ "a" ] );
- ASSERT( eq.matchesBSON( BSON( "a" << BSON_ARRAY( 5.0 << 6 ) ), NULL ) );
- ASSERT( !eq.matchesBSON( BSON( "a" << BSON_ARRAY( 6 << 7 ) ), NULL ) );
- }
-
- TEST( EqOp, MatchesReferencedObjectValue ) {
- BSONObj operand = BSON( "a.b" << 5 );
- EqualityMatchExpression eq;
- eq.init( "a.b", operand[ "a.b" ] );
- ASSERT( eq.matchesBSON( BSON( "a" << BSON( "b" << 5 ) ), NULL ) );
- ASSERT( eq.matchesBSON( BSON( "a" << BSON( "b" << BSON_ARRAY( 5 ) ) ), NULL ) );
- ASSERT( eq.matchesBSON( BSON( "a" << BSON_ARRAY( BSON( "b" << 5 ) ) ), NULL ) );
- }
-
- TEST( EqOp, MatchesReferencedArrayValue ) {
- BSONObj operand = BSON( "a.0" << 5 );
- EqualityMatchExpression eq;
- eq.init( "a.0", operand[ "a.0" ] );
- ASSERT( eq.matchesBSON( BSON( "a" << BSON_ARRAY( 5 ) ), NULL ) );
- ASSERT( !eq.matchesBSON( BSON( "a" << BSON_ARRAY( BSON_ARRAY( 5 ) ) ), NULL ) );
- }
-
- TEST( EqOp, MatchesNull ) {
- BSONObj operand = BSON( "a" << BSONNULL );
- EqualityMatchExpression eq;
- eq.init( "a", operand[ "a" ] );
- ASSERT( eq.matchesBSON( BSONObj(), NULL ) );
- ASSERT( eq.matchesBSON( BSON( "a" << BSONNULL ), NULL ) );
- ASSERT( !eq.matchesBSON( BSON( "a" << 4 ), NULL ) );
- // A non-existent field is treated same way as an empty bson object
- ASSERT( eq.matchesBSON( BSON( "b" << 4 ), NULL ) );
- }
-
- // This test documents how the matcher currently works,
- // not necessarily how it should work ideally.
- TEST( EqOp, MatchesNestedNull ) {
- BSONObj operand = BSON( "a.b" << BSONNULL );
- EqualityMatchExpression eq;
- eq.init( "a.b", operand[ "a.b" ] );
- // null matches any empty object that is on a subpath of a.b
- ASSERT( eq.matchesBSON( BSONObj(), NULL ) );
- ASSERT( eq.matchesBSON( BSON( "a" << BSONObj() ), NULL ) );
- ASSERT( eq.matchesBSON( BSON( "a" << BSON_ARRAY( BSONObj() ) ), NULL ) );
- ASSERT( eq.matchesBSON( BSON( "a" << BSON( "b" << BSONNULL ) ), NULL ) );
- // b does not exist as an element in array under a.
- ASSERT( !eq.matchesBSON( BSON( "a" << BSONArray() ), NULL ) );
- ASSERT( !eq.matchesBSON( BSON( "a" << BSON_ARRAY( BSONNULL ) ), NULL ) );
- ASSERT( !eq.matchesBSON( BSON( "a" << BSON_ARRAY( 1 << 2 ) ), NULL ) );
- // a.b exists but is not null.
- ASSERT( !eq.matchesBSON( BSON( "a" << BSON( "b" << 4 ) ), NULL ) );
- ASSERT( !eq.matchesBSON( BSON( "a" << BSON( "b" << BSONObj() ) ), NULL ) );
- // A non-existent field is treated same way as an empty bson object
- ASSERT( eq.matchesBSON( BSON( "b" << 4 ), NULL ) );
- }
-
- TEST( EqOp, MatchesMinKey ) {
- BSONObj operand = BSON( "a" << MinKey );
- EqualityMatchExpression eq;
- eq.init( "a", operand[ "a" ] );
- ASSERT( eq.matchesBSON( BSON( "a" << MinKey ), NULL ) );
- ASSERT( !eq.matchesBSON( BSON( "a" << MaxKey ), NULL ) );
- ASSERT( !eq.matchesBSON( BSON( "a" << 4 ), NULL ) );
- }
-
-
-
- TEST( EqOp, MatchesMaxKey ) {
- BSONObj operand = BSON( "a" << MaxKey );
- EqualityMatchExpression eq;
- ASSERT( eq.init( "a", operand[ "a" ] ).isOK() );
- ASSERT( eq.matchesBSON( BSON( "a" << MaxKey ), NULL ) );
- ASSERT( !eq.matchesBSON( BSON( "a" << MinKey ), NULL ) );
- ASSERT( !eq.matchesBSON( BSON( "a" << 4 ), NULL ) );
- }
-
- TEST( EqOp, MatchesFullArray ) {
- BSONObj operand = BSON( "a" << BSON_ARRAY( 1 << 2 ) );
- EqualityMatchExpression eq;
- ASSERT( eq.init( "a", operand[ "a" ] ).isOK() );
- ASSERT( eq.matchesBSON( BSON( "a" << BSON_ARRAY( 1 << 2 ) ), NULL ) );
- ASSERT( !eq.matchesBSON( BSON( "a" << BSON_ARRAY( 1 << 2 << 3 ) ), NULL ) );
- ASSERT( !eq.matchesBSON( BSON( "a" << BSON_ARRAY( 1 ) ), NULL ) );
- ASSERT( !eq.matchesBSON( BSON( "a" << 1 ), NULL ) );
- }
-
- TEST( EqOp, MatchesThroughNestedArray ) {
- BSONObj operand = BSON( "a.b.c.d" << 3 );
- EqualityMatchExpression eq;
- eq.init( "a.b.c.d", operand["a.b.c.d"] );
- BSONObj obj = fromjson("{a:{b:[{c:[{d:1},{d:2}]},{c:[{d:3}]}]}}");
- ASSERT( eq.matchesBSON( obj, NULL ) );
- }
-
- TEST( EqOp, ElemMatchKey ) {
- BSONObj operand = BSON( "a" << 5 );
- EqualityMatchExpression eq;
- ASSERT( eq.init( "a", operand[ "a" ] ).isOK() );
- MatchDetails details;
- details.requestElemMatchKey();
- ASSERT( !eq.matchesBSON( BSON( "a" << 4 ), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( eq.matchesBSON( BSON( "a" << 5 ), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( eq.matchesBSON( BSON( "a" << BSON_ARRAY( 1 << 2 << 5 ) ), &details ) );
- ASSERT( details.hasElemMatchKey() );
- ASSERT_EQUALS( "2", details.elemMatchKey() );
- }
-
- // SERVER-14886: when an array is being traversed explictly at the same time that a nested array
- // is being traversed implicitly, the elemMatch key should refer to the offset of the array
- // being implicitly traversed.
- TEST( EqOp, ElemMatchKeyWithImplicitAndExplicitTraversal ) {
- BSONObj operand = BSON( "a.0.b" << 3 );
- BSONElement operandFirstElt = operand.firstElement();
- EqualityMatchExpression eq;
- ASSERT( eq.init( operandFirstElt.fieldName(), operandFirstElt ).isOK() );
- MatchDetails details;
- details.requestElemMatchKey();
- BSONObj obj = fromjson("{a: [{b: [2, 3]}, {b: [4, 5]}]}");
- ASSERT( eq.matchesBSON( obj, &details ) );
- ASSERT( details.hasElemMatchKey() );
- ASSERT_EQUALS( "1", details.elemMatchKey() );
- }
-
- TEST( EqOp, Equality1 ) {
- EqualityMatchExpression eq1;
- EqualityMatchExpression eq2;
- EqualityMatchExpression eq3;
-
- BSONObj operand = BSON( "a" << 5 << "b" << 5 << "c" << 4 );
-
- eq1.init( "a", operand["a"] );
- eq2.init( "a", operand["b"] );
- eq3.init( "c", operand["c"] );
-
- ASSERT( eq1.equivalent( &eq1 ) );
- ASSERT( eq1.equivalent( &eq2 ) );
- ASSERT( !eq1.equivalent( &eq3 ) );
- }
-
- /**
- TEST( EqOp, MatchesIndexKeyScalar ) {
- BSONObj operand = BSON( "a" << 6 );
- EqualityMatchExpression eq;
- ASSERT( eq.init( "a", operand[ "a" ] ).isOK() );
- IndexSpec indexSpec( BSON( "a" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- eq.matchesIndexKey( BSON( "" << 6 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- eq.matchesIndexKey( BSON( "" << 4 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- eq.matchesIndexKey( BSON( "" << BSON_ARRAY( 6 ) ), indexSpec ) );
- }
-
- TEST( EqOp, MatchesIndexKeyMissing ) {
- BSONObj operand = BSON( "a" << 6 );
- EqualityMatchExpression eq;
- ASSERT( eq.init( "a", operand[ "a" ] ).isOK() );
- IndexSpec indexSpec( BSON( "b" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- eq.matchesIndexKey( BSON( "" << 6 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- eq.matchesIndexKey( BSON( "" << 4 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- eq.matchesIndexKey( BSON( "" << BSON_ARRAY( 8 << 6 ) ), indexSpec ) );
- }
-
- TEST( EqOp, MatchesIndexKeyArray ) {
- BSONObj operand = BSON( "a" << BSON_ARRAY( 4 << 5 ) );
- ComparisonMatchExpression eq
- ASSERT( eq.init( "a", operand[ "a" ] ).isOK() );
- IndexSpec indexSpec( BSON( "a" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- eq.matchesIndexKey( BSON( "" << 4 ), indexSpec ) );
- }
-
- TEST( EqOp, MatchesIndexKeyArrayValue ) {
- BSONObj operand = BSON( "a" << 6 );
- ComparisonMatchExpression eq
- ASSERT( eq.init( "a", operand[ "a" ] ).isOK() );
- IndexSpec indexSpec( BSON( "loc" << "mockarrayvalue" << "a" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- eq.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 6 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- eq.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 4 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- eq.matchesIndexKey( BSON( "" << "dummygeohash" <<
- "" << BSON_ARRAY( 8 << 6 ) ), indexSpec ) );
- }
- */
- TEST( LtOp, MatchesElement ) {
- BSONObj operand = BSON( "$lt" << 5 );
- BSONObj match = BSON( "a" << 4.5 );
- BSONObj notMatch = BSON( "a" << 6 );
- BSONObj notMatchEqual = BSON( "a" << 5 );
- BSONObj notMatchWrongType = BSON( "a" << "foo" );
- LTMatchExpression lt;
- ASSERT( lt.init( "", operand[ "$lt" ] ).isOK() );
- ASSERT( lt.matchesSingleElement( match.firstElement() ) );
- ASSERT( !lt.matchesSingleElement( notMatch.firstElement() ) );
- ASSERT( !lt.matchesSingleElement( notMatchEqual.firstElement() ) );
- ASSERT( !lt.matchesSingleElement( notMatchWrongType.firstElement() ) );
- }
-
- TEST( LtOp, InvalidEooOperand ) {
- BSONObj operand;
- LTMatchExpression lt;
- ASSERT( !lt.init( "", operand.firstElement() ).isOK() );
- }
-
- TEST( LtOp, MatchesScalar ) {
- BSONObj operand = BSON( "$lt" << 5 );
- LTMatchExpression lt;
- ASSERT( lt.init( "a", operand[ "$lt" ] ).isOK() );
- ASSERT( lt.matchesBSON( BSON( "a" << 4.5 ), NULL ) );
- ASSERT( !lt.matchesBSON( BSON( "a" << 6 ), NULL ) );
- }
-
- TEST( LtOp, MatchesScalarEmptyKey ) {
- BSONObj operand = BSON( "$lt" << 5 );
- LTMatchExpression lt;
- ASSERT( lt.init( "", operand[ "$lt" ] ).isOK() );
- ASSERT( lt.matchesBSON( BSON( "" << 4.5 ), NULL ) );
- ASSERT( !lt.matchesBSON( BSON( "" << 6 ), NULL ) );
- }
-
- TEST( LtOp, MatchesArrayValue ) {
- BSONObj operand = BSON( "$lt" << 5 );
- LTMatchExpression lt;
- ASSERT( lt.init( "a", operand[ "$lt" ] ).isOK() );
- ASSERT( lt.matchesBSON( BSON( "a" << BSON_ARRAY( 6 << 4.5 ) ), NULL ) );
- ASSERT( !lt.matchesBSON( BSON( "a" << BSON_ARRAY( 6 << 7 ) ), NULL ) );
- }
-
- TEST( LtOp, MatchesWholeArray ) {
- BSONObj operand = BSON( "$lt" << BSON_ARRAY( 5 ) );
- LTMatchExpression lt;
- ASSERT( lt.init( "a", operand[ "$lt" ] ).isOK() );
- ASSERT( lt.matchesBSON( BSON( "a" << BSON_ARRAY( 4 ) ), NULL ) );
- ASSERT( !lt.matchesBSON( BSON( "a" << BSON_ARRAY( 5 ) ), NULL ) );
- ASSERT( !lt.matchesBSON( BSON( "a" << BSON_ARRAY( 6 ) ), NULL ) );
- // Nested array.
- ASSERT( lt.matchesBSON( BSON( "a" << BSON_ARRAY( BSON_ARRAY( 4 ) ) ), NULL ) );
- ASSERT( !lt.matchesBSON( BSON( "a" << BSON_ARRAY( BSON_ARRAY( 5 ) ) ), NULL ) );
- ASSERT( !lt.matchesBSON( BSON( "a" << BSON_ARRAY( BSON_ARRAY( 6 ) ) ), NULL ) );
- }
-
- TEST( LtOp, MatchesNull ) {
- BSONObj operand = BSON( "$lt" << BSONNULL );
- LTMatchExpression lt;
- ASSERT( lt.init( "a", operand[ "$lt" ] ).isOK() );
- ASSERT( !lt.matchesBSON( BSONObj(), NULL ) );
- ASSERT( !lt.matchesBSON( BSON( "a" << BSONNULL ), NULL ) );
- ASSERT( !lt.matchesBSON( BSON( "a" << 4 ), NULL ) );
- // A non-existent field is treated same way as an empty bson object
- ASSERT( !lt.matchesBSON( BSON( "b" << 4 ), NULL ) );
- }
-
- TEST( LtOp, MatchesDotNotationNull) {
- BSONObj operand = BSON( "$lt" << BSONNULL );
- LTMatchExpression lt;
- ASSERT( lt.init( "a.b", operand[ "$lt" ] ).isOK() );
- ASSERT( !lt.matchesBSON( BSONObj(), NULL ) );
- ASSERT( !lt.matchesBSON( BSON( "a" << BSONNULL ), NULL ) );
- ASSERT( !lt.matchesBSON( BSON( "a" << 4 ), NULL ) );
- ASSERT( !lt.matchesBSON( BSON( "a" << BSONObj() ), NULL ) );
- ASSERT( !lt.matchesBSON( BSON( "a" << BSON_ARRAY( BSON( "b" << BSONNULL ) ) ), NULL ) );
- ASSERT( !lt.matchesBSON( BSON( "a" << BSON_ARRAY( BSON( "a" << 4 ) << BSON( "b" << 4 ) ) ), NULL ) );
- ASSERT( !lt.matchesBSON( BSON( "a" << BSON_ARRAY( 4 ) ), NULL ) );
- ASSERT( !lt.matchesBSON( BSON( "a" << BSON_ARRAY( BSON( "b" << 4 ) ) ), NULL ) );
- }
-
- TEST( LtOp, MatchesMinKey ) {
- BSONObj operand = BSON( "a" << MinKey );
- LTMatchExpression lt;
- ASSERT( lt.init( "a", operand[ "a" ] ).isOK() );
- ASSERT( !lt.matchesBSON( BSON( "a" << MinKey ), NULL ) );
- ASSERT( !lt.matchesBSON( BSON( "a" << MaxKey ), NULL ) );
- ASSERT( !lt.matchesBSON( BSON( "a" << 4 ), NULL ) );
- }
-
- TEST( LtOp, MatchesMaxKey ) {
- BSONObj operand = BSON( "a" << MaxKey );
- LTMatchExpression lt;
- ASSERT( lt.init( "a", operand[ "a" ] ).isOK() );
- ASSERT( !lt.matchesBSON( BSON( "a" << MaxKey ), NULL ) );
- ASSERT( lt.matchesBSON( BSON( "a" << MinKey ), NULL ) );
- ASSERT( lt.matchesBSON( BSON( "a" << 4 ), NULL ) );
- }
-
- TEST( LtOp, ElemMatchKey ) {
- BSONObj operand = BSON( "$lt" << 5 );
- LTMatchExpression lt;
- ASSERT( lt.init( "a", operand[ "$lt" ] ).isOK() );
- MatchDetails details;
- details.requestElemMatchKey();
- ASSERT( !lt.matchesBSON( BSON( "a" << 6 ), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( lt.matchesBSON( BSON( "a" << 4 ), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( lt.matchesBSON( BSON( "a" << BSON_ARRAY( 6 << 2 << 5 ) ), &details ) );
- ASSERT( details.hasElemMatchKey() );
- ASSERT_EQUALS( "1", details.elemMatchKey() );
- }
-
- /**
- TEST( LtOp, MatchesIndexKeyScalar ) {
- BSONObj operand = BSON( "$lt" << 6 );
- LtOp lt;
- ASSERT( lt.init( "a", operand[ "$lt" ] ).isOK() );
- IndexSpec indexSpec( BSON( "a" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- lt.matchesIndexKey( BSON( "" << 3 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- lt.matchesIndexKey( BSON( "" << 6 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- lt.matchesIndexKey( BSON( "" << BSON_ARRAY( 5 ) ), indexSpec ) );
- }
-
- TEST( LtOp, MatchesIndexKeyMissing ) {
- BSONObj operand = BSON( "$lt" << 6 );
- LtOp lt;
- ASSERT( lt.init( "a", operand[ "$lt" ] ).isOK() );
- IndexSpec indexSpec( BSON( "b" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- lt.matchesIndexKey( BSON( "" << 6 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- lt.matchesIndexKey( BSON( "" << 4 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- lt.matchesIndexKey( BSON( "" << BSON_ARRAY( 8 << 6 ) ), indexSpec ) );
- }
-
- TEST( LtOp, MatchesIndexKeyArray ) {
- BSONObj operand = BSON( "$lt" << BSON_ARRAY( 4 << 5 ) );
- LtOp lt;
- ASSERT( lt.init( "a", operand[ "$lt" ] ).isOK() );
- IndexSpec indexSpec( BSON( "a" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- lt.matchesIndexKey( BSON( "" << 3 ), indexSpec ) );
- }
-
- TEST( LtOp, MatchesIndexKeyArrayValue ) {
- BSONObj operand = BSON( "$lt" << 6 );
- LtOp lt;
- ASSERT( lt.init( "a", operand[ "$lt" ] ).isOK() );
- IndexSpec indexSpec( BSON( "loc" << "mockarrayvalue" << "a" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- lt.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 3 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- lt.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 6 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- lt.matchesIndexKey( BSON( "" << "dummygeohash" <<
- "" << BSON_ARRAY( 8 << 6 << 4 ) ), indexSpec ) );
- }
- */
- TEST( LteOp, MatchesElement ) {
- BSONObj operand = BSON( "$lte" << 5 );
- BSONObj match = BSON( "a" << 4.5 );
- BSONObj equalMatch = BSON( "a" << 5 );
- BSONObj notMatch = BSON( "a" << 6 );
- BSONObj notMatchWrongType = BSON( "a" << "foo" );
- LTEMatchExpression lte;
- ASSERT( lte.init( "", operand[ "$lte" ] ).isOK() );
- ASSERT( lte.matchesSingleElement( match.firstElement() ) );
- ASSERT( lte.matchesSingleElement( equalMatch.firstElement() ) );
- ASSERT( !lte.matchesSingleElement( notMatch.firstElement() ) );
- ASSERT( !lte.matchesSingleElement( notMatchWrongType.firstElement() ) );
- }
-
- TEST( LteOp, InvalidEooOperand ) {
- BSONObj operand;
- LTEMatchExpression lte;
- ASSERT( !lte.init( "", operand.firstElement() ).isOK() );
- }
-
- TEST( LteOp, MatchesScalar ) {
- BSONObj operand = BSON( "$lte" << 5 );
- LTEMatchExpression lte;
- ASSERT( lte.init( "a", operand[ "$lte" ] ).isOK() );
- ASSERT( lte.matchesBSON( BSON( "a" << 4.5 ), NULL ) );
- ASSERT( !lte.matchesBSON( BSON( "a" << 6 ), NULL ) );
- }
-
- TEST( LteOp, MatchesArrayValue ) {
- BSONObj operand = BSON( "$lte" << 5 );
- LTEMatchExpression lte;
- ASSERT( lte.init( "a", operand[ "$lte" ] ).isOK() );
- ASSERT( lte.matchesBSON( BSON( "a" << BSON_ARRAY( 6 << 4.5 ) ), NULL ) );
- ASSERT( !lte.matchesBSON( BSON( "a" << BSON_ARRAY( 6 << 7 ) ), NULL ) );
- }
-
- TEST( LteOp, MatchesWholeArray ) {
- BSONObj operand = BSON( "$lte" << BSON_ARRAY( 5 ) );
- LTEMatchExpression lte;
- ASSERT( lte.init( "a", operand[ "$lte" ] ).isOK() );
- ASSERT( lte.matchesBSON( BSON( "a" << BSON_ARRAY( 4 ) ), NULL ) );
- ASSERT( lte.matchesBSON( BSON( "a" << BSON_ARRAY( 5 ) ), NULL ) );
- ASSERT( !lte.matchesBSON( BSON( "a" << BSON_ARRAY( 6 ) ), NULL ) );
- // Nested array.
- ASSERT( lte.matchesBSON( BSON( "a" << BSON_ARRAY( BSON_ARRAY( 4 ) ) ), NULL ) );
- ASSERT( lte.matchesBSON( BSON( "a" << BSON_ARRAY( BSON_ARRAY( 5 ) ) ), NULL ) );
- ASSERT( !lte.matchesBSON( BSON( "a" << BSON_ARRAY( BSON_ARRAY( 6 ) ) ), NULL ) );
- }
-
- TEST( LteOp, MatchesNull ) {
- BSONObj operand = BSON( "$lte" << BSONNULL );
- LTEMatchExpression lte;
- ASSERT( lte.init( "a", operand[ "$lte" ] ).isOK() );
- ASSERT( lte.matchesBSON( BSONObj(), NULL ) );
- ASSERT( lte.matchesBSON( BSON( "a" << BSONNULL ), NULL ) );
- ASSERT( !lte.matchesBSON( BSON( "a" << 4 ), NULL ) );
- // A non-existent field is treated same way as an empty bson object
- ASSERT( lte.matchesBSON( BSON( "b" << 4 ), NULL ) );
- }
-
- TEST( LteOp, MatchesDotNotationNull) {
- BSONObj operand = BSON( "$lte" << BSONNULL );
- LTEMatchExpression lte;
- ASSERT( lte.init( "a.b", operand[ "$lte" ] ).isOK() );
- ASSERT( lte.matchesBSON( BSONObj(), NULL ) );
- ASSERT( lte.matchesBSON( BSON( "a" << BSONNULL ), NULL ) );
- ASSERT( lte.matchesBSON( BSON( "a" << 4 ), NULL ) );
- ASSERT( lte.matchesBSON( BSON( "a" << BSONObj() ), NULL ) );
- ASSERT( lte.matchesBSON( BSON( "a" << BSON_ARRAY( BSON( "b" << BSONNULL ) ) ), NULL ) );
- ASSERT( lte.matchesBSON( BSON( "a" << BSON_ARRAY( BSON( "a" << 4 ) << BSON( "b" << 4 ) ) ), NULL ) );
- ASSERT( !lte.matchesBSON( BSON( "a" << BSON_ARRAY( 4 ) ), NULL ) );
- ASSERT( !lte.matchesBSON( BSON( "a" << BSON_ARRAY( BSON( "b" << 4 ) ) ), NULL ) );
- }
-
- TEST( LteOp, MatchesMinKey ) {
- BSONObj operand = BSON( "a" << MinKey );
- LTEMatchExpression lte;
- ASSERT( lte.init( "a", operand[ "a" ] ).isOK() );
- ASSERT( lte.matchesBSON( BSON( "a" << MinKey ), NULL ) );
- ASSERT( !lte.matchesBSON( BSON( "a" << MaxKey ), NULL ) );
- ASSERT( !lte.matchesBSON( BSON( "a" << 4 ), NULL ) );
- }
-
- TEST( LteOp, MatchesMaxKey ) {
- BSONObj operand = BSON( "a" << MaxKey );
- LTEMatchExpression lte;
- ASSERT( lte.init( "a", operand[ "a" ] ).isOK() );
- ASSERT( lte.matchesBSON( BSON( "a" << MaxKey ), NULL ) );
- ASSERT( lte.matchesBSON( BSON( "a" << MinKey ), NULL ) );
- ASSERT( lte.matchesBSON( BSON( "a" << 4 ), NULL ) );
- }
-
-
- TEST( LteOp, ElemMatchKey ) {
- BSONObj operand = BSON( "$lte" << 5 );
- LTEMatchExpression lte;
- ASSERT( lte.init( "a", operand[ "$lte" ] ).isOK() );
- MatchDetails details;
- details.requestElemMatchKey();
- ASSERT( !lte.matchesBSON( BSON( "a" << 6 ), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( lte.matchesBSON( BSON( "a" << 4 ), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( lte.matchesBSON( BSON( "a" << BSON_ARRAY( 6 << 2 << 5 ) ), &details ) );
- ASSERT( details.hasElemMatchKey() );
- ASSERT_EQUALS( "1", details.elemMatchKey() );
- }
-
- /**
- TEST( LteOp, MatchesIndexKeyScalar ) {
- BSONObj operand = BSON( "$lte" << 6 );
- LteOp lte;
- ASSERT( lte.init( "a", operand[ "$lte" ] ).isOK() );
- IndexSpec indexSpec( BSON( "a" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- lte.matchesIndexKey( BSON( "" << 6 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- lte.matchesIndexKey( BSON( "" << 7 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- lte.matchesIndexKey( BSON( "" << BSON_ARRAY( 5 ) ), indexSpec ) );
- }
-
- TEST( LteOp, MatchesIndexKeyMissing ) {
- BSONObj operand = BSON( "$lte" << 6 );
- LteOp lte;
- ASSERT( lte.init( "a", operand[ "$lte" ] ).isOK() );
- IndexSpec indexSpec( BSON( "b" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- lte.matchesIndexKey( BSON( "" << 7 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- lte.matchesIndexKey( BSON( "" << 4 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- lte.matchesIndexKey( BSON( "" << BSON_ARRAY( 8 << 6 ) ), indexSpec ) );
- }
-
- TEST( LteOp, MatchesIndexKeyArray ) {
- BSONObj operand = BSON( "$lte" << BSON_ARRAY( 4 << 5 ) );
- LteOp lte;
- ASSERT( lte.init( "a", operand[ "$lte" ] ).isOK() );
- IndexSpec indexSpec( BSON( "a" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- lte.matchesIndexKey( BSON( "" << 3 ), indexSpec ) );
- }
-
- TEST( LteOp, MatchesIndexKeyArrayValue ) {
- BSONObj operand = BSON( "$lte" << 6 );
- LteOp lte;
- ASSERT( lte.init( "a", operand[ "$lte" ] ).isOK() );
- IndexSpec indexSpec( BSON( "loc" << "mockarrayvalue" << "a" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- lte.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 3 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- lte.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 7 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- lte.matchesIndexKey( BSON( "" << "dummygeohash" <<
- "" << BSON_ARRAY( 8 << 6 << 4 ) ), indexSpec ) );
- }
-
- TEST( GtOp, MatchesElement ) {
- BSONObj operand = BSON( "$gt" << 5 );
- BSONObj match = BSON( "a" << 5.5 );
- BSONObj notMatch = BSON( "a" << 4 );
- BSONObj notMatchEqual = BSON( "a" << 5 );
- BSONObj notMatchWrongType = BSON( "a" << "foo" );
- GtOp gt;
- ASSERT( gt.init( "", operand[ "$gt" ] ).isOK() );
- ASSERT( gt.matchesSingleElement( match.firstElement() ) );
- ASSERT( !gt.matchesSingleElement( notMatch.firstElement() ) );
- ASSERT( !gt.matchesSingleElement( notMatchEqual.firstElement() ) );
- ASSERT( !gt.matchesSingleElement( notMatchWrongType.firstElement() ) );
- }
- */
-
- TEST( GtOp, InvalidEooOperand ) {
- BSONObj operand;
- GTMatchExpression gt;
- ASSERT( !gt.init( "", operand.firstElement() ).isOK() );
- }
-
- TEST( GtOp, MatchesScalar ) {
- BSONObj operand = BSON( "$gt" << 5 );
- GTMatchExpression gt;
- ASSERT( gt.init( "a", operand[ "$gt" ] ).isOK() );
- ASSERT( gt.matchesBSON( BSON( "a" << 5.5 ), NULL ) );
- ASSERT( !gt.matchesBSON( BSON( "a" << 4 ), NULL ) );
- }
-
- TEST( GtOp, MatchesArrayValue ) {
- BSONObj operand = BSON( "$gt" << 5 );
- GTMatchExpression gt;
- ASSERT( gt.init( "a", operand[ "$gt" ] ).isOK() );
- ASSERT( gt.matchesBSON( BSON( "a" << BSON_ARRAY( 3 << 5.5 ) ), NULL ) );
- ASSERT( !gt.matchesBSON( BSON( "a" << BSON_ARRAY( 2 << 4 ) ), NULL ) );
- }
-
- TEST( GtOp, MatchesWholeArray ) {
- BSONObj operand = BSON( "$gt" << BSON_ARRAY( 5 ) );
- GTMatchExpression gt;
- ASSERT( gt.init( "a", operand[ "$gt" ] ).isOK() );
- ASSERT( !gt.matchesBSON( BSON( "a" << BSON_ARRAY( 4 ) ), NULL ) );
- ASSERT( !gt.matchesBSON( BSON( "a" << BSON_ARRAY( 5 ) ), NULL ) );
- ASSERT( gt.matchesBSON( BSON( "a" << BSON_ARRAY( 6 ) ), NULL ) );
- // Nested array.
- // XXX: The following assertion documents current behavior.
- ASSERT( gt.matchesBSON( BSON( "a" << BSON_ARRAY( BSON_ARRAY( 4 ) ) ), NULL ) );
- // XXX: The following assertion documents current behavior.
- ASSERT( gt.matchesBSON( BSON( "a" << BSON_ARRAY( BSON_ARRAY( 5 ) ) ), NULL ) );
- ASSERT( gt.matchesBSON( BSON( "a" << BSON_ARRAY( BSON_ARRAY( 6 ) ) ), NULL ) );
- }
-
- TEST( GtOp, MatchesNull ) {
- BSONObj operand = BSON( "$gt" << BSONNULL );
- GTMatchExpression gt;
- ASSERT( gt.init( "a", operand[ "$gt" ] ).isOK() );
- ASSERT( !gt.matchesBSON( BSONObj(), NULL ) );
- ASSERT( !gt.matchesBSON( BSON( "a" << BSONNULL ), NULL ) );
- ASSERT( !gt.matchesBSON( BSON( "a" << 4 ), NULL ) );
- // A non-existent field is treated same way as an empty bson object
- ASSERT( !gt.matchesBSON( BSON( "b" << 4 ), NULL ) );
- }
-
- TEST( GtOp, MatchesDotNotationNull) {
- BSONObj operand = BSON( "$gt" << BSONNULL );
- GTMatchExpression gt;
- ASSERT( gt.init( "a.b", operand[ "$gt" ] ).isOK() );
- ASSERT( !gt.matchesBSON( BSONObj(), NULL ) );
- ASSERT( !gt.matchesBSON( BSON( "a" << BSONNULL ), NULL ) );
- ASSERT( !gt.matchesBSON( BSON( "a" << 4 ), NULL ) );
- ASSERT( !gt.matchesBSON( BSON( "a" << BSONObj() ), NULL ) );
- ASSERT( !gt.matchesBSON( BSON( "a" << BSON_ARRAY( BSON( "b" << BSONNULL ) ) ), NULL ) );
- ASSERT( !gt.matchesBSON( BSON( "a" << BSON_ARRAY( BSON( "a" << 4 ) << BSON( "b" << 4 ) ) ), NULL ) );
- ASSERT( !gt.matchesBSON( BSON( "a" << BSON_ARRAY( 4 ) ), NULL ) );
- ASSERT( !gt.matchesBSON( BSON( "a" << BSON_ARRAY( BSON( "b" << 4 ) ) ), NULL ) );
- }
-
- TEST( GtOp, MatchesMinKey ) {
- BSONObj operand = BSON( "a" << MinKey );
- GTMatchExpression gt;
- ASSERT( gt.init( "a", operand[ "a" ] ).isOK() );
- ASSERT( !gt.matchesBSON( BSON( "a" << MinKey ), NULL ) );
- ASSERT( gt.matchesBSON( BSON( "a" << MaxKey ), NULL ) );
- ASSERT( gt.matchesBSON( BSON( "a" << 4 ), NULL ) );
- }
-
- TEST( GtOp, MatchesMaxKey ) {
- BSONObj operand = BSON( "a" << MaxKey );
- GTMatchExpression gt;
- ASSERT( gt.init( "a", operand[ "a" ] ).isOK() );
- ASSERT( !gt.matchesBSON( BSON( "a" << MaxKey ), NULL ) );
- ASSERT( !gt.matchesBSON( BSON( "a" << MinKey ), NULL ) );
- ASSERT( !gt.matchesBSON( BSON( "a" << 4 ), NULL ) );
- }
-
- TEST( GtOp, ElemMatchKey ) {
- BSONObj operand = BSON( "$gt" << 5 );
- GTMatchExpression gt;
- ASSERT( gt.init( "a", operand[ "$gt" ] ).isOK() );
- MatchDetails details;
- details.requestElemMatchKey();
- ASSERT( !gt.matchesBSON( BSON( "a" << 4 ), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( gt.matchesBSON( BSON( "a" << 6 ), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( gt.matchesBSON( BSON( "a" << BSON_ARRAY( 2 << 6 << 5 ) ), &details ) );
- ASSERT( details.hasElemMatchKey() );
- ASSERT_EQUALS( "1", details.elemMatchKey() );
- }
-
- /**
- TEST( GtOp, MatchesIndexKeyScalar ) {
- BSONObj operand = BSON( "$gt" << 6 );
- GtOp gt;
- ASSERT( gt.init( "a", operand[ "$gt" ] ).isOK() );
- IndexSpec indexSpec( BSON( "a" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- gt.matchesIndexKey( BSON( "" << 7 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- gt.matchesIndexKey( BSON( "" << 6 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- gt.matchesIndexKey( BSON( "" << BSON_ARRAY( 9 ) ), indexSpec ) );
- }
-
- TEST( GtOp, MatchesIndexKeyMissing ) {
- BSONObj operand = BSON( "$gt" << 6 );
- GtOp gt;
- ASSERT( gt.init( "a", operand[ "$gt" ] ).isOK() );
- IndexSpec indexSpec( BSON( "b" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- gt.matchesIndexKey( BSON( "" << 7 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- gt.matchesIndexKey( BSON( "" << 4 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- gt.matchesIndexKey( BSON( "" << BSON_ARRAY( 8 << 6 ) ), indexSpec ) );
- }
-
- TEST( GtOp, MatchesIndexKeyArray ) {
- BSONObj operand = BSON( "$gt" << BSON_ARRAY( 4 << 5 ) );
- GtOp gt;
- ASSERT( gt.init( "a", operand[ "$gt" ] ).isOK() );
- IndexSpec indexSpec( BSON( "a" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- gt.matchesIndexKey( BSON( "" << 8 ), indexSpec ) );
- }
-
- TEST( GtOp, MatchesIndexKeyArrayValue ) {
- BSONObj operand = BSON( "$gt" << 6 );
- GtOp gt;
- ASSERT( gt.init( "a", operand[ "$gt" ] ).isOK() );
- IndexSpec indexSpec( BSON( "loc" << "mockarrayvalue" << "a" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- gt.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 7 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- gt.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 3 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- gt.matchesIndexKey( BSON( "" << "dummygeohash" <<
- "" << BSON_ARRAY( 8 << 6 << 4 ) ), indexSpec ) );
- }
- */
-
- TEST( ComparisonMatchExpression, MatchesElement ) {
- BSONObj operand = BSON( "$gte" << 5 );
- BSONObj match = BSON( "a" << 5.5 );
- BSONObj equalMatch = BSON( "a" << 5 );
- BSONObj notMatch = BSON( "a" << 4 );
- BSONObj notMatchWrongType = BSON( "a" << "foo" );
- GTEMatchExpression gte;
- ASSERT( gte.init( "", operand[ "$gte" ] ).isOK() );
- ASSERT( gte.matchesSingleElement( match.firstElement() ) );
- ASSERT( gte.matchesSingleElement( equalMatch.firstElement() ) );
- ASSERT( !gte.matchesSingleElement( notMatch.firstElement() ) );
- ASSERT( !gte.matchesSingleElement( notMatchWrongType.firstElement() ) );
- }
-
- TEST( ComparisonMatchExpression, InvalidEooOperand ) {
- BSONObj operand;
- GTEMatchExpression gte;
- ASSERT( !gte.init( "", operand.firstElement() ).isOK() );
- }
-
- TEST( ComparisonMatchExpression, MatchesScalar ) {
- BSONObj operand = BSON( "$gte" << 5 );
- GTEMatchExpression gte;
- ASSERT( gte.init( "a", operand[ "$gte" ] ).isOK() );
- ASSERT( gte.matchesBSON( BSON( "a" << 5.5 ), NULL ) );
- ASSERT( !gte.matchesBSON( BSON( "a" << 4 ), NULL ) );
- }
-
- TEST( ComparisonMatchExpression, MatchesArrayValue ) {
- BSONObj operand = BSON( "$gte" << 5 );
- GTEMatchExpression gte;
- ASSERT( gte.init( "a", operand[ "$gte" ] ).isOK() );
- ASSERT( gte.matchesBSON( BSON( "a" << BSON_ARRAY( 4 << 5.5 ) ), NULL ) );
- ASSERT( !gte.matchesBSON( BSON( "a" << BSON_ARRAY( 1 << 2 ) ), NULL ) );
- }
-
- TEST( ComparisonMatchExpression, MatchesWholeArray ) {
- BSONObj operand = BSON( "$gte" << BSON_ARRAY( 5 ) );
- GTEMatchExpression gte;
- ASSERT( gte.init( "a", operand[ "$gte" ] ).isOK() );
- ASSERT( !gte.matchesBSON( BSON( "a" << BSON_ARRAY( 4 ) ), NULL ) );
- ASSERT( gte.matchesBSON( BSON( "a" << BSON_ARRAY( 5 ) ), NULL ) );
- ASSERT( gte.matchesBSON( BSON( "a" << BSON_ARRAY( 6 ) ), NULL ) );
- // Nested array.
- // XXX: The following assertion documents current behavior.
- ASSERT( gte.matchesBSON( BSON( "a" << BSON_ARRAY( BSON_ARRAY( 4 ) ) ), NULL ) );
- ASSERT( gte.matchesBSON( BSON( "a" << BSON_ARRAY( BSON_ARRAY( 5 ) ) ), NULL ) );
- ASSERT( gte.matchesBSON( BSON( "a" << BSON_ARRAY( BSON_ARRAY( 6 ) ) ), NULL ) );
- }
-
- TEST( ComparisonMatchExpression, MatchesNull ) {
- BSONObj operand = BSON( "$gte" << BSONNULL );
- GTEMatchExpression gte;
- ASSERT( gte.init( "a", operand[ "$gte" ] ).isOK() );
- ASSERT( gte.matchesBSON( BSONObj(), NULL ) );
- ASSERT( gte.matchesBSON( BSON( "a" << BSONNULL ), NULL ) );
- ASSERT( !gte.matchesBSON( BSON( "a" << 4 ), NULL ) );
- // A non-existent field is treated same way as an empty bson object
- ASSERT( gte.matchesBSON( BSON( "b" << 4 ), NULL ) );
- }
-
- TEST( ComparisonMatchExpression, MatchesDotNotationNull) {
- BSONObj operand = BSON( "$gte" << BSONNULL );
- GTEMatchExpression gte;
- ASSERT( gte.init( "a.b", operand[ "$gte" ] ).isOK() );
- ASSERT( gte.matchesBSON( BSONObj(), NULL ) );
- ASSERT( gte.matchesBSON( BSON( "a" << BSONNULL ), NULL ) );
- ASSERT( gte.matchesBSON( BSON( "a" << 4 ), NULL ) );
- ASSERT( gte.matchesBSON( BSON( "a" << BSONObj() ), NULL ) );
- ASSERT( gte.matchesBSON( BSON( "a" << BSON_ARRAY( BSON( "b" << BSONNULL ) ) ), NULL ) );
- ASSERT( gte.matchesBSON( BSON( "a" << BSON_ARRAY( BSON( "a" << 4 ) << BSON( "b" << 4 ) ) ), NULL ) );
- ASSERT( !gte.matchesBSON( BSON( "a" << BSON_ARRAY( 4 ) ), NULL ) );
- ASSERT( !gte.matchesBSON( BSON( "a" << BSON_ARRAY( BSON( "b" << 4 ) ) ), NULL ) );
- }
-
- TEST( ComparisonMatchExpression, MatchesMinKey ) {
- BSONObj operand = BSON( "a" << MinKey );
- GTEMatchExpression gte;
- ASSERT( gte.init( "a", operand[ "a" ] ).isOK() );
- ASSERT( gte.matchesBSON( BSON( "a" << MinKey ), NULL ) );
- ASSERT( gte.matchesBSON( BSON( "a" << MaxKey ), NULL ) );
- ASSERT( gte.matchesBSON( BSON( "a" << 4 ), NULL ) );
- }
-
- TEST( ComparisonMatchExpression, MatchesMaxKey ) {
- BSONObj operand = BSON( "a" << MaxKey );
- GTEMatchExpression gte;
- ASSERT( gte.init( "a", operand[ "a" ] ).isOK() );
- ASSERT( gte.matchesBSON( BSON( "a" << MaxKey ), NULL ) );
- ASSERT( !gte.matchesBSON( BSON( "a" << MinKey ), NULL ) );
- ASSERT( !gte.matchesBSON( BSON( "a" << 4 ), NULL ) );
- }
-
- TEST( ComparisonMatchExpression, ElemMatchKey ) {
- BSONObj operand = BSON( "$gte" << 5 );
- GTEMatchExpression gte;
- ASSERT( gte.init( "a", operand[ "$gte" ] ).isOK() );
- MatchDetails details;
- details.requestElemMatchKey();
- ASSERT( !gte.matchesBSON( BSON( "a" << 4 ), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( gte.matchesBSON( BSON( "a" << 6 ), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( gte.matchesBSON( BSON( "a" << BSON_ARRAY( 2 << 6 << 5 ) ), &details ) );
- ASSERT( details.hasElemMatchKey() );
- ASSERT_EQUALS( "1", details.elemMatchKey() );
- }
-
- /**
- TEST( GteOp, MatchesIndexKeyScalar ) {
- BSONObj operand = BSON( "$gte" << 6 );
- GteOp gte;
- ASSERT( gte.init( "a", operand[ "$gte" ] ).isOK() );
- IndexSpec indexSpec( BSON( "a" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- gte.matchesIndexKey( BSON( "" << 6 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- gte.matchesIndexKey( BSON( "" << 5 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- gte.matchesIndexKey( BSON( "" << BSON_ARRAY( 7 ) ), indexSpec ) );
- }
-
- TEST( GteOp, MatchesIndexKeyMissing ) {
- BSONObj operand = BSON( "$gte" << 6 );
- GteOp gte;
- ASSERT( gte.init( "a", operand[ "$gte" ] ).isOK() );
- IndexSpec indexSpec( BSON( "b" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- gte.matchesIndexKey( BSON( "" << 6 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- gte.matchesIndexKey( BSON( "" << 4 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- gte.matchesIndexKey( BSON( "" << BSON_ARRAY( 8 << 6 ) ), indexSpec ) );
- }
-
- TEST( GteOp, MatchesIndexKeyArray ) {
- BSONObj operand = BSON( "$gte" << BSON_ARRAY( 4 << 5 ) );
- GteOp gte;
- ASSERT( gte.init( "a", operand[ "$gte" ] ).isOK() );
- IndexSpec indexSpec( BSON( "a" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- gte.matchesIndexKey( BSON( "" << 6 ), indexSpec ) );
- }
-
- TEST( GteOp, MatchesIndexKeyArrayValue ) {
- BSONObj operand = BSON( "$gte" << 6 );
- GteOp gte;
- ASSERT( gte.init( "a", operand[ "$gte" ] ).isOK() );
- IndexSpec indexSpec( BSON( "loc" << "mockarrayvalue" << "a" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- gte.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 6 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- gte.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 3 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- gte.matchesIndexKey( BSON( "" << "dummygeohash" <<
- "" << BSON_ARRAY( 8 << 6 << 4 ) ), indexSpec ) );
- }
- */
-
- TEST( RegexMatchExpression, MatchesElementExact ) {
- BSONObj match = BSON( "a" << "b" );
- BSONObj notMatch = BSON( "a" << "c" );
- RegexMatchExpression regex;
- ASSERT( regex.init( "", "b", "" ).isOK() );
- ASSERT( regex.matchesSingleElement( match.firstElement() ) );
- ASSERT( !regex.matchesSingleElement( notMatch.firstElement() ) );
- }
-
- TEST( RegexMatchExpression, TooLargePattern ) {
- string tooLargePattern( 50 * 1000, 'z' );
- RegexMatchExpression regex;
- ASSERT( !regex.init( "a", tooLargePattern, "" ).isOK() );
- }
-
- TEST( RegexMatchExpression, MatchesElementSimplePrefix ) {
- BSONObj match = BSON( "x" << "abc" );
- BSONObj notMatch = BSON( "x" << "adz" );
- RegexMatchExpression regex;
- ASSERT( regex.init( "", "^ab", "" ).isOK() );
- ASSERT( regex.matchesSingleElement( match.firstElement() ) );
- ASSERT( !regex.matchesSingleElement( notMatch.firstElement() ) );
- }
-
- TEST( RegexMatchExpression, MatchesElementCaseSensitive ) {
- BSONObj match = BSON( "x" << "abc" );
- BSONObj notMatch = BSON( "x" << "ABC" );
- RegexMatchExpression regex;
- ASSERT( regex.init( "", "abc", "" ).isOK() );
- ASSERT( regex.matchesSingleElement( match.firstElement() ) );
- ASSERT( !regex.matchesSingleElement( notMatch.firstElement() ) );
- }
-
- TEST( RegexMatchExpression, MatchesElementCaseInsensitive ) {
- BSONObj match = BSON( "x" << "abc" );
- BSONObj matchUppercase = BSON( "x" << "ABC" );
- BSONObj notMatch = BSON( "x" << "abz" );
- RegexMatchExpression regex;
- ASSERT( regex.init( "", "abc", "i" ).isOK() );
- ASSERT( regex.matchesSingleElement( match.firstElement() ) );
- ASSERT( regex.matchesSingleElement( matchUppercase.firstElement() ) );
- ASSERT( !regex.matchesSingleElement( notMatch.firstElement() ) );
- }
-
- TEST( RegexMatchExpression, MatchesElementMultilineOff ) {
- BSONObj match = BSON( "x" << "az" );
- BSONObj notMatch = BSON( "x" << "\naz" );
- RegexMatchExpression regex;
- ASSERT( regex.init( "", "^a", "" ).isOK() );
- ASSERT( regex.matchesSingleElement( match.firstElement() ) );
- ASSERT( !regex.matchesSingleElement( notMatch.firstElement() ) );
- }
-
- TEST( RegexMatchExpression, MatchesElementMultilineOn ) {
- BSONObj match = BSON( "x" << "az" );
- BSONObj matchMultiline = BSON( "x" << "\naz" );
- BSONObj notMatch = BSON( "x" << "\n\n" );
- RegexMatchExpression regex;
- ASSERT( regex.init( "", "^a", "m" ).isOK() );
- ASSERT( regex.matchesSingleElement( match.firstElement() ) );
- ASSERT( regex.matchesSingleElement( matchMultiline.firstElement() ) );
- ASSERT( !regex.matchesSingleElement( notMatch.firstElement() ) );
- }
-
- TEST( RegexMatchExpression, MatchesElementExtendedOff ) {
- BSONObj match = BSON( "x" << "a b" );
- BSONObj notMatch = BSON( "x" << "ab" );
- RegexMatchExpression regex;
- ASSERT( regex.init( "", "a b", "" ).isOK() );
- ASSERT( regex.matchesSingleElement( match.firstElement() ) );
- ASSERT( !regex.matchesSingleElement( notMatch.firstElement() ) );
- }
-
- TEST( RegexMatchExpression, MatchesElementExtendedOn ) {
- BSONObj match = BSON( "x" << "ab" );
- BSONObj notMatch = BSON( "x" << "a b" );
- RegexMatchExpression regex;
- ASSERT( regex.init( "", "a b", "x" ).isOK() );
- ASSERT( regex.matchesSingleElement( match.firstElement() ) );
- ASSERT( !regex.matchesSingleElement( notMatch.firstElement() ) );
- }
-
- TEST( RegexMatchExpression, MatchesElementDotAllOff ) {
- BSONObj match = BSON( "x" << "a b" );
- BSONObj notMatch = BSON( "x" << "a\nb" );
- RegexMatchExpression regex;
- ASSERT( regex.init( "", "a.b", "" ).isOK() );
- ASSERT( regex.matchesSingleElement( match.firstElement() ) );
- ASSERT( !regex.matchesSingleElement( notMatch.firstElement() ) );
- }
-
- TEST( RegexMatchExpression, MatchesElementDotAllOn ) {
- BSONObj match = BSON( "x" << "a b" );
- BSONObj matchDotAll = BSON( "x" << "a\nb" );
- BSONObj notMatch = BSON( "x" << "ab" );
- RegexMatchExpression regex;
- ASSERT( regex.init( "", "a.b", "s" ).isOK() );
- ASSERT( regex.matchesSingleElement( match.firstElement() ) );
- ASSERT( regex.matchesSingleElement( matchDotAll.firstElement() ) );
- ASSERT( !regex.matchesSingleElement( notMatch.firstElement() ) );
- }
-
- TEST( RegexMatchExpression, MatchesElementMultipleFlags ) {
- BSONObj matchMultilineDotAll = BSON( "x" << "\na\nb" );
- RegexMatchExpression regex;
- ASSERT( regex.init( "", "^a.b", "ms" ).isOK() );
- ASSERT( regex.matchesSingleElement( matchMultilineDotAll.firstElement() ) );
- }
-
- TEST( RegexMatchExpression, MatchesElementRegexType ) {
- BSONObj match = BSONObjBuilder().appendRegex( "x", "yz", "i" ).obj();
- BSONObj notMatchPattern = BSONObjBuilder().appendRegex( "x", "r", "i" ).obj();
- BSONObj notMatchFlags = BSONObjBuilder().appendRegex( "x", "yz", "s" ).obj();
- RegexMatchExpression regex;
- ASSERT( regex.init( "", "yz", "i" ).isOK() );
- ASSERT( regex.matchesSingleElement( match.firstElement() ) );
- ASSERT( !regex.matchesSingleElement( notMatchPattern.firstElement() ) );
- ASSERT( !regex.matchesSingleElement( notMatchFlags.firstElement() ) );
- }
-
- TEST( RegexMatchExpression, MatchesElementSymbolType ) {
- BSONObj match = BSONObjBuilder().appendSymbol( "x", "yz" ).obj();
- BSONObj notMatch = BSONObjBuilder().appendSymbol( "x", "gg" ).obj();
- RegexMatchExpression regex;
- ASSERT( regex.init( "", "yz", "" ).isOK() );
- ASSERT( regex.matchesSingleElement( match.firstElement() ) );
- ASSERT( !regex.matchesSingleElement( notMatch.firstElement() ) );
- }
-
- TEST( RegexMatchExpression, MatchesElementWrongType ) {
- BSONObj notMatchInt = BSON( "x" << 1 );
- BSONObj notMatchBool = BSON( "x" << true );
- RegexMatchExpression regex;
- ASSERT( regex.init( "", "1", "" ).isOK() );
- ASSERT( !regex.matchesSingleElement( notMatchInt.firstElement() ) );
- ASSERT( !regex.matchesSingleElement( notMatchBool.firstElement() ) );
- }
-
- TEST( RegexMatchExpression, MatchesElementUtf8 ) {
- BSONObj multiByteCharacter = BSON( "x" << "\xc2\xa5" );
- RegexMatchExpression regex;
- ASSERT( regex.init( "", "^.$", "" ).isOK() );
- ASSERT( regex.matchesSingleElement( multiByteCharacter.firstElement() ) );
- }
-
- TEST( RegexMatchExpression, MatchesScalar ) {
- RegexMatchExpression regex;
- ASSERT( regex.init( "a", "b", "" ).isOK() );
- ASSERT( regex.matchesBSON( BSON( "a" << "b" ), NULL ) );
- ASSERT( !regex.matchesBSON( BSON( "a" << "c" ), NULL ) );
- }
-
- TEST( RegexMatchExpression, MatchesArrayValue ) {
- RegexMatchExpression regex;
- ASSERT( regex.init( "a", "b", "" ).isOK() );
- ASSERT( regex.matchesBSON( BSON( "a" << BSON_ARRAY( "c" << "b" ) ), NULL ) );
- ASSERT( !regex.matchesBSON( BSON( "a" << BSON_ARRAY( "d" << "c" ) ), NULL ) );
- }
-
- TEST( RegexMatchExpression, MatchesNull ) {
- RegexMatchExpression regex;
- ASSERT( regex.init( "a", "b", "" ).isOK() );
- ASSERT( !regex.matchesBSON( BSONObj(), NULL ) );
- ASSERT( !regex.matchesBSON( BSON( "a" << BSONNULL ), NULL ) );
- }
-
- TEST( RegexMatchExpression, ElemMatchKey ) {
- RegexMatchExpression regex;
- ASSERT( regex.init( "a", "b", "" ).isOK() );
- MatchDetails details;
- details.requestElemMatchKey();
- ASSERT( !regex.matchesBSON( BSON( "a" << "c" ), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( regex.matchesBSON( BSON( "a" << "b" ), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( regex.matchesBSON( BSON( "a" << BSON_ARRAY( "c" << "b" ) ), &details ) );
- ASSERT( details.hasElemMatchKey() );
- ASSERT_EQUALS( "1", details.elemMatchKey() );
- }
-
- TEST( RegexMatchExpression, Equality1 ) {
- RegexMatchExpression r1;
- RegexMatchExpression r2;
- RegexMatchExpression r3;
- RegexMatchExpression r4;
- ASSERT( r1.init( "a" , "b" ,"" ).isOK() );
- ASSERT( r2.init( "a" , "b" ,"x" ).isOK() );
- ASSERT( r3.init( "a" , "c" ,"" ).isOK() );
- ASSERT( r4.init( "b" , "b" ,"" ).isOK() );
-
- ASSERT( r1.equivalent( &r1 ) );
- ASSERT( !r1.equivalent( &r2 ) );
- ASSERT( !r1.equivalent( &r3 ) );
- ASSERT( !r1.equivalent( &r4 ) );
- }
-
- /**
- TEST( RegexMatchExpression, MatchesIndexKeyScalar ) {
- RegexMatchExpression regex;
- ASSERT( regex.init( "a", "xyz", "" ).isOK() );
- IndexSpec indexSpec( BSON( "a" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- regex.matchesIndexKey( BSON( "" << "z xyz" ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- regex.matchesIndexKey( BSON( "" << "xy" ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- regex.matchesIndexKey( BSON( "" << BSON_ARRAY( "xyz" ) ), indexSpec ) );
- }
-
- TEST( RegexMatchExpression, MatchesIndexKeyMissing ) {
- RegexMatchExpression regex;
- ASSERT( regex.init( "a", "xyz", "" ).isOK() );
- IndexSpec indexSpec( BSON( "b" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- regex.matchesIndexKey( BSON( "" << "z xyz" ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- regex.matchesIndexKey( BSON( "" << "xy" ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- regex.matchesIndexKey( BSON( "" << BSON_ARRAY( 8 << "xyz" ) ), indexSpec ) );
- }
-
- TEST( RegexMatchExpression, MatchesIndexKeyArrayValue ) {
- RegexMatchExpression regex;
- ASSERT( regex.init( "a", "xyz", "" ).isOK() );
- IndexSpec indexSpec( BSON( "loc" << "mockarrayvalue" << "a" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- regex.matchesIndexKey( BSON( "" << "dummygeohash" << "" << "xyz" ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- regex.matchesIndexKey( BSON( "" << "dummygeohash" << "" << "z" ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- regex.matchesIndexKey( BSON( "" << "dummygeohash" <<
- "" << BSON_ARRAY( "r" << 6 << "xyz" ) ), indexSpec ) );
- }
- */
-
- TEST( ModMatchExpression, MatchesElement ) {
- BSONObj match = BSON( "a" << 1 );
- BSONObj largerMatch = BSON( "a" << 4.0 );
- BSONObj longLongMatch = BSON( "a" << 68719476736LL );
- BSONObj notMatch = BSON( "a" << 6 );
- BSONObj negativeNotMatch = BSON( "a" << -2 );
- ModMatchExpression mod;
- ASSERT( mod.init( "", 3, 1 ).isOK() );
- ASSERT( mod.matchesSingleElement( match.firstElement() ) );
- ASSERT( mod.matchesSingleElement( largerMatch.firstElement() ) );
- ASSERT( mod.matchesSingleElement( longLongMatch.firstElement() ) );
- ASSERT( !mod.matchesSingleElement( notMatch.firstElement() ) );
- ASSERT( !mod.matchesSingleElement( negativeNotMatch.firstElement() ) );
- }
-
- TEST( ModMatchExpression, ZeroDivisor ) {
- ModMatchExpression mod;
- ASSERT( !mod.init( "", 0, 1 ).isOK() );
- }
-
- TEST( ModMatchExpression, MatchesScalar ) {
- ModMatchExpression mod;
- ASSERT( mod.init( "a", 5, 2 ).isOK() );
- ASSERT( mod.matchesBSON( BSON( "a" << 7.0 ), NULL ) );
- ASSERT( !mod.matchesBSON( BSON( "a" << 4 ), NULL ) );
- }
-
- TEST( ModMatchExpression, MatchesArrayValue ) {
- ModMatchExpression mod;
- ASSERT( mod.init( "a", 5, 2 ).isOK() );
- ASSERT( mod.matchesBSON( BSON( "a" << BSON_ARRAY( 5 << 12LL ) ), NULL ) );
- ASSERT( !mod.matchesBSON( BSON( "a" << BSON_ARRAY( 6 << 8 ) ), NULL ) );
- }
-
- TEST( ModMatchExpression, MatchesNull ) {
- ModMatchExpression mod;
- ASSERT( mod.init( "a", 5, 2 ).isOK() );
- ASSERT( !mod.matchesBSON( BSONObj(), NULL ) );
- ASSERT( !mod.matchesBSON( BSON( "a" << BSONNULL ), NULL ) );
- }
-
- TEST( ModMatchExpression, ElemMatchKey ) {
- ModMatchExpression mod;
- ASSERT( mod.init( "a", 5, 2 ).isOK() );
- MatchDetails details;
- details.requestElemMatchKey();
- ASSERT( !mod.matchesBSON( BSON( "a" << 4 ), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( mod.matchesBSON( BSON( "a" << 2 ), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( mod.matchesBSON( BSON( "a" << BSON_ARRAY( 1 << 2 << 5 ) ), &details ) );
- ASSERT( details.hasElemMatchKey() );
- ASSERT_EQUALS( "1", details.elemMatchKey() );
- }
-
- TEST( ModMatchExpression, Equality1 ) {
- ModMatchExpression m1;
- ModMatchExpression m2;
- ModMatchExpression m3;
- ModMatchExpression m4;
-
- m1.init( "a" , 1 , 2 );
- m2.init( "a" , 2 , 2 );
- m3.init( "a" , 1 , 1 );
- m4.init( "b" , 1 , 2 );
-
- ASSERT( m1.equivalent( &m1 ) );
- ASSERT( !m1.equivalent( &m2 ) );
- ASSERT( !m1.equivalent( &m3 ) );
- ASSERT( !m1.equivalent( &m4 ) );
- }
-
- /**
- TEST( ModMatchExpression, MatchesIndexKey ) {
- BSONObj operand = BSON( "$mod" << BSON_ARRAY( 2 << 1 ) );
- ModMatchExpression mod;
- ASSERT( mod.init( "a", operand[ "$mod" ] ).isOK() );
- IndexSpec indexSpec( BSON( "a" << 1 ) );
- BSONObj indexKey = BSON( "" << 1 );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- mod.matchesIndexKey( indexKey, indexSpec ) );
- }
- */
-
- TEST( ExistsMatchExpression, MatchesElement ) {
- BSONObj existsInt = BSON( "a" << 5 );
- BSONObj existsNull = BSON( "a" << BSONNULL );
- BSONObj doesntExist = BSONObj();
- ExistsMatchExpression exists;
- ASSERT( exists.init( "" ).isOK() );
- ASSERT( exists.matchesSingleElement( existsInt.firstElement() ) );
- ASSERT( exists.matchesSingleElement( existsNull.firstElement() ) );
- ASSERT( !exists.matchesSingleElement( doesntExist.firstElement() ) );
- }
-
- TEST( ExistsMatchExpression, MatchesElementExistsTrueValue ) {
- BSONObj exists = BSON( "a" << 5 );
- BSONObj missing = BSONObj();
- ExistsMatchExpression existsTrueValue;
- ASSERT( existsTrueValue.init( "" ).isOK() );
- ASSERT( existsTrueValue.matchesSingleElement( exists.firstElement() ) );
- ASSERT( !existsTrueValue.matchesSingleElement( missing.firstElement() ) );
- }
-
- TEST( ExistsMatchExpression, MatchesScalar ) {
- ExistsMatchExpression exists;
- ASSERT( exists.init( "a" ).isOK() );
- ASSERT( exists.matchesBSON( BSON( "a" << 1 ), NULL ) );
- ASSERT( exists.matchesBSON( BSON( "a" << BSONNULL ), NULL ) );
- ASSERT( !exists.matchesBSON( BSON( "b" << 1 ), NULL ) );
- }
-
- TEST( ExistsMatchExpression, MatchesArray ) {
- ExistsMatchExpression exists;
- ASSERT( exists.init( "a" ).isOK() );
- ASSERT( exists.matchesBSON( BSON( "a" << BSON_ARRAY( 4 << 5.5 ) ), NULL ) );
- }
-
- TEST( ExistsMatchExpression, ElemMatchKey ) {
- ExistsMatchExpression exists;
- ASSERT( exists.init( "a.b" ).isOK() );
- MatchDetails details;
- details.requestElemMatchKey();
- ASSERT( !exists.matchesBSON( BSON( "a" << 1 ), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( exists.matchesBSON( BSON( "a" << BSON( "b" << 6 ) ), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( exists.matchesBSON( BSON( "a" << BSON_ARRAY( 2 << BSON( "b" << 7 ) ) ), &details ) );
- ASSERT( details.hasElemMatchKey() );
- ASSERT_EQUALS( "1", details.elemMatchKey() );
- }
-
- TEST( ExistsMatchExpression, Equivalent ) {
- ExistsMatchExpression e1;
- ExistsMatchExpression e2;
- e1.init( "a" );
- e2.init( "b" );
-
- ASSERT( e1.equivalent( &e1 ) );
- ASSERT( !e1.equivalent( &e2 ) );
- }
-
- /**
- TEST( ExistsMatchExpression, MatchesIndexKey ) {
- BSONObj operand = BSON( "$exists" << true );
- ExistsMatchExpression exists;
- ASSERT( exists.init( "a", operand[ "$exists" ] ).isOK() );
- IndexSpec indexSpec( BSON( "a" << 1 ) );
- BSONObj indexKey = BSON( "" << 1 );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- exists.matchesIndexKey( indexKey, indexSpec ) );
- }
- */
-
-
-
- TEST( TypeMatchExpression, MatchesElementStringType ) {
- BSONObj match = BSON( "a" << "abc" );
- BSONObj notMatch = BSON( "a" << 5 );
- TypeMatchExpression type;
- ASSERT( type.init( "", String ).isOK() );
- ASSERT( type.matchesSingleElement( match[ "a" ] ) );
- ASSERT( !type.matchesSingleElement( notMatch[ "a" ] ) );
- }
-
- TEST( TypeMatchExpression, MatchesElementNullType ) {
- BSONObj match = BSON( "a" << BSONNULL );
- BSONObj notMatch = BSON( "a" << "abc" );
- TypeMatchExpression type;
- ASSERT( type.init( "", jstNULL ).isOK() );
- ASSERT( type.matchesSingleElement( match[ "a" ] ) );
- ASSERT( !type.matchesSingleElement( notMatch[ "a" ] ) );
- }
-
- TEST( TypeMatchExpression, InvalidTypeMatchExpressionerand ) {
- // If the provided type number is not a valid BSONType, it is not a parse error. The
- // operator will simply not match anything.
- BSONObj notMatch1 = BSON( "a" << BSONNULL );
- BSONObj notMatch2 = BSON( "a" << "abc" );
- TypeMatchExpression type;
- ASSERT( type.init( "", JSTypeMax + 1 ).isOK() );
- ASSERT( !type.matchesSingleElement( notMatch1[ "a" ] ) );
- ASSERT( !type.matchesSingleElement( notMatch2[ "a" ] ) );
- }
-
- TEST( TypeMatchExpression, MatchesScalar ) {
- TypeMatchExpression type;
- ASSERT( type.init( "a", Bool ).isOK() );
- ASSERT( type.matchesBSON( BSON( "a" << true ), NULL ) );
- ASSERT( !type.matchesBSON( BSON( "a" << 1 ), NULL ) );
- }
-
- TEST( TypeMatchExpression, MatchesArray ) {
- TypeMatchExpression type;
- ASSERT( type.init( "a", NumberInt ).isOK() );
- ASSERT( type.matchesBSON( BSON( "a" << BSON_ARRAY( 4 ) ), NULL ) );
- ASSERT( type.matchesBSON( BSON( "a" << BSON_ARRAY( 4 << "a" ) ), NULL ) );
- ASSERT( type.matchesBSON( BSON( "a" << BSON_ARRAY( "a" << 4 ) ), NULL ) );
- ASSERT( !type.matchesBSON( BSON( "a" << BSON_ARRAY( "a" ) ), NULL ) );
- ASSERT( !type.matchesBSON( BSON( "a" << BSON_ARRAY( BSON_ARRAY( 4 ) ) ), NULL ) );
- }
-
- TEST( TypeMatchExpression, MatchesOuterArray ) {
- TypeMatchExpression type;
- ASSERT( type.init( "a", Array ).isOK() );
- // The outer array is not matched.
- ASSERT( !type.matchesBSON( BSON( "a" << BSONArray() ), NULL ) );
- ASSERT( !type.matchesBSON( BSON( "a" << BSON_ARRAY( 4 << "a" ) ), NULL ) );
- ASSERT( type.matchesBSON( BSON( "a" << BSON_ARRAY( BSONArray() << 2 ) ), NULL ) );
- ASSERT( !type.matchesBSON( BSON( "a" << "bar" ), NULL ) );
- }
-
- TEST( TypeMatchExpression, MatchesObject ) {
- TypeMatchExpression type;
- ASSERT( type.init( "a", Object ).isOK() );
- ASSERT( type.matchesBSON( BSON( "a" << BSON( "b" << 1 ) ), NULL ) );
- ASSERT( !type.matchesBSON( BSON( "a" << 1 ), NULL ) );
- }
-
- TEST( TypeMatchExpression, MatchesDotNotationFieldObject ) {
- TypeMatchExpression type;
- ASSERT( type.init( "a.b", Object ).isOK() );
- ASSERT( type.matchesBSON( BSON( "a" << BSON( "b" << BSON( "c" << 1 ) ) ), NULL ) );
- ASSERT( !type.matchesBSON( BSON( "a" << BSON( "b" << 1 ) ), NULL ) );
- }
-
- TEST( TypeMatchExpression, MatchesDotNotationArrayElementArray ) {
- TypeMatchExpression type;
- ASSERT( type.init( "a.0", Array ).isOK() );
- ASSERT( type.matchesBSON( BSON( "a" << BSON_ARRAY( BSON_ARRAY( 1 ) ) ), NULL ) );
- ASSERT( !type.matchesBSON( BSON( "a" << BSON_ARRAY( "b" ) ), NULL ) );
- }
-
- TEST( TypeMatchExpression, MatchesDotNotationArrayElementScalar ) {
- TypeMatchExpression type;
- ASSERT( type.init( "a.0", String ).isOK() );
- ASSERT( type.matchesBSON( BSON( "a" << BSON_ARRAY( "b" ) ), NULL ) );
- ASSERT( !type.matchesBSON( BSON( "a" << BSON_ARRAY( 1 ) ), NULL ) );
- }
-
- TEST( TypeMatchExpression, MatchesDotNotationArrayElementObject ) {
- TypeMatchExpression type;
- ASSERT( type.init( "a.0", Object ).isOK() );
- ASSERT( type.matchesBSON( BSON( "a" << BSON_ARRAY( BSON( "b" << 1 ) ) ), NULL ) );
- ASSERT( !type.matchesBSON( BSON( "a" << BSON_ARRAY( 1 ) ), NULL ) );
- }
-
- TEST( TypeMatchExpression, MatchesNull ) {
- TypeMatchExpression type;
- ASSERT( type.init( "a", jstNULL ).isOK() );
- ASSERT( type.matchesBSON( BSON( "a" << BSONNULL ), NULL ) );
- ASSERT( !type.matchesBSON( BSON( "a" << 4 ), NULL ) );
- ASSERT( !type.matchesBSON( BSONObj(), NULL ) );
- }
-
- TEST( TypeMatchExpression, ElemMatchKey ) {
- TypeMatchExpression type;
- ASSERT( type.init( "a.b", String ).isOK() );
- MatchDetails details;
- details.requestElemMatchKey();
- ASSERT( !type.matchesBSON( BSON( "a" << 1 ), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( type.matchesBSON( BSON( "a" << BSON( "b" << "string" ) ), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( type.matchesBSON( BSON( "a" << BSON( "b" << BSON_ARRAY( "string" ) ) ), &details ) );
- ASSERT( details.hasElemMatchKey() );
- ASSERT_EQUALS( "0", details.elemMatchKey() );
- ASSERT( type.matchesBSON( BSON( "a" <<
- BSON_ARRAY( 2 <<
- BSON( "b" << BSON_ARRAY( "string" ) ) ) ),
- &details ) );
- ASSERT( details.hasElemMatchKey() );
- ASSERT_EQUALS( "1", details.elemMatchKey() );
- }
-
- TEST( TypeMatchExpression, Equivalent ) {
- TypeMatchExpression e1;
- TypeMatchExpression e2;
- TypeMatchExpression e3;
- e1.init( "a", String );
- e2.init( "a", NumberDouble );
- e3.init( "b", String );
-
- ASSERT( e1.equivalent( &e1 ) );
- ASSERT( !e1.equivalent( &e2 ) );
- ASSERT( !e1.equivalent( &e3 ) );
- }
-
-
- /**
- TEST( TypeMatchExpression, MatchesIndexKey ) {
- BSONObj operand = BSON( "$type" << 2 );
- TypeMatchExpression type;
- ASSERT( type.init( "a", operand[ "$type" ] ).isOK() );
- IndexSpec indexSpec( BSON( "a" << 1 ) );
- BSONObj indexKey = BSON( "" << "q" );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- type.matchesIndexKey( indexKey, indexSpec ) );
- }
- */
-
-
- TEST( InMatchExpression, MatchesElementSingle ) {
- BSONArray operand = BSON_ARRAY( 1 );
- BSONObj match = BSON( "a" << 1 );
- BSONObj notMatch = BSON( "a" << 2 );
- InMatchExpression in;
- in.getArrayFilterEntries()->addEquality( operand.firstElement() );
- ASSERT( in.matchesSingleElement( match[ "a" ] ) );
- ASSERT( !in.matchesSingleElement( notMatch[ "a" ] ) );
- }
-
- TEST( InMatchExpression, MatchesEmpty ) {
- InMatchExpression in;
- in.init( "a" );
-
- BSONObj notMatch = BSON( "a" << 2 );
- ASSERT( !in.matchesSingleElement( notMatch[ "a" ] ) );
- ASSERT( !in.matchesBSON( BSON( "a" << 1 ), NULL ) );
- ASSERT( !in.matchesBSON( BSONObj(), NULL ) );
- }
-
- TEST( InMatchExpression, MatchesElementMultiple ) {
- BSONObj operand = BSON_ARRAY( 1 << "r" << true << 1 );
- InMatchExpression in;
- in.getArrayFilterEntries()->addEquality( operand[0] );
- in.getArrayFilterEntries()->addEquality( operand[1] );
- in.getArrayFilterEntries()->addEquality( operand[2] );
- in.getArrayFilterEntries()->addEquality( operand[3] );
-
- BSONObj matchFirst = BSON( "a" << 1 );
- BSONObj matchSecond = BSON( "a" << "r" );
- BSONObj matchThird = BSON( "a" << true );
- BSONObj notMatch = BSON( "a" << false );
- ASSERT( in.matchesSingleElement( matchFirst[ "a" ] ) );
- ASSERT( in.matchesSingleElement( matchSecond[ "a" ] ) );
- ASSERT( in.matchesSingleElement( matchThird[ "a" ] ) );
- ASSERT( !in.matchesSingleElement( notMatch[ "a" ] ) );
- }
-
-
- TEST( InMatchExpression, MatchesScalar ) {
- BSONObj operand = BSON_ARRAY( 5 );
- InMatchExpression in;
- in.init( "a" );
- in.getArrayFilterEntries()->addEquality( operand.firstElement() );
-
- ASSERT( in.matchesBSON( BSON( "a" << 5.0 ), NULL ) );
- ASSERT( !in.matchesBSON( BSON( "a" << 4 ), NULL ) );
- }
-
- TEST( InMatchExpression, MatchesArrayValue ) {
- BSONObj operand = BSON_ARRAY( 5 );
- InMatchExpression in;
- in.init( "a" );
- in.getArrayFilterEntries()->addEquality( operand.firstElement() );
-
- ASSERT( in.matchesBSON( BSON( "a" << BSON_ARRAY( 5.0 << 6 ) ), NULL ) );
- ASSERT( !in.matchesBSON( BSON( "a" << BSON_ARRAY( 6 << 7 ) ), NULL ) );
- ASSERT( !in.matchesBSON( BSON( "a" << BSON_ARRAY( BSON_ARRAY( 5 ) ) ), NULL ) );
- }
-
- TEST( InMatchExpression, MatchesNull ) {
- BSONObj operand = BSON_ARRAY( BSONNULL );
-
- InMatchExpression in;
- in.init( "a" );
- in.getArrayFilterEntries()->addEquality( operand.firstElement() );
-
- ASSERT( in.matchesBSON( BSONObj(), NULL ) );
- ASSERT( in.matchesBSON( BSON( "a" << BSONNULL ), NULL ) );
- ASSERT( !in.matchesBSON( BSON( "a" << 4 ), NULL ) );
- // A non-existent field is treated same way as an empty bson object
- ASSERT( in.matchesBSON( BSON( "b" << 4 ), NULL ) );
- }
-
- TEST( InMatchExpression, MatchesUndefined ) {
- BSONObj operand = BSON_ARRAY( BSONUndefined );
-
- InMatchExpression in;
- in.init( "a" );
- Status s = in.getArrayFilterEntries()->addEquality( operand.firstElement() );
- ASSERT_NOT_OK(s);
- }
-
- TEST( InMatchExpression, MatchesMinKey ) {
- BSONObj operand = BSON_ARRAY( MinKey );
- InMatchExpression in;
- in.init( "a" );
- in.getArrayFilterEntries()->addEquality( operand.firstElement() );
-
- ASSERT( in.matchesBSON( BSON( "a" << MinKey ), NULL ) );
- ASSERT( !in.matchesBSON( BSON( "a" << MaxKey ), NULL ) );
- ASSERT( !in.matchesBSON( BSON( "a" << 4 ), NULL ) );
- }
-
- TEST( InMatchExpression, MatchesMaxKey ) {
- BSONObj operand = BSON_ARRAY( MaxKey );
- InMatchExpression in;
- in.init( "a" );
- in.getArrayFilterEntries()->addEquality( operand.firstElement() );
-
- ASSERT( in.matchesBSON( BSON( "a" << MaxKey ), NULL ) );
- ASSERT( !in.matchesBSON( BSON( "a" << MinKey ), NULL ) );
- ASSERT( !in.matchesBSON( BSON( "a" << 4 ), NULL ) );
- }
-
- TEST( InMatchExpression, MatchesFullArray ) {
- BSONObj operand = BSON_ARRAY( BSON_ARRAY( 1 << 2 ) << 4 << 5 );
- InMatchExpression in;
- in.init( "a" );
- in.getArrayFilterEntries()->addEquality( operand[0] );
- in.getArrayFilterEntries()->addEquality( operand[1] );
- in.getArrayFilterEntries()->addEquality( operand[2] );
-
- ASSERT( in.matchesBSON( BSON( "a" << BSON_ARRAY( 1 << 2 ) ), NULL ) );
- ASSERT( !in.matchesBSON( BSON( "a" << BSON_ARRAY( 1 << 2 << 3 ) ), NULL ) );
- ASSERT( !in.matchesBSON( BSON( "a" << BSON_ARRAY( 1 ) ), NULL ) );
- ASSERT( !in.matchesBSON( BSON( "a" << 1 ), NULL ) );
- }
-
- TEST( InMatchExpression, ElemMatchKey ) {
- BSONObj operand = BSON_ARRAY( 5 << 2 );
- InMatchExpression in;
- in.init( "a" );
- in.getArrayFilterEntries()->addEquality( operand[0] );
- in.getArrayFilterEntries()->addEquality( operand[1] );
-
- MatchDetails details;
- details.requestElemMatchKey();
- ASSERT( !in.matchesBSON( BSON( "a" << 4 ), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( in.matchesBSON( BSON( "a" << 5 ), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( in.matchesBSON( BSON( "a" << BSON_ARRAY( 1 << 2 << 5 ) ), &details ) );
- ASSERT( details.hasElemMatchKey() );
- ASSERT_EQUALS( "1", details.elemMatchKey() );
- }
-
- /**
- TEST( InMatchExpression, MatchesIndexKeyScalar ) {
- BSONObj operand = BSON( "$in" << BSON_ARRAY( 6 << 5 ) );
- InMatchExpression in;
- ASSERT( in.init( "a", operand[ "$in" ] ).isOK() );
- IndexSpec indexSpec( BSON( "a" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- in.matchesIndexKey( BSON( "" << 6 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- in.matchesIndexKey( BSON( "" << 5 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- in.matchesIndexKey( BSON( "" << 4 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- in.matchesIndexKey( BSON( "" << BSON_ARRAY( 6 ) ), indexSpec ) );
- }
-
- TEST( InMatchExpression, MatchesIndexKeyMissing ) {
- BSONObj operand = BSON( "$in" << BSON_ARRAY( 6 ) );
- ComparisonMatchExpression eq
- ASSERT( eq.init( "a", operand[ "$in" ] ).isOK() );
- IndexSpec indexSpec( BSON( "b" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- eq.matchesIndexKey( BSON( "" << 6 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- eq.matchesIndexKey( BSON( "" << 4 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- eq.matchesIndexKey( BSON( "" << BSON_ARRAY( 8 << 6 ) ), indexSpec ) );
- }
-
- TEST( InMatchExpression, MatchesIndexKeyArray ) {
- BSONObj operand = BSON( "$in" << BSON_ARRAY( 4 << BSON_ARRAY( 5 ) ) );
- InMatchExpression in;
- ASSERT( in.init( "a", operand[ "$in" ] ).isOK() );
- IndexSpec indexSpec( BSON( "a" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- in.matchesIndexKey( BSON( "" << 4 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- in.matchesIndexKey( BSON( "" << 5 ), indexSpec ) );
- }
-
- TEST( InMatchExpression, MatchesIndexKeyArrayValue ) {
- BSONObjBuilder inArray;
- inArray.append( "0", 4 ).append( "1", 5 ).appendRegex( "2", "abc", "" );
- BSONObj operand = BSONObjBuilder().appendArray( "$in", inArray.obj() ).obj();
- InMatchExpression in;
- ASSERT( in.init( "a", operand[ "$in" ] ).isOK() );
- IndexSpec indexSpec( BSON( "loc" << "mockarrayvalue" << "a" << 1 ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- in.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 4 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- in.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 6 ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- in.matchesIndexKey( BSON( "" << "dummygeohash" << "" << "abcd" ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- in.matchesIndexKey( BSONObjBuilder()
- .append( "", "dummygeohash" )
- .appendRegex( "", "abc", "" ).obj(),
- indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- in.matchesIndexKey( BSON( "" << "dummygeohash" << "" << "ab" ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- in.matchesIndexKey( BSON( "" << "dummygeohash" <<
- "" << BSON_ARRAY( 8 << 5 ) ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- in.matchesIndexKey( BSON( "" << "dummygeohash" <<
- "" << BSON_ARRAY( 8 << 9 ) ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_True ==
- in.matchesIndexKey( BSON( "" << "dummygeohash" <<
- "" << BSON_ARRAY( 8 << "abc" ) ), indexSpec ) );
- ASSERT( MatchMatchExpression::PartialMatchResult_False ==
- in.matchesIndexKey( BSON( "" << "dummygeohash" <<
- "" << BSON_ARRAY( 8 << "ac" ) ), indexSpec ) );
- }
- */
+using std::string;
+TEST(EqOp, MatchesElement) {
+ BSONObj operand = BSON("a" << 5);
+ BSONObj match = BSON("a" << 5.0);
+ BSONObj notMatch = BSON("a" << 6);
+
+ EqualityMatchExpression eq;
+ eq.init("", operand["a"]);
+ ASSERT(eq.matchesSingleElement(match.firstElement()));
+ ASSERT(!eq.matchesSingleElement(notMatch.firstElement()));
+
+ ASSERT(eq.equivalent(&eq));
+}
+
+TEST(EqOp, InvalidEooOperand) {
+ BSONObj operand;
+ EqualityMatchExpression eq;
+ ASSERT(!eq.init("", operand.firstElement()).isOK());
+}
+
+TEST(EqOp, MatchesScalar) {
+ BSONObj operand = BSON("a" << 5);
+ EqualityMatchExpression eq;
+ eq.init("a", operand["a"]);
+ ASSERT(eq.matchesBSON(BSON("a" << 5.0), NULL));
+ ASSERT(!eq.matchesBSON(BSON("a" << 4), NULL));
+}
+
+TEST(EqOp, MatchesArrayValue) {
+ BSONObj operand = BSON("a" << 5);
+ EqualityMatchExpression eq;
+ eq.init("a", operand["a"]);
+ ASSERT(eq.matchesBSON(BSON("a" << BSON_ARRAY(5.0 << 6)), NULL));
+ ASSERT(!eq.matchesBSON(BSON("a" << BSON_ARRAY(6 << 7)), NULL));
+}
+
+TEST(EqOp, MatchesReferencedObjectValue) {
+ BSONObj operand = BSON("a.b" << 5);
+ EqualityMatchExpression eq;
+ eq.init("a.b", operand["a.b"]);
+ ASSERT(eq.matchesBSON(BSON("a" << BSON("b" << 5)), NULL));
+ ASSERT(eq.matchesBSON(BSON("a" << BSON("b" << BSON_ARRAY(5))), NULL));
+ ASSERT(eq.matchesBSON(BSON("a" << BSON_ARRAY(BSON("b" << 5))), NULL));
+}
+
+TEST(EqOp, MatchesReferencedArrayValue) {
+ BSONObj operand = BSON("a.0" << 5);
+ EqualityMatchExpression eq;
+ eq.init("a.0", operand["a.0"]);
+ ASSERT(eq.matchesBSON(BSON("a" << BSON_ARRAY(5)), NULL));
+ ASSERT(!eq.matchesBSON(BSON("a" << BSON_ARRAY(BSON_ARRAY(5))), NULL));
+}
+
+TEST(EqOp, MatchesNull) {
+ BSONObj operand = BSON("a" << BSONNULL);
+ EqualityMatchExpression eq;
+ eq.init("a", operand["a"]);
+ ASSERT(eq.matchesBSON(BSONObj(), NULL));
+ ASSERT(eq.matchesBSON(BSON("a" << BSONNULL), NULL));
+ ASSERT(!eq.matchesBSON(BSON("a" << 4), NULL));
+ // A non-existent field is treated same way as an empty bson object
+ ASSERT(eq.matchesBSON(BSON("b" << 4), NULL));
+}
+
+// This test documents how the matcher currently works,
+// not necessarily how it should work ideally.
+TEST(EqOp, MatchesNestedNull) {
+ BSONObj operand = BSON("a.b" << BSONNULL);
+ EqualityMatchExpression eq;
+ eq.init("a.b", operand["a.b"]);
+ // null matches any empty object that is on a subpath of a.b
+ ASSERT(eq.matchesBSON(BSONObj(), NULL));
+ ASSERT(eq.matchesBSON(BSON("a" << BSONObj()), NULL));
+ ASSERT(eq.matchesBSON(BSON("a" << BSON_ARRAY(BSONObj())), NULL));
+ ASSERT(eq.matchesBSON(BSON("a" << BSON("b" << BSONNULL)), NULL));
+ // b does not exist as an element in array under a.
+ ASSERT(!eq.matchesBSON(BSON("a" << BSONArray()), NULL));
+ ASSERT(!eq.matchesBSON(BSON("a" << BSON_ARRAY(BSONNULL)), NULL));
+ ASSERT(!eq.matchesBSON(BSON("a" << BSON_ARRAY(1 << 2)), NULL));
+ // a.b exists but is not null.
+ ASSERT(!eq.matchesBSON(BSON("a" << BSON("b" << 4)), NULL));
+ ASSERT(!eq.matchesBSON(BSON("a" << BSON("b" << BSONObj())), NULL));
+ // A non-existent field is treated same way as an empty bson object
+ ASSERT(eq.matchesBSON(BSON("b" << 4), NULL));
+}
+
+TEST(EqOp, MatchesMinKey) {
+ BSONObj operand = BSON("a" << MinKey);
+ EqualityMatchExpression eq;
+ eq.init("a", operand["a"]);
+ ASSERT(eq.matchesBSON(BSON("a" << MinKey), NULL));
+ ASSERT(!eq.matchesBSON(BSON("a" << MaxKey), NULL));
+ ASSERT(!eq.matchesBSON(BSON("a" << 4), NULL));
+}
+
+
+TEST(EqOp, MatchesMaxKey) {
+ BSONObj operand = BSON("a" << MaxKey);
+ EqualityMatchExpression eq;
+ ASSERT(eq.init("a", operand["a"]).isOK());
+ ASSERT(eq.matchesBSON(BSON("a" << MaxKey), NULL));
+ ASSERT(!eq.matchesBSON(BSON("a" << MinKey), NULL));
+ ASSERT(!eq.matchesBSON(BSON("a" << 4), NULL));
+}
+
+TEST(EqOp, MatchesFullArray) {
+ BSONObj operand = BSON("a" << BSON_ARRAY(1 << 2));
+ EqualityMatchExpression eq;
+ ASSERT(eq.init("a", operand["a"]).isOK());
+ ASSERT(eq.matchesBSON(BSON("a" << BSON_ARRAY(1 << 2)), NULL));
+ ASSERT(!eq.matchesBSON(BSON("a" << BSON_ARRAY(1 << 2 << 3)), NULL));
+ ASSERT(!eq.matchesBSON(BSON("a" << BSON_ARRAY(1)), NULL));
+ ASSERT(!eq.matchesBSON(BSON("a" << 1), NULL));
+}
+
+TEST(EqOp, MatchesThroughNestedArray) {
+ BSONObj operand = BSON("a.b.c.d" << 3);
+ EqualityMatchExpression eq;
+ eq.init("a.b.c.d", operand["a.b.c.d"]);
+ BSONObj obj = fromjson("{a:{b:[{c:[{d:1},{d:2}]},{c:[{d:3}]}]}}");
+ ASSERT(eq.matchesBSON(obj, NULL));
+}
+
+TEST(EqOp, ElemMatchKey) {
+ BSONObj operand = BSON("a" << 5);
+ EqualityMatchExpression eq;
+ ASSERT(eq.init("a", operand["a"]).isOK());
+ MatchDetails details;
+ details.requestElemMatchKey();
+ ASSERT(!eq.matchesBSON(BSON("a" << 4), &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(eq.matchesBSON(BSON("a" << 5), &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(eq.matchesBSON(BSON("a" << BSON_ARRAY(1 << 2 << 5)), &details));
+ ASSERT(details.hasElemMatchKey());
+ ASSERT_EQUALS("2", details.elemMatchKey());
+}
+
+// SERVER-14886: when an array is being traversed explictly at the same time that a nested array
+// is being traversed implicitly, the elemMatch key should refer to the offset of the array
+// being implicitly traversed.
+TEST(EqOp, ElemMatchKeyWithImplicitAndExplicitTraversal) {
+ BSONObj operand = BSON("a.0.b" << 3);
+ BSONElement operandFirstElt = operand.firstElement();
+ EqualityMatchExpression eq;
+ ASSERT(eq.init(operandFirstElt.fieldName(), operandFirstElt).isOK());
+ MatchDetails details;
+ details.requestElemMatchKey();
+ BSONObj obj = fromjson("{a: [{b: [2, 3]}, {b: [4, 5]}]}");
+ ASSERT(eq.matchesBSON(obj, &details));
+ ASSERT(details.hasElemMatchKey());
+ ASSERT_EQUALS("1", details.elemMatchKey());
+}
+
+TEST(EqOp, Equality1) {
+ EqualityMatchExpression eq1;
+ EqualityMatchExpression eq2;
+ EqualityMatchExpression eq3;
+
+ BSONObj operand = BSON("a" << 5 << "b" << 5 << "c" << 4);
+
+ eq1.init("a", operand["a"]);
+ eq2.init("a", operand["b"]);
+ eq3.init("c", operand["c"]);
+
+ ASSERT(eq1.equivalent(&eq1));
+ ASSERT(eq1.equivalent(&eq2));
+ ASSERT(!eq1.equivalent(&eq3));
+}
+
+/**
+ TEST( EqOp, MatchesIndexKeyScalar ) {
+ BSONObj operand = BSON( "a" << 6 );
+ EqualityMatchExpression eq;
+ ASSERT( eq.init( "a", operand[ "a" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "a" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ eq.matchesIndexKey( BSON( "" << 6 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ eq.matchesIndexKey( BSON( "" << 4 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ eq.matchesIndexKey( BSON( "" << BSON_ARRAY( 6 ) ), indexSpec ) );
+ }
+
+ TEST( EqOp, MatchesIndexKeyMissing ) {
+ BSONObj operand = BSON( "a" << 6 );
+ EqualityMatchExpression eq;
+ ASSERT( eq.init( "a", operand[ "a" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "b" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ eq.matchesIndexKey( BSON( "" << 6 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ eq.matchesIndexKey( BSON( "" << 4 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ eq.matchesIndexKey( BSON( "" << BSON_ARRAY( 8 << 6 ) ), indexSpec ) );
+ }
+
+ TEST( EqOp, MatchesIndexKeyArray ) {
+ BSONObj operand = BSON( "a" << BSON_ARRAY( 4 << 5 ) );
+ ComparisonMatchExpression eq
+ ASSERT( eq.init( "a", operand[ "a" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "a" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ eq.matchesIndexKey( BSON( "" << 4 ), indexSpec ) );
+ }
+
+ TEST( EqOp, MatchesIndexKeyArrayValue ) {
+ BSONObj operand = BSON( "a" << 6 );
+ ComparisonMatchExpression eq
+ ASSERT( eq.init( "a", operand[ "a" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "loc" << "mockarrayvalue" << "a" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ eq.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 6 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ eq.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 4 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ eq.matchesIndexKey( BSON( "" << "dummygeohash" <<
+ "" << BSON_ARRAY( 8 << 6 ) ), indexSpec ) );
+ }
+*/
+TEST(LtOp, MatchesElement) {
+ BSONObj operand = BSON("$lt" << 5);
+ BSONObj match = BSON("a" << 4.5);
+ BSONObj notMatch = BSON("a" << 6);
+ BSONObj notMatchEqual = BSON("a" << 5);
+ BSONObj notMatchWrongType = BSON("a"
+ << "foo");
+ LTMatchExpression lt;
+ ASSERT(lt.init("", operand["$lt"]).isOK());
+ ASSERT(lt.matchesSingleElement(match.firstElement()));
+ ASSERT(!lt.matchesSingleElement(notMatch.firstElement()));
+ ASSERT(!lt.matchesSingleElement(notMatchEqual.firstElement()));
+ ASSERT(!lt.matchesSingleElement(notMatchWrongType.firstElement()));
+}
+
+TEST(LtOp, InvalidEooOperand) {
+ BSONObj operand;
+ LTMatchExpression lt;
+ ASSERT(!lt.init("", operand.firstElement()).isOK());
+}
+
+TEST(LtOp, MatchesScalar) {
+ BSONObj operand = BSON("$lt" << 5);
+ LTMatchExpression lt;
+ ASSERT(lt.init("a", operand["$lt"]).isOK());
+ ASSERT(lt.matchesBSON(BSON("a" << 4.5), NULL));
+ ASSERT(!lt.matchesBSON(BSON("a" << 6), NULL));
+}
+
+TEST(LtOp, MatchesScalarEmptyKey) {
+ BSONObj operand = BSON("$lt" << 5);
+ LTMatchExpression lt;
+ ASSERT(lt.init("", operand["$lt"]).isOK());
+ ASSERT(lt.matchesBSON(BSON("" << 4.5), NULL));
+ ASSERT(!lt.matchesBSON(BSON("" << 6), NULL));
+}
+
+TEST(LtOp, MatchesArrayValue) {
+ BSONObj operand = BSON("$lt" << 5);
+ LTMatchExpression lt;
+ ASSERT(lt.init("a", operand["$lt"]).isOK());
+ ASSERT(lt.matchesBSON(BSON("a" << BSON_ARRAY(6 << 4.5)), NULL));
+ ASSERT(!lt.matchesBSON(BSON("a" << BSON_ARRAY(6 << 7)), NULL));
+}
+
+TEST(LtOp, MatchesWholeArray) {
+ BSONObj operand = BSON("$lt" << BSON_ARRAY(5));
+ LTMatchExpression lt;
+ ASSERT(lt.init("a", operand["$lt"]).isOK());
+ ASSERT(lt.matchesBSON(BSON("a" << BSON_ARRAY(4)), NULL));
+ ASSERT(!lt.matchesBSON(BSON("a" << BSON_ARRAY(5)), NULL));
+ ASSERT(!lt.matchesBSON(BSON("a" << BSON_ARRAY(6)), NULL));
+ // Nested array.
+ ASSERT(lt.matchesBSON(BSON("a" << BSON_ARRAY(BSON_ARRAY(4))), NULL));
+ ASSERT(!lt.matchesBSON(BSON("a" << BSON_ARRAY(BSON_ARRAY(5))), NULL));
+ ASSERT(!lt.matchesBSON(BSON("a" << BSON_ARRAY(BSON_ARRAY(6))), NULL));
+}
+
+TEST(LtOp, MatchesNull) {
+ BSONObj operand = BSON("$lt" << BSONNULL);
+ LTMatchExpression lt;
+ ASSERT(lt.init("a", operand["$lt"]).isOK());
+ ASSERT(!lt.matchesBSON(BSONObj(), NULL));
+ ASSERT(!lt.matchesBSON(BSON("a" << BSONNULL), NULL));
+ ASSERT(!lt.matchesBSON(BSON("a" << 4), NULL));
+ // A non-existent field is treated same way as an empty bson object
+ ASSERT(!lt.matchesBSON(BSON("b" << 4), NULL));
+}
+
+TEST(LtOp, MatchesDotNotationNull) {
+ BSONObj operand = BSON("$lt" << BSONNULL);
+ LTMatchExpression lt;
+ ASSERT(lt.init("a.b", operand["$lt"]).isOK());
+ ASSERT(!lt.matchesBSON(BSONObj(), NULL));
+ ASSERT(!lt.matchesBSON(BSON("a" << BSONNULL), NULL));
+ ASSERT(!lt.matchesBSON(BSON("a" << 4), NULL));
+ ASSERT(!lt.matchesBSON(BSON("a" << BSONObj()), NULL));
+ ASSERT(!lt.matchesBSON(BSON("a" << BSON_ARRAY(BSON("b" << BSONNULL))), NULL));
+ ASSERT(!lt.matchesBSON(BSON("a" << BSON_ARRAY(BSON("a" << 4) << BSON("b" << 4))), NULL));
+ ASSERT(!lt.matchesBSON(BSON("a" << BSON_ARRAY(4)), NULL));
+ ASSERT(!lt.matchesBSON(BSON("a" << BSON_ARRAY(BSON("b" << 4))), NULL));
+}
+
+TEST(LtOp, MatchesMinKey) {
+ BSONObj operand = BSON("a" << MinKey);
+ LTMatchExpression lt;
+ ASSERT(lt.init("a", operand["a"]).isOK());
+ ASSERT(!lt.matchesBSON(BSON("a" << MinKey), NULL));
+ ASSERT(!lt.matchesBSON(BSON("a" << MaxKey), NULL));
+ ASSERT(!lt.matchesBSON(BSON("a" << 4), NULL));
+}
+
+TEST(LtOp, MatchesMaxKey) {
+ BSONObj operand = BSON("a" << MaxKey);
+ LTMatchExpression lt;
+ ASSERT(lt.init("a", operand["a"]).isOK());
+ ASSERT(!lt.matchesBSON(BSON("a" << MaxKey), NULL));
+ ASSERT(lt.matchesBSON(BSON("a" << MinKey), NULL));
+ ASSERT(lt.matchesBSON(BSON("a" << 4), NULL));
+}
+
+TEST(LtOp, ElemMatchKey) {
+ BSONObj operand = BSON("$lt" << 5);
+ LTMatchExpression lt;
+ ASSERT(lt.init("a", operand["$lt"]).isOK());
+ MatchDetails details;
+ details.requestElemMatchKey();
+ ASSERT(!lt.matchesBSON(BSON("a" << 6), &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(lt.matchesBSON(BSON("a" << 4), &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(lt.matchesBSON(BSON("a" << BSON_ARRAY(6 << 2 << 5)), &details));
+ ASSERT(details.hasElemMatchKey());
+ ASSERT_EQUALS("1", details.elemMatchKey());
+}
+
+/**
+ TEST( LtOp, MatchesIndexKeyScalar ) {
+ BSONObj operand = BSON( "$lt" << 6 );
+ LtOp lt;
+ ASSERT( lt.init( "a", operand[ "$lt" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "a" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ lt.matchesIndexKey( BSON( "" << 3 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ lt.matchesIndexKey( BSON( "" << 6 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ lt.matchesIndexKey( BSON( "" << BSON_ARRAY( 5 ) ), indexSpec ) );
+ }
+
+ TEST( LtOp, MatchesIndexKeyMissing ) {
+ BSONObj operand = BSON( "$lt" << 6 );
+ LtOp lt;
+ ASSERT( lt.init( "a", operand[ "$lt" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "b" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ lt.matchesIndexKey( BSON( "" << 6 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ lt.matchesIndexKey( BSON( "" << 4 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ lt.matchesIndexKey( BSON( "" << BSON_ARRAY( 8 << 6 ) ), indexSpec ) );
+ }
+
+ TEST( LtOp, MatchesIndexKeyArray ) {
+ BSONObj operand = BSON( "$lt" << BSON_ARRAY( 4 << 5 ) );
+ LtOp lt;
+ ASSERT( lt.init( "a", operand[ "$lt" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "a" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ lt.matchesIndexKey( BSON( "" << 3 ), indexSpec ) );
+ }
+
+ TEST( LtOp, MatchesIndexKeyArrayValue ) {
+ BSONObj operand = BSON( "$lt" << 6 );
+ LtOp lt;
+ ASSERT( lt.init( "a", operand[ "$lt" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "loc" << "mockarrayvalue" << "a" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ lt.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 3 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ lt.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 6 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ lt.matchesIndexKey( BSON( "" << "dummygeohash" <<
+ "" << BSON_ARRAY( 8 << 6 << 4 ) ), indexSpec ) );
+ }
+*/
+TEST(LteOp, MatchesElement) {
+ BSONObj operand = BSON("$lte" << 5);
+ BSONObj match = BSON("a" << 4.5);
+ BSONObj equalMatch = BSON("a" << 5);
+ BSONObj notMatch = BSON("a" << 6);
+ BSONObj notMatchWrongType = BSON("a"
+ << "foo");
+ LTEMatchExpression lte;
+ ASSERT(lte.init("", operand["$lte"]).isOK());
+ ASSERT(lte.matchesSingleElement(match.firstElement()));
+ ASSERT(lte.matchesSingleElement(equalMatch.firstElement()));
+ ASSERT(!lte.matchesSingleElement(notMatch.firstElement()));
+ ASSERT(!lte.matchesSingleElement(notMatchWrongType.firstElement()));
+}
+
+TEST(LteOp, InvalidEooOperand) {
+ BSONObj operand;
+ LTEMatchExpression lte;
+ ASSERT(!lte.init("", operand.firstElement()).isOK());
+}
+
+TEST(LteOp, MatchesScalar) {
+ BSONObj operand = BSON("$lte" << 5);
+ LTEMatchExpression lte;
+ ASSERT(lte.init("a", operand["$lte"]).isOK());
+ ASSERT(lte.matchesBSON(BSON("a" << 4.5), NULL));
+ ASSERT(!lte.matchesBSON(BSON("a" << 6), NULL));
+}
+
+TEST(LteOp, MatchesArrayValue) {
+ BSONObj operand = BSON("$lte" << 5);
+ LTEMatchExpression lte;
+ ASSERT(lte.init("a", operand["$lte"]).isOK());
+ ASSERT(lte.matchesBSON(BSON("a" << BSON_ARRAY(6 << 4.5)), NULL));
+ ASSERT(!lte.matchesBSON(BSON("a" << BSON_ARRAY(6 << 7)), NULL));
+}
+
+TEST(LteOp, MatchesWholeArray) {
+ BSONObj operand = BSON("$lte" << BSON_ARRAY(5));
+ LTEMatchExpression lte;
+ ASSERT(lte.init("a", operand["$lte"]).isOK());
+ ASSERT(lte.matchesBSON(BSON("a" << BSON_ARRAY(4)), NULL));
+ ASSERT(lte.matchesBSON(BSON("a" << BSON_ARRAY(5)), NULL));
+ ASSERT(!lte.matchesBSON(BSON("a" << BSON_ARRAY(6)), NULL));
+ // Nested array.
+ ASSERT(lte.matchesBSON(BSON("a" << BSON_ARRAY(BSON_ARRAY(4))), NULL));
+ ASSERT(lte.matchesBSON(BSON("a" << BSON_ARRAY(BSON_ARRAY(5))), NULL));
+ ASSERT(!lte.matchesBSON(BSON("a" << BSON_ARRAY(BSON_ARRAY(6))), NULL));
+}
+
+TEST(LteOp, MatchesNull) {
+ BSONObj operand = BSON("$lte" << BSONNULL);
+ LTEMatchExpression lte;
+ ASSERT(lte.init("a", operand["$lte"]).isOK());
+ ASSERT(lte.matchesBSON(BSONObj(), NULL));
+ ASSERT(lte.matchesBSON(BSON("a" << BSONNULL), NULL));
+ ASSERT(!lte.matchesBSON(BSON("a" << 4), NULL));
+ // A non-existent field is treated same way as an empty bson object
+ ASSERT(lte.matchesBSON(BSON("b" << 4), NULL));
+}
+
+TEST(LteOp, MatchesDotNotationNull) {
+ BSONObj operand = BSON("$lte" << BSONNULL);
+ LTEMatchExpression lte;
+ ASSERT(lte.init("a.b", operand["$lte"]).isOK());
+ ASSERT(lte.matchesBSON(BSONObj(), NULL));
+ ASSERT(lte.matchesBSON(BSON("a" << BSONNULL), NULL));
+ ASSERT(lte.matchesBSON(BSON("a" << 4), NULL));
+ ASSERT(lte.matchesBSON(BSON("a" << BSONObj()), NULL));
+ ASSERT(lte.matchesBSON(BSON("a" << BSON_ARRAY(BSON("b" << BSONNULL))), NULL));
+ ASSERT(lte.matchesBSON(BSON("a" << BSON_ARRAY(BSON("a" << 4) << BSON("b" << 4))), NULL));
+ ASSERT(!lte.matchesBSON(BSON("a" << BSON_ARRAY(4)), NULL));
+ ASSERT(!lte.matchesBSON(BSON("a" << BSON_ARRAY(BSON("b" << 4))), NULL));
+}
+
+TEST(LteOp, MatchesMinKey) {
+ BSONObj operand = BSON("a" << MinKey);
+ LTEMatchExpression lte;
+ ASSERT(lte.init("a", operand["a"]).isOK());
+ ASSERT(lte.matchesBSON(BSON("a" << MinKey), NULL));
+ ASSERT(!lte.matchesBSON(BSON("a" << MaxKey), NULL));
+ ASSERT(!lte.matchesBSON(BSON("a" << 4), NULL));
+}
+
+TEST(LteOp, MatchesMaxKey) {
+ BSONObj operand = BSON("a" << MaxKey);
+ LTEMatchExpression lte;
+ ASSERT(lte.init("a", operand["a"]).isOK());
+ ASSERT(lte.matchesBSON(BSON("a" << MaxKey), NULL));
+ ASSERT(lte.matchesBSON(BSON("a" << MinKey), NULL));
+ ASSERT(lte.matchesBSON(BSON("a" << 4), NULL));
+}
+
+
+TEST(LteOp, ElemMatchKey) {
+ BSONObj operand = BSON("$lte" << 5);
+ LTEMatchExpression lte;
+ ASSERT(lte.init("a", operand["$lte"]).isOK());
+ MatchDetails details;
+ details.requestElemMatchKey();
+ ASSERT(!lte.matchesBSON(BSON("a" << 6), &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(lte.matchesBSON(BSON("a" << 4), &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(lte.matchesBSON(BSON("a" << BSON_ARRAY(6 << 2 << 5)), &details));
+ ASSERT(details.hasElemMatchKey());
+ ASSERT_EQUALS("1", details.elemMatchKey());
+}
+
+/**
+ TEST( LteOp, MatchesIndexKeyScalar ) {
+ BSONObj operand = BSON( "$lte" << 6 );
+ LteOp lte;
+ ASSERT( lte.init( "a", operand[ "$lte" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "a" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ lte.matchesIndexKey( BSON( "" << 6 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ lte.matchesIndexKey( BSON( "" << 7 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ lte.matchesIndexKey( BSON( "" << BSON_ARRAY( 5 ) ), indexSpec ) );
+ }
+
+ TEST( LteOp, MatchesIndexKeyMissing ) {
+ BSONObj operand = BSON( "$lte" << 6 );
+ LteOp lte;
+ ASSERT( lte.init( "a", operand[ "$lte" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "b" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ lte.matchesIndexKey( BSON( "" << 7 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ lte.matchesIndexKey( BSON( "" << 4 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ lte.matchesIndexKey( BSON( "" << BSON_ARRAY( 8 << 6 ) ), indexSpec ) );
+ }
+
+ TEST( LteOp, MatchesIndexKeyArray ) {
+ BSONObj operand = BSON( "$lte" << BSON_ARRAY( 4 << 5 ) );
+ LteOp lte;
+ ASSERT( lte.init( "a", operand[ "$lte" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "a" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ lte.matchesIndexKey( BSON( "" << 3 ), indexSpec ) );
+ }
+
+ TEST( LteOp, MatchesIndexKeyArrayValue ) {
+ BSONObj operand = BSON( "$lte" << 6 );
+ LteOp lte;
+ ASSERT( lte.init( "a", operand[ "$lte" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "loc" << "mockarrayvalue" << "a" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ lte.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 3 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ lte.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 7 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ lte.matchesIndexKey( BSON( "" << "dummygeohash" <<
+ "" << BSON_ARRAY( 8 << 6 << 4 ) ), indexSpec ) );
+ }
+
+ TEST( GtOp, MatchesElement ) {
+ BSONObj operand = BSON( "$gt" << 5 );
+ BSONObj match = BSON( "a" << 5.5 );
+ BSONObj notMatch = BSON( "a" << 4 );
+ BSONObj notMatchEqual = BSON( "a" << 5 );
+ BSONObj notMatchWrongType = BSON( "a" << "foo" );
+ GtOp gt;
+ ASSERT( gt.init( "", operand[ "$gt" ] ).isOK() );
+ ASSERT( gt.matchesSingleElement( match.firstElement() ) );
+ ASSERT( !gt.matchesSingleElement( notMatch.firstElement() ) );
+ ASSERT( !gt.matchesSingleElement( notMatchEqual.firstElement() ) );
+ ASSERT( !gt.matchesSingleElement( notMatchWrongType.firstElement() ) );
+ }
+*/
+
+TEST(GtOp, InvalidEooOperand) {
+ BSONObj operand;
+ GTMatchExpression gt;
+ ASSERT(!gt.init("", operand.firstElement()).isOK());
+}
+
+TEST(GtOp, MatchesScalar) {
+ BSONObj operand = BSON("$gt" << 5);
+ GTMatchExpression gt;
+ ASSERT(gt.init("a", operand["$gt"]).isOK());
+ ASSERT(gt.matchesBSON(BSON("a" << 5.5), NULL));
+ ASSERT(!gt.matchesBSON(BSON("a" << 4), NULL));
+}
+
+TEST(GtOp, MatchesArrayValue) {
+ BSONObj operand = BSON("$gt" << 5);
+ GTMatchExpression gt;
+ ASSERT(gt.init("a", operand["$gt"]).isOK());
+ ASSERT(gt.matchesBSON(BSON("a" << BSON_ARRAY(3 << 5.5)), NULL));
+ ASSERT(!gt.matchesBSON(BSON("a" << BSON_ARRAY(2 << 4)), NULL));
+}
+
+TEST(GtOp, MatchesWholeArray) {
+ BSONObj operand = BSON("$gt" << BSON_ARRAY(5));
+ GTMatchExpression gt;
+ ASSERT(gt.init("a", operand["$gt"]).isOK());
+ ASSERT(!gt.matchesBSON(BSON("a" << BSON_ARRAY(4)), NULL));
+ ASSERT(!gt.matchesBSON(BSON("a" << BSON_ARRAY(5)), NULL));
+ ASSERT(gt.matchesBSON(BSON("a" << BSON_ARRAY(6)), NULL));
+ // Nested array.
+ // XXX: The following assertion documents current behavior.
+ ASSERT(gt.matchesBSON(BSON("a" << BSON_ARRAY(BSON_ARRAY(4))), NULL));
+ // XXX: The following assertion documents current behavior.
+ ASSERT(gt.matchesBSON(BSON("a" << BSON_ARRAY(BSON_ARRAY(5))), NULL));
+ ASSERT(gt.matchesBSON(BSON("a" << BSON_ARRAY(BSON_ARRAY(6))), NULL));
+}
+
+TEST(GtOp, MatchesNull) {
+ BSONObj operand = BSON("$gt" << BSONNULL);
+ GTMatchExpression gt;
+ ASSERT(gt.init("a", operand["$gt"]).isOK());
+ ASSERT(!gt.matchesBSON(BSONObj(), NULL));
+ ASSERT(!gt.matchesBSON(BSON("a" << BSONNULL), NULL));
+ ASSERT(!gt.matchesBSON(BSON("a" << 4), NULL));
+ // A non-existent field is treated same way as an empty bson object
+ ASSERT(!gt.matchesBSON(BSON("b" << 4), NULL));
+}
+
+TEST(GtOp, MatchesDotNotationNull) {
+ BSONObj operand = BSON("$gt" << BSONNULL);
+ GTMatchExpression gt;
+ ASSERT(gt.init("a.b", operand["$gt"]).isOK());
+ ASSERT(!gt.matchesBSON(BSONObj(), NULL));
+ ASSERT(!gt.matchesBSON(BSON("a" << BSONNULL), NULL));
+ ASSERT(!gt.matchesBSON(BSON("a" << 4), NULL));
+ ASSERT(!gt.matchesBSON(BSON("a" << BSONObj()), NULL));
+ ASSERT(!gt.matchesBSON(BSON("a" << BSON_ARRAY(BSON("b" << BSONNULL))), NULL));
+ ASSERT(!gt.matchesBSON(BSON("a" << BSON_ARRAY(BSON("a" << 4) << BSON("b" << 4))), NULL));
+ ASSERT(!gt.matchesBSON(BSON("a" << BSON_ARRAY(4)), NULL));
+ ASSERT(!gt.matchesBSON(BSON("a" << BSON_ARRAY(BSON("b" << 4))), NULL));
+}
+
+TEST(GtOp, MatchesMinKey) {
+ BSONObj operand = BSON("a" << MinKey);
+ GTMatchExpression gt;
+ ASSERT(gt.init("a", operand["a"]).isOK());
+ ASSERT(!gt.matchesBSON(BSON("a" << MinKey), NULL));
+ ASSERT(gt.matchesBSON(BSON("a" << MaxKey), NULL));
+ ASSERT(gt.matchesBSON(BSON("a" << 4), NULL));
+}
+
+TEST(GtOp, MatchesMaxKey) {
+ BSONObj operand = BSON("a" << MaxKey);
+ GTMatchExpression gt;
+ ASSERT(gt.init("a", operand["a"]).isOK());
+ ASSERT(!gt.matchesBSON(BSON("a" << MaxKey), NULL));
+ ASSERT(!gt.matchesBSON(BSON("a" << MinKey), NULL));
+ ASSERT(!gt.matchesBSON(BSON("a" << 4), NULL));
+}
+
+TEST(GtOp, ElemMatchKey) {
+ BSONObj operand = BSON("$gt" << 5);
+ GTMatchExpression gt;
+ ASSERT(gt.init("a", operand["$gt"]).isOK());
+ MatchDetails details;
+ details.requestElemMatchKey();
+ ASSERT(!gt.matchesBSON(BSON("a" << 4), &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(gt.matchesBSON(BSON("a" << 6), &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(gt.matchesBSON(BSON("a" << BSON_ARRAY(2 << 6 << 5)), &details));
+ ASSERT(details.hasElemMatchKey());
+ ASSERT_EQUALS("1", details.elemMatchKey());
+}
+
+/**
+ TEST( GtOp, MatchesIndexKeyScalar ) {
+ BSONObj operand = BSON( "$gt" << 6 );
+ GtOp gt;
+ ASSERT( gt.init( "a", operand[ "$gt" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "a" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ gt.matchesIndexKey( BSON( "" << 7 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ gt.matchesIndexKey( BSON( "" << 6 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ gt.matchesIndexKey( BSON( "" << BSON_ARRAY( 9 ) ), indexSpec ) );
+ }
+
+ TEST( GtOp, MatchesIndexKeyMissing ) {
+ BSONObj operand = BSON( "$gt" << 6 );
+ GtOp gt;
+ ASSERT( gt.init( "a", operand[ "$gt" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "b" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ gt.matchesIndexKey( BSON( "" << 7 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ gt.matchesIndexKey( BSON( "" << 4 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ gt.matchesIndexKey( BSON( "" << BSON_ARRAY( 8 << 6 ) ), indexSpec ) );
+ }
+
+ TEST( GtOp, MatchesIndexKeyArray ) {
+ BSONObj operand = BSON( "$gt" << BSON_ARRAY( 4 << 5 ) );
+ GtOp gt;
+ ASSERT( gt.init( "a", operand[ "$gt" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "a" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ gt.matchesIndexKey( BSON( "" << 8 ), indexSpec ) );
+ }
+
+ TEST( GtOp, MatchesIndexKeyArrayValue ) {
+ BSONObj operand = BSON( "$gt" << 6 );
+ GtOp gt;
+ ASSERT( gt.init( "a", operand[ "$gt" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "loc" << "mockarrayvalue" << "a" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ gt.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 7 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ gt.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 3 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ gt.matchesIndexKey( BSON( "" << "dummygeohash" <<
+ "" << BSON_ARRAY( 8 << 6 << 4 ) ), indexSpec ) );
+ }
+*/
+
+TEST(ComparisonMatchExpression, MatchesElement) {
+ BSONObj operand = BSON("$gte" << 5);
+ BSONObj match = BSON("a" << 5.5);
+ BSONObj equalMatch = BSON("a" << 5);
+ BSONObj notMatch = BSON("a" << 4);
+ BSONObj notMatchWrongType = BSON("a"
+ << "foo");
+ GTEMatchExpression gte;
+ ASSERT(gte.init("", operand["$gte"]).isOK());
+ ASSERT(gte.matchesSingleElement(match.firstElement()));
+ ASSERT(gte.matchesSingleElement(equalMatch.firstElement()));
+ ASSERT(!gte.matchesSingleElement(notMatch.firstElement()));
+ ASSERT(!gte.matchesSingleElement(notMatchWrongType.firstElement()));
+}
+
+TEST(ComparisonMatchExpression, InvalidEooOperand) {
+ BSONObj operand;
+ GTEMatchExpression gte;
+ ASSERT(!gte.init("", operand.firstElement()).isOK());
+}
+
+TEST(ComparisonMatchExpression, MatchesScalar) {
+ BSONObj operand = BSON("$gte" << 5);
+ GTEMatchExpression gte;
+ ASSERT(gte.init("a", operand["$gte"]).isOK());
+ ASSERT(gte.matchesBSON(BSON("a" << 5.5), NULL));
+ ASSERT(!gte.matchesBSON(BSON("a" << 4), NULL));
+}
+
+TEST(ComparisonMatchExpression, MatchesArrayValue) {
+ BSONObj operand = BSON("$gte" << 5);
+ GTEMatchExpression gte;
+ ASSERT(gte.init("a", operand["$gte"]).isOK());
+ ASSERT(gte.matchesBSON(BSON("a" << BSON_ARRAY(4 << 5.5)), NULL));
+ ASSERT(!gte.matchesBSON(BSON("a" << BSON_ARRAY(1 << 2)), NULL));
+}
+
+TEST(ComparisonMatchExpression, MatchesWholeArray) {
+ BSONObj operand = BSON("$gte" << BSON_ARRAY(5));
+ GTEMatchExpression gte;
+ ASSERT(gte.init("a", operand["$gte"]).isOK());
+ ASSERT(!gte.matchesBSON(BSON("a" << BSON_ARRAY(4)), NULL));
+ ASSERT(gte.matchesBSON(BSON("a" << BSON_ARRAY(5)), NULL));
+ ASSERT(gte.matchesBSON(BSON("a" << BSON_ARRAY(6)), NULL));
+ // Nested array.
+ // XXX: The following assertion documents current behavior.
+ ASSERT(gte.matchesBSON(BSON("a" << BSON_ARRAY(BSON_ARRAY(4))), NULL));
+ ASSERT(gte.matchesBSON(BSON("a" << BSON_ARRAY(BSON_ARRAY(5))), NULL));
+ ASSERT(gte.matchesBSON(BSON("a" << BSON_ARRAY(BSON_ARRAY(6))), NULL));
+}
+
+TEST(ComparisonMatchExpression, MatchesNull) {
+ BSONObj operand = BSON("$gte" << BSONNULL);
+ GTEMatchExpression gte;
+ ASSERT(gte.init("a", operand["$gte"]).isOK());
+ ASSERT(gte.matchesBSON(BSONObj(), NULL));
+ ASSERT(gte.matchesBSON(BSON("a" << BSONNULL), NULL));
+ ASSERT(!gte.matchesBSON(BSON("a" << 4), NULL));
+ // A non-existent field is treated same way as an empty bson object
+ ASSERT(gte.matchesBSON(BSON("b" << 4), NULL));
+}
+
+TEST(ComparisonMatchExpression, MatchesDotNotationNull) {
+ BSONObj operand = BSON("$gte" << BSONNULL);
+ GTEMatchExpression gte;
+ ASSERT(gte.init("a.b", operand["$gte"]).isOK());
+ ASSERT(gte.matchesBSON(BSONObj(), NULL));
+ ASSERT(gte.matchesBSON(BSON("a" << BSONNULL), NULL));
+ ASSERT(gte.matchesBSON(BSON("a" << 4), NULL));
+ ASSERT(gte.matchesBSON(BSON("a" << BSONObj()), NULL));
+ ASSERT(gte.matchesBSON(BSON("a" << BSON_ARRAY(BSON("b" << BSONNULL))), NULL));
+ ASSERT(gte.matchesBSON(BSON("a" << BSON_ARRAY(BSON("a" << 4) << BSON("b" << 4))), NULL));
+ ASSERT(!gte.matchesBSON(BSON("a" << BSON_ARRAY(4)), NULL));
+ ASSERT(!gte.matchesBSON(BSON("a" << BSON_ARRAY(BSON("b" << 4))), NULL));
+}
+
+TEST(ComparisonMatchExpression, MatchesMinKey) {
+ BSONObj operand = BSON("a" << MinKey);
+ GTEMatchExpression gte;
+ ASSERT(gte.init("a", operand["a"]).isOK());
+ ASSERT(gte.matchesBSON(BSON("a" << MinKey), NULL));
+ ASSERT(gte.matchesBSON(BSON("a" << MaxKey), NULL));
+ ASSERT(gte.matchesBSON(BSON("a" << 4), NULL));
+}
+
+TEST(ComparisonMatchExpression, MatchesMaxKey) {
+ BSONObj operand = BSON("a" << MaxKey);
+ GTEMatchExpression gte;
+ ASSERT(gte.init("a", operand["a"]).isOK());
+ ASSERT(gte.matchesBSON(BSON("a" << MaxKey), NULL));
+ ASSERT(!gte.matchesBSON(BSON("a" << MinKey), NULL));
+ ASSERT(!gte.matchesBSON(BSON("a" << 4), NULL));
+}
+
+TEST(ComparisonMatchExpression, ElemMatchKey) {
+ BSONObj operand = BSON("$gte" << 5);
+ GTEMatchExpression gte;
+ ASSERT(gte.init("a", operand["$gte"]).isOK());
+ MatchDetails details;
+ details.requestElemMatchKey();
+ ASSERT(!gte.matchesBSON(BSON("a" << 4), &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(gte.matchesBSON(BSON("a" << 6), &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(gte.matchesBSON(BSON("a" << BSON_ARRAY(2 << 6 << 5)), &details));
+ ASSERT(details.hasElemMatchKey());
+ ASSERT_EQUALS("1", details.elemMatchKey());
+}
+
+/**
+ TEST( GteOp, MatchesIndexKeyScalar ) {
+ BSONObj operand = BSON( "$gte" << 6 );
+ GteOp gte;
+ ASSERT( gte.init( "a", operand[ "$gte" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "a" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ gte.matchesIndexKey( BSON( "" << 6 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ gte.matchesIndexKey( BSON( "" << 5 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ gte.matchesIndexKey( BSON( "" << BSON_ARRAY( 7 ) ), indexSpec ) );
+ }
+
+ TEST( GteOp, MatchesIndexKeyMissing ) {
+ BSONObj operand = BSON( "$gte" << 6 );
+ GteOp gte;
+ ASSERT( gte.init( "a", operand[ "$gte" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "b" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ gte.matchesIndexKey( BSON( "" << 6 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ gte.matchesIndexKey( BSON( "" << 4 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ gte.matchesIndexKey( BSON( "" << BSON_ARRAY( 8 << 6 ) ), indexSpec ) );
+ }
+
+ TEST( GteOp, MatchesIndexKeyArray ) {
+ BSONObj operand = BSON( "$gte" << BSON_ARRAY( 4 << 5 ) );
+ GteOp gte;
+ ASSERT( gte.init( "a", operand[ "$gte" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "a" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ gte.matchesIndexKey( BSON( "" << 6 ), indexSpec ) );
+ }
+
+ TEST( GteOp, MatchesIndexKeyArrayValue ) {
+ BSONObj operand = BSON( "$gte" << 6 );
+ GteOp gte;
+ ASSERT( gte.init( "a", operand[ "$gte" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "loc" << "mockarrayvalue" << "a" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ gte.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 6 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ gte.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 3 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ gte.matchesIndexKey( BSON( "" << "dummygeohash" <<
+ "" << BSON_ARRAY( 8 << 6 << 4 ) ), indexSpec ) );
+ }
+*/
+
+TEST(RegexMatchExpression, MatchesElementExact) {
+ BSONObj match = BSON("a"
+ << "b");
+ BSONObj notMatch = BSON("a"
+ << "c");
+ RegexMatchExpression regex;
+ ASSERT(regex.init("", "b", "").isOK());
+ ASSERT(regex.matchesSingleElement(match.firstElement()));
+ ASSERT(!regex.matchesSingleElement(notMatch.firstElement()));
+}
+
+TEST(RegexMatchExpression, TooLargePattern) {
+ string tooLargePattern(50 * 1000, 'z');
+ RegexMatchExpression regex;
+ ASSERT(!regex.init("a", tooLargePattern, "").isOK());
+}
+
+TEST(RegexMatchExpression, MatchesElementSimplePrefix) {
+ BSONObj match = BSON("x"
+ << "abc");
+ BSONObj notMatch = BSON("x"
+ << "adz");
+ RegexMatchExpression regex;
+ ASSERT(regex.init("", "^ab", "").isOK());
+ ASSERT(regex.matchesSingleElement(match.firstElement()));
+ ASSERT(!regex.matchesSingleElement(notMatch.firstElement()));
+}
+
+TEST(RegexMatchExpression, MatchesElementCaseSensitive) {
+ BSONObj match = BSON("x"
+ << "abc");
+ BSONObj notMatch = BSON("x"
+ << "ABC");
+ RegexMatchExpression regex;
+ ASSERT(regex.init("", "abc", "").isOK());
+ ASSERT(regex.matchesSingleElement(match.firstElement()));
+ ASSERT(!regex.matchesSingleElement(notMatch.firstElement()));
+}
+
+TEST(RegexMatchExpression, MatchesElementCaseInsensitive) {
+ BSONObj match = BSON("x"
+ << "abc");
+ BSONObj matchUppercase = BSON("x"
+ << "ABC");
+ BSONObj notMatch = BSON("x"
+ << "abz");
+ RegexMatchExpression regex;
+ ASSERT(regex.init("", "abc", "i").isOK());
+ ASSERT(regex.matchesSingleElement(match.firstElement()));
+ ASSERT(regex.matchesSingleElement(matchUppercase.firstElement()));
+ ASSERT(!regex.matchesSingleElement(notMatch.firstElement()));
+}
+
+TEST(RegexMatchExpression, MatchesElementMultilineOff) {
+ BSONObj match = BSON("x"
+ << "az");
+ BSONObj notMatch = BSON("x"
+ << "\naz");
+ RegexMatchExpression regex;
+ ASSERT(regex.init("", "^a", "").isOK());
+ ASSERT(regex.matchesSingleElement(match.firstElement()));
+ ASSERT(!regex.matchesSingleElement(notMatch.firstElement()));
+}
+
+TEST(RegexMatchExpression, MatchesElementMultilineOn) {
+ BSONObj match = BSON("x"
+ << "az");
+ BSONObj matchMultiline = BSON("x"
+ << "\naz");
+ BSONObj notMatch = BSON("x"
+ << "\n\n");
+ RegexMatchExpression regex;
+ ASSERT(regex.init("", "^a", "m").isOK());
+ ASSERT(regex.matchesSingleElement(match.firstElement()));
+ ASSERT(regex.matchesSingleElement(matchMultiline.firstElement()));
+ ASSERT(!regex.matchesSingleElement(notMatch.firstElement()));
+}
+
+TEST(RegexMatchExpression, MatchesElementExtendedOff) {
+ BSONObj match = BSON("x"
+ << "a b");
+ BSONObj notMatch = BSON("x"
+ << "ab");
+ RegexMatchExpression regex;
+ ASSERT(regex.init("", "a b", "").isOK());
+ ASSERT(regex.matchesSingleElement(match.firstElement()));
+ ASSERT(!regex.matchesSingleElement(notMatch.firstElement()));
+}
+
+TEST(RegexMatchExpression, MatchesElementExtendedOn) {
+ BSONObj match = BSON("x"
+ << "ab");
+ BSONObj notMatch = BSON("x"
+ << "a b");
+ RegexMatchExpression regex;
+ ASSERT(regex.init("", "a b", "x").isOK());
+ ASSERT(regex.matchesSingleElement(match.firstElement()));
+ ASSERT(!regex.matchesSingleElement(notMatch.firstElement()));
+}
+
+TEST(RegexMatchExpression, MatchesElementDotAllOff) {
+ BSONObj match = BSON("x"
+ << "a b");
+ BSONObj notMatch = BSON("x"
+ << "a\nb");
+ RegexMatchExpression regex;
+ ASSERT(regex.init("", "a.b", "").isOK());
+ ASSERT(regex.matchesSingleElement(match.firstElement()));
+ ASSERT(!regex.matchesSingleElement(notMatch.firstElement()));
+}
+
+TEST(RegexMatchExpression, MatchesElementDotAllOn) {
+ BSONObj match = BSON("x"
+ << "a b");
+ BSONObj matchDotAll = BSON("x"
+ << "a\nb");
+ BSONObj notMatch = BSON("x"
+ << "ab");
+ RegexMatchExpression regex;
+ ASSERT(regex.init("", "a.b", "s").isOK());
+ ASSERT(regex.matchesSingleElement(match.firstElement()));
+ ASSERT(regex.matchesSingleElement(matchDotAll.firstElement()));
+ ASSERT(!regex.matchesSingleElement(notMatch.firstElement()));
+}
+
+TEST(RegexMatchExpression, MatchesElementMultipleFlags) {
+ BSONObj matchMultilineDotAll = BSON("x"
+ << "\na\nb");
+ RegexMatchExpression regex;
+ ASSERT(regex.init("", "^a.b", "ms").isOK());
+ ASSERT(regex.matchesSingleElement(matchMultilineDotAll.firstElement()));
+}
+
+TEST(RegexMatchExpression, MatchesElementRegexType) {
+ BSONObj match = BSONObjBuilder().appendRegex("x", "yz", "i").obj();
+ BSONObj notMatchPattern = BSONObjBuilder().appendRegex("x", "r", "i").obj();
+ BSONObj notMatchFlags = BSONObjBuilder().appendRegex("x", "yz", "s").obj();
+ RegexMatchExpression regex;
+ ASSERT(regex.init("", "yz", "i").isOK());
+ ASSERT(regex.matchesSingleElement(match.firstElement()));
+ ASSERT(!regex.matchesSingleElement(notMatchPattern.firstElement()));
+ ASSERT(!regex.matchesSingleElement(notMatchFlags.firstElement()));
+}
+
+TEST(RegexMatchExpression, MatchesElementSymbolType) {
+ BSONObj match = BSONObjBuilder().appendSymbol("x", "yz").obj();
+ BSONObj notMatch = BSONObjBuilder().appendSymbol("x", "gg").obj();
+ RegexMatchExpression regex;
+ ASSERT(regex.init("", "yz", "").isOK());
+ ASSERT(regex.matchesSingleElement(match.firstElement()));
+ ASSERT(!regex.matchesSingleElement(notMatch.firstElement()));
+}
+
+TEST(RegexMatchExpression, MatchesElementWrongType) {
+ BSONObj notMatchInt = BSON("x" << 1);
+ BSONObj notMatchBool = BSON("x" << true);
+ RegexMatchExpression regex;
+ ASSERT(regex.init("", "1", "").isOK());
+ ASSERT(!regex.matchesSingleElement(notMatchInt.firstElement()));
+ ASSERT(!regex.matchesSingleElement(notMatchBool.firstElement()));
+}
+
+TEST(RegexMatchExpression, MatchesElementUtf8) {
+ BSONObj multiByteCharacter = BSON("x"
+ << "\xc2\xa5");
+ RegexMatchExpression regex;
+ ASSERT(regex.init("", "^.$", "").isOK());
+ ASSERT(regex.matchesSingleElement(multiByteCharacter.firstElement()));
+}
+
+TEST(RegexMatchExpression, MatchesScalar) {
+ RegexMatchExpression regex;
+ ASSERT(regex.init("a", "b", "").isOK());
+ ASSERT(regex.matchesBSON(BSON("a"
+ << "b"),
+ NULL));
+ ASSERT(!regex.matchesBSON(BSON("a"
+ << "c"),
+ NULL));
+}
+
+TEST(RegexMatchExpression, MatchesArrayValue) {
+ RegexMatchExpression regex;
+ ASSERT(regex.init("a", "b", "").isOK());
+ ASSERT(regex.matchesBSON(BSON("a" << BSON_ARRAY("c"
+ << "b")),
+ NULL));
+ ASSERT(!regex.matchesBSON(BSON("a" << BSON_ARRAY("d"
+ << "c")),
+ NULL));
+}
+
+TEST(RegexMatchExpression, MatchesNull) {
+ RegexMatchExpression regex;
+ ASSERT(regex.init("a", "b", "").isOK());
+ ASSERT(!regex.matchesBSON(BSONObj(), NULL));
+ ASSERT(!regex.matchesBSON(BSON("a" << BSONNULL), NULL));
+}
+
+TEST(RegexMatchExpression, ElemMatchKey) {
+ RegexMatchExpression regex;
+ ASSERT(regex.init("a", "b", "").isOK());
+ MatchDetails details;
+ details.requestElemMatchKey();
+ ASSERT(!regex.matchesBSON(BSON("a"
+ << "c"),
+ &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(regex.matchesBSON(BSON("a"
+ << "b"),
+ &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(regex.matchesBSON(BSON("a" << BSON_ARRAY("c"
+ << "b")),
+ &details));
+ ASSERT(details.hasElemMatchKey());
+ ASSERT_EQUALS("1", details.elemMatchKey());
+}
+
+TEST(RegexMatchExpression, Equality1) {
+ RegexMatchExpression r1;
+ RegexMatchExpression r2;
+ RegexMatchExpression r3;
+ RegexMatchExpression r4;
+ ASSERT(r1.init("a", "b", "").isOK());
+ ASSERT(r2.init("a", "b", "x").isOK());
+ ASSERT(r3.init("a", "c", "").isOK());
+ ASSERT(r4.init("b", "b", "").isOK());
+
+ ASSERT(r1.equivalent(&r1));
+ ASSERT(!r1.equivalent(&r2));
+ ASSERT(!r1.equivalent(&r3));
+ ASSERT(!r1.equivalent(&r4));
+}
+
+/**
+ TEST( RegexMatchExpression, MatchesIndexKeyScalar ) {
+ RegexMatchExpression regex;
+ ASSERT( regex.init( "a", "xyz", "" ).isOK() );
+ IndexSpec indexSpec( BSON( "a" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ regex.matchesIndexKey( BSON( "" << "z xyz" ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ regex.matchesIndexKey( BSON( "" << "xy" ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ regex.matchesIndexKey( BSON( "" << BSON_ARRAY( "xyz" ) ), indexSpec ) );
+ }
+
+ TEST( RegexMatchExpression, MatchesIndexKeyMissing ) {
+ RegexMatchExpression regex;
+ ASSERT( regex.init( "a", "xyz", "" ).isOK() );
+ IndexSpec indexSpec( BSON( "b" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ regex.matchesIndexKey( BSON( "" << "z xyz" ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ regex.matchesIndexKey( BSON( "" << "xy" ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ regex.matchesIndexKey( BSON( "" << BSON_ARRAY( 8 << "xyz" ) ), indexSpec ) );
+ }
+
+ TEST( RegexMatchExpression, MatchesIndexKeyArrayValue ) {
+ RegexMatchExpression regex;
+ ASSERT( regex.init( "a", "xyz", "" ).isOK() );
+ IndexSpec indexSpec( BSON( "loc" << "mockarrayvalue" << "a" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ regex.matchesIndexKey( BSON( "" << "dummygeohash" << "" << "xyz" ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ regex.matchesIndexKey( BSON( "" << "dummygeohash" << "" << "z" ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ regex.matchesIndexKey( BSON( "" << "dummygeohash" <<
+ "" << BSON_ARRAY( "r" << 6 << "xyz" ) ), indexSpec ) );
+ }
+*/
+
+TEST(ModMatchExpression, MatchesElement) {
+ BSONObj match = BSON("a" << 1);
+ BSONObj largerMatch = BSON("a" << 4.0);
+ BSONObj longLongMatch = BSON("a" << 68719476736LL);
+ BSONObj notMatch = BSON("a" << 6);
+ BSONObj negativeNotMatch = BSON("a" << -2);
+ ModMatchExpression mod;
+ ASSERT(mod.init("", 3, 1).isOK());
+ ASSERT(mod.matchesSingleElement(match.firstElement()));
+ ASSERT(mod.matchesSingleElement(largerMatch.firstElement()));
+ ASSERT(mod.matchesSingleElement(longLongMatch.firstElement()));
+ ASSERT(!mod.matchesSingleElement(notMatch.firstElement()));
+ ASSERT(!mod.matchesSingleElement(negativeNotMatch.firstElement()));
+}
+
+TEST(ModMatchExpression, ZeroDivisor) {
+ ModMatchExpression mod;
+ ASSERT(!mod.init("", 0, 1).isOK());
+}
+
+TEST(ModMatchExpression, MatchesScalar) {
+ ModMatchExpression mod;
+ ASSERT(mod.init("a", 5, 2).isOK());
+ ASSERT(mod.matchesBSON(BSON("a" << 7.0), NULL));
+ ASSERT(!mod.matchesBSON(BSON("a" << 4), NULL));
+}
+
+TEST(ModMatchExpression, MatchesArrayValue) {
+ ModMatchExpression mod;
+ ASSERT(mod.init("a", 5, 2).isOK());
+ ASSERT(mod.matchesBSON(BSON("a" << BSON_ARRAY(5 << 12LL)), NULL));
+ ASSERT(!mod.matchesBSON(BSON("a" << BSON_ARRAY(6 << 8)), NULL));
+}
+
+TEST(ModMatchExpression, MatchesNull) {
+ ModMatchExpression mod;
+ ASSERT(mod.init("a", 5, 2).isOK());
+ ASSERT(!mod.matchesBSON(BSONObj(), NULL));
+ ASSERT(!mod.matchesBSON(BSON("a" << BSONNULL), NULL));
+}
+
+TEST(ModMatchExpression, ElemMatchKey) {
+ ModMatchExpression mod;
+ ASSERT(mod.init("a", 5, 2).isOK());
+ MatchDetails details;
+ details.requestElemMatchKey();
+ ASSERT(!mod.matchesBSON(BSON("a" << 4), &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(mod.matchesBSON(BSON("a" << 2), &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(mod.matchesBSON(BSON("a" << BSON_ARRAY(1 << 2 << 5)), &details));
+ ASSERT(details.hasElemMatchKey());
+ ASSERT_EQUALS("1", details.elemMatchKey());
+}
+
+TEST(ModMatchExpression, Equality1) {
+ ModMatchExpression m1;
+ ModMatchExpression m2;
+ ModMatchExpression m3;
+ ModMatchExpression m4;
+
+ m1.init("a", 1, 2);
+ m2.init("a", 2, 2);
+ m3.init("a", 1, 1);
+ m4.init("b", 1, 2);
+
+ ASSERT(m1.equivalent(&m1));
+ ASSERT(!m1.equivalent(&m2));
+ ASSERT(!m1.equivalent(&m3));
+ ASSERT(!m1.equivalent(&m4));
+}
+
+/**
+ TEST( ModMatchExpression, MatchesIndexKey ) {
+ BSONObj operand = BSON( "$mod" << BSON_ARRAY( 2 << 1 ) );
+ ModMatchExpression mod;
+ ASSERT( mod.init( "a", operand[ "$mod" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "a" << 1 ) );
+ BSONObj indexKey = BSON( "" << 1 );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ mod.matchesIndexKey( indexKey, indexSpec ) );
+ }
+*/
+
+TEST(ExistsMatchExpression, MatchesElement) {
+ BSONObj existsInt = BSON("a" << 5);
+ BSONObj existsNull = BSON("a" << BSONNULL);
+ BSONObj doesntExist = BSONObj();
+ ExistsMatchExpression exists;
+ ASSERT(exists.init("").isOK());
+ ASSERT(exists.matchesSingleElement(existsInt.firstElement()));
+ ASSERT(exists.matchesSingleElement(existsNull.firstElement()));
+ ASSERT(!exists.matchesSingleElement(doesntExist.firstElement()));
+}
+
+TEST(ExistsMatchExpression, MatchesElementExistsTrueValue) {
+ BSONObj exists = BSON("a" << 5);
+ BSONObj missing = BSONObj();
+ ExistsMatchExpression existsTrueValue;
+ ASSERT(existsTrueValue.init("").isOK());
+ ASSERT(existsTrueValue.matchesSingleElement(exists.firstElement()));
+ ASSERT(!existsTrueValue.matchesSingleElement(missing.firstElement()));
+}
+
+TEST(ExistsMatchExpression, MatchesScalar) {
+ ExistsMatchExpression exists;
+ ASSERT(exists.init("a").isOK());
+ ASSERT(exists.matchesBSON(BSON("a" << 1), NULL));
+ ASSERT(exists.matchesBSON(BSON("a" << BSONNULL), NULL));
+ ASSERT(!exists.matchesBSON(BSON("b" << 1), NULL));
+}
+
+TEST(ExistsMatchExpression, MatchesArray) {
+ ExistsMatchExpression exists;
+ ASSERT(exists.init("a").isOK());
+ ASSERT(exists.matchesBSON(BSON("a" << BSON_ARRAY(4 << 5.5)), NULL));
+}
+
+TEST(ExistsMatchExpression, ElemMatchKey) {
+ ExistsMatchExpression exists;
+ ASSERT(exists.init("a.b").isOK());
+ MatchDetails details;
+ details.requestElemMatchKey();
+ ASSERT(!exists.matchesBSON(BSON("a" << 1), &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(exists.matchesBSON(BSON("a" << BSON("b" << 6)), &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(exists.matchesBSON(BSON("a" << BSON_ARRAY(2 << BSON("b" << 7))), &details));
+ ASSERT(details.hasElemMatchKey());
+ ASSERT_EQUALS("1", details.elemMatchKey());
+}
+
+TEST(ExistsMatchExpression, Equivalent) {
+ ExistsMatchExpression e1;
+ ExistsMatchExpression e2;
+ e1.init("a");
+ e2.init("b");
+
+ ASSERT(e1.equivalent(&e1));
+ ASSERT(!e1.equivalent(&e2));
+}
+
+/**
+ TEST( ExistsMatchExpression, MatchesIndexKey ) {
+ BSONObj operand = BSON( "$exists" << true );
+ ExistsMatchExpression exists;
+ ASSERT( exists.init( "a", operand[ "$exists" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "a" << 1 ) );
+ BSONObj indexKey = BSON( "" << 1 );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ exists.matchesIndexKey( indexKey, indexSpec ) );
+ }
+*/
+
+
+TEST(TypeMatchExpression, MatchesElementStringType) {
+ BSONObj match = BSON("a"
+ << "abc");
+ BSONObj notMatch = BSON("a" << 5);
+ TypeMatchExpression type;
+ ASSERT(type.init("", String).isOK());
+ ASSERT(type.matchesSingleElement(match["a"]));
+ ASSERT(!type.matchesSingleElement(notMatch["a"]));
+}
+
+TEST(TypeMatchExpression, MatchesElementNullType) {
+ BSONObj match = BSON("a" << BSONNULL);
+ BSONObj notMatch = BSON("a"
+ << "abc");
+ TypeMatchExpression type;
+ ASSERT(type.init("", jstNULL).isOK());
+ ASSERT(type.matchesSingleElement(match["a"]));
+ ASSERT(!type.matchesSingleElement(notMatch["a"]));
+}
+
+TEST(TypeMatchExpression, InvalidTypeMatchExpressionerand) {
+ // If the provided type number is not a valid BSONType, it is not a parse error. The
+ // operator will simply not match anything.
+ BSONObj notMatch1 = BSON("a" << BSONNULL);
+ BSONObj notMatch2 = BSON("a"
+ << "abc");
+ TypeMatchExpression type;
+ ASSERT(type.init("", JSTypeMax + 1).isOK());
+ ASSERT(!type.matchesSingleElement(notMatch1["a"]));
+ ASSERT(!type.matchesSingleElement(notMatch2["a"]));
+}
+
+TEST(TypeMatchExpression, MatchesScalar) {
+ TypeMatchExpression type;
+ ASSERT(type.init("a", Bool).isOK());
+ ASSERT(type.matchesBSON(BSON("a" << true), NULL));
+ ASSERT(!type.matchesBSON(BSON("a" << 1), NULL));
+}
+
+TEST(TypeMatchExpression, MatchesArray) {
+ TypeMatchExpression type;
+ ASSERT(type.init("a", NumberInt).isOK());
+ ASSERT(type.matchesBSON(BSON("a" << BSON_ARRAY(4)), NULL));
+ ASSERT(type.matchesBSON(BSON("a" << BSON_ARRAY(4 << "a")), NULL));
+ ASSERT(type.matchesBSON(BSON("a" << BSON_ARRAY("a" << 4)), NULL));
+ ASSERT(!type.matchesBSON(BSON("a" << BSON_ARRAY("a")), NULL));
+ ASSERT(!type.matchesBSON(BSON("a" << BSON_ARRAY(BSON_ARRAY(4))), NULL));
+}
+
+TEST(TypeMatchExpression, MatchesOuterArray) {
+ TypeMatchExpression type;
+ ASSERT(type.init("a", Array).isOK());
+ // The outer array is not matched.
+ ASSERT(!type.matchesBSON(BSON("a" << BSONArray()), NULL));
+ ASSERT(!type.matchesBSON(BSON("a" << BSON_ARRAY(4 << "a")), NULL));
+ ASSERT(type.matchesBSON(BSON("a" << BSON_ARRAY(BSONArray() << 2)), NULL));
+ ASSERT(!type.matchesBSON(BSON("a"
+ << "bar"),
+ NULL));
+}
+
+TEST(TypeMatchExpression, MatchesObject) {
+ TypeMatchExpression type;
+ ASSERT(type.init("a", Object).isOK());
+ ASSERT(type.matchesBSON(BSON("a" << BSON("b" << 1)), NULL));
+ ASSERT(!type.matchesBSON(BSON("a" << 1), NULL));
+}
+
+TEST(TypeMatchExpression, MatchesDotNotationFieldObject) {
+ TypeMatchExpression type;
+ ASSERT(type.init("a.b", Object).isOK());
+ ASSERT(type.matchesBSON(BSON("a" << BSON("b" << BSON("c" << 1))), NULL));
+ ASSERT(!type.matchesBSON(BSON("a" << BSON("b" << 1)), NULL));
+}
+
+TEST(TypeMatchExpression, MatchesDotNotationArrayElementArray) {
+ TypeMatchExpression type;
+ ASSERT(type.init("a.0", Array).isOK());
+ ASSERT(type.matchesBSON(BSON("a" << BSON_ARRAY(BSON_ARRAY(1))), NULL));
+ ASSERT(!type.matchesBSON(BSON("a" << BSON_ARRAY("b")), NULL));
+}
+
+TEST(TypeMatchExpression, MatchesDotNotationArrayElementScalar) {
+ TypeMatchExpression type;
+ ASSERT(type.init("a.0", String).isOK());
+ ASSERT(type.matchesBSON(BSON("a" << BSON_ARRAY("b")), NULL));
+ ASSERT(!type.matchesBSON(BSON("a" << BSON_ARRAY(1)), NULL));
+}
+
+TEST(TypeMatchExpression, MatchesDotNotationArrayElementObject) {
+ TypeMatchExpression type;
+ ASSERT(type.init("a.0", Object).isOK());
+ ASSERT(type.matchesBSON(BSON("a" << BSON_ARRAY(BSON("b" << 1))), NULL));
+ ASSERT(!type.matchesBSON(BSON("a" << BSON_ARRAY(1)), NULL));
+}
+
+TEST(TypeMatchExpression, MatchesNull) {
+ TypeMatchExpression type;
+ ASSERT(type.init("a", jstNULL).isOK());
+ ASSERT(type.matchesBSON(BSON("a" << BSONNULL), NULL));
+ ASSERT(!type.matchesBSON(BSON("a" << 4), NULL));
+ ASSERT(!type.matchesBSON(BSONObj(), NULL));
+}
+
+TEST(TypeMatchExpression, ElemMatchKey) {
+ TypeMatchExpression type;
+ ASSERT(type.init("a.b", String).isOK());
+ MatchDetails details;
+ details.requestElemMatchKey();
+ ASSERT(!type.matchesBSON(BSON("a" << 1), &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(type.matchesBSON(BSON("a" << BSON("b"
+ << "string")),
+ &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(type.matchesBSON(BSON("a" << BSON("b" << BSON_ARRAY("string"))), &details));
+ ASSERT(details.hasElemMatchKey());
+ ASSERT_EQUALS("0", details.elemMatchKey());
+ ASSERT(type.matchesBSON(BSON("a" << BSON_ARRAY(2 << BSON("b" << BSON_ARRAY("string")))),
+ &details));
+ ASSERT(details.hasElemMatchKey());
+ ASSERT_EQUALS("1", details.elemMatchKey());
+}
+
+TEST(TypeMatchExpression, Equivalent) {
+ TypeMatchExpression e1;
+ TypeMatchExpression e2;
+ TypeMatchExpression e3;
+ e1.init("a", String);
+ e2.init("a", NumberDouble);
+ e3.init("b", String);
+
+ ASSERT(e1.equivalent(&e1));
+ ASSERT(!e1.equivalent(&e2));
+ ASSERT(!e1.equivalent(&e3));
+}
+
+
+/**
+ TEST( TypeMatchExpression, MatchesIndexKey ) {
+ BSONObj operand = BSON( "$type" << 2 );
+ TypeMatchExpression type;
+ ASSERT( type.init( "a", operand[ "$type" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "a" << 1 ) );
+ BSONObj indexKey = BSON( "" << "q" );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ type.matchesIndexKey( indexKey, indexSpec ) );
+ }
+*/
+
+
+TEST(InMatchExpression, MatchesElementSingle) {
+ BSONArray operand = BSON_ARRAY(1);
+ BSONObj match = BSON("a" << 1);
+ BSONObj notMatch = BSON("a" << 2);
+ InMatchExpression in;
+ in.getArrayFilterEntries()->addEquality(operand.firstElement());
+ ASSERT(in.matchesSingleElement(match["a"]));
+ ASSERT(!in.matchesSingleElement(notMatch["a"]));
+}
+
+TEST(InMatchExpression, MatchesEmpty) {
+ InMatchExpression in;
+ in.init("a");
+
+ BSONObj notMatch = BSON("a" << 2);
+ ASSERT(!in.matchesSingleElement(notMatch["a"]));
+ ASSERT(!in.matchesBSON(BSON("a" << 1), NULL));
+ ASSERT(!in.matchesBSON(BSONObj(), NULL));
+}
+
+TEST(InMatchExpression, MatchesElementMultiple) {
+ BSONObj operand = BSON_ARRAY(1 << "r" << true << 1);
+ InMatchExpression in;
+ in.getArrayFilterEntries()->addEquality(operand[0]);
+ in.getArrayFilterEntries()->addEquality(operand[1]);
+ in.getArrayFilterEntries()->addEquality(operand[2]);
+ in.getArrayFilterEntries()->addEquality(operand[3]);
+
+ BSONObj matchFirst = BSON("a" << 1);
+ BSONObj matchSecond = BSON("a"
+ << "r");
+ BSONObj matchThird = BSON("a" << true);
+ BSONObj notMatch = BSON("a" << false);
+ ASSERT(in.matchesSingleElement(matchFirst["a"]));
+ ASSERT(in.matchesSingleElement(matchSecond["a"]));
+ ASSERT(in.matchesSingleElement(matchThird["a"]));
+ ASSERT(!in.matchesSingleElement(notMatch["a"]));
+}
+
+
+TEST(InMatchExpression, MatchesScalar) {
+ BSONObj operand = BSON_ARRAY(5);
+ InMatchExpression in;
+ in.init("a");
+ in.getArrayFilterEntries()->addEquality(operand.firstElement());
+
+ ASSERT(in.matchesBSON(BSON("a" << 5.0), NULL));
+ ASSERT(!in.matchesBSON(BSON("a" << 4), NULL));
+}
+
+TEST(InMatchExpression, MatchesArrayValue) {
+ BSONObj operand = BSON_ARRAY(5);
+ InMatchExpression in;
+ in.init("a");
+ in.getArrayFilterEntries()->addEquality(operand.firstElement());
+
+ ASSERT(in.matchesBSON(BSON("a" << BSON_ARRAY(5.0 << 6)), NULL));
+ ASSERT(!in.matchesBSON(BSON("a" << BSON_ARRAY(6 << 7)), NULL));
+ ASSERT(!in.matchesBSON(BSON("a" << BSON_ARRAY(BSON_ARRAY(5))), NULL));
+}
+
+TEST(InMatchExpression, MatchesNull) {
+ BSONObj operand = BSON_ARRAY(BSONNULL);
+
+ InMatchExpression in;
+ in.init("a");
+ in.getArrayFilterEntries()->addEquality(operand.firstElement());
+
+ ASSERT(in.matchesBSON(BSONObj(), NULL));
+ ASSERT(in.matchesBSON(BSON("a" << BSONNULL), NULL));
+ ASSERT(!in.matchesBSON(BSON("a" << 4), NULL));
+ // A non-existent field is treated same way as an empty bson object
+ ASSERT(in.matchesBSON(BSON("b" << 4), NULL));
+}
+
+TEST(InMatchExpression, MatchesUndefined) {
+ BSONObj operand = BSON_ARRAY(BSONUndefined);
+
+ InMatchExpression in;
+ in.init("a");
+ Status s = in.getArrayFilterEntries()->addEquality(operand.firstElement());
+ ASSERT_NOT_OK(s);
+}
+
+TEST(InMatchExpression, MatchesMinKey) {
+ BSONObj operand = BSON_ARRAY(MinKey);
+ InMatchExpression in;
+ in.init("a");
+ in.getArrayFilterEntries()->addEquality(operand.firstElement());
+
+ ASSERT(in.matchesBSON(BSON("a" << MinKey), NULL));
+ ASSERT(!in.matchesBSON(BSON("a" << MaxKey), NULL));
+ ASSERT(!in.matchesBSON(BSON("a" << 4), NULL));
+}
+
+TEST(InMatchExpression, MatchesMaxKey) {
+ BSONObj operand = BSON_ARRAY(MaxKey);
+ InMatchExpression in;
+ in.init("a");
+ in.getArrayFilterEntries()->addEquality(operand.firstElement());
+
+ ASSERT(in.matchesBSON(BSON("a" << MaxKey), NULL));
+ ASSERT(!in.matchesBSON(BSON("a" << MinKey), NULL));
+ ASSERT(!in.matchesBSON(BSON("a" << 4), NULL));
+}
+
+TEST(InMatchExpression, MatchesFullArray) {
+ BSONObj operand = BSON_ARRAY(BSON_ARRAY(1 << 2) << 4 << 5);
+ InMatchExpression in;
+ in.init("a");
+ in.getArrayFilterEntries()->addEquality(operand[0]);
+ in.getArrayFilterEntries()->addEquality(operand[1]);
+ in.getArrayFilterEntries()->addEquality(operand[2]);
+
+ ASSERT(in.matchesBSON(BSON("a" << BSON_ARRAY(1 << 2)), NULL));
+ ASSERT(!in.matchesBSON(BSON("a" << BSON_ARRAY(1 << 2 << 3)), NULL));
+ ASSERT(!in.matchesBSON(BSON("a" << BSON_ARRAY(1)), NULL));
+ ASSERT(!in.matchesBSON(BSON("a" << 1), NULL));
+}
+
+TEST(InMatchExpression, ElemMatchKey) {
+ BSONObj operand = BSON_ARRAY(5 << 2);
+ InMatchExpression in;
+ in.init("a");
+ in.getArrayFilterEntries()->addEquality(operand[0]);
+ in.getArrayFilterEntries()->addEquality(operand[1]);
+
+ MatchDetails details;
+ details.requestElemMatchKey();
+ ASSERT(!in.matchesBSON(BSON("a" << 4), &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(in.matchesBSON(BSON("a" << 5), &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(in.matchesBSON(BSON("a" << BSON_ARRAY(1 << 2 << 5)), &details));
+ ASSERT(details.hasElemMatchKey());
+ ASSERT_EQUALS("1", details.elemMatchKey());
+}
+
+/**
+TEST( InMatchExpression, MatchesIndexKeyScalar ) {
+ BSONObj operand = BSON( "$in" << BSON_ARRAY( 6 << 5 ) );
+ InMatchExpression in;
+ ASSERT( in.init( "a", operand[ "$in" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "a" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ in.matchesIndexKey( BSON( "" << 6 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ in.matchesIndexKey( BSON( "" << 5 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ in.matchesIndexKey( BSON( "" << 4 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ in.matchesIndexKey( BSON( "" << BSON_ARRAY( 6 ) ), indexSpec ) );
+}
+
+TEST( InMatchExpression, MatchesIndexKeyMissing ) {
+ BSONObj operand = BSON( "$in" << BSON_ARRAY( 6 ) );
+ ComparisonMatchExpression eq
+ ASSERT( eq.init( "a", operand[ "$in" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "b" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ eq.matchesIndexKey( BSON( "" << 6 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ eq.matchesIndexKey( BSON( "" << 4 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ eq.matchesIndexKey( BSON( "" << BSON_ARRAY( 8 << 6 ) ), indexSpec ) );
+}
+
+TEST( InMatchExpression, MatchesIndexKeyArray ) {
+ BSONObj operand = BSON( "$in" << BSON_ARRAY( 4 << BSON_ARRAY( 5 ) ) );
+ InMatchExpression in;
+ ASSERT( in.init( "a", operand[ "$in" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "a" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ in.matchesIndexKey( BSON( "" << 4 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ in.matchesIndexKey( BSON( "" << 5 ), indexSpec ) );
+}
+
+TEST( InMatchExpression, MatchesIndexKeyArrayValue ) {
+ BSONObjBuilder inArray;
+ inArray.append( "0", 4 ).append( "1", 5 ).appendRegex( "2", "abc", "" );
+ BSONObj operand = BSONObjBuilder().appendArray( "$in", inArray.obj() ).obj();
+ InMatchExpression in;
+ ASSERT( in.init( "a", operand[ "$in" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "loc" << "mockarrayvalue" << "a" << 1 ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ in.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 4 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ in.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 6 ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ in.matchesIndexKey( BSON( "" << "dummygeohash" << "" << "abcd" ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ in.matchesIndexKey( BSONObjBuilder()
+ .append( "", "dummygeohash" )
+ .appendRegex( "", "abc", "" ).obj(),
+ indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ in.matchesIndexKey( BSON( "" << "dummygeohash" << "" << "ab" ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ in.matchesIndexKey( BSON( "" << "dummygeohash" <<
+ "" << BSON_ARRAY( 8 << 5 ) ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ in.matchesIndexKey( BSON( "" << "dummygeohash" <<
+ "" << BSON_ARRAY( 8 << 9 ) ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_True ==
+ in.matchesIndexKey( BSON( "" << "dummygeohash" <<
+ "" << BSON_ARRAY( 8 << "abc" ) ), indexSpec ) );
+ ASSERT( MatchMatchExpression::PartialMatchResult_False ==
+ in.matchesIndexKey( BSON( "" << "dummygeohash" <<
+ "" << BSON_ARRAY( 8 << "ac" ) ), indexSpec ) );
+}
+*/
}