1
Fork 0

auto merge of #17506 : sfackler/rust/cfg-attr, r=alexcrichton

cc #17490 

Reopening of #16230
This commit is contained in:
bors 2014-09-27 01:37:53 +00:00
commit 43d7d7c15e
20 changed files with 143 additions and 20 deletions

View file

@ -72,8 +72,8 @@ is not used.
Tests that should not be run can be annotated with the `ignore` Tests that should not be run can be annotated with the `ignore`
attribute. The existence of these tests will be noted in the test attribute. The existence of these tests will be noted in the test
runner output, but the test will not be run. Tests can also be ignored runner output, but the test will not be run. Tests can also be ignored
by configuration so, for example, to ignore a test on windows you can by configuration using the `cfg_attr` attribute so, for example, to ignore a
write `#[ignore(cfg(target_os = "win32"))]`. test on windows you can write `#[cfg_attr(windows, ignore)]`.
Tests that are intended to fail can be annotated with the Tests that are intended to fail can be annotated with the
`should_fail` attribute. The test will be run, and if it causes its `should_fail` attribute. The test will be run, and if it causes its

View file

@ -506,7 +506,7 @@ mod tests {
use std::os; use std::os;
use std::rt::rtio::{RtioFileStream, SeekSet}; use std::rt::rtio::{RtioFileStream, SeekSet};
#[ignore(cfg(target_os = "freebsd"))] // hmm, maybe pipes have a tiny buffer #[cfg_attr(target_os = "freebsd", ignore)] // hmm, maybe pipes have a tiny buffer
#[test] #[test]
fn test_file_desc() { fn test_file_desc() {
// Run this test with some pipes so we don't have to mess around with // Run this test with some pipes so we don't have to mess around with

View file

@ -219,7 +219,7 @@ mod test {
} }
#[test] #[test]
#[ignore(cfg(target_arch = "x86"))] #[cfg_attr(target_arch = "x86", ignore)]
// FIXME #7158: (maybe?) currently failing on x86. // FIXME #7158: (maybe?) currently failing on x86.
fn test_norm() { fn test_norm() {
fn test(c: Complex64, ns: f64) { fn test(c: Complex64, ns: f64) {

View file

@ -1085,7 +1085,7 @@ mod test {
} }
#[test] #[test]
#[ignore(cfg(windows))] // FIXME(#10102) server never sees second packet #[cfg_attr(windows, ignore)] // FIXME(#10102) server never sees second packet
fn test_udp_twice() { fn test_udp_twice() {
let server_addr = ::next_test_ip4(); let server_addr = ::next_test_ip4();
let client_addr = ::next_test_ip4(); let client_addr = ::next_test_ip4();

View file

@ -3352,7 +3352,7 @@ mod tests {
} }
} }
#[test] #[test]
#[ignore(cfg(target_word_size = "32"))] // FIXME(#14064) #[cfg_attr(target_word_size = "32", ignore)] // FIXME(#14064)
fn test_streaming_parser() { fn test_streaming_parser() {
assert_stream_equal( assert_stream_equal(
r#"{ "foo":"bar", "array" : [0, 1, 2, 3, 4, 5], "idents":[null,true,false]}"#, r#"{ "foo":"bar", "array" : [0, 1, 2, 3, 4, 5], "idents":[null,true,false]}"#,
@ -3388,7 +3388,7 @@ mod tests {
} }
#[test] #[test]
#[ignore(cfg(target_word_size = "32"))] // FIXME(#14064) #[cfg_attr(target_word_size = "32", ignore)] // FIXME(#14064)
fn test_read_object_streaming() { fn test_read_object_streaming() {
assert_eq!(last_event("{ "), Error(SyntaxError(EOFWhileParsingObject, 1, 3))); assert_eq!(last_event("{ "), Error(SyntaxError(EOFWhileParsingObject, 1, 3)));
assert_eq!(last_event("{1"), Error(SyntaxError(KeyMustBeAString, 1, 2))); assert_eq!(last_event("{1"), Error(SyntaxError(KeyMustBeAString, 1, 2)));
@ -3461,7 +3461,7 @@ mod tests {
); );
} }
#[test] #[test]
#[ignore(cfg(target_word_size = "32"))] // FIXME(#14064) #[cfg_attr(target_word_size = "32", ignore)] // FIXME(#14064)
fn test_read_list_streaming() { fn test_read_list_streaming() {
assert_stream_equal( assert_stream_equal(
"[]", "[]",

View file

@ -162,8 +162,7 @@ mod test {
use mem; use mem;
#[test] #[test]
#[ignore(cfg(windows))] // FIXME #8818 #[cfg_attr(any(windows, target_os = "android"), ignore)] // FIXME #8818, #10379
#[ignore(cfg(target_os="android"))] // FIXME(#10379)
fn test_loading_cosine() { fn test_loading_cosine() {
// The math library does not need to be loaded since it is already // The math library does not need to be loaded since it is already
// statically linked in // statically linked in

View file

@ -320,7 +320,7 @@ mod tests {
}, proc(_client) { }, proc(_client) {
// drop the client // drop the client
}) })
} #[ignore(cfg(windows))]) // FIXME(#12516) } #[cfg_attr(windows, ignore)]) // FIXME(#12516)
iotest!(fn write_begone() { iotest!(fn write_begone() {
smalltest(proc(mut server) { smalltest(proc(mut server) {

View file

@ -533,7 +533,7 @@ mod test {
Ok(..) => fail!(), Ok(..) => fail!(),
Err(e) => assert_eq!(e.kind, PermissionDenied), Err(e) => assert_eq!(e.kind, PermissionDenied),
} }
} #[ignore(cfg(windows))] #[ignore(cfg(target_os = "android"))]) } #[cfg_attr(any(windows, target_os = "android"), ignore)])
iotest!(fn connect_error() { iotest!(fn connect_error() {
match TcpStream::connect("0.0.0.0", 1) { match TcpStream::connect("0.0.0.0", 1) {

View file

@ -273,7 +273,7 @@ mod test {
Ok(..) => fail!(), Ok(..) => fail!(),
Err(e) => assert_eq!(e.kind, PermissionDenied), Err(e) => assert_eq!(e.kind, PermissionDenied),
} }
} #[ignore(cfg(windows))] #[ignore(cfg(target_os = "android"))]) } #[cfg_attr(any(windows, target_os = "android"), ignore)])
iotest!(fn socket_smoke_test_ip4() { iotest!(fn socket_smoke_test_ip4() {
let server_ip = next_test_ip4(); let server_ip = next_test_ip4();

View file

@ -766,7 +766,7 @@ mod tests {
assert_eq!((-0f32).frexp(), (-0f32, 0)); assert_eq!((-0f32).frexp(), (-0f32, 0));
} }
#[test] #[ignore(cfg(windows))] // FIXME #8755 #[test] #[cfg_attr(windows, ignore)] // FIXME #8755
fn test_frexp_nowin() { fn test_frexp_nowin() {
let inf: f32 = Float::infinity(); let inf: f32 = Float::infinity();
let neg_inf: f32 = Float::neg_infinity(); let neg_inf: f32 = Float::neg_infinity();

View file

@ -768,7 +768,7 @@ mod tests {
assert_eq!((-0f64).frexp(), (-0f64, 0)); assert_eq!((-0f64).frexp(), (-0f64, 0));
} }
#[test] #[ignore(cfg(windows))] // FIXME #8755 #[test] #[cfg_attr(windows, ignore)] // FIXME #8755
fn test_frexp_nowin() { fn test_frexp_nowin() {
let inf: f64 = Float::infinity(); let inf: f64 = Float::infinity();
let neg_inf: f64 = Float::neg_infinity(); let neg_inf: f64 = Float::neg_infinity();

View file

@ -600,7 +600,7 @@ mod tests {
} }
#[test] #[test]
#[ignore(cfg(windows))] // apparently windows scheduling is weird? #[cfg_attr(windows, ignore)] // apparently windows scheduling is weird?
fn no_starvation() { fn no_starvation() {
static AMT: int = 10000; static AMT: int = 10000;
static NTHREADS: int = 4; static NTHREADS: int = 4;

View file

@ -439,6 +439,8 @@ fn initial_syntax_expander_table() -> SyntaxEnv {
syntax_expanders.insert(intern("cfg"), syntax_expanders.insert(intern("cfg"),
builtin_normal_expander( builtin_normal_expander(
ext::cfg::expand_cfg)); ext::cfg::expand_cfg));
syntax_expanders.insert(intern("cfg_attr"),
Modifier(box ext::cfg_attr::expand));
syntax_expanders.insert(intern("trace_macros"), syntax_expanders.insert(intern("trace_macros"),
builtin_normal_expander( builtin_normal_expander(
ext::trace_macros::expand_trace_macros)); ext::trace_macros::expand_trace_macros));

View file

@ -0,0 +1,57 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use ast;
use attr;
use codemap::Span;
use ext::base::ExtCtxt;
use ext::build::AstBuilder;
use ptr::P;
pub fn expand(cx: &mut ExtCtxt, sp: Span, mi: &ast::MetaItem, it: P<ast::Item>) -> P<ast::Item> {
let (cfg, attr) = match mi.node {
ast::MetaList(_, ref mis) if mis.len() == 2 => (&mis[0], &mis[1]),
_ => {
cx.span_err(sp, "expected `#[cfg_attr(<cfg pattern>, <attr>)]`");
return it;
}
};
let mut out = (*it).clone();
if cfg_matches(cx, &**cfg) {
out.attrs.push(cx.attribute(attr.span, attr.clone()));
}
P(out)
}
fn cfg_matches(cx: &mut ExtCtxt, cfg: &ast::MetaItem) -> bool {
match cfg.node {
ast::MetaList(ref pred, ref mis) if pred.get() == "any" =>
mis.iter().any(|mi| cfg_matches(cx, &**mi)),
ast::MetaList(ref pred, ref mis) if pred.get() == "all" =>
mis.iter().all(|mi| cfg_matches(cx, &**mi)),
ast::MetaList(ref pred, ref mis) if pred.get() == "not" => {
if mis.len() != 1 {
cx.span_err(cfg.span, format!("expected 1 value, got {}",
mis.len()).as_slice());
return false;
}
!cfg_matches(cx, &*mis[0])
}
ast::MetaList(ref pred, _) => {
cx.span_err(cfg.span,
format!("invalid predicate `{}`", pred).as_slice());
false
},
ast::MetaWord(_) | ast::MetaNameValue(..) =>
attr::contains(cx.cfg.as_slice(), cfg),
}
}

View file

@ -83,6 +83,7 @@ pub mod ext {
pub mod build; pub mod build;
pub mod bytes; pub mod bytes;
pub mod cfg; pub mod cfg;
pub mod cfg_attr;
pub mod concat; pub mod concat;
pub mod concat_idents; pub mod concat_idents;
pub mod deriving; pub mod deriving;

View file

@ -339,6 +339,12 @@ fn is_ignored(cx: &TestCtxt, i: &ast::Item) -> bool {
// check ignore(cfg(foo, bar)) // check ignore(cfg(foo, bar))
attr.check_name("ignore") && match attr.meta_item_list() { attr.check_name("ignore") && match attr.meta_item_list() {
Some(ref cfgs) => { Some(ref cfgs) => {
if cfgs.iter().any(|cfg| cfg.check_name("cfg")) {
cx.span_diagnostic.span_warn(attr.span,
"The use of cfg filters in #[ignore] is \
deprecated. Use #[cfg_attr(<cfg pattern>, \
ignore)] instead.");
}
attr::test_cfg(cx.config.as_slice(), cfgs.iter()) attr::test_cfg(cx.config.as_slice(), cfgs.iter())
} }
None => true None => true

View file

@ -356,8 +356,7 @@ Test Attributes:
#[ignore] - When applied to a function which is already attributed as a #[ignore] - When applied to a function which is already attributed as a
test, then the test runner will ignore these tests during test, then the test runner will ignore these tests during
normal test runs. Running with --ignored will run these normal test runs. Running with --ignored will run these
tests. This may also be written as #[ignore(cfg(...))] to tests.",
ignore the test on certain configurations.",
usage = getopts::usage(message.as_slice(), usage = getopts::usage(message.as_slice(),
optgroups().as_slice())); optgroups().as_slice()));
} }

View file

@ -1564,7 +1564,7 @@ mod tests {
} }
#[test] #[test]
#[ignore(cfg(target_os = "android"))] // FIXME #10958 #[cfg_attr(target_os = "android", ignore)] // FIXME #10958
fn run_tests() { fn run_tests() {
// The tests race on tzset. So instead of having many independent // The tests race on tzset. So instead of having many independent
// tests, we will just call the functions now. // tests, we will just call the functions now.

View file

@ -0,0 +1,59 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags:--cfg set1 --cfg set2
#![allow(dead_code)]
use std::fmt::Show;
struct NotShowable;
#[cfg_attr(set1, deriving(Show))]
struct Set1;
#[cfg_attr(notset, deriving(Show))]
struct Notset(NotShowable);
#[cfg_attr(not(notset), deriving(Show))]
struct NotNotset;
#[cfg_attr(not(set1), deriving(Show))]
struct NotSet1(NotShowable);
#[cfg_attr(all(set1, set2), deriving(Show))]
struct AllSet1Set2;
#[cfg_attr(all(set1, notset), deriving(Show))]
struct AllSet1Notset(NotShowable);
#[cfg_attr(any(set1, notset), deriving(Show))]
struct AnySet1Notset;
#[cfg_attr(any(notset, notset2), deriving(Show))]
struct AnyNotsetNotset2(NotShowable);
#[cfg_attr(all(not(notset), any(set1, notset)), deriving(Show))]
struct Complex;
#[cfg_attr(any(notset, not(any(set1, notset))), deriving(Show))]
struct ComplexNot(NotShowable);
#[cfg_attr(any(target_endian = "little", target_endian = "big"), deriving(Show))]
struct KeyValue;
fn is_show<T: Show>() {}
fn main() {
is_show::<Set1>();
is_show::<NotNotset>();
is_show::<AllSet1Set2>();
is_show::<AnySet1Notset>();
is_show::<Complex>();
is_show::<KeyValue>();
}

View file

@ -80,7 +80,7 @@ iotest!(fn eventual_timeout() {
} }
} }
fail!("never timed out!"); fail!("never timed out!");
} #[ignore(cfg(target_os = "freebsd"))]) } #[cfg_attr(target_os = "freebsd", ignore)])
iotest!(fn timeout_success() { iotest!(fn timeout_success() {
let addr = next_test_ip4(); let addr = next_test_ip4();