diff options
author | David Storch <david.storch@10gen.com> | 2014-04-18 16:54:21 -0400 |
---|---|---|
committer | David Storch <david.storch@10gen.com> | 2014-04-21 15:48:27 -0400 |
commit | e87b42c4f13e48078f5c4aefba3caf18dcfba072 (patch) | |
tree | b9f09cb02522451c4f8d390a9866ac8f1f3f1106 | |
parent | 3286b208b30c43450354422e554070485f526e7b (diff) | |
download | mongo-e87b42c4f13e48078f5c4aefba3caf18dcfba072.tar.gz |
SERVER-8192 port btree key generation tests to a new unit test
-rw-r--r-- | src/mongo/db/index/SConscript | 11 | ||||
-rw-r--r-- | src/mongo/db/index/btree_key_generator_test.cpp | 541 | ||||
-rw-r--r-- | src/mongo/dbtests/namespacetests.cpp | 946 |
3 files changed, 552 insertions, 946 deletions
diff --git a/src/mongo/db/index/SConscript b/src/mongo/db/index/SConscript index c8d757d150c..6cf5084abb2 100644 --- a/src/mongo/db/index/SConscript +++ b/src/mongo/db/index/SConscript @@ -29,3 +29,14 @@ env.Library( '$BUILD_DIR/mongo/bson', ], ) + +env.CppUnitTest( + target='btree_key_generator_test', + source=[ + 'btree_key_generator_test.cpp', + ], + LIBDEPS=[ + 'key_generator', + '$BUILD_DIR/mongo/mongohasher', + ], +) diff --git a/src/mongo/db/index/btree_key_generator_test.cpp b/src/mongo/db/index/btree_key_generator_test.cpp new file mode 100644 index 00000000000..f26a64c64e5 --- /dev/null +++ b/src/mongo/db/index/btree_key_generator_test.cpp @@ -0,0 +1,541 @@ +/** + * Copyright (C) 2014 MongoDB Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#include "mongo/db/index/btree_key_generator.h" + +#include "mongo/db/json.h" +#include "mongo/unittest/unittest.h" + +using namespace mongo; + +namespace { + + // + // Helper functions + // + + std::string dumpKeyset(const BSONObjSet& objs) { + std::stringstream ss; + ss << "[ "; + for (BSONObjSet::iterator i = objs.begin(); i != objs.end(); ++i) { + ss << i->toString() << " "; + } + ss << "]"; + + return ss.str(); + } + + bool keysetsMatch(const BSONObjSet& expected, const BSONObjSet& actual) { + if (expected.size() != actual.size()) { + return false; + } + + for (BSONObjSet::iterator i = expected.begin(); i != expected.end(); ++i) { + if (actual.end() == actual.find(*i)) { + return false; + } + } + + return true; + } + + bool testKeygen(const BSONObj& kp, const BSONObj& obj, + const BSONObjSet& expectedKeys, bool sparse = false) { + // + // Step 1: construct the btree key generator object, using the + // index key pattern. + // + vector<const char*> fieldNames; + vector<BSONElement> fixed; + + BSONObjIterator it(kp); + while (it.more()) { + BSONElement elt = it.next(); + fieldNames.push_back(elt.fieldName()); + fixed.push_back(BSONElement()); + } + + scoped_ptr<BtreeKeyGenerator> keyGen( + new BtreeKeyGeneratorV1(fieldNames, fixed, sparse)); + + // + // Step 2: ask 'keyGen' to generate index keys for the object 'obj'. + // + BSONObjSet actualKeys; + keyGen->getKeys(obj, &actualKeys); + + // + // Step 3: check that the results match the expected result. + // + bool match = keysetsMatch(expectedKeys, actualKeys); + if (!match) { + cout << "Expected: " << dumpKeyset(expectedKeys) << ", " + << "Actual: " << dumpKeyset(actualKeys) << endl; + } + + return match; + } + + // + // Unit tests + // + + TEST(BtreeKeyGeneratorTest, GetKeysFromObjectSimple) { + BSONObj keyPattern = fromjson("{a: 1}"); + BSONObj genKeysFrom = fromjson("{b: 4, a: 5}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': 5}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromObjectDotted) { + BSONObj keyPattern = fromjson("{'a.b': 1}"); + BSONObj genKeysFrom = fromjson("{a: {b: 4}, c: 'foo'}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': 4}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromArraySimple) { + BSONObj keyPattern = fromjson("{a: 1}"); + BSONObj genKeysFrom = fromjson("{a: [1, 2, 3]}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': 1}")); + expectedKeys.insert(fromjson("{'': 2}")); + expectedKeys.insert(fromjson("{'': 3}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromArrayFirstElement) { + BSONObj keyPattern = fromjson("{a: 1, b: 1}"); + BSONObj genKeysFrom = fromjson("{a: [1, 2, 3], b: 2}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': 1, '': 2}")); + expectedKeys.insert(fromjson("{'': 2, '': 2}")); + expectedKeys.insert(fromjson("{'': 3, '': 2}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromArraySecondElement) { + BSONObj keyPattern = fromjson("{first: 1, a: 1}"); + BSONObj genKeysFrom = fromjson("{first: 5, a: [1, 2, 3]}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': 5, '': 1}")); + expectedKeys.insert(fromjson("{'': 5, '': 2}")); + expectedKeys.insert(fromjson("{'': 5, '': 3}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromSecondLevelArray) { + BSONObj keyPattern = fromjson("{'a.b': 1}"); + BSONObj genKeysFrom = fromjson("{a: {b: [1, 2, 3]}}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': 1}")); + expectedKeys.insert(fromjson("{'': 2}")); + expectedKeys.insert(fromjson("{'': 3}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromParallelArraysBasic) { + BSONObj keyPattern = fromjson("{'a': 1, 'b': 1}"); + BSONObj genKeysFrom = fromjson("{a: [1, 2, 3], b: [1, 2, 3]}}"); + BSONObjSet expectedKeys; + ASSERT_THROWS(testKeygen(keyPattern, genKeysFrom, expectedKeys), UserException); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromArraySubobjectBasic) { + BSONObj keyPattern = fromjson("{'a.b': 1}"); + BSONObj genKeysFrom = fromjson("{a: [{b:1,c:4}, {b:2,c:4}, {b:3,c:4}]}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': 1}")); + expectedKeys.insert(fromjson("{'': 2}")); + expectedKeys.insert(fromjson("{'': 3}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysArraySubobjectCompoundIndex) { + BSONObj keyPattern = fromjson("{'a.b': 1, d: 99}"); + BSONObj genKeysFrom = fromjson("{a: [{b:1,c:4}, {b:2,c:4}, {b:3,c:4}], d: 99}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': 1, '': 99}")); + expectedKeys.insert(fromjson("{'': 2, '': 99}")); + expectedKeys.insert(fromjson("{'': 3, '': 99}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysArraySubobjectSingleMissing) { + BSONObj keyPattern = fromjson("{'a.b': 1}"); + BSONObj genKeysFrom = fromjson("{a: [{foo: 41}, {b:1,c:4}, {b:2,c:4}, {b:3,c:4}]}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': null}")); + expectedKeys.insert(fromjson("{'': 1}")); + expectedKeys.insert(fromjson("{'': 2}")); + expectedKeys.insert(fromjson("{'': 3}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromArraySubobjectMissing) { + BSONObj keyPattern = fromjson("{'a.b': 1}"); + BSONObj genKeysFrom = fromjson("{a: [{foo: 41}, {foo: 41}, {foo: 41}]}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': null}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysMissingField) { + BSONObj keyPattern = fromjson("{a: 1}"); + BSONObj genKeysFrom = fromjson("{b: 1}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': null}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysSubobjectMissing) { + BSONObj keyPattern = fromjson("{'a.b': 1}"); + BSONObj genKeysFrom = fromjson("{a: [1, 2]}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': null}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromCompound) { + BSONObj keyPattern = fromjson("{x: 1, y: 1}"); + BSONObj genKeysFrom = fromjson("{x: 'a', y: 'b'}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': 'a', '': 'b'}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromCompoundMissing) { + BSONObj keyPattern = fromjson("{x: 1, y: 1}"); + BSONObj genKeysFrom = fromjson("{x: 'a'}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': 'a', '': null}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromArraySubelementComplex) { + BSONObj keyPattern = fromjson("{'a.b': 1}"); + BSONObj genKeysFrom = fromjson("{a:[{b:[2]}]}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': 2}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromParallelArraysComplex) { + BSONObj keyPattern = fromjson("{'a.b': 1, 'a.c': 1}"); + BSONObj genKeysFrom = fromjson("{a:[{b:[1],c:[2]}]}"); + BSONObjSet expectedKeys; + ASSERT_THROWS(testKeygen(keyPattern, genKeysFrom, expectedKeys), UserException); + } + + TEST(BtreeKeyGeneratorTest, GetKeysAlternateMissing) { + BSONObj keyPattern = fromjson("{'a.b': 1, 'a.c': 1}"); + BSONObj genKeysFrom = fromjson("{a:[{b:1},{c:2}]}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': null, '': 2}")); + expectedKeys.insert(fromjson("{'': 1, '': null}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromMultiComplex) { + BSONObj keyPattern = fromjson("{'a.b': 1}"); + BSONObj genKeysFrom = fromjson("{a:[{b:1},{b:[1,2,3]}]}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': 1}")); + expectedKeys.insert(fromjson("{'': 2}")); + expectedKeys.insert(fromjson("{'': 3}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysArrayEmpty) { + BSONObj keyPattern = fromjson("{a: 1}"); + BSONObj genKeysFrom = fromjson("{a:[1,2]}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': 1}")); + expectedKeys.insert(fromjson("{'': 2}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + + genKeysFrom = fromjson("{a: [1]}"); + expectedKeys.clear(); + expectedKeys.insert(fromjson("{'': 1}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + + genKeysFrom = fromjson("{a: null}"); + expectedKeys.clear(); + expectedKeys.insert(fromjson("{'': null}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + + genKeysFrom = fromjson("{a: []}"); + expectedKeys.clear(); + expectedKeys.insert(fromjson("{'': undefined}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromDoubleArray) { + BSONObj keyPattern = fromjson("{a: 1, a: 1}"); + BSONObj genKeysFrom = fromjson("{a:[1,2]}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': 1, '': 1}")); + expectedKeys.insert(fromjson("{'': 2, '': 2}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromDoubleEmptyArray) { + BSONObj keyPattern = fromjson("{a: 1, a: 1}"); + BSONObj genKeysFrom = fromjson("{a:[]}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': undefined, '': undefined}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromMultiEmptyArray) { + BSONObj keyPattern = fromjson("{a: 1, b: 1}"); + BSONObj genKeysFrom = fromjson("{a: 1, b: [1, 2]}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': 1, '': 1}")); + expectedKeys.insert(fromjson("{'': 1, '': 2}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + + genKeysFrom = fromjson("{a: 1, b: [1]}"); + expectedKeys.clear(); + expectedKeys.insert(fromjson("{'': 1, '': 1}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + + genKeysFrom = fromjson("{a: 1, b: []}"); + expectedKeys.clear(); + expectedKeys.insert(fromjson("{'': 1, '': undefined}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromNestedEmptyArray) { + BSONObj keyPattern = fromjson("{'a.b': 1}"); + BSONObj genKeysFrom = fromjson("{a:[]}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': null}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromMultiNestedEmptyArray) { + BSONObj keyPattern = fromjson("{'a.b': 1, 'a.c': 1}"); + BSONObj genKeysFrom = fromjson("{a:[]}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': null, '': null}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromUnevenNestedEmptyArray) { + BSONObj keyPattern = fromjson("{'a': 1, 'a.b': 1}"); + BSONObj genKeysFrom = fromjson("{a:[]}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': undefined, '': null}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + + genKeysFrom = fromjson("{a:[{b: 1}]}"); + expectedKeys.clear(); + expectedKeys.insert(fromjson("{'': {b:1}, '': 1}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + + genKeysFrom = fromjson("{a:[{b: []}]}"); + expectedKeys.clear(); + expectedKeys.insert(fromjson("{'': {b:[]}, '': undefined}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromReverseUnevenNestedEmptyArray) { + BSONObj keyPattern = fromjson("{'a.b': 1, 'a': 1}"); + BSONObj genKeysFrom = fromjson("{a:[]}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': null, '': undefined}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, SparseReverseUnevenNestedEmptyArray) { + BSONObj keyPattern = fromjson("{'a.b': 1, 'a': 1}"); + BSONObj genKeysFrom = fromjson("{a:[]}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': null, '': undefined}")); + // true means sparse + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys, true)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromSparseEmptyArray) { + BSONObj keyPattern = fromjson("{'a.b': 1}"); + BSONObj genKeysFrom = fromjson("{a:1}"); + BSONObjSet expectedKeys; + // true means sparse + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys, true)); + + genKeysFrom = fromjson("{a:[]}"); + // true means sparse + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys, true)); + + genKeysFrom = fromjson("{a:[{c:1}]}"); + // true means sparse + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys, true)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromSparseEmptyArraySecond) { + BSONObj keyPattern = fromjson("{z: 1, 'a.b': 1}"); + BSONObj genKeysFrom = fromjson("{a:1}"); + BSONObjSet expectedKeys; + // true means sparse + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys, true)); + + genKeysFrom = fromjson("{a:[]}"); + // true means sparse + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys, true)); + + genKeysFrom = fromjson("{a:[{c:1}]}"); + // true means sparse + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys, true)); + } + + TEST(BtreeKeyGeneratorTest, SparseNonObjectMissingNestedField) { + BSONObj keyPattern = fromjson("{'a.b': 1}"); + BSONObj genKeysFrom = fromjson("{a:[]}"); + BSONObjSet expectedKeys; + // true means sparse + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys, true)); + + genKeysFrom = fromjson("{a:[1]}"); + // true means sparse + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys, true)); + + genKeysFrom = fromjson("{a:[1,{b:1}]}"); + expectedKeys.clear(); + expectedKeys.insert(fromjson("{'': 1}")); + // true means sparse + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys, true)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromIndexedArrayIndex) { + BSONObj keyPattern = fromjson("{'a.0': 1}"); + BSONObj genKeysFrom = fromjson("{a:[1]}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': 1}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + + genKeysFrom = fromjson("{a:[[1]]}"); + expectedKeys.clear(); + expectedKeys.insert(fromjson("{'': [1]}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + + genKeysFrom = fromjson("{a:[[]]}"); + expectedKeys.clear(); + expectedKeys.insert(fromjson("{'': undefined}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + + genKeysFrom = fromjson("{a:[[]]}"); + expectedKeys.clear(); + expectedKeys.insert(fromjson("{'': undefined}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + + genKeysFrom = fromjson("{a:{'0':1}}"); + expectedKeys.clear(); + expectedKeys.insert(fromjson("{'': 1}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + + genKeysFrom = fromjson("{a:[{'0':1}]}"); + expectedKeys.clear(); + ASSERT_THROWS(testKeygen(keyPattern, genKeysFrom, expectedKeys), UserException); + + genKeysFrom = fromjson("{a:[1,{'0':2}]}"); + ASSERT_THROWS(testKeygen(keyPattern, genKeysFrom, expectedKeys), UserException); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromDoubleIndexedArrayIndex) { + BSONObj keyPattern = fromjson("{'a.0.0': 1}"); + BSONObj genKeysFrom = fromjson("{a:[[1]]}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': 1}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + + genKeysFrom = fromjson("{a:[[]]}"); + expectedKeys.clear(); + expectedKeys.insert(fromjson("{'': null}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + + genKeysFrom = fromjson("{a:[]}"); + expectedKeys.clear(); + expectedKeys.insert(fromjson("{'': null}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + + genKeysFrom = fromjson("{a:[[[]]]}"); + expectedKeys.clear(); + expectedKeys.insert(fromjson("{'': undefined}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromObjectWithinArray) { + BSONObj keyPattern = fromjson("{'a.0.b': 1}"); + BSONObj genKeysFrom = fromjson("{a:[{b:1}]}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': 1}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + + genKeysFrom = fromjson("{a:[{b:[1]}]}"); + expectedKeys.clear(); + expectedKeys.insert(fromjson("{'': 1}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + + genKeysFrom = fromjson("{a:[{b:[[1]]}]}"); + expectedKeys.clear(); + expectedKeys.insert(fromjson("{'': [1]}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + + genKeysFrom = fromjson("{a:[[{b:1}]]}"); + expectedKeys.clear(); + expectedKeys.insert(fromjson("{'': 1}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + + genKeysFrom = fromjson("{a:[[{b:[1]}]]}"); + expectedKeys.clear(); + expectedKeys.insert(fromjson("{'': 1}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + + genKeysFrom = fromjson("{a:[[{b:[[1]]}]]}"); + expectedKeys.clear(); + expectedKeys.insert(fromjson("{'': [1]}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + + genKeysFrom = fromjson("{a:[[{b:[]}]]}"); + expectedKeys.clear(); + expectedKeys.insert(fromjson("{'': undefined}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + + TEST(BtreeKeyGeneratorTest, GetKeysFromArrayWithinObjectWithinArray) { + BSONObj keyPattern = fromjson("{'a.0.b.0': 1}"); + BSONObj genKeysFrom = fromjson("{a:[{b:[1]}]}"); + BSONObjSet expectedKeys; + expectedKeys.insert(fromjson("{'': 1}")); + ASSERT(testKeygen(keyPattern, genKeysFrom, expectedKeys)); + } + +} // namespace diff --git a/src/mongo/dbtests/namespacetests.cpp b/src/mongo/dbtests/namespacetests.cpp index 72b2d917627..17455edc906 100644 --- a/src/mongo/dbtests/namespacetests.cpp +++ b/src/mongo/dbtests/namespacetests.cpp @@ -33,7 +33,6 @@ #include "mongo/pch.h" #include "mongo/db/db.h" -#include "mongo/db/index/btree_key_generator.h" #include "mongo/db/index/expression_keys_private.h" #include "mongo/db/index_legacy.h" #include "mongo/db/index_names.h" @@ -53,915 +52,6 @@ namespace NamespaceTests { const int MinExtentSize = 4096; - namespace IndexDetailsTests { - class Base { - public: - Base() { - } - virtual ~Base() { - } - protected: - void create( bool sparse = false ) { - - BSONObjBuilder builder; - builder.append( "ns", ns() ); - builder.append( "name", "testIndex" ); - builder.append( "key", key() ); - builder.append( "sparse", sparse ); - - BSONObj bobj = builder.done(); - - _index.reset( new IndexDescriptor( NULL, IndexNames::BTREE, bobj ) ); - - _keyPattern = key().getOwned(); - - // The key generation wants these values. - vector<const char*> fieldNames; - vector<BSONElement> fixed; - - BSONObjIterator it(_keyPattern); - while (it.more()) { - BSONElement elt = it.next(); - fieldNames.push_back(elt.fieldName()); - fixed.push_back(BSONElement()); - } - - _keyGen.reset(new BtreeKeyGeneratorV1(fieldNames, fixed, sparse)); - } - - static const char* ns() { - return "unittests.indexdetailstests"; - } - - IndexDescriptor* id() { - return _index.get(); - } - - // TODO: This is testing Btree key creation, not IndexDetails. - void getKeysFromObject(const BSONObj& obj, BSONObjSet& out) { - _keyGen->getKeys(obj, &out); - } - - virtual BSONObj key() const { - BSONObjBuilder k; - k.append( "a", 1 ); - return k.obj(); - } - BSONObj aDotB() const { - BSONObjBuilder k; - k.append( "a.b", 1 ); - return k.obj(); - } - BSONObj aAndB() const { - BSONObjBuilder k; - k.append( "a", 1 ); - k.append( "b", 1 ); - return k.obj(); - } - static vector< int > shortArray() { - vector< int > a; - a.push_back( 1 ); - a.push_back( 2 ); - a.push_back( 3 ); - return a; - } - static BSONObj simpleBC( int i ) { - BSONObjBuilder b; - b.append( "b", i ); - b.append( "c", 4 ); - return b.obj(); - } - static void checkSize( int expected, const BSONObjSet &objs ) { - ASSERT_EQUALS( BSONObjSet::size_type( expected ), objs.size() ); - } - static void assertEquals( const BSONObj &a, const BSONObj &b ) { - if ( a.woCompare( b ) != 0 ) { - out() << "expected: " << a.toString() - << ", got: " << b.toString() << endl; - } - ASSERT( a.woCompare( b ) == 0 ); - } - BSONObj nullObj() const { - BSONObjBuilder b; - b.appendNull( "" ); - return b.obj(); - } - private: - scoped_ptr<BtreeKeyGenerator> _keyGen; - BSONObj _keyPattern; - scoped_ptr<IndexDescriptor> _index; - - }; - - class Create : public Base { - public: - void run() { - create(); - ASSERT_EQUALS( "testIndex", id()->indexName() ); - ASSERT_EQUALS( ns(), id()->parentNS() ); - assertEquals( key(), id()->keyPattern() ); - } - }; - - class GetKeysFromObjectSimple : public Base { - public: - void run() { - create(); - BSONObjBuilder b, e; - b.append( "b", 4 ); - b.append( "a", 5 ); - e.append( "", 5 ); - BSONObjSet keys; - getKeysFromObject( b.done(), keys ); - checkSize( 1, keys ); - assertEquals( e.obj(), *keys.begin() ); - } - }; - - class GetKeysFromObjectDotted : public Base { - public: - void run() { - create(); - BSONObjBuilder a, e, b; - b.append( "b", 4 ); - a.append( "a", b.done() ); - a.append( "c", "foo" ); - e.append( "", 4 ); - BSONObjSet keys; - getKeysFromObject( a.done(), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( e.obj(), *keys.begin() ); - } - private: - virtual BSONObj key() const { - return aDotB(); - } - }; - - class GetKeysFromArraySimple : public Base { - public: - void run() { - create(); - BSONObjBuilder b; - b.append( "a", shortArray()) ; - - BSONObjSet keys; - getKeysFromObject( b.done(), keys ); - checkSize( 3, keys ); - int j = 1; - for ( BSONObjSet::iterator i = keys.begin(); i != keys.end(); ++i, ++j ) { - BSONObjBuilder b; - b.append( "", j ); - assertEquals( b.obj(), *i ); - } - } - }; - - class GetKeysFromArrayFirstElement : public Base { - public: - void run() { - create(); - BSONObjBuilder b; - b.append( "a", shortArray() ); - b.append( "b", 2 ); - - BSONObjSet keys; - getKeysFromObject( b.done(), keys ); - checkSize( 3, keys ); - int j = 1; - for ( BSONObjSet::iterator i = keys.begin(); i != keys.end(); ++i, ++j ) { - BSONObjBuilder b; - b.append( "", j ); - b.append( "", 2 ); - assertEquals( b.obj(), *i ); - } - } - private: - virtual BSONObj key() const { - return aAndB(); - } - }; - - class GetKeysFromArraySecondElement : public Base { - public: - void run() { - create(); - BSONObjBuilder b; - b.append( "first", 5 ); - b.append( "a", shortArray()) ; - - BSONObjSet keys; - getKeysFromObject( b.done(), keys ); - checkSize( 3, keys ); - int j = 1; - for ( BSONObjSet::iterator i = keys.begin(); i != keys.end(); ++i, ++j ) { - BSONObjBuilder b; - b.append( "", 5 ); - b.append( "", j ); - assertEquals( b.obj(), *i ); - } - } - private: - virtual BSONObj key() const { - BSONObjBuilder k; - k.append( "first", 1 ); - k.append( "a", 1 ); - return k.obj(); - } - }; - - class GetKeysFromSecondLevelArray : public Base { - public: - void run() { - create(); - BSONObjBuilder b; - b.append( "b", shortArray() ); - BSONObjBuilder a; - a.append( "a", b.done() ); - - BSONObjSet keys; - getKeysFromObject( a.done(), keys ); - checkSize( 3, keys ); - int j = 1; - for ( BSONObjSet::iterator i = keys.begin(); i != keys.end(); ++i, ++j ) { - BSONObjBuilder b; - b.append( "", j ); - assertEquals( b.obj(), *i ); - } - } - private: - virtual BSONObj key() const { - return aDotB(); - } - }; - - class ParallelArraysBasic : public Base { - public: - void run() { - create(); - BSONObjBuilder b; - b.append( "a", shortArray() ); - b.append( "b", shortArray() ); - - BSONObjSet keys; - ASSERT_THROWS( getKeysFromObject( b.done(), keys ), - UserException ); - } - private: - virtual BSONObj key() const { - return aAndB(); - } - }; - - class ArraySubobjectBasic : public Base { - public: - void run() { - create(); - vector< BSONObj > elts; - for ( int i = 1; i < 4; ++i ) - elts.push_back( simpleBC( i ) ); - BSONObjBuilder b; - b.append( "a", elts ); - - BSONObjSet keys; - getKeysFromObject( b.done(), keys ); - checkSize( 3, keys ); - int j = 1; - for ( BSONObjSet::iterator i = keys.begin(); i != keys.end(); ++i, ++j ) { - BSONObjBuilder b; - b.append( "", j ); - assertEquals( b.obj(), *i ); - } - } - private: - virtual BSONObj key() const { - return aDotB(); - } - }; - - class ArraySubobjectMultiFieldIndex : public Base { - public: - void run() { - create(); - vector< BSONObj > elts; - for ( int i = 1; i < 4; ++i ) - elts.push_back( simpleBC( i ) ); - BSONObjBuilder b; - b.append( "a", elts ); - b.append( "d", 99 ); - - BSONObjSet keys; - getKeysFromObject( b.done(), keys ); - checkSize( 3, keys ); - int j = 1; - for ( BSONObjSet::iterator i = keys.begin(); i != keys.end(); ++i, ++j ) { - BSONObjBuilder c; - c.append( "", j ); - c.append( "", 99 ); - assertEquals( c.obj(), *i ); - } - } - private: - virtual BSONObj key() const { - BSONObjBuilder k; - k.append( "a.b", 1 ); - k.append( "d", 1 ); - return k.obj(); - } - }; - - class ArraySubobjectSingleMissing : public Base { - public: - void run() { - create(); - vector< BSONObj > elts; - BSONObjBuilder s; - s.append( "foo", 41 ); - elts.push_back( s.obj() ); - for ( int i = 1; i < 4; ++i ) - elts.push_back( simpleBC( i ) ); - BSONObjBuilder b; - b.append( "a", elts ); - BSONObj obj = b.obj(); - - BSONObjSet keys; - getKeysFromObject( obj, keys ); - checkSize( 4, keys ); - BSONObjSet::iterator i = keys.begin(); - assertEquals( nullObj(), *i++ ); // see SERVER-3377 - for ( int j = 1; j < 4; ++i, ++j ) { - BSONObjBuilder b; - b.append( "", j ); - assertEquals( b.obj(), *i ); - } - } - private: - virtual BSONObj key() const { - return aDotB(); - } - }; - - class ArraySubobjectMissing : public Base { - public: - void run() { - create(); - vector< BSONObj > elts; - BSONObjBuilder s; - s.append( "foo", 41 ); - for ( int i = 1; i < 4; ++i ) - elts.push_back( s.done() ); - BSONObjBuilder b; - b.append( "a", elts ); - - BSONObjSet keys; - getKeysFromObject( b.done(), keys ); - checkSize( 1, keys ); - assertEquals( nullObj(), *keys.begin() ); - } - private: - virtual BSONObj key() const { - return aDotB(); - } - }; - - class MissingField : public Base { - public: - void run() { - create(); - BSONObjSet keys; - getKeysFromObject( BSON( "b" << 1 ), keys ); - checkSize( 1, keys ); - assertEquals( nullObj(), *keys.begin() ); - } - private: - virtual BSONObj key() const { - return BSON( "a" << 1 ); - } - }; - - class SubobjectMissing : public Base { - public: - void run() { - create(); - BSONObjSet keys; - getKeysFromObject( fromjson( "{a:[1,2]}" ), keys ); - checkSize( 1, keys ); - assertEquals( nullObj(), *keys.begin() ); - } - private: - virtual BSONObj key() const { - return aDotB(); - } - }; - - class CompoundMissing : public Base { - public: - void run() { - create(); - - { - BSONObjSet keys; - getKeysFromObject( fromjson( "{x:'a',y:'b'}" ) , keys ); - checkSize( 1 , keys ); - assertEquals( BSON( "" << "a" << "" << "b" ) , *keys.begin() ); - } - - { - BSONObjSet keys; - getKeysFromObject( fromjson( "{x:'a'}" ) , keys ); - checkSize( 1 , keys ); - BSONObjBuilder b; - b.append( "" , "a" ); - b.appendNull( "" ); - assertEquals( b.obj() , *keys.begin() ); - } - - } - - private: - virtual BSONObj key() const { - return BSON( "x" << 1 << "y" << 1 ); - } - - }; - - class ArraySubelementComplex : public Base { - public: - void run() { - create(); - BSONObjSet keys; - getKeysFromObject( fromjson( "{a:[{b:[2]}]}" ), keys ); - checkSize( 1, keys ); - assertEquals( BSON( "" << 2 ), *keys.begin() ); - } - private: - virtual BSONObj key() const { - return aDotB(); - } - }; - - class ParallelArraysComplex : public Base { - public: - void run() { - create(); - BSONObjSet keys; - ASSERT_THROWS( getKeysFromObject( fromjson( "{a:[{b:[1],c:[2]}]}" ), keys ), - UserException ); - } - private: - virtual BSONObj key() const { - return fromjson( "{'a.b':1,'a.c':1}" ); - } - }; - - class AlternateMissing : public Base { - public: - void run() { - create(); - BSONObjSet keys; - getKeysFromObject( fromjson( "{a:[{b:1},{c:2}]}" ), keys ); - checkSize( 2, keys ); - BSONObjSet::iterator i = keys.begin(); - { - BSONObjBuilder e; - e.appendNull( "" ); - e.append( "", 2 ); - assertEquals( e.obj(), *i++ ); - } - - { - BSONObjBuilder e; - e.append( "", 1 ); - e.appendNull( "" ); - assertEquals( e.obj(), *i++ ); - } - } - private: - virtual BSONObj key() const { - return fromjson( "{'a.b':1,'a.c':1}" ); - } - }; - - class MultiComplex : public Base { - public: - void run() { - create(); - BSONObjSet keys; - getKeysFromObject( fromjson( "{a:[{b:1},{b:[1,2,3]}]}" ), keys ); - checkSize( 3, keys ); - } - private: - virtual BSONObj key() const { - return aDotB(); - } - }; - - class EmptyArray : Base { - public: - void run() { - create(); - - BSONObjSet keys; - getKeysFromObject( fromjson( "{a:[1,2]}" ), keys ); - checkSize(2, keys ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:[1]}" ), keys ); - checkSize(1, keys ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:null}" ), keys ); - checkSize(1, keys ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:[]}" ), keys ); - checkSize(1, keys ); - ASSERT_EQUALS( Undefined, keys.begin()->firstElement().type() ); - keys.clear(); - } - }; - - class DoubleArray : Base { - public: - void run() { - create(); - - BSONObjSet keys; - getKeysFromObject( fromjson( "{a:[1,2]}" ), keys ); - checkSize(2, keys ); - BSONObjSet::const_iterator i = keys.begin(); - ASSERT_EQUALS( BSON( "" << 1 << "" << 1 ), *i ); - ++i; - ASSERT_EQUALS( BSON( "" << 2 << "" << 2 ), *i ); - keys.clear(); - } - - protected: - BSONObj key() const { - return BSON( "a" << 1 << "a" << 1 ); - } - }; - - class DoubleEmptyArray : Base { - public: - void run() { - create(); - - BSONObjSet keys; - getKeysFromObject( fromjson( "{a:[]}" ), keys ); - checkSize(1, keys ); - ASSERT_EQUALS( fromjson( "{'':undefined,'':undefined}" ), *keys.begin() ); - keys.clear(); - } - - protected: - BSONObj key() const { - return BSON( "a" << 1 << "a" << 1 ); - } - }; - - class MultiEmptyArray : Base { - public: - void run() { - create(); - - BSONObjSet keys; - getKeysFromObject( fromjson( "{a:1,b:[1,2]}" ), keys ); - checkSize(2, keys ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:1,b:[1]}" ), keys ); - checkSize(1, keys ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:1,b:null}" ), keys ); - //cout << "YO : " << *(keys.begin()) << endl; - checkSize(1, keys ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:1,b:[]}" ), keys ); - checkSize(1, keys ); - //cout << "YO : " << *(keys.begin()) << endl; - BSONObjIterator i( *keys.begin() ); - ASSERT_EQUALS( NumberInt , i.next().type() ); - ASSERT_EQUALS( Undefined , i.next().type() ); - keys.clear(); - } - - protected: - BSONObj key() const { - return aAndB(); - } - }; - - class NestedEmptyArray : Base { - public: - void run() { - create(); - - BSONObjSet keys; - getKeysFromObject( fromjson( "{a:[]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':null}" ), *keys.begin() ); - keys.clear(); - } - protected: - BSONObj key() const { return BSON( "a.b" << 1 ); } - }; - - class MultiNestedEmptyArray : Base { - public: - void run() { - create(); - - BSONObjSet keys; - getKeysFromObject( fromjson( "{a:[]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':null,'':null}" ), *keys.begin() ); - keys.clear(); - } - protected: - BSONObj key() const { return BSON( "a.b" << 1 << "a.c" << 1 ); } - }; - - class UnevenNestedEmptyArray : public Base { - public: - void run() { - create(); - - BSONObjSet keys; - getKeysFromObject( fromjson( "{a:[]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':undefined,'':null}" ), *keys.begin() ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:[{b:1}]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':{b:1},'':1}" ), *keys.begin() ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:[{b:[]}]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':{b:[]},'':undefined}" ), *keys.begin() ); - keys.clear(); - } - protected: - BSONObj key() const { return BSON( "a" << 1 << "a.b" << 1 ); } - }; - - class ReverseUnevenNestedEmptyArray : public Base { - public: - void run() { - create(); - - BSONObjSet keys; - getKeysFromObject( fromjson( "{a:[]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':null,'':undefined}" ), *keys.begin() ); - keys.clear(); - } - protected: - BSONObj key() const { return BSON( "a.b" << 1 << "a" << 1 ); } - }; - - class SparseReverseUnevenNestedEmptyArray : public Base { - public: - void run() { - create( true ); - - BSONObjSet keys; - getKeysFromObject( fromjson( "{a:[]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':null,'':undefined}" ), *keys.begin() ); - keys.clear(); - } - protected: - BSONObj key() const { return BSON( "a.b" << 1 << "a" << 1 ); } - }; - - class SparseEmptyArray : public Base { - public: - void run() { - create( true ); - - BSONObjSet keys; - getKeysFromObject( fromjson( "{a:1}" ), keys ); - checkSize( 0, keys ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:[]}" ), keys ); - checkSize( 0, keys ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:[{c:1}]}" ), keys ); - checkSize( 0, keys ); - keys.clear(); - } - protected: - BSONObj key() const { return BSON( "a.b" << 1 ); } - }; - - class SparseEmptyArraySecond : public Base { - public: - void run() { - create( true ); - - BSONObjSet keys; - getKeysFromObject( fromjson( "{a:1}" ), keys ); - checkSize( 0, keys ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:[]}" ), keys ); - checkSize( 0, keys ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:[{c:1}]}" ), keys ); - checkSize( 0, keys ); - keys.clear(); - } - protected: - BSONObj key() const { return BSON( "z" << 1 << "a.b" << 1 ); } - }; - - class NonObjectMissingNestedField : public Base { - public: - void run() { - create(); - - BSONObjSet keys; - getKeysFromObject( fromjson( "{a:[]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':null}" ), *keys.begin() ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:[1]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':null}" ), *keys.begin() ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:[1,{b:1}]}" ), keys ); - checkSize( 2, keys ); - BSONObjSet::const_iterator c = keys.begin(); - ASSERT_EQUALS( fromjson( "{'':null}" ), *c ); - ++c; - ASSERT_EQUALS( fromjson( "{'':1}" ), *c ); - keys.clear(); - } - protected: - BSONObj key() const { return BSON( "a.b" << 1 ); } - }; - - class SparseNonObjectMissingNestedField : public Base { - public: - void run() { - create( true ); - - BSONObjSet keys; - getKeysFromObject( fromjson( "{a:[]}" ), keys ); - checkSize( 0, keys ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:[1]}" ), keys ); - checkSize( 0, keys ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:[1,{b:1}]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':1}" ), *keys.begin() ); - keys.clear(); - } - protected: - BSONObj key() const { return BSON( "a.b" << 1 ); } - }; - - class IndexedArrayIndex : public Base { - public: - void run() { - create(); - - BSONObjSet keys; - getKeysFromObject( fromjson( "{a:[1]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( BSON( "" << 1 ), *keys.begin() ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:[[1]]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':[1]}" ), *keys.begin() ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:[[]]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':undefined}" ), *keys.begin() ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:{'0':1}}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( BSON( "" << 1 ), *keys.begin() ); - keys.clear(); - - ASSERT_THROWS( getKeysFromObject( fromjson( "{a:[{'0':1}]}" ), keys ), UserException ); - - ASSERT_THROWS( getKeysFromObject( fromjson( "{a:[1,{'0':2}]}" ), keys ), UserException ); - } - protected: - BSONObj key() const { return BSON( "a.0" << 1 ); } - }; - - class DoubleIndexedArrayIndex : public Base { - public: - void run() { - create(); - - BSONObjSet keys; - getKeysFromObject( fromjson( "{a:[[1]]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':1}" ), *keys.begin() ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:[[]]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':null}" ), *keys.begin() ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:[]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':null}" ), *keys.begin() ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:[[[]]]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':undefined}" ), *keys.begin() ); - keys.clear(); - } - protected: - BSONObj key() const { return BSON( "a.0.0" << 1 ); } - }; - - class ObjectWithinArray : public Base { - public: - void run() { - create(); - - BSONObjSet keys; - getKeysFromObject( fromjson( "{a:[{b:1}]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':1}" ), *keys.begin() ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:[{b:[1]}]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':1}" ), *keys.begin() ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:[{b:[[1]]}]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':[1]}" ), *keys.begin() ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:[[{b:1}]]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':1}" ), *keys.begin() ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:[[{b:[1]}]]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':1}" ), *keys.begin() ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:[[{b:[[1]]}]]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':[1]}" ), *keys.begin() ); - keys.clear(); - - getKeysFromObject( fromjson( "{a:[[{b:[]}]]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':undefined}" ), *keys.begin() ); - keys.clear(); - } - protected: - BSONObj key() const { return BSON( "a.0.b" << 1 ); } - }; - - class ArrayWithinObjectWithinArray : public Base { - public: - void run() { - create(); - - BSONObjSet keys; - getKeysFromObject( fromjson( "{a:[{b:[1]}]}" ), keys ); - checkSize( 1, keys ); - ASSERT_EQUALS( fromjson( "{'':1}" ), *keys.begin() ); - keys.clear(); - } - protected: - BSONObj key() const { return BSON( "a.0.b.0" << 1 ); } - }; - - // also test numeric string field names - - } // namespace IndexDetailsTests - namespace MissingFieldTests { /** A missing field is represented as null in a btree index. */ @@ -1822,42 +912,6 @@ namespace NamespaceTests { } void setupTests() { - add< IndexDetailsTests::Create >(); - add< IndexDetailsTests::GetKeysFromObjectSimple >(); - add< IndexDetailsTests::GetKeysFromObjectDotted >(); - add< IndexDetailsTests::GetKeysFromArraySimple >(); - add< IndexDetailsTests::GetKeysFromArrayFirstElement >(); - add< IndexDetailsTests::GetKeysFromArraySecondElement >(); - add< IndexDetailsTests::GetKeysFromSecondLevelArray >(); - add< IndexDetailsTests::ParallelArraysBasic >(); - add< IndexDetailsTests::ArraySubobjectBasic >(); - add< IndexDetailsTests::ArraySubobjectMultiFieldIndex >(); - add< IndexDetailsTests::ArraySubobjectSingleMissing >(); - add< IndexDetailsTests::ArraySubobjectMissing >(); - add< IndexDetailsTests::ArraySubelementComplex >(); - add< IndexDetailsTests::ParallelArraysComplex >(); - add< IndexDetailsTests::AlternateMissing >(); - add< IndexDetailsTests::MultiComplex >(); - add< IndexDetailsTests::EmptyArray >(); - add< IndexDetailsTests::DoubleArray >(); - add< IndexDetailsTests::DoubleEmptyArray >(); - add< IndexDetailsTests::MultiEmptyArray >(); - add< IndexDetailsTests::NestedEmptyArray >(); - add< IndexDetailsTests::MultiNestedEmptyArray >(); - add< IndexDetailsTests::UnevenNestedEmptyArray >(); - add< IndexDetailsTests::ReverseUnevenNestedEmptyArray >(); - add< IndexDetailsTests::SparseReverseUnevenNestedEmptyArray >(); - add< IndexDetailsTests::SparseEmptyArray >(); - add< IndexDetailsTests::SparseEmptyArraySecond >(); - add< IndexDetailsTests::NonObjectMissingNestedField >(); - add< IndexDetailsTests::SparseNonObjectMissingNestedField >(); - add< IndexDetailsTests::IndexedArrayIndex >(); - add< IndexDetailsTests::DoubleIndexedArrayIndex >(); - add< IndexDetailsTests::ObjectWithinArray >(); - add< IndexDetailsTests::ArrayWithinObjectWithinArray >(); - add< IndexDetailsTests::MissingField >(); - add< IndexDetailsTests::SubobjectMissing >(); - add< IndexDetailsTests::CompoundMissing >(); add< NamespaceDetailsTests::Create >(); add< NamespaceDetailsTests::SingleAlloc >(); add< NamespaceDetailsTests::Realloc >(); |