Skip to content

Commit

Permalink
Fix test progress bar for small screens.
Browse files Browse the repository at this point in the history
  • Loading branch information
jcamiel committed Jun 24, 2024
1 parent 6546d11 commit 8aba7c2
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 15 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/hurl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ lazy_static = "1.5.0"
# uuid features: lets you generate random UUIDs and use a faster (but still sufficiently random) RNG
uuid = { version = "1.8.0", features = ["v4" , "fast-rng"] }
similar = "2.5.0"
terminal_size = "0.3.0"

[target.'cfg(unix)'.dependencies]
termion = "4.0.2"
Expand Down
84 changes: 73 additions & 11 deletions packages/hurl/src/parallel/progress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ pub struct ParProgress {
mode: Mode,
/// The standard error format for message: ANSI or plain.
format: Format,
/// The maximum width of the progress string, in chars.
max_width: Option<usize>,
/// Save last progress bar refresh to limits flickering.
throttle: Throttle,
}
Expand All @@ -52,12 +54,18 @@ const FIRST_THROTTLE: Duration = Duration::from_millis(16);

impl ParProgress {
/// Creates a new instance.
pub fn new(max_running_displayed: usize, mode: Mode, color: bool) -> Self {
pub fn new(
max_running_displayed: usize,
mode: Mode,
color: bool,
max_width: Option<usize>,
) -> Self {
let format = if color { Format::Ansi } else { Format::Plain };
ParProgress {
max_running_displayed,
mode,
format,
max_width,
throttle: Throttle::new(UPDATE_INTERVAL, FIRST_THROTTLE),
}
}
Expand Down Expand Up @@ -91,6 +99,7 @@ impl ParProgress {
count,
self.max_running_displayed,
self.format,
self.max_width,
) else {
return;
};
Expand Down Expand Up @@ -199,13 +208,15 @@ impl Throttle {
///
/// `max_running_displayed` is used to limit the number of running progress bar. If more jobs are
/// running, a label "...x more" is displayed.
/// `color` is `true` when the returned progress string uses color.
/// `format` is the format of the progress string (ANSI or plain).
/// The progress string is wrapped with new lines at width `max_width`.
fn build_progress(
workers: &[(Worker, WorkerState)],
completed: usize,
count: Option<usize>,
max_running_displayed: usize,
format: Format,
max_width: Option<usize>,
) -> Option<String> {
// Select the running workers to be displayed
let mut workers = workers
Expand Down Expand Up @@ -237,7 +248,7 @@ fn build_progress(
})
.max()
.unwrap();
let max_width = 2 * (((max as f64).log10() as usize) + 1) + 1;
let max_completed_width = 2 * (((max as f64).log10() as usize) + 1) + 1;

// Construct all the progress strings
let mut all_progress = String::new();
Expand All @@ -248,6 +259,8 @@ fn build_progress(
}
None => format!("Executed files: {completed}\n"),
};
// We don't wrap this string for the moment, there is low chance to overlap the maximum width
// of the terminal.
all_progress.push_str(&progress);

for (_, state) in &workers {
Expand All @@ -259,7 +272,7 @@ fn build_progress(
{
let entry_index = entry_index + 1; // entry index display is 1-based
let requests = format!("{entry_index}/{entry_count}");
let padding = " ".repeat(max_width - requests.len());
let padding = " ".repeat(max_completed_width - requests.len());
let bar = progress_bar(entry_index, *entry_count);

let mut progress = StyledString::new();
Expand All @@ -271,6 +284,13 @@ fn build_progress(
progress.push_with("Running", Style::new().cyan().bold());
progress.push("\n");

// We wrap the progress string with new lines if necessary
if let Some(max_width) = max_width {
if progress.len() >= max_width {
progress = progress.wrap(max_width);
}
}

let progress = progress.to_string(format);
all_progress.push_str(&progress);
}
Expand Down Expand Up @@ -370,7 +390,14 @@ mod tests {
(w4, WorkerState::Idle),
];

let progress = build_progress(&workers, completed, total, max_displayed, Format::Plain);
let progress = build_progress(
&workers,
completed,
total,
max_displayed,
Format::Plain,
None,
);
assert!(progress.is_none());

workers[0].1 = new_running_state(&jobs[0], 0, 10);
Expand All @@ -379,7 +406,14 @@ mod tests {
workers[3].1 = new_running_state(&jobs[3], 0, 7);
workers[4].1 = new_running_state(&jobs[4], 0, 4);

let progress = build_progress(&workers, completed, total, max_displayed, Format::Plain);
let progress = build_progress(
&workers,
completed,
total,
max_displayed,
Format::Plain,
None,
);
assert_eq!(
progress.unwrap(),
"\
Expand All @@ -397,7 +431,14 @@ Executed files: 75/100 (75%)\n\
workers[3].1 = new_running_state(&jobs[3], 3, 7);
workers[4].1 = new_running_state(&jobs[4], 1, 4);

let progress = build_progress(&workers, completed, total, max_displayed, Format::Plain);
let progress = build_progress(
&workers,
completed,
total,
max_displayed,
Format::Plain,
None,
);
assert_eq!(
progress.unwrap(),
"\
Expand All @@ -415,7 +456,14 @@ Executed files: 75/100 (75%)\n\
workers[3].1 = new_running_state(&jobs[3], 5, 7);
workers[4].1 = new_running_state(&jobs[4], 2, 4);

let progress = build_progress(&workers, completed, total, max_displayed, Format::Plain);
let progress = build_progress(
&workers,
completed,
total,
max_displayed,
Format::Plain,
None,
);
assert_eq!(
progress.unwrap(),
"\
Expand All @@ -433,7 +481,14 @@ Executed files: 75/100 (75%)\n\
workers[3].1 = WorkerState::Idle;
workers[4].1 = new_running_state(&jobs[4], 3, 4);

let progress = build_progress(&workers, completed, total, max_displayed, Format::Plain);
let progress = build_progress(
&workers,
completed,
total,
max_displayed,
Format::Plain,
None,
);
assert_eq!(
progress.unwrap(),
"\
Expand All @@ -449,7 +504,14 @@ Executed files: 75/100 (75%)\n\
workers[3].1 = WorkerState::Idle;
workers[4].1 = WorkerState::Idle;

let progress = build_progress(&workers, completed, total, max_displayed, Format::Plain);
let progress = build_progress(
&workers,
completed,
total,
max_displayed,
Format::Plain,
None,
);
assert_eq!(
progress.unwrap(),
"\
Expand All @@ -475,7 +537,7 @@ Executed files: 75/100 (75%)\n\
assert_eq!(progress_bar(2, 3), "[========> ] 2/3");
assert_eq!(progress_bar(3, 3), "[================> ] 3/3");

// Progress strings with 1 entries:
// Progress strings with 1 entry:
assert_eq!(progress_bar(1, 1), "[> ] 1/1");
}
}
10 changes: 6 additions & 4 deletions packages/hurl/src/parallel/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,12 @@ impl ParallelRunner {
/// whether as a raw response body bytes, or in a structured JSON output.
///
/// The runner can repeat running a list of jobs. For instance, when repeating two times the job
/// sequence (`a`, `b`, `c`), runner will act as if it runs (`a`, `b`, `c`).
/// sequence (`a`, `b`, `c`), runner will act as if it runs (`a`, `b`, `c`, `a`, `b`, `c`).
///
/// If `test` mode is `true` the runner is run in "test" mode, reporting the success or failure
/// of each file on standard error. Additionally to the test mode, a `progress_bar` designed for
/// parallel run progression can be used.
/// of each file on standard error. In addition to the test mode, a `progress_bar` designed for
/// parallel run progression can be used. When the progress bar is displayed, it's wrapped with
/// new lines at width `max_width`.
///
/// `color` determines if color if used in standard error.
pub fn new(
Expand All @@ -109,6 +110,7 @@ impl ParallelRunner {
test: bool,
progress_bar: bool,
color: bool,
max_width: Option<usize>,
) -> Self {
// Worker are running on theirs own thread, while parallel runner is running in the main
// thread.
Expand All @@ -128,7 +130,7 @@ impl ParallelRunner {
.collect::<Vec<_>>();

let mode = Mode::new(test, progress_bar);
let progress = ParProgress::new(MAX_RUNNING_DISPLAYED, mode, color);
let progress = ParProgress::new(MAX_RUNNING_DISPLAYED, mode, color, max_width);

ParallelRunner {
workers,
Expand Down
2 changes: 2 additions & 0 deletions packages/hurl/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ pub fn run_par(
let output_type = options
.output_type
.to_output_type(options.include, options.color);
let max_width = terminal_size::terminal_size().map(|(w, _)| w.0 as usize);

let jobs = files
.iter()
Expand All @@ -192,6 +193,7 @@ pub fn run_par(
options.test,
options.progress_bar,
options.color,
max_width,
);
let results = runner.run(&jobs)?;
let results = results.into_iter().map(HurlRun::from).collect();
Expand Down

0 comments on commit 8aba7c2

Please sign in to comment.