From 18712e6edf685855ce0e0470730192165e56e0b1 Mon Sep 17 00:00:00 2001 From: kennytm Date: Thu, 6 Jul 2017 11:25:29 +0800 Subject: [PATCH 1/3] compiletest: Refactor: Move the `ignore-{}` logic into its own method. Prepare for `normalize-std???` which will share the same logic. Added `ignore-32bit` and `ignore-64bit`. --- src/test/run-pass/i128-ffi.rs | 7 +--- src/tools/compiletest/src/header.rs | 56 ++++++++++++++--------------- src/tools/compiletest/src/util.rs | 8 +++++ 3 files changed, 35 insertions(+), 36 deletions(-) diff --git a/src/test/run-pass/i128-ffi.rs b/src/test/run-pass/i128-ffi.rs index d07fb7b4a7143..d989210dd71f2 100644 --- a/src/test/run-pass/i128-ffi.rs +++ b/src/test/run-pass/i128-ffi.rs @@ -13,12 +13,7 @@ // should look like. // ignore-windows - -// Ignore 32 bit targets: -// ignore-x86 -// ignore-arm - -// ignore-emscripten +// ignore-32bit #![feature(i128_type)] diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 5ac60d8f2c857..59d08ceae219e 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -40,15 +40,8 @@ impl EarlyProps { None, &mut |ln| { props.ignore = - props.ignore || config.parse_name_directive(ln, "ignore-test") || - config.parse_name_directive(ln, &ignore_target(config)) || - config.parse_name_directive(ln, &ignore_architecture(config)) || - config.parse_name_directive(ln, &ignore_stage(config)) || - config.parse_name_directive(ln, &ignore_env(config)) || - (config.mode == common::Pretty && - config.parse_name_directive(ln, "ignore-pretty")) || - (config.target != config.host && - config.parse_name_directive(ln, "ignore-cross-compile")) || + props.ignore || + config.parse_cfg_name_directive(ln, "ignore") || ignore_gdb(config, ln) || ignore_lldb(config, ln) || ignore_llvm(config, ln); @@ -62,28 +55,11 @@ impl EarlyProps { return props; - fn ignore_target(config: &Config) -> String { - format!("ignore-{}", util::get_os(&config.target)) - } - fn ignore_architecture(config: &Config) -> String { - format!("ignore-{}", util::get_arch(&config.target)) - } - fn ignore_stage(config: &Config) -> String { - format!("ignore-{}", config.stage_id.split('-').next().unwrap()) - } - fn ignore_env(config: &Config) -> String { - format!("ignore-{}", - util::get_env(&config.target).unwrap_or("")) - } fn ignore_gdb(config: &Config, line: &str) -> bool { if config.mode != common::DebugInfoGdb { return false; } - if config.parse_name_directive(line, "ignore-gdb") { - return true; - } - if let Some(actual_version) = config.gdb_version { if line.starts_with("min-gdb-version") { let (start_ver, end_ver) = extract_gdb_version_range(line); @@ -144,10 +120,6 @@ impl EarlyProps { return false; } - if config.parse_name_directive(line, "ignore-lldb") { - return true; - } - if let Some(ref actual_version) = config.lldb_version { if line.starts_with("min-lldb-version") { let min_version = line.trim_right() @@ -525,6 +497,30 @@ impl Config { } } + /// 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 { + if line.starts_with(prefix) && line.as_bytes().get(prefix.len()) == Some(&b'-') { + let name = line[prefix.len()+1 ..].split(&[':', ' '][..]).next().unwrap(); + + name == "test" || + name == util::get_os(&self.target) || // target + name == util::get_arch(&self.target) || // architecture + name == util::get_pointer_width(&self.target) || // pointer width + name == self.stage_id.split('-').next().unwrap() || // stage + Some(name) == util::get_env(&self.target) || // env + match self.mode { + common::DebugInfoGdb => name == "gdb", + common::DebugInfoLldb => name == "lldb", + common::Pretty => name == "pretty", + _ => false, + } || + (self.target != self.host && name == "cross-compile") + } else { + false + } + } + fn parse_name_directive(&self, line: &str, directive: &str) -> bool { // Ensure the directive is a whole word. Do not match "ignore-x86" when // the line says "ignore-x86_64". diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 4202356bd97a0..85fa38bbd3be7 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -72,6 +72,14 @@ pub fn get_env(triple: &str) -> Option<&str> { triple.split('-').nth(3) } +pub fn get_pointer_width(triple: &str) -> &'static str { + if triple.contains("64") || triple.starts_with("s390x") { + "64bit" + } else { + "32bit" + } +} + pub fn make_new_path(path: &str) -> String { assert!(cfg!(windows)); // Windows just uses PATH as the library search path, so we have to From 4582ecda64f6f9173281390ef5698fac29dd6264 Mon Sep 17 00:00:00 2001 From: kennytm Date: Thu, 6 Jul 2017 13:54:58 +0800 Subject: [PATCH 2/3] compiletest: Support custom normalization rules. --- src/test/ui/enum-size-variance.rs | 18 ++---- src/test/ui/enum-size-variance.stderr | 10 +-- src/test/ui/transmute/main.rs | 8 +-- src/test/ui/transmute/main.stderr | 2 +- .../transmute-from-fn-item-types-error.rs | 11 +--- .../transmute-from-fn-item-types-error.stderr | 64 +++++++------------ .../ui/transmute/transmute-type-parameters.rs | 8 +-- src/tools/compiletest/src/header.rs | 55 +++++++++++++++- src/tools/compiletest/src/runtest.rs | 16 +++-- 9 files changed, 112 insertions(+), 80 deletions(-) diff --git a/src/test/ui/enum-size-variance.rs b/src/test/ui/enum-size-variance.rs index 075bd9acf5f38..582998a986d00 100644 --- a/src/test/ui/enum-size-variance.rs +++ b/src/test/ui/enum-size-variance.rs @@ -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 { 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() { } diff --git a/src/test/ui/enum-size-variance.stderr b/src/test/ui/enum-size-variance.stderr index 5745b9344b4a7..a21243a49907f 100644 --- a/src/test/ui/enum-size-variance.stderr +++ b/src/test/ui/enum-size-variance.stderr @@ -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)] | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/transmute/main.rs b/src/test/ui/transmute/main.rs index d5968a388dc1d..ab448de656e67 100644 --- a/src/test/ui/transmute/main.rs +++ b/src/test/ui/transmute/main.rs @@ -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; diff --git a/src/test/ui/transmute/main.stderr b/src/test/ui/transmute/main.stderr index a7fc0808e1845..b7e34d3e0bc46 100644 --- a/src/test/ui/transmute/main.stderr +++ b/src/test/ui/transmute/main.stderr @@ -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 diff --git a/src/test/ui/transmute/transmute-from-fn-item-types-error.rs b/src/test/ui/transmute/transmute-from-fn-item-types-error.rs index 98d2e1e3628f2..d60c97f1d59a8 100644 --- a/src/test/ui/transmute/transmute-from-fn-item-types-error.rs +++ b/src/test/ui/transmute/transmute-from-fn-item-types-error.rs @@ -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) { +unsafe fn foo() -> (i8, *const (), Option) { 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::(main); + mem::transmute::(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::, u32>(Some(main)); + mem::transmute::, usize>(Some(main)); } fn main() { diff --git a/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr b/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr index 7f1929050bb8f..197daf1b79596 100644 --- a/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr +++ b/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr @@ -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) {foo} + = note: source type: unsafe fn() -> (i8, *const (), std::option::Option) {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,48 @@ 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) {foo} + = note: source type: unsafe fn() -> (i8, *const (), std::option::Option) {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); +39 | 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::(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 + --> $DIR/transmute-from-fn-item-types-error.rs:48:5 | -53 | mem::transmute::<_, *mut ()>(Some(foo)); +48 | mem::transmute::<_, *mut ()>(Some(foo)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: source type: unsafe fn() -> (i32, *const (), std::option::Option) {foo} + = note: source type: unsafe fn() -> (i8, *const (), std::option::Option) {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 + --> $DIR/transmute-from-fn-item-types-error.rs:52:5 | -57 | mem::transmute::<_, fn()>(Some(bar)); +52 | mem::transmute::<_, fn()>(Some(bar)); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: source type: unsafe fn() {bar} @@ -86,23 +77,14 @@ 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:56:5 | -61 | mem::transmute::<_, Option>(Some(baz)); +56 | mem::transmute::<_, Option>(Some(baz)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: source type: unsafe fn() {baz} = note: target type: std::option::Option = 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::, u32>(Some(main)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: source type: std::option::Option (64 bits) - = note: target type: u32 (32 bits) - -error: aborting due to 11 previous errors +error: aborting due to 9 previous errors diff --git a/src/test/ui/transmute/transmute-type-parameters.rs b/src/test/ui/transmute/transmute-type-parameters.rs index fa83a10dc48e8..117fc2cc5df24 100644 --- a/src/test/ui/transmute/transmute-type-parameters.rs +++ b/src/test/ui/transmute/transmute-type-parameters.rs @@ -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. diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 59d08ceae219e..bb9bf57d55e2f 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -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 { 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 { + // 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) +} diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 2254d6d23a83d..45a733d411ab9 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -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 { From 34209b0eaaa41dd5630772c59e5d3f03624caed5 Mon Sep 17 00:00:00 2001 From: kennytm Date: Fri, 7 Jul 2017 02:10:48 +0800 Subject: [PATCH 3/3] Merge ui/README.md into COMPILER_TESTS.md and describe how custom UI normalization works. --- src/test/COMPILER_TESTS.md | 73 +++++++++++++++++++++++++++++++++++++- src/test/ui/README.md | 31 ---------------- 2 files changed, 72 insertions(+), 32 deletions(-) delete mode 100644 src/test/ui/README.md diff --git a/src/test/COMPILER_TESTS.md b/src/test/COMPILER_TESTS.md index 58df1aae6d3f0..0380454b8278d 100644 --- a/src/test/COMPILER_TESTS.md +++ b/src/test/COMPILER_TESTS.md @@ -37,7 +37,7 @@ The error levels that you can have are: Header commands specify something about the entire test file as a whole, instead of just a few lines inside the test. -* `ignore-X` where `X` is an architecture, OS or stage will ignore the test accordingly +* `ignore-X` where `X` is a target detail or stage will ignore the test accordingly (see below) * `ignore-pretty` will not compile the pretty-printed test (this is done to test the pretty-printer, but might not always work) * `ignore-test` always ignores the test * `ignore-lldb` and `ignore-gdb` will skip the debuginfo tests @@ -50,6 +50,14 @@ whole, instead of just a few lines inside the test. feature is attempted without the proper `#![feature(X)]` tag. Each unstable lang feature is required to have a gate test. +Some examples of `X` in `ignore-X`: + +* Architecture: `aarch64`, `arm`, `asmjs`, `mips`, `wasm32`, `x86_64`, `x86`, ... +* OS: `android`, `emscripten`, `freebsd`, `ios`, `linux`, `macos`, `windows`, ... +* Environment (fourth word of the target triple): `gnu`, `msvc`, `musl`. +* Pointer width: `32bit`, `64bit`. +* Stage: `stage0`, `stage1`, `stage2`. + ## Revisions Certain classes of tests support "revisions" (as of the time of this @@ -86,3 +94,66 @@ For example, the `ignore-test` header (and all "ignore" headers) currently only apply to the test as a whole, not to particular revisions. The only headers that are intended to really work when customized to a revision are error patterns and compiler flags. + +## Guide to the UI Tests + +The UI tests are intended to capture the compiler's complete output, +so that we can test all aspects of the presentation. They work by +compiling a file (e.g., `ui/hello_world/main.rs`), capturing the output, +and then applying some normalization (see below). This normalized +result is then compared against reference files named +`ui/hello_world/main.stderr` and `ui/hello_world/main.stdout`. If either of +those files doesn't exist, the output must be empty. If the test run +fails, we will print out the current output, but it is also saved in +`build//test/ui/hello_world/main.stdout` (this path is +printed as part of the test failure mesage), so you can run `diff` and +so forth. + +### Editing and updating the reference files + +If you have changed the compiler's output intentionally, or you are +making a new test, you can use the script `ui/update-references.sh` to +update the references. When you run the test framework, it will report +various errors: in those errors is a command you can use to run the +`ui/update-references.sh` script, which will then copy over the files +from the build directory and use them as the new reference. You can +also just run `ui/update-all-references.sh`. In both cases, you can run +the script with `--help` to get a help message. + +### Normalization + +The normalization applied is aimed at eliminating output difference +between platforms, mainly about filenames: + +- the test directory is replaced with `$DIR` +- all backslashes (`\`) are converted to forward slashes (`/`) (for Windows) +- all CR LF newlines are converted to LF + +Sometimes these built-in normalizations are not enough. In such cases, you +may provide custom normalization rules using the header commands, e.g. + +``` +// normalize-stderr-32bit: "fn() (32 bits)" -> "fn() ($PTR bits)" +// normalize-stderr-64bit: "fn() (64 bits)" -> "fn() ($PTR bits)" +``` + +This tells the test, on 32-bit platforms, whenever the compiler writes +`fn() (32 bits)` to stderr, it should be normalized to read `fn() ($PTR bits)` +instead. Similar for 64-bit. + +The corresponding reference file will use the normalized output to test both +32-bit and 64-bit platforms: + +``` +... + | + = note: source type: fn() ($PTR bits) + = note: target type: u16 (16 bits) +... +``` + +Please see `ui/transmute/main.rs` and `.stderr` for a concrete usage example. + +Besides `normalize-stderr-32bit` and `-64bit`, one may use any target +information or stage supported by `ignore-X` here as well (e.g. +`normalize-stderr-windows`). diff --git a/src/test/ui/README.md b/src/test/ui/README.md deleted file mode 100644 index dcdeabd80322f..0000000000000 --- a/src/test/ui/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# Guide to the UI Tests - -The UI tests are intended to capture the compiler's complete output, -so that we can test all aspects of the presentation. They work by -compiling a file (e.g., `hello_world/main.rs`), capturing the output, -and then applying some normalization (see below). This normalized -result is then compared against reference files named -`hello_world/main.stderr` and `hello_world/main.stdout`. If either of -those files doesn't exist, the output must be empty. If the test run -fails, we will print out the current output, but it is also saved in -`build//test/ui/hello_world/main.stdout` (this path is -printed as part of the test failure mesage), so you can run `diff` and -so forth. - -# Editing and updating the reference files - -If you have changed the compiler's output intentionally, or you are -making a new test, you can use the script `update-references.sh` to -update the references. When you run the test framework, it will report -various errors: in those errors is a command you can use to run the -`update-references.sh` script, which will then copy over the files -from the build directory and use them as the new reference. You can -also just run `update-all-references.sh`. In both cases, you can run -the script with `--help` to get a help message. - -# Normalization - -The normalization applied is aimed at filenames: - -- the test directory is replaced with `$DIR` -- all backslashes (\) are converted to forward slashes (/) (for windows)