Skip to content

Commit b1061a8

Browse files
committed
Add test to validate the config loading rules
Configs are loaded in the following order: 1. Load configs from the `--config-path` option 2. Travers the directory hierarchy looking for a config file 3. Check the user's `HOME` directory for a config file 4. Check the user's config directory for a config file
1 parent 1b5f8ef commit b1061a8

File tree

1 file changed

+123
-0
lines changed

1 file changed

+123
-0
lines changed

tests/rustfmt/main.rs

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,3 +174,126 @@ fn rustfmt_emits_error_on_line_overflow_true() {
174174
"line formatted, but exceeded maximum width (maximum: 100 (see `max_width` option)"
175175
))
176176
}
177+
178+
#[cfg(not(windows))]
179+
mod load_config {
180+
use super::rustfmt;
181+
use std::path::Path;
182+
183+
/// helper function to write a new rustfmt.toml to a file
184+
fn write_rustfmt_toml<P: AsRef<Path>>(path: P) {
185+
let dir_path = if path.as_ref().is_dir() {
186+
path.as_ref()
187+
} else {
188+
path.as_ref().parent().unwrap()
189+
};
190+
191+
rustfmt(&[
192+
"--print-config=default",
193+
&dir_path.join("rustfmt.toml").display().to_string(),
194+
]);
195+
}
196+
197+
/// helper function to turn an AsRef<Path> into a String
198+
fn path_arg<P: AsRef<Path>>(path: P) -> String {
199+
path.as_ref().display().to_string()
200+
}
201+
202+
macro_rules! assert_using_expected_config {
203+
($file_path:expr) => {
204+
// case where we don't specify a config
205+
// No configs should exist in the file system when calling this case
206+
let (stdout, _stderr) = rustfmt(&["-v", &path_arg($file_path)]);
207+
assert!(!stdout.contains("rustfmt.toml"));
208+
};
209+
210+
($file_path:expr, $config_dir:expr) => {
211+
// case where we expect a config to be implicitly loaded
212+
let (stdout, _stderr) = rustfmt(&["-v", &path_arg($file_path)]);
213+
assert!(stdout.contains(&path_arg($config_dir)));
214+
};
215+
216+
($file_path:expr, "--config-path", $config_path:expr) => {
217+
// case where we explictly set a config and ensure it gets loaded
218+
let (stdout, _stderr) = rustfmt(&[
219+
"-v",
220+
"--config-path",
221+
&path_arg($config_path),
222+
&path_arg($file_path),
223+
]);
224+
assert!(stdout.contains(&path_arg($config_path)));
225+
};
226+
}
227+
/// Ensure that we're loading the correct config when running rustfmt
228+
///
229+
/// Configs are loaded in the following order:
230+
/// 1. Load configs from the `--config-path` option.
231+
/// 2. Travers the directory hierarchy looking for a config file
232+
/// 3. Check the user's `HOME` directory for a config file (could vary by platform)
233+
/// 4. Check the user's config directory for a config file (could vary by platform)
234+
///
235+
/// When no configs are found rustfmt is run with just the default options.
236+
#[test]
237+
fn test_load_config_logic() {
238+
// Create a temporary directory and set it as the new $HOME.
239+
// This sets up a clean environment that we'll use to test the config loading logic
240+
let tmpdir = tempfile::tempdir().unwrap();
241+
let _home_env = tmp_env::set_var("HOME", tmpdir.as_ref());
242+
243+
// Sanity check to make sure that we set the $HOME directory
244+
let home_dir = dirs::home_dir().unwrap();
245+
assert_eq!(tmpdir.as_ref(), home_dir.as_path());
246+
247+
// Create a working directory nested a few levels deep inside the temporary $HOME.
248+
// We want a few directory levels so we can properly test case #2 listed above.
249+
// Set the current working directory to the new path so we don't pick up any rustfmt.toml
250+
// files defined outside our clean environment.
251+
let work_dir = home_dir.join("path").join("to").join("file");
252+
std::fs::create_dir_all(&work_dir).unwrap();
253+
let _current_dir = tmp_env::set_current_dir(&work_dir).unwrap();
254+
255+
// Set up the user's config directory
256+
let mut config_dir = dirs::config_dir().unwrap();
257+
config_dir.push("rustfmt");
258+
std::fs::create_dir_all(&config_dir).unwrap();
259+
260+
// Write a hello world file used for formatting checks in the working directory
261+
let file_path = work_dir.join("test.rs");
262+
std::fs::write(
263+
&file_path,
264+
"fn main() {\n println!(\"Hello world!\");\n}",
265+
)
266+
.unwrap();
267+
268+
// 1. Run rustfmt and make sure we don't load any configs
269+
assert_using_expected_config!(&file_path);
270+
271+
// Write a rustfmt.toml to the users config directory
272+
// 2. Run rustfmt and make sure we load the config from the user's config dir.
273+
// Sinces no other configs exist this one should be used.
274+
write_rustfmt_toml(&config_dir);
275+
assert_using_expected_config!(&file_path, &config_dir);
276+
277+
// Write a rustfmt.toml to the users $HOME directory
278+
// 3. Run rustmft and make sure we load the config from the user's $HOME dir
279+
// Configs in the $HOME dir take precedence over those in the config dir
280+
write_rustfmt_toml(&home_dir);
281+
assert_using_expected_config!(&file_path, &home_dir);
282+
283+
// write a rustfmt.toml to some directory in the `work_dir` hierarchy.
284+
// 4. Run rustfmt and make sure we load the config from the file hierarcy.
285+
// Configs found in the file hierarcy take precedence to those in $HOME and the config dir.
286+
let config_along_path = work_dir.parent().unwrap().parent().unwrap();
287+
write_rustfmt_toml(&config_along_path);
288+
assert_using_expected_config!(&file_path, &config_along_path);
289+
290+
// write a rustfmt.toml outside the working directory hierarchy.
291+
// This ensures it isn't automatically picked up.
292+
// 5. run rustfmt and explicitly set the `--config-path` option to this config file.
293+
// Configs that are explicity set take precedence over all other configs.
294+
let explicit_config_path = home_dir.join("new").join("config").join("path");
295+
std::fs::create_dir_all(&explicit_config_path).unwrap();
296+
write_rustfmt_toml(&explicit_config_path);
297+
assert_using_expected_config!(&file_path, "--config-path", &explicit_config_path);
298+
}
299+
}

0 commit comments

Comments
 (0)