Skip to content

Commit a21f1b6

Browse files
ytmimicalebcartwright
authored andcommitted
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() { ... }
1 parent 67fd9ec commit a21f1b6

File tree

4 files changed

+88
-68
lines changed

4 files changed

+88
-68
lines changed

config_proc_macro/src/lib.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ mod item_enum;
88
mod item_struct;
99
mod utils;
1010

11+
use std::str::FromStr;
12+
1113
use proc_macro::TokenStream;
1214
use syn::parse_macro_input;
1315

@@ -23,3 +25,43 @@ pub fn config_type(_args: TokenStream, input: TokenStream) -> TokenStream {
2325

2426
TokenStream::from(output)
2527
}
28+
29+
/// Used to conditionally output the TokenStream for tests that need to be run on nightly only.
30+
///
31+
/// ```rust
32+
/// #[nightly_only_test]
33+
/// #[test]
34+
/// fn test_needs_nightly_rustfmt() {
35+
/// assert!(true);
36+
/// }
37+
/// ```
38+
#[proc_macro_attribute]
39+
pub fn nightly_only_test(_args: TokenStream, input: TokenStream) -> TokenStream {
40+
// if CFG_RELEASE_CHANNEL is not set we default to nightly, hence why the default is true
41+
if option_env!("CFG_RELEASE_CHANNEL").map_or(true, |c| c == "nightly" || c == "dev") {
42+
input
43+
} else {
44+
// output an empty token stream if CFG_RELEASE_CHANNEL is not set to "nightly" or "dev"
45+
TokenStream::from_str("").unwrap()
46+
}
47+
}
48+
49+
/// Used to conditionally output the TokenStream for tests that need to be run on stable only.
50+
///
51+
/// ```rust
52+
/// #[stable_only_test]
53+
/// #[test]
54+
/// fn test_needs_stable_rustfmt() {
55+
/// assert!(true);
56+
/// }
57+
/// ```
58+
#[proc_macro_attribute]
59+
pub fn stable_only_test(_args: TokenStream, input: TokenStream) -> TokenStream {
60+
// if CFG_RELEASE_CHANNEL is not set we default to nightly, hence why the default is false
61+
if option_env!("CFG_RELEASE_CHANNEL").map_or(false, |c| c == "stable") {
62+
input
63+
} else {
64+
// output an empty token stream if CFG_RELEASE_CHANNEL is not set or is not 'stable'
65+
TokenStream::from_str("").unwrap()
66+
}
67+
}

src/config/mod.rs

Lines changed: 36 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,8 @@ mod test {
405405
use super::*;
406406
use std::str;
407407

408+
use rustfmt_config_proc_macro::{nightly_only_test, stable_only_test};
409+
408410
#[allow(dead_code)]
409411
mod mock {
410412
use super::super::*;
@@ -525,21 +527,17 @@ mod test {
525527
assert!(config.license_template.is_none());
526528
}
527529

530+
#[nightly_only_test]
528531
#[test]
529532
fn test_valid_license_template_path() {
530-
if !crate::is_nightly_channel!() {
531-
return;
532-
}
533533
let toml = r#"license_template_path = "tests/license-template/lt.txt""#;
534534
let config = Config::from_toml(toml, Path::new("")).unwrap();
535535
assert!(config.license_template.is_some());
536536
}
537537

538+
#[nightly_only_test]
538539
#[test]
539540
fn test_override_existing_license_with_no_license() {
540-
if !crate::is_nightly_channel!() {
541-
return;
542-
}
543541
let toml = r#"license_template_path = "tests/license-template/lt.txt""#;
544542
let mut config = Config::from_toml(toml, Path::new("")).unwrap();
545543
assert!(config.license_template.is_some());
@@ -634,48 +632,42 @@ make_backup = false
634632
assert_eq!(&toml, &default_config);
635633
}
636634

637-
// FIXME(#2183): these tests cannot be run in parallel because they use env vars.
638-
// #[test]
639-
// fn test_as_not_nightly_channel() {
640-
// let mut config = Config::default();
641-
// assert_eq!(config.was_set().unstable_features(), false);
642-
// config.set().unstable_features(true);
643-
// assert_eq!(config.was_set().unstable_features(), false);
644-
// }
645-
646-
// #[test]
647-
// fn test_as_nightly_channel() {
648-
// let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from(""));
649-
// ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly");
650-
// let mut config = Config::default();
651-
// config.set().unstable_features(true);
652-
// assert_eq!(config.was_set().unstable_features(), false);
653-
// config.set().unstable_features(true);
654-
// assert_eq!(config.unstable_features(), true);
655-
// ::std::env::set_var("CFG_RELEASE_CHANNEL", v);
656-
// }
657-
658-
// #[test]
659-
// fn test_unstable_from_toml() {
660-
// let mut config = Config::from_toml("unstable_features = true").unwrap();
661-
// assert_eq!(config.was_set().unstable_features(), false);
662-
// let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from(""));
663-
// ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly");
664-
// config = Config::from_toml("unstable_features = true").unwrap();
665-
// assert_eq!(config.was_set().unstable_features(), true);
666-
// assert_eq!(config.unstable_features(), true);
667-
// ::std::env::set_var("CFG_RELEASE_CHANNEL", v);
668-
// }
635+
#[stable_only_test]
636+
#[test]
637+
fn test_as_not_nightly_channel() {
638+
let mut config = Config::default();
639+
assert_eq!(config.was_set().unstable_features(), false);
640+
config.set().unstable_features(true);
641+
assert_eq!(config.was_set().unstable_features(), false);
642+
}
643+
644+
#[nightly_only_test]
645+
#[test]
646+
fn test_as_nightly_channel() {
647+
let mut config = Config::default();
648+
config.set().unstable_features(true);
649+
// When we don't set the config from toml or command line options it
650+
// doesn't get marked as set by the user.
651+
assert_eq!(config.was_set().unstable_features(), false);
652+
config.set().unstable_features(true);
653+
assert_eq!(config.unstable_features(), true);
654+
}
655+
656+
#[nightly_only_test]
657+
#[test]
658+
fn test_unstable_from_toml() {
659+
let config = Config::from_toml("unstable_features = true", Path::new("")).unwrap();
660+
assert_eq!(config.was_set().unstable_features(), true);
661+
assert_eq!(config.unstable_features(), true);
662+
}
669663

670664
#[cfg(test)]
671665
mod deprecated_option_merge_imports {
672666
use super::*;
673667

668+
#[nightly_only_test]
674669
#[test]
675670
fn test_old_option_set() {
676-
if !crate::is_nightly_channel!() {
677-
return;
678-
}
679671
let toml = r#"
680672
unstable_features = true
681673
merge_imports = true
@@ -684,11 +676,9 @@ make_backup = false
684676
assert_eq!(config.imports_granularity(), ImportGranularity::Crate);
685677
}
686678

679+
#[nightly_only_test]
687680
#[test]
688681
fn test_both_set() {
689-
if !crate::is_nightly_channel!() {
690-
return;
691-
}
692682
let toml = r#"
693683
unstable_features = true
694684
merge_imports = true
@@ -698,11 +688,9 @@ make_backup = false
698688
assert_eq!(config.imports_granularity(), ImportGranularity::Preserve);
699689
}
700690

691+
#[nightly_only_test]
701692
#[test]
702693
fn test_new_overridden() {
703-
if !crate::is_nightly_channel!() {
704-
return;
705-
}
706694
let toml = r#"
707695
unstable_features = true
708696
merge_imports = true
@@ -712,11 +700,9 @@ make_backup = false
712700
assert_eq!(config.imports_granularity(), ImportGranularity::Preserve);
713701
}
714702

703+
#[nightly_only_test]
715704
#[test]
716705
fn test_old_overridden() {
717-
if !crate::is_nightly_channel!() {
718-
return;
719-
}
720706
let toml = r#"
721707
unstable_features = true
722708
imports_granularity = "Module"

src/syntux/session.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -286,10 +286,11 @@ impl LineRangeUtils for ParseSess {
286286
mod tests {
287287
use super::*;
288288

289+
use rustfmt_config_proc_macro::nightly_only_test;
290+
289291
mod emitter {
290292
use super::*;
291293
use crate::config::IgnoreList;
292-
use crate::is_nightly_channel;
293294
use crate::utils::mk_sp;
294295
use rustc_span::{FileName as SourceMapFileName, MultiSpan, RealFileName, DUMMY_SP};
295296
use std::path::PathBuf;
@@ -371,11 +372,9 @@ mod tests {
371372
assert_eq!(can_reset_errors.load(Ordering::Acquire), false);
372373
}
373374

375+
#[nightly_only_test]
374376
#[test]
375377
fn handles_recoverable_parse_error_in_ignored_file() {
376-
if !is_nightly_channel!() {
377-
return;
378-
}
379378
let num_emitted_errors = Lrc::new(AtomicU32::new(0));
380379
let can_reset_errors = Lrc::new(AtomicBool::new(false));
381380
let ignore_list = get_ignore_list(r#"ignore = ["foo.rs"]"#);
@@ -398,11 +397,9 @@ mod tests {
398397
assert_eq!(can_reset_errors.load(Ordering::Acquire), true);
399398
}
400399

400+
#[nightly_only_test]
401401
#[test]
402402
fn handles_recoverable_parse_error_in_non_ignored_file() {
403-
if !is_nightly_channel!() {
404-
return;
405-
}
406403
let num_emitted_errors = Lrc::new(AtomicU32::new(0));
407404
let can_reset_errors = Lrc::new(AtomicBool::new(false));
408405
let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty()));
@@ -424,11 +421,9 @@ mod tests {
424421
assert_eq!(can_reset_errors.load(Ordering::Acquire), false);
425422
}
426423

424+
#[nightly_only_test]
427425
#[test]
428426
fn handles_mix_of_recoverable_parse_error() {
429-
if !is_nightly_channel!() {
430-
return;
431-
}
432427
let num_emitted_errors = Lrc::new(AtomicU32::new(0));
433428
let can_reset_errors = Lrc::new(AtomicBool::new(false));
434429
let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty()));

src/test/mod.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChu
1515
use crate::source_file;
1616
use crate::{is_nightly_channel, FormatReport, FormatReportFormatterBuilder, Input, Session};
1717

18+
use rustfmt_config_proc_macro::nightly_only_test;
19+
1820
mod configuration_snippet;
1921
mod mod_resolver;
2022
mod parser;
@@ -307,14 +309,11 @@ fn assert_output(source: &Path, expected_filename: &Path) {
307309

308310
// Idempotence tests. Files in tests/target are checked to be unaltered by
309311
// rustfmt.
312+
#[nightly_only_test]
310313
#[test]
311314
fn idempotence_tests() {
312315
init_log();
313316
run_test_with(&TestSetting::default(), || {
314-
// these tests require nightly
315-
if !is_nightly_channel!() {
316-
return;
317-
}
318317
// Get all files in the tests/target directory.
319318
let files = get_test_files(Path::new("tests/target"), true);
320319
let (_reports, count, fails) = check_files(files, &None);
@@ -332,13 +331,11 @@ fn idempotence_tests() {
332331

333332
// Run rustfmt on itself. This operation must be idempotent. We also check that
334333
// no warnings are emitted.
334+
// Issue-3443: these tests require nightly
335+
#[nightly_only_test]
335336
#[test]
336337
fn self_tests() {
337338
init_log();
338-
// Issue-3443: these tests require nightly
339-
if !is_nightly_channel!() {
340-
return;
341-
}
342339
let mut files = get_test_files(Path::new("tests"), false);
343340
let bin_directories = vec!["cargo-fmt", "git-rustfmt", "bin", "format-diff"];
344341
for dir in bin_directories {

0 commit comments

Comments
 (0)