mirror of
https://github.com/Orange-OpenSource/hurl.git
synced 2024-11-26 11:43:08 +03:00
Fix test progress bar for small screens.
This commit is contained in:
parent
6546d11cf8
commit
8aba7c2bef
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -527,6 +527,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"similar",
|
||||
"terminal_size",
|
||||
"termion",
|
||||
"url",
|
||||
"uuid",
|
||||
|
@ -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"
|
||||
|
@ -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,
|
||||
}
|
||||
@ -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),
|
||||
}
|
||||
}
|
||||
@ -91,6 +99,7 @@ impl ParProgress {
|
||||
count,
|
||||
self.max_running_displayed,
|
||||
self.format,
|
||||
self.max_width,
|
||||
) else {
|
||||
return;
|
||||
};
|
||||
@ -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
|
||||
@ -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();
|
||||
@ -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 {
|
||||
@ -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();
|
||||
@ -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);
|
||||
}
|
||||
@ -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);
|
||||
@ -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(),
|
||||
"\
|
||||
@ -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(),
|
||||
"\
|
||||
@ -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(),
|
||||
"\
|
||||
@ -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(),
|
||||
"\
|
||||
@ -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(),
|
||||
"\
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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(
|
||||
@ -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.
|
||||
@ -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,
|
||||
|
@ -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()
|
||||
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user