@@ -2,12 +2,22 @@ use std::time::Duration;
2
2
3
3
use futures:: stream:: StreamExt ;
4
4
use lazy_static:: lazy_static;
5
+ use semver:: VersionReq ;
5
6
6
7
use crate :: {
7
8
bson:: { doc, Bson , Document } ,
8
- error:: ErrorKind ,
9
+ error:: { ErrorKind , Result } ,
9
10
event:: command:: CommandStartedEvent ,
10
- options:: { AggregateOptions , FindOptions , InsertManyOptions , UpdateOptions } ,
11
+ options:: {
12
+ AggregateOptions ,
13
+ DeleteOptions ,
14
+ FindOneAndDeleteOptions ,
15
+ FindOptions ,
16
+ Hint ,
17
+ InsertManyOptions ,
18
+ UpdateOptions ,
19
+ } ,
20
+ results:: DeleteResult ,
11
21
test:: {
12
22
util:: { drop_collection, CommandEvent , EventClient , TestClient } ,
13
23
LOCK ,
@@ -515,23 +525,11 @@ async fn allow_disk_use_test(options: FindOptions, expected_value: Option<bool>)
515
525
. collection ( function_name ! ( ) ) ;
516
526
coll. find ( None , options) . await . unwrap ( ) ;
517
527
518
- let events = event_client. command_events . read ( ) . unwrap ( ) ;
519
- let mut iter = events. iter ( ) . filter ( |event| match event {
520
- CommandEvent :: CommandStartedEvent ( CommandStartedEvent { command_name, .. } ) => {
521
- command_name == "find"
522
- }
523
- _ => false ,
524
- } ) ;
528
+ let events = event_client. get_command_started_events ( "find" ) ;
529
+ assert_eq ! ( events. len( ) , 1 ) ;
525
530
526
- let event = iter. next ( ) . unwrap ( ) ;
527
- let allow_disk_use = match event {
528
- CommandEvent :: CommandStartedEvent ( CommandStartedEvent { command, .. } ) => {
529
- command. get_bool ( "allowDiskUse" ) . ok ( )
530
- }
531
- _ => None ,
532
- } ;
531
+ let allow_disk_use = events[ 0 ] . command . get_bool ( "allowDiskUse" ) . ok ( ) ;
533
532
assert_eq ! ( allow_disk_use, expected_value) ;
534
- assert_eq ! ( iter. count( ) , 0 ) ;
535
533
}
536
534
537
535
#[ cfg_attr( feature = "tokio-runtime" , tokio:: test) ]
@@ -545,3 +543,120 @@ async fn ns_not_found_suppression() {
545
543
coll. drop ( None ) . await . expect ( "drop should not fail" ) ;
546
544
coll. drop ( None ) . await . expect ( "drop should not fail" ) ;
547
545
}
546
+
547
+ async fn delete_hint_test ( options : Option < DeleteOptions > , name : & str ) {
548
+ let _guard = LOCK . run_concurrently ( ) . await ;
549
+
550
+ let client = EventClient :: new ( ) . await ;
551
+ let coll = client. database ( name) . collection ( name) ;
552
+ let _: Result < DeleteResult > = coll. delete_many ( doc ! { } , options. clone ( ) ) . await ;
553
+
554
+ let events = client. get_command_started_events ( "delete" ) ;
555
+ assert_eq ! ( events. len( ) , 1 ) ;
556
+
557
+ let event_hint = events[ 0 ] . command . get ( "hint" ) . cloned ( ) ;
558
+ let expected_hint = match options {
559
+ Some ( options) => options. hint . map ( |hint| hint. to_bson ( ) ) ,
560
+ None => None ,
561
+ } ;
562
+ assert_eq ! ( event_hint, expected_hint) ;
563
+ }
564
+
565
+ #[ cfg_attr( feature = "tokio-runtime" , tokio:: test) ]
566
+ #[ cfg_attr( feature = "async-std-runtime" , async_std:: test) ]
567
+ #[ function_name:: named]
568
+ async fn delete_hint_keys_specified ( ) {
569
+ let options = DeleteOptions :: builder ( ) . hint ( Hint :: Keys ( doc ! { } ) ) . build ( ) ;
570
+ delete_hint_test ( Some ( options) , function_name ! ( ) ) . await ;
571
+ }
572
+
573
+ #[ cfg_attr( feature = "tokio-runtime" , tokio:: test) ]
574
+ #[ cfg_attr( feature = "async-std-runtime" , async_std:: test) ]
575
+ #[ function_name:: named]
576
+ async fn delete_hint_string_specified ( ) {
577
+ let options = DeleteOptions :: builder ( )
578
+ . hint ( Hint :: Name ( String :: new ( ) ) )
579
+ . build ( ) ;
580
+ delete_hint_test ( Some ( options) , function_name ! ( ) ) . await ;
581
+ }
582
+
583
+ #[ cfg_attr( feature = "tokio-runtime" , tokio:: test) ]
584
+ #[ cfg_attr( feature = "async-std-runtime" , async_std:: test) ]
585
+ #[ function_name:: named]
586
+ async fn delete_hint_not_specified ( ) {
587
+ delete_hint_test ( None , function_name ! ( ) ) . await ;
588
+ }
589
+
590
+ async fn find_one_and_delete_hint_test ( options : Option < FindOneAndDeleteOptions > , name : & str ) {
591
+ let _guard = LOCK . run_concurrently ( ) . await ;
592
+ let client = EventClient :: new ( ) . await ;
593
+
594
+ let req = VersionReq :: parse ( "< 4.2" ) . unwrap ( ) ;
595
+ if options. is_some ( ) && req. matches ( & client. server_version ) {
596
+ return ;
597
+ }
598
+
599
+ let coll = client. database ( name) . collection ( name) ;
600
+ let _: Result < Option < Document > > = coll. find_one_and_delete ( doc ! { } , options. clone ( ) ) . await ;
601
+
602
+ let events = client. get_command_started_events ( "findAndModify" ) ;
603
+ assert_eq ! ( events. len( ) , 1 ) ;
604
+
605
+ let event_hint = events[ 0 ] . command . get ( "hint" ) . cloned ( ) ;
606
+ let expected_hint = options. and_then ( |options| options. hint . map ( |hint| hint. to_bson ( ) ) ) ;
607
+ assert_eq ! ( event_hint, expected_hint) ;
608
+ }
609
+
610
+ #[ cfg_attr( feature = "tokio-runtime" , tokio:: test) ]
611
+ #[ cfg_attr( feature = "async-std-runtime" , async_std:: test) ]
612
+ #[ function_name:: named]
613
+ async fn find_one_and_delete_hint_keys_specified ( ) {
614
+ let options = FindOneAndDeleteOptions :: builder ( )
615
+ . hint ( Hint :: Keys ( doc ! { } ) )
616
+ . build ( ) ;
617
+ find_one_and_delete_hint_test ( Some ( options) , function_name ! ( ) ) . await ;
618
+ }
619
+
620
+ #[ cfg_attr( feature = "tokio-runtime" , tokio:: test) ]
621
+ #[ cfg_attr( feature = "async-std-runtime" , async_std:: test) ]
622
+ #[ function_name:: named]
623
+ async fn find_one_and_delete_hint_string_specified ( ) {
624
+ let options = FindOneAndDeleteOptions :: builder ( )
625
+ . hint ( Hint :: Name ( String :: new ( ) ) )
626
+ . build ( ) ;
627
+ find_one_and_delete_hint_test ( Some ( options) , function_name ! ( ) ) . await ;
628
+ }
629
+
630
+ #[ cfg_attr( feature = "tokio-runtime" , tokio:: test) ]
631
+ #[ cfg_attr( feature = "async-std-runtime" , async_std:: test) ]
632
+ #[ function_name:: named]
633
+ async fn find_one_and_delete_hint_not_specified ( ) {
634
+ find_one_and_delete_hint_test ( None , function_name ! ( ) ) . await ;
635
+ }
636
+
637
+ #[ cfg_attr( feature = "tokio-runtime" , tokio:: test) ]
638
+ #[ cfg_attr( feature = "async-std-runtime" , async_std:: test) ]
639
+ #[ function_name:: named]
640
+ async fn find_one_and_delete_hint_server_version ( ) {
641
+ let _guard = LOCK . run_concurrently ( ) . await ;
642
+
643
+ let client = EventClient :: new ( ) . await ;
644
+ let coll = client. database ( function_name ! ( ) ) . collection ( "coll" ) ;
645
+
646
+ let options = FindOneAndDeleteOptions :: builder ( )
647
+ . hint ( Hint :: Name ( String :: new ( ) ) )
648
+ . build ( ) ;
649
+ let res = coll. find_one_and_delete ( doc ! { } , options) . await ;
650
+
651
+ let req1 = VersionReq :: parse ( "< 4.2" ) . unwrap ( ) ;
652
+ let req2 = VersionReq :: parse ( "4.2.*" ) . unwrap ( ) ;
653
+ if req1. matches ( & client. server_version ) {
654
+ let error = res. expect_err ( "find one and delete should fail" ) ;
655
+ assert ! ( matches!( error. kind. as_ref( ) , ErrorKind :: OperationError { .. } ) ) ;
656
+ } else if req2. matches ( & client. server_version ) {
657
+ let error = res. expect_err ( "find one and delete should fail" ) ;
658
+ assert ! ( matches!( error. kind. as_ref( ) , ErrorKind :: CommandError { .. } ) ) ;
659
+ } else {
660
+ assert ! ( res. is_ok( ) ) ;
661
+ }
662
+ }
0 commit comments