summaryrefslogtreecommitdiff
path: root/src/mongo/db/field_parser_test.cpp
diff options
context:
space:
mode:
authorJason Rassi <rassi@10gen.com>2013-06-03 14:23:51 -0400
committerJason Rassi <rassi@10gen.com>2013-06-03 14:23:51 -0400
commitc4b60b8ff775f494873535343cf50794f995cb5f (patch)
tree6dfa8e06ce78e706f0fba792120f50ac4c604e99 /src/mongo/db/field_parser_test.cpp
parent59a12930f6be0d422b0a3be342181646b3010bca (diff)
downloadmongo-c4b60b8ff775f494873535343cf50794f995cb5f.tar.gz
SERVER-9468 Move s/field-parser* to db/
Diffstat (limited to 'src/mongo/db/field_parser_test.cpp')
-rw-r--r--src/mongo/db/field_parser_test.cpp413
1 files changed, 413 insertions, 0 deletions
diff --git a/src/mongo/db/field_parser_test.cpp b/src/mongo/db/field_parser_test.cpp
new file mode 100644
index 00000000000..6878245bc5e
--- /dev/null
+++ b/src/mongo/db/field_parser_test.cpp
@@ -0,0 +1,413 @@
+/**
+ * Copyright (C) 2012 10gen 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/>.
+ */
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include "mongo/bson/bson_field.h"
+#include "mongo/bson/util/misc.h" // for Date_t
+#include "mongo/db/field_parser.h"
+#include "mongo/db/jsobj.h"
+#include "mongo/unittest/unittest.h"
+
+namespace {
+
+ using mongo::BSONArray;
+ using mongo::BSONField;
+ using mongo::BSONObj;
+ using mongo::BSONObjBuilder;
+ using mongo::Date_t;
+ using mongo::FieldParser;
+ using mongo::OID;
+ using std::string;
+ using std::vector;
+ using std::map;
+
+ class ExtractionFixture: public mongo::unittest::Test {
+ protected:
+ BSONObj doc;
+
+ bool valBool;
+ BSONArray valArray;
+ BSONObj valObj;
+ Date_t valDate;
+ string valString;
+ OID valOID;
+ long long valLong;
+
+ static BSONField<bool> aBool;
+ static BSONField<BSONArray> anArray;
+ static BSONField<BSONObj> anObj;
+ static BSONField<Date_t> aDate;
+ static BSONField<string> aString;
+ static BSONField<OID> anOID;
+ static BSONField<long long> aLong;
+
+ void setUp() {
+ valBool = true;
+ valArray = BSON_ARRAY(1 << 2 << 3);
+ valObj = BSON("a" << 1);
+ valDate = 1ULL;
+ valString = "a string";
+ valOID = OID::gen();
+ valLong = 1LL;
+
+ doc = BSON(aBool(valBool) <<
+ anArray(valArray) <<
+ anObj(valObj) <<
+ aDate(valDate) <<
+ aString(valString) <<
+ anOID(valOID) <<
+ aLong(valLong));
+ }
+
+ void tearDown() {
+ }
+ };
+
+ BSONField<bool> ExtractionFixture::aBool("aBool");
+ BSONField<BSONArray> ExtractionFixture::anArray("anArray");
+ BSONField<BSONObj> ExtractionFixture::anObj("anObj");
+ BSONField<Date_t> ExtractionFixture::aDate("aDate");
+ BSONField<string> ExtractionFixture::aString("aString");
+ BSONField<OID> ExtractionFixture::anOID("anOID");
+ BSONField<long long> ExtractionFixture::aLong("aLong");
+
+ TEST_F(ExtractionFixture, GetBool) {
+ BSONField<bool> notThere("otherBool", true);
+ BSONField<bool> wrongType(anObj.name());
+ bool val;
+ ASSERT_TRUE(FieldParser::extract(doc, aBool, &val));
+ ASSERT_EQUALS(val, valBool);
+ ASSERT_TRUE(FieldParser::extract(doc, notThere, &val));
+ ASSERT_EQUALS(val, true);
+ ASSERT_FALSE(FieldParser::extract(doc, wrongType, &val));
+ }
+
+ TEST_F(ExtractionFixture, GetBSONArray) {
+ BSONField<BSONArray> notThere("otherArray", BSON_ARRAY("a" << "b"));
+ BSONField<BSONArray> wrongType(aString.name());
+ BSONArray val;
+ ASSERT_TRUE(FieldParser::extract(doc, anArray, &val));
+ ASSERT_EQUALS(val, valArray);
+ ASSERT_TRUE(FieldParser::extract(doc, notThere, &val));
+ ASSERT_EQUALS(val, BSON_ARRAY("a" << "b"));
+ ASSERT_FALSE(FieldParser::extract(doc, wrongType, &val));
+ }
+
+ TEST_F(ExtractionFixture, GetBSONObj) {
+ BSONField<BSONObj> notThere("otherObj", BSON("b" << 1));
+ BSONField<BSONObj> wrongType(aString.name());
+ BSONObj val;
+ ASSERT_TRUE(FieldParser::extract(doc, anObj, &val));
+ ASSERT_EQUALS(val, valObj);
+ ASSERT_TRUE(FieldParser::extract(doc, notThere, &val));
+ ASSERT_EQUALS(val, BSON("b" << 1));
+ ASSERT_FALSE(FieldParser::extract(doc, wrongType, &val));
+ }
+
+ TEST_F(ExtractionFixture, GetDate) {
+ BSONField<Date_t> notThere("otherDate", 99ULL);
+ BSONField<Date_t> wrongType(aString.name());
+ Date_t val;
+ ASSERT_TRUE(FieldParser::extract(doc, aDate, &val));
+ ASSERT_EQUALS(val, valDate);
+ ASSERT_TRUE(FieldParser::extract(doc, notThere, &val));
+ ASSERT_EQUALS(val, 99ULL);
+ ASSERT_FALSE(FieldParser::extract(doc, wrongType, &val));
+ }
+
+ TEST_F(ExtractionFixture, GetString) {
+ BSONField<string> notThere("otherString", "abc");
+ BSONField<string> wrongType(aBool.name());
+ string val;
+ ASSERT_TRUE(FieldParser::extract(doc, aString, &val));
+ ASSERT_EQUALS(val, valString);
+ ASSERT_TRUE(FieldParser::extract(doc, notThere, &val));
+ ASSERT_EQUALS(val, "abc");
+ ASSERT_FALSE(FieldParser::extract(doc, wrongType, &val));
+ }
+
+ TEST_F(ExtractionFixture, GetOID) {
+ OID defOID = OID::gen();
+ BSONField<OID> notThere("otherOID", defOID);
+ BSONField<OID> wrongType(aString.name());
+ OID val;
+ ASSERT_TRUE(FieldParser::extract(doc, anOID, &val));
+ ASSERT_EQUALS(val, valOID);
+ ASSERT_TRUE(FieldParser::extract(doc, notThere, &val));
+ ASSERT_EQUALS(val, defOID);
+ ASSERT_FALSE(FieldParser::extract(doc, wrongType, &val));
+ }
+
+ TEST_F(ExtractionFixture, GetLong) {
+ BSONField<long long> notThere("otherLong", 0);
+ BSONField<long long> wrongType(aString.name());
+ long long val;
+ ASSERT_TRUE(FieldParser::extract(doc, aLong, &val));
+ ASSERT_EQUALS(val, valLong);
+ ASSERT_TRUE(FieldParser::extract(doc, notThere, &val));
+ ASSERT_EQUALS(val, 0);
+ ASSERT_FALSE(FieldParser::extract(doc, wrongType, &val));
+ }
+
+ TEST_F(ExtractionFixture, IsFound) {
+ bool bool_val;
+ BSONField<bool> aBoolMissing("aBoolMissing");
+ ASSERT_EQUALS(FieldParser::extract(doc, aBool, &bool_val, NULL),
+ FieldParser::FIELD_SET);
+ ASSERT_EQUALS(FieldParser::extract(doc, aBoolMissing, &bool_val, NULL),
+ FieldParser::FIELD_NONE);
+
+ Date_t Date_t_val;
+ BSONField<Date_t> aDateMissing("aDateMissing");
+ ASSERT_EQUALS(FieldParser::extract(doc, aDate, &Date_t_val, NULL),
+ FieldParser::FIELD_SET);
+ ASSERT_EQUALS(FieldParser::extract(doc, aDateMissing, &Date_t_val, NULL),
+ FieldParser::FIELD_NONE);
+
+ string string_val;
+ BSONField<string> aStringMissing("aStringMissing");
+ ASSERT_EQUALS(FieldParser::extract(doc, aString, &string_val, NULL),
+ FieldParser::FIELD_SET);
+ ASSERT_EQUALS(FieldParser::extract(doc, aStringMissing, &string_val, NULL),
+ FieldParser::FIELD_NONE);
+
+ OID OID_val;
+ BSONField<OID> anOIDMissing("anOIDMissing");
+ ASSERT_EQUALS(FieldParser::extract(doc, anOID, &OID_val, NULL),
+ FieldParser::FIELD_SET);
+ ASSERT_EQUALS(FieldParser::extract(doc, anOIDMissing, &OID_val, NULL),
+ FieldParser::FIELD_NONE);
+
+ long long long_long_val;
+ BSONField<long long> aLongMissing("aLongMissing");
+ ASSERT_EQUALS(FieldParser::extract(doc, aLong, &long_long_val, NULL),
+ FieldParser::FIELD_SET);
+ ASSERT_EQUALS(FieldParser::extract(doc, aLongMissing, &long_long_val, NULL),
+ FieldParser::FIELD_NONE);
+ }
+
+ TEST(ComplexExtraction, GetStringVector) {
+
+ // Test valid string vector extraction
+ BSONField<vector<string> > vectorField("testVector");
+
+ BSONObjBuilder bob;
+ bob << vectorField() << BSON_ARRAY("a" << "b" << "c");
+ BSONObj obj = bob.obj();
+
+ vector<string> parsedVector;
+
+ ASSERT(FieldParser::extract(obj, vectorField, &parsedVector));
+ ASSERT_EQUALS("a", parsedVector[0]);
+ ASSERT_EQUALS("b", parsedVector[1]);
+ ASSERT_EQUALS("c", parsedVector[2]);
+ ASSERT_EQUALS(parsedVector.size(), static_cast<size_t>(3));
+ }
+
+ TEST(ComplexExtraction, GetObjectVector) {
+
+ // Test valid BSONObj vector extraction
+ BSONField<vector<BSONObj> > vectorField("testVector");
+
+ BSONObjBuilder bob;
+ bob << vectorField() << BSON_ARRAY(BSON("a" << 1) << BSON("b" << 1) << BSON("c" << 1));
+ BSONObj obj = bob.obj();
+
+ vector<BSONObj> parsedVector;
+
+ ASSERT(FieldParser::extract(obj, vectorField, &parsedVector));
+ ASSERT_EQUALS(BSON("a" << 1), parsedVector[0]);
+ ASSERT_EQUALS(BSON("b" << 1), parsedVector[1]);
+ ASSERT_EQUALS(BSON("c" << 1), parsedVector[2]);
+ ASSERT_EQUALS(parsedVector.size(), static_cast<size_t>(3));
+ }
+
+ TEST(ComplexExtraction, GetBadVector) {
+
+ // Test invalid vector extraction
+ BSONField<vector<BSONObj> > vectorField("testVector");
+
+ BSONObjBuilder bob;
+ bob << vectorField() << BSON_ARRAY(BSON("a" << 1) << "XXX" << BSON("c" << 1));
+ BSONObj obj = bob.obj();
+
+ vector<BSONObj> parsedVector;
+
+ string errMsg;
+ ASSERT(!FieldParser::extract(obj, vectorField, &parsedVector, &errMsg));
+ ASSERT_NOT_EQUALS(errMsg, "");
+ }
+
+ TEST(ComplexExtraction, RoundTripVector) {
+
+ // Test vector extraction after re-writing to BSON
+ BSONField<vector<string> > vectorField("testVector");
+
+ BSONObj obj;
+ {
+ BSONObjBuilder bob;
+ bob << vectorField() << BSON_ARRAY("a" << "b" << "c");
+ obj = bob.obj();
+ }
+
+ vector<string> parsedVector;
+ ASSERT(FieldParser::extract(obj, vectorField, &parsedVector));
+
+ {
+ BSONObjBuilder bob;
+ bob.append(vectorField(), parsedVector);
+ obj = bob.obj();
+ }
+
+ parsedVector.clear();
+ ASSERT(FieldParser::extract(obj, vectorField, &parsedVector));
+
+ ASSERT_EQUALS("a", parsedVector[0]);
+ ASSERT_EQUALS("b", parsedVector[1]);
+ ASSERT_EQUALS("c", parsedVector[2]);
+ ASSERT_EQUALS(parsedVector.size(), static_cast<size_t>(3));
+ }
+
+ TEST(ComplexExtraction, GetStringMap) {
+
+ // Test valid string->string map extraction
+ BSONField<map<string, string> > mapField("testMap");
+
+ BSONObjBuilder bob;
+ bob << mapField() << BSON("a" << "a" << "b" << "b" << "c" << "c");
+ BSONObj obj = bob.obj();
+
+ map<string, string> parsedMap;
+
+ ASSERT(FieldParser::extract(obj, mapField, &parsedMap));
+ ASSERT_EQUALS("a", parsedMap["a"]);
+ ASSERT_EQUALS("b", parsedMap["b"]);
+ ASSERT_EQUALS("c", parsedMap["c"]);
+ ASSERT_EQUALS(parsedMap.size(), static_cast<size_t>(3));
+ }
+
+ TEST(ComplexExtraction, GetObjectMap) {
+
+ // Test valid string->BSONObj map extraction
+ BSONField<map<string, BSONObj> > mapField("testMap");
+
+ BSONObjBuilder bob;
+ bob << mapField() << BSON("a" << BSON("a" << "a") <<
+ "b" << BSON("b" << "b") <<
+ "c" << BSON("c" << "c"));
+ BSONObj obj = bob.obj();
+
+ map<string, BSONObj> parsedMap;
+
+ ASSERT(FieldParser::extract(obj, mapField, &parsedMap));
+ ASSERT_EQUALS(BSON("a" << "a"), parsedMap["a"]);
+ ASSERT_EQUALS(BSON("b" << "b"), parsedMap["b"]);
+ ASSERT_EQUALS(BSON("c" << "c"), parsedMap["c"]);
+ ASSERT_EQUALS(parsedMap.size(), static_cast<size_t>(3));
+ }
+
+ TEST(ComplexExtraction, GetBadMap) {
+
+ // Test invalid map extraction
+ BSONField<map<string, string> > mapField("testMap");
+
+ BSONObjBuilder bob;
+ bob << mapField() << BSON("a" << "a" << "b" << 123 << "c" << "c");
+ BSONObj obj = bob.obj();
+
+ map<string, string> parsedMap;
+
+ string errMsg;
+ ASSERT(!FieldParser::extract(obj, mapField, &parsedMap, &errMsg));
+ ASSERT_NOT_EQUALS(errMsg, "");
+ }
+
+ TEST(ComplexExtraction, RoundTripMap) {
+
+ // Test map extraction after re-writing to BSON
+ BSONField<map<string, string> > mapField("testMap");
+
+ BSONObj obj;
+ {
+ BSONObjBuilder bob;
+ bob << mapField() << BSON("a" << "a" << "b" << "b" << "c" << "c");
+ obj = bob.obj();
+ }
+
+ map<string, string> parsedMap;
+ ASSERT(FieldParser::extract(obj, mapField, &parsedMap));
+
+ {
+ BSONObjBuilder bob;
+ bob.append(mapField(), parsedMap);
+ obj = bob.obj();
+ }
+
+ parsedMap.clear();
+ ASSERT(FieldParser::extract(obj, mapField, &parsedMap));
+
+ ASSERT_EQUALS("a", parsedMap["a"]);
+ ASSERT_EQUALS("b", parsedMap["b"]);
+ ASSERT_EQUALS("c", parsedMap["c"]);
+ ASSERT_EQUALS(parsedMap.size(), static_cast<size_t>(3));
+ }
+
+ TEST(ComplexExtraction, GetNestedMap) {
+
+ // Test extraction of complex nested vector and map
+ BSONField<vector<map<string, string> > > nestedField("testNested");
+
+ BSONObj nestedMapObj = BSON("a" << "a" << "b" << "b" << "c" << "c");
+
+ BSONObjBuilder bob;
+ bob << nestedField() << BSON_ARRAY(nestedMapObj << nestedMapObj << nestedMapObj);
+ BSONObj obj = bob.obj();
+
+ vector<map<string, string> > parsed;
+
+ ASSERT(FieldParser::extract(obj, nestedField, &parsed));
+ ASSERT_EQUALS(parsed.size(), static_cast<size_t>(3));
+ for (int i = 0; i < 3; i++) {
+ map<string, string>& parsedMap = parsed[i];
+ ASSERT_EQUALS("a", parsedMap["a"]);
+ ASSERT_EQUALS("b", parsedMap["b"]);
+ ASSERT_EQUALS("c", parsedMap["c"]);
+ ASSERT_EQUALS(parsedMap.size(), static_cast<size_t>(3));
+ }
+ }
+
+ TEST(ComplexExtraction, GetBadNestedMap) {
+
+ // Test extraction of invalid complex nested vector and map
+ BSONField<vector<map<string, string> > > nestedField("testNested");
+
+ BSONObj nestedMapObj = BSON("a" << "a" << "b" << 123 << "c" << "c");
+
+ BSONObjBuilder bob;
+ bob << nestedField() << BSON_ARRAY(nestedMapObj << nestedMapObj << nestedMapObj);
+ BSONObj obj = bob.obj();
+
+ vector<map<string, string> > parsed;
+
+ string errMsg;
+ ASSERT(!FieldParser::extract(obj, nestedField, &parsed, &errMsg));
+ ASSERT_NOT_EQUALS(errMsg, "");
+ }
+
+} // unnamed namespace