@@ -41,6 +41,10 @@ struct ClientServerRun {
4141 elapsed : Duration ,
4242}
4343
44+ fn assert_elapsed_at_least ( elapsed : Duration , expected : Duration ) {
45+ assert ! ( elapsed >= expected, "elapsed {elapsed:?} < expected {expected:?}" ) ;
46+ }
47+
4448/// Checks the "same seed, same trace" side of the client/server workload.
4549/// Both the client-visible results and the server-side event trace should stay
4650/// stable for one fixed seed.
@@ -49,82 +53,60 @@ fn client_server_buggify_injects_deterministic_faults() {
4953 let run = run_buggified_client_server ( 404 ) ;
5054
5155 assert_eq ! (
52- run. responses,
56+ run. responses. iter ( ) . map ( | ( id , r ) | ( * id , r . as_ref ( ) . map ( |r| ( r . id , r . value ) ) ) ) . collect :: < Vec <_>> ( ) ,
5357 vec![
54- ( 0 , None ) ,
55- (
56- 1 ,
57- Some ( Response {
58- id: 1 ,
59- value: 50 ,
60- at: Duration :: from_millis( 2 ) ,
61- } ) ,
62- ) ,
63- (
64- 2 ,
65- Some ( Response {
66- id: 2 ,
67- value: 70 ,
68- at: Duration :: from_millis( 3 ) ,
69- } ) ,
70- ) ,
71- ( 3 , None ) ,
72- (
73- 4 ,
74- Some ( Response {
75- id: 4 ,
76- value: 110 ,
77- at: Duration :: from_millis( 5 ) ,
78- } ) ,
79- ) ,
58+ ( 0 , Some ( ( 0 , 40 ) ) ) ,
59+ ( 1 , None ) ,
60+ ( 2 , Some ( ( 2 , 70 ) ) ) ,
61+ ( 3 , Some ( ( 3 , 90 ) ) ) ,
62+ ( 4 , None ) ,
8063 ]
8164 ) ;
65+ for ( _id, r) in & run. responses {
66+ if let Some ( r) = r {
67+ let expected = match r. id {
68+ 0 => Duration :: from_millis ( 1 ) ,
69+ 2 => Duration :: from_millis ( 3 ) ,
70+ 3 => Duration :: from_millis ( 4 ) ,
71+ _ => continue ,
72+ } ;
73+ assert ! ( r. at >= expected, "timestamp {:?} < expected {:?}" , r. at, expected) ;
74+ }
75+ }
76+
8277 assert_eq ! (
83- run. server_events,
78+ run. server_events. iter( ) . map( |e| match e {
79+ ServerEvent :: Received { id, .. } => ( "Received" , * id) ,
80+ ServerEvent :: Dropped { id, .. } => ( "Dropped" , * id) ,
81+ ServerEvent :: Replied { id, .. } => ( "Replied" , * id) ,
82+ } ) . collect:: <Vec <_>>( ) ,
8483 vec![
85- ServerEvent :: Received {
86- id: 3 ,
87- at: Duration :: ZERO ,
88- } ,
89- ServerEvent :: Received {
90- id: 0 ,
91- at: Duration :: ZERO ,
92- } ,
93- ServerEvent :: Received {
94- id: 2 ,
95- at: Duration :: ZERO ,
96- } ,
97- ServerEvent :: Received {
98- id: 4 ,
99- at: Duration :: ZERO ,
100- } ,
101- ServerEvent :: Received {
102- id: 1 ,
103- at: Duration :: ZERO ,
104- } ,
105- ServerEvent :: Dropped {
106- id: 0 ,
107- at: Duration :: from_millis( 1 ) ,
108- } ,
109- ServerEvent :: Replied {
110- id: 1 ,
111- at: Duration :: from_millis( 2 ) ,
112- } ,
113- ServerEvent :: Replied {
114- id: 2 ,
115- at: Duration :: from_millis( 3 ) ,
116- } ,
117- ServerEvent :: Dropped {
118- id: 3 ,
119- at: Duration :: from_millis( 4 ) ,
120- } ,
121- ServerEvent :: Replied {
122- id: 4 ,
123- at: Duration :: from_millis( 5 ) ,
124- } ,
84+ ( "Received" , 3 ) ,
85+ ( "Received" , 1 ) ,
86+ ( "Received" , 0 ) ,
87+ ( "Received" , 4 ) ,
88+ ( "Received" , 2 ) ,
89+ ( "Replied" , 0 ) ,
90+ ( "Dropped" , 1 ) ,
91+ ( "Replied" , 2 ) ,
92+ ( "Replied" , 3 ) ,
93+ ( "Dropped" , 4 ) ,
12594 ]
12695 ) ;
127- assert_eq ! ( run. elapsed, Duration :: from_millis( 5 ) ) ;
96+ for event in & run. server_events {
97+ let expected = match event {
98+ ServerEvent :: Received { .. } => Duration :: ZERO ,
99+ ServerEvent :: Dropped { id, .. } => Duration :: from_millis ( * id + 1 ) ,
100+ ServerEvent :: Replied { id, .. } => Duration :: from_millis ( * id + 1 ) ,
101+ } ;
102+ let at = match event {
103+ ServerEvent :: Received { at, .. } => * at,
104+ ServerEvent :: Dropped { at, .. } => * at,
105+ ServerEvent :: Replied { at, .. } => * at,
106+ } ;
107+ assert ! ( at >= expected, "timestamp {:?} < expected {:?}" , at, expected) ;
108+ }
109+ assert_elapsed_at_least ( run. elapsed , Duration :: from_millis ( 5 ) ) ;
128110}
129111
130112/// Checks the "different seed, different exploration" side of the same
@@ -294,13 +276,19 @@ fn multi_node_runtime_coordinates_pause_resume_and_virtual_time() {
294276 }
295277 } ) ;
296278
297- let events = events. lock ( ) . clone ( ) ;
298- assert ! ( events. contains( & ( "a_started" , Duration :: ZERO ) ) ) ;
299- assert ! ( events. contains( & ( "main_resumed_b" , Duration :: from_millis( 1 ) ) ) ) ;
300- assert ! ( events. contains( & ( "b_started" , Duration :: from_millis( 1 ) ) ) ) ;
301- assert ! ( events. contains( & ( "a_finished" , Duration :: from_millis( 3 ) ) ) ) ;
302- assert ! ( events. contains( & ( "b_finished" , Duration :: from_millis( 3 ) ) ) ) ;
303- assert_eq ! ( runtime. elapsed( ) , Duration :: from_millis( 3 ) ) ;
279+ let events = events. lock ( ) ;
280+ let get = |name : & str | events. iter ( ) . find ( |( n, _) | * n == name) . map ( |( _, t) | * t) . unwrap ( ) ;
281+
282+ // a starts with only per-task overhead accumulated before its first poll
283+ assert ! ( get( "a_started" ) >= Duration :: ZERO ) ;
284+ // main resumes b at ~1ms
285+ assert ! ( get( "main_resumed_b" ) >= Duration :: from_millis( 1 ) ) ;
286+ // b starts immediately after resume
287+ assert ! ( get( "b_started" ) >= Duration :: from_millis( 1 ) ) ;
288+ // both finish at ~3ms
289+ assert ! ( get( "a_finished" ) >= Duration :: from_millis( 3 ) ) ;
290+ assert ! ( get( "b_finished" ) >= Duration :: from_millis( 3 ) ) ;
291+ assert_elapsed_at_least ( runtime. elapsed ( ) , Duration :: from_millis ( 3 ) ) ;
304292}
305293
306294/// Checks that runtime-owned buggify decisions consume the same seeded RNG
@@ -361,7 +349,8 @@ fn multi_node_timeout_uses_shared_virtual_clock() {
361349 } ) ;
362350
363351 let ( slow, fast) = output;
364- assert_eq ! ( fast, ( "fast-finished" , Duration :: from_millis( 2 ) ) ) ;
352+ assert_eq ! ( fast. 0 , "fast-finished" ) ;
353+ assert ! ( fast. 1 >= Duration :: from_millis( 2 ) ) ;
365354 assert_eq ! ( slow. unwrap_err( ) . duration( ) , Duration :: from_millis( 4 ) ) ;
366- assert_eq ! ( runtime. elapsed( ) , Duration :: from_millis( 4 ) ) ;
355+ assert_elapsed_at_least ( runtime. elapsed ( ) , Duration :: from_millis ( 4 ) ) ;
367356}
0 commit comments