@@ -852,6 +852,121 @@ test_transaction_recovery_token_cleared (void *ctx)
852
852
mongoc_client_destroy (client );
853
853
}
854
854
855
+ static void
856
+ test_selected_server_is_pinned_to_mongos (void * ctx )
857
+ {
858
+ mongoc_uri_t * uri = NULL ;
859
+ mongoc_client_t * client = NULL ;
860
+ mongoc_set_t * servers = NULL ;
861
+ mongoc_transaction_opt_t * txn_opts = NULL ;
862
+ mongoc_session_opt_t * session_opts = NULL ;
863
+ mongoc_client_session_t * session = NULL ;
864
+ mongoc_server_stream_t * server_stream = NULL ;
865
+ bson_error_t error ;
866
+ bson_t reply ;
867
+ bson_t * insert_opts = NULL ;
868
+ mongoc_database_t * db = NULL ;
869
+ mongoc_collection_t * coll = NULL ;
870
+ bool r ;
871
+ uint32_t expected_id ;
872
+ uint32_t actual_id ;
873
+ mongoc_server_description_t * sd = NULL ;
874
+ int i ;
875
+
876
+ uri = test_framework_get_uri ();
877
+ ASSERT_OR_PRINT (
878
+ mongoc_uri_upsert_host_and_port (uri , "localhost:27018" , & error ), error );
879
+
880
+ client = mongoc_client_new_from_uri (uri );
881
+ BSON_ASSERT (client );
882
+
883
+ txn_opts = mongoc_transaction_opts_new ();
884
+ session_opts = mongoc_session_opts_new ();
885
+
886
+ session = mongoc_client_start_session (client , session_opts , & error );
887
+ ASSERT_OR_PRINT (session , error );
888
+
889
+ /* set the server id to an arbitrary value */
890
+ _mongoc_client_session_pin (session , 42 );
891
+ BSON_ASSERT (42 == mongoc_client_session_get_server_id (session ));
892
+
893
+ /* starting a transaction should clear the server id */
894
+ r = mongoc_client_session_start_transaction (session , txn_opts , & error );
895
+ ASSERT_OR_PRINT (r , error );
896
+ BSON_ASSERT (0 == mongoc_client_session_get_server_id (session ));
897
+
898
+ expected_id = mongoc_topology_select_server_id (
899
+ client -> topology , MONGOC_SS_WRITE , NULL , & error );
900
+ ASSERT_OR_PRINT (expected_id , error );
901
+
902
+ /* session should still be unpinned */
903
+ BSON_ASSERT (0 == mongoc_client_session_get_server_id (session ));
904
+
905
+ /* should pin to the expected server id */
906
+ server_stream = mongoc_cluster_stream_for_server (
907
+ & client -> cluster , expected_id , true, session , NULL , & error );
908
+ ASSERT_OR_PRINT (server_stream , error );
909
+ ASSERT_CMPINT32 (
910
+ expected_id , = = , mongoc_client_session_get_server_id (session ));
911
+
912
+ db = mongoc_client_get_database (client , "db" );
913
+ coll = mongoc_database_create_collection (db , "coll" , NULL , & error );
914
+
915
+ insert_opts = bson_new ();
916
+ r = mongoc_client_session_append (session , insert_opts , & error );
917
+ ASSERT_OR_PRINT (r , error );
918
+
919
+ /* this should not override the expected server id */
920
+ r = mongoc_collection_insert_one (
921
+ coll , tmp_bson ("{}" ), insert_opts , NULL , & error );
922
+ ASSERT_OR_PRINT (r , error );
923
+ actual_id = mongoc_client_session_get_server_id (session );
924
+
925
+ ASSERT_CMPINT32 (actual_id , = = , expected_id );
926
+
927
+ /* get a valid server id that's different from the pinned server id */
928
+ servers = client -> topology -> description .servers ;
929
+ for (i = 0 ; i < servers -> items_len ; i ++ ) {
930
+ sd = (mongoc_server_description_t * ) mongoc_set_get_item (servers , i );
931
+ if (sd && sd -> id != actual_id ) {
932
+ break ;
933
+ }
934
+ }
935
+
936
+ /* attempting to pin to a different but valid server id should fail */
937
+ BSON_ASSERT (sd );
938
+ r = mongoc_client_command_with_opts (
939
+ client ,
940
+ "db" ,
941
+ tmp_bson ("{'ping': 1}" ),
942
+ NULL ,
943
+ tmp_bson ("{'serverId': %d, 'sessionId': {'$numberLong': '%ld'}}" ,
944
+ sd -> id ,
945
+ session -> client_session_id ),
946
+ & reply ,
947
+ & error );
948
+
949
+ BSON_ASSERT (!r );
950
+ ASSERT_ERROR_CONTAINS (
951
+ error ,
952
+ MONGOC_ERROR_COMMAND ,
953
+ MONGOC_ERROR_SERVER_SELECTION_INVALID_ID ,
954
+ "Requested server id does not matched pinned server id" );
955
+
956
+ r = mongoc_client_session_abort_transaction (session , & error );
957
+ ASSERT_OR_PRINT (r , error );
958
+
959
+ bson_destroy (insert_opts );
960
+ mongoc_collection_destroy (coll );
961
+ mongoc_database_destroy (db );
962
+ mongoc_session_opts_destroy (session_opts );
963
+ mongoc_transaction_opts_destroy (txn_opts );
964
+ mongoc_server_stream_cleanup (server_stream );
965
+ mongoc_client_session_destroy (session );
966
+ mongoc_client_destroy (client );
967
+ mongoc_uri_destroy (uri );
968
+ }
969
+
855
970
void
856
971
test_transactions_install (TestSuite * suite )
857
972
{
@@ -919,4 +1034,12 @@ test_transactions_install (TestSuite *suite)
919
1034
test_framework_skip_if_no_crypto ,
920
1035
test_framework_skip_if_max_wire_version_less_than_8 ,
921
1036
test_framework_skip_if_not_mongos );
1037
+ TestSuite_AddFull (suite ,
1038
+ "/transactions/selected_server_pinned_to_mongos" ,
1039
+ test_selected_server_is_pinned_to_mongos ,
1040
+ NULL ,
1041
+ NULL ,
1042
+ test_framework_skip_if_no_sessions ,
1043
+ test_framework_skip_if_max_wire_version_less_than_8 ,
1044
+ test_framework_skip_if_not_mongos );
922
1045
}
0 commit comments