diff options
author | Andrew Morrow <acm@10gen.com> | 2013-05-28 23:45:08 -0400 |
---|---|---|
committer | Andrew Morrow <acm@10gen.com> | 2013-05-31 11:08:13 -0400 |
commit | 29f747605154a4855ce76d21cd5ecbc2fa3890a0 (patch) | |
tree | e84fe18321546c65ee661fc391e26e7db07d741f | |
parent | f844ed02b1df1b54ea96b6e902cb7ab0663612d8 (diff) | |
download | mongo-29f747605154a4855ce76d21cd5ecbc2fa3890a0.tar.gz |
SERVER-8046 Add utilities to simplify debugging and testing with mutable
-rw-r--r-- | src/mongo/bson/mutable/const_element-inl.h | 4 | ||||
-rw-r--r-- | src/mongo/bson/mutable/const_element.h | 2 | ||||
-rw-r--r-- | src/mongo/bson/mutable/document-inl.h | 4 | ||||
-rw-r--r-- | src/mongo/bson/mutable/document.h | 2 | ||||
-rw-r--r-- | src/mongo/bson/mutable/element.cpp | 18 | ||||
-rw-r--r-- | src/mongo/bson/mutable/element.h | 3 | ||||
-rw-r--r-- | src/mongo/bson/mutable/mutable_bson_test.cpp | 46 | ||||
-rw-r--r-- | src/mongo/bson/mutable/mutable_bson_test_utils.cpp | 84 | ||||
-rw-r--r-- | src/mongo/bson/mutable/mutable_bson_test_utils.h | 18 |
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); |