summaryrefslogtreecommitdiff
path: root/src/mongo/db/matcher/expression_array_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/matcher/expression_array_test.cpp')
-rw-r--r--src/mongo/db/matcher/expression_array_test.cpp864
1 files changed, 419 insertions, 445 deletions
diff --git a/src/mongo/db/matcher/expression_array_test.cpp b/src/mongo/db/matcher/expression_array_test.cpp
index 891d12752f6..201d11fbed4 100644
--- a/src/mongo/db/matcher/expression_array_test.cpp
+++ b/src/mongo/db/matcher/expression_array_test.cpp
@@ -38,448 +38,422 @@
namespace mongo {
- using std::unique_ptr;
-
- TEST( ElemMatchObjectMatchExpression, MatchesElementSingle ) {
- BSONObj baseOperand = BSON( "b" << 5 );
- BSONObj match = BSON( "a" << BSON_ARRAY( BSON( "b" << 5.0 ) ) );
- BSONObj notMatch = BSON( "a" << BSON_ARRAY( BSON( "b" << 6 ) ) );
- unique_ptr<ComparisonMatchExpression> eq( new EqualityMatchExpression() );
- ASSERT( eq->init( "b", baseOperand[ "b" ] ).isOK() );
- ElemMatchObjectMatchExpression op;
- ASSERT( op.init( "a", eq.release() ).isOK() );
- ASSERT( op.matchesSingleElement( match[ "a" ] ) );
- ASSERT( !op.matchesSingleElement( notMatch[ "a" ] ) );
- }
-
- TEST( ElemMatchObjectMatchExpression, MatchesElementArray ) {
- BSONObj baseOperand = BSON( "1" << 5 );
- BSONObj match = BSON( "a" << BSON_ARRAY( BSON_ARRAY( 's' << 5.0 ) ) );
- BSONObj notMatch = BSON( "a" << BSON_ARRAY( BSON_ARRAY( 5 << 6 ) ) );
- unique_ptr<ComparisonMatchExpression> eq( new EqualityMatchExpression() );
- ASSERT( eq->init( "1", baseOperand[ "1" ] ).isOK() );
- ElemMatchObjectMatchExpression op;
- ASSERT( op.init( "a", eq.release() ).isOK() );
- ASSERT( op.matchesSingleElement( match[ "a" ] ) );
- ASSERT( !op.matchesSingleElement( notMatch[ "a" ] ) );
- }
-
- TEST( ElemMatchObjectMatchExpression, MatchesElementMultiple ) {
- BSONObj baseOperand1 = BSON( "b" << 5 );
- BSONObj baseOperand2 = BSON( "b" << 6 );
- BSONObj baseOperand3 = BSON( "c" << 7 );
- BSONObj notMatch1 = BSON( "a" << BSON_ARRAY( BSON( "b" << 5 << "c" << 7 ) ) );
- BSONObj notMatch2 = BSON( "a" << BSON_ARRAY( BSON( "b" << 6 << "c" << 7 ) ) );
- BSONObj notMatch3 = BSON( "a" << BSON_ARRAY( BSON( "b" << BSON_ARRAY( 5 << 6 ) ) ) );
- BSONObj match =
- BSON( "a" << BSON_ARRAY( BSON( "b" << BSON_ARRAY( 5 << 6 ) << "c" << 7 ) ) );
- unique_ptr<ComparisonMatchExpression> eq1( new EqualityMatchExpression() );
- ASSERT( eq1->init( "b", baseOperand1[ "b" ] ).isOK() );
- unique_ptr<ComparisonMatchExpression> eq2( new EqualityMatchExpression() );
- ASSERT( eq2->init( "b", baseOperand2[ "b" ] ).isOK() );
- unique_ptr<ComparisonMatchExpression> eq3( new EqualityMatchExpression() );
- ASSERT( eq3->init( "c", baseOperand3[ "c" ] ).isOK() );
-
- unique_ptr<AndMatchExpression> andOp( new AndMatchExpression() );
- andOp->add( eq1.release() );
- andOp->add( eq2.release() );
- andOp->add( eq3.release() );
-
- ElemMatchObjectMatchExpression op;
- ASSERT( op.init( "a", andOp.release() ).isOK() );
- ASSERT( !op.matchesSingleElement( notMatch1[ "a" ] ) );
- ASSERT( !op.matchesSingleElement( notMatch2[ "a" ] ) );
- ASSERT( !op.matchesSingleElement( notMatch3[ "a" ] ) );
- ASSERT( op.matchesSingleElement( match[ "a" ] ) );
- }
-
- TEST( ElemMatchObjectMatchExpression, MatchesNonArray ) {
- BSONObj baseOperand = BSON( "b" << 5 );
- unique_ptr<ComparisonMatchExpression> eq( new EqualityMatchExpression() );
- ASSERT( eq->init( "b", baseOperand[ "b" ] ).isOK() );
- ElemMatchObjectMatchExpression op;
- ASSERT( op.init( "a", eq.release() ).isOK() );
- // Directly nested objects are not matched with $elemMatch. An intervening array is
- // required.
- ASSERT( !op.matchesBSON( BSON( "a" << BSON( "b" << 5 ) ), NULL ) );
- ASSERT( !op.matchesBSON( BSON( "a" << BSON( "0" << ( BSON( "b" << 5 ) ) ) ), NULL ) );
- ASSERT( !op.matchesBSON( BSON( "a" << 4 ), NULL ) );
- }
-
- TEST( ElemMatchObjectMatchExpression, MatchesArrayObject ) {
- BSONObj baseOperand = BSON( "b" << 5 );
- unique_ptr<ComparisonMatchExpression> eq( new EqualityMatchExpression() );
- ASSERT( eq->init( "b", baseOperand[ "b" ] ).isOK() );
- ElemMatchObjectMatchExpression op;
- ASSERT( op.init( "a", eq.release() ).isOK() );
- ASSERT( op.matchesBSON( BSON( "a" << BSON_ARRAY( BSON( "b" << 5 ) ) ), NULL ) );
- ASSERT( op.matchesBSON( BSON( "a" << BSON_ARRAY( 4 << BSON( "b" << 5 ) ) ), NULL ) );
- ASSERT( op.matchesBSON( BSON( "a" << BSON_ARRAY( BSONObj() << BSON( "b" << 5 ) ) ), NULL ) );
- ASSERT( op.matchesBSON( BSON( "a" << BSON_ARRAY( BSON( "b" << 6 ) << BSON( "b" << 5 ) ) ),
- NULL ) );
- }
-
- TEST( ElemMatchObjectMatchExpression, MatchesMultipleNamedValues ) {
- BSONObj baseOperand = BSON( "c" << 5 );
- unique_ptr<ComparisonMatchExpression> eq( new EqualityMatchExpression() );
- ASSERT( eq->init( "c", baseOperand[ "c" ] ).isOK() );
- ElemMatchObjectMatchExpression op;
- ASSERT( op.init( "a.b", eq.release() ).isOK() );
- ASSERT( op.matchesBSON( BSON( "a" <<
- BSON_ARRAY( BSON( "b" <<
- BSON_ARRAY( BSON( "c" <<
- 5 ) ) ) ) ),
- NULL ) );
- ASSERT( op.matchesBSON( BSON( "a" <<
- BSON_ARRAY( BSON( "b" <<
- BSON_ARRAY( BSON( "c" <<
- 1 ) ) ) <<
- BSON( "b" <<
- BSON_ARRAY( BSON( "c" <<
- 5 ) ) ) ) ),
- NULL ) );
- }
-
- TEST( ElemMatchObjectMatchExpression, ElemMatchKey ) {
- BSONObj baseOperand = BSON( "c" << 6 );
- unique_ptr<ComparisonMatchExpression> eq( new EqualityMatchExpression() );
- ASSERT( eq->init( "c", baseOperand[ "c" ] ).isOK() );
- ElemMatchObjectMatchExpression op;
- ASSERT( op.init( "a.b", eq.release() ).isOK() );
- MatchDetails details;
- details.requestElemMatchKey();
- ASSERT( !op.matchesBSON( BSONObj(), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( !op.matchesBSON( BSON( "a" << BSON( "b" << BSON_ARRAY( BSON( "c" << 7 ) ) ) ),
- &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( op.matchesBSON( BSON( "a" << BSON( "b" << BSON_ARRAY( 3 << BSON( "c" << 6 ) ) ) ),
- &details ) );
- ASSERT( details.hasElemMatchKey() );
- // The entry within the $elemMatch array is reported.
- ASSERT_EQUALS( "1", details.elemMatchKey() );
- ASSERT( op.matchesBSON( BSON( "a" <<
- BSON_ARRAY( 1 << 2 <<
- BSON( "b" << BSON_ARRAY( 3 <<
- 5 <<
- BSON( "c" << 6 ) ) ) ) ),
- &details ) );
- ASSERT( details.hasElemMatchKey() );
- // The entry within a parent of the $elemMatch array is reported.
- ASSERT_EQUALS( "2", details.elemMatchKey() );
- }
-
- /**
- TEST( ElemMatchObjectMatchExpression, MatchesIndexKey ) {
- BSONObj baseOperand = BSON( "b" << 5 );
- unique_ptr<ComparisonMatchExpression> eq( new ComparisonMatchExpression() );
- ASSERT( eq->init( "b", baseOperand[ "b" ] ).isOK() );
- ElemMatchObjectMatchExpression op;
- ASSERT( op.init( "a", eq.release() ).isOK() );
- IndexSpec indexSpec( BSON( "a.b" << 1 ) );
- BSONObj indexKey = BSON( "" << "5" );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- op.matchesIndexKey( indexKey, indexSpec ) );
- }
- */
-
- TEST( ElemMatchValueMatchExpression, MatchesElementSingle ) {
- BSONObj baseOperand = BSON( "$gt" << 5 );
- BSONObj match = BSON( "a" << BSON_ARRAY( 6 ) );
- BSONObj notMatch = BSON( "a" << BSON_ARRAY( 4 ) );
- unique_ptr<ComparisonMatchExpression> gt( new GTMatchExpression() );
- ASSERT( gt->init( "", baseOperand[ "$gt" ] ).isOK() );
- ElemMatchValueMatchExpression op;
- ASSERT( op.init( "a", gt.release() ).isOK() );
- ASSERT( op.matchesSingleElement( match[ "a" ] ) );
- ASSERT( !op.matchesSingleElement( notMatch[ "a" ] ) );
- }
-
- TEST( ElemMatchValueMatchExpression, MatchesElementMultiple ) {
- BSONObj baseOperand1 = BSON( "$gt" << 1 );
- BSONObj baseOperand2 = BSON( "$lt" << 10 );
- BSONObj notMatch1 = BSON( "a" << BSON_ARRAY( 0 << 1 ) );
- BSONObj notMatch2 = BSON( "a" << BSON_ARRAY( 10 << 11 ) );
- BSONObj match = BSON( "a" << BSON_ARRAY( 0 << 5 << 11 ) );
- unique_ptr<ComparisonMatchExpression> gt( new GTMatchExpression() );
- ASSERT( gt->init( "", baseOperand1[ "$gt" ] ).isOK() );
- unique_ptr<ComparisonMatchExpression> lt( new LTMatchExpression() );
- ASSERT( lt->init( "", baseOperand2[ "$lt" ] ).isOK() );
-
- ElemMatchValueMatchExpression op;
- ASSERT( op.init( "a" ).isOK() );
- op.add( gt.release() );
- op.add( lt.release() );
-
- ASSERT( !op.matchesSingleElement( notMatch1[ "a" ] ) );
- ASSERT( !op.matchesSingleElement( notMatch2[ "a" ] ) );
- ASSERT( op.matchesSingleElement( match[ "a" ] ) );
- }
-
- TEST( ElemMatchValueMatchExpression, MatchesNonArray ) {
- BSONObj baseOperand = BSON( "$gt" << 5 );
- unique_ptr<ComparisonMatchExpression> gt( new GTMatchExpression() );
- ASSERT( gt->init( "", baseOperand[ "$gt" ] ).isOK() );
- ElemMatchObjectMatchExpression op;
- ASSERT( op.init( "a", gt.release() ).isOK() );
- // Directly nested objects are not matched with $elemMatch. An intervening array is
- // required.
- ASSERT( !op.matchesBSON( BSON( "a" << 6 ), NULL ) );
- ASSERT( !op.matchesBSON( BSON( "a" << BSON( "0" << 6 ) ), NULL ) );
- }
-
- TEST( ElemMatchValueMatchExpression, MatchesArrayScalar ) {
- BSONObj baseOperand = BSON( "$gt" << 5 );
- unique_ptr<ComparisonMatchExpression> gt( new GTMatchExpression() );
- ASSERT( gt->init( "", baseOperand[ "$gt" ] ).isOK() );
- ElemMatchValueMatchExpression op;
- ASSERT( op.init( "a", gt.release() ).isOK() );
- ASSERT( op.matchesBSON( BSON( "a" << BSON_ARRAY( 6 ) ), NULL ) );
- ASSERT( op.matchesBSON( BSON( "a" << BSON_ARRAY( 4 << 6 ) ), NULL ) );
- ASSERT( op.matchesBSON( BSON( "a" << BSON_ARRAY( BSONObj() << 7 ) ), NULL ) );
- }
-
- TEST( ElemMatchValueMatchExpression, MatchesMultipleNamedValues ) {
- BSONObj baseOperand = BSON( "$gt" << 5 );
- unique_ptr<ComparisonMatchExpression> gt( new GTMatchExpression() );
- ASSERT( gt->init( "", baseOperand[ "$gt" ] ).isOK() );
- ElemMatchValueMatchExpression op;
- ASSERT( op.init( "a.b", gt.release() ).isOK() );
- ASSERT( op.matchesBSON( BSON( "a" << BSON_ARRAY( BSON( "b" << BSON_ARRAY( 6 ) ) ) ), NULL ) );
- ASSERT( op.matchesBSON( BSON( "a" <<
- BSON_ARRAY( BSON( "b" << BSON_ARRAY( 4 ) ) <<
- BSON( "b" << BSON_ARRAY( 4 << 6 ) ) ) ),
- NULL ) );
- }
-
- TEST( ElemMatchValueMatchExpression, ElemMatchKey ) {
- BSONObj baseOperand = BSON( "$gt" << 6 );
- unique_ptr<ComparisonMatchExpression> gt( new GTMatchExpression() );
- ASSERT( gt->init( "", baseOperand[ "$gt" ] ).isOK() );
- ElemMatchValueMatchExpression op;
- ASSERT( op.init( "a.b", gt.release() ).isOK() );
- MatchDetails details;
- details.requestElemMatchKey();
- ASSERT( !op.matchesBSON( BSONObj(), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( !op.matchesBSON( BSON( "a" << BSON( "b" << BSON_ARRAY( 2 ) ) ),
- &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( op.matchesBSON( BSON( "a" << BSON( "b" << BSON_ARRAY( 3 << 7 ) ) ),
- &details ) );
- ASSERT( details.hasElemMatchKey() );
- // The entry within the $elemMatch array is reported.
- ASSERT_EQUALS( "1", details.elemMatchKey() );
- ASSERT( op.matchesBSON( BSON( "a" <<
- BSON_ARRAY( 1 << 2 <<
- BSON( "b" << BSON_ARRAY( 3 << 7 ) ) ) ),
- &details ) );
- ASSERT( details.hasElemMatchKey() );
- // The entry within a parent of the $elemMatch array is reported.
- ASSERT_EQUALS( "2", details.elemMatchKey() );
- }
-
- /**
- TEST( ElemMatchValueMatchExpression, MatchesIndexKey ) {
- BSONObj baseOperand = BSON( "$lt" << 5 );
- unique_ptr<LtOp> lt( new ComparisonMatchExpression() );
- ASSERT( lt->init( "a", baseOperand[ "$lt" ] ).isOK() );
- ElemMatchValueMatchExpression op;
- ASSERT( op.init( "a", lt.release() ).isOK() );
- IndexSpec indexSpec( BSON( "a" << 1 ) );
- BSONObj indexKey = BSON( "" << "3" );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- op.matchesIndexKey( indexKey, indexSpec ) );
- }
- */
-
- TEST( AndOfElemMatch, MatchesElement ) {
-
-
- BSONObj baseOperanda1 = BSON( "a" << 1 );
- unique_ptr<ComparisonMatchExpression> eqa1( new EqualityMatchExpression() );
- ASSERT( eqa1->init( "a", baseOperanda1[ "a" ] ).isOK() );
-
- BSONObj baseOperandb1 = BSON( "b" << 1 );
- unique_ptr<ComparisonMatchExpression> eqb1( new EqualityMatchExpression() );
- ASSERT( eqb1->init( "b", baseOperandb1[ "b" ] ).isOK() );
-
- unique_ptr<AndMatchExpression> and1( new AndMatchExpression() );
- and1->add( eqa1.release() );
- and1->add( eqb1.release() );
- // and1 = { a : 1, b : 1 }
-
- unique_ptr<ElemMatchObjectMatchExpression> elemMatch1( new ElemMatchObjectMatchExpression() );
- elemMatch1->init( "x", and1.release() );
- // elemMatch1 = { x : { $elemMatch : { a : 1, b : 1 } } }
-
- BSONObj baseOperanda2 = BSON( "a" << 2 );
- unique_ptr<ComparisonMatchExpression> eqa2( new EqualityMatchExpression() );
- ASSERT( eqa2->init( "a", baseOperanda2[ "a" ] ).isOK() );
-
- BSONObj baseOperandb2 = BSON( "b" << 2 );
- unique_ptr<ComparisonMatchExpression> eqb2( new EqualityMatchExpression() );
- ASSERT( eqb2->init( "b", baseOperandb2[ "b" ] ).isOK() );
-
- unique_ptr<AndMatchExpression> and2( new AndMatchExpression() );
- and2->add( eqa2.release() );
- and2->add( eqb2.release() );
- // and2 = { a : 2, b : 2 }
-
- unique_ptr<ElemMatchObjectMatchExpression> elemMatch2( new ElemMatchObjectMatchExpression() );
- elemMatch2->init( "x", and2.release() );
- // elemMatch2 = { x : { $elemMatch : { a : 2, b : 2 } } }
-
- unique_ptr<AndMatchExpression> andOfEM( new AndMatchExpression() );
- andOfEM->add( elemMatch1.release() );
- andOfEM->add( elemMatch2.release() );
-
- BSONObj nonArray = BSON( "x" << 4 );
- ASSERT( !andOfEM->matchesSingleElement( nonArray[ "x" ] ) );
- BSONObj emptyArray = BSON( "x" << BSONArray() );
- ASSERT( !andOfEM->matchesSingleElement( emptyArray[ "x" ] ) );
- BSONObj nonObjArray = BSON( "x" << BSON_ARRAY( 4 ) );
- ASSERT( !andOfEM->matchesSingleElement( nonObjArray[ "x" ] ) );
- BSONObj singleObjMatch = BSON( "x" << BSON_ARRAY( BSON( "a" << 1 << "b" << 1 ) ) );
- ASSERT( !andOfEM->matchesSingleElement( singleObjMatch[ "x" ] ) );
- BSONObj otherObjMatch = BSON( "x" << BSON_ARRAY( BSON( "a" << 2 << "b" << 2 ) ) );
- ASSERT( !andOfEM->matchesSingleElement( otherObjMatch[ "x" ] ) );
- BSONObj bothObjMatch = BSON( "x" << BSON_ARRAY( BSON( "a" << 1 << "b" << 1 ) <<
- BSON( "a" << 2 << "b" << 2 ) ) );
- ASSERT( andOfEM->matchesSingleElement( bothObjMatch[ "x" ] ) );
- BSONObj noObjMatch = BSON( "x" << BSON_ARRAY( BSON( "a" << 1 << "b" << 2 ) <<
- BSON( "a" << 2 << "b" << 1 ) ) );
- ASSERT( !andOfEM->matchesSingleElement( noObjMatch[ "x" ] ) );
- }
-
- TEST( AndOfElemMatch, Matches ) {
- BSONObj baseOperandgt1 = BSON( "$gt" << 1 );
- unique_ptr<ComparisonMatchExpression> gt1( new GTMatchExpression() );
- ASSERT( gt1->init( "", baseOperandgt1[ "$gt" ] ).isOK() );
-
- BSONObj baseOperandlt1 = BSON( "$lt" << 10 );
- unique_ptr<ComparisonMatchExpression> lt1( new LTMatchExpression() );
- ASSERT( lt1->init( "", baseOperandlt1[ "$lt" ] ).isOK() );
-
- unique_ptr<ElemMatchValueMatchExpression> elemMatch1( new ElemMatchValueMatchExpression() );
- elemMatch1->init( "x" );
- elemMatch1->add( gt1.release() );
- elemMatch1->add( lt1.release() );
- // elemMatch1 = { x : { $elemMatch : { $gt : 1 , $lt : 10 } } }
-
- BSONObj baseOperandgt2 = BSON( "$gt" << 101 );
- unique_ptr<ComparisonMatchExpression> gt2( new GTMatchExpression() );
- ASSERT( gt2->init( "", baseOperandgt2[ "$gt" ] ).isOK() );
-
- BSONObj baseOperandlt2 = BSON( "$lt" << 110 );
- unique_ptr<ComparisonMatchExpression> lt2( new LTMatchExpression() );
- ASSERT( lt2->init( "", baseOperandlt2[ "$lt" ] ).isOK() );
-
- unique_ptr<ElemMatchValueMatchExpression> elemMatch2( new ElemMatchValueMatchExpression() );
- elemMatch2->init( "x" );
- elemMatch2->add( gt2.release() );
- elemMatch2->add( lt2.release() );
- // elemMatch2 = { x : { $elemMatch : { $gt : 101 , $lt : 110 } } }
-
- unique_ptr<AndMatchExpression> andOfEM( new AndMatchExpression() );
- andOfEM->add( elemMatch1.release() );
- andOfEM->add( elemMatch2.release() );
-
- BSONObj nonArray = BSON( "x" << 4 );
- ASSERT( !andOfEM->matchesBSON( nonArray, NULL ) );
- BSONObj emptyArray = BSON( "x" << BSONArray() );
- ASSERT( !andOfEM->matchesBSON( emptyArray, NULL ) );
- BSONObj nonNumberArray = BSON( "x" << BSON_ARRAY( "q" ) );
- ASSERT( !andOfEM->matchesBSON( nonNumberArray, NULL ) );
- BSONObj singleMatch = BSON( "x" << BSON_ARRAY( 5 ) );
- ASSERT( !andOfEM->matchesBSON( singleMatch, NULL ) );
- BSONObj otherMatch = BSON( "x" << BSON_ARRAY( 105 ) );
- ASSERT( !andOfEM->matchesBSON( otherMatch, NULL ) );
- BSONObj bothMatch = BSON( "x" << BSON_ARRAY( 5 << 105 ) );
- ASSERT( andOfEM->matchesBSON( bothMatch, NULL ) );
- BSONObj neitherMatch = BSON( "x" << BSON_ARRAY( 0 << 200 ) );
- ASSERT( !andOfEM->matchesBSON( neitherMatch, NULL ) );
- }
-
- TEST( SizeMatchExpression, MatchesElement ) {
- BSONObj match = BSON( "a" << BSON_ARRAY( 5 << 6 ) );
- BSONObj notMatch = BSON( "a" << BSON_ARRAY( 5 ) );
- SizeMatchExpression size;
- ASSERT( size.init( "", 2 ).isOK() );
- ASSERT( size.matchesSingleElement( match.firstElement() ) );
- ASSERT( !size.matchesSingleElement( notMatch.firstElement() ) );
- }
-
- TEST( SizeMatchExpression, MatchesNonArray ) {
- // Non arrays do not match.
- BSONObj stringValue = BSON( "a" << "z" );
- BSONObj numberValue = BSON( "a" << 0 );
- BSONObj arrayValue = BSON( "a" << BSONArray() );
- SizeMatchExpression size;
- ASSERT( size.init( "", 0 ).isOK() );
- ASSERT( !size.matchesSingleElement( stringValue.firstElement() ) );
- ASSERT( !size.matchesSingleElement( numberValue.firstElement() ) );
- ASSERT( size.matchesSingleElement( arrayValue.firstElement() ) );
- }
-
- TEST( SizeMatchExpression, MatchesArray ) {
- SizeMatchExpression size;
- ASSERT( size.init( "a", 2 ).isOK() );
- ASSERT( size.matchesBSON( BSON( "a" << BSON_ARRAY( 4 << 5.5 ) ), NULL ) );
- // Arrays are not unwound to look for matching subarrays.
- ASSERT( !size.matchesBSON( BSON( "a" << BSON_ARRAY( 4 << 5.5 << BSON_ARRAY( 1 << 2 ) ) ),
- NULL ) );
- }
-
- TEST( SizeMatchExpression, MatchesNestedArray ) {
- SizeMatchExpression size;
- ASSERT( size.init( "a.2", 2 ).isOK() );
- // A numerically referenced nested array is matched.
- ASSERT( size.matchesBSON( BSON( "a" << BSON_ARRAY( 4 << 5.5 << BSON_ARRAY( 1 << 2 ) ) ),
- NULL ) );
- }
-
- TEST( SizeMatchExpression, ElemMatchKey ) {
- SizeMatchExpression size;
- ASSERT( size.init( "a.b", 3 ).isOK() );
- MatchDetails details;
- details.requestElemMatchKey();
- ASSERT( !size.matchesBSON( BSON( "a" << 1 ), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( size.matchesBSON( BSON( "a" << BSON( "b" << BSON_ARRAY( 1 << 2 << 3 ) ) ), &details ) );
- ASSERT( !details.hasElemMatchKey() );
- ASSERT( size.matchesBSON( BSON( "a" <<
- BSON_ARRAY( 2 <<
- BSON( "b" << BSON_ARRAY( 1 << 2 << 3 ) ) ) ),
- &details ) );
- ASSERT( details.hasElemMatchKey() );
- ASSERT_EQUALS( "1", details.elemMatchKey() );
- }
-
- TEST( SizeMatchExpression, Equivalent ) {
- SizeMatchExpression e1;
- SizeMatchExpression e2;
- SizeMatchExpression e3;
-
- e1.init( "a", 5 );
- e2.init( "a", 6 );
- e3.init( "v", 5 );
-
- ASSERT( e1.equivalent( &e1 ) );
- ASSERT( !e1.equivalent( &e2 ) );
- ASSERT( !e1.equivalent( &e3 ) );
- }
-
- /**
- TEST( SizeMatchExpression, MatchesIndexKey ) {
- BSONObj operand = BSON( "$size" << 4 );
- SizeMatchExpression size;
- ASSERT( size.init( "a", operand[ "$size" ] ).isOK() );
- IndexSpec indexSpec( BSON( "a" << 1 ) );
- BSONObj indexKey = BSON( "" << 1 );
- ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
- size.matchesIndexKey( indexKey, indexSpec ) );
- }
- */
-
-} // namespace mongo
+using std::unique_ptr;
+
+TEST(ElemMatchObjectMatchExpression, MatchesElementSingle) {
+ BSONObj baseOperand = BSON("b" << 5);
+ BSONObj match = BSON("a" << BSON_ARRAY(BSON("b" << 5.0)));
+ BSONObj notMatch = BSON("a" << BSON_ARRAY(BSON("b" << 6)));
+ unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression());
+ ASSERT(eq->init("b", baseOperand["b"]).isOK());
+ ElemMatchObjectMatchExpression op;
+ ASSERT(op.init("a", eq.release()).isOK());
+ ASSERT(op.matchesSingleElement(match["a"]));
+ ASSERT(!op.matchesSingleElement(notMatch["a"]));
+}
+
+TEST(ElemMatchObjectMatchExpression, MatchesElementArray) {
+ BSONObj baseOperand = BSON("1" << 5);
+ BSONObj match = BSON("a" << BSON_ARRAY(BSON_ARRAY('s' << 5.0)));
+ BSONObj notMatch = BSON("a" << BSON_ARRAY(BSON_ARRAY(5 << 6)));
+ unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression());
+ ASSERT(eq->init("1", baseOperand["1"]).isOK());
+ ElemMatchObjectMatchExpression op;
+ ASSERT(op.init("a", eq.release()).isOK());
+ ASSERT(op.matchesSingleElement(match["a"]));
+ ASSERT(!op.matchesSingleElement(notMatch["a"]));
+}
+
+TEST(ElemMatchObjectMatchExpression, MatchesElementMultiple) {
+ BSONObj baseOperand1 = BSON("b" << 5);
+ BSONObj baseOperand2 = BSON("b" << 6);
+ BSONObj baseOperand3 = BSON("c" << 7);
+ BSONObj notMatch1 = BSON("a" << BSON_ARRAY(BSON("b" << 5 << "c" << 7)));
+ BSONObj notMatch2 = BSON("a" << BSON_ARRAY(BSON("b" << 6 << "c" << 7)));
+ BSONObj notMatch3 = BSON("a" << BSON_ARRAY(BSON("b" << BSON_ARRAY(5 << 6))));
+ BSONObj match = BSON("a" << BSON_ARRAY(BSON("b" << BSON_ARRAY(5 << 6) << "c" << 7)));
+ unique_ptr<ComparisonMatchExpression> eq1(new EqualityMatchExpression());
+ ASSERT(eq1->init("b", baseOperand1["b"]).isOK());
+ unique_ptr<ComparisonMatchExpression> eq2(new EqualityMatchExpression());
+ ASSERT(eq2->init("b", baseOperand2["b"]).isOK());
+ unique_ptr<ComparisonMatchExpression> eq3(new EqualityMatchExpression());
+ ASSERT(eq3->init("c", baseOperand3["c"]).isOK());
+
+ unique_ptr<AndMatchExpression> andOp(new AndMatchExpression());
+ andOp->add(eq1.release());
+ andOp->add(eq2.release());
+ andOp->add(eq3.release());
+
+ ElemMatchObjectMatchExpression op;
+ ASSERT(op.init("a", andOp.release()).isOK());
+ ASSERT(!op.matchesSingleElement(notMatch1["a"]));
+ ASSERT(!op.matchesSingleElement(notMatch2["a"]));
+ ASSERT(!op.matchesSingleElement(notMatch3["a"]));
+ ASSERT(op.matchesSingleElement(match["a"]));
+}
+
+TEST(ElemMatchObjectMatchExpression, MatchesNonArray) {
+ BSONObj baseOperand = BSON("b" << 5);
+ unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression());
+ ASSERT(eq->init("b", baseOperand["b"]).isOK());
+ ElemMatchObjectMatchExpression op;
+ ASSERT(op.init("a", eq.release()).isOK());
+ // Directly nested objects are not matched with $elemMatch. An intervening array is
+ // required.
+ ASSERT(!op.matchesBSON(BSON("a" << BSON("b" << 5)), NULL));
+ ASSERT(!op.matchesBSON(BSON("a" << BSON("0" << (BSON("b" << 5)))), NULL));
+ ASSERT(!op.matchesBSON(BSON("a" << 4), NULL));
+}
+
+TEST(ElemMatchObjectMatchExpression, MatchesArrayObject) {
+ BSONObj baseOperand = BSON("b" << 5);
+ unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression());
+ ASSERT(eq->init("b", baseOperand["b"]).isOK());
+ ElemMatchObjectMatchExpression op;
+ ASSERT(op.init("a", eq.release()).isOK());
+ ASSERT(op.matchesBSON(BSON("a" << BSON_ARRAY(BSON("b" << 5))), NULL));
+ ASSERT(op.matchesBSON(BSON("a" << BSON_ARRAY(4 << BSON("b" << 5))), NULL));
+ ASSERT(op.matchesBSON(BSON("a" << BSON_ARRAY(BSONObj() << BSON("b" << 5))), NULL));
+ ASSERT(op.matchesBSON(BSON("a" << BSON_ARRAY(BSON("b" << 6) << BSON("b" << 5))), NULL));
+}
+
+TEST(ElemMatchObjectMatchExpression, MatchesMultipleNamedValues) {
+ BSONObj baseOperand = BSON("c" << 5);
+ unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression());
+ ASSERT(eq->init("c", baseOperand["c"]).isOK());
+ ElemMatchObjectMatchExpression op;
+ ASSERT(op.init("a.b", eq.release()).isOK());
+ ASSERT(op.matchesBSON(BSON("a" << BSON_ARRAY(BSON("b" << BSON_ARRAY(BSON("c" << 5))))), NULL));
+ ASSERT(op.matchesBSON(BSON("a" << BSON_ARRAY(BSON("b" << BSON_ARRAY(BSON("c" << 1)))
+ << BSON("b" << BSON_ARRAY(BSON("c" << 5))))),
+ NULL));
+}
+
+TEST(ElemMatchObjectMatchExpression, ElemMatchKey) {
+ BSONObj baseOperand = BSON("c" << 6);
+ unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression());
+ ASSERT(eq->init("c", baseOperand["c"]).isOK());
+ ElemMatchObjectMatchExpression op;
+ ASSERT(op.init("a.b", eq.release()).isOK());
+ MatchDetails details;
+ details.requestElemMatchKey();
+ ASSERT(!op.matchesBSON(BSONObj(), &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(!op.matchesBSON(BSON("a" << BSON("b" << BSON_ARRAY(BSON("c" << 7)))), &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(op.matchesBSON(BSON("a" << BSON("b" << BSON_ARRAY(3 << BSON("c" << 6)))), &details));
+ ASSERT(details.hasElemMatchKey());
+ // The entry within the $elemMatch array is reported.
+ ASSERT_EQUALS("1", details.elemMatchKey());
+ ASSERT(op.matchesBSON(
+ BSON("a" << BSON_ARRAY(1 << 2 << BSON("b" << BSON_ARRAY(3 << 5 << BSON("c" << 6))))),
+ &details));
+ ASSERT(details.hasElemMatchKey());
+ // The entry within a parent of the $elemMatch array is reported.
+ ASSERT_EQUALS("2", details.elemMatchKey());
+}
+
+/**
+TEST( ElemMatchObjectMatchExpression, MatchesIndexKey ) {
+ BSONObj baseOperand = BSON( "b" << 5 );
+ unique_ptr<ComparisonMatchExpression> eq( new ComparisonMatchExpression() );
+ ASSERT( eq->init( "b", baseOperand[ "b" ] ).isOK() );
+ ElemMatchObjectMatchExpression op;
+ ASSERT( op.init( "a", eq.release() ).isOK() );
+ IndexSpec indexSpec( BSON( "a.b" << 1 ) );
+ BSONObj indexKey = BSON( "" << "5" );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ op.matchesIndexKey( indexKey, indexSpec ) );
+}
+*/
+
+TEST(ElemMatchValueMatchExpression, MatchesElementSingle) {
+ BSONObj baseOperand = BSON("$gt" << 5);
+ BSONObj match = BSON("a" << BSON_ARRAY(6));
+ BSONObj notMatch = BSON("a" << BSON_ARRAY(4));
+ unique_ptr<ComparisonMatchExpression> gt(new GTMatchExpression());
+ ASSERT(gt->init("", baseOperand["$gt"]).isOK());
+ ElemMatchValueMatchExpression op;
+ ASSERT(op.init("a", gt.release()).isOK());
+ ASSERT(op.matchesSingleElement(match["a"]));
+ ASSERT(!op.matchesSingleElement(notMatch["a"]));
+}
+
+TEST(ElemMatchValueMatchExpression, MatchesElementMultiple) {
+ BSONObj baseOperand1 = BSON("$gt" << 1);
+ BSONObj baseOperand2 = BSON("$lt" << 10);
+ BSONObj notMatch1 = BSON("a" << BSON_ARRAY(0 << 1));
+ BSONObj notMatch2 = BSON("a" << BSON_ARRAY(10 << 11));
+ BSONObj match = BSON("a" << BSON_ARRAY(0 << 5 << 11));
+ unique_ptr<ComparisonMatchExpression> gt(new GTMatchExpression());
+ ASSERT(gt->init("", baseOperand1["$gt"]).isOK());
+ unique_ptr<ComparisonMatchExpression> lt(new LTMatchExpression());
+ ASSERT(lt->init("", baseOperand2["$lt"]).isOK());
+
+ ElemMatchValueMatchExpression op;
+ ASSERT(op.init("a").isOK());
+ op.add(gt.release());
+ op.add(lt.release());
+
+ ASSERT(!op.matchesSingleElement(notMatch1["a"]));
+ ASSERT(!op.matchesSingleElement(notMatch2["a"]));
+ ASSERT(op.matchesSingleElement(match["a"]));
+}
+
+TEST(ElemMatchValueMatchExpression, MatchesNonArray) {
+ BSONObj baseOperand = BSON("$gt" << 5);
+ unique_ptr<ComparisonMatchExpression> gt(new GTMatchExpression());
+ ASSERT(gt->init("", baseOperand["$gt"]).isOK());
+ ElemMatchObjectMatchExpression op;
+ ASSERT(op.init("a", gt.release()).isOK());
+ // Directly nested objects are not matched with $elemMatch. An intervening array is
+ // required.
+ ASSERT(!op.matchesBSON(BSON("a" << 6), NULL));
+ ASSERT(!op.matchesBSON(BSON("a" << BSON("0" << 6)), NULL));
+}
+
+TEST(ElemMatchValueMatchExpression, MatchesArrayScalar) {
+ BSONObj baseOperand = BSON("$gt" << 5);
+ unique_ptr<ComparisonMatchExpression> gt(new GTMatchExpression());
+ ASSERT(gt->init("", baseOperand["$gt"]).isOK());
+ ElemMatchValueMatchExpression op;
+ ASSERT(op.init("a", gt.release()).isOK());
+ ASSERT(op.matchesBSON(BSON("a" << BSON_ARRAY(6)), NULL));
+ ASSERT(op.matchesBSON(BSON("a" << BSON_ARRAY(4 << 6)), NULL));
+ ASSERT(op.matchesBSON(BSON("a" << BSON_ARRAY(BSONObj() << 7)), NULL));
+}
+
+TEST(ElemMatchValueMatchExpression, MatchesMultipleNamedValues) {
+ BSONObj baseOperand = BSON("$gt" << 5);
+ unique_ptr<ComparisonMatchExpression> gt(new GTMatchExpression());
+ ASSERT(gt->init("", baseOperand["$gt"]).isOK());
+ ElemMatchValueMatchExpression op;
+ ASSERT(op.init("a.b", gt.release()).isOK());
+ ASSERT(op.matchesBSON(BSON("a" << BSON_ARRAY(BSON("b" << BSON_ARRAY(6)))), NULL));
+ ASSERT(op.matchesBSON(
+ BSON("a" << BSON_ARRAY(BSON("b" << BSON_ARRAY(4)) << BSON("b" << BSON_ARRAY(4 << 6)))),
+ NULL));
+}
+
+TEST(ElemMatchValueMatchExpression, ElemMatchKey) {
+ BSONObj baseOperand = BSON("$gt" << 6);
+ unique_ptr<ComparisonMatchExpression> gt(new GTMatchExpression());
+ ASSERT(gt->init("", baseOperand["$gt"]).isOK());
+ ElemMatchValueMatchExpression op;
+ ASSERT(op.init("a.b", gt.release()).isOK());
+ MatchDetails details;
+ details.requestElemMatchKey();
+ ASSERT(!op.matchesBSON(BSONObj(), &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(!op.matchesBSON(BSON("a" << BSON("b" << BSON_ARRAY(2))), &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(op.matchesBSON(BSON("a" << BSON("b" << BSON_ARRAY(3 << 7))), &details));
+ ASSERT(details.hasElemMatchKey());
+ // The entry within the $elemMatch array is reported.
+ ASSERT_EQUALS("1", details.elemMatchKey());
+ ASSERT(op.matchesBSON(BSON("a" << BSON_ARRAY(1 << 2 << BSON("b" << BSON_ARRAY(3 << 7)))),
+ &details));
+ ASSERT(details.hasElemMatchKey());
+ // The entry within a parent of the $elemMatch array is reported.
+ ASSERT_EQUALS("2", details.elemMatchKey());
+}
+
+/**
+TEST( ElemMatchValueMatchExpression, MatchesIndexKey ) {
+ BSONObj baseOperand = BSON( "$lt" << 5 );
+ unique_ptr<LtOp> lt( new ComparisonMatchExpression() );
+ ASSERT( lt->init( "a", baseOperand[ "$lt" ] ).isOK() );
+ ElemMatchValueMatchExpression op;
+ ASSERT( op.init( "a", lt.release() ).isOK() );
+ IndexSpec indexSpec( BSON( "a" << 1 ) );
+ BSONObj indexKey = BSON( "" << "3" );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ op.matchesIndexKey( indexKey, indexSpec ) );
+}
+*/
+
+TEST(AndOfElemMatch, MatchesElement) {
+ BSONObj baseOperanda1 = BSON("a" << 1);
+ unique_ptr<ComparisonMatchExpression> eqa1(new EqualityMatchExpression());
+ ASSERT(eqa1->init("a", baseOperanda1["a"]).isOK());
+
+ BSONObj baseOperandb1 = BSON("b" << 1);
+ unique_ptr<ComparisonMatchExpression> eqb1(new EqualityMatchExpression());
+ ASSERT(eqb1->init("b", baseOperandb1["b"]).isOK());
+
+ unique_ptr<AndMatchExpression> and1(new AndMatchExpression());
+ and1->add(eqa1.release());
+ and1->add(eqb1.release());
+ // and1 = { a : 1, b : 1 }
+
+ unique_ptr<ElemMatchObjectMatchExpression> elemMatch1(new ElemMatchObjectMatchExpression());
+ elemMatch1->init("x", and1.release());
+ // elemMatch1 = { x : { $elemMatch : { a : 1, b : 1 } } }
+
+ BSONObj baseOperanda2 = BSON("a" << 2);
+ unique_ptr<ComparisonMatchExpression> eqa2(new EqualityMatchExpression());
+ ASSERT(eqa2->init("a", baseOperanda2["a"]).isOK());
+
+ BSONObj baseOperandb2 = BSON("b" << 2);
+ unique_ptr<ComparisonMatchExpression> eqb2(new EqualityMatchExpression());
+ ASSERT(eqb2->init("b", baseOperandb2["b"]).isOK());
+
+ unique_ptr<AndMatchExpression> and2(new AndMatchExpression());
+ and2->add(eqa2.release());
+ and2->add(eqb2.release());
+ // and2 = { a : 2, b : 2 }
+
+ unique_ptr<ElemMatchObjectMatchExpression> elemMatch2(new ElemMatchObjectMatchExpression());
+ elemMatch2->init("x", and2.release());
+ // elemMatch2 = { x : { $elemMatch : { a : 2, b : 2 } } }
+
+ unique_ptr<AndMatchExpression> andOfEM(new AndMatchExpression());
+ andOfEM->add(elemMatch1.release());
+ andOfEM->add(elemMatch2.release());
+
+ BSONObj nonArray = BSON("x" << 4);
+ ASSERT(!andOfEM->matchesSingleElement(nonArray["x"]));
+ BSONObj emptyArray = BSON("x" << BSONArray());
+ ASSERT(!andOfEM->matchesSingleElement(emptyArray["x"]));
+ BSONObj nonObjArray = BSON("x" << BSON_ARRAY(4));
+ ASSERT(!andOfEM->matchesSingleElement(nonObjArray["x"]));
+ BSONObj singleObjMatch = BSON("x" << BSON_ARRAY(BSON("a" << 1 << "b" << 1)));
+ ASSERT(!andOfEM->matchesSingleElement(singleObjMatch["x"]));
+ BSONObj otherObjMatch = BSON("x" << BSON_ARRAY(BSON("a" << 2 << "b" << 2)));
+ ASSERT(!andOfEM->matchesSingleElement(otherObjMatch["x"]));
+ BSONObj bothObjMatch =
+ BSON("x" << BSON_ARRAY(BSON("a" << 1 << "b" << 1) << BSON("a" << 2 << "b" << 2)));
+ ASSERT(andOfEM->matchesSingleElement(bothObjMatch["x"]));
+ BSONObj noObjMatch =
+ BSON("x" << BSON_ARRAY(BSON("a" << 1 << "b" << 2) << BSON("a" << 2 << "b" << 1)));
+ ASSERT(!andOfEM->matchesSingleElement(noObjMatch["x"]));
+}
+
+TEST(AndOfElemMatch, Matches) {
+ BSONObj baseOperandgt1 = BSON("$gt" << 1);
+ unique_ptr<ComparisonMatchExpression> gt1(new GTMatchExpression());
+ ASSERT(gt1->init("", baseOperandgt1["$gt"]).isOK());
+
+ BSONObj baseOperandlt1 = BSON("$lt" << 10);
+ unique_ptr<ComparisonMatchExpression> lt1(new LTMatchExpression());
+ ASSERT(lt1->init("", baseOperandlt1["$lt"]).isOK());
+
+ unique_ptr<ElemMatchValueMatchExpression> elemMatch1(new ElemMatchValueMatchExpression());
+ elemMatch1->init("x");
+ elemMatch1->add(gt1.release());
+ elemMatch1->add(lt1.release());
+ // elemMatch1 = { x : { $elemMatch : { $gt : 1 , $lt : 10 } } }
+
+ BSONObj baseOperandgt2 = BSON("$gt" << 101);
+ unique_ptr<ComparisonMatchExpression> gt2(new GTMatchExpression());
+ ASSERT(gt2->init("", baseOperandgt2["$gt"]).isOK());
+
+ BSONObj baseOperandlt2 = BSON("$lt" << 110);
+ unique_ptr<ComparisonMatchExpression> lt2(new LTMatchExpression());
+ ASSERT(lt2->init("", baseOperandlt2["$lt"]).isOK());
+
+ unique_ptr<ElemMatchValueMatchExpression> elemMatch2(new ElemMatchValueMatchExpression());
+ elemMatch2->init("x");
+ elemMatch2->add(gt2.release());
+ elemMatch2->add(lt2.release());
+ // elemMatch2 = { x : { $elemMatch : { $gt : 101 , $lt : 110 } } }
+
+ unique_ptr<AndMatchExpression> andOfEM(new AndMatchExpression());
+ andOfEM->add(elemMatch1.release());
+ andOfEM->add(elemMatch2.release());
+
+ BSONObj nonArray = BSON("x" << 4);
+ ASSERT(!andOfEM->matchesBSON(nonArray, NULL));
+ BSONObj emptyArray = BSON("x" << BSONArray());
+ ASSERT(!andOfEM->matchesBSON(emptyArray, NULL));
+ BSONObj nonNumberArray = BSON("x" << BSON_ARRAY("q"));
+ ASSERT(!andOfEM->matchesBSON(nonNumberArray, NULL));
+ BSONObj singleMatch = BSON("x" << BSON_ARRAY(5));
+ ASSERT(!andOfEM->matchesBSON(singleMatch, NULL));
+ BSONObj otherMatch = BSON("x" << BSON_ARRAY(105));
+ ASSERT(!andOfEM->matchesBSON(otherMatch, NULL));
+ BSONObj bothMatch = BSON("x" << BSON_ARRAY(5 << 105));
+ ASSERT(andOfEM->matchesBSON(bothMatch, NULL));
+ BSONObj neitherMatch = BSON("x" << BSON_ARRAY(0 << 200));
+ ASSERT(!andOfEM->matchesBSON(neitherMatch, NULL));
+}
+
+TEST(SizeMatchExpression, MatchesElement) {
+ BSONObj match = BSON("a" << BSON_ARRAY(5 << 6));
+ BSONObj notMatch = BSON("a" << BSON_ARRAY(5));
+ SizeMatchExpression size;
+ ASSERT(size.init("", 2).isOK());
+ ASSERT(size.matchesSingleElement(match.firstElement()));
+ ASSERT(!size.matchesSingleElement(notMatch.firstElement()));
+}
+
+TEST(SizeMatchExpression, MatchesNonArray) {
+ // Non arrays do not match.
+ BSONObj stringValue = BSON("a"
+ << "z");
+ BSONObj numberValue = BSON("a" << 0);
+ BSONObj arrayValue = BSON("a" << BSONArray());
+ SizeMatchExpression size;
+ ASSERT(size.init("", 0).isOK());
+ ASSERT(!size.matchesSingleElement(stringValue.firstElement()));
+ ASSERT(!size.matchesSingleElement(numberValue.firstElement()));
+ ASSERT(size.matchesSingleElement(arrayValue.firstElement()));
+}
+
+TEST(SizeMatchExpression, MatchesArray) {
+ SizeMatchExpression size;
+ ASSERT(size.init("a", 2).isOK());
+ ASSERT(size.matchesBSON(BSON("a" << BSON_ARRAY(4 << 5.5)), NULL));
+ // Arrays are not unwound to look for matching subarrays.
+ ASSERT(!size.matchesBSON(BSON("a" << BSON_ARRAY(4 << 5.5 << BSON_ARRAY(1 << 2))), NULL));
+}
+
+TEST(SizeMatchExpression, MatchesNestedArray) {
+ SizeMatchExpression size;
+ ASSERT(size.init("a.2", 2).isOK());
+ // A numerically referenced nested array is matched.
+ ASSERT(size.matchesBSON(BSON("a" << BSON_ARRAY(4 << 5.5 << BSON_ARRAY(1 << 2))), NULL));
+}
+
+TEST(SizeMatchExpression, ElemMatchKey) {
+ SizeMatchExpression size;
+ ASSERT(size.init("a.b", 3).isOK());
+ MatchDetails details;
+ details.requestElemMatchKey();
+ ASSERT(!size.matchesBSON(BSON("a" << 1), &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(size.matchesBSON(BSON("a" << BSON("b" << BSON_ARRAY(1 << 2 << 3))), &details));
+ ASSERT(!details.hasElemMatchKey());
+ ASSERT(size.matchesBSON(BSON("a" << BSON_ARRAY(2 << BSON("b" << BSON_ARRAY(1 << 2 << 3)))),
+ &details));
+ ASSERT(details.hasElemMatchKey());
+ ASSERT_EQUALS("1", details.elemMatchKey());
+}
+
+TEST(SizeMatchExpression, Equivalent) {
+ SizeMatchExpression e1;
+ SizeMatchExpression e2;
+ SizeMatchExpression e3;
+
+ e1.init("a", 5);
+ e2.init("a", 6);
+ e3.init("v", 5);
+
+ ASSERT(e1.equivalent(&e1));
+ ASSERT(!e1.equivalent(&e2));
+ ASSERT(!e1.equivalent(&e3));
+}
+
+/**
+ TEST( SizeMatchExpression, MatchesIndexKey ) {
+ BSONObj operand = BSON( "$size" << 4 );
+ SizeMatchExpression size;
+ ASSERT( size.init( "a", operand[ "$size" ] ).isOK() );
+ IndexSpec indexSpec( BSON( "a" << 1 ) );
+ BSONObj indexKey = BSON( "" << 1 );
+ ASSERT( MatchMatchExpression::PartialMatchResult_Unknown ==
+ size.matchesIndexKey( indexKey, indexSpec ) );
+ }
+*/
+
+} // namespace mongo