1
1
import { expect } from 'chai' ;
2
2
import { on , once } from 'events' ;
3
+ import { gte } from 'semver' ;
4
+ import * as sinon from 'sinon' ;
3
5
4
6
import {
5
7
type Collection ,
6
8
type CommandStartedEvent ,
9
+ type CommandSucceededEvent ,
7
10
type Db ,
8
11
LEGACY_HELLO_COMMAND ,
9
- MongoClient
12
+ MongoClient ,
13
+ OpMsgRequest
10
14
} from '../../mongodb' ;
11
15
import * as mock from '../../tools/mongodb-mock/index' ;
12
16
import { filterForCommands } from '../shared' ;
13
17
14
- describe . only ( 'Write Concern' , function ( ) {
18
+ describe ( 'Write Concern' , function ( ) {
15
19
context ( 'when the WriteConcern is set in the uri' , function ( ) {
16
20
let client ;
17
21
const events : CommandStartedEvent [ ] = [ ] ;
@@ -29,8 +33,7 @@ describe.only('Write Concern', function () {
29
33
expect ( events [ 0 ] ) . to . containSubset ( {
30
34
commandName : 'insert' ,
31
35
command : {
32
- writeConcern : { w : 0 } ,
33
- moreToCome : true
36
+ writeConcern : { w : 0 }
34
37
}
35
38
} ) ;
36
39
} ) ;
@@ -169,4 +172,136 @@ describe.only('Write Concern', function () {
169
172
} ) ;
170
173
} ) ;
171
174
} ) ;
175
+
176
+ describe ( 'fire-and-forget protocol' , function ( ) {
177
+ context ( 'when writeConcern = 0 and OP_MSG is used' , function ( ) {
178
+ const writeOperations : { name : string ; command : any ; expectedReturnVal : any } [ ] = [
179
+ {
180
+ name : 'insertOne' ,
181
+ command : client => client . db ( 'test' ) . collection ( 'test' ) . insertOne ( { a : 1 } ) ,
182
+ expectedReturnVal : { acknowledged : false }
183
+ } ,
184
+ {
185
+ name : 'insertMany' ,
186
+ command : client =>
187
+ client
188
+ . db ( 'test' )
189
+ . collection ( 'test' )
190
+ . insertMany ( [ { a : 1 } , { b : 2 } ] ) ,
191
+ expectedReturnVal : { acknowledged : false }
192
+ } ,
193
+ {
194
+ name : 'updateOne' ,
195
+ command : client =>
196
+ client
197
+ . db ( 'test' )
198
+ . collection ( 'test' )
199
+ . updateOne ( { i : 128 } , { $set : { c : 2 } } ) ,
200
+ expectedReturnVal : { acknowledged : false }
201
+ } ,
202
+ {
203
+ name : 'updateMany' ,
204
+ command : client =>
205
+ client
206
+ . db ( 'test' )
207
+ . collection ( 'test' )
208
+ . updateMany ( { name : 'foobar' } , { $set : { name : 'fizzbuzz' } } ) ,
209
+ expectedReturnVal : { acknowledged : false }
210
+ } ,
211
+ {
212
+ name : 'deleteOne' ,
213
+ command : client => client . db ( 'test' ) . collection ( 'test' ) . deleteOne ( { a : 1 } ) ,
214
+ expectedReturnVal : { acknowledged : false }
215
+ } ,
216
+ {
217
+ name : 'deleteMany' ,
218
+ command : client => client . db ( 'test' ) . collection ( 'test' ) . deleteMany ( { name : 'foobar' } ) ,
219
+ expectedReturnVal : { acknowledged : false }
220
+ } ,
221
+ {
222
+ name : 'replaceOne' ,
223
+ command : client => client . db ( 'test' ) . collection ( 'test' ) . replaceOne ( { a : 1 } , { b : 2 } ) ,
224
+ expectedReturnVal : { acknowledged : false }
225
+ } ,
226
+ {
227
+ name : 'removeUser' ,
228
+ command : client => client . db ( 'test' ) . removeUser ( 'albert' ) ,
229
+ expectedReturnVal : true
230
+ } ,
231
+ {
232
+ name : 'findAndModify' ,
233
+ command : client =>
234
+ client
235
+ . db ( 'test' )
236
+ . collection ( 'test' )
237
+ . findOneAndUpdate ( { } , { $setOnInsert : { a : 1 } } , { upsert : true } ) ,
238
+ expectedReturnVal : null
239
+ } ,
240
+ {
241
+ name : 'dropDatabase' ,
242
+ command : client => client . db ( 'test' ) . dropDatabase ( ) ,
243
+ expectedReturnVal : true
244
+ } ,
245
+ {
246
+ name : 'dropCollection' ,
247
+ command : client => client . db ( 'test' ) . dropCollection ( 'test' ) ,
248
+ expectedReturnVal : true
249
+ } ,
250
+ {
251
+ name : 'dropIndexes' ,
252
+ command : client => client . db ( 'test' ) . collection ( 'test' ) . dropIndex ( 'a' ) ,
253
+ expectedReturnVal : { ok : 1 }
254
+ } ,
255
+ {
256
+ name : 'createIndexes' ,
257
+ command : client => client . db ( 'test' ) . collection ( 'test' ) . createIndex ( { a : 1 } ) ,
258
+ expectedReturnVal : 'a_1'
259
+ } ,
260
+ {
261
+ name : 'createCollection' ,
262
+ command : client => client . db ( 'test' ) . createCollection ( 'test' ) ,
263
+ expectedReturnVal : { }
264
+ }
265
+ ] ;
266
+
267
+ for ( const op of writeOperations ) {
268
+ context ( `when the write operation ${ op . name } is run` , function ( ) {
269
+ let client ;
270
+ let spy ;
271
+
272
+ beforeEach ( async function ( ) {
273
+ if ( gte ( '3.6.0' , this . configuration . version ) ) {
274
+ this . currentTest . skipReason = 'Test requires OP_MSG, needs to be on MongoDB 3.6+' ;
275
+ this . skip ( ) ;
276
+ }
277
+ spy = sinon . spy ( OpMsgRequest . prototype , 'toBin' ) ;
278
+ client = this . configuration . newClient ( { monitorCommands : true , w : 0 } ) ;
279
+ await client . connect ( ) ;
280
+ } ) ;
281
+
282
+ afterEach ( function ( ) {
283
+ sinon . restore ( ) ;
284
+ client . close ( ) ;
285
+ } ) ;
286
+
287
+ it ( 'the request should have moreToCome bit set' , async function ( ) {
288
+ await op . command ( client ) ;
289
+ expect ( spy . returnValues [ spy . returnValues . length - 1 ] [ 0 ] [ 16 ] ) . to . equal ( 2 ) ;
290
+ } ) ;
291
+
292
+ it ( 'the return value of the command should be nullish' , async function ( ) {
293
+ const result = await op . command ( client ) ;
294
+ expect ( result ) . to . containSubset ( op . expectedReturnVal ) ;
295
+ } ) ;
296
+
297
+ it ( 'commandSucceededEvent should have reply with only {ok: 1}' , async function ( ) {
298
+ const events : CommandSucceededEvent [ ] = [ ] ;
299
+ client . on ( 'commandSucceeded' , event => events . push ( event ) ) ;
300
+ await op . command ( client ) ;
301
+ expect ( events [ 0 ] ) . to . containSubset ( { reply : { ok : 1 } } ) ;
302
+ } ) ;
303
+ } ) ;
304
+ }
305
+ } ) ;
306
+ } ) ;
172
307
} ) ;
0 commit comments