1
1
use std:: {
2
2
collections:: HashMap ,
3
3
path:: PathBuf ,
4
- sync:: { Arc , Mutex } ,
4
+ sync:: {
5
+ atomic:: { AtomicBool , Ordering } ,
6
+ Arc ,
7
+ Mutex ,
8
+ } ,
5
9
time:: Duration ,
6
10
} ;
7
11
12
+ #[ cfg( not( feature = "tokio-runtime" ) ) ]
13
+ use async_std:: net:: TcpListener ;
8
14
use bson:: {
9
15
doc,
10
16
spec:: { BinarySubtype , ElementType } ,
@@ -16,6 +22,8 @@ use bson::{
16
22
use futures_util:: TryStreamExt ;
17
23
use lazy_static:: lazy_static;
18
24
use mongocrypt:: ctx:: { Algorithm , KmsProvider } ;
25
+ #[ cfg( feature = "tokio-runtime" ) ]
26
+ use tokio:: net:: TcpListener ;
19
27
20
28
use crate :: {
21
29
client:: { auth:: Credential , options:: TlsOptions } ,
@@ -35,6 +43,7 @@ use crate::{
35
43
CommandSucceededEvent ,
36
44
} ,
37
45
options:: { IndexOptions , ReadConcern , WriteConcern } ,
46
+ runtime,
38
47
test:: { Event , EventHandler , SdamEvent } ,
39
48
Client ,
40
49
Collection ,
@@ -1313,6 +1322,62 @@ async fn custom_endpoint_kmip_invalid_endpoint() -> Result<()> {
1313
1322
Ok ( ( ) )
1314
1323
}
1315
1324
1325
+ // Prose test 8. Bypass Spawning mongocryptd (Via loading shared library)
1326
+ #[ cfg_attr( feature = "tokio-runtime" , tokio:: test) ]
1327
+ #[ cfg_attr( feature = "async-std-runtime" , async_std:: test) ]
1328
+ async fn bypass_mongocryptd_via_shared_library ( ) -> Result < ( ) > {
1329
+ if !check_env ( "bypass_mongocryptd_via_shared_library" , false ) {
1330
+ return Ok ( ( ) ) ;
1331
+ }
1332
+ let _guard = LOCK . run_exclusively ( ) . await ;
1333
+
1334
+ if * DISABLE_CRYPT_SHARED {
1335
+ log_uncaptured (
1336
+ "Skipping bypass mongocryptd via shared library test: crypt_shared is disabled." ,
1337
+ ) ;
1338
+ return Ok ( ( ) ) ;
1339
+ }
1340
+
1341
+ // Setup: encrypted client.
1342
+ let client_encrypted = Client :: encrypted_builder (
1343
+ CLIENT_OPTIONS . get ( ) . await . clone ( ) ,
1344
+ KV_NAMESPACE . clone ( ) ,
1345
+ LOCAL_KMS . clone ( ) ,
1346
+ ) ?
1347
+ . schema_map ( {
1348
+ [ (
1349
+ "db.coll" . to_string ( ) ,
1350
+ load_testdata ( "external-schema.json" ) ?,
1351
+ ) ]
1352
+ . into_iter ( )
1353
+ . collect :: < HashMap < String , Document > > ( )
1354
+ } )
1355
+ . extra_options ( doc ! {
1356
+ "mongocryptdURI" : "mongodb://localhost:27021/db?serverSelectionTimeoutMS=1000" ,
1357
+ "mongocryptdSpawnArgs" : [ "--pidfilepath=bypass-spawning-mongocryptd.pid" , "--port=27021" ] ,
1358
+ "cryptSharedLibPath" : EXTRA_OPTIONS . get( "cryptSharedLibPath" ) . unwrap( ) ,
1359
+ "cryptSharedRequired" : true ,
1360
+ } )
1361
+ . build ( )
1362
+ . await ?;
1363
+
1364
+ // Test: insert succeeds.
1365
+ client_encrypted
1366
+ . database ( "db" )
1367
+ . collection :: < Document > ( "coll" )
1368
+ . insert_one ( doc ! { "unencrypted" : "test" } , None )
1369
+ . await ?;
1370
+ // Test: mongocryptd not spawned.
1371
+ assert ! ( !client_encrypted. mongocryptd_spawned( ) . await ) ;
1372
+ // Test: attempting to connect fails.
1373
+ let client =
1374
+ Client :: with_uri_str ( "mongodb://localhost:27021/?serverSelectionTimeoutMS=1000" ) . await ?;
1375
+ let result = client. list_database_names ( None , None ) . await ;
1376
+ assert ! ( result. unwrap_err( ) . is_server_selection_error( ) ) ;
1377
+
1378
+ Ok ( ( ) )
1379
+ }
1380
+
1316
1381
// Prose test 8. Bypass Spawning mongocryptd (Via mongocryptdBypassSpawn)
1317
1382
#[ cfg_attr( feature = "tokio-runtime" , tokio:: test) ]
1318
1383
#[ cfg_attr( feature = "async-std-runtime" , async_std:: test) ]
@@ -2712,3 +2777,65 @@ impl CommandEventHandler for DecryptionEventsHandler {
2712
2777
// TODO RUST-1417: implement prose test 17. On-demand GCP Credentials
2713
2778
2714
2779
// TODO RUST-1442: implement prose test 18. Azure IMDS Credentials
2780
+
2781
+ // TODO RUST-1442: implement prose test 19. Azure IMDS Credentials Integration Test
2782
+
2783
+ // Prose test 20. Bypass creating mongocryptd client when shared library is loaded
2784
+ #[ cfg_attr( feature = "tokio-runtime" , tokio:: test) ]
2785
+ #[ cfg_attr( feature = "async-std-runtime" , async_std:: test) ]
2786
+ async fn bypass_mongocryptd_client ( ) -> Result < ( ) > {
2787
+ if !check_env ( "bypass_mongocryptd_client" , false ) {
2788
+ return Ok ( ( ) ) ;
2789
+ }
2790
+ let _guard = LOCK . run_exclusively ( ) . await ;
2791
+
2792
+ if * DISABLE_CRYPT_SHARED {
2793
+ log_uncaptured ( "Skipping bypass mongocryptd client test: crypt_shared is disabled." ) ;
2794
+ return Ok ( ( ) ) ;
2795
+ }
2796
+
2797
+ let connected = Arc :: new ( AtomicBool :: new ( false ) ) ;
2798
+ {
2799
+ let connected = Arc :: clone ( & connected) ;
2800
+ let listener = bind ( "127.0.0.1:27021" ) . await ?;
2801
+ runtime:: spawn ( async move {
2802
+ let _ = listener. accept ( ) . await ;
2803
+ log_uncaptured ( "test failure: connection accepted" ) ;
2804
+ connected. store ( true , Ordering :: SeqCst ) ;
2805
+ } )
2806
+ } ;
2807
+
2808
+ let client_encrypted = Client :: encrypted_builder (
2809
+ CLIENT_OPTIONS . get ( ) . await . clone ( ) ,
2810
+ KV_NAMESPACE . clone ( ) ,
2811
+ LOCAL_KMS . clone ( ) ,
2812
+ ) ?
2813
+ . extra_options ( {
2814
+ let mut extra_options = EXTRA_OPTIONS . clone ( ) ;
2815
+ extra_options. insert ( "mongocryptdURI" , "mongodb://localhost:27021" ) ;
2816
+ extra_options
2817
+ } )
2818
+ . build ( )
2819
+ . await ?;
2820
+ client_encrypted
2821
+ . database ( "db" )
2822
+ . collection :: < Document > ( "coll" )
2823
+ . insert_one ( doc ! { "unencrypted" : "test" } , None )
2824
+ . await ?;
2825
+
2826
+ assert ! ( !client_encrypted. has_mongocryptd_client( ) . await ) ;
2827
+ assert ! ( !connected. load( Ordering :: SeqCst ) ) ;
2828
+
2829
+ Ok ( ( ) )
2830
+ }
2831
+
2832
+ async fn bind ( addr : & str ) -> Result < TcpListener > {
2833
+ #[ cfg( feature = "tokio-runtime" ) ]
2834
+ {
2835
+ Ok ( TcpListener :: bind ( addr. parse :: < std:: net:: SocketAddr > ( ) ?) . await ?)
2836
+ }
2837
+ #[ cfg( not( feature = "tokio-runtime" ) ) ]
2838
+ {
2839
+ Ok ( TcpListener :: bind ( addr) . await ?)
2840
+ }
2841
+ }
0 commit comments