11use std:: {
22 collections:: HashMap ,
33 path:: PathBuf ,
4- sync:: { Arc , Mutex } ,
4+ sync:: {
5+ atomic:: { AtomicBool , Ordering } ,
6+ Arc ,
7+ Mutex ,
8+ } ,
59 time:: Duration ,
610} ;
711
12+ #[ cfg( not( feature = "tokio-runtime" ) ) ]
13+ use async_std:: net:: TcpListener ;
814use bson:: {
915 doc,
1016 spec:: { BinarySubtype , ElementType } ,
@@ -16,6 +22,8 @@ use bson::{
1622use futures_util:: TryStreamExt ;
1723use lazy_static:: lazy_static;
1824use mongocrypt:: ctx:: { Algorithm , KmsProvider } ;
25+ #[ cfg( feature = "tokio-runtime" ) ]
26+ use tokio:: net:: TcpListener ;
1927
2028use crate :: {
2129 client:: { auth:: Credential , options:: TlsOptions } ,
@@ -35,6 +43,7 @@ use crate::{
3543 CommandSucceededEvent ,
3644 } ,
3745 options:: { IndexOptions , ReadConcern , WriteConcern } ,
46+ runtime,
3847 test:: { Event , EventHandler , SdamEvent } ,
3948 Client ,
4049 Collection ,
@@ -1313,6 +1322,62 @@ async fn custom_endpoint_kmip_invalid_endpoint() -> Result<()> {
13131322 Ok ( ( ) )
13141323}
13151324
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+
13161381// Prose test 8. Bypass Spawning mongocryptd (Via mongocryptdBypassSpawn)
13171382#[ cfg_attr( feature = "tokio-runtime" , tokio:: test) ]
13181383#[ cfg_attr( feature = "async-std-runtime" , async_std:: test) ]
@@ -2712,3 +2777,65 @@ impl CommandEventHandler for DecryptionEventsHandler {
27122777// TODO RUST-1417: implement prose test 17. On-demand GCP Credentials
27132778
27142779// 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