summaryrefslogtreecommitdiff
path: root/src/mongo/dbtests/jsontests.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/dbtests/jsontests.cpp')
-rw-r--r--src/mongo/dbtests/jsontests.cpp319
1 files changed, 206 insertions, 113 deletions
diff --git a/src/mongo/dbtests/jsontests.cpp b/src/mongo/dbtests/jsontests.cpp
index 69476f19b77..f1b670e6bdd 100644
--- a/src/mongo/dbtests/jsontests.cpp
+++ b/src/mongo/dbtests/jsontests.cpp
@@ -35,9 +35,12 @@
#include "mongo/platform/basic.h"
+#include <boost/property_tree/json_parser.hpp>
+#include <boost/property_tree/ptree.hpp>
#include <fmt/format.h>
#include <fmt/printf.h>
#include <limits>
+#include <sstream>
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
@@ -46,7 +49,21 @@
#include "mongo/unittest/unittest.h"
#include "mongo/util/log.h"
+
namespace {
+std::string makeJsonEquvalent(const std::string& json) {
+ boost::property_tree::ptree tree;
+
+ std::istringstream in(json);
+ boost::property_tree::read_json(in, tree);
+
+ std::ostringstream out;
+ boost::property_tree::write_json(out, tree);
+
+ return out.str();
+}
+
+#define ASSERT_JSON_EQUALS(a, b) ASSERT_EQUALS(makeJsonEquvalent(a), makeJsonEquvalent(b))
using B = BSONObjBuilder;
using Arr = BSONArrayBuilder;
@@ -54,13 +71,15 @@ using Arr = BSONArrayBuilder;
// Tests of the BSONObj::jsonString member function.
namespace JsonStringTests {
-void checkJsonString(const BSONObj& bson, const std::string& json) {
- ASSERT_EQUALS(bson.jsonString(Strict), json);
-}
-
void checkJsonStringEach(const std::vector<std::pair<BSONObj, std::string>>& pairs) {
for (const auto& pair : pairs) {
- checkJsonString(pair.first, pair.second);
+ ASSERT_JSON_EQUALS(pair.first.jsonString(ExtendedCanonicalV2_0_0), pair.second);
+ ASSERT_JSON_EQUALS(pair.first.jsonString(ExtendedRelaxedV2_0_0), pair.second);
+
+ // Use ASSERT_EQUALS instead of ASSERT_JSON_EQUALS for LegacyStrict.
+ // LegacyStrict that not produce valid JSON in all cases (which makes boost::property_tree
+ // throw) and we have other tests elsewhere that checks for exact strings.
+ ASSERT_EQUALS(pair.first.jsonString(LegacyStrict), pair.second);
}
}
@@ -73,129 +92,168 @@ TEST(JsonStringTest, BasicTest) {
// per http://www.ietf.org/rfc/rfc4627.txt, control characters are
// (U+0000 through U+001F). U+007F is not mentioned as a control character.
{B().append("a", "\x1 \x1f").obj(),
- R"({ "a" : "\u0001 \u001f" })"}, // AdditionalControlCharacters
- {B().append("a", "\x80").obj(), "{ \"a\" : \"\x80\" }"}, // ExtendedAscii
- {B().append("\t", "b").obj(), R"({ "\t" : "b" })"}, // EscapeFieldName
- {B().append("a", 1).obj(), R"({ "a" : 1 })"}, // SingleIntMember
+ R"({ "a" : "\u0001 \u001f" })"}, // AdditionalControlCharacters
+ {B().append("\t", "b").obj(), R"({ "\t" : "b" })"}, // EscapeFieldName
});
}
+TEST(JsonStringTest, UnicodeTest) {
+ // Extended Canonical/Relaxed escapes invalid UTF-8 while LegacyStricts treats it as Extended
+ // Ascii
+ ASSERT_JSON_EQUALS(B().append("a", "\x80").obj().jsonString(ExtendedCanonicalV2_0_0),
+ R"({ "a" : "\u0080" })");
+ ASSERT_JSON_EQUALS(B().append("a", "\x80").obj().jsonString(ExtendedRelaxedV2_0_0),
+ R"({ "a" : "\u0080" })");
+ // Can't use ASSERT_JSON_EQUALS because property_tree does not allow invalid unicode
+ ASSERT_EQUALS(B().append("a", "\x80").obj().jsonString(LegacyStrict), "{ \"a\" : \"\x80\" }");
+}
+
+
TEST(JsonStringTest, NumbersTest) {
const double qNaN = std::numeric_limits<double>::quiet_NaN();
const double sNaN = std::numeric_limits<double>::signaling_NaN();
// Note there is no NaN in the JSON RFC but what would be the alternative?
- ASSERT(str::contains(B().append("a", qNaN).obj().jsonString(Strict), "NaN"));
- ASSERT(str::contains(B().append("a", sNaN).obj().jsonString(Strict), "NaN"));
+ ASSERT(str::contains(B().append("a", qNaN).obj().jsonString(ExtendedCanonicalV2_0_0), "NaN"));
+ ASSERT(str::contains(B().append("a", sNaN).obj().jsonString(ExtendedCanonicalV2_0_0), "NaN"));
- checkJsonStringEach({
- {B().append("a", 1.5).obj(), R"({ "a" : 1.5 })"}, // SingleNumberMember
- {B().append("a", 123456789).obj(), R"({ "a" : 123456789 })"}, // NumberPrecision
- {B().append("a", -1).obj(), R"({ "a" : -1 })"}, // NegativeNumber
- });
+ ASSERT_JSON_EQUALS(B().append("a", 1).obj().jsonString(ExtendedCanonicalV2_0_0),
+ R"({ "a" : {"$numberInt": 1 }})");
+ ASSERT_JSON_EQUALS(B().append("a", 1).obj().jsonString(ExtendedRelaxedV2_0_0),
+ R"({ "a" : 1 })");
+ ASSERT_EQUALS(B().append("a", 1).obj().jsonString(LegacyStrict), R"({ "a" : 1 })");
+
+ ASSERT_JSON_EQUALS(B().append("a", -1).obj().jsonString(ExtendedCanonicalV2_0_0),
+ R"({ "a" : {"$numberInt": -1 }})");
+ ASSERT_JSON_EQUALS(B().append("a", -1).obj().jsonString(ExtendedRelaxedV2_0_0),
+ R"({ "a" : -1 })");
+ ASSERT_EQUALS(B().append("a", -1).obj().jsonString(LegacyStrict), R"({ "a" : -1 })");
+
+ ASSERT_JSON_EQUALS(B().append("a", 1.5).obj().jsonString(ExtendedCanonicalV2_0_0),
+ R"({ "a" : {"$numberDouble": 1.5 }})");
+ ASSERT_JSON_EQUALS(B().append("a", 1.5).obj().jsonString(ExtendedRelaxedV2_0_0),
+ R"({ "a" : 1.5 })");
+ ASSERT_EQUALS(B().append("a", 1.5).obj().jsonString(LegacyStrict), R"({ "a" : 1.5 })");
}
TEST(JsonStringTest, NumberLongStrictZero) {
BSONObjBuilder b;
b.append("a", 0LL);
- ASSERT_EQUALS("{ \"a\" : { \"$numberLong\" : \"0\" } }", b.done().jsonString(Strict));
+ ASSERT_JSON_EQUALS("{ \"a\" : { \"$numberLong\" : \"0\" } }",
+ b.done().jsonString(ExtendedCanonicalV2_0_0));
+ ASSERT_JSON_EQUALS("{ \"a\" : 0 }", b.done().jsonString(ExtendedRelaxedV2_0_0));
+ ASSERT_EQUALS("{ \"a\" : { \"$numberLong\" : \"0\" } }", b.done().jsonString(LegacyStrict));
}
TEST(JsonStringTest, NumberLongStrict) {
BSONObjBuilder b;
b.append("a", 20000LL);
- ASSERT_EQUALS("{ \"a\" : { \"$numberLong\" : \"20000\" } }", b.done().jsonString(Strict));
+ ASSERT_JSON_EQUALS("{ \"a\" : { \"$numberLong\" : \"20000\" } }",
+ b.done().jsonString(ExtendedCanonicalV2_0_0));
+ ASSERT_JSON_EQUALS("{ \"a\" : 20000 }", b.done().jsonString(ExtendedRelaxedV2_0_0));
+ ASSERT_EQUALS("{ \"a\" : { \"$numberLong\" : \"20000\" } }", b.done().jsonString(LegacyStrict));
}
// Test a NumberLong that is too big to fit into a 32 bit integer
TEST(JsonStringTest, NumberLongStrictLarge) {
BSONObjBuilder b;
b.append("a", 9223372036854775807LL);
+ ASSERT_JSON_EQUALS("{ \"a\" : { \"$numberLong\" : \"9223372036854775807\" } }",
+ b.done().jsonString(ExtendedCanonicalV2_0_0));
+ ASSERT_JSON_EQUALS("{ \"a\" : 9223372036854775807 }",
+ b.done().jsonString(ExtendedRelaxedV2_0_0));
ASSERT_EQUALS("{ \"a\" : { \"$numberLong\" : \"9223372036854775807\" } }",
- b.done().jsonString(Strict));
+ b.done().jsonString(LegacyStrict));
}
TEST(JsonStringTest, NumberLongStrictNegative) {
BSONObjBuilder b;
b.append("a", -20000LL);
- ASSERT_EQUALS("{ \"a\" : { \"$numberLong\" : \"-20000\" } }", b.done().jsonString(Strict));
+ ASSERT_JSON_EQUALS("{ \"a\" : { \"$numberLong\" : \"-20000\" } }",
+ b.done().jsonString(ExtendedCanonicalV2_0_0));
+ ASSERT_JSON_EQUALS("{ \"a\" : -20000 }", b.done().jsonString(ExtendedRelaxedV2_0_0));
+ ASSERT_EQUALS("{ \"a\" : { \"$numberLong\" : \"-20000\" } }",
+ b.done().jsonString(LegacyStrict));
}
TEST(JsonStringTest, NumberDecimal) {
- BSONObjBuilder b;
- b.append("a", mongo::Decimal128("123456789.12345"));
- ASSERT_EQUALS("{ \"a\" : NumberDecimal(\"123456789.12345\") }", b.done().jsonString(TenGen));
-}
-
-TEST(JsonStringTest, NumberDecimalStrict) {
- BSONObjBuilder b;
- b.append("a", mongo::Decimal128("123456789.12345"));
- ASSERT_EQUALS("{ \"a\" : { \"$numberDecimal\" : \"123456789.12345\" } }",
- b.done().jsonString(Strict));
+ checkJsonStringEach({{B().append("a", mongo::Decimal128("123456789.12345")).obj(),
+ "{ \"a\" : { \"$numberDecimal\" : \"123456789.12345\" } }"}});
}
TEST(JsonStringTest, NumberDoubleNaN) {
BSONObjBuilder b;
b.append("a", std::numeric_limits<double>::quiet_NaN());
- ASSERT_EQUALS("{ \"a\" : NaN }", b.done().jsonString(Strict));
+ ASSERT_JSON_EQUALS(R"({ "a" : { "$numberDouble": "NaN" }})",
+ b.done().jsonString(ExtendedCanonicalV2_0_0));
+ ASSERT_JSON_EQUALS(R"({ "a" : { "$numberDouble": "NaN" }})",
+ b.done().jsonString(ExtendedRelaxedV2_0_0));
+ ASSERT_EQUALS(R"({ "a" : NaN })", b.done().jsonString(LegacyStrict));
}
TEST(JsonStringTest, NumberDoubleInfinity) {
BSONObjBuilder b;
b.append("a", std::numeric_limits<double>::infinity());
- ASSERT_EQUALS("{ \"a\" : Infinity }", b.done().jsonString(Strict));
+ ASSERT_JSON_EQUALS(R"({ "a" : { "$numberDouble": "Infinity" }})",
+ b.done().jsonString(ExtendedCanonicalV2_0_0));
+ ASSERT_JSON_EQUALS(R"({ "a" : { "$numberDouble": "Infinity" }})",
+ b.done().jsonString(ExtendedRelaxedV2_0_0));
+ ASSERT_EQUALS(R"({ "a" : Infinity })", b.done().jsonString(LegacyStrict));
}
TEST(JsonStringTest, NumberDoubleNegativeInfinity) {
BSONObjBuilder b;
b.append("a", -std::numeric_limits<double>::infinity());
- ASSERT_EQUALS("{ \"a\" : -Infinity }", b.done().jsonString(Strict));
+ ASSERT_JSON_EQUALS(R"({ "a" : { "$numberDouble": "-Infinity" }})",
+ b.done().jsonString(ExtendedCanonicalV2_0_0));
+ ASSERT_JSON_EQUALS(R"({ "a" : { "$numberDouble": "-Infinity" }})",
+ b.done().jsonString(ExtendedRelaxedV2_0_0));
+ ASSERT_EQUALS(R"({ "a" : -Infinity })", b.done().jsonString(LegacyStrict));
}
TEST(JsonStringTest, SingleBoolMember) {
- ASSERT_EQUALS(R"({ "a" : true })", B().appendBool("a", true).obj().jsonString(Strict));
- ASSERT_EQUALS(R"({ "a" : false })", B().appendBool("a", false).obj().jsonString(Strict));
+ checkJsonStringEach({{B().appendBool("a", true).obj(), R"({ "a" : true })"},
+ {B().appendBool("a", false).obj(), R"({ "a" : false })"}});
}
TEST(JsonStringTest, SingleNullMember) {
- BSONObjBuilder b;
- b.appendNull("a");
- ASSERT_EQUALS("{ \"a\" : null }", b.done().jsonString(Strict));
+ checkJsonStringEach({{B().appendNull("a").obj(), R"({ "a" : null })"}});
}
TEST(JsonStringTest, SingleUndefinedMember) {
- BSONObjBuilder b;
- b.appendUndefined("a");
- ASSERT_EQUALS("{ \"a\" : { \"$undefined\" : true } }", b.done().jsonString(Strict));
- ASSERT_EQUALS("{ \"a\" : undefined }", b.done().jsonString(TenGen));
+ checkJsonStringEach({{B().appendUndefined("a").obj(), R"({ "a" : { "$undefined" : true } })"}});
}
TEST(JsonStringTest, SingleObjectMember) {
- BSONObjBuilder b, c;
- b.append("a", c.done());
- ASSERT_EQUALS("{ \"a\" : {} }", b.done().jsonString(Strict));
+ BSONObjBuilder c;
+ checkJsonStringEach({{B().append("a", c.done()).obj(), R"({ "a" : {} })"}});
}
TEST(JsonStringTest, TwoMembers) {
BSONObjBuilder b;
b.append("a", 1);
b.append("b", 2);
- ASSERT_EQUALS("{ \"a\" : 1, \"b\" : 2 }", b.done().jsonString(Strict));
+ ASSERT_JSON_EQUALS(R"({ "a" : {"$numberInt" : 1}, "b" : {"$numberInt" : 2} })",
+ b.done().jsonString(ExtendedCanonicalV2_0_0));
+ ASSERT_JSON_EQUALS(R"({ "a" : 1, "b" : 2 })", b.done().jsonString(ExtendedRelaxedV2_0_0));
+ ASSERT_EQUALS(R"({ "a" : 1, "b" : 2 })", b.done().jsonString(LegacyStrict));
}
TEST(JsonStringTest, EmptyArray) {
std::vector<int> arr;
BSONObjBuilder b;
b.append("a", arr);
- ASSERT_EQUALS("{ \"a\" : [] }", b.done().jsonString(Strict));
+
+ checkJsonStringEach({{b.done(), R"({ "a" : [] })"}});
}
TEST(JsonStringTest, Array) {
- std::vector<int> arr;
- arr.push_back(1);
- arr.push_back(2);
+ std::vector<std::string> arr;
+ arr.push_back("1");
+ arr.push_back("2");
BSONObjBuilder b;
b.append("a", arr);
- ASSERT_EQUALS("{ \"a\" : [ 1, 2 ] }", b.done().jsonString(Strict));
+
+ checkJsonStringEach({{b.done(), R"({ "a" : [ "1", "2" ] })"}});
}
TEST(JsonStringTest, DBRef) {
@@ -204,12 +262,9 @@ TEST(JsonStringTest, DBRef) {
OID oid = OID::from(OIDbytes);
BSONObjBuilder b;
b.appendDBRef("a", "namespace", oid);
- BSONObj built = b.done();
- ASSERT_EQUALS(
- "{ \"a\" : { \"$ref\" : \"namespace\", \"$id\" : \"ffffffffffffffffffffffff\" } }",
- built.jsonString(Strict));
- ASSERT_EQUALS("{ \"a\" : Dbref( \"namespace\", \"ffffffffffffffffffffffff\" ) }",
- built.jsonString(TenGen));
+
+ checkJsonStringEach(
+ {{b.done(), R"({ "a" : { "$ref" : "namespace", "$id" : "ffffffffffffffffffffffff" } })"}});
}
TEST(JsonStringTest, DBRefZero) {
@@ -218,9 +273,9 @@ TEST(JsonStringTest, DBRefZero) {
OID oid = OID::from(OIDbytes);
BSONObjBuilder b;
b.appendDBRef("a", "namespace", oid);
- ASSERT_EQUALS(
- "{ \"a\" : { \"$ref\" : \"namespace\", \"$id\" : \"000000000000000000000000\" } }",
- b.done().jsonString(Strict));
+
+ checkJsonStringEach(
+ {{b.done(), R"({ "a" : { "$ref" : "namespace", "$id" : "000000000000000000000000" } })"}});
}
TEST(JsonStringTest, ObjectId) {
@@ -230,9 +285,8 @@ TEST(JsonStringTest, ObjectId) {
BSONObjBuilder b;
b.appendOID("a", &oid);
BSONObj built = b.done();
- ASSERT_EQUALS("{ \"a\" : { \"$oid\" : \"ffffffffffffffffffffffff\" } }",
- built.jsonString(Strict));
- ASSERT_EQUALS("{ \"a\" : ObjectId( \"ffffffffffffffffffffffff\" ) }", built.jsonString(TenGen));
+
+ checkJsonStringEach({{b.done(), R"({ "a" : { "$oid" : "ffffffffffffffffffffffff" } })"}});
}
TEST(JsonStringTest, BinData) {
@@ -243,25 +297,40 @@ TEST(JsonStringTest, BinData) {
BSONObjBuilder b;
b.appendBinData("a", 3, BinDataGeneral, z);
- std::string o = b.done().jsonString(Strict);
-
- ASSERT_EQUALS("{ \"a\" : { \"$binary\" : \"YWJj\", \"$type\" : \"00\" } }", o);
+ ASSERT_JSON_EQUALS(R"({ "a" : { "$binary" : { "base64": "YWJj", "subType" : "0" } } })",
+ b.done().jsonString(ExtendedCanonicalV2_0_0));
+ ASSERT_JSON_EQUALS(R"({ "a" : { "$binary" : { "base64": "YWJj", "subType" : "0" } } })",
+ b.done().jsonString(ExtendedRelaxedV2_0_0));
+ ASSERT_EQUALS(R"({ "a" : { "$binary" : "YWJj", "$type" : "00" } })",
+ b.done().jsonString(LegacyStrict));
BSONObjBuilder c;
c.appendBinData("a", 2, BinDataGeneral, z);
- ASSERT_EQUALS("{ \"a\" : { \"$binary\" : \"YWI=\", \"$type\" : \"00\" } }",
- c.done().jsonString(Strict));
+ ASSERT_JSON_EQUALS(R"({ "a" : { "$binary" : { "base64": "YWI=", "subType" : "0" } } })",
+ c.done().jsonString(ExtendedCanonicalV2_0_0));
+ ASSERT_JSON_EQUALS(R"({ "a" : { "$binary" : { "base64": "YWI=", "subType" : "0" } } })",
+ c.done().jsonString(ExtendedRelaxedV2_0_0));
+ ASSERT_EQUALS(R"({ "a" : { "$binary" : "YWI=", "$type" : "00" } })",
+ c.done().jsonString(LegacyStrict));
BSONObjBuilder d;
d.appendBinData("a", 1, BinDataGeneral, z);
- ASSERT_EQUALS("{ \"a\" : { \"$binary\" : \"YQ==\", \"$type\" : \"00\" } }",
- d.done().jsonString(Strict));
+ ASSERT_JSON_EQUALS(R"({ "a" : { "$binary" : { "base64": "YQ==", "subType" : "0" } } })",
+ d.done().jsonString(ExtendedCanonicalV2_0_0));
+ ASSERT_JSON_EQUALS(R"({ "a" : { "$binary" : { "base64": "YQ==", "subType" : "0" } } })",
+ d.done().jsonString(ExtendedRelaxedV2_0_0));
+ ASSERT_EQUALS(R"({ "a" : { "$binary" : "YQ==", "$type" : "00" } })",
+ d.done().jsonString(LegacyStrict));
}
TEST(JsonStringTest, Symbol) {
BSONObjBuilder b;
b.appendSymbol("a", "b");
- ASSERT_EQUALS("{ \"a\" : \"b\" }", b.done().jsonString(Strict));
+ ASSERT_JSON_EQUALS(R"({ "a" : { "$symbol": "b" } })",
+ b.done().jsonString(ExtendedCanonicalV2_0_0));
+ ASSERT_JSON_EQUALS(R"({ "a" : { "$symbol": "b" } })",
+ b.done().jsonString(ExtendedRelaxedV2_0_0));
+ ASSERT_EQUALS(R"({ "a" : "b" })", b.done().jsonString(LegacyStrict));
}
#ifdef _WIN32
@@ -321,94 +390,115 @@ TEST(JsonStringTest, Date) {
BSONObjBuilder b;
b.appendDate("a", Date_t());
BSONObj built = b.done();
- ASSERT_EQUALS("{ \"a\" : { \"$date\" : \"1969-12-31T19:00:00.000-0500\" } }",
- built.jsonString(Strict));
- ASSERT_EQUALS("{ \"a\" : Date( 0 ) }", built.jsonString(TenGen));
+ ASSERT_JSON_EQUALS(R"({ "a" : { "$date" : { "$numberLong" : "0" } } })",
+ built.jsonString(ExtendedCanonicalV2_0_0));
+ ASSERT_JSON_EQUALS(R"({ "a" : { "$date" : "1969-12-31T19:00:00.000-0500" } })",
+ built.jsonString(ExtendedRelaxedV2_0_0));
+ ASSERT_EQUALS(R"({ "a" : { "$date" : "1969-12-31T19:00:00.000-0500" } })",
+ built.jsonString(LegacyStrict));
// Test dates above our maximum formattable date. See SERVER-13760.
BSONObjBuilder b2;
b2.appendDate("a", Date_t::fromMillisSinceEpoch(32535262800000LL));
- BSONObj built2 = b2.done();
- ASSERT_EQUALS("{ \"a\" : { \"$date\" : { \"$numberLong\" : \"32535262800000\" } } }",
- built2.jsonString(Strict));
+
+ checkJsonStringEach(
+ {{b2.done(), R"({ "a" : { "$date" : { "$numberLong" : "32535262800000" } } })"}});
}
TEST(JsonStringTest, DateNegative) {
BSONObjBuilder b;
b.appendDate("a", Date_t::fromMillisSinceEpoch(-1));
- BSONObj built = b.done();
- ASSERT_EQUALS("{ \"a\" : { \"$date\" : { \"$numberLong\" : \"-1\" } } }",
- built.jsonString(Strict));
- ASSERT_EQUALS("{ \"a\" : Date( -1 ) }", built.jsonString(TenGen));
+
+ checkJsonStringEach({{b.done(), R"({ "a" : { "$date" : { "$numberLong" : "-1" } } })"}});
}
TEST(JsonStringTest, Regex) {
BSONObj built = B().appendRegex("a", "abc", "i").obj();
- ASSERT_EQUALS(R"({ "a" : { "$regex" : "abc", "$options" : "i" } })", built.jsonString(Strict));
- ASSERT_EQUALS(R"({ "a" : /abc/i })", built.jsonString(TenGen));
+ ASSERT_JSON_EQUALS(
+ R"({ "a" : { "$regularExpression" : { "pattern" : "abc", "options" : "i" } } })",
+ built.jsonString(ExtendedCanonicalV2_0_0));
+ ASSERT_JSON_EQUALS(
+ R"({ "a" : { "$regularExpression" : { "pattern" : "abc", "options" : "i" } } })",
+ built.jsonString(ExtendedRelaxedV2_0_0));
+ ASSERT_EQUALS(R"({ "a" : { "$regex" : "abc", "$options" : "i" } })",
+ built.jsonString(LegacyStrict));
}
TEST(JsonStringTest, RegexEscape) {
BSONObjBuilder b;
b.appendRegex("a", "/\"", "i");
BSONObj built = b.done();
- ASSERT_EQUALS("{ \"a\" : { \"$regex\" : \"/\\\"\", \"$options\" : \"i\" } }",
- built.jsonString(Strict));
- ASSERT_EQUALS("{ \"a\" : /\\/\\\"/i }", built.jsonString(TenGen));
+
+ // These raw string literal breaks the Visual Studio preprocessor
+ const char* expected =
+ R"({ "a" : { "$regularExpression" : { "pattern" : "/\"", "options" : "i" } } })";
+ const char* expectedLegacy = R"({ "a" : { "$regex" : "/\"", "$options" : "i" } })";
+ ASSERT_JSON_EQUALS(expected, built.jsonString(ExtendedCanonicalV2_0_0));
+ ASSERT_JSON_EQUALS(expected, built.jsonString(ExtendedRelaxedV2_0_0));
+ ASSERT_EQUALS(expectedLegacy, built.jsonString(LegacyStrict));
}
TEST(JsonStringTest, RegexManyOptions) {
BSONObjBuilder b;
b.appendRegex("a", "z", "abcgimx");
BSONObj built = b.done();
- ASSERT_EQUALS("{ \"a\" : { \"$regex\" : \"z\", \"$options\" : \"abcgimx\" } }",
- built.jsonString(Strict));
- ASSERT_EQUALS("{ \"a\" : /z/gim }", built.jsonString(TenGen));
+ ASSERT_JSON_EQUALS(
+ R"({ "a" : { "$regularExpression" : { "pattern" : "z", "options" : "abcgimx" } } })",
+ built.jsonString(ExtendedCanonicalV2_0_0));
+ ASSERT_JSON_EQUALS(
+ R"({ "a" : { "$regularExpression" : { "pattern" : "z", "options" : "abcgimx" } } })",
+ built.jsonString(ExtendedRelaxedV2_0_0));
+ ASSERT_EQUALS(R"({ "a" : { "$regex" : "z", "$options" : "abcgimx" } })",
+ built.jsonString(LegacyStrict));
}
TEST(JsonStringTest, RegexValidOption) {
BSONObj built = B().appendRegex("a", "sometext", "ms").obj();
+ ASSERT_JSON_EQUALS(
+ R"({ "a" : { "$regularExpression" : { "pattern" : "sometext", "options" : "ms" } } })",
+ built.jsonString(ExtendedCanonicalV2_0_0));
+ ASSERT_JSON_EQUALS(
+ R"({ "a" : { "$regularExpression" : { "pattern" : "sometext", "options" : "ms" } } })",
+ built.jsonString(ExtendedRelaxedV2_0_0));
ASSERT_EQUALS(R"({ "a" : { "$regex" : "sometext", "$options" : "ms" } })",
- built.jsonString(Strict));
- ASSERT_EQUALS(R"({ "a" : /sometext/ms })", built.jsonString(TenGen));
+ built.jsonString(LegacyStrict));
}
TEST(JsonStringTest, CodeTests) {
BSONObjBuilder b;
b.appendCode("x", "function(arg){ var string = \"\\n\"; return 1; }");
- BSONObj o = b.obj();
- ASSERT_EQUALS(
- "{ \"x\" : \"function(arg){ var string = \\\"\\\\n\\\"; "
- "return 1; }\" }",
- o.jsonString());
+
+ checkJsonStringEach({{b.done(),
+ "{ \"x\" : { \"$code\" : \"function(arg){ var string = \\\"\\\\n\\\"; "
+ "return 1; }\" } }"}});
}
TEST(JsonStringTest, CodeWScopeTests) {
BSONObjBuilder b;
- b.appendCodeWScope("x", "function(arg){ var string = \"\\n\"; return x; }", BSON("x" << 1));
- BSONObj o = b.obj();
- ASSERT_EQUALS(
- "{ \"x\" : "
- "{ \"$code\" : "
- "\"function(arg){ var string = \\\"\\\\n\\\"; return x; }\" , "
- "\"$scope\" : { \"x\" : 1 } } }",
- o.jsonString());
+ b.appendCodeWScope("x",
+ "function(arg){ var string = \"\\n\"; return x; }",
+ BSON("x"
+ << "1"));
+
+ checkJsonStringEach({{b.done(),
+ "{ \"x\" : "
+ "{ \"$code\" : "
+ "\"function(arg){ var string = \\\"\\\\n\\\"; return x; }\", "
+ "\"$scope\" : { \"x\" : \"1\" } } }"}});
}
TEST(JsonStringTest, TimestampTests) {
BSONObjBuilder b;
b.append("x", Timestamp(4, 10));
- BSONObj o = b.obj();
- ASSERT_EQUALS("{ \"x\" : { \"$timestamp\" : { \"t\" : 4, \"i\" : 10 } } }",
- o.jsonString(Strict));
- ASSERT_EQUALS("{ \"x\" : Timestamp( 4, 10 ) }", o.jsonString(TenGen));
+
+ checkJsonStringEach({{b.done(), R"({ "x" : { "$timestamp" : { "t" : 4, "i" : 10 } } })"}});
}
TEST(JsonStringTest, NullString) {
BSONObjBuilder b;
b.append("x", "a\0b", 4);
- BSONObj o = b.obj();
- ASSERT_EQUALS("{ \"x\" : \"a\\u0000b\" }", o.jsonString());
+
+ checkJsonStringEach({{b.done(), "{ \"x\" : \"a\\u0000b\" }"}});
}
TEST(JsonStringTest, AllTypesTest) {
@@ -439,7 +529,9 @@ TEST(JsonStringTest, AllTypesTest) {
b.appendMaxKey("v");
BSONObj o = b.obj();
- o.jsonString();
+ o.jsonString(ExtendedCanonicalV2_0_0);
+ o.jsonString(ExtendedRelaxedV2_0_0);
+ o.jsonString(LegacyStrict);
}
} // namespace JsonStringTests
@@ -468,8 +560,9 @@ void checkEquivalence(const std::string& json, const BSONObj& bson) {
ASSERT(fromjson(json).valid(BSONVersion::kLatest));
assertEquals(json, bson, fromjson(json), "mode: json-to-bson");
assertEquals(json, bson, fromjson(tojson(bson)), "mode: <default>");
- assertEquals(json, bson, fromjson(tojson(bson, Strict)), "mode: strict");
- assertEquals(json, bson, fromjson(tojson(bson, TenGen)), "mode: tengen");
+ assertEquals(json, bson, fromjson(tojson(bson, LegacyStrict)), "mode: strict");
+ assertEquals(json, bson, fromjson(tojson(bson, ExtendedCanonicalV2_0_0)), "mode: canonical");
+ assertEquals(json, bson, fromjson(tojson(bson, ExtendedRelaxedV2_0_0)), "mode: relaxed");
}
void checkRejection(const std::string& json) {