@@ -78,15 +78,31 @@ pub struct ProgressBarJsonFormatter;
7878impl ProgressBarJsonFormatter {
7979 /// Get a json formatted string given the progress bar status
8080 pub fn format ( progress_bar : & ProgressBar ) -> String {
81- format ! (
82- r#"{{"timestamp": "{}", "bytes_downloaded": {}, "bytes_total": {}, "seconds_left": {}.{:0>3}, "seconds_elapsed": {}.{:0>3}}}"# ,
81+ ProgressBarJsonFormatter :: format_values (
8382 Utc :: now ( ) . to_rfc3339 ( ) ,
8483 progress_bar. position ( ) ,
8584 progress_bar. length ( ) . unwrap_or ( 0 ) ,
86- progress_bar. eta( ) . as_secs( ) ,
87- progress_bar. eta( ) . subsec_millis( ) ,
88- progress_bar. elapsed( ) . as_secs( ) ,
89- progress_bar. elapsed( ) . subsec_millis( ) ,
85+ progress_bar. eta ( ) ,
86+ progress_bar. elapsed ( ) ,
87+ )
88+ }
89+
90+ fn format_values (
91+ timestamp : String ,
92+ bytes_downloaded : u64 ,
93+ bytes_total : u64 ,
94+ duration_left : Duration ,
95+ duration_elapsed : Duration ,
96+ ) -> String {
97+ format ! (
98+ r#"{{"timestamp": "{}", "bytes_downloaded": {}, "bytes_total": {}, "seconds_left": {}.{:0>3}, "seconds_elapsed": {}.{:0>3}}}"# ,
99+ timestamp,
100+ bytes_downloaded,
101+ bytes_total,
102+ duration_left. as_secs( ) ,
103+ duration_left. subsec_millis( ) ,
104+ duration_elapsed. as_secs( ) ,
105+ duration_elapsed. subsec_millis( ) ,
90106 )
91107 }
92108}
@@ -150,13 +166,23 @@ mod tests {
150166
151167 use super :: * ;
152168 use indicatif:: ProgressBar ;
169+ use serde_json:: Value ;
153170
154171 #[ test]
155- fn check_seconds_elapsed_in_json_report_with_more_than_100_milliseconds ( ) {
156- let progress_bar = ProgressBar :: new ( 10 ) . with_elapsed ( Duration :: from_millis ( 5124 ) ) ;
157-
158- let json_string = ProgressBarJsonFormatter :: format ( & progress_bar) ;
172+ fn check_seconds_formatting_in_json_report_with_more_than_100_milliseconds ( ) {
173+ let json_string = ProgressBarJsonFormatter :: format_values (
174+ "" . to_string ( ) ,
175+ 0 ,
176+ 0 ,
177+ Duration :: from_millis ( 7569 ) ,
178+ Duration :: from_millis ( 5124 ) ,
179+ ) ;
159180
181+ assert ! (
182+ json_string. contains( r#""seconds_left": 7.569"# ) ,
183+ "Not expected value in json output: {}" ,
184+ json_string
185+ ) ;
160186 assert ! (
161187 json_string. contains( r#""seconds_elapsed": 5.124"# ) ,
162188 "Not expected value in json output: {}" ,
@@ -165,11 +191,20 @@ mod tests {
165191 }
166192
167193 #[ test]
168- fn check_seconds_elapsed_in_json_report_with_less_than_100_milliseconds ( ) {
169- let progress_bar = ProgressBar :: new ( 10 ) . with_elapsed ( Duration :: from_millis ( 5004 ) ) ;
170-
171- let json_string = ProgressBarJsonFormatter :: format ( & progress_bar) ;
194+ fn check_seconds_formatting_in_json_report_with_less_than_100_milliseconds ( ) {
195+ let json_string = ProgressBarJsonFormatter :: format_values (
196+ "" . to_string ( ) ,
197+ 0 ,
198+ 0 ,
199+ Duration :: from_millis ( 7006 ) ,
200+ Duration :: from_millis ( 5004 ) ,
201+ ) ;
172202
203+ assert ! (
204+ json_string. contains( r#""seconds_left": 7.006"# ) ,
205+ "Not expected value in json output: {}" ,
206+ json_string
207+ ) ;
173208 assert ! (
174209 json_string. contains( r#""seconds_elapsed": 5.004"# ) ,
175210 "Not expected value in json output: {}" ,
@@ -178,40 +213,83 @@ mod tests {
178213 }
179214
180215 #[ test]
181- fn check_seconds_left_in_json_report_with_more_than_100_milliseconds ( ) {
182- let half_position = 5 ;
183- let progress_bar = ProgressBar :: new ( half_position * 2 ) ;
184- sleep ( Duration :: from_millis ( 123 ) ) ;
185- progress_bar. set_position ( half_position) ;
186- let json_string = ProgressBarJsonFormatter :: format ( & progress_bar) ;
216+ fn check_seconds_formatting_in_json_report_with_milliseconds_ending_by_zeros ( ) {
217+ let json_string = ProgressBarJsonFormatter :: format_values (
218+ "" . to_string ( ) ,
219+ 0 ,
220+ 0 ,
221+ Duration :: from_millis ( 7200 ) ,
222+ Duration :: from_millis ( 5100 ) ,
223+ ) ;
187224
188- let milliseconds = progress_bar. eta ( ) . subsec_millis ( ) ;
189- assert ! ( milliseconds > 100 ) ;
190225 assert ! (
191- json_string. contains( & format!( r#""seconds_left": 0.{}"# , milliseconds) ) ,
226+ json_string. contains( r#""seconds_left": 7.200"# ) ,
227+ "Not expected value in json output: {}" ,
228+ json_string
229+ ) ;
230+ assert ! (
231+ json_string. contains( r#""seconds_elapsed": 5.100"# ) ,
192232 "Not expected value in json output: {}" ,
193233 json_string
194234 ) ;
195235 }
196236
197237 #[ test]
198- fn check_seconds_left_in_json_report_with_less_than_100_milliseconds ( ) {
199- let half_position = 5 ;
200- let progress_bar = ProgressBar :: new ( half_position * 2 ) ;
201- sleep ( Duration :: from_millis ( 1 ) ) ;
202- progress_bar. set_position ( half_position) ;
238+ fn check_seconds_left_and_elapsed_time_are_used_by_the_formatter ( ) {
239+ fn format_duration ( duration : & Duration ) -> String {
240+ format ! ( "{}.{}" , duration. as_secs( ) , duration. subsec_nanos( ) )
241+ }
242+ fn round_at_ms ( duration : Duration ) -> Duration {
243+ Duration :: from_millis ( duration. as_millis ( ) as u64 )
244+ }
245+
246+ // 4 steps
247+ let progress_bar = ProgressBar :: new ( 4 ) ;
248+ // 1 step done in 15 ms, left 45ms to finish the 4th steps
249+ sleep ( Duration :: from_millis ( 15 ) ) ;
250+ progress_bar. set_position ( 1 ) ;
251+
252+ let duration_left_before = round_at_ms ( progress_bar. eta ( ) ) ;
253+ let duration_elapsed_before = round_at_ms ( progress_bar. elapsed ( ) ) ;
254+
203255 let json_string = ProgressBarJsonFormatter :: format ( & progress_bar) ;
204256
257+ let duration_left_after = round_at_ms ( progress_bar. eta ( ) ) ;
258+ let duration_elapsed_after = round_at_ms ( progress_bar. elapsed ( ) ) ;
259+
260+ // Milliseconds in json may not be exactly the same as the one we get because of the test duration.
261+ let delta = 0.1 ;
262+
263+ let json_value: Value = serde_json:: from_str ( & json_string) . unwrap ( ) ;
264+ let seconds_left = json_value[ "seconds_left" ] . as_f64 ( ) . unwrap ( ) ;
265+ let seconds_elapsed = json_value[ "seconds_elapsed" ] . as_f64 ( ) . unwrap ( ) ;
266+
267+ // We check that we pass the right values to format checking that time left is 3 times the time elapsed
205268 assert ! (
206- json_string. contains( r#""seconds_left": 0.0"# ) ,
207- "Not expected value in json output: {}" ,
208- json_string
269+ seconds_elapsed * 3.0 - delta < seconds_left
270+ && seconds_left < seconds_elapsed * 3.0 + delta,
271+ "seconds_left should be close to 3*{} but it's {}." ,
272+ & seconds_elapsed,
273+ & seconds_left
209274 ) ;
210275
276+ let duration_left = Duration :: from_secs_f64 ( seconds_left) ;
211277 assert ! (
212- !json_string. contains( r#""seconds_left": 0.000"# ) ,
213- "Not expected value in json output: {}" ,
214- json_string
278+ duration_left_before <= duration_left && duration_left <= duration_left_after,
279+ "Duration left: {} should be between {} and {}" ,
280+ format_duration( & duration_left) ,
281+ format_duration( & duration_left_before) ,
282+ format_duration( & duration_left_after) ,
283+ ) ;
284+
285+ let duration_elapsed = Duration :: from_secs_f64 ( seconds_elapsed) ;
286+ assert ! (
287+ duration_elapsed_before <= duration_elapsed
288+ && duration_elapsed <= duration_elapsed_after,
289+ "Duration elapsed: {} should be between {} and {}" ,
290+ format_duration( & duration_elapsed) ,
291+ format_duration( & duration_elapsed_before) ,
292+ format_duration( & duration_elapsed_after) ,
215293 ) ;
216294 }
217295}
0 commit comments