Skip to content

Commit 75b2504

Browse files
committed
Add a test case involving a param file
1 parent 0b0f53e commit 75b2504

File tree

1 file changed

+106
-24
lines changed

1 file changed

+106
-24
lines changed

util/process_wrapper/options.rs

Lines changed: 106 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ pub(crate) fn options() -> Result<Options, OptionError> {
208208
child_args,
209209
&subst_mappings,
210210
require_explicit_unstable_features,
211+
None,
212+
None,
211213
)?;
212214
// Split the executable path from the rest of the arguments.
213215
let (exec_path, args) = child_args.split_first().ok_or_else(|| {
@@ -270,58 +272,89 @@ fn prepare_arg(mut arg: String, subst_mappings: &[(String, String)]) -> String {
270272
arg
271273
}
272274

273-
/// Apply substitutions to the given param file. Returns the new filename and whether any
274-
/// allow-features flags were found.
275+
/// Apply substitutions to the given param file. Returns true iff any allow-features flags were found.
275276
fn prepare_param_file(
276277
filename: &str,
277278
subst_mappings: &[(String, String)],
278-
) -> Result<(String, bool), OptionError> {
279-
let expanded_file = format!("{filename}.expanded");
280-
let format_err = |err: io::Error| {
281-
OptionError::Generic(format!(
282-
"{} writing path: {:?}, current directory: {:?}",
283-
err,
284-
expanded_file,
285-
std::env::current_dir()
286-
))
287-
};
288-
let mut out = io::BufWriter::new(File::create(&expanded_file).map_err(format_err)?);
279+
read_file: &mut impl FnMut(&str) -> Result<Vec<String>, OptionError>,
280+
write_to_file: &mut impl FnMut(&str) -> Result<(), OptionError>,
281+
) -> Result<bool, OptionError> {
289282
fn process_file(
290283
filename: &str,
291-
out: &mut io::BufWriter<File>,
292284
subst_mappings: &[(String, String)],
293-
format_err: &impl Fn(io::Error) -> OptionError,
285+
read_file: &mut impl FnMut(&str) -> Result<Vec<String>, OptionError>,
286+
write_to_file: &mut impl FnMut(&str) -> Result<(), OptionError>,
294287
) -> Result<bool, OptionError> {
295288
let mut has_allow_features_flag = false;
296-
for arg in read_file_to_array(filename).map_err(OptionError::Generic)? {
289+
for arg in read_file(filename)? {
297290
let arg = prepare_arg(arg, subst_mappings);
298291
has_allow_features_flag |= is_allow_features_flag(&arg);
299292
if let Some(arg_file) = arg.strip_prefix('@') {
300-
has_allow_features_flag |= process_file(arg_file, out, subst_mappings, format_err)?;
293+
has_allow_features_flag |=
294+
process_file(arg_file, subst_mappings, read_file, write_to_file)?;
301295
} else {
302-
writeln!(out, "{arg}").map_err(format_err)?;
296+
write_to_file(&arg)?;
303297
}
304298
}
305299
Ok(has_allow_features_flag)
306300
}
307-
let has_allow_features_flag = process_file(filename, &mut out, subst_mappings, &format_err)?;
308-
Ok((expanded_file, has_allow_features_flag))
301+
let has_allow_features_flag = process_file(filename, subst_mappings, read_file, write_to_file)?;
302+
Ok(has_allow_features_flag)
309303
}
310304

311305
/// Apply substitutions to the provided arguments, recursing into param files.
306+
#[allow(clippy::type_complexity)]
312307
fn prepare_args(
313308
args: Vec<String>,
314309
subst_mappings: &[(String, String)],
315310
require_explicit_unstable_features: bool,
311+
read_file: Option<&mut dyn FnMut(&str) -> Result<Vec<String>, OptionError>>,
312+
mut write_file: Option<&mut dyn FnMut(&str, &str) -> Result<(), OptionError>>,
316313
) -> Result<Vec<String>, OptionError> {
317314
let mut allowed_features = false;
318315
let mut processed_args = Vec::<String>::new();
316+
317+
let mut read_file_wrapper = |s: &str| read_file_to_array(s).map_err(OptionError::Generic);
318+
let mut read_file = read_file.unwrap_or(&mut read_file_wrapper);
319+
319320
for arg in args.into_iter() {
320321
let arg = prepare_arg(arg, subst_mappings);
321322
if let Some(param_file) = arg.strip_prefix('@') {
323+
let expanded_file = format!("{param_file}.expanded");
324+
let format_err = |err: io::Error| {
325+
OptionError::Generic(format!(
326+
"{} writing path: {:?}, current directory: {:?}",
327+
err,
328+
expanded_file,
329+
std::env::current_dir()
330+
))
331+
};
332+
333+
enum Writer<'f, F: FnMut(&str, &str) -> Result<(), OptionError>> {
334+
Function(&'f mut F),
335+
BufWriter(io::BufWriter<File>),
336+
}
337+
let mut out = match write_file {
338+
Some(ref mut f) => Writer::Function(f),
339+
None => Writer::BufWriter(io::BufWriter::new(
340+
File::create(&expanded_file).map_err(format_err)?,
341+
)),
342+
};
343+
let mut write_to_file = |s: &str| -> Result<(), OptionError> {
344+
match out {
345+
Writer::Function(ref mut f) => f(&expanded_file, s),
346+
Writer::BufWriter(ref mut bw) => writeln!(bw, "{s}").map_err(format_err),
347+
}
348+
};
349+
322350
// Note that substitutions may also apply to the param file path!
323-
let (file, allowed) = prepare_param_file(param_file, subst_mappings)
324-
.map(|(filename, af)| (format!("@{filename}"), af))?;
351+
let (file, allowed) = prepare_param_file(
352+
param_file,
353+
subst_mappings,
354+
&mut read_file,
355+
&mut write_to_file,
356+
)
357+
.map(|af| (format!("@{expanded_file}"), af))?;
325358
allowed_features |= allowed;
326359
processed_args.push(file);
327360
} else {
@@ -373,7 +406,7 @@ mod test {
373406
fn test_enforce_allow_features_flag_user_didnt_say() {
374407
let args = vec!["rustc".to_string()];
375408
let subst_mappings: Vec<(String, String)> = vec![];
376-
let args = prepare_args(args, &subst_mappings).unwrap();
409+
let args = prepare_args(args, &subst_mappings, true, None, None).unwrap();
377410
assert_eq!(
378411
args,
379412
vec!["rustc".to_string(), "-Zallow-features=".to_string(),]
@@ -387,7 +420,7 @@ mod test {
387420
"-Zallow-features=whitespace_instead_of_curly_braces".to_string(),
388421
];
389422
let subst_mappings: Vec<(String, String)> = vec![];
390-
let args = prepare_args(args, &subst_mappings).unwrap();
423+
let args = prepare_args(args, &subst_mappings, true, None, None).unwrap();
391424
assert_eq!(
392425
args,
393426
vec![
@@ -396,4 +429,53 @@ mod test {
396429
]
397430
);
398431
}
432+
433+
#[test]
434+
fn test_enforce_allow_features_flag_user_requested_something_in_param_file() {
435+
let mut written_files = HashMap::<String, String>::new();
436+
let mut read_files = HashMap::<String, Vec<String>>::new();
437+
read_files.insert(
438+
"rustc_params".to_string(),
439+
vec!["-Zallow-features=whitespace_instead_of_curly_braces".to_string()],
440+
);
441+
442+
let mut read_file = |filename: &str| -> Result<Vec<String>, OptionError> {
443+
read_files
444+
.get(filename)
445+
.cloned()
446+
.ok_or_else(|| OptionError::Generic(format!("file not found: {}", filename)))
447+
};
448+
let mut write_file = |filename: &str, content: &str| -> Result<(), OptionError> {
449+
if let Some(v) = written_files.get_mut(filename) {
450+
v.push_str(content);
451+
} else {
452+
written_files.insert(filename.to_owned(), content.to_owned());
453+
}
454+
Ok(())
455+
};
456+
457+
let args = vec!["rustc".to_string(), "@rustc_params".to_string()];
458+
let subst_mappings: Vec<(String, String)> = vec![];
459+
460+
let args = prepare_args(
461+
args,
462+
&subst_mappings,
463+
true,
464+
Some(&mut read_file),
465+
Some(&mut write_file),
466+
);
467+
468+
assert_eq!(
469+
args.unwrap(),
470+
vec!["rustc".to_string(), "@rustc_params.expanded".to_string(),]
471+
);
472+
473+
assert_eq!(
474+
written_files,
475+
HashMap::<String, String>::from([(
476+
"rustc_params.expanded".to_string(),
477+
"-Zallow-features=whitespace_instead_of_curly_braces".to_string()
478+
)])
479+
);
480+
}
399481
}

0 commit comments

Comments
 (0)