@@ -11,8 +11,8 @@ const { expect } = require('chai');
11
11
const sinon = require ( 'sinon' ) ;
12
12
const { MongoRuntimeError } = require ( '../../src/error' ) ;
13
13
14
- describe ( 'utils' , function ( ) {
15
- context ( 'eachAsync' , function ( ) {
14
+ describe ( 'driver utils' , function ( ) {
15
+ context ( 'eachAsync function ' , function ( ) {
16
16
it ( 'should callback with an error' , function ( done ) {
17
17
eachAsync (
18
18
[ { error : false } , { error : true } ] ,
@@ -43,7 +43,7 @@ describe('utils', function () {
43
43
} ) ;
44
44
} ) ;
45
45
46
- context ( 'makeInterruptibleAsyncInterval' , function ( ) {
46
+ context ( 'makeInterruptibleAsyncInterval function ' , function ( ) {
47
47
before ( function ( ) {
48
48
this . clock = sinon . useFakeTimers ( ) ;
49
49
} ) ;
@@ -170,7 +170,7 @@ describe('utils', function () {
170
170
} ) ;
171
171
} ) ;
172
172
173
- context ( 'BufferPool' , function ( ) {
173
+ context ( 'BufferPool class ' , function ( ) {
174
174
it ( 'should report the correct length' , function ( ) {
175
175
const buffer = new BufferPool ( ) ;
176
176
buffer . append ( Buffer . from ( [ 0 , 1 ] ) ) ;
@@ -257,7 +257,7 @@ describe('utils', function () {
257
257
} ) ;
258
258
} ) ;
259
259
260
- context ( 'executeLegacyOperation' , function ( ) {
260
+ context ( 'executeLegacyOperation function ' , function ( ) {
261
261
it ( 'should call callback with errors on throw errors, and rethrow error' , function ( ) {
262
262
const expectedError = new Error ( 'THIS IS AN ERROR' ) ;
263
263
let callbackError , caughtError ;
@@ -300,7 +300,7 @@ describe('utils', function () {
300
300
} ) ;
301
301
} ) ;
302
302
303
- describe ( 'shuffler function' , ( ) => {
303
+ describe ( 'shuffle function' , ( ) => {
304
304
it ( 'should support iterables' , function ( ) {
305
305
// Kind of an implicit test, we should not throw/crash here.
306
306
const input = new Set ( [ 'a' , 'b' , 'c' ] ) ;
@@ -315,24 +315,43 @@ describe('utils', function () {
315
315
expect ( output ) . to . have . lengthOf ( input . length ) ;
316
316
} ) ;
317
317
318
- it ( 'should give a random subset if limit is less than the input length' , ( ) => {
319
- const input = [ 'a' , 'b' , 'c' , 'd' , 'e' ] ;
320
- const output = shuffle ( input , 3 ) ;
321
- expect ( output ) . to . have . lengthOf ( 3 ) ;
318
+ it ( `should give a random subset of length input.length - 1` , function ( ) {
319
+ const input = [ 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , 'i' ] ;
320
+ const output = shuffle ( input , input . length - 1 ) ;
321
+ expect ( output ) . to . not . deep . equal ( input ) ;
322
+ expect ( output ) . to . have . lengthOf ( input . length - 1 ) ;
322
323
} ) ;
323
324
324
- const input = [ 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , 'i' ] ;
325
- for ( let n = 1 ; n <= input . length ; n ++ ) {
326
- it ( `should give a random subset of length ${ n } ` , function ( ) {
327
- const output = shuffle ( input , n ) ;
328
- if ( n > 2 ) {
329
- // This expectation fails more at n values below 3
330
- // sparing us the flake
331
- expect ( output ) . to . not . deep . equal ( input . slice ( 0 , n ) ) ;
332
- }
333
- expect ( output ) . to . have . lengthOf ( n ) ;
334
- } ) ;
335
- }
325
+ it ( `should give a random subset of length input.length` , function ( ) {
326
+ const input = [ 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , 'i' ] ;
327
+ const output = shuffle ( input , input . length ) ;
328
+ expect ( output ) . to . not . deep . equal ( input ) ;
329
+ expect ( output ) . to . have . lengthOf ( input . length ) ;
330
+ } ) ;
331
+
332
+ it ( `should always return the same element when input is one item` , function ( ) {
333
+ const input = [ 'a' ] ;
334
+ for ( let i = 0 ; i < 10 ; i ++ ) {
335
+ const output = shuffle ( input ) ;
336
+ expect ( output ) . to . deep . equal ( input ) ;
337
+ }
338
+ for ( let i = 0 ; i < 10 ; i ++ ) {
339
+ const output = shuffle ( input , 1 ) ; // and with limit
340
+ expect ( output ) . to . deep . equal ( input ) ;
341
+ }
342
+ } ) ;
343
+
344
+ it ( `should return a different item on every call of limit 1` , function ( ) {
345
+ const input = [ 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , 'i' ] ;
346
+ const outputs = new Set ( ) ;
347
+ for ( let i = 0 ; i < 5 ; i ++ ) {
348
+ const output = shuffle ( input , 1 ) ;
349
+ expect ( output ) . to . have . lengthOf ( 1 ) ;
350
+ outputs . add ( output [ 0 ] ) ;
351
+ }
352
+ // Of the 5 shuffles we got at least 2 unique random items, this is to avoid flakiness
353
+ expect ( outputs . size ) . is . greaterThanOrEqual ( 2 ) ;
354
+ } ) ;
336
355
337
356
it ( 'should give a random shuffling of the entire input when no limit provided' , ( ) => {
338
357
const input = [ 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , 'i' ] ;
@@ -342,8 +361,14 @@ describe('utils', function () {
342
361
expect ( output ) . to . not . deep . equal ( input ) ;
343
362
expect ( output ) . to . have . lengthOf ( input . length ) ;
344
363
} ) ;
364
+ it ( 'should give a random shuffling of the entire input when limit is explicitly set to 0' , ( ) => {
365
+ const input = [ 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , 'i' ] ;
366
+ const output = shuffle ( input , 0 ) ;
367
+ expect ( output ) . to . not . deep . equal ( input ) ;
368
+ expect ( output ) . to . have . lengthOf ( input . length ) ;
369
+ } ) ;
345
370
346
- it ( 'should handle empty array' , function ( ) {
371
+ it ( 'should handle empty array if limit is unspecified or 0 ' , function ( ) {
347
372
expect ( shuffle ( [ ] ) ) . to . deep . equal ( [ ] ) ;
348
373
expect ( shuffle ( [ ] , 0 ) ) . to . deep . equal ( [ ] ) ;
349
374
} ) ;
@@ -355,6 +380,7 @@ describe('utils', function () {
355
380
356
381
it ( 'should throw if limit is greater than zero and empty array' , function ( ) {
357
382
expect ( ( ) => shuffle ( [ ] , 2 ) ) . to . throw ( MongoRuntimeError ) ;
383
+ expect ( ( ) => shuffle ( [ ] , 1 ) ) . to . throw ( MongoRuntimeError ) ;
358
384
} ) ;
359
385
360
386
it ( 'should throw if limit is larger than input size' , ( ) => {
0 commit comments