@@ -823,6 +823,98 @@ skip_if_not_loadbalanced (void)
823
823
return test_framework_is_loadbalanced () ? 1 : 0 ;
824
824
}
825
825
826
+ void
827
+ store_last_command_started_callback (const mongoc_apm_command_started_t * event )
828
+ {
829
+ bson_t * * last_command = mongoc_apm_command_started_get_context (event );
830
+ const bson_t * cmd = mongoc_apm_command_started_get_command (event );
831
+ bson_destroy (* last_command );
832
+ * last_command = bson_copy (cmd );
833
+ }
834
+
835
+ // `test_loadbalanced_sends_recoveryToken` is a regression test for
836
+ // CDRIVER-4718. Ensure that a `recoveryToken` is included in the outgoing
837
+ // `commitTransaction` and `abortTransaction` commands when connected to a load
838
+ // balanced cluster.
839
+ static void
840
+ test_loadbalanced_sends_recoveryToken (void * unused )
841
+ {
842
+ mongoc_client_t * client ;
843
+ bson_error_t error ;
844
+ bson_t * last_command = NULL ;
845
+
846
+ BSON_UNUSED (unused );
847
+
848
+ client = test_framework_new_default_client ();
849
+ // Set a callback to store the most recent command started.
850
+ {
851
+ mongoc_apm_callbacks_t * cbs = mongoc_apm_callbacks_new ();
852
+ mongoc_apm_set_command_started_cb (cbs ,
853
+ store_last_command_started_callback );
854
+ mongoc_client_set_apm_callbacks (client , cbs , & last_command );
855
+ mongoc_apm_callbacks_destroy (cbs );
856
+ }
857
+
858
+ mongoc_client_session_t * session =
859
+ mongoc_client_start_session (client , NULL /* opts */ , & error );
860
+ ASSERT_OR_PRINT (session , error );
861
+
862
+ mongoc_collection_t * coll =
863
+ mongoc_client_get_collection (client , "db" , "coll" );
864
+
865
+ // Commit a transaction. Expect `commitTransaction` to include
866
+ // `recoveryToken`.
867
+ {
868
+ bool ok = mongoc_client_session_start_transaction (
869
+ session , NULL /* opts */ , & error );
870
+ ASSERT_OR_PRINT (ok , error );
871
+
872
+ bson_t * insert_opts = tmp_bson ("{}" );
873
+ ok = mongoc_client_session_append (session , insert_opts , & error );
874
+ ASSERT_OR_PRINT (ok , error );
875
+
876
+ ok = mongoc_collection_insert_one (
877
+ coll , tmp_bson ("{}" ), insert_opts , NULL , & error );
878
+ ASSERT_OR_PRINT (ok , error );
879
+
880
+ ok = mongoc_client_session_commit_transaction (
881
+ session , NULL /* reply */ , & error );
882
+ ASSERT_OR_PRINT (ok , error );
883
+
884
+ ASSERT_MATCH (
885
+ last_command ,
886
+ "{'commitTransaction': 1, 'recoveryToken': { '$exists': true } }" );
887
+ }
888
+
889
+ // Abort a transaction. Expect `commitTransaction` to include
890
+ // `recoveryToken`.
891
+ {
892
+ bool ok = mongoc_client_session_start_transaction (
893
+ session , NULL /* opts */ , & error );
894
+ ASSERT_OR_PRINT (ok , error );
895
+
896
+ bson_t * insert_opts = tmp_bson ("{}" );
897
+ ok = mongoc_client_session_append (session , insert_opts , & error );
898
+ ASSERT_OR_PRINT (ok , error );
899
+
900
+ ok = mongoc_collection_insert_one (
901
+ coll , tmp_bson ("{}" ), insert_opts , NULL , & error );
902
+ ASSERT_OR_PRINT (ok , error );
903
+
904
+ ok = mongoc_client_session_abort_transaction (session , & error );
905
+ ASSERT_OR_PRINT (ok , error );
906
+
907
+ ASSERT_MATCH (
908
+ last_command ,
909
+ "{'abortTransaction': 1, 'recoveryToken': { '$exists': true } }" );
910
+ }
911
+
912
+ mongoc_collection_destroy (coll );
913
+ mongoc_client_session_destroy (session );
914
+ mongoc_client_destroy (client );
915
+ bson_destroy (last_command );
916
+ }
917
+
826
918
void
827
919
test_loadbalanced_install (TestSuite * suite )
828
920
{
@@ -893,4 +985,11 @@ test_loadbalanced_install (TestSuite *suite)
893
985
suite ,
894
986
"/loadbalanced/post_handshake_error_clears_pool" ,
895
987
test_post_handshake_error_clears_pool );
988
+
989
+ TestSuite_AddFull (suite ,
990
+ "/loadbalanced/sends_recoveryToken" ,
991
+ test_loadbalanced_sends_recoveryToken ,
992
+ NULL /* ctx */ ,
993
+ NULL /* dtor */ ,
994
+ skip_if_not_loadbalanced );
896
995
}
0 commit comments