@@ -10,8 +10,8 @@ const { expect } = require('chai');
1010const sinon = require ( 'sinon' ) ;
1111const { 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