Skip to content

test(NODE-3719): reorganize spec tests and remove unneeded skips #486

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions test/node/bson_corpus.prose.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
'use strict';

const BSON = require('../register-bson');
const BSONRegExp = BSON.BSONRegExp;

describe('BSON Corpus Prose Tests', function () {
/**
* The BSON spec uses null-terminated strings to represent document field names and
* regex components (i.e. pattern and flags/options). Drivers MUST assert that null
* bytes are prohibited in the following contexts when encoding BSON (i.e. creating
* raw BSON bytes or constructing BSON-specific type classes):
* - Field name within a root document
* - Field name within a sub-document
* - Pattern for a regular expression
* - Flags/options for a regular expression
* Depending on how drivers implement BSON encoding, they MAY expect an error when
* constructing a type class (e.g. BSON Document or Regex class) or when encoding a
* language representation to BSON (e.g. converting a dictionary, which might allow
* null bytes in its keys, to raw BSON bytes).
*/
describe('1. Prohibit null bytes in null-terminated strings when encoding BSON', () => {
it('Field name within a root document', () => {
expect(() => BSON.serialize({ 'a\x00b': 1 })).to.throw(/null bytes/);
});

it('Field name within a sub-document', () => {
expect(() => BSON.serialize({ a: { 'a\x00b': 1 } })).to.throw(/null bytes/);
});

it('Pattern for a regular expression', () => {
// eslint-disable-next-line no-control-regex
expect(() => BSON.serialize({ a: new RegExp('a\x00b') })).to.throw(/null bytes/);
expect(() => BSON.serialize({ a: new BSONRegExp('a\x00b') })).to.throw(/null bytes/);
});

it('Flags/options for a regular expression', () => {
expect(() => BSON.serialize({ a: new BSONRegExp('a', 'i\x00m') })).to.throw(/null bytes/);

// eslint-disable-next-line no-invalid-regexp
expect(() => new RegExp('a', 'i\x00m')).to.throw(SyntaxError);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -108,40 +108,29 @@ const parseErrorForRootDocument = scenario => {
}
};

const skipBSON = {
'NaN with payload':
'passing this would require building a custom type to store the NaN payload data.'
};
// tests from the corpus that we need to skip, and explanations why
const skipExtendedJSON = {
'Timestamp with high-order bit set on both seconds and increment':
'Current BSON implementation of timestamp/long cannot hold these values - 1 too large.',
'Timestamp with high-order bit set on both seconds and increment (not UINT32_MAX)':
'Current BSON implementation of timestamp/long cannot hold these values - 1 too large.'
};

const SKIP_TESTS = new Map([
...Object.entries(skipBSON),
...Object.entries(skipExtendedJSON),
[
'All BSON types',
'there is just too much variation in the specified expectation to make this work'
]
]);

const corpus = require('./tools/bson_corpus_test_loader');
describe('BSON Corpus', function () {
for (const scenario of corpus) {
const deprecated = scenario.deprecated;
const description = scenario.description;
const valid = scenario.valid || [];
const scenarioName = `${description} (${scenario._filename})`;
const valid = scenario.valid;

describe(description, function () {
describe(scenarioName, function () {
if (valid) {
describe('valid-bson', function () {
for (const v of valid) {
it(v.description, function () {
if (SKIP_TESTS.has(v.description)) {
if (v.description === 'NaN with payload') {
// TODO(NODE-3630): remove custom float parser so we can handle the NaN payload data
this.skip();
}

if (
v.description === 'All BSON types' &&
scenario._filename === 'multi-type-deprecated'
) {
// TODO(NODE-3987): fix multi-type-deprecated test
this.skip();
}

Expand Down Expand Up @@ -181,9 +170,6 @@ describe('BSON Corpus', function () {
describe('valid-extjson', function () {
for (const v of valid) {
it(v.description, function () {
if (SKIP_TESTS.has(v.description)) {
this.skip();
}
// read in test case data. if this scenario is for a deprecated
// type, we want to use the "converted" BSON and EJSON, which
// use the upgraded version of the deprecated type. otherwise,
Expand Down Expand Up @@ -230,6 +216,7 @@ describe('BSON Corpus', function () {
expect(nativeToREJSON(nativeFromCB)).to.equal(rEJ);

// relaxed EJSON -> native -> relaxed EJSON unchanged
// TODO(NODE-3396): jsonToNative doesn't correctly parse the relaxed form
expect(nativeToREJSON(jsonToNative(rEJ))).to.equal(rEJ);
}
});
Expand All @@ -242,7 +229,7 @@ describe('BSON Corpus', function () {
for (const d of scenario.decodeErrors) {
it(d.description, function () {
const B = Buffer.from(d.bson, 'hex');
expect(() => BSON.deserialize(B, deserializeOptions)).to.throw();
expect(() => BSON.deserialize(B, deserializeOptions)).to.throw(BSONError);
});
}
});
Expand Down
34 changes: 0 additions & 34 deletions test/node/bson_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1986,38 +1986,4 @@ describe('BSON', function () {
expect(inspect(timestamp)).to.equal('new Timestamp({ t: 100, i: 1 })');
});
});

/**
* The BSON spec uses null-terminated strings to represent document field names and
* regex components (i.e. pattern and flags/options). Drivers MUST assert that null
* bytes are prohibited in the following contexts when encoding BSON (i.e. creating
* raw BSON bytes or constructing BSON-specific type classes):
* - Field name within a root document
* - Field name within a sub-document
* - Pattern for a regular expression
* - Flags/options for a regular expression
* Depending on how drivers implement BSON encoding, they MAY expect an error when
* constructing a type class (e.g. BSON Document or Regex class) or when encoding a
* language representation to BSON (e.g. converting a dictionary, which might allow
* null bytes in its keys, to raw BSON bytes).
*/
describe('null byte handling during serializing', () => {
it('should throw when null byte in BSON Field name within a root document', () => {
expect(() => BSON.serialize({ 'a\x00b': 1 })).to.throw(/null bytes/);
});

it('should throw when null byte in BSON Field name within a sub-document', () => {
expect(() => BSON.serialize({ a: { 'a\x00b': 1 } })).to.throw(/null bytes/);
});

it('should throw when null byte in Pattern for a regular expression', () => {
// eslint-disable-next-line no-control-regex
expect(() => BSON.serialize({ a: new RegExp('a\x00b') })).to.throw(/null bytes/);
expect(() => BSON.serialize({ a: new BSONRegExp('a\x00b') })).to.throw(/null bytes/);
});

it('should throw when null byte in Flags/options for a regular expression', () => {
expect(() => BSON.serialize({ a: new BSONRegExp('a', 'i\x00m') })).to.throw(/null bytes/);
});
});
});
Loading