@@ -292,6 +292,143 @@ test_index_offset (void)
292292}
293293
294294
295+ static void
296+ test_bulk_edge_case_372 (void )
297+ {
298+ mongoc_client_t * client ;
299+ mongoc_collection_t * collection ;
300+ mongoc_bulk_operation_t * bulk ;
301+ bson_error_t error ;
302+ bson_iter_t iter ;
303+ bson_iter_t citer ;
304+ bson_iter_t child ;
305+ const char * str ;
306+ bson_t * selector ;
307+ bson_t * update ;
308+ bson_t reply ;
309+ bool r ;
310+ int count ;
311+ int vmaj = 0 ;
312+ int vmin = 0 ;
313+ int vmic = 0 ;
314+
315+ client = mongoc_client_new (gTestUri );
316+ assert (client );
317+
318+ collection = get_test_collection (client , "CDRIVER_372" );
319+ assert (collection );
320+
321+ bulk = mongoc_collection_create_bulk_operation (collection , true, NULL );
322+ assert (bulk );
323+
324+ selector = BCON_NEW ("_id" , BCON_INT32 (0 ));
325+ update = BCON_NEW ("$set" , "{" , "a" , BCON_INT32 (0 ), "}" );
326+ mongoc_bulk_operation_update_one (bulk , selector , update , true);
327+ bson_destroy (selector );
328+ bson_destroy (update );
329+
330+ selector = BCON_NEW ("a" , BCON_INT32 (1 ));
331+ update = BCON_NEW ("_id" , BCON_INT32 (1 ));
332+ mongoc_bulk_operation_replace_one (bulk , selector , update , true);
333+ bson_destroy (selector );
334+ bson_destroy (update );
335+
336+ r = mongoc_client_get_server_status (client , NULL , & reply , & error );
337+ if (!r ) fprintf (stderr , "%s\n" , error .message );
338+ assert (r );
339+
340+ if (bson_iter_init_find (& iter , & reply , "version" ) &&
341+ BSON_ITER_HOLDS_UTF8 (& iter ) &&
342+ (str = bson_iter_utf8 (& iter , NULL ))) {
343+ sscanf (str , "%d.%d.%d" , & vmaj , & vmin , & vmic );
344+ }
345+
346+ bson_destroy (& reply );
347+
348+ if (vmaj >=2 || (vmaj == 2 && vmin >= 6 )) {
349+ /* This is just here to make the counts right in all cases. */
350+ selector = BCON_NEW ("_id" , BCON_INT32 (2 ));
351+ update = BCON_NEW ("_id" , BCON_INT32 (2 ));
352+ mongoc_bulk_operation_replace_one (bulk , selector , update , true);
353+ bson_destroy (selector );
354+ bson_destroy (update );
355+ } else {
356+ /* This case is only possible in MongoDB versions before 2.6. */
357+ selector = BCON_NEW ("_id" , BCON_INT32 (3 ));
358+ update = BCON_NEW ("_id" , BCON_INT32 (2 ));
359+ mongoc_bulk_operation_replace_one (bulk , selector , update , true);
360+ bson_destroy (selector );
361+ bson_destroy (update );
362+ }
363+
364+ r = mongoc_bulk_operation_execute (bulk , & reply , & error );
365+ if (!r ) fprintf (stderr , "%s\n" , error .message );
366+ assert (r );
367+
368+ #if 0
369+ printf ("%s\n" , bson_as_json (& reply , NULL ));
370+ #endif
371+
372+ assert (bson_iter_init_find (& iter , & reply , "nMatched" ) &&
373+ BSON_ITER_HOLDS_INT32 (& iter ) &&
374+ (0 == bson_iter_int32 (& iter )));
375+ assert (bson_iter_init_find (& iter , & reply , "nUpserted" ) &&
376+ BSON_ITER_HOLDS_INT32 (& iter ) &&
377+ (3 == bson_iter_int32 (& iter )));
378+ assert (bson_iter_init_find (& iter , & reply , "nInserted" ) &&
379+ BSON_ITER_HOLDS_INT32 (& iter ) &&
380+ (0 == bson_iter_int32 (& iter )));
381+ assert (bson_iter_init_find (& iter , & reply , "nRemoved" ) &&
382+ BSON_ITER_HOLDS_INT32 (& iter ) &&
383+ (0 == bson_iter_int32 (& iter )));
384+
385+ assert (bson_iter_init_find (& iter , & reply , "upserted" ) &&
386+ BSON_ITER_HOLDS_ARRAY (& iter ) &&
387+ bson_iter_recurse (& iter , & citer ));
388+
389+ assert (bson_iter_next (& citer ));
390+ assert (BSON_ITER_HOLDS_DOCUMENT (& citer ));
391+ assert (bson_iter_recurse (& citer , & child ));
392+ assert (bson_iter_find (& child , "_id" ));
393+ assert (BSON_ITER_HOLDS_INT32 (& child ));
394+ assert (0 == bson_iter_int32 (& child ));
395+ assert (bson_iter_recurse (& citer , & child ));
396+ assert (bson_iter_find (& child , "index" ));
397+ assert (BSON_ITER_HOLDS_INT32 (& child ));
398+ assert (0 == bson_iter_int32 (& child ));
399+
400+ assert (bson_iter_next (& citer ));
401+ assert (BSON_ITER_HOLDS_DOCUMENT (& citer ));
402+ assert (bson_iter_recurse (& citer , & child ));
403+ assert (bson_iter_find (& child , "_id" ));
404+ assert (BSON_ITER_HOLDS_INT32 (& child ));
405+ assert (1 == bson_iter_int32 (& child ));
406+ assert (bson_iter_recurse (& citer , & child ));
407+ assert (bson_iter_find (& child , "index" ));
408+ assert (BSON_ITER_HOLDS_INT32 (& child ));
409+ assert (1 == bson_iter_int32 (& child ));
410+
411+ assert (bson_iter_next (& citer ));
412+ assert (BSON_ITER_HOLDS_DOCUMENT (& citer ));
413+ assert (bson_iter_recurse (& citer , & child ));
414+ assert (bson_iter_find (& child , "_id" ));
415+ assert (BSON_ITER_HOLDS_INT32 (& child ));
416+ assert (2 == bson_iter_int32 (& child ));
417+ assert (bson_iter_recurse (& citer , & child ));
418+ assert (bson_iter_find (& child , "index" ));
419+ assert (BSON_ITER_HOLDS_INT32 (& child ));
420+ assert (2 == bson_iter_int32 (& child ));
421+
422+ assert (!bson_iter_next (& citer ));
423+
424+ bson_destroy (& reply );
425+
426+ mongoc_bulk_operation_destroy (bulk );
427+ mongoc_collection_destroy (collection );
428+ mongoc_client_destroy (client );
429+ }
430+
431+
295432void
296433test_bulk_install (TestSuite * suite )
297434{
@@ -300,6 +437,7 @@ test_bulk_install (TestSuite *suite)
300437 TestSuite_Add (suite , "/BulkOperation/basic" , test_bulk );
301438 TestSuite_Add (suite , "/BulkOperation/update_upserted" , test_update_upserted );
302439 TestSuite_Add (suite , "/BulkOperation/index_offset" , test_index_offset );
440+ TestSuite_Add (suite , "/BulkOperation/CDRIVER-372" , test_bulk_edge_case_372 );
303441
304442 atexit (cleanup_globals );
305443}
0 commit comments