about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYacin Tmimi <yacintmimi@gmail.com>2021-11-27 17:14:15 -0500
committerCaleb Cartwright <calebcartwright@users.noreply.github.com>2021-11-27 17:36:18 -0600
commita21f1b6c2a5734f39a1efe3fa84d6475843d14fe (patch)
tree8142f1b04d7ed510ae84ec838b0546cf2abca992
parent67fd9ec3002d269c272f68fa0e34a1cb2ca5fd08 (diff)
downloadrust-a21f1b6c2a5734f39a1efe3fa84d6475843d14fe.tar.gz
rust-a21f1b6c2a5734f39a1efe3fa84d6475843d14fe.zip
Conditionally compile tests based on CFG_RELEASE_CHANNEL env var
Adds the ``nightly_only_test`` and ``stable_only_test`` attribute macros
that prevent or allow certain tests to compile on nightly and stable
respectively. This is achieved through conditionally outputting the
tests TokenStream.

If CFG_RELEASE_CHANNEL is not set, it's assumed that we're running in a
nightly environment.

To mark a test as nightly only:

    #[nightly_only_test]
    #[test]
    fn only_run_on_nightly() {
        ...
    }

To mark a test a stable only:

    #[stable_only_test]
    #[test]
    fn only_run_on_stable() {
        ...
    }
-rw-r--r--config_proc_macro/src/lib.rs42
-rw-r--r--src/config/mod.rs86
-rw-r--r--src/syntux/session.rs15
-rw-r--r--src/test/mod.rs13
4 files changed, 88 insertions, 68 deletions
diff --git a/config_proc_macro/src/lib.rs b/config_proc_macro/src/lib.rs
index 78e7e098ed9..51301821319 100644
--- a/config_proc_macro/src/lib.rs
+++ b/config_proc_macro/src/lib.rs
@@ -8,6 +8,8 @@ mod item_enum;
 mod item_struct;
 mod utils;
 
+use std::str::FromStr;
+
 use proc_macro::TokenStream;
 use syn::parse_macro_input;
 
@@ -23,3 +25,43 @@ pub fn config_type(_args: TokenStream, input: TokenStream) -> TokenStream {
 
     TokenStream::from(output)
 }
+
+/// Used to conditionally output the TokenStream for tests that need to be run on nightly only.
+///
+/// ```rust
+/// #[nightly_only_test]
+/// #[test]
+/// fn test_needs_nightly_rustfmt() {
+///   assert!(true);
+/// }
+/// ```
+#[proc_macro_attribute]
+pub fn nightly_only_test(_args: TokenStream, input: TokenStream) -> TokenStream {
+    // if CFG_RELEASE_CHANNEL is not set we default to nightly, hence why the default is true
+    if option_env!("CFG_RELEASE_CHANNEL").map_or(true, |c| c == "nightly" || c == "dev") {
+        input
+    } else {
+        // output an empty token stream if CFG_RELEASE_CHANNEL is not set to "nightly" or "dev"
+        TokenStream::from_str("").unwrap()
+    }
+}
+
+/// Used to conditionally output the TokenStream for tests that need to be run on stable only.
+///
+/// ```rust
+/// #[stable_only_test]
+/// #[test]
+/// fn test_needs_stable_rustfmt() {
+///   assert!(true);
+/// }
+/// ```
+#[proc_macro_attribute]
+pub fn stable_only_test(_args: TokenStream, input: TokenStream) -> TokenStream {
+    // if CFG_RELEASE_CHANNEL is not set we default to nightly, hence why the default is false
+    if option_env!("CFG_RELEASE_CHANNEL").map_or(false, |c| c == "stable") {
+        input
+    } else {
+        // output an empty token stream if CFG_RELEASE_CHANNEL is not set or is not 'stable'
+        TokenStream::from_str("").unwrap()
+    }
+}
diff --git a/src/config/mod.rs b/src/config/mod.rs
index c5419d860c9..5dbe532ac38 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -405,6 +405,8 @@ mod test {
     use super::*;
     use std::str;
 
+    use rustfmt_config_proc_macro::{nightly_only_test, stable_only_test};
+
     #[allow(dead_code)]
     mod mock {
         use super::super::*;
@@ -525,21 +527,17 @@ mod test {
         assert!(config.license_template.is_none());
     }
 
+    #[nightly_only_test]
     #[test]
     fn test_valid_license_template_path() {
-        if !crate::is_nightly_channel!() {
-            return;
-        }
         let toml = r#"license_template_path = "tests/license-template/lt.txt""#;
         let config = Config::from_toml(toml, Path::new("")).unwrap();
         assert!(config.license_template.is_some());
     }
 
+    #[nightly_only_test]
     #[test]
     fn test_override_existing_license_with_no_license() {
-        if !crate::is_nightly_channel!() {
-            return;
-        }
         let toml = r#"license_template_path = "tests/license-template/lt.txt""#;
         let mut config = Config::from_toml(toml, Path::new("")).unwrap();
         assert!(config.license_template.is_some());
@@ -634,48 +632,42 @@ make_backup = false
         assert_eq!(&toml, &default_config);
     }
 
-    // FIXME(#2183): these tests cannot be run in parallel because they use env vars.
-    // #[test]
-    // fn test_as_not_nightly_channel() {
-    //     let mut config = Config::default();
-    //     assert_eq!(config.was_set().unstable_features(), false);
-    //     config.set().unstable_features(true);
-    //     assert_eq!(config.was_set().unstable_features(), false);
-    // }
-
-    // #[test]
-    // fn test_as_nightly_channel() {
-    //     let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from(""));
-    //     ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly");
-    //     let mut config = Config::default();
-    //     config.set().unstable_features(true);
-    //     assert_eq!(config.was_set().unstable_features(), false);
-    //     config.set().unstable_features(true);
-    //     assert_eq!(config.unstable_features(), true);
-    //     ::std::env::set_var("CFG_RELEASE_CHANNEL", v);
-    // }
-
-    // #[test]
-    // fn test_unstable_from_toml() {
-    //     let mut config = Config::from_toml("unstable_features = true").unwrap();
-    //     assert_eq!(config.was_set().unstable_features(), false);
-    //     let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from(""));
-    //     ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly");
-    //     config = Config::from_toml("unstable_features = true").unwrap();
-    //     assert_eq!(config.was_set().unstable_features(), true);
-    //     assert_eq!(config.unstable_features(), true);
-    //     ::std::env::set_var("CFG_RELEASE_CHANNEL", v);
-    // }
+    #[stable_only_test]
+    #[test]
+    fn test_as_not_nightly_channel() {
+        let mut config = Config::default();
+        assert_eq!(config.was_set().unstable_features(), false);
+        config.set().unstable_features(true);
+        assert_eq!(config.was_set().unstable_features(), false);
+    }
+
+    #[nightly_only_test]
+    #[test]
+    fn test_as_nightly_channel() {
+        let mut config = Config::default();
+        config.set().unstable_features(true);
+        // When we don't set the config from toml or command line options it
+        // doesn't get marked as set by the user.
+        assert_eq!(config.was_set().unstable_features(), false);
+        config.set().unstable_features(true);
+        assert_eq!(config.unstable_features(), true);
+    }
+
+    #[nightly_only_test]
+    #[test]
+    fn test_unstable_from_toml() {
+        let config = Config::from_toml("unstable_features = true", Path::new("")).unwrap();
+        assert_eq!(config.was_set().unstable_features(), true);
+        assert_eq!(config.unstable_features(), true);
+    }
 
     #[cfg(test)]
     mod deprecated_option_merge_imports {
         use super::*;
 
+        #[nightly_only_test]
         #[test]
         fn test_old_option_set() {
-            if !crate::is_nightly_channel!() {
-                return;
-            }
             let toml = r#"
                 unstable_features = true
                 merge_imports = true
@@ -684,11 +676,9 @@ make_backup = false
             assert_eq!(config.imports_granularity(), ImportGranularity::Crate);
         }
 
+        #[nightly_only_test]
         #[test]
         fn test_both_set() {
-            if !crate::is_nightly_channel!() {
-                return;
-            }
             let toml = r#"
                 unstable_features = true
                 merge_imports = true
@@ -698,11 +688,9 @@ make_backup = false
             assert_eq!(config.imports_granularity(), ImportGranularity::Preserve);
         }
 
+        #[nightly_only_test]
         #[test]
         fn test_new_overridden() {
-            if !crate::is_nightly_channel!() {
-                return;
-            }
             let toml = r#"
                 unstable_features = true
                 merge_imports = true
@@ -712,11 +700,9 @@ make_backup = false
             assert_eq!(config.imports_granularity(), ImportGranularity::Preserve);
         }
 
+        #[nightly_only_test]
         #[test]
         fn test_old_overridden() {
-            if !crate::is_nightly_channel!() {
-                return;
-            }
             let toml = r#"
                 unstable_features = true
                 imports_granularity = "Module"
diff --git a/src/syntux/session.rs b/src/syntux/session.rs
index cdb4893d443..dd7c7352686 100644
--- a/src/syntux/session.rs
+++ b/src/syntux/session.rs
@@ -286,10 +286,11 @@ impl LineRangeUtils for ParseSess {
 mod tests {
     use super::*;
 
+    use rustfmt_config_proc_macro::nightly_only_test;
+
     mod emitter {
         use super::*;
         use crate::config::IgnoreList;
-        use crate::is_nightly_channel;
         use crate::utils::mk_sp;
         use rustc_span::{FileName as SourceMapFileName, MultiSpan, RealFileName, DUMMY_SP};
         use std::path::PathBuf;
@@ -371,11 +372,9 @@ mod tests {
             assert_eq!(can_reset_errors.load(Ordering::Acquire), false);
         }
 
+        #[nightly_only_test]
         #[test]
         fn handles_recoverable_parse_error_in_ignored_file() {
-            if !is_nightly_channel!() {
-                return;
-            }
             let num_emitted_errors = Lrc::new(AtomicU32::new(0));
             let can_reset_errors = Lrc::new(AtomicBool::new(false));
             let ignore_list = get_ignore_list(r#"ignore = ["foo.rs"]"#);
@@ -398,11 +397,9 @@ mod tests {
             assert_eq!(can_reset_errors.load(Ordering::Acquire), true);
         }
 
+        #[nightly_only_test]
         #[test]
         fn handles_recoverable_parse_error_in_non_ignored_file() {
-            if !is_nightly_channel!() {
-                return;
-            }
             let num_emitted_errors = Lrc::new(AtomicU32::new(0));
             let can_reset_errors = Lrc::new(AtomicBool::new(false));
             let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty()));
@@ -424,11 +421,9 @@ mod tests {
             assert_eq!(can_reset_errors.load(Ordering::Acquire), false);
         }
 
+        #[nightly_only_test]
         #[test]
         fn handles_mix_of_recoverable_parse_error() {
-            if !is_nightly_channel!() {
-                return;
-            }
             let num_emitted_errors = Lrc::new(AtomicU32::new(0));
             let can_reset_errors = Lrc::new(AtomicBool::new(false));
             let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty()));
diff --git a/src/test/mod.rs b/src/test/mod.rs
index e2620508c34..cceb28dfea6 100644
--- a/src/test/mod.rs
+++ b/src/test/mod.rs
@@ -15,6 +15,8 @@ use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChu
 use crate::source_file;
 use crate::{is_nightly_channel, FormatReport, FormatReportFormatterBuilder, Input, Session};
 
+use rustfmt_config_proc_macro::nightly_only_test;
+
 mod configuration_snippet;
 mod mod_resolver;
 mod parser;
@@ -307,14 +309,11 @@ fn assert_output(source: &Path, expected_filename: &Path) {
 
 // Idempotence tests. Files in tests/target are checked to be unaltered by
 // rustfmt.
+#[nightly_only_test]
 #[test]
 fn idempotence_tests() {
     init_log();
     run_test_with(&TestSetting::default(), || {
-        // these tests require nightly
-        if !is_nightly_channel!() {
-            return;
-        }
         // Get all files in the tests/target directory.
         let files = get_test_files(Path::new("tests/target"), true);
         let (_reports, count, fails) = check_files(files, &None);
@@ -332,13 +331,11 @@ fn idempotence_tests() {
 
 // Run rustfmt on itself. This operation must be idempotent. We also check that
 // no warnings are emitted.
+// Issue-3443: these tests require nightly
+#[nightly_only_test]
 #[test]
 fn self_tests() {
     init_log();
-    // Issue-3443: these tests require nightly
-    if !is_nightly_channel!() {
-        return;
-    }
     let mut files = get_test_files(Path::new("tests"), false);
     let bin_directories = vec!["cargo-fmt", "git-rustfmt", "bin", "format-diff"];
     for dir in bin_directories {