summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Morrow <acm@10gen.com>2013-05-28 23:45:08 -0400
committerAndrew Morrow <acm@10gen.com>2013-05-31 11:08:13 -0400
commit29f747605154a4855ce76d21cd5ecbc2fa3890a0 (patch)
treee84fe18321546c65ee661fc391e26e7db07d741f
parentf844ed02b1df1b54ea96b6e902cb7ab0663612d8 (diff)
downloadmongo-29f747605154a4855ce76d21cd5ecbc2fa3890a0.tar.gz
SERVER-8046 Add utilities to simplify debugging and testing with mutable
-rw-r--r--src/mongo/bson/mutable/const_element-inl.h4
-rw-r--r--src/mongo/bson/mutable/const_element.h2
-rw-r--r--src/mongo/bson/mutable/document-inl.h4
-rw-r--r--src/mongo/bson/mutable/document.h2
-rw-r--r--src/mongo/bson/mutable/element.cpp18
-rw-r--r--src/mongo/bson/mutable/element.h3
-rw-r--r--src/mongo/bson/mutable/mutable_bson_test.cpp46
-rw-r--r--src/mongo/bson/mutable/mutable_bson_test_utils.cpp84
-rw-r--r--src/mongo/bson/mutable/mutable_bson_test_utils.h18
9 files changed, 152 insertions, 29 deletions
diff --git a/src/mongo/bson/mutable/const_element-inl.h b/src/mongo/bson/mutable/const_element-inl.h
index 1af561a515b..2e928ce53ac 100644
--- a/src/mongo/bson/mutable/const_element-inl.h
+++ b/src/mongo/bson/mutable/const_element-inl.h
@@ -172,6 +172,10 @@ namespace mutablebson {
return _basis.getIdx();
}
+ inline std::string ConstElement::toString() const {
+ return _basis.toString();
+ }
+
inline bool operator==(const ConstElement& l, const ConstElement& r) {
return l._basis == r._basis;
}
diff --git a/src/mongo/bson/mutable/const_element.h b/src/mongo/bson/mutable/const_element.h
index c3b751c43fa..1253a0566eb 100644
--- a/src/mongo/bson/mutable/const_element.h
+++ b/src/mongo/bson/mutable/const_element.h
@@ -88,6 +88,8 @@ namespace mutablebson {
inline StringData getFieldName() const;
inline Element::RepIdx getIdx() const;
+ inline std::string toString() const;
+
friend bool operator==(const ConstElement&, const ConstElement&);
private:
diff --git a/src/mongo/bson/mutable/document-inl.h b/src/mongo/bson/mutable/document-inl.h
index 63dea69dac8..5d6de21554f 100644
--- a/src/mongo/bson/mutable/document-inl.h
+++ b/src/mongo/bson/mutable/document-inl.h
@@ -47,5 +47,9 @@ namespace mutablebson {
return _root;
}
+ inline std::string Document::toString() const {
+ return getObject().toString();
+ }
+
} // namespace mutablebson
} // namespace mongo
diff --git a/src/mongo/bson/mutable/document.h b/src/mongo/bson/mutable/document.h
index 9b348f54920..2c0fdabf61b 100644
--- a/src/mongo/bson/mutable/document.h
+++ b/src/mongo/bson/mutable/document.h
@@ -384,6 +384,8 @@ namespace mutablebson {
/** Returns an element that will compare equal to a non-ok element. */
ConstElement end() const;
+ inline std::string toString() const;
+
private:
friend class Element;
diff --git a/src/mongo/bson/mutable/element.cpp b/src/mongo/bson/mutable/element.cpp
index fed2318b8ce..3abb68e9788 100644
--- a/src/mongo/bson/mutable/element.cpp
+++ b/src/mongo/bson/mutable/element.cpp
@@ -149,5 +149,23 @@ namespace mutablebson {
return pushBack(getDocument().makeElementSafeNum(fieldName, value));
}
+ std::string Element::toString() const {
+ if (hasValue()) {
+ return getValue().toString();
+ } else if (isType(mongo::Object)) {
+ BSONObjBuilder builder;
+ writeTo(&builder);
+ BSONObj obj = builder.obj();
+ return obj.firstElement().toString();
+ } else if (isType(mongo::Array)) {
+ BSONArrayBuilder builder;
+ writeArrayTo(&builder);
+ BSONArray arr = builder.arr();
+ return arr.firstElement().toString();
+ } else {
+ return "corrupted element";
+ }
+ }
+
} // namespace mutablebson
} // namespace mongo
diff --git a/src/mongo/bson/mutable/element.h b/src/mongo/bson/mutable/element.h
index dd9d83d9489..9839a4ceaea 100644
--- a/src/mongo/bson/mutable/element.h
+++ b/src/mongo/bson/mutable/element.h
@@ -551,6 +551,9 @@ namespace mutablebson {
*/
Status appendSafeNum(const StringData& fieldName, SafeNum value);
+ /** Convert this element to its JSON representation */
+ std::string toString() const;
+
private:
friend class Document;
friend bool operator==(const Element&, const Element&);
diff --git a/src/mongo/bson/mutable/mutable_bson_test.cpp b/src/mongo/bson/mutable/mutable_bson_test.cpp
index e788ce154d6..a9b859c93c0 100644
--- a/src/mongo/bson/mutable/mutable_bson_test.cpp
+++ b/src/mongo/bson/mutable/mutable_bson_test.cpp
@@ -458,6 +458,40 @@ namespace {
ASSERT_EQUALS(mongo::String, t0.getType());
}
+ TEST(Element, toString) {
+ mongo::BSONObj obj = mongo::fromjson("{ a : 1, b : [1, 2, 3], c : { x : 'x' } }");
+ mmb::Document doc(obj);
+
+ // Deserialize the 'c' but keep its value the same.
+ mmb::Element c = doc.root().rightChild();
+ ASSERT_TRUE(c.ok());
+ ASSERT_OK(c.appendString("y", "y"));
+ ASSERT_OK(c.popBack());
+
+ // 'a'
+ mongo::BSONObjIterator iter(obj);
+ mmb::Element docChild = doc.root().leftChild();
+ ASSERT_TRUE(docChild.ok());
+ ASSERT_EQUALS(iter.next().toString(), docChild.toString());
+
+ // 'b'
+ docChild = docChild.rightSibling();
+ ASSERT_TRUE(docChild.ok());
+ ASSERT_TRUE(iter.more());
+ ASSERT_EQUALS(iter.next().toString(), docChild.toString());
+
+ // 'c'
+ docChild = docChild.rightSibling();
+ ASSERT_TRUE(docChild.ok());
+ ASSERT_TRUE(iter.more());
+ ASSERT_EQUALS(iter.next().toString(), docChild.toString());
+
+ // eoo
+ docChild = docChild.rightSibling();
+ ASSERT_FALSE(iter.more());
+ ASSERT_FALSE(docChild.ok());
+ }
+
TEST(TimestampType, createElement) {
mmb::Document doc;
@@ -1160,5 +1194,17 @@ namespace {
ASSERT_EQUALS(newElem.getValueInt(), 1);
}
+ TEST(Document, toStringEmpty) {
+ mongo::BSONObj obj;
+ mmb::Document doc;
+ ASSERT_EQUALS(obj.toString(), doc.toString());
+ }
+
+ TEST(Document, toStringComplex) {
+ mongo::BSONObj obj = mongo::fromjson("{a : 1, b : [1, 2, 3], c : 'c'}");
+ mmb::Document doc(obj);
+ ASSERT_EQUALS(obj.toString(), doc.toString());
+ }
+
} // namespace
diff --git a/src/mongo/bson/mutable/mutable_bson_test_utils.cpp b/src/mongo/bson/mutable/mutable_bson_test_utils.cpp
index 11a5191b22e..64184526dee 100644
--- a/src/mongo/bson/mutable/mutable_bson_test_utils.cpp
+++ b/src/mongo/bson/mutable/mutable_bson_test_utils.cpp
@@ -27,49 +27,77 @@
namespace mongo {
namespace mutablebson {
+ namespace {
+
+ inline void assertSameSign(int lhs, int rhs) {
+ if (lhs == 0) {
+ ASSERT_EQUALS(rhs, 0);
+ } else if (lhs < 0) {
+ ASSERT_LESS_THAN(rhs, 0);
+ } else {
+ ASSERT_GREATER_THAN(rhs, 0);
+ }
+ }
+
+ inline void assertOppositeSign(int lhs, int rhs) {
+ if (lhs == 0) {
+ ASSERT_EQUALS(rhs, 0);
+ } else if (lhs < 0) {
+ ASSERT_GREATER_THAN(rhs, 0);
+ } else {
+ ASSERT_LESS_THAN(rhs, 0);
+ }
+ }
+
+ } // namespace
+
// TODO: We should really update this to be an ASSERT_ something, so that we can print out
// the expected and actual documents.
- bool checkDoc(const Document& doc, const BSONObj& exp) {
+ bool checkDoc(const Document& lhs, const BSONObj& rhs) {
// Get the fundamental result via BSONObj's woCompare path. This is the best starting
// point, because we think that Document::getObject and the serialization mechanism is
// pretty well sorted.
- BSONObj fromDoc = doc.getObject();
- const int primaryResult = fromDoc.woCompare(exp);
+ BSONObj fromLhs = lhs.getObject();
+ const int primaryResult = fromLhs.woCompare(rhs);
// Validate primary result via other comparison paths.
- const int secondaryResult = doc.compareWithBSONObj(exp);
-
- if (primaryResult == 0) {
- ASSERT_EQUALS(secondaryResult, 0);
- } else if (primaryResult < 0) {
- ASSERT_LESS_THAN(secondaryResult, 0);
- } else {
- ASSERT_GREATER_THAN(secondaryResult, 0);
- }
+ const int secondaryResult = lhs.compareWithBSONObj(rhs);
+
+ assertSameSign(primaryResult, secondaryResult);
// Check that mutables serialized result matches against its origin.
- ASSERT_EQUALS(0, doc.compareWithBSONObj(fromDoc));
+ ASSERT_EQUALS(0, lhs.compareWithBSONObj(fromLhs));
return (primaryResult == 0);
}
- std::ostream& operator<<(std::ostream& stream, const ConstElement& elt) {
- stream << "Element("<< static_cast<const void*>(&elt.getDocument()) << ", ";
- if (elt.ok())
- stream << elt.getIdx();
- else
- stream << "kInvalidIndex";
- stream << ")";
-
- if (elt.ok()) {
- stream << " of type '" << typeName(elt.getType()) << "'";
- if (elt.hasValue())
- stream << " with accessible value '" << elt.getValue() << "'";
- else
- stream << " with no accessible value";
- }
+ bool checkDoc(const Document& lhs, const Document& rhs) {
+
+ const int primaryResult = lhs.compareWith(rhs);
+ const BSONObj fromLhs = lhs.getObject();
+ const BSONObj fromRhs = rhs.getObject();
+
+ const int result_d_o = lhs.compareWithBSONObj(fromRhs);
+ const int result_o_d = rhs.compareWithBSONObj(fromLhs);
+
+ assertSameSign(primaryResult, result_d_o);
+ assertOppositeSign(primaryResult, result_o_d);
+
+ ASSERT_EQUALS(0, lhs.compareWithBSONObj(fromLhs));
+ ASSERT_EQUALS(0, rhs.compareWithBSONObj(fromRhs));
+
+ return (primaryResult == 0);
+ }
+
+ std::ostream& operator<<(std::ostream& stream, const Document& doc) {
+ stream << doc.toString();
+ return stream;
+ }
+
+ std::ostream& operator<<(std::ostream& stream, const ConstElement& elt) {
+ stream << elt.toString();
return stream;
}
diff --git a/src/mongo/bson/mutable/mutable_bson_test_utils.h b/src/mongo/bson/mutable/mutable_bson_test_utils.h
index f62376b79a4..386378a2a49 100644
--- a/src/mongo/bson/mutable/mutable_bson_test_utils.h
+++ b/src/mongo/bson/mutable/mutable_bson_test_utils.h
@@ -33,7 +33,23 @@ namespace mutablebson {
* (a) 'doc's generated object, (b) 'exp', the expected object, and (c) 'doc(exp)', a
* document created from 'exp'. Returns true if all three are equal, otherwise false.
*/
- bool checkDoc(const Document& doc, const BSONObj& exp);
+ bool checkDoc(const Document& lhs, const BSONObj& rhs);
+ bool checkDoc(const Document& lhs, const Document& rhs);
+
+ inline bool operator==(const Document& lhs, const Document& rhs) {
+ return checkDoc(lhs, rhs);
+ }
+
+ inline bool operator==(const BSONObj& lhs, const Document& rhs) {
+ return checkDoc(rhs, lhs);
+ }
+
+ inline bool operator==(const Document& lhs, const BSONObj& rhs) {
+ return checkDoc(lhs, rhs);
+ }
+
+ /** Stream out a document; useful within ASSERT calls */
+ std::ostream& operator<<(std::ostream& stream, const Document& doc);
/** Stream out an element; useful within ASSERT calls */
std::ostream& operator<<(std::ostream& stream, const ConstElement& elt);