diff --git a/packages/cli-repl/test/e2e-bson.spec.ts b/packages/cli-repl/test/e2e-bson.spec.ts index 7458a2c20..063f49ece 100644 --- a/packages/cli-repl/test/e2e-bson.spec.ts +++ b/packages/cli-repl/test/e2e-bson.spec.ts @@ -44,7 +44,7 @@ describe('BSON e2e', function() { MaxKey: 'MaxKey()', NumberInt: 'Int32(32)', NumberLong: 'Long("64")', - Timestamp: 'Timestamp(1, 100)', + Timestamp: 'Timestamp({ t: 100, i: 1 })', Symbol: 'abc', Code: 'Code("abc")', NumberDecimal: 'Decimal128("1")', @@ -61,7 +61,7 @@ describe('BSON e2e', function() { DBRef3: new bson.DBRef('a', { x: '5f16b8bebe434dc98cdfc9cb' } as any, 'db'), MinKey: new bson.MinKey(), MaxKey: new bson.MaxKey(), - Timestamp: new bson.Timestamp(1, 100), + Timestamp: new bson.Timestamp(new bson.Long(1, 100)), Symbol: new bson.BSONSymbol('abc'), Code: new bson.Code('abc'), NumberDecimal: new bson.Decimal128('1'), @@ -97,7 +97,7 @@ describe('BSON e2e', function() { MaxKey: new MaxKey(), NumberInt: NumberInt("32"), NumberLong: NumberLong("64"), - Timestamp: new Timestamp(1, 100), + Timestamp: new Timestamp(100, 1), Symbol: new BSONSymbol('abc'), Code: new Code('abc'), NumberDecimal: NumberDecimal('1'), @@ -164,10 +164,10 @@ describe('BSON e2e', function() { shell.assertNoErrors(); }); it('Timestamp prints when returned from the server', async() => { - const value = new bson.Timestamp(0, 100); + const value = new bson.Timestamp(new bson.Long(0, 100)); await shell.executeLine(`use ${dbName}`); await db.collection('test').insertOne({ value: value }); - expect(await shell.executeLine('db.test.findOne().value')).to.include('Timestamp(0, 100)'); + expect(await shell.executeLine('db.test.findOne().value')).to.include('Timestamp({ t: 100, i: 0 })'); shell.assertNoErrors(); }); it('Code prints when returned from the server', async() => { @@ -249,8 +249,13 @@ describe('BSON e2e', function() { expect(await shell.executeLine(value)).to.include('Long("345678654321234561")'); shell.assertNoErrors(); }); - it('Timestamp prints when created by user', async() => { - const value = 'Timestamp(0, 100)'; + it('Timestamp prints when created by user (legacy)', async() => { + const value = 'Timestamp(100, 0)'; + expect(await shell.executeLine(value)).to.include('Timestamp({ t: 100, i: 0 })'); + shell.assertNoErrors(); + }); + it('Timestamp prints when created by user ({t, i})', async() => { + const value = 'Timestamp({ t: 100, i: 0 })'; expect(await shell.executeLine(value)).to.include(value); shell.assertNoErrors(); }); diff --git a/packages/java-shell/src/test/resources/collection/insertOne.js b/packages/java-shell/src/test/resources/collection/insertOne.js index 8d2d535c8..96c868935 100644 --- a/packages/java-shell/src/test/resources/collection/insertOne.js +++ b/packages/java-shell/src/test/resources/collection/insertOne.js @@ -10,7 +10,7 @@ const res = db.coll.insertOne({ date: new Date("2012-12-19"), isoDate: new ISODate("2012-12-19"), numberInt: NumberInt("24"), - timestamp: new Timestamp(0, 100), + timestamp: new Timestamp(100, 0), "undefined": undefined, "null": null, uuid: new UUID('01234567-89ab-cdef-0123-456789abcdef') diff --git a/packages/java-shell/src/test/resources/literal/Timestamp.js b/packages/java-shell/src/test/resources/literal/Timestamp.js index 8b9faea8c..1c50b8e29 100644 --- a/packages/java-shell/src/test/resources/literal/Timestamp.js +++ b/packages/java-shell/src/test/resources/literal/Timestamp.js @@ -1,2 +1,2 @@ // command checkResultClass -new Timestamp(0, 100) \ No newline at end of file +new Timestamp(100, 0) diff --git a/packages/service-provider-core/src/printable-bson.spec.ts b/packages/service-provider-core/src/printable-bson.spec.ts index 68e317726..710c24360 100644 --- a/packages/service-provider-core/src/printable-bson.spec.ts +++ b/packages/service-provider-core/src/printable-bson.spec.ts @@ -44,7 +44,7 @@ describe('BSON printers', function() { }); it('formats Timestamp correctly', function() { - expect(inspect(new bson.Timestamp(1, 100))).to.equal('Timestamp(1, 100)'); + expect(inspect(new bson.Timestamp(new bson.Long(100, 1)))).to.equal('Timestamp({ t: 1, i: 100 })'); }); it('formats Symbol correctly', function() { diff --git a/packages/service-provider-core/src/printable-bson.ts b/packages/service-provider-core/src/printable-bson.ts index 2d9714238..18c893519 100644 --- a/packages/service-provider-core/src/printable-bson.ts +++ b/packages/service-provider-core/src/printable-bson.ts @@ -23,7 +23,7 @@ export const bsonStringifiers: Record { // Make sure that each individual chunk in the output is on a single line expect(inspectedCollectionInfo).to.include('chunks: [\n' + ' { min: { key: MinKey() }, max: { key: MaxKey() }, ' + - `'on shard': '${collectionInfo.chunks[0]['on shard']}', 'last modified': Timestamp(0, 1) }\n` + + `'on shard': '${collectionInfo.chunks[0]['on shard']}', 'last modified': Timestamp({ t: 1, i: 0 }) }\n` + ' ],\n'); }); }); diff --git a/packages/shell-api/src/shell-bson.spec.ts b/packages/shell-api/src/shell-bson.spec.ts index eb41d218d..3401d19d3 100644 --- a/packages/shell-api/src/shell-bson.spec.ts +++ b/packages/shell-api/src/shell-bson.spec.ts @@ -196,8 +196,14 @@ describe('Shell BSON', () => { }); it('constructs with default args 1', () => { const s = shellBson.Timestamp(1); - expect(s.low).to.equal(1); - expect(s.high).to.equal(0); + expect(s.low).to.equal(0); + expect(s.high).to.equal(1); + }); + it('constructs with { t, i } signature', () => { + const s = shellBson.Timestamp({ t: 10, i: 20 }); + expect(s.low).to.equal(20); + expect(s.high).to.equal(10); + expect(s.toExtendedJSON()).to.deep.equal({ $timestamp: { t: 10, i: 20 } }); }); }); describe('Code', () => { diff --git a/packages/shell-api/src/shell-bson.ts b/packages/shell-api/src/shell-bson.ts index e218274e8..266d5f068 100644 --- a/packages/shell-api/src/shell-bson.ts +++ b/packages/shell-api/src/shell-bson.ts @@ -71,9 +71,16 @@ export default function constructShellBson(bson: typeof BSON, printWarning: (msg assertArgsDefinedType([id], [[undefined, 'string', 'number', 'object']], 'ObjectId'); return new bson.ObjectId(id); }, { ...bson.ObjectId, prototype: bson.ObjectId.prototype }), - Timestamp: Object.assign(function Timestamp(low?: number | typeof bson.Long.prototype, high?: number): typeof bson.Timestamp.prototype { - assertArgsDefinedType([low, high], [['number', 'object', undefined], [undefined, 'number']], 'Timestamp'); - return new bson.Timestamp(low as number, high as number); + Timestamp: Object.assign(function Timestamp(t?: number | typeof bson.Long.prototype | { t: number, i: number }, i?: number): typeof bson.Timestamp.prototype { + assertArgsDefinedType([t, i], [['number', 'object', undefined], [undefined, 'number']], 'Timestamp'); + // Order of Timestamp() arguments is reversed in mongo/mongosh and the driver: + // https://jira.mongodb.org/browse/MONGOSH-930 + if (typeof t === 'object' && t !== null && 't' in t && 'i' in t) { + return new bson.Timestamp(new bson.Long(t.i, t.t)); + } else if (i !== undefined || typeof t === 'number') { + return new bson.Timestamp(new bson.Long((i ?? 0) as number, t as number)); + } + return new bson.Timestamp(t as typeof bson.Long.prototype); }, { ...bson.Timestamp, prototype: bson.Timestamp.prototype }), Code: Object.assign(function Code(c: string | Function = '', s?: any): typeof bson.Code.prototype { assertArgsDefinedType([c, s], [[undefined, 'string', 'function'], [undefined, 'object']], 'Code');