Skip to content

Commit

Permalink
Add test to validate the config loading rules
Browse files Browse the repository at this point in the history
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
  • Loading branch information
ytmimi committed Aug 22, 2022
1 parent 1b5f8ef commit 35130a3
Showing 1 changed file with 119 additions and 0 deletions.
119 changes: 119 additions & 0 deletions tests/rustfmt/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,122 @@ fn rustfmt_emits_error_on_line_overflow_true() {
"line formatted, but exceeded maximum width (maximum: 100 (see `max_width` option)"
))
}

/// helper function to write a new rustfmt.toml to a file
fn write_rustfmt_toml<P: AsRef<Path>>(path: P) {
let dir_path = if path.as_ref().is_dir() {
path.as_ref()
} else {
path.as_ref().parent().unwrap()
};

rustfmt(&[
"--print-config=default",
&dir_path.join("rustfmt.toml").display().to_string(),
]);
}

/// helper function to turn an AsRef<Path> into a String
fn path_arg<P: AsRef<Path>>(path: P) -> String {
path.as_ref().display().to_string()
}

macro_rules! assert_using_expected_config {
($file_path:expr) => {
// case where we don't specify a config
// No configs should exist in the file system when calling this case
let (stdout, _stderr) = rustfmt(&["-v", &path_arg($file_path)]);
assert!(!stdout.contains("rustfmt.toml"));
};

($file_path:expr, $config_dir:expr) => {
// case where we expect a config to be implicitly loaded
let (stdout, _stderr) = rustfmt(&["-v", &path_arg($file_path)]);
assert!(stdout.contains(&path_arg($config_dir)));
};

($file_path:expr, "--config-path", $config_path:expr) => {
// case where we explictly set a config and ensure it gets loaded
let (stdout, _stderr) = rustfmt(&[
"-v",
"--config-path",
&path_arg($config_path),
&path_arg($file_path),
]);
assert!(stdout.contains(&path_arg($config_path)));
};
}

/// Ensure that we're loading the correct config when running rustfmt
///
/// 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 (could vary by platform)
/// 4. Check the user's config directory for a config file (could vary by platform)
///
/// When no configs are found rustfmt is run with just the default options.
#[cfg(not(windows))]
#[test]
fn test_load_config_logic() {
// Create a temporary directory and set it as the new $HOME.
// This sets up a clean environment that we'll use to test the config loading logic
let tmpdir = tempfile::tempdir().unwrap();
let _home_env = tmp_env::set_var("HOME", tmpdir.as_ref());

// Sanity check to make sure that we set the $HOME directory
let home_dir = dirs::home_dir().unwrap();
assert_eq!(tmpdir.as_ref(), home_dir.as_path());

// Create a working directory nested a few levels deep inside the temporary $HOME.
// We want a few directory levels so we can properly test case #2 listed above.
// Set the current working directory to the new path so we don't pick up any rustfmt.toml
// files defined outside our clean environment.
let work_dir = home_dir.join("path").join("to").join("file");
std::fs::create_dir_all(&work_dir).unwrap();
let _current_dir = tmp_env::set_current_dir(&work_dir).unwrap();

// Set up the user's config directory
let mut config_dir = dirs::config_dir().unwrap();
config_dir.push("rustfmt");
std::fs::create_dir_all(&config_dir).unwrap();

// Write a hello world file used for formatting checks in the working directory
let file_path = work_dir.join("test.rs");
std::fs::write(
&file_path,
"fn main() {\n println!(\"Hello world!\");\n}",
)
.unwrap();

// 1. Run rustfmt and make sure we don't load any configs
assert_using_expected_config!(&file_path);

// Write a rustfmt.toml to the users config directory
// 2. Run rustfmt and make sure we load the config from the user's config dir.
// Sinces no other configs exist this one should be used.
write_rustfmt_toml(&config_dir);
assert_using_expected_config!(&file_path, &config_dir);

// Write a rustfmt.toml to the users $HOME directory
// 3. Run rustmft and make sure we load the config from the user's $HOME dir
// Configs in the $HOME dir take precedence over those in the config dir
write_rustfmt_toml(&home_dir);
assert_using_expected_config!(&file_path, &home_dir);

// write a rustfmt.toml to some directory in the `work_dir` hierarchy.
// 4. Run rustfmt and make sure we load the config from the file hierarcy.
// Configs found in the file hierarcy take precedence to those in $HOME and the config dir.
let config_along_path = work_dir.parent().unwrap().parent().unwrap();
write_rustfmt_toml(&config_along_path);
assert_using_expected_config!(&file_path, &config_along_path);

// write a rustfmt.toml outside the working directory hierarchy.
// This ensures it isn't automatically picked up.
// 5. run rustfmt and explicitly set the `--config-path` option to this config file.
// Configs that are explicity set take precedence over all other configs.
let explicit_config_path = home_dir.join("new").join("config").join("path");
std::fs::create_dir_all(&explicit_config_path).unwrap();
write_rustfmt_toml(&explicit_config_path);
assert_using_expected_config!(&file_path, "--config-path", &explicit_config_path);
}

0 comments on commit 35130a3

Please sign in to comment.