compiletest: Support custom normalization rules.

This commit is contained in:
kennytm 2017-07-06 13:54:58 +08:00
parent 18712e6edf
commit 4582ecda64
No known key found for this signature in database
GPG key ID: FEF6C8051D0E013C
9 changed files with 127 additions and 95 deletions

View file

@ -9,10 +9,6 @@
// except according to those terms.
// run-pass
// ignore-x86
// ignore-arm
// ignore-emscripten
// ^ ignore 32-bit targets, as the error message is target-dependent. see PR #41968.
#![warn(variant_size_differences)]
#![allow(dead_code)]
@ -24,26 +20,26 @@ enum Enum1 { }
enum Enum2 { A, B, C }
enum Enum3 { D(isize), E, F }
enum Enum3 { D(i64), E, F }
enum Enum4 { H(isize), I(isize), J }
enum Enum4 { H(i64), I(i64), J }
enum Enum5 {
L(isize, isize, isize, isize), //~ WARNING three times larger
M(isize),
L(i64, i64, i64, i64), //~ WARNING three times larger
M(i64),
N
}
enum Enum6<T, U> {
O(T),
P(U),
Q(isize)
Q(i64)
}
#[allow(variant_size_differences)]
enum Enum7 {
R(isize, isize, isize, isize),
S(isize),
R(i64, i64, i64, i64),
S(i64),
T
}
pub fn main() { }

View file

@ -1,12 +1,12 @@
warning: enum variant is more than three times larger (32 bytes) than the next largest
--> $DIR/enum-size-variance.rs:32:5
--> $DIR/enum-size-variance.rs:28:5
|
32 | L(isize, isize, isize, isize), //~ WARNING three times larger
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
28 | L(i64, i64, i64, i64), //~ WARNING three times larger
| ^^^^^^^^^^^^^^^^^^^^^
|
note: lint level defined here
--> $DIR/enum-size-variance.rs:17:9
--> $DIR/enum-size-variance.rs:13:9
|
17 | #![warn(variant_size_differences)]
13 | #![warn(variant_size_differences)]
| ^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -8,10 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-x86
// ignore-arm
// ignore-emscripten
// ignore 32-bit platforms (test output is different)
// normalize-stderr-32bit: "&str (64 bits)" -> "&str ($STR bits)"
// normalize-stderr-64bit: "&str (128 bits)" -> "&str ($STR bits)"
#![feature(untagged_unions)]
use std::mem::transmute;

View file

@ -22,7 +22,7 @@ error[E0512]: transmute called with types of different sizes
34 | let x: u8 = transmute("test"); //~ ERROR transmute called with types of different sizes
| ^^^^^^^^^
|
= note: source type: &str (128 bits)
= note: source type: &str ($STR bits)
= note: target type: u8 (8 bits)
error[E0512]: transmute called with types of different sizes

View file

@ -8,14 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-x86
// ignore-arm
// ignore-emscripten
// ignore 32-bit platforms (test output is different)
use std::mem;
unsafe fn foo() -> (i32, *const (), Option<fn()>) {
unsafe fn foo() -> (i8, *const (), Option<fn()>) {
let i = mem::transmute(bar);
//~^ ERROR is zero-sized and can't be transmuted
//~^^ NOTE cast with `as` to a pointer instead
@ -46,7 +41,7 @@ unsafe fn bar() {
//~^^ NOTE cast with `as` to a pointer instead
// No error if a coercion would otherwise occur.
mem::transmute::<fn(), u32>(main);
mem::transmute::<fn(), usize>(main);
}
unsafe fn baz() {
@ -63,7 +58,7 @@ unsafe fn baz() {
//~^^ NOTE cast with `as` to a pointer instead
// No error if a coercion would otherwise occur.
mem::transmute::<Option<fn()>, u32>(Some(main));
mem::transmute::<Option<fn()>, usize>(Some(main));
}
fn main() {

View file

@ -1,26 +1,26 @@
error[E0512]: transmute called with types of different sizes
--> $DIR/transmute-from-fn-item-types-error.rs:19:13
--> $DIR/transmute-from-fn-item-types-error.rs:14:13
|
19 | let i = mem::transmute(bar);
14 | let i = mem::transmute(bar);
| ^^^^^^^^^^^^^^
|
= note: source type: unsafe fn() {bar} (0 bits)
= note: target type: i32 (32 bits)
= note: target type: i8 (8 bits)
error[E0591]: can't transmute zero-sized type
--> $DIR/transmute-from-fn-item-types-error.rs:23:13
--> $DIR/transmute-from-fn-item-types-error.rs:18:13
|
23 | let p = mem::transmute(foo);
18 | let p = mem::transmute(foo);
| ^^^^^^^^^^^^^^
|
= note: source type: unsafe fn() -> (i32, *const (), std::option::Option<fn()>) {foo}
= note: source type: unsafe fn() -> (i8, *const (), std::option::Option<fn()>) {foo}
= note: target type: *const ()
= help: cast with `as` to a pointer instead
error[E0591]: can't transmute zero-sized type
--> $DIR/transmute-from-fn-item-types-error.rs:27:14
--> $DIR/transmute-from-fn-item-types-error.rs:22:14
|
27 | let of = mem::transmute(main);
22 | let of = mem::transmute(main);
| ^^^^^^^^^^^^^^
|
= note: source type: fn() {main}
@ -28,57 +28,28 @@ error[E0591]: can't transmute zero-sized type
= help: cast with `as` to a pointer instead
error[E0512]: transmute called with types of different sizes
--> $DIR/transmute-from-fn-item-types-error.rs:36:5
--> $DIR/transmute-from-fn-item-types-error.rs:31:5
|
36 | mem::transmute::<_, u8>(main);
31 | mem::transmute::<_, u8>(main);
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: source type: fn() {main} (0 bits)
= note: target type: u8 (8 bits)
error[E0591]: can't transmute zero-sized type
--> $DIR/transmute-from-fn-item-types-error.rs:40:5
--> $DIR/transmute-from-fn-item-types-error.rs:35:5
|
40 | mem::transmute::<_, *mut ()>(foo);
35 | mem::transmute::<_, *mut ()>(foo);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: source type: unsafe fn() -> (i32, *const (), std::option::Option<fn()>) {foo}
= note: source type: unsafe fn() -> (i8, *const (), std::option::Option<fn()>) {foo}
= note: target type: *mut ()
= help: cast with `as` to a pointer instead
error[E0591]: can't transmute zero-sized type
--> $DIR/transmute-from-fn-item-types-error.rs:44:5
--> $DIR/transmute-from-fn-item-types-error.rs:39:5
|
44 | mem::transmute::<_, fn()>(bar);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: source type: unsafe fn() {bar}
= note: target type: fn()
= help: cast with `as` to a pointer instead
error[E0512]: transmute called with types of different sizes
--> $DIR/transmute-from-fn-item-types-error.rs:49:5
|
49 | mem::transmute::<fn(), u32>(main);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: source type: fn() (64 bits)
= note: target type: u32 (32 bits)
error[E0591]: can't transmute zero-sized type
--> $DIR/transmute-from-fn-item-types-error.rs:53:5
|
53 | mem::transmute::<_, *mut ()>(Some(foo));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: source type: unsafe fn() -> (i32, *const (), std::option::Option<fn()>) {foo}
= note: target type: *mut ()
= help: cast with `as` to a pointer instead
error[E0591]: can't transmute zero-sized type
--> $DIR/transmute-from-fn-item-types-error.rs:57:5
|
57 | mem::transmute::<_, fn()>(Some(bar));
39 | mem::transmute::<_, fn()>(bar);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: source type: unsafe fn() {bar}
@ -86,23 +57,34 @@ error[E0591]: can't transmute zero-sized type
= help: cast with `as` to a pointer instead
error[E0591]: can't transmute zero-sized type
--> $DIR/transmute-from-fn-item-types-error.rs:61:5
--> $DIR/transmute-from-fn-item-types-error.rs:48:5
|
61 | mem::transmute::<_, Option<fn()>>(Some(baz));
48 | mem::transmute::<_, *mut ()>(Some(foo));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: source type: unsafe fn() -> (i8, *const (), std::option::Option<fn()>) {foo}
= note: target type: *mut ()
= help: cast with `as` to a pointer instead
error[E0591]: can't transmute zero-sized type
--> $DIR/transmute-from-fn-item-types-error.rs:52:5
|
52 | mem::transmute::<_, fn()>(Some(bar));
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: source type: unsafe fn() {bar}
= note: target type: fn()
= help: cast with `as` to a pointer instead
error[E0591]: can't transmute zero-sized type
--> $DIR/transmute-from-fn-item-types-error.rs:56:5
|
56 | mem::transmute::<_, Option<fn()>>(Some(baz));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: source type: unsafe fn() {baz}
= note: target type: std::option::Option<fn()>
= help: cast with `as` to a pointer instead
error[E0512]: transmute called with types of different sizes
--> $DIR/transmute-from-fn-item-types-error.rs:66:5
|
66 | mem::transmute::<Option<fn()>, u32>(Some(main));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: source type: std::option::Option<fn()> (64 bits)
= note: target type: u32 (32 bits)
error: aborting due to 11 previous errors
error: aborting due to 9 previous errors

View file

@ -8,10 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-x86
// ignore-arm
// ignore-emscripten
// ignore 32-bit platforms (test output is different)
// Tests that `transmute` cannot be called on type parameters.

View file

@ -211,6 +211,9 @@ pub struct TestProps {
// The test must be compiled and run successfully. Only used in UI tests for
// now.
pub run_pass: bool,
// customized normalization rules
pub normalize_stdout: Vec<(String, String)>,
pub normalize_stderr: Vec<(String, String)>,
}
impl TestProps {
@ -237,6 +240,8 @@ impl TestProps {
must_compile_successfully: false,
check_test_line_numbers_match: false,
run_pass: false,
normalize_stdout: vec![],
normalize_stderr: vec![],
}
}
@ -351,6 +356,13 @@ impl TestProps {
if !self.run_pass {
self.run_pass = config.parse_run_pass(ln);
}
if let Some(rule) = config.parse_custom_normalization(ln, "normalize-stdout") {
self.normalize_stdout.push(rule);
}
if let Some(rule) = config.parse_custom_normalization(ln, "normalize-stderr") {
self.normalize_stderr.push(rule);
}
});
for key in &["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] {
@ -399,7 +411,6 @@ fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut FnMut(&str)) {
}
impl Config {
fn parse_error_pattern(&self, line: &str) -> Option<String> {
self.parse_name_value_directive(line, "error-pattern")
}
@ -497,6 +508,22 @@ impl Config {
}
}
fn parse_custom_normalization(&self, mut line: &str, prefix: &str) -> Option<(String, String)> {
if self.parse_cfg_name_directive(line, prefix) {
let from = match parse_normalization_string(&mut line) {
Some(s) => s,
None => return None,
};
let to = match parse_normalization_string(&mut line) {
Some(s) => s,
None => return None,
};
Some((from, to))
} else {
None
}
}
/// Parses a name-value directive which contains config-specific information, e.g. `ignore-x86`
/// or `normalize-stderr-32bit`. Returns `true` if the line matches it.
fn parse_cfg_name_directive(&self, line: &str, prefix: &str) -> bool {
@ -568,3 +595,29 @@ fn expand_variables(mut value: String, config: &Config) -> String {
value
}
/// Finds the next quoted string `"..."` in `line`, and extract the content from it. Move the `line`
/// variable after the end of the quoted string.
///
/// # Examples
///
/// ```
/// let mut s = "normalize-stderr-32bit: \"something (32 bits)\" -> \"something ($WORD bits)\".";
/// let first = parse_normalization_string(&mut s);
/// assert_eq!(first, Some("something (32 bits)".to_owned()));
/// assert_eq!(s, " -> \"something ($WORD bits)\".");
/// ```
fn parse_normalization_string(line: &mut &str) -> Option<String> {
// FIXME support escapes in strings.
let begin = match line.find('"') {
Some(i) => i + 1,
None => return None,
};
let end = match line[begin..].find('"') {
Some(i) => i + begin,
None => return None,
};
let result = line[begin..end].to_owned();
*line = &line[end+1..];
Some(result)
}

View file

@ -2228,8 +2228,10 @@ actual:\n\
let expected_stdout_path = self.expected_output_path("stdout");
let expected_stdout = self.load_expected_output(&expected_stdout_path);
let normalized_stdout = self.normalize_output(&proc_res.stdout);
let normalized_stderr = self.normalize_output(&proc_res.stderr);
let normalized_stdout =
self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout);
let normalized_stderr =
self.normalize_output(&proc_res.stderr, &self.props.normalize_stderr);
let mut errors = 0;
errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout);
@ -2375,13 +2377,17 @@ actual:\n\
mir_dump_dir
}
fn normalize_output(&self, output: &str) -> String {
fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> String {
let parent_dir = self.testpaths.file.parent().unwrap();
let parent_dir_str = parent_dir.display().to_string();
output.replace(&parent_dir_str, "$DIR")
let mut normalized = output.replace(&parent_dir_str, "$DIR")
.replace("\\", "/") // normalize for paths on windows
.replace("\r\n", "\n") // normalize for linebreaks on windows
.replace("\t", "\\t") // makes tabs visible
.replace("\t", "\\t"); // makes tabs visible
for rule in custom_rules {
normalized = normalized.replace(&rule.0, &rule.1);
}
normalized
}
fn expected_output_path(&self, kind: &str) -> PathBuf {