Merge pull request #2405 from miDeb/pr/races

tests/pr: prevent races
This commit is contained in:
Terts Diepraam 2021-06-13 23:22:13 +02:00 committed by GitHub
commit a5fcf8c6a4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 87 additions and 100 deletions

View file

@ -3,6 +3,7 @@
use crate::common::util::*;
use chrono::offset::Local;
use chrono::DateTime;
use chrono::Duration;
use std::fs::metadata;
fn file_last_modified_time(ucmd: &UCommand, path: &str) -> String {
@ -20,8 +21,22 @@ fn file_last_modified_time(ucmd: &UCommand, path: &str) -> String {
.unwrap_or_default()
}
fn now_time() -> String {
Local::now().format("%b %d %H:%M %Y").to_string()
fn all_minutes(from: DateTime<Local>, to: DateTime<Local>) -> Vec<String> {
const FORMAT: &str = "%b %d %H:%M %Y";
let mut vec = vec![];
let mut current = from;
while current < to {
vec.push(current.format(FORMAT).to_string());
current = current + Duration::minutes(1);
}
vec
}
fn valid_last_modified_template_vars(from: DateTime<Local>) -> Vec<Vec<(String, String)>> {
all_minutes(from, Local::now())
.into_iter()
.map(|time| vec![("{last_modified_time}".to_string(), time)])
.collect()
}
#[test]
@ -33,10 +48,7 @@ fn test_without_any_options() {
scenario
.args(&[test_file_path])
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path,
vec![(&"{last_modified_time}".to_string(), &value)],
);
.stdout_is_templated_fixture(expected_test_file_path, &[("{last_modified_time}", &value)]);
}
#[test]
@ -48,10 +60,7 @@ fn test_with_numbering_option_with_number_width() {
scenario
.args(&["-n", "2", test_file_path])
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path,
vec![(&"{last_modified_time}".to_string(), &value)],
);
.stdout_is_templated_fixture(expected_test_file_path, &[("{last_modified_time}", &value)]);
}
#[test]
@ -66,10 +75,7 @@ fn test_with_long_header_option() {
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path,
vec![
(&"{last_modified_time}".to_string(), &value),
(&"{header}".to_string(), &header.to_string()),
],
&[("{last_modified_time}", &value), ("{header}", header)],
);
new_ucmd!()
@ -77,10 +83,7 @@ fn test_with_long_header_option() {
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path,
vec![
(&"{last_modified_time}".to_string(), &value),
(&"{header}".to_string(), &header.to_string()),
],
&[("{last_modified_time}", &value), ("{header}", header)],
);
}
@ -93,18 +96,12 @@ fn test_with_double_space_option() {
scenario
.args(&["-d", test_file_path])
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path,
vec![(&"{last_modified_time}".to_string(), &value)],
);
.stdout_is_templated_fixture(expected_test_file_path, &[("{last_modified_time}", &value)]);
new_ucmd!()
.args(&["--double-space", test_file_path])
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path,
vec![(&"{last_modified_time}".to_string(), &value)],
);
.stdout_is_templated_fixture(expected_test_file_path, &[("{last_modified_time}", &value)]);
}
#[test]
@ -116,10 +113,7 @@ fn test_with_first_line_number_option() {
scenario
.args(&["-N", "5", "-n", test_file_path])
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path,
vec![(&"{last_modified_time}".to_string(), &value)],
);
.stdout_is_templated_fixture(expected_test_file_path, &[("{last_modified_time}", &value)]);
}
#[test]
@ -131,10 +125,7 @@ fn test_with_first_line_number_long_option() {
scenario
.args(&["--first-line-number=5", "-n", test_file_path])
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path,
vec![(&"{last_modified_time}".to_string(), &value)],
);
.stdout_is_templated_fixture(expected_test_file_path, &[("{last_modified_time}", &value)]);
}
#[test]
@ -146,10 +137,7 @@ fn test_with_number_option_with_custom_separator_char() {
scenario
.args(&["-nc", test_file_path])
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path,
vec![(&"{last_modified_time}".to_string(), &value)],
);
.stdout_is_templated_fixture(expected_test_file_path, &[("{last_modified_time}", &value)]);
}
#[test]
@ -161,10 +149,7 @@ fn test_with_number_option_with_custom_separator_char_and_width() {
scenario
.args(&["-nc1", test_file_path])
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path,
vec![(&"{last_modified_time}".to_string(), &value)],
);
.stdout_is_templated_fixture(expected_test_file_path, &[("{last_modified_time}", &value)]);
}
#[test]
@ -207,25 +192,19 @@ fn test_with_page_range() {
scenario
.args(&["--pages=15", test_file_path])
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path,
vec![(&"{last_modified_time}".to_string(), &value)],
);
.stdout_is_templated_fixture(expected_test_file_path, &[("{last_modified_time}", &value)]);
new_ucmd!()
.args(&["+15", test_file_path])
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path,
vec![(&"{last_modified_time}".to_string(), &value)],
);
.stdout_is_templated_fixture(expected_test_file_path, &[("{last_modified_time}", &value)]);
new_ucmd!()
.args(&["--pages=15:17", test_file_path])
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path1,
vec![(&"{last_modified_time}".to_string(), &value)],
&[("{last_modified_time}", &value)],
);
new_ucmd!()
@ -233,7 +212,7 @@ fn test_with_page_range() {
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path1,
vec![(&"{last_modified_time}".to_string(), &value)],
&[("{last_modified_time}", &value)],
);
}
@ -246,10 +225,7 @@ fn test_with_no_header_trailer_option() {
scenario
.args(&["-t", test_file_path])
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path,
vec![(&"{last_modified_time}".to_string(), &value)],
);
.stdout_is_templated_fixture(expected_test_file_path, &[("{last_modified_time}", &value)]);
}
#[test]
@ -262,10 +238,7 @@ fn test_with_page_length_option() {
scenario
.args(&["--pages=2:3", "-l", "100", "-n", test_file_path])
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path,
vec![(&"{last_modified_time}".to_string(), &value)],
);
.stdout_is_templated_fixture(expected_test_file_path, &[("{last_modified_time}", &value)]);
new_ucmd!()
.args(&["--pages=2:3", "-l", "5", "-n", test_file_path])
@ -288,14 +261,14 @@ fn test_with_suppress_error_option() {
fn test_with_stdin() {
let expected_file_path = "stdin.log.expected";
let mut scenario = new_ucmd!();
let now = now_time();
let start = Local::now();
scenario
.pipe_in_fixture("stdin.log")
.args(&["--pages=1:2", "-n", "-"])
.run()
.stdout_is_templated_fixture(
.stdout_is_templated_fixture_any(
expected_file_path,
vec![(&"{last_modified_time}".to_string(), &now)],
&valid_last_modified_template_vars(start),
);
}
@ -308,18 +281,12 @@ fn test_with_column() {
scenario
.args(&["--pages=3:5", "--column=3", "-n", test_file_path])
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path,
vec![(&"{last_modified_time}".to_string(), &value)],
);
.stdout_is_templated_fixture(expected_test_file_path, &[("{last_modified_time}", &value)]);
new_ucmd!()
.args(&["--pages=3:5", "-3", "-n", test_file_path])
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path,
vec![(&"{last_modified_time}".to_string(), &value)],
);
.stdout_is_templated_fixture(expected_test_file_path, &[("{last_modified_time}", &value)]);
}
#[test]
@ -331,10 +298,7 @@ fn test_with_column_across_option() {
scenario
.args(&["--pages=3:5", "--column=3", "-a", "-n", test_file_path])
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path,
vec![(&"{last_modified_time}".to_string(), &value)],
);
.stdout_is_templated_fixture(expected_test_file_path, &[("{last_modified_time}", &value)]);
}
#[test]
@ -354,10 +318,7 @@ fn test_with_column_across_option_and_column_separator() {
test_file_path,
])
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path,
vec![(&"{last_modified_time}".to_string(), &value)],
);
.stdout_is_templated_fixture(expected_test_file_path, &[("{last_modified_time}", &value)]);
new_ucmd!()
.args(&[
@ -371,7 +332,7 @@ fn test_with_column_across_option_and_column_separator() {
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path1,
vec![(&"{last_modified_time}".to_string(), &value)],
&[("{last_modified_time}", &value)],
);
}
@ -382,25 +343,25 @@ fn test_with_mpr() {
let expected_test_file_path = "mpr.log.expected";
let expected_test_file_path1 = "mpr1.log.expected";
let expected_test_file_path2 = "mpr2.log.expected";
let now = now_time();
let start = Local::now();
new_ucmd!()
.args(&["--pages=1:2", "-m", "-n", test_file_path, test_file_path1])
.succeeds()
.stdout_is_templated_fixture(
.stdout_is_templated_fixture_any(
expected_test_file_path,
vec![(&"{last_modified_time}".to_string(), &now)],
&valid_last_modified_template_vars(start),
);
let now = now_time();
let start = Local::now();
new_ucmd!()
.args(&["--pages=2:4", "-m", "-n", test_file_path, test_file_path1])
.succeeds()
.stdout_is_templated_fixture(
.stdout_is_templated_fixture_any(
expected_test_file_path1,
vec![(&"{last_modified_time}".to_string(), &now)],
&valid_last_modified_template_vars(start),
);
let now = now_time();
let start = Local::now();
new_ucmd!()
.args(&[
"--pages=1:2",
@ -413,9 +374,9 @@ fn test_with_mpr() {
test_file_path,
])
.succeeds()
.stdout_is_templated_fixture(
.stdout_is_templated_fixture_any(
expected_test_file_path2,
vec![(&"{last_modified_time}".to_string(), &now)],
&valid_last_modified_template_vars(start),
);
}
@ -452,10 +413,7 @@ fn test_with_offset_space_option() {
test_file_path,
])
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path,
vec![(&"{last_modified_time}".to_string(), &value)],
);
.stdout_is_templated_fixture(expected_test_file_path, &[("{last_modified_time}", &value)]);
}
#[test]
@ -497,9 +455,9 @@ fn test_with_pr_core_utils_tests() {
scenario_with_expected_status.stdout_is_templated_fixture(
test_file_path,
vec![
(&"{last_modified_time}".to_string(), &value),
(&"{file_name}".to_string(), &input_file_path.to_string()),
&[
("{last_modified_time}", &value),
("{file_name}", input_file_path),
],
);
}
@ -511,12 +469,12 @@ fn test_with_join_lines_option() {
let test_file_2 = "test.log";
let expected_file_path = "joined.log.expected";
let mut scenario = new_ucmd!();
let now = now_time();
let start = Local::now();
scenario
.args(&["+1:2", "-J", "-m", test_file_1, test_file_2])
.run()
.stdout_is_templated_fixture(
.stdout_is_templated_fixture_any(
expected_file_path,
vec![(&"{last_modified_time}".to_string(), &now)],
&valid_last_modified_template_vars(start),
);
}

View file

@ -223,6 +223,18 @@ impl CmdResult {
self
}
/// like `stdout_is`, but succeeds if any elements of `expected` matches stdout.
pub fn stdout_is_any<T: AsRef<str> + std::fmt::Debug>(&self, expected: Vec<T>) -> &CmdResult {
if !expected.iter().any(|msg| self.stdout_str() == msg.as_ref()) {
panic!(
"stdout was {}\nExpected any of {:#?}",
self.stdout_str(),
expected
)
}
self
}
/// Like `stdout_is` but newlines are normalized to `\n`.
pub fn normalized_newlines_stdout_is<T: AsRef<str>>(&self, msg: T) -> &CmdResult {
let msg = msg.as_ref().replace("\r\n", "\n");
@ -247,7 +259,7 @@ impl CmdResult {
pub fn stdout_is_templated_fixture<T: AsRef<OsStr>>(
&self,
file_rel_path: T,
template_vars: Vec<(&String, &String)>,
template_vars: &[(&str, &str)],
) -> &CmdResult {
let mut contents =
String::from_utf8(read_scenario_fixture(&self.tmpd, file_rel_path)).unwrap();
@ -257,6 +269,23 @@ impl CmdResult {
self.stdout_is(contents)
}
/// like `stdout_is_templated_fixture`, but succeeds if any replacement by `template_vars` results in the actual stdout.
pub fn stdout_is_templated_fixture_any<T: AsRef<OsStr>>(
&self,
file_rel_path: T,
template_vars: &[Vec<(String, String)>],
) {
let contents = String::from_utf8(read_scenario_fixture(&self.tmpd, file_rel_path)).unwrap();
let possible_values = template_vars.iter().map(|vars| {
let mut contents = contents.clone();
for kv in vars.iter() {
contents = contents.replace(&kv.0, &kv.1);
}
contents
});
self.stdout_is_any(possible_values.collect());
}
/// asserts that the command resulted in stderr stream output that equals the
/// passed in value, when both are trimmed of trailing whitespace
/// stderr_only is a better choice unless stdout may or will be non-empty