Skip to content

Commit 1d09e18

Browse files
committed
fix: shuffle tests round 2 undo srv event saving
1 parent 7879773 commit 1d09e18

File tree

6 files changed

+57
-52
lines changed

6 files changed

+57
-52
lines changed

src/connection_string.ts

+2-5
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,7 @@ function matchesParentDomain(srvAddress: string, parentDomain: string): boolean
6363
* @param uri - The connection string to parse
6464
* @param options - Optional user provided connection string options
6565
*/
66-
export function resolveSRVRecord(
67-
options: MongoOptions,
68-
callback: Callback<{ hosts: HostAddress[]; records: dns.SrvRecord[] }>
69-
): void {
66+
export function resolveSRVRecord(options: MongoOptions, callback: Callback<HostAddress[]>): void {
7067
if (typeof options.srvHost !== 'string') {
7168
return callback(new MongoAPIError('Option "srvHost" must not be empty'));
7269
}
@@ -162,7 +159,7 @@ export function resolveSRVRecord(
162159
}
163160
}
164161

165-
callback(undefined, { hosts: hostAddresses, records: addresses });
162+
callback(undefined, hostAddresses);
166163
});
167164
});
168165
}

src/operations/connect.ts

+4-10
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,8 @@ export function connect(
5050
};
5151

5252
if (typeof options.srvHost === 'string') {
53-
return resolveSRVRecord(options, (err, res) => {
54-
if (err || !res) return callback(err);
55-
56-
const { hosts, records } = res;
53+
return resolveSRVRecord(options, (err, hosts) => {
54+
if (err || !hosts) return callback(err);
5755

5856
const selectedHosts =
5957
options.srvMaxHosts === 0 || options.srvMaxHosts >= hosts.length
@@ -64,11 +62,7 @@ export function connect(
6462
options.hosts[index] = host;
6563
}
6664

67-
return createTopology(
68-
mongoClient,
69-
{ ...options, initialSrvResults: records },
70-
connectCallback
71-
);
65+
return createTopology(mongoClient, options, connectCallback);
7266
});
7367
}
7468

@@ -77,7 +71,7 @@ export function connect(
7771

7872
function createTopology(
7973
mongoClient: MongoClient,
80-
options: MongoOptions & { initialSrvResults?: dns.SrvRecord[] },
74+
options: MongoOptions,
8175
callback: Callback<Topology>
8276
) {
8377
// Create the topology

src/sdam/srv_polling.ts

+1-11
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,6 @@ export interface SrvPollerOptions extends LoggerOptions {
5656
srvMaxHosts: number;
5757
srvHost: string;
5858
heartbeatFrequencyMS: number;
59-
60-
initialSrvResults?: dns.SrvRecord[];
6159
}
6260

6361
/** @internal */
@@ -75,7 +73,6 @@ export class SrvPoller extends TypedEventEmitter<SrvPollerEvents> {
7573
generation: number;
7674
srvMaxHosts: number;
7775
srvServiceName: string;
78-
lastSrvPollingEvent?: SrvPollingEvent;
7976
_timeout?: NodeJS.Timeout;
8077

8178
/** @event */
@@ -93,9 +90,6 @@ export class SrvPoller extends TypedEventEmitter<SrvPollerEvents> {
9390
this.srvServiceName = options.srvServiceName ?? 'mongodb';
9491
this.rescanSrvIntervalMS = options.rescanSrvIntervalMS ?? 60000;
9592
this.heartbeatFrequencyMS = options.heartbeatFrequencyMS ?? 10000;
96-
this.lastSrvPollingEvent = Array.isArray(options.initialSrvResults)
97-
? new SrvPollingEvent(options.initialSrvResults)
98-
: undefined;
9993
this.logger = new Logger('srvPoller', options);
10094

10195
this.haMode = false;
@@ -137,11 +131,7 @@ export class SrvPoller extends TypedEventEmitter<SrvPollerEvents> {
137131
success(srvRecords: dns.SrvRecord[]): void {
138132
this.haMode = false;
139133
this.schedule();
140-
const event = new SrvPollingEvent(srvRecords);
141-
if (!this.lastSrvPollingEvent?.equals(event)) {
142-
this.emit(SrvPoller.SRV_RECORD_DISCOVERY, event);
143-
}
144-
this.lastSrvPollingEvent = event;
134+
this.emit(SrvPoller.SRV_RECORD_DISCOVERY, new SrvPollingEvent(srvRecords));
145135
}
146136

147137
failure(message: string, obj?: NodeJS.ErrnoException): void {

src/sdam/topology.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@ export interface TopologyOptions extends BSONSerializeOptions, ServerOptions {
144144
srvMaxHosts: number;
145145
srvServiceName: string;
146146
rescanSrvIntervalMS: number;
147-
initialSrvResults?: dns.SrvRecord[];
148147
hosts: HostAddress[];
149148
retryWrites: boolean;
150149
retryReads: boolean;
@@ -347,8 +346,7 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
347346
srvHost: options.srvHost,
348347
srvMaxHosts: options.srvMaxHosts,
349348
srvServiceName: options.srvServiceName,
350-
rescanSrvIntervalMS: options.rescanSrvIntervalMS,
351-
initialSrvResults: options.initialSrvResults
349+
rescanSrvIntervalMS: options.rescanSrvIntervalMS
352350
});
353351

354352
this.on(Topology.TOPOLOGY_DESCRIPTION_CHANGED, this.s.detectShardedTopology);

src/utils.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1425,7 +1425,7 @@ export function parsePackageVersion({ version }: { version: string }): {
14251425
*
14261426
* Reference: https://bost.ocks.org/mike/shuffle/
14271427
* @param sequence - items to be shuffled
1428-
* @param limit - the number of ite
1428+
* @param limit - if nonzero shuffle will slice the randomized array e.g, `.slice(0, limit)`
14291429
*/
14301430
export function shuffle<T>(sequence: Iterable<T>, limit = 0): Array<T> {
14311431
const items = Array.from(sequence); // shallow copy in order to never shuffle the input

test/unit/utils.test.js

+48-22
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ const { expect } = require('chai');
1010
const sinon = require('sinon');
1111
const { MongoRuntimeError } = require('../../src/error');
1212

13-
describe('utils', function () {
14-
context('eachAsync', function () {
13+
describe('driver utils', function () {
14+
context('eachAsync function', function () {
1515
it('should callback with an error', function (done) {
1616
eachAsync(
1717
[{ error: false }, { error: true }],
@@ -329,7 +329,7 @@ describe('utils', function () {
329329
});
330330
});
331331

332-
context('BufferPool', function () {
332+
context('BufferPool class', function () {
333333
it('should report the correct length', function () {
334334
const buffer = new BufferPool();
335335
buffer.append(Buffer.from([0, 1]));
@@ -416,7 +416,7 @@ describe('utils', function () {
416416
});
417417
});
418418

419-
context('executeLegacyOperation', function () {
419+
context('executeLegacyOperation function', function () {
420420
it('should call callback with errors on throw errors, and rethrow error', function () {
421421
const expectedError = new Error('THIS IS AN ERROR');
422422
let callbackError, caughtError;
@@ -459,7 +459,7 @@ describe('utils', function () {
459459
});
460460
});
461461

462-
describe('shuffler function', () => {
462+
describe('shuffle function', () => {
463463
it('should support iterables', function () {
464464
// Kind of an implicit test, we should not throw/crash here.
465465
const input = new Set(['a', 'b', 'c']);
@@ -474,24 +474,43 @@ describe('utils', function () {
474474
expect(output).to.have.lengthOf(input.length);
475475
});
476476

477-
it('should give a random subset if limit is less than the input length', () => {
478-
const input = ['a', 'b', 'c', 'd', 'e'];
479-
const output = shuffle(input, 3);
480-
expect(output).to.have.lengthOf(3);
477+
it(`should give a random subset of length input.length - 1`, function () {
478+
const input = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'];
479+
const output = shuffle(input, input.length - 1);
480+
expect(output).to.not.deep.equal(input);
481+
expect(output).to.have.lengthOf(input.length - 1);
481482
});
482483

483-
const input = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'];
484-
for (let n = 1; n <= input.length; n++) {
485-
it(`should give a random subset of length ${n}`, function () {
486-
const output = shuffle(input, n);
487-
if (n > 2) {
488-
// This expectation fails more at n values below 3
489-
// sparing us the flake
490-
expect(output).to.not.deep.equal(input.slice(0, n));
491-
}
492-
expect(output).to.have.lengthOf(n);
493-
});
494-
}
484+
it(`should give a random subset of length input.length`, function () {
485+
const input = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'];
486+
const output = shuffle(input, input.length);
487+
expect(output).to.not.deep.equal(input);
488+
expect(output).to.have.lengthOf(input.length);
489+
});
490+
491+
it(`should always return the same element when input is one item`, function () {
492+
const input = ['a'];
493+
for (let i = 0; i < 10; i++) {
494+
const output = shuffle(input);
495+
expect(output).to.deep.equal(input);
496+
}
497+
for (let i = 0; i < 10; i++) {
498+
const output = shuffle(input, 1); // and with limit
499+
expect(output).to.deep.equal(input);
500+
}
501+
});
502+
503+
it(`should return a different item on every call of limit 1`, function () {
504+
const input = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'];
505+
const outputs = new Set();
506+
for (let i = 0; i < 5; i++) {
507+
const output = shuffle(input, 1);
508+
expect(output).to.have.lengthOf(1);
509+
outputs.add(output[0]);
510+
}
511+
// Of the 5 shuffles we got at least 2 unique random items, this is to avoid flakiness
512+
expect(outputs.size).is.greaterThanOrEqual(2);
513+
});
495514

496515
it('should give a random shuffling of the entire input when no limit provided', () => {
497516
const input = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'];
@@ -501,8 +520,14 @@ describe('utils', function () {
501520
expect(output).to.not.deep.equal(input);
502521
expect(output).to.have.lengthOf(input.length);
503522
});
523+
it('should give a random shuffling of the entire input when limit is explicitly set to 0', () => {
524+
const input = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'];
525+
const output = shuffle(input, 0);
526+
expect(output).to.not.deep.equal(input);
527+
expect(output).to.have.lengthOf(input.length);
528+
});
504529

505-
it('should handle empty array', function () {
530+
it('should handle empty array if limit is unspecified or 0', function () {
506531
expect(shuffle([])).to.deep.equal([]);
507532
expect(shuffle([], 0)).to.deep.equal([]);
508533
});
@@ -514,6 +539,7 @@ describe('utils', function () {
514539

515540
it('should throw if limit is greater than zero and empty array', function () {
516541
expect(() => shuffle([], 2)).to.throw(MongoRuntimeError);
542+
expect(() => shuffle([], 1)).to.throw(MongoRuntimeError);
517543
});
518544

519545
it('should throw if limit is larger than input size', () => {

0 commit comments

Comments
 (0)