SERVER-116459: Backfill unittest coverage for tojson (#46122)

GitOrigin-RevId: 110dcc3957a45735654a1e58fb2eca4b39641754
This commit is contained in:
Steve McClure 2026-01-09 13:08:32 -05:00 committed by MongoDB Bot
parent 67d243121c
commit 55d73726a6
3 changed files with 265 additions and 40 deletions

View File

@ -26,13 +26,28 @@ describe("Date shims and polyfills", function () {
});
it("tojson", function () {
let d;
let d, json;
d = new Date(0);
assert.eq(d.tojson(), 'ISODate("1970-01-01T00:00:00Z")');
json = d.tojson();
assert.eq(json, 'ISODate("1970-01-01T00:00:00Z")');
d = new Date(1, 2, 3, 4, 5, 6, 7);
assert.eq(d.tojson(), 'ISODate("1901-03-03T04:05:06.007Z")');
json = d.tojson();
assert.eq(json, 'ISODate("1901-03-03T04:05:06.007Z")');
d = new Date(Date.UTC(1970, 0, 1, 23, 59, 59, 999));
json = d.tojson();
assert.eq(json, 'ISODate("1970-01-01T23:59:59.999Z")');
json = tojson(d);
assert.eq(json, 'ISODate("1970-01-01T23:59:59.999Z")');
json = JSON.stringify(d);
assert.eq(json, '"1970-01-01T23:59:59.999Z"');
json = toJsonForLog(d);
assert.eq(json, '{"$date":"1970-01-01T23:59:59.999+00:00"}');
});
it("tojson on incomplete dates", function () {

View File

@ -1,7 +1,41 @@
import {describe, it} from "jstests/libs/mochalite.js";
import {after, before, describe, it} from "jstests/libs/mochalite.js";
globalThis.TestData ??= {};
describe("Array.tojson", () => {
it("should indent and lint arrays properly", () => {
const arr = ["foo", "bar"];
let json;
json = Array.tojson(arr);
assert.eq(
// this is a bizarre latent bug!
json,
`\
[
undefined "foo",
undefined "bar"
ndefined ]`,
);
json = Array.tojson(arr, "", false);
assert.eq(
json,
`\
[
"foo",
"bar"
]`,
);
json = Array.tojson(arr, "", true);
assert.eq(json, '[ "foo", "bar" ]');
json = Array.tojson(arr, " ", true);
assert.eq(json, '[ "foo", "bar" ]');
});
});
describe("tojson", function () {
it("should indent and lint arrays properly", function () {
const arr = ["foo", "bar"];
@ -97,6 +131,9 @@ BC ]`,
json = tojson(obj, "", true); // explicitly a oneliner
assert.eq(json, '{ "x" : 1, "y" : 2 }');
json = tojson(obj, " ", true); // matches tojsononeline calls
assert.eq(json, '{ "x" : 1, "y" : 2 }');
json = tojson(obj, "", false); // force pretty print
assert.eq(
json,
@ -143,9 +180,11 @@ BC ]`,
assert.eq(json, '{ "x" : [ ], "y" : { } }');
json = tojson(obj, "", true);
jsTest.log.info(json);
assert.eq(json, '{ "x" : [ ], "y" : { } }');
json = tojson(obj, " ", true);
assert.eq(json, '{ "x" : [ ], "y" : { } }');
json = toJsonForLog(obj);
assert.eq(json, '{"x":[],"y":{}}');
@ -160,6 +199,11 @@ BC ]`,
}
}`,
);
let x = {"a": {"x": "foobar"}};
json = tojson(x, " ", true);
assert.eq(json, '{ "a" : { "x" : "foobar" } }');
});
it("deep", function () {
@ -172,6 +216,12 @@ BC ]`,
'{ "x" : [ { "x" : [ 1, 2, [ ] ], "z" : "ok", "y" : [ [ ] ] }, { "foo" : "bar" } ], "y" : null }',
);
json = tojson(obj, " ", true); // matches tojsononeline calls
assert.eq(
json,
'{ "x" : [ { "x" : [ 1, 2, [ ] ], "z" : "ok", "y" : [ [ ] ] }, { "foo" : "bar" } ], "y" : null }',
);
json = toJsonForLog(obj);
assert.eq(json, '{"x":[{"x":[1,2,[]],"z":"ok","y":[[]]},{"foo":"bar"}],"y":null}');
@ -274,6 +324,12 @@ BC ],
ABC "y" : null
BC }`,
);
json = tojson(obj, "ABC", true); // indents should be ignored completely (but aren't!)
assert.eq(
json,
'{ ABC"x" : [ { "x" : [ 1, 2, [ ] ], "z" : "ok", "y" : [ [ ] ] }, { "foo" : "bar" } ], ABC"y" : null BC}',
);
});
});
@ -355,17 +411,6 @@ BC }`,
assert.eq(json, '{"$binary":"VG8gYmUgb3Igbm90IHRvIGJlLi4uIFRoYXQgaXMgdGhlIHF1ZXN0aW9uLg==","$type":"00"}');
});
it("timestamp", function () {
const x = Timestamp(987654321, 0);
let json;
json = JSON.stringify(x);
assert.eq(json, '{"$timestamp":{"t":987654321,"i":0}}');
json = toJsonForLog(x);
assert.eq(json, '{"$timestamp":{"t":987654321,"i":0}}');
});
it("regex", function () {
const x = /^acme/i;
let json;
@ -414,6 +459,9 @@ BC }`,
const x = undefined;
let json;
json = tojson(x);
assert.eq(json, "undefined");
json = JSON.stringify(x);
assert.eq(json, undefined);
@ -425,6 +473,9 @@ BC }`,
const x = MinKey;
let json;
json = tojson(x);
assert.eq(json, '{ "$minKey" : 1 }');
json = JSON.stringify(x);
assert.eq(json, '{"$minKey":1}');
@ -436,6 +487,9 @@ BC }`,
const x = MaxKey;
let json;
json = tojson(x);
assert.eq(json, '{ "$maxKey" : 1 }');
json = JSON.stringify(x);
assert.eq(json, '{"$maxKey":1}');
@ -447,6 +501,9 @@ BC }`,
const x = NumberLong("12345");
let json;
json = tojson(x);
assert.eq(json, "NumberLong(12345)");
json = JSON.stringify(x);
assert.eq(json, '{"$numberLong":"12345"}');
@ -458,6 +515,9 @@ BC }`,
const x = NumberInt(5);
let json;
json = tojson(x);
assert.eq(json, "NumberInt(5)");
json = JSON.stringify(x);
assert.eq(json, "5");
@ -469,23 +529,15 @@ BC }`,
const x = NumberDecimal(3.14);
let json;
json = tojson(x);
assert.eq(json, 'NumberDecimal("3.14000000000000")');
json = JSON.stringify(x);
assert.eq(json, '{"$numberDecimal":"3.14000000000000"}');
json = toJsonForLog(x);
assert.eq(json, '{"$numberDecimal":"3.14000000000000"}');
});
it("date", function () {
const x = new Date(Date.UTC(1970, 0, 1, 23, 59, 59, 999));
let json;
json = JSON.stringify(x);
assert.eq(json, '"1970-01-01T23:59:59.999Z"');
json = toJsonForLog(x);
assert.eq(json, '{"$date":"1970-01-01T23:59:59.999+00:00"}');
});
});
describe("recursive objects", function () {
@ -509,9 +561,45 @@ BC }`,
[2, {y: [3, 4]}],
]);
let json = tojson(x);
assert.eq(
json,
`\
{
"array" : [
1,
"two",
[
3,
false
]
],
"set" : new Set([
1,
"two",
true
]),
"map" : new Map([
[
"one",
1
],
[
2,
{
"y" : [
3,
4
]
}
]
])
}`,
);
assert.docEq(x, eval("(" + tojson(x) + ")"));
let json = toJsonForLog(x);
json = toJsonForLog(x);
assert.eq(
json,
'{"array":[1,"two",[3,false]],"set":{"$set":[1,"two",true]},"map":{"$map":[["one",1],[2,{"y":[3,4]}]]}}',
@ -545,24 +633,24 @@ BC }`,
});
describe("logformat json", function () {
it("should override indent", function () {
const oldLogFormat = TestData.logFormat;
const oldLogFormat = TestData.logFormat;
before(() => {
TestData.logFormat = "json";
});
after(() => {
TestData.logFormat = oldLogFormat;
});
it("should override indent", function () {
const x = {a: 1, b: [2, 3]};
let json = tojson(x, "\t");
TestData.logFormat = oldLogFormat;
assert.eq(json, '{ "a" : 1, "b" : [ 2, 3 ] }');
});
it("should not override if nolint is specified", function () {
const oldLogFormat = TestData.logFormat;
TestData.logFormat = "json";
const x = {a: 1, b: [2, 3]};
let json = tojson(x, "\t", false);
TestData.logFormat = oldLogFormat;
assert.eq(
json,
@ -662,3 +750,112 @@ describe("tojsonObject", () => {
);
});
});
// The "depth" is not really a user-facing value to tune; it is more for tracking internal recursion limits.
// It doesn't help truncate the depth itself, but adjusting the tojson.MAX_DEPTH does.
describe("depth", () => {
const obj = {a: {b: {c: {d: {e: 5}}}}};
let json;
it("does not truncate", () => {
// does not truncate because we still have MAX_DEPTH-2 stacks to go,
// but it does indent an extra 2 levels
json = tojson(obj, "", false, 2);
assert.eq(
json,
`\
{
"a" : {
"b" : {
"c" : {
"d" : {
"e" : 5
}
}
}
}
}`,
);
json = tojson(obj, " ", false, 2);
assert.eq(
json,
`\
{
"a" : {
"b" : {
"c" : {
"d" : {
"e" : 5
}
}
}
}
}`,
);
});
describe("MAX_DEPTH", () => {
const oldDepth = tojson.MAX_DEPTH;
before(() => {
tojson.MAX_DEPTH = 2;
});
after(() => {
tojson.MAX_DEPTH = oldDepth;
});
it("truncates", () => {
json = tojson(obj, "", false);
assert.eq(
json,
`\
{
"a" : {
"b" : {
"c" : [Object]
}
}
}`,
);
json = tojson(obj, " ", false);
assert.eq(
json,
`\
{
"a" : {
"b" : {
"c" : [Object]
}
}
}`,
);
json = tojson(obj, "", false);
assert.eq(
json,
`\
{
"a" : {
"b" : {
"c" : [Object]
}
}
}`,
);
json = tojson(obj, " ", false);
assert.eq(
json,
`\
{
"a" : {
"b" : {
"c" : [Object]
}
}
}`,
);
});
});
});

View File

@ -56,12 +56,25 @@ describe("Timestamp shims and polyfills", function () {
});
it("tojson", function () {
const ts0 = new Timestamp();
assert.eq(ts0.tojson(), "Timestamp(0, 0)");
let ts, json;
const ts = new Timestamp(1, 2);
assert.eq(ts.tojson(), "Timestamp(1, 2)");
assert.eq(toJsonForLog(ts, "", true), '{"$timestamp":{"t":1,"i":2}}');
ts = new Timestamp();
json = ts.tojson();
assert.eq(json, "Timestamp(0, 0)");
ts = new Timestamp(1, 2);
json = ts.tojson();
assert.eq(json, "Timestamp(1, 2)");
json = toJsonForLog(ts, "", true);
assert.eq(json, '{"$timestamp":{"t":1,"i":2}}');
ts = Timestamp(987654321, 0);
json = JSON.stringify(ts);
assert.eq(json, '{"$timestamp":{"t":987654321,"i":0}}');
json = toJsonForLog(ts);
assert.eq(json, '{"$timestamp":{"t":987654321,"i":0}}');
});
it("toStringIncomparable", function () {