@@ -288,17 +288,11 @@ where
288288 . into_iter ( )
289289 . map ( |bp| SourceBreakpoint {
290290 line : bp. line ,
291- condition : if bp. condition . is_empty ( ) {
292- None
293- } else {
294- Some ( bp. condition )
295- } ,
296- log_message : if bp. log_message . is_empty ( ) {
297- None
298- } else {
299- Some ( bp. log_message )
300- } ,
301- ..Default :: default ( )
291+ column : bp. column ,
292+ condition : bp. condition ,
293+ hit_condition : bp. hit_condition ,
294+ log_message : bp. log_message ,
295+ mode : bp. mode ,
302296 } )
303297 . collect ( )
304298 } else {
@@ -785,8 +779,11 @@ impl DapperControlPlane for DapperControlPlaneClient {
785779 . iter ( )
786780 . map ( |bp| dapper_control_proto:: SourceBreakpoint {
787781 line : bp. line ,
788- condition : bp. condition . clone ( ) . unwrap_or_default ( ) ,
789- log_message : bp. log_message . clone ( ) . unwrap_or_default ( ) ,
782+ condition : bp. condition . clone ( ) ,
783+ hit_condition : bp. hit_condition . clone ( ) ,
784+ log_message : bp. log_message . clone ( ) ,
785+ column : bp. column ,
786+ mode : bp. mode . clone ( ) ,
790787 } )
791788 . collect ( ) ;
792789 let lines: Vec < i64 > = breakpoint_specs. iter ( ) . map ( |bp| bp. line ) . collect ( ) ;
@@ -877,6 +874,7 @@ impl DapperControlPlane for DapperControlPlaneClient {
877874#[ cfg( test) ]
878875mod tests {
879876 use std:: sync:: Arc ;
877+ use std:: sync:: Mutex ;
880878 use std:: sync:: atomic:: AtomicBool ;
881879 use std:: sync:: atomic:: Ordering ;
882880
@@ -912,10 +910,14 @@ mod tests {
912910
913911 struct TestServer {
914912 stop_was_called : Arc < AtomicBool > ,
913+ breakpoint_specs : Arc < Mutex < Vec < SourceBreakpoint > > > ,
915914 }
916915 impl TestServer {
917916 fn new ( stop_was_called : Arc < AtomicBool > ) -> Self {
918- TestServer { stop_was_called }
917+ TestServer {
918+ stop_was_called,
919+ breakpoint_specs : Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ,
920+ }
919921 }
920922 }
921923 #[ async_trait:: async_trait]
@@ -1062,6 +1064,11 @@ mod tests {
10621064 clear_existing : bool ,
10631065 breakpoint_specs : & [ SourceBreakpoint ] ,
10641066 ) -> anyhow:: Result < ControlPlaneResult < dapper_session:: SetBreakpointsResult > > {
1067+ * self
1068+ . breakpoint_specs
1069+ . lock ( )
1070+ . expect ( "breakpoint recorder mutex should not be poisoned" ) =
1071+ breakpoint_specs. to_vec ( ) ;
10651072 let breakpoints = breakpoint_specs
10661073 . iter ( )
10671074 . map ( |bp| dapper_session:: BreakpointInfo {
@@ -1165,6 +1172,60 @@ mod tests {
11651172 }
11661173 }
11671174
1175+ async fn round_trip_breakpoint_specs (
1176+ breakpoint_specs : & [ SourceBreakpoint ] ,
1177+ ) -> anyhow:: Result < Vec < SourceBreakpoint > > {
1178+ let server = TestServer :: new ( Arc :: new ( AtomicBool :: new ( false ) ) ) ;
1179+ let recorded_specs = Arc :: clone ( & server. breakpoint_specs ) ;
1180+ let control_plane_server = serve ( None , server) . await ?;
1181+ tokio:: task:: yield_now ( ) . await ;
1182+
1183+ let client = DapperControlPlaneClient :: for_port ( control_plane_server. port ) ;
1184+ let result = client
1185+ . set_breakpoints ( "/path/to/file.py" , true , breakpoint_specs)
1186+ . await ;
1187+ control_plane_server. handle . abort ( ) ;
1188+ result?;
1189+
1190+ let specs = recorded_specs
1191+ . lock ( )
1192+ . expect ( "breakpoint recorder mutex should not be poisoned" )
1193+ . clone ( ) ;
1194+ Ok ( specs)
1195+ }
1196+
1197+ #[ tokio:: test]
1198+ async fn set_breakpoints_grpc_preserves_source_breakpoint_metadata ( ) -> anyhow:: Result < ( ) > {
1199+ let expected = SourceBreakpoint {
1200+ line : 42 ,
1201+ column : Some ( 7 ) ,
1202+ condition : Some ( "x > 0" . into ( ) ) ,
1203+ hit_condition : Some ( "3" . into ( ) ) ,
1204+ log_message : Some ( "hit {x}" . into ( ) ) ,
1205+ mode : Some ( "hardware" . into ( ) ) ,
1206+ } ;
1207+
1208+ let recorded = round_trip_breakpoint_specs ( std:: slice:: from_ref ( & expected) ) . await ?;
1209+ assert_eq ! ( recorded, vec![ expected] ) ;
1210+ Ok ( ( ) )
1211+ }
1212+
1213+ #[ tokio:: test]
1214+ async fn set_breakpoints_grpc_preserves_present_empty_strings ( ) -> anyhow:: Result < ( ) > {
1215+ let expected = SourceBreakpoint {
1216+ line : 42 ,
1217+ condition : Some ( String :: new ( ) ) ,
1218+ hit_condition : Some ( String :: new ( ) ) ,
1219+ log_message : Some ( String :: new ( ) ) ,
1220+ mode : Some ( String :: new ( ) ) ,
1221+ ..Default :: default ( )
1222+ } ;
1223+
1224+ let recorded = round_trip_breakpoint_specs ( std:: slice:: from_ref ( & expected) ) . await ?;
1225+ assert_eq ! ( recorded, vec![ expected] ) ;
1226+ Ok ( ( ) )
1227+ }
1228+
11681229 #[ tokio:: test]
11691230 async fn client_calls_server ( ) -> anyhow:: Result < ( ) > {
11701231 let stop_was_called = Arc :: new ( AtomicBool :: new ( false ) ) ;
0 commit comments