diff options
author | aaron <aaron@10gen.com> | 2013-03-15 08:19:59 -0700 |
---|---|---|
committer | aaron <aaron@10gen.com> | 2013-03-15 18:41:06 -0700 |
commit | 4c75c66c34bae94e61e805403ceca4e132856064 (patch) | |
tree | 1c5dbe444a55783ea9b7bc9c10b6603e9559c75a /src/mongo/dbtests/namespacetests.cpp | |
parent | e60c28a09c691a7c4d9447dab9347d15d85e5e39 (diff) | |
download | mongo-4c75c66c34bae94e61e805403ceca4e132856064.tar.gz |
SERVER-5848 Additional tests.
Diffstat (limited to 'src/mongo/dbtests/namespacetests.cpp')
-rw-r--r-- | src/mongo/dbtests/namespacetests.cpp | 561 |
1 files changed, 549 insertions, 12 deletions
diff --git a/src/mongo/dbtests/namespacetests.cpp b/src/mongo/dbtests/namespacetests.cpp index 2f07ac18d95..d1baff95327 100644 --- a/src/mongo/dbtests/namespacetests.cpp +++ b/src/mongo/dbtests/namespacetests.cpp @@ -922,17 +922,123 @@ namespace NamespaceTests { } // namespace IndexDetailsTests - namespace IndexSpecTests { + namespace IndexSpecSuitability { + + /** An index is helpful for a query on the indexed field. */ + class IndexedQueryField { + public: + void run() { + IndexSpec spec( BSON( "a" << 1 ), BSONObj() ); + FieldRangeSet frs( "n/a", BSON( "a" << 2 ), true , true ); + // Checking a return value of HELPFUL instead of OPTIMAL is descriptive rather than + // normative. See SERVER-4485. + ASSERT_EQUALS( HELPFUL, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** An index is useless for a query not on an indexed field. */ + class NoIndexedQueryField { + public: + void run() { + IndexSpec spec( BSON( "a" << 1 ), BSONObj() ); + FieldRangeSet frs( "n/a", BSON( "b" << 2 ), true , true ); + ASSERT_EQUALS( USELESS, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** An index is useless for a query on the child of the indexed field. */ + class ChildOfIndexQueryField { + public: + void run() { + IndexSpec spec( BSON( "a" << 1 ), BSONObj() ); + FieldRangeSet frs( "n/a", BSON( "a.b" << 2 ), true , true ); + ASSERT_EQUALS( USELESS, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** An index is useless for a query on the parent of the indexed field. */ + class ParentOfIndexQueryField { + public: + void run() { + IndexSpec spec( BSON( "a.b" << 1 ), BSONObj() ); + FieldRangeSet frs( "n/a", BSON( "a" << 2 ), true , true ); + ASSERT_EQUALS( USELESS, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** + * An index is useless for an equality query containing a field name completing the indexed + * field path. + */ + class ObjectMatchCompletingIndexField { + public: + void run() { + IndexSpec spec( BSON( "a.b" << 1 ), BSONObj() ); + FieldRangeSet frs( "n/a", BSON( "a" << BSON( "b" << 2 ) ), true , true ); + ASSERT_EQUALS( USELESS, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** An index is helpful for an ordering on the indexed field. */ + class IndexedOrderField { + public: + void run() { + IndexSpec spec( BSON( "a" << 1 ), BSONObj() ); + FieldRangeSet frs( "n/a", BSONObj(), true , true ); + ASSERT_EQUALS( HELPFUL, spec.suitability( frs, BSON( "a" << 1 ) ) ); + } + }; + + /** An index is helpful for a reverse direction ordering on the indexed field. */ + class IndexedReverseOrderField { + public: + void run() { + IndexSpec spec( BSON( "a" << -1 ), BSONObj() ); + FieldRangeSet frs( "n/a", BSONObj(), true , true ); + ASSERT_EQUALS( HELPFUL, spec.suitability( frs, BSON( "a" << 1 ) ) ); + } + }; + + /** + * An index is helpful for an ordering containing the indexed field, even if the first + * ordered field is not indexed. This is a descriptive rather than normative test. + */ + class NonPrefixIndexedOrderField { + public: + void run() { + IndexSpec spec( BSON( "a" << 1 ), BSONObj() ); + FieldRangeSet frs( "n/a", BSONObj(), true , true ); + ASSERT_EQUALS( HELPFUL, spec.suitability( frs, BSON( "b" << 1 << "a" << 1 ) ) ); + } + }; + + /** An index is useless for an ordering on an unindexed field. */ + class NoIndexedOrderField { + public: + void run() { + IndexSpec spec( BSON( "a" << 1 ), BSONObj() ); + FieldRangeSet frs( "n/a", BSONObj(), true , true ); + ASSERT_EQUALS( USELESS, spec.suitability( frs, BSON( "b" << 1 ) ) ); + } + }; - class Suitability { + /** An index is useless for an ordering on the child of an indexed field. */ + class ChildOfIndexOrderField { public: void run() { IndexSpec spec( BSON( "a" << 1 ), BSONObj() ); - FieldRangeSet frs1( "", BSON( "a" << 2 << "b" << 3 ), true , true ); - ASSERT_EQUALS( HELPFUL, spec.suitability( frs1 , BSONObj() ) ); - FieldRangeSet frs2( "", BSON( "b" << 3 ), true , true ); - ASSERT_EQUALS( USELESS, spec.suitability( frs2, BSONObj() ) ); - ASSERT_EQUALS( HELPFUL, spec.suitability( frs2, BSON( "a" << 1 ) ) ); + FieldRangeSet frs( "n/a", BSONObj(), true , true ); + ASSERT_EQUALS( USELESS, spec.suitability( frs, BSON( "a.b" << 1 ) ) ); + } + }; + + /** An index is useless for an ordering on the parent of an indexed field. */ + class ParentOfIndexOrderField { + public: + void run() { + IndexSpec spec( BSON( "a.b" << 1 ), BSONObj() ); + FieldRangeSet frs( "n/a", BSONObj(), true , true ); + ASSERT_EQUALS( USELESS, spec.suitability( frs, BSON( "a" << 1 ) ) ); } }; @@ -941,15 +1047,406 @@ namespace NamespaceTests { public: void run() { IndexSpec spec( BSON( "1" << 1 ), BSONObj() ); - FieldRangeSet frs1( "", BSON( "1" << 2 ), true , true ); + FieldRangeSet frs1( "n/a", BSON( "1" << 2 ), true , true ); ASSERT_EQUALS( HELPFUL, spec.suitability( frs1, BSONObj() ) ); - FieldRangeSet frs2( "", BSON( "01" << 3), true , true ); + FieldRangeSet frs2( "n/a", BSON( "01" << 3), true , true ); ASSERT_EQUALS( USELESS, spec.suitability( frs2, BSON( "01" << 1 ) ) ); - FieldRangeSet frs3( "", BSONObj() , true , true ); + FieldRangeSet frs3( "n/a", BSONObj() , true , true ); ASSERT_EQUALS( HELPFUL, spec.suitability( frs3, BSON( "1" << 1 ) ) ); } }; + namespace TwoD { + + /** A 2d index is optimal for a $within predicate on the indexed field. */ + class Within { + public: + void run() { + BSONObj query = fromjson( "{a:{$within:{$box:[[100,0],[120,100]]}}}" ); + FieldRangeSet frs( "n/a", query, true, true ); + IndexSpec spec( BSON( "a" << "2d" ) ); + ASSERT_EQUALS( OPTIMAL, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** A 2d index is useless for a $within predicate not on the indexed field. */ + class WithinUnindexed { + public: + void run() { + BSONObj query = fromjson( "{a:{$within:{$box:[[100,0],[120,100]]}}}" ); + FieldRangeSet frs( "n/a", query, true, true ); + IndexSpec spec( BSON( "b" << "2d" ) ); + ASSERT_EQUALS( USELESS, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** A 2d index is optimal for a $near predicate on the indexed field. */ + class Near { + public: + void run() { + BSONObj query = fromjson( "{a:{$near:[100,0]}}" ); + FieldRangeSet frs( "n/a", query, true, true ); + IndexSpec spec( BSON( "a" << "2d" ) ); + ASSERT_EQUALS( OPTIMAL, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** + * A 2d index is helpful for a location object equality predicate on the indexed field. + */ + class LocationObject { + public: + void run() { + BSONObj query = fromjson( "{a:{lat:4,lon:5}}" ); + FieldRangeSet frs( "n/a", query, true, true ); + IndexSpec spec( BSON( "a" << "2d" ) ); + ASSERT_EQUALS( HELPFUL, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** + * A 2d index is helpful for a predicate object on the indexed field. This is a + * descriptive rather than normative test. See SERVER-8644. + */ + class PredicateObject { + public: + void run() { + BSONObj query = fromjson( "{a:{$gt:4,$lt:5}}" ); + FieldRangeSet frs( "n/a", query, true, true ); + IndexSpec spec( BSON( "a" << "2d" ) ); + ASSERT_EQUALS( HELPFUL, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** A 2d index is helpful for an array equality predicate on the indexed field. */ + class Array { + public: + void run() { + BSONObj query = fromjson( "{a:[1,1]}" ); + FieldRangeSet frs( "n/a", query, true, true ); + IndexSpec spec( BSON( "a" << "2d" ) ); + ASSERT_EQUALS( HELPFUL, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** A 2d index is useless for a numeric equality predicate on the indexed field. */ + class Number { + public: + void run() { + BSONObj query = fromjson( "{a:1}" ); + FieldRangeSet frs( "n/a", query, true, true ); + IndexSpec spec( BSON( "a" << "2d" ) ); + ASSERT_EQUALS( USELESS, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** A 2d index is useless without a predicate on the indexed field. */ + class Missing { + public: + void run() { + BSONObj query = fromjson( "{}" ); + FieldRangeSet frs( "n/a", query, true, true ); + IndexSpec spec( BSON( "a" << "2d" ) ); + ASSERT_EQUALS( USELESS, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** + * A 2d index is useless for a $near predicate on the indexed field within a $and + * clause. This is a descriptive rather than normative test. See SERVER-4572. + */ + class InsideAnd { + public: + void run() { + BSONObj query = fromjson( "{$and:[{a:{$near:[100,0]}}]}" ); + FieldRangeSet frs( "n/a", query, true, true ); + IndexSpec spec( BSON( "a" << "2d" ) ); + ASSERT_EQUALS( USELESS, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** + * A 2d index is optimal for a $near predicate on the indexed field adjacent to a $or + * expression. + */ + class OutsideOr { + public: + void run() { + BSONObj query = fromjson( "{a:{$near:[100,0]},$or:[{b:1}]}" ); + OrRangeGenerator org( "n/a", query, true ); + scoped_ptr<FieldRangeSetPair> frsp( org.topFrsp() ); + IndexSpec spec( BSON( "a" << "2d" ) ); + ASSERT_EQUALS( OPTIMAL, + spec.suitability( frsp->getSingleKeyFRS(), BSONObj() ) ); + } + }; + + } // namespace TwoD + + namespace S2 { + + /** A 2dsphere index is optimal for a $geoIntersects predicate on the indexed field. */ + class GeoIntersects { + public: + void run() { + BSONObj query = fromjson( "{a:{$geoIntersects:{$geometry:{type:'Point'," + "coordinates:[40,5]}}}}" ); + FieldRangeSet frs( "n/a", query, true, true ); + IndexSpec spec( BSON( "a" << "2dsphere" ) ); + ASSERT_EQUALS( OPTIMAL, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** A 2dsphere index is useless for a $geoIntersects predicate on an unindexed field. */ + class GeoIntersectsUnindexed { + public: + void run() { + BSONObj query = fromjson( "{a:{$geoIntersects:{$geometry:{type:'Point'," + "coordinates:[40,5]}}}}" ); + FieldRangeSet frs( "n/a", query, true, true ); + IndexSpec spec( BSON( "b" << "2dsphere" ) ); + ASSERT_EQUALS( USELESS, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** A 2dsphere index is optimal for a $near predicate on the indexed field. */ + class Near { + public: + void run() { + BSONObj query = fromjson( "{a:{$near:[100,0]}}" ); + FieldRangeSet frs( "n/a", query, true, true ); + IndexSpec spec( BSON( "a" << "2dsphere" ) ); + ASSERT_EQUALS( OPTIMAL, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** + * A 2dsphere index is useless for a location object equality predicate on the indexed + * field. + */ + class LocationObject { + public: + void run() { + BSONObj query = fromjson( "{a:{lat:4,lon:5}}" ); + FieldRangeSet frs( "n/a", query, true, true ); + IndexSpec spec( BSON( "a" << "2dsphere" ) ); + ASSERT_EQUALS( USELESS, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** A 2dsphere index is useless for a predicate object on the indexed field. */ + class PredicateObject { + public: + void run() { + BSONObj query = fromjson( "{a:{$gt:4,$lt:5}}" ); + FieldRangeSet frs( "n/a", query, true, true ); + IndexSpec spec( BSON( "a" << "2dsphere" ) ); + ASSERT_EQUALS( USELESS, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** A 2dsphere index is helpful for an array equality predicate on the indexed field. */ + class Array { + public: + void run() { + BSONObj query = fromjson( "{a:[1,1]}" ); + FieldRangeSet frs( "n/a", query, true, true ); + IndexSpec spec( BSON( "a" << "2dsphere" ) ); + ASSERT_EQUALS( HELPFUL, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** + * A 2dsphere index is useless for a numeric equality predicate on the indexed field. + */ + class Number { + public: + void run() { + BSONObj query = fromjson( "{a:1}" ); + FieldRangeSet frs( "n/a", query, true, true ); + IndexSpec spec( BSON( "a" << "2dsphere" ) ); + ASSERT_EQUALS( USELESS, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** A 2dsphere index is useless without a predicate on the indexed field. */ + class Missing { + public: + void run() { + BSONObj query = fromjson( "{}" ); + FieldRangeSet frs( "n/a", query, true, true ); + IndexSpec spec( BSON( "a" << "2dsphere" ) ); + ASSERT_EQUALS( USELESS, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** + * A 2dsphere index is useless for a $near predicate on the indexed field within a $and + * clause. This is a descriptive rather than normative test. See SERVER-4572. + */ + class InsideAnd { + public: + void run() { + BSONObj query = fromjson( "{$and:[{a:{$near:[100,0]}}]}" ); + FieldRangeSet frs( "n/a", query, true, true ); + IndexSpec spec( BSON( "a" << "2dsphere" ) ); + ASSERT_EQUALS( USELESS, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** + * A 2dsphere index is optimal for a $near predicate on the indexed field adjacent to a + * $or expression. + */ + class OutsideOr { + public: + void run() { + BSONObj query = fromjson( "{a:{$near:[100,0]},$or:[{b:1}]}" ); + OrRangeGenerator org( "n/a", query, true ); + scoped_ptr<FieldRangeSetPair> frsp( org.topFrsp() ); + IndexSpec spec( BSON( "a" << "2dsphere" ) ); + ASSERT_EQUALS( OPTIMAL, + spec.suitability( frsp->getSingleKeyFRS(), BSONObj() ) ); + } + }; + + } // namespace S2 + + namespace Hashed { + + /** A hashed index is helpful for an equality predicate on the indexed field. */ + class Equality { + public: + void run() { + BSONObj query = fromjson( "{a:5}" ); + FieldRangeSet frs( "n/a", query, true, true ); + IndexSpec spec( BSON( "a" << "hashed" ) ); + ASSERT_EQUALS( HELPFUL, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** A hashed index is useless for a range predicate on the indexed field. */ + class GreaterThan { + public: + void run() { + BSONObj query = fromjson( "{a:{$gt:4}}" ); + FieldRangeSet frs( "n/a", query, true, true ); + IndexSpec spec( BSON( "a" << "hashed" ) ); + ASSERT_EQUALS( USELESS, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** A hashed index is helpful for a set membership predicate on the indexed field. */ + class InSet { + public: + void run() { + BSONObj query = fromjson( "{a:{$in:[1,2]}}" ); + FieldRangeSet frs( "n/a", query, true, true ); + IndexSpec spec( BSON( "a" << "hashed" ) ); + ASSERT_EQUALS( HELPFUL, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** + * A hashed index is helpful for an equality predicate on the indexed field, within a + * singleton $and clause. + */ + class AndEqualitySingleton { + public: + void run() { + BSONObj query = fromjson( "{$and:[{a:5}]}" ); + FieldRangeSet frs( "n/a", query, true, true ); + IndexSpec spec( BSON( "a" << "hashed" ) ); + ASSERT_EQUALS( HELPFUL, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** + * A hashed index is helpful for an equality predicate on the indexed field, within a + * non singleton $and clause. + */ + class AndEqualityNonSingleton { + public: + void run() { + BSONObj query = fromjson( "{$and:[{a:5},{b:5}]}" ); + FieldRangeSet frs( "n/a", query, true, true ); + IndexSpec spec( BSON( "a" << "hashed" ) ); + ASSERT_EQUALS( HELPFUL, spec.suitability( frs, BSONObj() ) ); + } + }; + + /** + * A hashed index is helpful for an equality predicate on the indexed field, within a + * singleton $or clause. + */ + class EqualityInsideSingletonOr { + public: + void run() { + BSONObj query = fromjson( "{$or:[{a:5}]}" ); + OrRangeGenerator org( "n/a", query, true ); + scoped_ptr<FieldRangeSetPair> frsp( org.topFrsp() ); + IndexSpec spec( BSON( "a" << "hashed" ) ); + ASSERT_EQUALS( HELPFUL, spec.suitability( frsp->getSingleKeyFRS(), + BSONObj() ) ); + } + }; + + /** + * A hashed index is helpful for an equality predicate on the indexed field, within a + * non standalone singleton $or clause. + */ + class EqualityInsideNonStandaloneSingletonOr { + public: + void run() { + BSONObj query = fromjson( "{z:5,$or:[{a:5}]}" ); + OrRangeGenerator org( "n/a", query, true ); + scoped_ptr<FieldRangeSetPair> frsp( org.topFrsp() ); + IndexSpec spec( BSON( "a" << "hashed" ) ); + ASSERT_EQUALS( HELPFUL, spec.suitability( frsp->getSingleKeyFRS(), + BSONObj() ) ); + } + }; + + /** + * A hashed index is helpful for an equality predicate on the indexed field, within a + * non singleton $or clause. + */ + class EqualityInsideNonSingletonOr { + public: + void run() { + BSONObj query = fromjson( "{$or:[{a:5},{b:5}]}" ); + OrRangeGenerator org( "n/a", query, true ); + scoped_ptr<FieldRangeSetPair> frsp( org.topFrsp() ); + IndexSpec spec( BSON( "a" << "hashed" ) ); + ASSERT_EQUALS( HELPFUL, spec.suitability( frsp->getSingleKeyFRS(), + BSONObj() ) ); + } + }; + + /** + * A hashed index is helpful for an equality predicate on the indexed field, adjacent to + * a $or clause. + */ + class EqualityOutsideOr { + public: + void run() { + BSONObj query = fromjson( "{a:5,$or:[{z:5}]}" ); + OrRangeGenerator org( "n/a", query, true ); + scoped_ptr<FieldRangeSetPair> frsp( org.topFrsp() ); + IndexSpec spec( BSON( "a" << "hashed" ) ); + ASSERT_EQUALS( HELPFUL, spec.suitability( frsp->getSingleKeyFRS(), + BSONObj() ) ); + } + }; + + } // namespace Hashed + + // GeoHaystack does not implement its own suitability(). See SERVER-8645. + + } // namespace IndexSpecSuitability + + namespace IndexSpecTests { + /** A missing field is represented as null in a btree index. */ class BtreeIndexMissingField { public: @@ -1830,8 +2327,48 @@ namespace NamespaceTests { add< IndexDetailsTests::MissingField >(); add< IndexDetailsTests::SubobjectMissing >(); add< IndexDetailsTests::CompoundMissing >(); - add< IndexSpecTests::Suitability >(); - add< IndexSpecTests::NumericFieldSuitability >(); + add< IndexSpecSuitability::IndexedQueryField >(); + add< IndexSpecSuitability::NoIndexedQueryField >(); + add< IndexSpecSuitability::ChildOfIndexQueryField >(); + add< IndexSpecSuitability::ParentOfIndexQueryField >(); + add< IndexSpecSuitability::ObjectMatchCompletingIndexField >(); + add< IndexSpecSuitability::NoIndexedQueryField >(); + add< IndexSpecSuitability::IndexedOrderField >(); + add< IndexSpecSuitability::IndexedReverseOrderField >(); + add< IndexSpecSuitability::NonPrefixIndexedOrderField >(); + add< IndexSpecSuitability::NoIndexedOrderField >(); + add< IndexSpecSuitability::ChildOfIndexOrderField >(); + add< IndexSpecSuitability::ParentOfIndexOrderField >(); + add< IndexSpecSuitability::NumericFieldSuitability >(); + add< IndexSpecSuitability::TwoD::Within >(); + add< IndexSpecSuitability::TwoD::WithinUnindexed >(); + add< IndexSpecSuitability::TwoD::Near >(); + add< IndexSpecSuitability::TwoD::LocationObject >(); + add< IndexSpecSuitability::TwoD::PredicateObject >(); + add< IndexSpecSuitability::TwoD::Array >(); + add< IndexSpecSuitability::TwoD::Number >(); + add< IndexSpecSuitability::TwoD::Missing >(); + add< IndexSpecSuitability::TwoD::InsideAnd >(); + add< IndexSpecSuitability::TwoD::OutsideOr >(); + add< IndexSpecSuitability::S2::GeoIntersects >(); + add< IndexSpecSuitability::S2::GeoIntersectsUnindexed >(); + add< IndexSpecSuitability::S2::Near >(); + add< IndexSpecSuitability::S2::LocationObject >(); + add< IndexSpecSuitability::S2::PredicateObject >(); + add< IndexSpecSuitability::S2::Array >(); + add< IndexSpecSuitability::S2::Number >(); + add< IndexSpecSuitability::S2::Missing >(); + add< IndexSpecSuitability::S2::InsideAnd >(); + add< IndexSpecSuitability::S2::OutsideOr >(); + add< IndexSpecSuitability::Hashed::Equality >(); + add< IndexSpecSuitability::Hashed::GreaterThan >(); + add< IndexSpecSuitability::Hashed::InSet >(); + add< IndexSpecSuitability::Hashed::AndEqualitySingleton >(); + add< IndexSpecSuitability::Hashed::AndEqualityNonSingleton >(); + add< IndexSpecSuitability::Hashed::EqualityInsideSingletonOr >(); + add< IndexSpecSuitability::Hashed::EqualityInsideNonStandaloneSingletonOr >(); + add< IndexSpecSuitability::Hashed::EqualityInsideNonSingletonOr >(); + add< IndexSpecSuitability::Hashed::EqualityOutsideOr >(); add< IndexSpecTests::BtreeIndexMissingField >(); add< IndexSpecTests::TwoDIndexMissingField >(); add< IndexSpecTests::HashedIndexMissingField >(); |