about summary refs log tree commit diff
path: root/src/tools/compiletest
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2016-05-11 12:28:52 -0700
committerNiko Matsakis <niko@alum.mit.edu>2016-05-13 15:22:45 -0700
commitcb112dc8cfe105b9eec2a3e1b59dd66eca386ee6 (patch)
tree475aef34a1b5ba5895a77cb10b151397f230e7d9 /src/tools/compiletest
parent33a5c9dfd106e2f900aba7074f10b5e8e617be7b (diff)
downloadrust-cb112dc8cfe105b9eec2a3e1b59dd66eca386ee6.tar.gz
rust-cb112dc8cfe105b9eec2a3e1b59dd66eca386ee6.zip
add UI testing framework
Diffstat (limited to 'src/tools/compiletest')
-rw-r--r--src/tools/compiletest/src/common.rs3
-rw-r--r--src/tools/compiletest/src/runtest.rs88
2 files changed, 90 insertions, 1 deletions
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index ae8beb83530..5ec62e06e37 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -28,6 +28,7 @@ pub enum Mode {
     CodegenUnits,
     Incremental,
     RunMake,
+    Ui,
 }
 
 impl FromStr for Mode {
@@ -47,6 +48,7 @@ impl FromStr for Mode {
           "codegen-units" => Ok(CodegenUnits),
           "incremental" => Ok(Incremental),
           "run-make" => Ok(RunMake),
+          "ui" => Ok(Ui),
           _ => Err(()),
         }
     }
@@ -68,6 +70,7 @@ impl fmt::Display for Mode {
             CodegenUnits => "codegen-units",
             Incremental => "incremental",
             RunMake => "run-make",
+            Ui => "ui",
         }, f)
     }
 }
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index aa1b9d2bafb..9e4f331d16e 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -11,7 +11,7 @@
 use common::Config;
 use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind};
 use common::{Codegen, DebugInfoLldb, DebugInfoGdb, Rustdoc, CodegenUnits};
-use common::{Incremental, RunMake};
+use common::{Incremental, RunMake, Ui};
 use errors::{self, ErrorKind, Error};
 use json;
 use header::TestProps;
@@ -29,6 +29,7 @@ use std::io::prelude::*;
 use std::net::TcpStream;
 use std::path::{Path, PathBuf};
 use std::process::{Command, Output, ExitStatus};
+use std::str;
 
 pub fn run(config: Config, testpaths: &TestPaths) {
     match &*config.target {
@@ -118,6 +119,7 @@ impl<'test> TestCx<'test> {
             CodegenUnits => self.run_codegen_units_test(),
             Incremental => self.run_incremental_test(),
             RunMake => self.run_rmake_test(),
+            Ui => self.run_ui_test(),
         }
     }
 
@@ -1314,6 +1316,7 @@ actual:\n\
             Codegen |
             Rustdoc |
             RunMake |
+            Ui |
             CodegenUnits => {
                 // do not use JSON output
             }
@@ -2096,6 +2099,89 @@ actual:\n\
         }
         fs::remove_dir(path)
     }
+
+    fn run_ui_test(&self) {
+        println!("ui: {}", self.testpaths.file.display());
+
+        let proc_res = self.compile_test();
+
+        let expected_stderr_path = self.expected_output_path("stderr");
+        let expected_stderr = self.load_expected_output(&expected_stderr_path);
+
+        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 mut errors = 0;
+        errors += self.compare_output("stdout", normalized_stdout.as_bytes(), &expected_stdout);
+        errors += self.compare_output("stderr", normalized_stderr.as_bytes(), &expected_stderr);
+
+        if errors > 0 {
+            println!("To update references, run this command from build directory:");
+            let relative_path_to_file =
+                self.testpaths.relative_dir
+                              .join(self.testpaths.file.file_name().unwrap());
+            println!("{}/update-references.sh '{}' '{}'",
+                     self.config.src_base.display(),
+                     self.config.build_base.display(),
+                     relative_path_to_file.display());
+            self.fatal(&format!("{} errors occurred comparing output.", errors));
+        }
+    }
+
+    fn normalize_output(&self, output: &str) -> String {
+        let parent_dir = self.testpaths.file.parent().unwrap();
+        let parent_dir_str = parent_dir.display().to_string();
+        output.replace(&parent_dir_str, "$DIR")
+              .replace("\\", "/") // windows, you know.
+    }
+
+    fn expected_output_path(&self, kind: &str) -> PathBuf {
+        let extension = match self.revision {
+            Some(r) => format!("{}.{}", r, kind),
+            None => kind.to_string(),
+        };
+        self.testpaths.file.with_extension(extension)
+    }
+
+    fn load_expected_output(&self, path: &Path) -> Vec<u8> {
+        if !path.exists() {
+            return vec![];
+        }
+
+        let mut result = Vec::new();
+        match File::open(path).and_then(|mut f| f.read_to_end(&mut result)) {
+            Ok(_) => result,
+            Err(e) => {
+                self.fatal(&format!("failed to load expected output from `{}`: {}", path.display(), e))
+            }
+        }
+    }
+
+    fn compare_output(&self, kind: &str, actual: &[u8], expected: &[u8]) -> usize {
+        if self.config.verbose {
+            println!("normalized {}:\n{}\n", kind, str::from_utf8(actual).unwrap_or("not utf8"));
+            println!("expected {}:\n{}\n", kind, str::from_utf8(expected).unwrap_or("not utf8"));
+        }
+        if actual == expected {
+            return 0;
+        }
+
+        let output_file = self.output_base_name().with_extension(kind);
+        match File::create(&output_file).and_then(|mut f| f.write_all(actual)) {
+            Ok(()) => { }
+            Err(e) => {
+                self.fatal(&format!("failed to write {} to `{}`: {}",
+                                    kind, output_file.display(), e))
+            }
+        }
+
+        println!("\nThe actual {0} differed from the expected {0}.", kind);
+        println!("Actual {} saved to {}", kind, output_file.display());
+        1
+    }
 }
 
 struct ProcArgs {