Skip to content

Commit

Permalink
added more prose tests
Browse files Browse the repository at this point in the history
  • Loading branch information
aditi-khare-mongoDB committed Sep 5, 2024
1 parent ad151f7 commit 15dc8ee
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 87 deletions.
11 changes: 9 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1141,14 +1141,21 @@ export function matchesParentDomain(address: string, srvHost: string): boolean {
const normalizedSrvHost = srvHost.endsWith('.') ? srvHost.slice(0, srvHost.length - 1) : srvHost;

const allCharacterBeforeFirstDot = /^.*?\./;
const srvIsLessThanThreeParts = srvHost.split('.').length < 3;
// Remove all characters before first dot
// Add leading dot back to string so
// an srvHostDomain = '.trusted.site'
// will not satisfy an addressDomain that endsWith '.fake-trusted.site'
const addressDomain = `.${normalizedAddress.replace(allCharacterBeforeFirstDot, '')}`;
const srvHostDomain = `.${normalizedSrvHost.replace(allCharacterBeforeFirstDot, '')}`;
const srvHostDomain = srvIsLessThanThreeParts
? normalizedSrvHost
: `.${normalizedSrvHost.replace(allCharacterBeforeFirstDot, '')}`;

return addressDomain.endsWith(srvHostDomain);
return (
addressDomain.endsWith(srvHostDomain) &&
(!srvIsLessThanThreeParts ||
normalizedAddress.split('.').length > normalizedSrvHost.split('.').length)
);
}

interface RequestOptions {
Expand Down
1 change: 0 additions & 1 deletion test/integration/change-streams/change_stream.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { strict as assert } from 'assert';
import { expect } from 'chai';
import * as dns from 'dns';
import { on, once } from 'events';
import { gte, lt } from 'semver';
import * as sinon from 'sinon';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import { once } from 'node:events';
import { expect } from 'chai';

import { type ConnectionPoolCreatedEvent, type Db, type MongoClient } from '../../mongodb';
import sinon = require('sinon');
import dns = require('dns');

describe('Connection Pool', function () {
let client: MongoClient;
Expand All @@ -21,52 +19,6 @@ describe('Connection Pool', function () {

describe('Events', function () {
describe('ConnectionPoolCreatedEvent', function () {
describe.only(
'Initial DNS Seedlist Discovery (Prose Tests)',
{ requires: { topology: 'single' } },
() => {
function makeSrvStub() {
sinon.stub(dns.promises, 'resolveSrv').callsFake(async () => {
return [
{
name: 'localhost',
port: 27017,
weight: 0,
priority: 0
}
];
});

sinon.stub(dns.promises, 'resolveTxt').callsFake(async () => {
throw { code: 'ENODATA' };
});
}

afterEach(async function () {
sinon.restore();
});

it('1.1 Driver should not throw error on valid SRV URI with one part', async function () {
// 1. make dns resolution always pass
makeSrvStub();
// 2. assert that creating a MongoClient with the uri 'mongodb+srv:/localhost' does not cause an error
client = this.configuration.newClient('mongodb+srv://localhost', {});
console.log('stubbed srv client', client);
// 3. assert that connecting the client from 2. to the server does not cause an error
//await client.connect();
});

it('1.1 Driver should not throw error on valid SRV URI with two parts', async function () {
// 1. make dns resolution always pass
makeSrvStub();
// 2. assert that creating a MongoClient with the uri 'mongodb+srv://mongodb.localhost' does not cause an error
const client = this.configuration.newClient('mongodb://localhost', {});
console.log('stubbed normal client', client);
// 3. assert that connecting the client to the server does not cause an error
//await client.connect();
});
}
);
context('when no connection pool options are passed in', function () {
let pConnectionPoolCreated: Promise<ConnectionPoolCreatedEvent[]>;
let connectionPoolCreated: ConnectionPoolCreatedEvent;
Expand Down
2 changes: 1 addition & 1 deletion test/integration/crud/bulk.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,7 @@ describe('Bulk', function () {
}
});

it.only(
it(
'should correctly execute ordered batch using w:0',
// TODO(NODE-6060): set `moreToCome` op_msg bit when `w: 0` is specified
{ requires: { mongodb: '<8.0.0' } },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,52 +1,183 @@
import * as dns from 'dns';
import sinon = require('sinon');
// import { expect } from 'chai';

import { type MongoClient } from '../../mongodb';
import { expect } from 'chai';

import { MongoAPIError, Server, ServerDescription, Topology } from '../../mongodb';
import { topologyWithPlaceholderClient } from '../../tools/utils';

describe(
'Initial DNS Seedlist Discovery (Prose Tests)',
{ requires: { topology: 'single' } },
() => {
let client: MongoClient;

function makeSrvStub() {
sinon.stub(dns.promises, 'resolveSrv').callsFake(async () => {
return [
{
name: 'localhost',
port: 27017,
weight: 0,
priority: 0
}
];
context('When running validation on an SRV string before DNS resolution', function () {
beforeEach(async function () {
// this fn stubs DNS resolution to always pass - so we are only checking pre-DNS validation

sinon.stub(dns.promises, 'resolveSrv').callsFake(async () => {
return [
{
name: 'resolved.mongodb.localhost',
port: 27017,
weight: 0,
priority: 0
}
];
});

sinon.stub(dns.promises, 'resolveTxt').callsFake(async () => {
throw { code: 'ENODATA' };
});

sinon.stub(Topology.prototype, 'selectServer').callsFake(async () => {
return new Server(
topologyWithPlaceholderClient([], {} as any),
new ServerDescription('a:1'),
{} as any
);
});
});

sinon.stub(dns.promises, 'resolveTxt').callsFake(async () => {
throw { code: 'ENODATA' };
afterEach(async function () {
sinon.restore();
});
}

afterEach(async function () {
sinon.restore();
});
it('do not error on an SRV because it has one domain level', async function () {
const client = await this.configuration.newClient('mongodb+srv://localhost', {});
client.connect();
client.close();
});

it('1.1 Driver should not throw error on valid SRV URI with one part', async function () {
// 1. make dns resolution always pass
//makeSrvStub();
// 2. assert that creating a MongoClient with the uri 'mongodb+srv:/localhost' does not cause an error
client = this.configuration.newClient('mongodb://localhost', {});
// 3. assert that connecting the client from 2. to the server does not cause an error
await client.connect();
it('do not error on an SRV because it has two domain levels', async function () {
const client = await this.configuration.newClient('mongodb+srv://mongodb.localhost', {});
client.connect();
client.close();
});
});

it('1.1 Driver should not throw error on valid SRV URI with two parts', async function () {
// 1. make dns resolution always pass
makeSrvStub();
// 2. assert that creating a MongoClient with the uri 'mongodb+srv://mongodb.localhost' does not cause an error
//const client = new MongoClient('mongodb+srv://mongodb.localhost', {});
// 3. assert that connecting the client to the server does not cause an error
//await client.connect();
});
context(
'When given a DNS resolution that does NOT end with the original SRVs domain name',
function () {
beforeEach(async function () {
sinon.stub(dns.promises, 'resolveTxt').callsFake(async () => {
throw { code: 'ENODATA' };
});
});

afterEach(async function () {
sinon.restore();
});

it('an SRV with one domain level causes a runtime error', async function () {
sinon.stub(dns.promises, 'resolveSrv').callsFake(async () => {
return [
{
name: 'localhost.mongodb', // this string contains the SRV but does not end with it
port: 27017,
weight: 0,
priority: 0
}
];
});
const err = await this.configuration
.newClient('mongodb+srv://localhost', {})
.connect()
.catch(e => e);
expect(err).to.be.instanceOf(MongoAPIError);
expect(err.message).to.equal('Server record does not share hostname with parent URI');
});

it('an SRV with two domain levels causes a runtime error', async function () {
sinon.stub(dns.promises, 'resolveSrv').callsFake(async () => {
return [
{
name: 'evil.localhost', // this string only ends with part of the domain, not all of it!
port: 27017,
weight: 0,
priority: 0
}
];
});
const err = await this.configuration
.newClient('mongodb+srv://mongodb.localhost', {})
.connect()
.catch(e => e);
expect(err).to.be.instanceOf(MongoAPIError);
expect(err.message).to.equal('Server record does not share hostname with parent URI');
});

it('an SRV with three or more domain levels causes a runtime error', async function () {
sinon.stub(dns.promises, 'resolveSrv').callsFake(async () => {
return [
{
name: 'blogs.evil.co.uk',
port: 27017,
weight: 0,
priority: 0
}
];
});
const err = await this.configuration
.newClient('mongodb+srv://blogs.mongodb.com', {})
.connect()
.catch(e => e);
expect(err).to.be.instanceOf(MongoAPIError);
expect(err.message).to.equal('Server record does not share hostname with parent URI');
});
}
);

context(
'When given a DNS resolution that is identical to the original SRVs hostname',
function () {
beforeEach(async function () {
sinon.stub(dns.promises, 'resolveTxt').callsFake(async () => {
throw { code: 'ENODATA' };
});
});

afterEach(async function () {
sinon.restore();
});

it('an SRV with one domain level causes a runtime error', async function () {
sinon.stub(dns.promises, 'resolveSrv').callsFake(async () => {
return [
{
name: 'localhost', // this string contains the SRV but does not end with it
port: 27017,
weight: 0,
priority: 0
}
];
});
const err = await this.configuration
.newClient('mongodb+srv://localhost', {})
.connect()
.catch(e => e);
expect(err).to.be.instanceOf(MongoAPIError);
expect(err.message).to.equal('Server record does not share hostname with parent URI');
});

it('an SRV with two domain levels causes a runtime error', async function () {
sinon.stub(dns.promises, 'resolveSrv').callsFake(async () => {
return [
{
name: 'mongodb.localhost', // this string only ends with part of the domain, not all of it!
port: 27017,
weight: 0,
priority: 0
}
];
});
const err = await this.configuration
.newClient('mongodb+srv://mongodb.localhost', {})
.connect()
.catch(e => e);
expect(err).to.be.instanceOf(MongoAPIError);
expect(err.message).to.equal('Server record does not share hostname with parent URI');
});
}
);
}
);

0 comments on commit 15dc8ee

Please sign in to comment.