Skip to content

Commit bb8f465

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

File tree

1 file changed

+105
-24
lines changed

1 file changed

+105
-24
lines changed

util/process_wrapper/options.rs

Lines changed: 105 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,88 @@ 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.
312306
fn prepare_args(
313307
args: Vec<String>,
314308
subst_mappings: &[(String, String)],
315309
require_explicit_unstable_features: bool,
310+
read_file: Option<&mut dyn FnMut(&str) -> Result<Vec<String>, OptionError>>,
311+
mut write_file: Option<&mut dyn FnMut(&str, &str) -> Result<(), OptionError>>,
316312
) -> Result<Vec<String>, OptionError> {
317313
let mut allowed_features = false;
318314
let mut processed_args = Vec::<String>::new();
315+
316+
let mut read_file_wrapper = |s: &str| read_file_to_array(s).map_err(OptionError::Generic);
317+
let mut read_file = read_file.unwrap_or(&mut read_file_wrapper);
318+
319319
for arg in args.into_iter() {
320320
let arg = prepare_arg(arg, subst_mappings);
321321
if let Some(param_file) = arg.strip_prefix('@') {
322+
let expanded_file = format!("{param_file}.expanded");
323+
let format_err = |err: io::Error| {
324+
OptionError::Generic(format!(
325+
"{} writing path: {:?}, current directory: {:?}",
326+
err,
327+
expanded_file,
328+
std::env::current_dir()
329+
))
330+
};
331+
332+
enum Writer<'f, F: FnMut(&str, &str) -> Result<(), OptionError>> {
333+
Function(&'f mut F),
334+
BufWriter(io::BufWriter<File>),
335+
}
336+
let mut out = match write_file {
337+
Some(ref mut f) => Writer::Function(f),
338+
None => Writer::BufWriter(io::BufWriter::new(
339+
File::create(&expanded_file).map_err(format_err)?,
340+
)),
341+
};
342+
let mut write_to_file = |s: &str| -> Result<(), OptionError> {
343+
match out {
344+
Writer::Function(ref mut f) => f(&expanded_file, &s),
345+
Writer::BufWriter(ref mut bw) => writeln!(bw, "{s}").map_err(format_err),
346+
}
347+
};
348+
322349
// 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))?;
350+
let (file, allowed) = prepare_param_file(
351+
param_file,
352+
subst_mappings,
353+
&mut read_file,
354+
&mut write_to_file,
355+
)
356+
.map(|af| (format!("@{expanded_file}"), af))?;
325357
allowed_features |= allowed;
326358
processed_args.push(file);
327359
} else {
@@ -373,7 +405,7 @@ mod test {
373405
fn test_enforce_allow_features_flag_user_didnt_say() {
374406
let args = vec!["rustc".to_string()];
375407
let subst_mappings: Vec<(String, String)> = vec![];
376-
let args = prepare_args(args, &subst_mappings).unwrap();
408+
let args = prepare_args(args, &subst_mappings, true, None, None).unwrap();
377409
assert_eq!(
378410
args,
379411
vec!["rustc".to_string(), "-Zallow-features=".to_string(),]
@@ -387,7 +419,7 @@ mod test {
387419
"-Zallow-features=whitespace_instead_of_curly_braces".to_string(),
388420
];
389421
let subst_mappings: Vec<(String, String)> = vec![];
390-
let args = prepare_args(args, &subst_mappings).unwrap();
422+
let args = prepare_args(args, &subst_mappings, true, None, None).unwrap();
391423
assert_eq!(
392424
args,
393425
vec![
@@ -396,4 +428,53 @@ mod test {
396428
]
397429
);
398430
}
431+
432+
#[test]
433+
fn test_enforce_allow_features_flag_user_requested_something_in_param_file() {
434+
let mut written_files = HashMap::<String, String>::new();
435+
let mut read_files = HashMap::<String, Vec<String>>::new();
436+
read_files.insert(
437+
"rustc_params".to_string(),
438+
vec!["-Zallow-features=whitespace_instead_of_curly_braces".to_string()],
439+
);
440+
441+
let mut read_file = |filename: &str| -> Result<Vec<String>, OptionError> {
442+
read_files
443+
.get(filename)
444+
.map(Vec::clone)
445+
.ok_or_else(|| OptionError::Generic(format!("file not found: {}", filename)))
446+
};
447+
let mut write_file = |filename: &str, content: &str| -> Result<(), OptionError> {
448+
if let Some(v) = written_files.get_mut(filename) {
449+
v.push_str(content);
450+
} else {
451+
written_files.insert(filename.to_owned(), content.to_owned());
452+
}
453+
Ok(())
454+
};
455+
456+
let args = vec!["rustc".to_string(), "@rustc_params".to_string()];
457+
let subst_mappings: Vec<(String, String)> = vec![];
458+
459+
let args = prepare_args(
460+
args,
461+
&subst_mappings,
462+
true,
463+
Some(&mut read_file),
464+
Some(&mut write_file),
465+
);
466+
467+
assert_eq!(
468+
args.unwrap(),
469+
vec!["rustc".to_string(), "@rustc_params.expanded".to_string(),]
470+
);
471+
472+
assert_eq!(
473+
written_files,
474+
HashMap::<String, String>::from([(
475+
"rustc_params.expanded".to_string(),
476+
"-Zallow-features=whitespace_instead_of_curly_braces".to_string()
477+
)])
478+
);
479+
}
399480
}

0 commit comments

Comments
 (0)