From b0ce232af0e99356e508d265dc1d79f3e9f91721 Mon Sep 17 00:00:00 2001 From: aditi-khare-mongoDB Date: Tue, 26 Jul 2022 11:49:46 -0400 Subject: [PATCH 1/8] added tests --- src/parser/deserializer.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/parser/deserializer.ts b/src/parser/deserializer.ts index bd306c95..c7f7d527 100644 --- a/src/parser/deserializer.ts +++ b/src/parser/deserializer.ts @@ -35,6 +35,8 @@ export interface DeserializeOptions { promoteBuffers?: boolean; /** when deserializing will promote BSON values to their Node.js closest equivalent types. */ promoteValues?: boolean; + /** when deserializing will return UUID type */ + promoteUUIDs?: boolean; /** allow to specify if there what fields we wish to return as unserialized raw buffer. */ fieldsAsRaw?: Document; /** return BSON regular expressions as BSONRegExp instances. */ @@ -135,6 +137,7 @@ function deserializeObject( const promoteBuffers = options['promoteBuffers'] == null ? false : options['promoteBuffers']; const promoteLongs = options['promoteLongs'] == null ? true : options['promoteLongs']; const promoteValues = options['promoteValues'] == null ? true : options['promoteValues']; + const promoteUUIDs = options['promoteUUIDs'] == null ? false : options['promoteUUIDs']; // Ensures default validation option if none given const validation = options.validation == null ? { utf8: true } : options.validation; @@ -413,7 +416,9 @@ function deserializeObject( throw new BSONError('Binary type with subtype 0x02 contains too short binary size'); } - if (promoteBuffers && promoteValues) { + if (promoteUUIDs && subType === 4) { + value = new Binary(buffer.slice(index, index + binarySize), subType).toUUID(); + } else if (promoteBuffers && promoteValues) { value = buffer.slice(index, index + binarySize); } else { value = new Binary(buffer.slice(index, index + binarySize), subType); @@ -440,7 +445,9 @@ function deserializeObject( _buffer[i] = buffer[index + i]; } - if (promoteBuffers && promoteValues) { + if (promoteUUIDs && subType === 4) { + value = new Binary(_buffer, subType).toUUID(); + } else if (promoteBuffers && promoteValues) { value = _buffer; } else { value = new Binary(_buffer, subType); From 2d398ac8e5821b894ab68f440b53936405cdeecb Mon Sep 17 00:00:00 2001 From: aditi-khare-mongoDB Date: Tue, 26 Jul 2022 16:42:13 -0400 Subject: [PATCH 2/8] added promoteBuffers tests and PR review changes --- src/parser/deserializer.ts | 4 ++-- test/node/uuid_tests.js | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/parser/deserializer.ts b/src/parser/deserializer.ts index c7f7d527..3f103616 100644 --- a/src/parser/deserializer.ts +++ b/src/parser/deserializer.ts @@ -35,7 +35,7 @@ export interface DeserializeOptions { promoteBuffers?: boolean; /** when deserializing will promote BSON values to their Node.js closest equivalent types. */ promoteValues?: boolean; - /** when deserializing will return UUID type */ + /** when deserializing will return UUID type, if promoteBuffers is also true then promoteUUIDs will take precedence and a buffer will not be returned */ promoteUUIDs?: boolean; /** allow to specify if there what fields we wish to return as unserialized raw buffer. */ fieldsAsRaw?: Document; @@ -137,7 +137,7 @@ function deserializeObject( const promoteBuffers = options['promoteBuffers'] == null ? false : options['promoteBuffers']; const promoteLongs = options['promoteLongs'] == null ? true : options['promoteLongs']; const promoteValues = options['promoteValues'] == null ? true : options['promoteValues']; - const promoteUUIDs = options['promoteUUIDs'] == null ? false : options['promoteUUIDs']; + const promoteUUIDs = options.promoteUUIDs == null ? false : options.promoteUUIDs; // Ensures default validation option if none given const validation = options.validation == null ? { utf8: true } : options.validation; diff --git a/test/node/uuid_tests.js b/test/node/uuid_tests.js index f48360d8..e81c87e0 100644 --- a/test/node/uuid_tests.js +++ b/test/node/uuid_tests.js @@ -190,5 +190,24 @@ describe('UUID', () => { const plainUUIDSerialization = BSON.serialize({ uuid: exampleUUID }); expect(plainUUIDSerialization).to.deep.equal(toBinarySerialization); }); + + describe('promoteBuffers', () => { + const promoteUUIDValues = [true, false, undefined]; + const promoteBufferValues = [true, false, undefined]; + + const testCases = promoteUUIDValues.flatMap(promoteUUIDs => + promoteBufferValues.flatMap(promoteBuffers => ({ + options: { promoteUUIDs, promoteBuffers }, + outcome: promoteUUIDs ? 'UUID' : promoteBuffers ? undefined : 'Binary' + })) + ); + + for (const { options, outcome } of testCases) { + it(`should deserialize to ${outcome} type when promoteUUIDs is ${options.promoteUUIDs} and promoteBuffers is ${options.promoteBuffers}`, () => { + const { uuid } = BSON.deserialize(serializedUUID, options); + expect(uuid._bsontype).to.equal(outcome); + }); + } + }); }); }); From d1fda7ff30a8603e6bf50d2cc282e7cf3191cb13 Mon Sep 17 00:00:00 2001 From: aditi-khare-mongoDB Date: Tue, 26 Jul 2022 17:13:55 -0400 Subject: [PATCH 3/8] Added comment about buffer being undefined: --- test/node/uuid_tests.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/node/uuid_tests.js b/test/node/uuid_tests.js index e81c87e0..dd18f2f2 100644 --- a/test/node/uuid_tests.js +++ b/test/node/uuid_tests.js @@ -198,6 +198,7 @@ describe('UUID', () => { const testCases = promoteUUIDValues.flatMap(promoteUUIDs => promoteBufferValues.flatMap(promoteBuffers => ({ options: { promoteUUIDs, promoteBuffers }, + // promoteBuffers: true returns a Buffer so _bsontype does not exist outcome: promoteUUIDs ? 'UUID' : promoteBuffers ? undefined : 'Binary' })) ); From e3f2ad0fa1988a025265f7d672585ce8d4e6781f Mon Sep 17 00:00:00 2001 From: aditi-khare-mongoDB Date: Tue, 2 Aug 2022 11:13:30 -0400 Subject: [PATCH 4/8] removed tests for rebase, will add back in later --- test/node/uuid_tests.js | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/test/node/uuid_tests.js b/test/node/uuid_tests.js index dd18f2f2..f48360d8 100644 --- a/test/node/uuid_tests.js +++ b/test/node/uuid_tests.js @@ -190,25 +190,5 @@ describe('UUID', () => { const plainUUIDSerialization = BSON.serialize({ uuid: exampleUUID }); expect(plainUUIDSerialization).to.deep.equal(toBinarySerialization); }); - - describe('promoteBuffers', () => { - const promoteUUIDValues = [true, false, undefined]; - const promoteBufferValues = [true, false, undefined]; - - const testCases = promoteUUIDValues.flatMap(promoteUUIDs => - promoteBufferValues.flatMap(promoteBuffers => ({ - options: { promoteUUIDs, promoteBuffers }, - // promoteBuffers: true returns a Buffer so _bsontype does not exist - outcome: promoteUUIDs ? 'UUID' : promoteBuffers ? undefined : 'Binary' - })) - ); - - for (const { options, outcome } of testCases) { - it(`should deserialize to ${outcome} type when promoteUUIDs is ${options.promoteUUIDs} and promoteBuffers is ${options.promoteBuffers}`, () => { - const { uuid } = BSON.deserialize(serializedUUID, options); - expect(uuid._bsontype).to.equal(outcome); - }); - } - }); }); }); From 7860f24103ae7bd5d4c7be02e7de5dd9f1163736 Mon Sep 17 00:00:00 2001 From: aditi-khare-mongoDB Date: Tue, 2 Aug 2022 11:15:54 -0400 Subject: [PATCH 5/8] rebase help --- test/node/uuid_tests.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/node/uuid_tests.js b/test/node/uuid_tests.js index f48360d8..0b8585f2 100644 --- a/test/node/uuid_tests.js +++ b/test/node/uuid_tests.js @@ -1,3 +1,5 @@ + + 'use strict'; const { Buffer } = require('buffer'); From d68a097b33276e8b95eadb5bf1215c6eeb6e269e Mon Sep 17 00:00:00 2001 From: aditi-khare-mongoDB Date: Tue, 2 Aug 2022 11:37:28 -0400 Subject: [PATCH 6/8] readded tests --- test/node/uuid_tests.js | 61 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/test/node/uuid_tests.js b/test/node/uuid_tests.js index 0b8585f2..0e035059 100644 --- a/test/node/uuid_tests.js +++ b/test/node/uuid_tests.js @@ -193,4 +193,65 @@ describe('UUID', () => { expect(plainUUIDSerialization).to.deep.equal(toBinarySerialization); }); }); + + describe('deserialize', () => { + const originalUUID = new BSON.UUID(); + const binaryUUID = originalUUID.toBinary(); + const serializedUUID = BSON.serialize({ uuid: originalUUID.toBinary() }); + + it('should promoteUUIDs when flag is true', () => { + const { uuid: promotedUUID } = BSON.deserialize(serializedUUID, { promoteUUIDs: true }); + expect(promotedUUID._bsontype).to.equal('UUID'); + expect(promotedUUID).to.deep.equal(originalUUID); + }); + + it('should not promoteUUIDs when flag is false', () => { + const { uuid: unpromotedUUID } = BSON.deserialize(serializedUUID, { promoteUUIDs: false }); + expect(unpromotedUUID._bsontype).to.equal('Binary'); + expect(unpromotedUUID).to.deep.equal(binaryUUID); + }); + + it('should not promoteUUIDs when flag is omitted', () => { + const { uuid: omittedFlagUUID } = BSON.deserialize(serializedUUID); + expect(omittedFlagUUID._bsontype).to.equal('Binary'); + expect(omittedFlagUUID).to.deep.equal(binaryUUID); + }); + + it('should throw BSONTypeError if _bsontype is not UUID and promoteUUIDs is true', () => { + const binaryVar = new Binary(Buffer.from('abc')); + const serializedBinary = BSON.serialize(binaryVar); + expect(() => { + BSON.deserialize(serializedBinary, { promoteUUIDs: true }); + }).to.throw(BSONTypeError); + }); + + describe('promoteBuffers', () => { + const promoteUUIDValues = [true, false, undefined]; + const promoteBufferValues = [true, false, undefined]; + + const testCases = promoteUUIDValues.flatMap(promoteUUIDs => + promoteBufferValues.flatMap(promoteBuffers => ({ + options: { promoteUUIDs, promoteBuffers }, + // promoteBuffers: true returns a Buffer so _bsontype does not exist + outcome: promoteUUIDs ? 'UUID' : promoteBuffers ? undefined : 'Binary' + })) + ); + + for (const { options, outcome } of testCases) { + it(`should deserialize to ${outcome} type when promoteUUIDs is ${options.promoteUUIDs} and promoteBuffers is ${options.promoteBuffers}`, () => { + const { uuid } = BSON.deserialize(serializedUUID, options); + expect(uuid._bsontype).to.equal(outcome); + if (uuid._bsontype === 'UUID') { + expect(uuid.id).to.deep.equal(originalUUID.id); + } else if (uuid._bsontype === 'Binary') { + expect(uuid.buffer).to.deep.equal(originalUUID.id); + } else if (uuid._bsontype === undefined) { + expect(uuid).to.deep.equal(originalUUID.id); + } else { + expect.fail('Unexpected _bsontype'); + } + }); + } + }); + }); }); From 8c8a4292449bba37bf9a5287c81fb7b379e1c416 Mon Sep 17 00:00:00 2001 From: aditi-khare-mongoDB Date: Tue, 2 Aug 2022 11:50:39 -0400 Subject: [PATCH 7/8] flatMap devDependencies install --- package-lock.json | 49 +++++++++++++++++++++++++++++++++++++++++ package.json | 1 + test/node/uuid_tests.js | 2 -- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index c7cfd9d8..55a0ef03 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "@typescript-eslint/eslint-plugin": "^5.30.0", "@typescript-eslint/parser": "^5.30.0", "array-includes": "^3.1.3", + "array.prototype.flatmap": "^1.3.0", "benchmark": "^2.1.4", "chai": "^4.2.0", "eslint": "^8.18.0", @@ -2614,6 +2615,24 @@ "node": ">=8" } }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz", + "integrity": "sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.2", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -3914,6 +3933,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + } + }, "node_modules/es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", @@ -11233,6 +11261,18 @@ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, + "array.prototype.flatmap": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz", + "integrity": "sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.2", + "es-shim-unscopables": "^1.0.0" + } + }, "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -12248,6 +12288,15 @@ "unbox-primitive": "^1.0.2" } }, + "es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, "es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", diff --git a/package.json b/package.json index a070c00b..669f4063 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "@typescript-eslint/eslint-plugin": "^5.30.0", "@typescript-eslint/parser": "^5.30.0", "array-includes": "^3.1.3", + "array.prototype.flatmap": "^1.3.0", "benchmark": "^2.1.4", "chai": "^4.2.0", "eslint": "^8.18.0", diff --git a/test/node/uuid_tests.js b/test/node/uuid_tests.js index 0e035059..07ebba69 100644 --- a/test/node/uuid_tests.js +++ b/test/node/uuid_tests.js @@ -1,5 +1,3 @@ - - 'use strict'; const { Buffer } = require('buffer'); From acd4867df596689eda1856fac650664030d9e1b8 Mon Sep 17 00:00:00 2001 From: aditi-khare-mongoDB Date: Tue, 2 Aug 2022 14:27:17 -0400 Subject: [PATCH 8/8] flatMap fix and BSONTypeError test case fix --- test/node/uuid_tests.js | 4 ++-- test/register-bson.js | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/test/node/uuid_tests.js b/test/node/uuid_tests.js index 07ebba69..c35177c8 100644 --- a/test/node/uuid_tests.js +++ b/test/node/uuid_tests.js @@ -216,8 +216,8 @@ describe('UUID', () => { }); it('should throw BSONTypeError if _bsontype is not UUID and promoteUUIDs is true', () => { - const binaryVar = new Binary(Buffer.from('abc')); - const serializedBinary = BSON.serialize(binaryVar); + const binaryVar = new Binary(Buffer.from('abc'), BSON_BINARY_SUBTYPE_UUID_NEW); + const serializedBinary = BSON.serialize({ d: binaryVar }); expect(() => { BSON.deserialize(serializedBinary, { promoteUUIDs: true }); }).to.throw(BSONTypeError); diff --git a/test/register-bson.js b/test/register-bson.js index a8240154..712641f1 100644 --- a/test/register-bson.js +++ b/test/register-bson.js @@ -10,6 +10,7 @@ require('chai/register-expect'); require('array-includes/auto'); require('object.entries/auto'); +require('array.prototype.flatmap/auto'); const BSON = require('../lib/bson'); const { ensureBuffer } = require('../lib/ensure_buffer');