summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2014-04-18 16:54:21 -0400
committerDavid Storch <david.storch@10gen.com>2014-04-21 15:48:27 -0400
commite87b42c4f13e48078f5c4aefba3caf18dcfba072 (patch)
treeb9f09cb02522451c4f8d390a9866ac8f1f3f1106
parent3286b208b30c43450354422e554070485f526e7b (diff)
downloadmongo-e87b42c4f13e48078f5c4aefba3caf18dcfba072.tar.gz
SERVER-8192 port btree key generation tests to a new unit test
-rw-r--r--src/mongo/db/index/SConscript11
-rw-r--r--src/mongo/db/index/btree_key_generator_test.cpp541
-rw-r--r--src/mongo/dbtests/namespacetests.cpp946
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 >();