// jsontests.cpp - Tests for json.{h,cpp} code and BSONObj::jsonString() // /** * Copyright (C) 2018-present MongoDB, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the Server Side Public License, version 1, * as published by MongoDB, Inc. * * 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 * Server Side Public License for more details. * * You should have received a copy of the Server Side Public License * along with this program. If not, see * . * * 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 Server Side 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. */ #define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kDefault #include "mongo/platform/basic.h" #include #include "mongo/db/jsobj.h" #include "mongo/db/json.h" #include "mongo/dbtests/dbtests.h" #include "mongo/platform/decimal128.h" #include "mongo/util/log.h" namespace JsonTests { using std::cout; using std::endl; using std::numeric_limits; using std::string; using std::stringstream; using std::vector; namespace JsonStringTests { class Empty { public: void run() { ASSERT_EQUALS("{}", BSONObj().jsonString(Strict)); } }; class SingleStringMember { public: void run() { ASSERT_EQUALS("{ \"a\" : \"b\" }", BSON("a" << "b") .jsonString(Strict)); } }; class EscapedCharacters { public: void run() { BSONObjBuilder b; b.append("a", "\" \\ / \b \f \n \r \t"); ASSERT_EQUALS("{ \"a\" : \"\\\" \\\\ / \\b \\f \\n \\r \\t\" }", b.done().jsonString(Strict)); } }; // 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. class AdditionalControlCharacters { public: void run() { BSONObjBuilder b; b.append("a", "\x1 \x1f"); ASSERT_EQUALS("{ \"a\" : \"\\u0001 \\u001f\" }", b.done().jsonString(Strict)); } }; class ExtendedAscii { public: void run() { BSONObjBuilder b; b.append("a", "\x80"); ASSERT_EQUALS("{ \"a\" : \"\x80\" }", b.done().jsonString(Strict)); } }; class EscapeFieldName { public: void run() { BSONObjBuilder b; b.append("\t", "b"); ASSERT_EQUALS("{ \"\\t\" : \"b\" }", b.done().jsonString(Strict)); } }; class SingleIntMember { public: void run() { BSONObjBuilder b; b.append("a", 1); ASSERT_EQUALS("{ \"a\" : 1 }", b.done().jsonString(Strict)); } }; class SingleNumberMember { public: void run() { BSONObjBuilder b; b.append("a", 1.5); ASSERT_EQUALS("{ \"a\" : 1.5 }", b.done().jsonString(Strict)); } }; class InvalidNumbers { public: void run() { BSONObjBuilder c; c.append("a", numeric_limits::quiet_NaN()); string s = c.done().jsonString(Strict); // Note there is no NaN in the JSON RFC but what would be the alternative? ASSERT(str::contains(s, "NaN")); // commented out assertion as it doesn't throw anymore: // ASSERT_THROWS( c.done().jsonString( Strict ), AssertionException ); BSONObjBuilder d; d.append("a", numeric_limits::signaling_NaN()); // ASSERT_THROWS( d.done().jsonString( Strict ), AssertionException ); s = d.done().jsonString(Strict); ASSERT(str::contains(s, "NaN")); } }; class NumberPrecision { public: void run() { BSONObjBuilder b; b.append("a", 123456789); ASSERT_EQUALS("{ \"a\" : 123456789 }", b.done().jsonString(Strict)); } }; class NegativeNumber { public: void run() { BSONObjBuilder b; b.append("a", -1); ASSERT_EQUALS("{ \"a\" : -1 }", b.done().jsonString(Strict)); } }; class NumberLongStrictZero { public: void run() { BSONObjBuilder b; b.append("a", 0LL); ASSERT_EQUALS("{ \"a\" : { \"$numberLong\" : \"0\" } }", b.done().jsonString(Strict)); } }; class NumberLongStrict { public: void run() { BSONObjBuilder b; b.append("a", 20000LL); ASSERT_EQUALS("{ \"a\" : { \"$numberLong\" : \"20000\" } }", b.done().jsonString(Strict)); } }; // Test a NumberLong that is too big to fit into a 32 bit integer class NumberLongStrictLarge { public: void run() { BSONObjBuilder b; b.append("a", 9223372036854775807LL); ASSERT_EQUALS("{ \"a\" : { \"$numberLong\" : \"9223372036854775807\" } }", b.done().jsonString(Strict)); } }; class NumberLongStrictNegative { public: void run() { BSONObjBuilder b; b.append("a", -20000LL); ASSERT_EQUALS("{ \"a\" : { \"$numberLong\" : \"-20000\" } }", b.done().jsonString(Strict)); } }; class NumberDecimal { public: void run() { BSONObjBuilder b; b.append("a", mongo::Decimal128("123456789.12345")); ASSERT_EQUALS("{ \"a\" : NumberDecimal(\"123456789.12345\") }", b.done().jsonString(TenGen)); } }; class NumberDecimalStrict { public: void run() { BSONObjBuilder b; b.append("a", mongo::Decimal128("123456789.12345")); ASSERT_EQUALS("{ \"a\" : { \"$numberDecimal\" : \"123456789.12345\" } }", b.done().jsonString(Strict)); } }; class NumberDoubleNaN { public: void run() { BSONObjBuilder b; b.append("a", std::numeric_limits::quiet_NaN()); ASSERT_EQUALS("{ \"a\" : NaN }", b.done().jsonString(Strict)); } }; class NumberDoubleInfinity { public: void run() { BSONObjBuilder b; b.append("a", std::numeric_limits::infinity()); ASSERT_EQUALS("{ \"a\" : Infinity }", b.done().jsonString(Strict)); } }; class NumberDoubleNegativeInfinity { public: void run() { BSONObjBuilder b; b.append("a", -std::numeric_limits::infinity()); ASSERT_EQUALS("{ \"a\" : -Infinity }", b.done().jsonString(Strict)); } }; class SingleBoolMember { public: void run() { BSONObjBuilder b; b.appendBool("a", true); ASSERT_EQUALS("{ \"a\" : true }", b.done().jsonString(Strict)); BSONObjBuilder c; c.appendBool("a", false); ASSERT_EQUALS("{ \"a\" : false }", c.done().jsonString(Strict)); } }; class SingleNullMember { public: void run() { BSONObjBuilder b; b.appendNull("a"); ASSERT_EQUALS("{ \"a\" : null }", b.done().jsonString(Strict)); } }; class SingleUndefinedMember { public: void run() { BSONObjBuilder b; b.appendUndefined("a"); ASSERT_EQUALS("{ \"a\" : { \"$undefined\" : true } }", b.done().jsonString(Strict)); ASSERT_EQUALS("{ \"a\" : undefined }", b.done().jsonString(TenGen)); } }; class SingleObjectMember { public: void run() { BSONObjBuilder b, c; b.append("a", c.done()); ASSERT_EQUALS("{ \"a\" : {} }", b.done().jsonString(Strict)); } }; class TwoMembers { public: void run() { BSONObjBuilder b; b.append("a", 1); b.append("b", 2); ASSERT_EQUALS("{ \"a\" : 1, \"b\" : 2 }", b.done().jsonString(Strict)); } }; class EmptyArray { public: void run() { vector arr; BSONObjBuilder b; b.append("a", arr); ASSERT_EQUALS("{ \"a\" : [] }", b.done().jsonString(Strict)); } }; class Array { public: void run() { vector arr; arr.push_back(1); arr.push_back(2); BSONObjBuilder b; b.append("a", arr); ASSERT_EQUALS("{ \"a\" : [ 1, 2 ] }", b.done().jsonString(Strict)); } }; class DBRef { public: void run() { char OIDbytes[OID::kOIDSize]; memset(&OIDbytes, 0xff, OID::kOIDSize); 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)); } }; class DBRefZero { public: void run() { char OIDbytes[OID::kOIDSize]; memset(&OIDbytes, 0, OID::kOIDSize); OID oid = OID::from(OIDbytes); BSONObjBuilder b; b.appendDBRef("a", "namespace", oid); ASSERT_EQUALS( "{ \"a\" : { \"$ref\" : \"namespace\", \"$id\" : \"000000000000000000000000\" } }", b.done().jsonString(Strict)); } }; class ObjectId { public: void run() { char OIDbytes[OID::kOIDSize]; memset(&OIDbytes, 0xff, OID::kOIDSize); OID oid = OID::from(OIDbytes); 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)); } }; class BinData { public: void run() { char z[3]; z[0] = 'a'; z[1] = 'b'; z[2] = 'c'; BSONObjBuilder b; b.appendBinData("a", 3, BinDataGeneral, z); string o = b.done().jsonString(Strict); ASSERT_EQUALS("{ \"a\" : { \"$binary\" : \"YWJj\", \"$type\" : \"00\" } }", o); BSONObjBuilder c; c.appendBinData("a", 2, BinDataGeneral, z); ASSERT_EQUALS("{ \"a\" : { \"$binary\" : \"YWI=\", \"$type\" : \"00\" } }", c.done().jsonString(Strict)); BSONObjBuilder d; d.appendBinData("a", 1, BinDataGeneral, z); ASSERT_EQUALS("{ \"a\" : { \"$binary\" : \"YQ==\", \"$type\" : \"00\" } }", d.done().jsonString(Strict)); } }; class Symbol { public: void run() { BSONObjBuilder b; b.appendSymbol("a", "b"); ASSERT_EQUALS("{ \"a\" : \"b\" }", b.done().jsonString(Strict)); } }; #ifdef _WIN32 char tzEnvString[] = "TZ=EST+5EDT"; #else char tzEnvString[] = "TZ=America/New_York"; #endif class Date { public: Date() { char* _oldTimezonePtr = getenv("TZ"); _oldTimezone = std::string(_oldTimezonePtr ? _oldTimezonePtr : ""); if (-1 == putenv(tzEnvString)) { FAIL(errnoWithDescription()); } tzset(); } ~Date() { if (!_oldTimezone.empty()) { #ifdef _WIN32 errno_t ret = _putenv_s("TZ", _oldTimezone.c_str()); if (0 != ret) { StringBuilder sb; sb << "Error setting TZ environment variable to: " << _oldTimezone << ". Error code: " << ret; FAIL(sb.str()); } #else if (-1 == setenv("TZ", _oldTimezone.c_str(), 1)) { FAIL(errnoWithDescription()); } #endif } else { #ifdef _WIN32 errno_t ret = _putenv_s("TZ", ""); if (0 != ret) { StringBuilder sb; sb << "Error unsetting TZ environment variable. Error code: " << ret; FAIL(sb.str()); } #else if (-1 == unsetenv("TZ")) { FAIL(errnoWithDescription()); } #endif } tzset(); } void run() { 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)); // 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)); } private: std::string _oldTimezone; }; class DateNegative { public: void run() { 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)); } }; class Regex { public: void run() { BSONObjBuilder b; b.appendRegex("a", "abc", "i"); BSONObj built = b.done(); ASSERT_EQUALS("{ \"a\" : { \"$regex\" : \"abc\", \"$options\" : \"i\" } }", built.jsonString(Strict)); ASSERT_EQUALS("{ \"a\" : /abc/i }", built.jsonString(TenGen)); } }; class RegexEscape { public: void run() { 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)); } }; class RegexManyOptions { public: void run() { 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)); } }; class CodeTests { public: void run() { 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()); } }; class CodeWScopeTests { public: void run() { 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()); } }; class TimestampTests { public: void run() { 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)); } }; class NullString { public: void run() { BSONObjBuilder b; b.append("x", "a\0b", 4); BSONObj o = b.obj(); ASSERT_EQUALS("{ \"x\" : \"a\\u0000b\" }", o.jsonString()); } }; class AllTypes { public: void run() { OID oid; oid.init(); BSONObjBuilder b; b.appendMinKey("a"); b.append("b", 5.5); b.append("c", "abc"); b.append("e", BSON("x" << 1)); b.append("f", BSON_ARRAY(1 << 2 << 3)); b.appendBinData("g", sizeof(AllTypes), bdtCustom, (const void*)this); b.appendUndefined("h"); b.append("i", oid); b.appendBool("j", 1); b.appendDate("k", Date_t::fromMillisSinceEpoch(123)); b.appendNull("l"); b.appendRegex("m", "a"); b.appendDBRef("n", "foo", oid); b.appendCode("o", "function(){}"); b.appendSymbol("p", "foo"); b.appendCodeWScope("q", "function(){}", BSON("x" << 1)); b.append("r", (int)5); b.appendTimestamp("s", 123123123123123LL); b.append("t", 12321312312LL); b.append("u", "123456789.12345"); b.appendMaxKey("v"); BSONObj o = b.obj(); o.jsonString(); // cout << o.jsonString() << endl; } }; } // namespace JsonStringTests namespace FromJsonTests { class Base { public: virtual ~Base() {} void run() { ASSERT(fromjson(json()).valid(BSONVersion::kLatest)); assertEquals(bson(), fromjson(json()), "mode: json-to-bson"); assertEquals(bson(), fromjson(tojson(bson())), "mode: "); assertEquals(bson(), fromjson(tojson(bson(), Strict)), "mode: strict"); assertEquals(bson(), fromjson(tojson(bson(), TenGen)), "mode: tengen"); } protected: virtual BSONObj bson() const = 0; virtual string json() const = 0; private: void assertEquals(const BSONObj& expected, const BSONObj& actual, const char* msg) { const bool bad = expected.woCompare(actual); if (bad) { ::mongo::log() << "want:" << expected.jsonString() << " size: " << expected.objsize() << endl; ::mongo::log() << "got :" << actual.jsonString() << " size: " << actual.objsize() << endl; ::mongo::log() << expected.hexDump() << endl; ::mongo::log() << actual.hexDump() << endl; ::mongo::log() << msg << endl; ::mongo::log() << "orig json:" << this->json(); } ASSERT(!bad); } }; class Bad { public: virtual ~Bad() {} void run() { ASSERT_THROWS(fromjson(json()), AssertionException); } protected: virtual string json() const = 0; }; class Empty : public Base { virtual BSONObj bson() const { BSONObjBuilder b; return b.obj(); } virtual string json() const { return "{}"; } }; class EmptyWithSpace : public Base { virtual BSONObj bson() const { BSONObjBuilder b; return b.obj(); } virtual string json() const { return "{ }"; } }; class SingleString : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("a", "b"); return b.obj(); } virtual string json() const { return "{ \"a\" : \"b\" }"; } }; class EmptyStrings : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("", ""); return b.obj(); } virtual string json() const { return "{ \"\" : \"\" }"; } }; class ReservedFieldName : public Bad { virtual string json() const { return "{ \"$oid\" : \"b\" }"; } }; class ReservedFieldName1 : public Bad { virtual string json() const { return "{ \"$ref\" : \"b\" }"; } }; class NumberFieldName : public Bad { virtual string json() const { return "{ 0 : \"b\" }"; } }; class InvalidFieldName : public Bad { virtual string json() const { return "{ test.test : \"b\" }"; } }; class QuotedNullName : public Bad { virtual string json() const { return "{ \"nc\0nc\" : \"b\" }"; } }; class NoValue : public Bad { virtual string json() const { return "{ a : }"; } }; class InvalidValue : public Bad { virtual string json() const { return "{ a : a }"; } }; class OkDollarFieldName : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("$where", 1); return b.obj(); } virtual string json() const { return "{ \"$where\" : 1 }"; } }; class SingleNumber : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("a", 1); return b.obj(); } virtual string json() const { return "{ \"a\" : 1 }"; } }; class RealNumber : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("a", strtod("0.7", 0)); return b.obj(); } virtual string json() const { return "{ \"a\" : 0.7 }"; } }; class FancyNumber : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("a", strtod("-4.4433e-2", 0)); return b.obj(); } virtual string json() const { return "{ \"a\" : -4.4433e-2 }"; } }; class TwoElements : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("a", 1); b.append("b", "foo"); return b.obj(); } virtual string json() const { return "{ \"a\" : 1, \"b\" : \"foo\" }"; } }; class Subobject : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("a", 1); BSONObjBuilder c; c.append("z", b.done()); return c.obj(); } virtual string json() const { return "{ \"z\" : { \"a\" : 1 } }"; } }; class DeeplyNestedObject : public Base { virtual string buildJson(int depth) const { if (depth == 0) { return "{\"0\":true}"; } else { std::stringstream ss; ss << "{\"" << depth << "\":" << buildJson(depth - 1) << "}"; depth--; return ss.str(); } } virtual BSONObj buildBson(int depth) const { BSONObjBuilder builder; if (depth == 0) { builder.append("0", true); return builder.obj(); } else { std::stringstream ss; ss << depth; depth--; builder.append(ss.str(), buildBson(depth)); return builder.obj(); } } virtual BSONObj bson() const { return buildBson(35); } virtual string json() const { return buildJson(35); } }; class ArrayEmpty : public Base { virtual BSONObj bson() const { vector arr; BSONObjBuilder b; b.append("a", arr); return b.obj(); } virtual string json() const { return "{ \"a\" : [] }"; } }; class TopLevelArrayEmpty : public Base { virtual BSONObj bson() const { return BSONArray(); } virtual string json() const { return "[]"; } }; class TopLevelArray : public Base { virtual BSONObj bson() const { BSONArrayBuilder builder; builder.append(123); builder.append("abc"); return builder.arr(); } virtual string json() const { return "[ 123, \"abc\" ]"; } }; class Array : public Base { virtual BSONObj bson() const { vector arr; arr.push_back(1); arr.push_back(2); arr.push_back(3); BSONObjBuilder b; b.append("a", arr); return b.obj(); } virtual string json() const { return "{ \"a\" : [ 1, 2, 3 ] }"; } }; class True : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendBool("a", true); return b.obj(); } virtual string json() const { return "{ \"a\" : true }"; } }; class False : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendBool("a", false); return b.obj(); } virtual string json() const { return "{ \"a\" : false }"; } }; class Null : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendNull("a"); return b.obj(); } virtual string json() const { return "{ \"a\" : null }"; } }; class Undefined : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendUndefined("a"); return b.obj(); } virtual string json() const { return "{ \"a\" : undefined }"; } }; class UndefinedStrict : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendUndefined("a"); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$undefined\" : true } }"; } }; class UndefinedStrictBad : public Bad { virtual string json() const { return "{ \"a\" : { \"$undefined\" : false } }"; } }; class EscapedCharacters : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("a", "\" \\ / \b \f \n \r \t \v"); return b.obj(); } virtual string json() const { return "{ \"a\" : \"\\\" \\\\ \\/ \\b \\f \\n \\r \\t \\v\" }"; } }; class NonEscapedCharacters : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("a", "% { a z $ # ' "); return b.obj(); } virtual string json() const { return "{ \"a\" : \"\\% \\{ \\a \\z \\$ \\# \\' \\ \" }"; } }; class AllowedControlCharacter : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("a", "\x7f"); return b.obj(); } virtual string json() const { return "{ \"a\" : \"\x7f\" }"; } }; class InvalidControlCharacter : public Bad { virtual string json() const { return "{ \"a\" : \"\x1f\" }"; } }; class NumbersInFieldName : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("b1", "b"); return b.obj(); } virtual string json() const { return "{ b1 : \"b\" }"; } }; class EscapeFieldName : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("\n", "b"); return b.obj(); } virtual string json() const { return "{ \"\\n\" : \"b\" }"; } }; class EscapedUnicodeToUtf8 : public Base { virtual BSONObj bson() const { BSONObjBuilder b; unsigned char u[7]; u[0] = 0xe0 | 0x0a; u[1] = 0x80; u[2] = 0x80; u[3] = 0xe0 | 0x0a; u[4] = 0x80; u[5] = 0x80; u[6] = 0; b.append("a", (char*)u); BSONObj built = b.obj(); ASSERT_EQUALS(string((char*)u), built.firstElement().valuestr()); return built; } virtual string json() const { return "{ \"a\" : \"\\ua000\\uA000\" }"; } }; class Utf8AllOnes : public Base { virtual BSONObj bson() const { BSONObjBuilder b; unsigned char u[8]; u[0] = 0x01; u[1] = 0x7f; u[2] = 0xdf; u[3] = 0xbf; u[4] = 0xef; u[5] = 0xbf; u[6] = 0xbf; u[7] = 0; b.append("a", (char*)u); return b.obj(); } virtual string json() const { return "{ \"a\" : \"\\u0001\\u007f\\u07ff\\uffff\" }"; } }; class Utf8FirstByteOnes : public Base { virtual BSONObj bson() const { BSONObjBuilder b; unsigned char u[6]; u[0] = 0xdc; u[1] = 0x80; u[2] = 0xef; u[3] = 0xbc; u[4] = 0x80; u[5] = 0; b.append("a", (char*)u); return b.obj(); } virtual string json() const { return "{ \"a\" : \"\\u0700\\uff00\" }"; } }; class Utf8Invalid : public Bad { virtual string json() const { return "{ \"a\" : \"\\u0ZZZ\" }"; } }; class Utf8TooShort : public Bad { virtual string json() const { return "{ \"a\" : \"\\u000\" }"; } }; class DBRefConstructor : public Base { virtual BSONObj bson() const { BSONObjBuilder b; BSONObjBuilder subBuilder(b.subobjStart("a")); subBuilder.append("$ref", "ns"); subBuilder.append("$id", "000000000000000000000000"); subBuilder.done(); return b.obj(); } virtual string json() const { return "{ \"a\" : Dbref( \"ns\", \"000000000000000000000000\" ) }"; } }; // Added for consistency with the mongo shell class DBRefConstructorCapitals : public Base { virtual BSONObj bson() const { BSONObjBuilder b; BSONObjBuilder subBuilder(b.subobjStart("a")); subBuilder.append("$ref", "ns"); subBuilder.append("$id", "000000000000000000000000"); subBuilder.done(); return b.obj(); } virtual string json() const { return "{ \"a\" : DBRef( \"ns\", \"000000000000000000000000\" ) }"; } }; class DBRefConstructorDbName : public Base { virtual BSONObj bson() const { BSONObjBuilder b; BSONObjBuilder subBuilder(b.subobjStart("a")); subBuilder.append("$ref", "ns"); subBuilder.append("$id", "000000000000000000000000"); subBuilder.append("$db", "dbname"); subBuilder.done(); return b.obj(); } virtual string json() const { return "{ \"a\" : Dbref( \"ns\", \"000000000000000000000000\", \"dbname\" ) }"; } }; class DBRefConstructorNumber : public Base { virtual BSONObj bson() const { BSONObjBuilder b; BSONObjBuilder subBuilder(b.subobjStart("a")); subBuilder.append("$ref", "ns"); subBuilder.append("$id", 1); subBuilder.done(); return b.obj(); } virtual string json() const { return "{ \"a\" : Dbref( \"ns\", 1 ) }"; } }; class DBRefConstructorObject : public Base { virtual BSONObj bson() const { BSONObjBuilder b; BSONObjBuilder subBuilder(b.subobjStart("a")); subBuilder.append("$ref", "ns"); BSONObjBuilder idSubBuilder(subBuilder.subobjStart("$id")); idSubBuilder.append("b", true); idSubBuilder.done(); subBuilder.done(); return b.obj(); } virtual string json() const { return "{ \"a\" : Dbref( \"ns\", { \"b\" : true } ) }"; } }; class DBRefNumberId : public Base { virtual BSONObj bson() const { BSONObjBuilder b; BSONObjBuilder subBuilder(b.subobjStart("a")); subBuilder.append("$ref", "ns"); subBuilder.append("$id", 1); subBuilder.done(); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$ref\" : \"ns\", \"$id\" : 1 } }"; } }; class DBRefObjectAsId : public Base { virtual BSONObj bson() const { BSONObjBuilder b; BSONObjBuilder subBuilder(b.subobjStart("a")); subBuilder.append("$ref", "ns"); BSONObjBuilder idSubBuilder(subBuilder.subobjStart("$id")); idSubBuilder.append("b", true); idSubBuilder.done(); subBuilder.done(); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$ref\" : \"ns\", \"$id\" : { \"b\" : true } } }"; } }; class DBRefStringId : public Base { virtual BSONObj bson() const { BSONObjBuilder b; BSONObjBuilder subBuilder(b.subobjStart("a")); subBuilder.append("$ref", "ns"); subBuilder.append("$id", "000000000000000000000000"); subBuilder.done(); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$ref\" : \"ns\", \"$id\" : \"000000000000000000000000\" } }"; } }; class DBRefObjectIDObject : public Base { virtual BSONObj bson() const { BSONObjBuilder b; OID o; BSONObjBuilder subBuilder(b.subobjStart("a")); subBuilder.append("$ref", "ns"); subBuilder.append("$id", o); subBuilder.done(); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$ref\" : \"ns\", \"$id\" : { \"$oid\" : \"000000000000000000000000\" " "} } }"; } }; class DBRefObjectIDConstructor : public Base { virtual BSONObj bson() const { BSONObjBuilder b; OID o; BSONObjBuilder subBuilder(b.subobjStart("a")); subBuilder.append("$ref", "ns"); subBuilder.append("$id", o); subBuilder.done(); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$ref\" : \"ns\", \"$id\" : ObjectId( \"000000000000000000000000\" ) " "} }"; } }; class DBRefDbName : public Base { virtual BSONObj bson() const { BSONObjBuilder b; BSONObjBuilder subBuilder(b.subobjStart("a")); subBuilder.append("$ref", "ns"); subBuilder.append("$id", "000000000000000000000000"); subBuilder.append("$db", "dbname"); subBuilder.done(); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$ref\" : \"ns\", \"$id\" : \"000000000000000000000000\"" ", \"$db\" : \"dbname\" } }"; } }; class Oid : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendOID("_id"); return b.obj(); } virtual string json() const { return "{ \"_id\" : { \"$oid\" : \"000000000000000000000000\" } }"; } }; class Oid2 : public Base { virtual BSONObj bson() const { BSONObjBuilder b; char OIDbytes[OID::kOIDSize]; memset(&OIDbytes, 0x0f, OID::kOIDSize); OID o = OID::from(OIDbytes); b.appendOID("_id", &o); return b.obj(); } virtual string json() const { return "{ \"_id\" : ObjectId( \"0f0f0f0f0f0f0f0f0f0f0f0f\" ) }"; } }; class OidTooLong : public Bad { virtual string json() const { return "{ \"_id\" : { \"$oid\" : \"0000000000000000000000000\" } }"; } }; class Oid2TooLong : public Bad { virtual string json() const { return "{ \"_id\" : ObjectId( \"0f0f0f0f0f0f0f0f0f0f0f0f0\" ) }"; } }; class OidTooShort : public Bad { virtual string json() const { return "{ \"_id\" : { \"$oid\" : \"00000000000000000000000\" } }"; } }; class Oid2TooShort : public Bad { virtual string json() const { return "{ \"_id\" : ObjectId( \"0f0f0f0f0f0f0f0f0f0f0f0\" ) }"; } }; class OidInvalidChar : public Bad { virtual string json() const { return "{ \"_id\" : { \"$oid\" : \"00000000000Z000000000000\" } }"; } }; class Oid2InvalidChar : public Bad { virtual string json() const { return "{ \"_id\" : ObjectId( \"0f0f0f0f0f0fZf0f0f0f0f0f\" ) }"; } }; class StringId : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("_id", "000000000000000000000000"); return b.obj(); } virtual string json() const { return "{ \"_id\" : \"000000000000000000000000\" }"; } }; class BinData : public Base { virtual BSONObj bson() const { char z[3]; z[0] = 'a'; z[1] = 'b'; z[2] = 'c'; BSONObjBuilder b; b.appendBinData("a", 3, BinDataGeneral, z); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$binary\" : \"YWJj\", \"$type\" : \"00\" } }"; } }; class BinData1 : public Base { virtual BSONObj bson() const { char z[3]; z[0] = 'a'; z[1] = 'b'; z[2] = 'c'; BSONObjBuilder b; b.appendBinData("a", 3, Function, z); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$binary\" : \"YWJj\", \"$type\" : \"01\" } }"; } }; class BinData2 : public Base { virtual BSONObj bson() const { char z[3]; z[0] = 'a'; z[1] = 'b'; z[2] = 'c'; BSONObjBuilder b; b.appendBinData("a", 3, ByteArrayDeprecated, z); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$binary\" : \"YWJj\", \"$type\" : \"02\" } }"; } }; class BinData3 : public Base { virtual BSONObj bson() const { char z[3]; z[0] = 'a'; z[1] = 'b'; z[2] = 'c'; BSONObjBuilder b; b.appendBinData("a", 3, bdtUUID, z); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$binary\" : \"YWJj\", \"$type\" : \"03\" } }"; } }; class BinData4 : public Base { virtual BSONObj bson() const { char z[3]; z[0] = 'a'; z[1] = 'b'; z[2] = 'c'; BSONObjBuilder b; b.appendBinData("a", 3, newUUID, z); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$binary\" : \"YWJj\", \"$type\" : \"04\" } }"; } }; class BinData5 : public Base { virtual BSONObj bson() const { char z[3]; z[0] = 'a'; z[1] = 'b'; z[2] = 'c'; BSONObjBuilder b; b.appendBinData("a", 3, MD5Type, z); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$binary\" : \"YWJj\", \"$type\" : \"05\" } }"; } }; class BinData80 : public Base { virtual BSONObj bson() const { char z[3]; z[0] = 'a'; z[1] = 'b'; z[2] = 'c'; BSONObjBuilder b; b.appendBinData("a", 3, bdtCustom, z); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$binary\" : \"YWJj\", \"$type\" : \"80\" } }"; } }; class BinDataPaddedSingle : public Base { virtual BSONObj bson() const { char z[2]; z[0] = 'a'; z[1] = 'b'; BSONObjBuilder b; b.appendBinData("a", 2, BinDataGeneral, z); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$binary\" : \"YWI=\", \"$type\" : \"00\" } }"; } }; class BinDataPaddedDouble : public Base { virtual BSONObj bson() const { char z[1]; z[0] = 'a'; BSONObjBuilder b; b.appendBinData("a", 1, BinDataGeneral, z); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$binary\" : \"YQ==\", \"$type\" : \"00\" } }"; } }; class BinDataAllChars : public Base { virtual BSONObj bson() const { unsigned char z[] = {0x00, 0x10, 0x83, 0x10, 0x51, 0x87, 0x20, 0x92, 0x8B, 0x30, 0xD3, 0x8F, 0x41, 0x14, 0x93, 0x51, 0x55, 0x97, 0x61, 0x96, 0x9B, 0x71, 0xD7, 0x9F, 0x82, 0x18, 0xA3, 0x92, 0x59, 0xA7, 0xA2, 0x9A, 0xAB, 0xB2, 0xDB, 0xAF, 0xC3, 0x1C, 0xB3, 0xD3, 0x5D, 0xB7, 0xE3, 0x9E, 0xBB, 0xF3, 0xDF, 0xBF}; BSONObjBuilder b; b.appendBinData("a", 48, BinDataGeneral, z); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$binary\" : " "\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\", \"$type\" : " "\"00\" } }"; } }; class BinDataBadLength : public Bad { virtual string json() const { return "{ \"a\" : { \"$binary\" : \"YQ=\", \"$type\" : \"00\" } }"; } }; class BinDataBadLength1 : public Bad { virtual string json() const { return "{ \"a\" : { \"$binary\" : \"YQ\", \"$type\" : \"00\" } }"; } }; class BinDataBadLength2 : public Bad { virtual string json() const { return "{ \"a\" : { \"$binary\" : \"YQX==\", \"$type\" : \"00\" } }"; } }; class BinDataBadLength3 : public Bad { virtual string json() const { return "{ \"a\" : { \"$binary\" : \"YQX\", \"$type\" : \"00\" } }"; } }; class BinDataBadLength4 : public Bad { virtual string json() const { return "{ \"a\" : { \"$binary\" : \"YQXZ=\", \"$type\" : \"00\" } }"; } }; class BinDataBadLength5 : public Bad { virtual string json() const { return "{ \"a\" : { \"$binary\" : \"YQXZ==\", \"$type\" : \"00\" } }"; } }; class BinDataBadChars : public Bad { virtual string json() const { return "{ \"a\" : { \"$binary\" : \"a...\", \"$type\" : \"00\" } }"; } }; class BinDataTypeTooShort : public Bad { virtual string json() const { return "{ \"a\" : { \"$binary\" : \"AAAA\", \"$type\" : \"0\" } }"; } }; class BinDataTypeTooLong : public Bad { virtual string json() const { return "{ \"a\" : { \"$binary\" : \"AAAA\", \"$type\" : \"000\" } }"; } }; class BinDataTypeBadChars : public Bad { virtual string json() const { return "{ \"a\" : { \"$binary\" : \"AAAA\", \"$type\" : \"ZZ\" } }"; } }; class BinDataEmptyType : public Bad { virtual string json() const { return "{ \"a\" : { \"$binary\" : \"AAAA\", \"$type\" : \"\" } }"; } }; class BinDataNoType : public Bad { virtual string json() const { return "{ \"a\" : { \"$binary\" : \"AAAA\" } }"; } }; class BinDataInvalidType : public Bad { virtual string json() const { return "{ \"a\" : { \"$binary\" : \"AAAA\", \"$type\" : \"100\" } }"; } }; class Date : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendDate("a", Date_t()); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$date\" : 0 } }"; } }; class DateNonzero : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendDate("a", Date_t::fromMillisSinceEpoch(1000000000)); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$date\" : 1000000000 } }"; } }; class DateStrictTooLong : public Bad { virtual string json() const { stringstream ss; ss << "{ \"a\" : { \"$date\" : " << ~(0ULL) << "1" << " } }"; return ss.str(); } }; class DateTooLong : public Bad { virtual string json() const { stringstream ss; ss << "{ \"a\" : Date( " << ~(0ULL) << "1" << " ) }"; return ss.str(); } }; class DateIsString : public Bad { virtual string json() const { stringstream ss; ss << "{ \"a\" : { \"$date\" : \"100\" } }"; return ss.str(); } }; class DateIsString1 : public Bad { virtual string json() const { stringstream ss; ss << "{ \"a\" : Date(\"a\") }"; return ss.str(); } }; class DateIsString2 : public Bad { virtual string json() const { stringstream ss; ss << "{ \"a\" : new Date(\"a\") }"; return ss.str(); } }; class DateIsFloat : public Bad { virtual string json() const { stringstream ss; ss << "{ \"a\" : { \"$date\" : 1.1 } }"; return ss.str(); } }; class DateIsFloat1 : public Bad { virtual string json() const { stringstream ss; ss << "{ \"a\" : Date(1.1) }"; return ss.str(); } }; class DateIsFloat2 : public Bad { virtual string json() const { stringstream ss; ss << "{ \"a\" : new Date(1.1) }"; return ss.str(); } }; class DateIsExponent : public Bad { virtual string json() const { stringstream ss; ss << "{ \"a\" : { \"$date\" : 10e3 } }"; return ss.str(); } }; class DateIsExponent1 : public Bad { virtual string json() const { stringstream ss; ss << "{ \"a\" : Date(10e3) }"; return ss.str(); } }; class DateIsExponent2 : public Bad { virtual string json() const { stringstream ss; ss << "{ \"a\" : new Date(10e3) }"; return ss.str(); } }; /* Need to handle this because jsonString outputs the value of Date_t as unsigned. * See SERVER-8330 and SERVER-8573 */ class DateStrictMaxUnsigned : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendDate("a", Date_t::fromMillisSinceEpoch(-1)); return b.obj(); } virtual string json() const { stringstream ss; ss << "{ \"a\" : { \"$date\" : " << std::numeric_limits::max() << " } }"; return ss.str(); } }; class DateMaxUnsigned : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendDate("a", Date_t::fromMillisSinceEpoch(-1)); return b.obj(); } virtual string json() const { stringstream ss; ss << "{ \"a\" : Date( " << std::numeric_limits::max() << " ) }"; return ss.str(); } }; class DateStrictNegative : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendDate("a", Date_t::fromMillisSinceEpoch(-1)); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$date\" : -1 } }"; } }; class DateNegative : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendDate("a", Date_t::fromMillisSinceEpoch(-1)); return b.obj(); } virtual string json() const { return "{ \"a\" : Date( -1 ) }"; } }; class NumberLongTest : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("a", 20000LL); return b.obj(); } virtual string json() const { return "{ \"a\" : NumberLong( 20000 ) }"; } }; class NumberLongMin : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("a", std::numeric_limits::min()); return b.obj(); } virtual string json() const { std::stringstream ss; ss << "{'a': NumberLong("; ss << std::numeric_limits::min(); ss << ") }"; return ss.str(); } }; class NumberIntTest : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendNumber("a", 20000); return b.obj(); } virtual string json() const { return "{ \"a\" : NumberInt( 20000 ) }"; } }; class NumberLongNeg : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("a", -20000LL); return b.obj(); } virtual string json() const { return "{ \"a\" : NumberLong( -20000 ) }"; } }; class NumberIntNeg : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendNumber("a", -20000); return b.obj(); } virtual string json() const { return "{ \"a\" : NumberInt( -20000 ) }"; } }; class NumberLongBad : public Bad { virtual string json() const { return "{ \"a\" : NumberLong( 'sdf' ) }"; } }; class NumberIntBad : public Bad { virtual string json() const { return "{ \"a\" : NumberInt( 'sdf' ) }"; } }; class JSTimestamp : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("a", Timestamp(20, 5)); return b.obj(); } virtual string json() const { return "{ \"a\" : Timestamp( 20, 5 ) }"; } }; class TimestampNoIncrement : public Bad { virtual string json() const { return "{ \"a\" : Timestamp( 20 ) }"; } }; class TimestampZero : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("a", Timestamp()); return b.obj(); } virtual string json() const { return "{ \"a\" : Timestamp( 0, 0 ) }"; } }; class TimestampNoArgs : public Bad { virtual string json() const { return "{ \"a\" : Timestamp() }"; } }; class TimestampFloatSeconds : public Bad { virtual string json() const { return "{ \"a\" : Timestamp( 20.0, 1 ) }"; } }; class TimestampFloatIncrement : public Bad { virtual string json() const { return "{ \"a\" : Timestamp( 20, 1.0 ) }"; } }; class TimestampNegativeSeconds : public Bad { virtual string json() const { return "{ \"a\" : Timestamp( -20, 5 ) }"; } }; class TimestampNegativeIncrement : public Bad { virtual string json() const { return "{ \"a\" : Timestamp( 20, -5 ) }"; } }; class TimestampInvalidSeconds : public Bad { virtual string json() const { return "{ \"a\" : Timestamp( q, 5 ) }"; } }; class TimestampObject : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("a", Timestamp(20, 5)); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$timestamp\" : { \"t\" : 20 , \"i\" : 5 } } }"; } }; class TimestampObjectInvalidFieldName : public Bad { virtual string json() const { return "{ \"a\" : { \"$timestamp\" : { \"time\" : 20 , \"increment\" : 5 } } }"; } }; class TimestampObjectNoIncrement : public Bad { virtual string json() const { return "{ \"a\" : { \"$timestamp\" : { \"t\" : 20 } } }"; } }; class TimestampObjectNegativeSeconds : public Bad { virtual string json() const { return "{ \"a\" : { \"$timestamp\" : { \"t\" : -20 , \"i\" : 5 } } }"; } }; class TimestampObjectNegativeIncrement : public Bad { virtual string json() const { return "{ \"a\" : { \"$timestamp\" : { \"t\" : 20 , \"i\" : -5 } } }"; } }; class TimestampObjectInvalidSeconds : public Bad { virtual string json() const { return "{ \"a\" : { \"$timestamp\" : { \"t\" : q , \"i\" : 5 } } }"; } }; class TimestampObjectZero : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("a", Timestamp()); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$timestamp\" : { \"t\" : 0, \"i\" : 0} } }"; } }; class TimestampObjectNoArgs : public Bad { virtual string json() const { return "{ \"a\" : { \"$timestamp\" : { } } }"; } }; class TimestampObjectFloatSeconds : public Bad { virtual string json() const { return "{ \"a\" : { \"$timestamp\" : { \"t\" : 1.0, \"i\" : 0} } }"; } }; class TimestampObjectFloatIncrement : public Bad { virtual string json() const { return "{ \"a\" : { \"$timestamp\" : { \"t\" : 20, \"i\" : 1.0} } }"; } }; class Regex : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendRegex("a", "b", "i"); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$regex\" : \"b\", \"$options\" : \"i\" } }"; } }; class RegexNoOptionField : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendRegex("a", "b", ""); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$regex\" : \"b\" } }"; } }; class RegexEscape : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendRegex("a", "\t", "i"); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$regex\" : \"\\t\", \"$options\" : \"i\" } }"; } }; class RegexWithQuotes : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendRegex("a", "\"", ""); return b.obj(); } virtual string json() const { return "{ \"a\" : /\"/ }"; } }; class RegexWithQuotes1 : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendRegex("a", "\"", ""); return b.obj(); } virtual string json() const { return "{ \"a\" : { $regex : \"\\\"\" }}"; } }; class RegexInvalidField : public Bad { virtual string json() const { return "{ \"a\" : { \"$regex\" : \"b\", \"field\" : \"i\" } }"; } }; class RegexInvalidOption : public Bad { virtual string json() const { return "{ \"a\" : { \"$regex\" : \"b\", \"$options\" : \"1\" } }"; } }; class RegexInvalidOption2 : public Bad { virtual string json() const { return "{ \"a\" : /b/c }"; } }; class RegexInvalidOption3 : public Bad { virtual string json() const { return "{ \"a\" : /b/ic }"; } }; class RegexInvalidOption4 : public Bad { virtual string json() const { return "{ \"a\" : { \"$regex\" : \"b\", \"$options\" : \"a\" } }"; } }; class RegexInvalidOption5 : public Bad { virtual string json() const { return "{ \"a\" : /b/a }"; } }; class RegexEmptyOption : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendRegex("a", "b", ""); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$regex\" : \"b\", \"$options\" : \"\" } }"; } }; class RegexEmpty : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendRegex("a", "", ""); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$regex\" : \"\", \"$options\" : \"\"} }"; } }; class RegexEmpty1 : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendRegex("a", "", ""); return b.obj(); } virtual string json() const { return "{ \"a\" : // }"; } }; class RegexOverlap : public Bad { virtual string json() const { return "{ \"a\" : { \"$regex\" : // } }"; } }; class Malformed : public Bad { string json() const { return "{"; } }; class Malformed1 : public Bad { string json() const { return "}"; } }; class Malformed2 : public Bad { string json() const { return "{test}"; } }; class Malformed3 : public Bad { string json() const { return "{test"; } }; class Malformed4 : public Bad { string json() const { return "{ test : 1"; } }; class Malformed5 : public Bad { string json() const { return "{ test : 1 , }"; } }; class Malformed6 : public Bad { string json() const { return "{ test : 1 , tst}"; } }; class Malformed7 : public Bad { string json() const { return "{ a : []"; } }; class Malformed8 : public Bad { string json() const { return "{ a : { test : 1 }"; } }; class Malformed9 : public Bad { string json() const { return "{ a : [ { test : 1]}"; } }; class Malformed10 : public Bad { string json() const { return "{ a : [ { test : 1], b : 2}"; } }; class Malformed11 : public Bad { string json() const { return "{ a : \"test\"string }"; } }; class Malformed12 : public Bad { string json() const { return "{ a : test\"string\" }"; } }; class Malformed13 : public Bad { string json() const { return "{ a\"bad\" : \"teststring\" }"; } }; class Malformed14 : public Bad { string json() const { return "{ \"a\"test : \"teststring\" }"; } }; class Malformed15 : public Bad { string json() const { return "{ \"atest : \"teststring\" }"; } }; class Malformed16 : public Bad { string json() const { return "{ atest\" : \"teststring\" }"; } }; class Malformed17 : public Bad { string json() const { return "{ atest\" : 1 }"; } }; class Malformed18 : public Bad { string json() const { return "{ atest : \"teststring }"; } }; class Malformed19 : public Bad { string json() const { return "{ atest : teststring\" }"; } }; class UnquotedFieldName : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("a_b", 1); return b.obj(); } virtual string json() const { return "{ a_b : 1 }"; } }; class UnquotedFieldNameBad : public Bad { string json() const { return "{ 123 : 1 }"; } }; class UnquotedFieldNameBad1 : public Bad { string json() const { return "{ -123 : 1 }"; } }; class UnquotedFieldNameBad2 : public Bad { string json() const { return "{ .123 : 1 }"; } }; class UnquotedFieldNameBad3 : public Bad { string json() const { return "{ -.123 : 1 }"; } }; class UnquotedFieldNameBad4 : public Bad { string json() const { return "{ -1.23 : 1 }"; } }; class UnquotedFieldNameBad5 : public Bad { string json() const { return "{ 1e23 : 1 }"; } }; class UnquotedFieldNameBad6 : public Bad { string json() const { return "{ -1e23 : 1 }"; } }; class UnquotedFieldNameBad7 : public Bad { string json() const { return "{ -1e-23 : 1 }"; } }; class UnquotedFieldNameBad8 : public Bad { string json() const { return "{ -hello : 1 }"; } }; class UnquotedFieldNameBad9 : public Bad { string json() const { return "{ il.legal : 1 }"; } }; class UnquotedFieldNameBad10 : public Bad { string json() const { return "{ 10gen : 1 }"; } }; class UnquotedFieldNameBad11 : public Bad { string json() const { return "{ _123. : 1 }"; } }; class UnquotedFieldNameBad12 : public Bad { string json() const { return "{ he-llo : 1 }"; } }; class UnquotedFieldNameBad13 : public Bad { string json() const { return "{ bad\nchar : 1 }"; } }; class UnquotedFieldNameBad14 : public Bad { string json() const { return "{ thiswill\fail : 1 }"; } }; class UnquotedFieldNameBad15 : public Bad { string json() const { return "{ failu\re : 1 }"; } }; class UnquotedFieldNameBad16 : public Bad { string json() const { return "{ t\test : 1 }"; } }; class UnquotedFieldNameBad17 : public Bad { string json() const { return "{ \break: 1 }"; } }; class UnquotedFieldNameBad18 : public Bad { string json() const { // here we fill the memory directly to test unicode values // In this case we set \u0700 and \uFF00 // Setting it directly in memory avoids MSVC error c4566 unsigned char u[6]; u[0] = 0xdc; u[1] = 0x80; u[2] = 0xef; u[3] = 0xbc; u[4] = 0x80; u[5] = 0; std::stringstream ss; ss << "{ " << u << " : 1 }"; return ss.str(); } }; class UnquotedFieldNameBad19 : public Bad { string json() const { return "{ bl\\u3333p: 1 }"; } }; class UnquotedFieldNameBad20 : public Bad { string json() const { return "{ bl-33p: 1 }"; } }; class UnquotedFieldNameDollar : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("$a_b", 1); return b.obj(); } virtual string json() const { return "{ $a_b : 1 }"; } }; class SingleQuotes : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("ab'c\"", "bb\b '\""); return b.obj(); } virtual string json() const { return "{ 'ab\\'c\"' : 'bb\\b \\'\"' }"; } }; class QuoteTest : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("\"", "test"); return b.obj(); } virtual string json() const { return "{ '\"' : \"test\" }"; } }; class QuoteTest1 : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("'", "test"); return b.obj(); } virtual string json() const { return "{ \"'\" : \"test\" }"; } }; class QuoteTest2 : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("\"", "test"); return b.obj(); } virtual string json() const { return "{ '\"' : \"test\" }"; } }; class QuoteTest3 : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("\"'\"", "test"); return b.obj(); } virtual string json() const { return "{ '\"\\\'\"' : \"test\" }"; } }; class QuoteTest4 : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("'\"'", "test"); return b.obj(); } virtual string json() const { return "{ \"'\\\"'\" : \"test\" }"; } }; class QuoteTest5 : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("test", "'"); return b.obj(); } virtual string json() const { return "{ \"test\" : \"'\" }"; } }; class QuoteTest6 : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("test", "\""); return b.obj(); } virtual string json() const { return "{ \"test\" : '\"' }"; } }; class ObjectId : public Base { virtual BSONObj bson() const { OID id; id.init("deadbeeff00ddeadbeeff00d"); BSONObjBuilder b; b.appendOID("_id", &id); return b.obj(); } virtual string json() const { return "{ \"_id\": ObjectId( \"deadbeeff00ddeadbeeff00d\" ) }"; } }; class ObjectId2 : public Base { virtual BSONObj bson() const { OID id; id.init("deadbeeff00ddeadbeeff00d"); BSONObjBuilder b; b.appendOID("foo", &id); return b.obj(); } virtual string json() const { return "{ \"foo\": ObjectId( \"deadbeeff00ddeadbeeff00d\" ) }"; } }; class NumericTypes : public Base { public: void run() { Base::run(); BSONObj o = fromjson(json()); ASSERT(o["int"].type() == NumberInt); ASSERT(o["long"].type() == NumberLong); ASSERT(o["double"].type() == NumberDouble); ASSERT(o["long"].numberLong() == 9223372036854775807ll); } virtual BSONObj bson() const { return BSON("int" << 123 << "long" << 9223372036854775807ll // 2**63 - 1 << "double" << 3.14); } virtual string json() const { return "{ \"int\": 123, \"long\": 9223372036854775807, \"double\": 3.14 }"; } }; class NumericTypesJS : public Base { public: void run() { Base::run(); BSONObj o = fromjson(json()); ASSERT(o["int"].type() == NumberInt); ASSERT(o["long"].type() == NumberLong); ASSERT(o["double"].type() == NumberDouble); ASSERT(o["long"].numberLong() == 9223372036854775807ll); } virtual BSONObj bson() const { return BSON("int" << 123 << "long" << 9223372036854775807ll // 2**63 - 1 << "double" << 3.14); } virtual string json() const { return "{ 'int': NumberInt(123), " "'long': NumberLong(9223372036854775807), " "'double': 3.14 }"; } }; class NumericLongMin : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("a", std::numeric_limits::min()); return b.obj(); } virtual string json() const { std::stringstream ss; ss << "{'a': "; ss << std::numeric_limits::min(); ss << " }"; return ss.str(); } }; class NumericIntMin : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendNumber("a", std::numeric_limits::min()); return b.obj(); } virtual string json() const { std::stringstream ss; ss << "{'a': "; ss << std::numeric_limits::min(); ss << " }"; return ss.str(); } }; class NumericLimits : public Base { virtual BSONObj bson() const { BSONObjBuilder builder; BSONArrayBuilder numArray(builder.subarrayStart("")); numArray.append(std::numeric_limits::max()); numArray.append(std::numeric_limits::min()); numArray.append(std::numeric_limits::max()); numArray.append(std::numeric_limits::min()); numArray.done(); return builder.obj(); } virtual string json() const { std::stringstream ss; ss << "{'': ["; ss << std::numeric_limits::max() << ","; ss << std::numeric_limits::min() << ","; ss << std::numeric_limits::max() << ","; ss << std::numeric_limits::min(); ss << "] }"; return ss.str(); } }; // Overflows double by giving it an exponent that is too large class NumericLimitsBad : public Bad { virtual string json() const { std::stringstream ss; ss << "{ test : "; ss << std::numeric_limits::max() << "1111111111"; ss << "}"; return ss.str(); } }; class NumericLimitsBad1 : public Bad { virtual string json() const { std::stringstream ss; ss << "{ test : "; ss << std::numeric_limits::min() << "11111111111"; ss << "}"; return ss.str(); } }; class NegativeNumericTypes : public Base { public: void run() { Base::run(); BSONObj o = fromjson(json()); ASSERT(o["int"].type() == NumberInt); ASSERT(o["long"].type() == NumberLong); ASSERT(o["double"].type() == NumberDouble); ASSERT(o["long"].numberLong() == -9223372036854775807ll); } virtual BSONObj bson() const { return BSON("int" << -123 << "long" << -9223372036854775807ll // -1 * (2**63 - 1) << "double" << -3.14); } virtual string json() const { return "{ \"int\": -123, \"long\": -9223372036854775807, \"double\": -3.14 }"; } }; class EmbeddedDatesBase : public Base { public: virtual void run() { BSONObj o = fromjson(json()); ASSERT_EQUALS(3, (o["time.valid"].type())); BSONObj e = o["time.valid"].embeddedObjectUserCheck(); ASSERT_EQUALS(9, e["$gt"].type()); ASSERT_EQUALS(9, e["$lt"].type()); Base::run(); } BSONObj bson() const { BSONObjBuilder e; e.appendDate("$gt", Date_t::fromMillisSinceEpoch(1257829200000LL)); e.appendDate("$lt", Date_t::fromMillisSinceEpoch(1257829200100LL)); BSONObjBuilder b; b.append("time.valid", e.obj()); return b.obj(); } virtual string json() const = 0; }; struct EmbeddedDatesFormat1 : EmbeddedDatesBase { string json() const { return "{ \"time.valid\" : { $gt : { \"$date\" : 1257829200000 } , $lt : { \"$date\" : " "1257829200100 } } }"; } }; struct EmbeddedDatesFormat2 : EmbeddedDatesBase { string json() const { return "{ \"time.valid\" : { $gt : Date(1257829200000) , $lt : Date( 1257829200100 ) } }"; } }; struct EmbeddedDatesFormat3 : EmbeddedDatesBase { string json() const { return "{ \"time.valid\" : { $gt : new Date(1257829200000) , $lt : new Date( 1257829200100 " ") } }"; } }; class NullString : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.append("x", "a\0b", 4); return b.obj(); } virtual string json() const { return "{ \"x\" : \"a\\u0000b\" }"; } }; class NullFieldUnquoted : public Bad { virtual string json() const { return "{ x\\u0000y : \"a\" }"; } }; class MinKeyAlone : public Bad { virtual string json() const { return "{ \"$minKey\" : 1 }"; } }; class MaxKeyAlone : public Bad { virtual string json() const { return "{ \"$maxKey\" : 1 }"; } }; class MinKey : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendMinKey("a"); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$minKey\" : 1 } }"; } }; class MaxKey : public Base { virtual BSONObj bson() const { BSONObjBuilder b; b.appendMaxKey("a"); return b.obj(); } virtual string json() const { return "{ \"a\" : { \"$maxKey\" : 1 } }"; } }; } // namespace FromJsonTests class All : public Suite { public: All() : Suite("json") {} void setupTests() { add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); // DOCS-2539: We cannot parse dates generated with a Unix timestamp of zero in local // time, since the body of the date may be before the Unix Epoch. This causes parsing // to fail even if the offset would properly adjust the time. For example, // "1969-12-31T19:00:00-05:00" actually represents the Unix timestamp of zero, but we // cannot parse it because the body of the date is before 1970. // add< FromJsonTests::Date >(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); } }; SuiteInstance myall; } // namespace JsonTests