// Copyright 2012-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 common::Config;
use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind};
use common::{Codegen, DebugInfoLldb, DebugInfoGdb, Rustdoc, CodegenUnits};
use common::{Incremental, RunMake, Ui, MirOpt};
use errors::{self, ErrorKind, Error};
use json;
use header::TestProps;
use header;
use procsrv;
use test::TestPaths;
use uidiff;
use util::logv;

use std::env;
use std::collections::HashSet;
use std::fmt;
use std::fs::{self, File};
use std::io::{self, BufReader};
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 {

        "arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android" => {
            if !config.adb_device_status {
                panic!("android device not available");
            }
        }

        _=> { }
    }

    if config.verbose {
        // We're going to be dumping a lot of info. Start on a new line.
        print!("\n\n");
    }
    debug!("running {:?}", testpaths.file.display());
    let base_props = TestProps::from_file(&testpaths.file);

    let base_cx = TestCx { config: &config,
                           props: &base_props,
                           testpaths: testpaths,
                           revision: None };
    base_cx.init_all();

    if base_props.revisions.is_empty() {
        base_cx.run_revision()
    } else {
        for revision in &base_props.revisions {
            let mut revision_props = base_props.clone();
            revision_props.load_from(&testpaths.file, Some(&revision));
            let rev_cx = TestCx {
                config: &config,
                props: &revision_props,
                testpaths: testpaths,
                revision: Some(revision)
            };
            rev_cx.run_revision();
        }
    }

    base_cx.complete_all();
}

struct TestCx<'test> {
    config: &'test Config,
    props: &'test TestProps,
    testpaths: &'test TestPaths,
    revision: Option<&'test str>
}

struct DebuggerCommands {
    commands: Vec<String>,
    check_lines: Vec<String>,
    breakpoint_lines: Vec<usize>,
}

impl<'test> TestCx<'test> {
    /// invoked once before any revisions have been processed
    fn init_all(&self) {
        assert!(self.revision.is_none(), "init_all invoked for a revision");
        match self.config.mode {
            Incremental => self.init_incremental_test(),
            _ => { }
        }
    }

    /// Code executed for each revision in turn (or, if there are no
    /// revisions, exactly once, with revision == None).
    fn run_revision(&self) {
        match self.config.mode {
            CompileFail => self.run_cfail_test(),
            ParseFail => self.run_cfail_test(),
            RunFail => self.run_rfail_test(),
            RunPass => self.run_rpass_test(),
            RunPassValgrind => self.run_valgrind_test(),
            Pretty => self.run_pretty_test(),
            DebugInfoGdb => self.run_debuginfo_gdb_test(),
            DebugInfoLldb => self.run_debuginfo_lldb_test(),
            Codegen => self.run_codegen_test(),
            Rustdoc => self.run_rustdoc_test(),
            CodegenUnits => self.run_codegen_units_test(),
            Incremental => self.run_incremental_test(),
            RunMake => self.run_rmake_test(),
            Ui => self.run_ui_test(),
            MirOpt => self.run_mir_opt_test(),
        }
    }

    /// Invoked after all revisions have executed.
    fn complete_all(&self) {
        assert!(self.revision.is_none(), "init_all invoked for a revision");
    }

    fn run_cfail_test(&self) {
        let proc_res = self.compile_test();

        if proc_res.status.success() {
            self.fatal_proc_rec(
                &format!("{} test compiled successfully!", self.config.mode)[..],
                &proc_res);
        }

        self.check_correct_failure_status(&proc_res);

        if proc_res.status.success() {
            self.fatal("process did not return an error status");
        }

        let output_to_check = self.get_output(&proc_res);
        let expected_errors = errors::load_errors(&self.testpaths.file, self.revision);
        if !expected_errors.is_empty() {
            if !self.props.error_patterns.is_empty() {
                self.fatal("both error pattern and expected errors specified");
            }
            self.check_expected_errors(expected_errors, &proc_res);
        } else {
            self.check_error_patterns(&output_to_check, &proc_res);
        }
        self.check_no_compiler_crash(&proc_res);
        self.check_forbid_output(&output_to_check, &proc_res);
    }

    fn run_rfail_test(&self) {
        let proc_res = self.compile_test();

        if !proc_res.status.success() {
            self.fatal_proc_rec("compilation failed!", &proc_res);
        }

        let proc_res = self.exec_compiled_test();

        // The value our Makefile configures valgrind to return on failure
        const VALGRIND_ERR: i32 = 100;
        if proc_res.status.code() == Some(VALGRIND_ERR) {
            self.fatal_proc_rec("run-fail test isn't valgrind-clean!", &proc_res);
        }

        let output_to_check = self.get_output(&proc_res);
        self.check_correct_failure_status(&proc_res);
        self.check_error_patterns(&output_to_check, &proc_res);
    }

    fn get_output(&self, proc_res: &ProcRes) -> String {
        if self.props.check_stdout {
            format!("{}{}", proc_res.stdout, proc_res.stderr)
        } else {
            proc_res.stderr.clone()
        }
    }

    fn check_correct_failure_status(&self, proc_res: &ProcRes) {
        // The value the rust runtime returns on failure
        const RUST_ERR: i32 = 101;
        if proc_res.status.code() != Some(RUST_ERR) {
            self.fatal_proc_rec(
                &format!("failure produced the wrong error: {}",
                         proc_res.status),
                proc_res);
        }
    }

    fn run_rpass_test(&self) {
        let proc_res = self.compile_test();

        if !proc_res.status.success() {
            self.fatal_proc_rec("compilation failed!", &proc_res);
        }

        let proc_res = self.exec_compiled_test();

        if !proc_res.status.success() {
            self.fatal_proc_rec("test run failed!", &proc_res);
        }
    }

    fn run_valgrind_test(&self) {
        assert!(self.revision.is_none(), "revisions not relevant here");

        if self.config.valgrind_path.is_none() {
            assert!(!self.config.force_valgrind);
            return self.run_rpass_test();
        }

        let mut proc_res = self.compile_test();

        if !proc_res.status.success() {
            self.fatal_proc_rec("compilation failed!", &proc_res);
        }

        let mut new_config = self.config.clone();
        new_config.runtool = new_config.valgrind_path.clone();
        let new_cx = TestCx { config: &new_config, ..*self };
        proc_res = new_cx.exec_compiled_test();

        if !proc_res.status.success() {
            self.fatal_proc_rec("test run failed!", &proc_res);
        }
    }

    fn run_pretty_test(&self) {
        if self.props.pp_exact.is_some() {
            logv(self.config, "testing for exact pretty-printing".to_owned());
        } else {
            logv(self.config, "testing for converging pretty-printing".to_owned());
        }

        let rounds = match self.props.pp_exact { Some(_) => 1, None => 2 };

        let mut src = String::new();
        File::open(&self.testpaths.file).unwrap().read_to_string(&mut src).unwrap();
        let mut srcs = vec!(src);

        let mut round = 0;
        while round < rounds {
            logv(self.config, format!("pretty-printing round {} revision {:?}",
                                      round, self.revision));
            let proc_res = self.print_source(srcs[round].to_owned(), &self.props.pretty_mode);

            if !proc_res.status.success() {
                self.fatal_proc_rec(&format!("pretty-printing failed in round {} revision {:?}",
                                             round, self.revision),
                                    &proc_res);
            }

            let ProcRes{ stdout, .. } = proc_res;
            srcs.push(stdout);
            round += 1;
        }

        let mut expected = match self.props.pp_exact {
            Some(ref file) => {
                let filepath = self.testpaths.file.parent().unwrap().join(file);
                let mut s = String::new();
                File::open(&filepath).unwrap().read_to_string(&mut s).unwrap();
                s
            }
            None => { srcs[srcs.len() - 2].clone() }
        };
        let mut actual = srcs[srcs.len() - 1].clone();

        if self.props.pp_exact.is_some() {
            // Now we have to care about line endings
            let cr = "\r".to_owned();
            actual = actual.replace(&cr, "").to_owned();
            expected = expected.replace(&cr, "").to_owned();
        }

        self.compare_source(&expected, &actual);

        // If we're only making sure that the output matches then just stop here
        if self.props.pretty_compare_only { return; }

        // Finally, let's make sure it actually appears to remain valid code
        let proc_res = self.typecheck_source(actual);
        if !proc_res.status.success() {
            self.fatal_proc_rec("pretty-printed source does not typecheck", &proc_res);
        }

        if !self.props.pretty_expanded { return }

        // additionally, run `--pretty expanded` and try to build it.
        let proc_res = self.print_source(srcs[round].clone(), "expanded");
        if !proc_res.status.success() {
            self.fatal_proc_rec("pretty-printing (expanded) failed", &proc_res);
        }

        let ProcRes{ stdout: expanded_src, .. } = proc_res;
        let proc_res = self.typecheck_source(expanded_src);
        if !proc_res.status.success() {
            self.fatal_proc_rec(
                "pretty-printed source (expanded) does not typecheck",
                &proc_res);
        }
    }

    fn print_source(&self,
                    src: String,
                    pretty_type: &str)
                    -> ProcRes {
        let aux_dir = self.aux_output_dir_name();
        self.compose_and_run(self.make_pp_args(pretty_type.to_owned()),
                             self.props.exec_env.clone(),
                             self.config.compile_lib_path.to_str().unwrap(),
                             Some(aux_dir.to_str().unwrap()),
                             Some(src))
    }

    fn make_pp_args(&self,
                    pretty_type: String)
                    -> ProcArgs {
        let aux_dir = self.aux_output_dir_name();
        // FIXME (#9639): This needs to handle non-utf8 paths
        let mut args = vec!("-".to_owned(),
                            "-Zunstable-options".to_owned(),
                            "--unpretty".to_owned(),
                            pretty_type,
                            format!("--target={}", self.config.target),
                            "-L".to_owned(),
                            aux_dir.to_str().unwrap().to_owned());
        args.extend(self.split_maybe_args(&self.config.target_rustcflags));
        args.extend(self.props.compile_flags.iter().cloned());
        return ProcArgs {
            prog: self.config.rustc_path.to_str().unwrap().to_owned(),
            args: args,
        };
    }

    fn compare_source(&self,
                      expected: &str,
                      actual: &str) {
        if expected != actual {
            self.error("pretty-printed source does not match expected source");
            println!("\n\
expected:\n\
------------------------------------------\n\
{}\n\
------------------------------------------\n\
actual:\n\
------------------------------------------\n\
{}\n\
------------------------------------------\n\
\n",
                     expected, actual);
            panic!();
        }
    }

    fn typecheck_source(&self, src: String) -> ProcRes {
        let args = self.make_typecheck_args();
        self.compose_and_run_compiler(args, Some(src))
    }

    fn make_typecheck_args(&self) -> ProcArgs {
        let aux_dir = self.aux_output_dir_name();
        let target = if self.props.force_host {
            &*self.config.host
        } else {
            &*self.config.target
        };

        let out_dir = self.output_base_name().with_extension("pretty-out");
        let _ = fs::remove_dir_all(&out_dir);
        self.create_dir_racy(&out_dir);

        // FIXME (#9639): This needs to handle non-utf8 paths
        let mut args = vec!("-".to_owned(),
                            "-Zno-trans".to_owned(),
                            "--out-dir".to_owned(),
                            out_dir.to_str().unwrap().to_owned(),
                            format!("--target={}", target),
                            "-L".to_owned(),
                            self.config.build_base.to_str().unwrap().to_owned(),
                            "-L".to_owned(),
                            aux_dir.to_str().unwrap().to_owned());
        if let Some(revision) = self.revision {
            args.extend(vec![
                format!("--cfg"),
                format!("{}", revision),
            ]);
        }
        args.extend(self.split_maybe_args(&self.config.target_rustcflags));
        args.extend(self.props.compile_flags.iter().cloned());
        // FIXME (#9639): This needs to handle non-utf8 paths
        return ProcArgs {
            prog: self.config.rustc_path.to_str().unwrap().to_owned(),
            args: args,
        };
    }

    fn run_debuginfo_gdb_test(&self) {
        assert!(self.revision.is_none(), "revisions not relevant here");

        let config = Config {
            target_rustcflags: self.cleanup_debug_info_options(&self.config.target_rustcflags),
            host_rustcflags: self.cleanup_debug_info_options(&self.config.host_rustcflags),
            .. self.config.clone()
        };

        let test_cx = TestCx {
            config: &config,
            ..*self
        };

        test_cx.run_debuginfo_gdb_test_no_opt();
    }

    fn run_debuginfo_gdb_test_no_opt(&self) {
        let DebuggerCommands {
            commands,
            check_lines,
            breakpoint_lines
        } = self.parse_debugger_commands("gdb");
        let mut cmds = commands.join("\n");

        // compile test file (it should have 'compile-flags:-g' in the header)
        let compiler_run_result = self.compile_test();
        if !compiler_run_result.status.success() {
            self.fatal_proc_rec("compilation failed!", &compiler_run_result);
        }

        let exe_file = self.make_exe_name();

        let debugger_run_result;
        match &*self.config.target {
            "arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android" => {

                cmds = cmds.replace("run", "continue");

                let tool_path = match self.config.android_cross_path.to_str() {
                    Some(x) => x.to_owned(),
                    None => self.fatal("cannot find android cross path")
                };

                // write debugger script
                let mut script_str = String::with_capacity(2048);
                script_str.push_str(&format!("set charset {}\n", Self::charset()));
                script_str.push_str(&format!("set sysroot {}\n", tool_path));
                script_str.push_str(&format!("file {}\n", exe_file.to_str().unwrap()));
                script_str.push_str("target remote :5039\n");
                script_str.push_str(&format!("set solib-search-path \
                                              ./{}/stage2/lib/rustlib/{}/lib/\n",
                                             self.config.host, self.config.target));
                for line in &breakpoint_lines {
                    script_str.push_str(&format!("break {:?}:{}\n",
                                                 self.testpaths.file.file_name()
                                                 .unwrap()
                                                 .to_string_lossy(),
                                                 *line)[..]);
                }
                script_str.push_str(&cmds);
                script_str.push_str("\nquit\n");

                debug!("script_str = {}", script_str);
                self.dump_output_file(&script_str, "debugger.script");


                procsrv::run("",
                             &self.config.adb_path,
                             None,
                             &[
                                 "push".to_owned(),
                                 exe_file.to_str().unwrap().to_owned(),
                                 self.config.adb_test_dir.clone()
                             ],
                             vec!(("".to_owned(), "".to_owned())),
                             Some("".to_owned()))
                    .expect(&format!("failed to exec `{:?}`", self.config.adb_path));

                procsrv::run("",
                             &self.config.adb_path,
                             None,
                             &[
                                 "forward".to_owned(),
                                 "tcp:5039".to_owned(),
                                 "tcp:5039".to_owned()
                             ],
                             vec!(("".to_owned(), "".to_owned())),
                             Some("".to_owned()))
                    .expect(&format!("failed to exec `{:?}`", self.config.adb_path));

                let adb_arg = format!("export LD_LIBRARY_PATH={}; \
                                       gdbserver{} :5039 {}/{}",
                                      self.config.adb_test_dir.clone(),
                                      if self.config.target.contains("aarch64")
                                      {"64"} else {""},
                                      self.config.adb_test_dir.clone(),
                                      exe_file.file_name().unwrap().to_str()
                                      .unwrap());

                let mut process = procsrv::run_background("",
                                                          &self.config.adb_path
                                                          ,
                                                          None,
                                                          &[
                                                              "shell".to_owned(),
                                                              adb_arg.clone()
                                                          ],
                                                          vec!(("".to_owned(),
                                                                "".to_owned())),
                                                          Some("".to_owned()))
                    .expect(&format!("failed to exec `{:?}`", self.config.adb_path));
                loop {
                    //waiting 1 second for gdbserver start
                    ::std::thread::sleep(::std::time::Duration::new(1,0));
                    if TcpStream::connect("127.0.0.1:5039").is_ok() {
                        break
                    }
                }

                let debugger_script = self.make_out_name("debugger.script");
                // FIXME (#9639): This needs to handle non-utf8 paths
                let debugger_opts =
                    vec!("-quiet".to_owned(),
                         "-batch".to_owned(),
                         "-nx".to_owned(),
                         format!("-command={}", debugger_script.to_str().unwrap()));

                let mut gdb_path = tool_path;
                gdb_path.push_str(&format!("/bin/{}-gdb", self.config.target));
                let procsrv::Result {
                    out,
                    err,
                    status
                } = procsrv::run("",
                                 &gdb_path,
                                 None,
                                 &debugger_opts,
                                 vec!(("".to_owned(), "".to_owned())),
                                 None)
                    .expect(&format!("failed to exec `{:?}`", gdb_path));
                let cmdline = {
                    let cmdline = self.make_cmdline("",
                                                    &format!("{}-gdb", self.config.target),
                                                    &debugger_opts);
                    logv(self.config, format!("executing {}", cmdline));
                    cmdline
                };

                debugger_run_result = ProcRes {
                    status: Status::Normal(status),
                    stdout: out,
                    stderr: err,
                    cmdline: cmdline
                };
                if process.kill().is_err() {
                    println!("Adb process is already finished.");
                }
            }

            _=> {
                let rust_src_root = self.find_rust_src_root()
                                        .expect("Could not find Rust source root");
                let rust_pp_module_rel_path = Path::new("./src/etc");
                let rust_pp_module_abs_path = rust_src_root.join(rust_pp_module_rel_path)
                                                           .to_str()
                                                           .unwrap()
                                                           .to_owned();
                // write debugger script
                let mut script_str = String::with_capacity(2048);
                script_str.push_str(&format!("set charset {}\n", Self::charset()));
                script_str.push_str("show version\n");

                match self.config.gdb_version {
                    Some(ref version) => {
                        println!("NOTE: compiletest thinks it is using GDB version {}",
                                 version);

                        if header::gdb_version_to_int(version) >
                            header::gdb_version_to_int("7.4") {
                                // Add the directory containing the pretty printers to
                                // GDB's script auto loading safe path
                                script_str.push_str(
                                    &format!("add-auto-load-safe-path {}\n",
                                             rust_pp_module_abs_path.replace(r"\", r"\\"))
                                );
                            }
                    }
                    _ => {
                        println!("NOTE: compiletest does not know which version of \
                                  GDB it is using");
                    }
                }

                // The following line actually doesn't have to do anything with
                // pretty printing, it just tells GDB to print values on one line:
                script_str.push_str("set print pretty off\n");

                // Add the pretty printer directory to GDB's source-file search path
                script_str.push_str(&format!("directory {}\n",
                                             rust_pp_module_abs_path));

                // Load the target executable
                script_str.push_str(&format!("file {}\n",
                                             exe_file.to_str().unwrap()
                                             .replace(r"\", r"\\")));

                // Add line breakpoints
                for line in &breakpoint_lines {
                    script_str.push_str(&format!("break '{}':{}\n",
                                                 self.testpaths.file.file_name().unwrap()
                                                 .to_string_lossy(),
                                                 *line));
                }

                script_str.push_str(&cmds);
                script_str.push_str("\nquit\n");

                debug!("script_str = {}", script_str);
                self.dump_output_file(&script_str, "debugger.script");

                // run debugger script with gdb
                fn debugger() -> &'static str {
                    if cfg!(windows) {"gdb.exe"} else {"gdb"}
                }

                let debugger_script = self.make_out_name("debugger.script");

                // FIXME (#9639): This needs to handle non-utf8 paths
                let debugger_opts =
                    vec!("-quiet".to_owned(),
                         "-batch".to_owned(),
                         "-nx".to_owned(),
                         format!("-command={}", debugger_script.to_str().unwrap()));

                let proc_args = ProcArgs {
                    prog: debugger().to_owned(),
                    args: debugger_opts,
                };

                let environment = vec![("PYTHONPATH".to_owned(), rust_pp_module_abs_path)];

                debugger_run_result =
                    self.compose_and_run(proc_args,
                                         environment,
                                         self.config.run_lib_path.to_str().unwrap(),
                                         None,
                                         None);
            }
        }

        if !debugger_run_result.status.success() {
            self.fatal("gdb failed to execute");
        }

        self.check_debugger_output(&debugger_run_result, &check_lines);
    }

    fn find_rust_src_root(&self) -> Option<PathBuf> {
        let mut path = self.config.src_base.clone();
        let path_postfix = Path::new("src/etc/lldb_batchmode.py");

        while path.pop() {
            if path.join(&path_postfix).is_file() {
                return Some(path);
            }
        }

        return None;
    }

    fn run_debuginfo_lldb_test(&self) {
        assert!(self.revision.is_none(), "revisions not relevant here");

        if self.config.lldb_python_dir.is_none() {
            self.fatal("Can't run LLDB test because LLDB's python path is not set.");
        }

        let config = Config {
            target_rustcflags: self.cleanup_debug_info_options(&self.config.target_rustcflags),
            host_rustcflags: self.cleanup_debug_info_options(&self.config.host_rustcflags),
            .. self.config.clone()
        };


        let test_cx = TestCx {
            config: &config,
            ..*self
        };

        test_cx.run_debuginfo_lldb_test_no_opt();
    }

    fn run_debuginfo_lldb_test_no_opt(&self) {
        // compile test file (it should have 'compile-flags:-g' in the header)
        let compile_result = self.compile_test();
        if !compile_result.status.success() {
            self.fatal_proc_rec("compilation failed!", &compile_result);
        }

        let exe_file = self.make_exe_name();

        match self.config.lldb_version {
            Some(ref version) => {
                println!("NOTE: compiletest thinks it is using LLDB version {}",
                         version);
            }
            _ => {
                println!("NOTE: compiletest does not know which version of \
                          LLDB it is using");
            }
        }

        // Parse debugger commands etc from test files
        let DebuggerCommands {
            commands,
            check_lines,
            breakpoint_lines,
            ..
        } = self.parse_debugger_commands("lldb");

        // Write debugger script:
        // We don't want to hang when calling `quit` while the process is still running
        let mut script_str = String::from("settings set auto-confirm true\n");

        // Make LLDB emit its version, so we have it documented in the test output
        script_str.push_str("version\n");

        // Switch LLDB into "Rust mode"
        let rust_src_root = self.find_rust_src_root().expect("Could not find Rust source root");
        let rust_pp_module_rel_path = Path::new("./src/etc/lldb_rust_formatters.py");
        let rust_pp_module_abs_path = rust_src_root.join(rust_pp_module_rel_path)
                                                   .to_str()
                                                   .unwrap()
                                                   .to_owned();

        script_str.push_str(&format!("command script import {}\n",
                                     &rust_pp_module_abs_path[..])[..]);
        script_str.push_str("type summary add --no-value ");
        script_str.push_str("--python-function lldb_rust_formatters.print_val ");
        script_str.push_str("-x \".*\" --category Rust\n");
        script_str.push_str("type category enable Rust\n");

        // Set breakpoints on every line that contains the string "#break"
        let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy();
        for line in &breakpoint_lines {
            script_str.push_str(&format!("breakpoint set --file '{}' --line {}\n",
                                         source_file_name,
                                         line));
        }

        // Append the other commands
        for line in &commands {
            script_str.push_str(line);
            script_str.push_str("\n");
        }

        // Finally, quit the debugger
        script_str.push_str("\nquit\n");

        // Write the script into a file
        debug!("script_str = {}", script_str);
        self.dump_output_file(&script_str, "debugger.script");
        let debugger_script = self.make_out_name("debugger.script");

        // Let LLDB execute the script via lldb_batchmode.py
        let debugger_run_result = self.run_lldb(&exe_file,
                                                &debugger_script,
                                                &rust_src_root);

        if !debugger_run_result.status.success() {
            self.fatal_proc_rec("Error while running LLDB", &debugger_run_result);
        }

        self.check_debugger_output(&debugger_run_result, &check_lines);
    }

    fn run_lldb(&self,
                test_executable: &Path,
                debugger_script: &Path,
                rust_src_root: &Path)
                -> ProcRes {
        // Prepare the lldb_batchmode which executes the debugger script
        let lldb_script_path = rust_src_root.join("src/etc/lldb_batchmode.py");
        self.cmd2procres(Command::new(&self.config.lldb_python)
                         .arg(&lldb_script_path)
                         .arg(test_executable)
                         .arg(debugger_script)
                         .env("PYTHONPATH",
                              self.config.lldb_python_dir.as_ref().unwrap()))
    }

    fn cmd2procres(&self, cmd: &mut Command) -> ProcRes {
        let (status, out, err) = match cmd.output() {
            Ok(Output { status, stdout, stderr }) => {
                (status,
                 String::from_utf8(stdout).unwrap(),
                 String::from_utf8(stderr).unwrap())
            },
            Err(e) => {
                self.fatal(&format!("Failed to setup Python process for \
                                      LLDB script: {}", e))
            }
        };

        self.dump_output(&out, &err);
        ProcRes {
            status: Status::Normal(status),
            stdout: out,
            stderr: err,
            cmdline: format!("{:?}", cmd)
        }
    }

    fn parse_debugger_commands(&self, debugger_prefix: &str) -> DebuggerCommands {
        let command_directive = format!("{}-command", debugger_prefix);
        let check_directive = format!("{}-check", debugger_prefix);

        let mut breakpoint_lines = vec!();
        let mut commands = vec!();
        let mut check_lines = vec!();
        let mut counter = 1;
        let reader = BufReader::new(File::open(&self.testpaths.file).unwrap());
        for line in reader.lines() {
            match line {
                Ok(line) => {
                    if line.contains("#break") {
                        breakpoint_lines.push(counter);
                    }

                    header::parse_name_value_directive(
                        &line,
                        &command_directive).map(|cmd| {
                            commands.push(cmd)
                        });

                    header::parse_name_value_directive(
                        &line,
                        &check_directive).map(|cmd| {
                            check_lines.push(cmd)
                        });
                }
                Err(e) => {
                    self.fatal(&format!("Error while parsing debugger commands: {}", e))
                }
            }
            counter += 1;
        }

        DebuggerCommands {
            commands: commands,
            check_lines: check_lines,
            breakpoint_lines: breakpoint_lines,
        }
    }

    fn cleanup_debug_info_options(&self, options: &Option<String>) -> Option<String> {
        if options.is_none() {
            return None;
        }

        // Remove options that are either unwanted (-O) or may lead to duplicates due to RUSTFLAGS.
        let options_to_remove = [
            "-O".to_owned(),
            "-g".to_owned(),
            "--debuginfo".to_owned()
        ];
        let new_options =
            self.split_maybe_args(options).into_iter()
                                          .filter(|x| !options_to_remove.contains(x))
                                          .collect::<Vec<String>>();

        Some(new_options.join(" "))
    }

    fn check_debugger_output(&self, debugger_run_result: &ProcRes, check_lines: &[String]) {
        let num_check_lines = check_lines.len();

        let mut check_line_index = 0;
        for line in debugger_run_result.stdout.lines() {
            if check_line_index >= num_check_lines {
                break;
            }

            if check_single_line(line, &(check_lines[check_line_index])[..]) {
                check_line_index += 1;
            }
        }
        if check_line_index != num_check_lines && num_check_lines > 0 {
            self.fatal_proc_rec(&format!("line not found in debugger output: {}",
                                         check_lines[check_line_index]),
                                debugger_run_result);
        }

        fn check_single_line(line: &str, check_line: &str) -> bool {
            // Allow check lines to leave parts unspecified (e.g., uninitialized
            // bits in the  wrong case of an enum) with the notation "[...]".
            let line = line.trim();
            let check_line = check_line.trim();
            let can_start_anywhere = check_line.starts_with("[...]");
            let can_end_anywhere = check_line.ends_with("[...]");

            let check_fragments: Vec<&str> = check_line.split("[...]")
                                                       .filter(|frag| !frag.is_empty())
                                                       .collect();
            if check_fragments.is_empty() {
                return true;
            }

            let (mut rest, first_fragment) = if can_start_anywhere {
                match line.find(check_fragments[0]) {
                    Some(pos) => (&line[pos + check_fragments[0].len() ..], 1),
                    None => return false
                }
            } else {
                (line, 0)
            };

            for fragment_index in first_fragment .. check_fragments.len() {
                let current_fragment = check_fragments[fragment_index];
                match rest.find(current_fragment) {
                    Some(pos) => {
                        rest = &rest[pos + current_fragment.len() .. ];
                    }
                    None => return false
                }
            }

            if !can_end_anywhere && !rest.is_empty() {
                return false;
            }

            return true;
        }
    }

    fn check_error_patterns(&self,
                            output_to_check: &str,
                            proc_res: &ProcRes) {
        if self.props.error_patterns.is_empty() {
            self.fatal(&format!("no error pattern specified in {:?}",
                                self.testpaths.file.display()));
        }
        let mut next_err_idx = 0;
        let mut next_err_pat = self.props.error_patterns[next_err_idx].trim();
        let mut done = false;
        for line in output_to_check.lines() {
            if line.contains(next_err_pat) {
                debug!("found error pattern {}", next_err_pat);
                next_err_idx += 1;
                if next_err_idx == self.props.error_patterns.len() {
                    debug!("found all error patterns");
                    done = true;
                    break;
                }
                next_err_pat = self.props.error_patterns[next_err_idx].trim();
            }
        }
        if done { return; }

        let missing_patterns = &self.props.error_patterns[next_err_idx..];
        if missing_patterns.len() == 1 {
            self.fatal_proc_rec(
                &format!("error pattern '{}' not found!", missing_patterns[0]),
                proc_res);
        } else {
            for pattern in missing_patterns {
                self.error(&format!("error pattern '{}' not found!", *pattern));
            }
            self.fatal_proc_rec("multiple error patterns not found", proc_res);
        }
    }

    fn check_no_compiler_crash(&self, proc_res: &ProcRes) {
        for line in proc_res.stderr.lines() {
            if line.starts_with("error: internal compiler error:") {
                self.fatal_proc_rec("compiler encountered internal error", proc_res);
            }
        }
    }

    fn check_forbid_output(&self,
                           output_to_check: &str,
                           proc_res: &ProcRes) {
        for pat in &self.props.forbid_output {
            if output_to_check.contains(pat) {
                self.fatal_proc_rec("forbidden pattern found in compiler output", proc_res);
            }
        }
    }

    fn check_expected_errors(&self,
                             expected_errors: Vec<errors::Error>,
                             proc_res: &ProcRes) {
        if proc_res.status.success() {
            self.fatal_proc_rec("process did not return an error status", proc_res);
        }

        let file_name =
            format!("{}", self.testpaths.file.display())
            .replace(r"\", "/"); // on windows, translate all '\' path separators to '/'

        // If the testcase being checked contains at least one expected "help"
        // message, then we'll ensure that all "help" messages are expected.
        // Otherwise, all "help" messages reported by the compiler will be ignored.
        // This logic also applies to "note" messages.
        let expect_help = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Help));
        let expect_note = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Note));

        // Parse the JSON output from the compiler and extract out the messages.
        let actual_errors = json::parse_output(&file_name, &proc_res.stderr, &proc_res);
        let mut unexpected = Vec::new();
        let mut found = vec![false; expected_errors.len()];
        for actual_error in &actual_errors {
            let opt_index =
                expected_errors
                .iter()
                .enumerate()
                .position(|(index, expected_error)| {
                    !found[index] &&
                        actual_error.line_num == expected_error.line_num &&
                        (expected_error.kind.is_none() ||
                         actual_error.kind == expected_error.kind) &&
                        actual_error.msg.contains(&expected_error.msg)
                });

            match opt_index {
                Some(index) => {
                    // found a match, everybody is happy
                    assert!(!found[index]);
                    found[index] = true;
                }

                None => {
                    if self.is_unexpected_compiler_message(actual_error, expect_help, expect_note) {
                        self.error(
                            &format!("{}:{}: unexpected {:?}: '{}'",
                                     file_name,
                                     actual_error.line_num,
                                     actual_error.kind.as_ref()
                                     .map_or(String::from("message"),
                                             |k| k.to_string()),
                                     actual_error.msg));
                        unexpected.push(actual_error.clone());
                    }
                }
            }
        }

        let mut not_found = Vec::new();
        // anything not yet found is a problem
        for (index, expected_error) in expected_errors.iter().enumerate() {
            if !found[index] {
                self.error(
                    &format!("{}:{}: expected {} not found: {}",
                             file_name,
                             expected_error.line_num,
                             expected_error.kind.as_ref()
                             .map_or("message".into(),
                                     |k| k.to_string()),
                             expected_error.msg));
                not_found.push(expected_error.clone());
            }
        }

        if unexpected.len() > 0 || not_found.len() > 0 {
            self.error(
                &format!("{} unexpected errors found, {} expected errors not found",
                         unexpected.len(), not_found.len()));
            print!("status: {}\ncommand: {}\n",
                   proc_res.status, proc_res.cmdline);
            if unexpected.len() > 0 {
                println!("unexpected errors (from JSON output): {:#?}\n", unexpected);
            }
            if not_found.len() > 0 {
                println!("not found errors (from test file): {:#?}\n", not_found);
            }
            panic!();
        }
    }

    /// Returns true if we should report an error about `actual_error`,
    /// which did not match any of the expected error. We always require
    /// errors/warnings to be explicitly listed, but only require
    /// helps/notes if there are explicit helps/notes given.
    fn is_unexpected_compiler_message(&self,
                                      actual_error: &Error,
                                      expect_help: bool,
                                      expect_note: bool)
                                      -> bool {
        match actual_error.kind {
            Some(ErrorKind::Help) => expect_help,
            Some(ErrorKind::Note) => expect_note,
            Some(ErrorKind::Error) => true,
            Some(ErrorKind::Warning) => true,
            Some(ErrorKind::Suggestion) => false,
            None => false
        }
    }

    fn compile_test(&self) -> ProcRes {
        let aux_dir = self.aux_output_dir_name();
        // FIXME (#9639): This needs to handle non-utf8 paths
        let link_args = vec!("-L".to_owned(),
                             aux_dir.to_str().unwrap().to_owned());
        let args = self.make_compile_args(link_args,
                                          &self.testpaths.file,
                                          TargetLocation::ThisFile(self.make_exe_name()));
        self.compose_and_run_compiler(args, None)
    }

    fn document(&self, out_dir: &Path) -> ProcRes {
        if self.props.build_aux_docs {
            for rel_ab in &self.props.aux_builds {
                let aux_testpaths = self.compute_aux_test_paths(rel_ab);
                let aux_props = self.props.from_aux_file(&aux_testpaths.file, self.revision);
                let aux_cx = TestCx {
                    config: self.config,
                    props: &aux_props,
                    testpaths: &aux_testpaths,
                    revision: self.revision
                };
                let auxres = aux_cx.document(out_dir);
                if !auxres.status.success() {
                    return auxres;
                }
            }
        }

        let aux_dir = self.aux_output_dir_name();
        let mut args = vec!["-L".to_owned(),
                            aux_dir.to_str().unwrap().to_owned(),
                            "-o".to_owned(),
                            out_dir.to_str().unwrap().to_owned(),
                            self.testpaths.file.to_str().unwrap().to_owned()];
        args.extend(self.props.compile_flags.iter().cloned());
        let args = ProcArgs {
            prog: self.config.rustdoc_path.to_str().unwrap().to_owned(),
            args: args,
        };
        self.compose_and_run_compiler(args, None)
    }

    fn exec_compiled_test(&self) -> ProcRes {
        let env = self.props.exec_env.clone();

        match &*self.config.target {

            "arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android" => {
                self._arm_exec_compiled_test(env)
            }

            _=> {
                let aux_dir = self.aux_output_dir_name();
                self.compose_and_run(self.make_run_args(),
                                     env,
                                     self.config.run_lib_path.to_str().unwrap(),
                                     Some(aux_dir.to_str().unwrap()),
                                     None)
            }
        }
    }

    /// For each `aux-build: foo/bar` annotation, we check to find the
    /// file in a `aux` directory relative to the test itself.
    fn compute_aux_test_paths(&self, rel_ab: &str) -> TestPaths {
        let test_ab = self.testpaths.file
                                    .parent()
                                    .expect("test file path has no parent")
                                    .join("auxiliary")
                                    .join(rel_ab);
        if !test_ab.exists() {
            self.fatal(&format!("aux-build `{}` source not found", test_ab.display()))
        }

        TestPaths {
            file: test_ab,
            base: self.testpaths.base.clone(),
            relative_dir: self.testpaths.relative_dir
                                        .join("auxiliary")
                                        .join(rel_ab)
                                        .parent()
                                        .expect("aux-build path has no parent")
                                        .to_path_buf()
        }
    }

    fn compose_and_run_compiler(&self, args: ProcArgs, input: Option<String>) -> ProcRes {
        if !self.props.aux_builds.is_empty() {
            self.create_dir_racy(&self.aux_output_dir_name());
        }

        let aux_dir = self.aux_output_dir_name();
        // FIXME (#9639): This needs to handle non-utf8 paths
        let extra_link_args = vec!["-L".to_owned(),
                                   aux_dir.to_str().unwrap().to_owned()];

        for rel_ab in &self.props.aux_builds {
            let aux_testpaths = self.compute_aux_test_paths(rel_ab);
            let aux_props = self.props.from_aux_file(&aux_testpaths.file, self.revision);
            let mut crate_type = if aux_props.no_prefer_dynamic {
                Vec::new()
            } else {
                // We primarily compile all auxiliary libraries as dynamic libraries
                // to avoid code size bloat and large binaries as much as possible
                // for the test suite (otherwise including libstd statically in all
                // executables takes up quite a bit of space).
                //
                // For targets like MUSL or Emscripten, however, there is no support for
                // dynamic libraries so we just go back to building a normal library. Note,
                // however, that for MUSL if the library is built with `force_host` then
                // it's ok to be a dylib as the host should always support dylibs.
                if (self.config.target.contains("musl") && !aux_props.force_host) ||
                    self.config.target.contains("emscripten")
                {
                    vec!("--crate-type=lib".to_owned())
                } else {
                    vec!("--crate-type=dylib".to_owned())
                }
            };
            crate_type.extend(extra_link_args.clone());
            let aux_output = {
                let f = self.make_lib_name(&self.testpaths.file);
                let parent = f.parent().unwrap();
                TargetLocation::ThisDirectory(parent.to_path_buf())
            };
            let aux_cx = TestCx {
                config: self.config,
                props: &aux_props,
                testpaths: &aux_testpaths,
                revision: self.revision
            };
            let aux_args = aux_cx.make_compile_args(crate_type, &aux_testpaths.file, aux_output);
            let auxres = aux_cx.compose_and_run(aux_args,
                                                Vec::new(),
                                                aux_cx.config.compile_lib_path.to_str().unwrap(),
                                                Some(aux_dir.to_str().unwrap()),
                                                None);
            if !auxres.status.success() {
                self.fatal_proc_rec(
                    &format!("auxiliary build of {:?} failed to compile: ",
                             aux_testpaths.file.display()),
                    &auxres);
            }

            match &*self.config.target {
                "arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android" => {
                    self._arm_push_aux_shared_library();
                }
                _ => {}
            }
        }

        self.compose_and_run(args,
                             self.props.rustc_env.clone(),
                             self.config.compile_lib_path.to_str().unwrap(),
                             Some(aux_dir.to_str().unwrap()),
                             input)
    }

    // Like std::fs::create_dir_all, except handles concurrent calls among multiple
    // threads or processes.
    fn create_dir_racy(&self, path: &Path) {
        match fs::create_dir(path) {
            Ok(()) => return,
            Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => return,
            Err(ref e) if e.kind() == io::ErrorKind::NotFound => {}
            Err(e) => panic!("failed to create dir {:?}: {}", path, e),
        }
        self.create_dir_racy(path.parent().unwrap());
        match fs::create_dir(path) {
            Ok(()) => {}
            Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => {}
            Err(e) => panic!("failed to create dir {:?}: {}", path, e),
        }
    }

    fn compose_and_run(&self,
                       ProcArgs{ args, prog }: ProcArgs,
                       procenv: Vec<(String, String)> ,
                       lib_path: &str,
                       aux_path: Option<&str>,
                       input: Option<String>) -> ProcRes {
        return self.program_output(lib_path, prog, aux_path, args, procenv, input);
    }

    fn make_compile_args(&self,
                         extras: Vec<String> ,
                         input_file: &Path,
                         output_file: TargetLocation)
                         -> ProcArgs
    {
        let target = if self.props.force_host {
            &*self.config.host
        } else {
            &*self.config.target
        };

        // FIXME (#9639): This needs to handle non-utf8 paths
        let mut args = vec!(input_file.to_str().unwrap().to_owned(),
                            "-L".to_owned(),
                            self.config.build_base.to_str().unwrap().to_owned(),
                            format!("--target={}", target));

        if let Some(revision) = self.revision {
            args.extend(vec![
                format!("--cfg"),
                format!("{}", revision),
            ]);
        }

        if let Some(ref incremental_dir) = self.props.incremental_dir {
            args.extend(vec![
                format!("-Z"),
                format!("incremental={}", incremental_dir.display()),
            ]);
        }


        match self.config.mode {
            CompileFail |
            ParseFail |
            Incremental => {
                // If we are extracting and matching errors in the new
                // fashion, then you want JSON mode. Old-skool error
                // patterns still match the raw compiler output.
                if self.props.error_patterns.is_empty() {
                    args.extend(["--error-format",
                                 "json",
                                 "-Z",
                                 "unstable-options"]
                                .iter()
                                .map(|s| s.to_string()));
                }
            }
            MirOpt => {
                args.extend(["-Z",
                             "dump-mir=all",
                             "-Z"]
                            .iter()
                            .map(|s| s.to_string()));


                let mir_dump_dir = self.get_mir_dump_dir();
                self.create_dir_racy(mir_dump_dir.as_path());
                let mut dir_opt = "dump-mir-dir=".to_string();
                dir_opt.push_str(mir_dump_dir.to_str().unwrap());
                debug!("dir_opt: {:?}", dir_opt);

                args.push(dir_opt);
            }
            RunFail |
            RunPass |
            RunPassValgrind |
            Pretty |
            DebugInfoGdb |
            DebugInfoLldb |
            Codegen |
            Rustdoc |
            RunMake |
            Ui |
            CodegenUnits => {
                // do not use JSON output
            }
        }

        args.extend_from_slice(&extras);
        if !self.props.no_prefer_dynamic {
            args.push("-C".to_owned());
            args.push("prefer-dynamic".to_owned());
        }
        let path = match output_file {
            TargetLocation::ThisFile(path) => {
                args.push("-o".to_owned());
                path
            }
            TargetLocation::ThisDirectory(path) => {
                args.push("--out-dir".to_owned());
                path
            }
        };
        args.push(path.to_str().unwrap().to_owned());
        if self.props.force_host {
            args.extend(self.split_maybe_args(&self.config.host_rustcflags));
        } else {
            args.extend(self.split_maybe_args(&self.config.target_rustcflags));
        }
        args.extend(self.props.compile_flags.iter().cloned());
        return ProcArgs {
            prog: self.config.rustc_path.to_str().unwrap().to_owned(),
            args: args,
        };
    }

    fn make_lib_name(&self, auxfile: &Path) -> PathBuf {
        // what we return here is not particularly important, as it
        // happens; rustc ignores everything except for the directory.
        let auxname = self.output_testname(auxfile);
        self.aux_output_dir_name().join(&auxname)
    }

    fn make_exe_name(&self) -> PathBuf {
        let mut f = self.output_base_name();
        // FIXME: This is using the host architecture exe suffix, not target!
        if self.config.target == "asmjs-unknown-emscripten" {
            let mut fname = f.file_name().unwrap().to_os_string();
            fname.push(".js");
            f.set_file_name(&fname);
        } else if !env::consts::EXE_SUFFIX.is_empty() {
            let mut fname = f.file_name().unwrap().to_os_string();
            fname.push(env::consts::EXE_SUFFIX);
            f.set_file_name(&fname);
        }
        f
    }

    fn make_run_args(&self) -> ProcArgs {
        // If we've got another tool to run under (valgrind),
        // then split apart its command
        let mut args = self.split_maybe_args(&self.config.runtool);

        // If this is emscripten, then run tests under nodejs
        if self.config.target == "asmjs-unknown-emscripten" {
            args.push("nodejs".to_owned());
        }

        let exe_file = self.make_exe_name();

        // FIXME (#9639): This needs to handle non-utf8 paths
        args.push(exe_file.to_str().unwrap().to_owned());

        // Add the arguments in the run_flags directive
        args.extend(self.split_maybe_args(&self.props.run_flags));

        let prog = args.remove(0);
        return ProcArgs {
            prog: prog,
            args: args,
        };
    }

    fn split_maybe_args(&self, argstr: &Option<String>) -> Vec<String> {
        match *argstr {
            Some(ref s) => {
                s
                    .split(' ')
                    .filter_map(|s| {
                        if s.chars().all(|c| c.is_whitespace()) {
                            None
                        } else {
                            Some(s.to_owned())
                        }
                    }).collect()
            }
            None => Vec::new()
        }
    }

    fn program_output(&self,
                      lib_path: &str,
                      prog: String,
                      aux_path: Option<&str>,
                      args: Vec<String>,
                      env: Vec<(String, String)>,
                      input: Option<String>)
                      -> ProcRes {
        let cmdline =
        {
            let cmdline = self.make_cmdline(lib_path,
                                            &prog,
                                            &args);
            logv(self.config, format!("executing {}", cmdline));
            cmdline
        };
        let procsrv::Result {
            out,
            err,
            status
        } = procsrv::run(lib_path,
                         &prog,
                         aux_path,
                         &args,
                         env,
                         input).expect(&format!("failed to exec `{}`", prog));
        self.dump_output(&out, &err);
        return ProcRes {
            status: Status::Normal(status),
            stdout: out,
            stderr: err,
            cmdline: cmdline,
        };
    }

    fn make_cmdline(&self, libpath: &str, prog: &str, args: &[String]) -> String {
        use util;

        // Linux and mac don't require adjusting the library search path
        if cfg!(unix) {
            format!("{} {}", prog, args.join(" "))
        } else {
            // Build the LD_LIBRARY_PATH variable as it would be seen on the command line
            // for diagnostic purposes
            fn lib_path_cmd_prefix(path: &str) -> String {
                format!("{}=\"{}\"", util::lib_path_env_var(), util::make_new_path(path))
            }

            format!("{} {} {}", lib_path_cmd_prefix(libpath), prog, args.join(" "))
        }
    }

    fn dump_output(&self, out: &str, err: &str) {
        self.dump_output_file(out, "out");
        self.dump_output_file(err, "err");
        self.maybe_dump_to_stdout(out, err);
    }

    fn dump_output_file(&self,
                        out: &str,
                        extension: &str) {
        let outfile = self.make_out_name(extension);
        File::create(&outfile).unwrap().write_all(out.as_bytes()).unwrap();
    }

    fn make_out_name(&self, extension: &str) -> PathBuf {
        self.output_base_name().with_extension(extension)
    }

    fn aux_output_dir_name(&self) -> PathBuf {
        let f = self.output_base_name();
        let mut fname = f.file_name().unwrap().to_os_string();
        fname.push(&format!(".{}.libaux", self.config.mode));
        f.with_file_name(&fname)
    }

    fn output_testname(&self, filepath: &Path) -> PathBuf {
        PathBuf::from(filepath.file_stem().unwrap())
    }

    /// Given a test path like `compile-fail/foo/bar.rs` Returns a name like
    ///
    ///     <output>/foo/bar-stage1
    fn output_base_name(&self) -> PathBuf {
        let dir = self.config.build_base.join(&self.testpaths.relative_dir);

        // Note: The directory `dir` is created during `collect_tests_from_dir`
        dir
            .join(&self.output_testname(&self.testpaths.file))
            .with_extension(&self.config.stage_id)
    }

    fn maybe_dump_to_stdout(&self, out: &str, err: &str) {
        if self.config.verbose {
            println!("------{}------------------------------", "stdout");
            println!("{}", out);
            println!("------{}------------------------------", "stderr");
            println!("{}", err);
            println!("------------------------------------------");
        }
    }

    fn error(&self, err: &str) {
        match self.revision {
            Some(rev) => println!("\nerror in revision `{}`: {}", rev, err),
            None => println!("\nerror: {}", err)
        }
    }

    fn fatal(&self, err: &str) -> ! {
        self.error(err); panic!();
    }

    fn fatal_proc_rec(&self, err: &str, proc_res: &ProcRes) -> ! {
        self.error(err);
        proc_res.fatal(None);
    }

    fn _arm_exec_compiled_test(&self, env: Vec<(String, String)>) -> ProcRes {
        let args = self.make_run_args();
        let cmdline = self.make_cmdline("", &args.prog, &args.args);

        // get bare program string
        let mut tvec: Vec<String> = args.prog
                                        .split('/')
                                        .map(str::to_owned)
                                        .collect();
        let prog_short = tvec.pop().unwrap();

        // copy to target
        let copy_result = procsrv::run("",
                                       &self.config.adb_path,
                                       None,
                                       &[
                                           "push".to_owned(),
                                           args.prog.clone(),
                                           self.config.adb_test_dir.clone()
                                       ],
                                       vec!(("".to_owned(), "".to_owned())),
                                       Some("".to_owned()))
            .expect(&format!("failed to exec `{}`", self.config.adb_path));

        if self.config.verbose {
            println!("push ({}) {} {} {}",
                     self.config.target,
                     args.prog,
                     copy_result.out,
                     copy_result.err);
        }

        logv(self.config, format!("executing ({}) {}", self.config.target, cmdline));

        let mut runargs = Vec::new();

        // run test via adb_run_wrapper
        runargs.push("shell".to_owned());
        for (key, val) in env {
            runargs.push(format!("{}={}", key, val));
        }
        runargs.push(format!("{}/../adb_run_wrapper.sh", self.config.adb_test_dir));
        runargs.push(format!("{}", self.config.adb_test_dir));
        runargs.push(format!("{}", prog_short));

        for tv in &args.args {
            runargs.push(tv.to_owned());
        }
        procsrv::run("",
                     &self.config.adb_path,
                     None,
                     &runargs,
                     vec!(("".to_owned(), "".to_owned())), Some("".to_owned()))
            .expect(&format!("failed to exec `{}`", self.config.adb_path));

        // get exitcode of result
        runargs = Vec::new();
        runargs.push("shell".to_owned());
        runargs.push("cat".to_owned());
        runargs.push(format!("{}/{}.exitcode", self.config.adb_test_dir, prog_short));

        let procsrv::Result{ out: exitcode_out, err: _, status: _ } =
            procsrv::run("",
                         &self.config.adb_path,
                         None,
                         &runargs,
                         vec!(("".to_owned(), "".to_owned())),
                         Some("".to_owned()))
            .expect(&format!("failed to exec `{}`", self.config.adb_path));

        let mut exitcode: i32 = 0;
        for c in exitcode_out.chars() {
            if !c.is_numeric() { break; }
            exitcode = exitcode * 10 + match c {
                '0' ... '9' => c as i32 - ('0' as i32),
                _ => 101,
            }
        }

        // get stdout of result
        runargs = Vec::new();
        runargs.push("shell".to_owned());
        runargs.push("cat".to_owned());
        runargs.push(format!("{}/{}.stdout", self.config.adb_test_dir, prog_short));

        let procsrv::Result{ out: stdout_out, err: _, status: _ } =
            procsrv::run("",
                         &self.config.adb_path,
                         None,
                         &runargs,
                         vec!(("".to_owned(), "".to_owned())),
                         Some("".to_owned()))
            .expect(&format!("failed to exec `{}`", self.config.adb_path));

        // get stderr of result
        runargs = Vec::new();
        runargs.push("shell".to_owned());
        runargs.push("cat".to_owned());
        runargs.push(format!("{}/{}.stderr", self.config.adb_test_dir, prog_short));

        let procsrv::Result{ out: stderr_out, err: _, status: _ } =
            procsrv::run("",
                         &self.config.adb_path,
                         None,
                         &runargs,
                         vec!(("".to_owned(), "".to_owned())),
                         Some("".to_owned()))
            .expect(&format!("failed to exec `{}`", self.config.adb_path));

        self.dump_output(&stdout_out, &stderr_out);

        ProcRes {
            status: Status::Parsed(exitcode),
            stdout: stdout_out,
            stderr: stderr_out,
            cmdline: cmdline
        }
    }

    fn _arm_push_aux_shared_library(&self) {
        let tdir = self.aux_output_dir_name();

        let dirs = fs::read_dir(&tdir).unwrap();
        for file in dirs {
            let file = file.unwrap().path();
            if file.extension().and_then(|s| s.to_str()) == Some("so") {
                // FIXME (#9639): This needs to handle non-utf8 paths
                let copy_result = procsrv::run("",
                                               &self.config.adb_path,
                                               None,
                                               &[
                                                   "push".to_owned(),
                                                   file.to_str()
                                                       .unwrap()
                                                       .to_owned(),
                                                   self.config.adb_test_dir.to_owned(),
                                               ],
                                               vec!(("".to_owned(),
                                                     "".to_owned())),
                                               Some("".to_owned()))
                    .expect(&format!("failed to exec `{}`", self.config.adb_path));

                if self.config.verbose {
                    println!("push ({}) {:?} {} {}",
                             self.config.target, file.display(),
                             copy_result.out, copy_result.err);
                }
            }
        }
    }

    // codegen tests (using FileCheck)

    fn compile_test_and_save_ir(&self) -> ProcRes {
        let aux_dir = self.aux_output_dir_name();
        // FIXME (#9639): This needs to handle non-utf8 paths
        let mut link_args = vec!("-L".to_owned(),
                                 aux_dir.to_str().unwrap().to_owned());
        let llvm_args = vec!("--emit=llvm-ir".to_owned(),);
        link_args.extend(llvm_args);
        let args = self.make_compile_args(link_args,
                                          &self.testpaths.file,
                                          TargetLocation::ThisDirectory(
                                              self.output_base_name().parent()
                                                                     .unwrap()
                                                                     .to_path_buf()));
        self.compose_and_run_compiler(args, None)
    }

    fn check_ir_with_filecheck(&self) -> ProcRes {
        let irfile = self.output_base_name().with_extension("ll");
        let prog = self.config.llvm_filecheck.as_ref().unwrap();
        let proc_args = ProcArgs {
            // FIXME (#9639): This needs to handle non-utf8 paths
            prog: prog.to_str().unwrap().to_owned(),
            args: vec!(format!("-input-file={}", irfile.to_str().unwrap()),
                       self.testpaths.file.to_str().unwrap().to_owned())
        };
        self.compose_and_run(proc_args, Vec::new(), "", None, None)
    }

    fn run_codegen_test(&self) {
        assert!(self.revision.is_none(), "revisions not relevant here");

        if self.config.llvm_filecheck.is_none() {
            self.fatal("missing --llvm-filecheck");
        }

        let mut proc_res = self.compile_test_and_save_ir();
        if !proc_res.status.success() {
            self.fatal_proc_rec("compilation failed!", &proc_res);
        }

        proc_res = self.check_ir_with_filecheck();
        if !proc_res.status.success() {
            self.fatal_proc_rec("verification with 'FileCheck' failed", &proc_res);
        }
    }

    fn charset() -> &'static str {
        // FreeBSD 10.1 defaults to GDB 6.1.1 which doesn't support "auto" charset
        if cfg!(target_os = "bitrig") {
            "auto"
        } else if cfg!(target_os = "freebsd") {
            "ISO-8859-1"
        } else {
            "UTF-8"
        }
    }

    fn run_rustdoc_test(&self) {
        assert!(self.revision.is_none(), "revisions not relevant here");

        let out_dir = self.output_base_name();
        let _ = fs::remove_dir_all(&out_dir);
        self.create_dir_racy(&out_dir);

        let proc_res = self.document(&out_dir);
        if !proc_res.status.success() {
            self.fatal_proc_rec("rustdoc failed!", &proc_res);
        }
        let root = self.find_rust_src_root().unwrap();

        let res = self.cmd2procres(Command::new(&self.config.docck_python)
                                   .arg(root.join("src/etc/htmldocck.py"))
                                   .arg(out_dir)
                                   .arg(&self.testpaths.file));
        if !res.status.success() {
            self.fatal_proc_rec("htmldocck failed!", &res);
        }
    }

    fn run_codegen_units_test(&self) {
        assert!(self.revision.is_none(), "revisions not relevant here");

        let proc_res = self.compile_test();

        if !proc_res.status.success() {
            self.fatal_proc_rec("compilation failed!", &proc_res);
        }

        self.check_no_compiler_crash(&proc_res);

        const PREFIX: &'static str = "TRANS_ITEM ";
        const CGU_MARKER: &'static str = "@@";

        let actual: Vec<TransItem> = proc_res
            .stdout
            .lines()
            .filter(|line| line.starts_with(PREFIX))
            .map(str_to_trans_item)
            .collect();

        let expected: Vec<TransItem> = errors::load_errors(&self.testpaths.file, None)
            .iter()
            .map(|e| str_to_trans_item(&e.msg[..]))
            .collect();

        let mut missing = Vec::new();
        let mut wrong_cgus = Vec::new();

        for expected_item in &expected {
            let actual_item_with_same_name = actual.iter()
                                                   .find(|ti| ti.name == expected_item.name);

            if let Some(actual_item) = actual_item_with_same_name {
                if !expected_item.codegen_units.is_empty() {
                    // Also check for codegen units
                    if expected_item.codegen_units != actual_item.codegen_units {
                        wrong_cgus.push((expected_item.clone(), actual_item.clone()));
                    }
                }
            } else {
                missing.push(expected_item.string.clone());
            }
        }

        let unexpected: Vec<_> =
            actual.iter()
                  .filter(|acgu| !expected.iter().any(|ecgu| acgu.name == ecgu.name))
                  .map(|acgu| acgu.string.clone())
                  .collect();

        if !missing.is_empty() {
            missing.sort();

            println!("\nThese items should have been contained but were not:\n");

            for item in &missing {
                println!("{}", item);
            }

            println!("\n");
        }

        if !unexpected.is_empty() {
            let sorted = {
                let mut sorted = unexpected.clone();
                sorted.sort();
                sorted
            };

            println!("\nThese items were contained but should not have been:\n");

            for item in sorted {
                println!("{}", item);
            }

            println!("\n");
        }

        if !wrong_cgus.is_empty() {
            wrong_cgus.sort_by_key(|pair| pair.0.name.clone());
            println!("\nThe following items were assigned to wrong codegen units:\n");

            for &(ref expected_item, ref actual_item) in &wrong_cgus {
                println!("{}", expected_item.name);
                println!("  expected: {}", codegen_units_to_str(&expected_item.codegen_units));
                println!("  actual:   {}", codegen_units_to_str(&actual_item.codegen_units));
                println!("");
            }
        }

        if !(missing.is_empty() && unexpected.is_empty() && wrong_cgus.is_empty())
        {
            panic!();
        }

        #[derive(Clone, Eq, PartialEq)]
        struct TransItem {
            name: String,
            codegen_units: HashSet<String>,
            string: String,
        }

        // [TRANS_ITEM] name [@@ (cgu)+]
        fn str_to_trans_item(s: &str) -> TransItem {
            let s = if s.starts_with(PREFIX) {
                (&s[PREFIX.len()..]).trim()
            } else {
                s.trim()
            };

            let full_string = format!("{}{}", PREFIX, s.trim().to_owned());

            let parts: Vec<&str> = s.split(CGU_MARKER)
                                    .map(str::trim)
                                    .filter(|s| !s.is_empty())
                                    .collect();

            let name = parts[0].trim();

            let cgus = if parts.len() > 1 {
                let cgus_str = parts[1];

                cgus_str.split(" ")
                        .map(str::trim)
                        .filter(|s| !s.is_empty())
                        .map(str::to_owned)
                        .collect()
            }
            else {
                HashSet::new()
            };

            TransItem {
                name: name.to_owned(),
                codegen_units: cgus,
                string: full_string,
            }
        }

        fn codegen_units_to_str(cgus: &HashSet<String>) -> String
        {
            let mut cgus: Vec<_> = cgus.iter().collect();
            cgus.sort();

            let mut string = String::new();
            for cgu in cgus {
                string.push_str(&cgu[..]);
                string.push_str(" ");
            }

            string
        }
    }

    fn init_incremental_test(&self) {
        // (See `run_incremental_test` for an overview of how incremental tests work.)

        // Before any of the revisions have executed, create the
        // incremental workproduct directory.  Delete any old
        // incremental work products that may be there from prior
        // runs.
        let incremental_dir = self.incremental_dir();
        if incremental_dir.exists() {
            fs::remove_dir_all(&incremental_dir).unwrap();
        }
        fs::create_dir_all(&incremental_dir).unwrap();

        if self.config.verbose {
            print!("init_incremental_test: incremental_dir={}", incremental_dir.display());
        }
    }

    fn run_incremental_test(&self) {
        // Basic plan for a test incremental/foo/bar.rs:
        // - load list of revisions rpass1, cfail2, rpass3
        //   - each should begin with `rpass`, `cfail`, or `cfail`
        //   - if `rpass`, expect compile and execution to succeed
        //   - if `cfail`, expect compilation to fail
        //   - if `rfail`, expect execution to fail
        // - create a directory build/foo/bar.incremental
        // - compile foo/bar.rs with -Z incremental=.../foo/bar.incremental and -C rpass1
        //   - because name of revision starts with "rpass", expect success
        // - compile foo/bar.rs with -Z incremental=.../foo/bar.incremental and -C cfail2
        //   - because name of revision starts with "cfail", expect an error
        //   - load expected errors as usual, but filter for those that end in `[rfail2]`
        // - compile foo/bar.rs with -Z incremental=.../foo/bar.incremental and -C rpass3
        //   - because name of revision starts with "rpass", expect success
        // - execute build/foo/bar.exe and save output
        //
        // FIXME -- use non-incremental mode as an oracle? That doesn't apply
        // to #[rustc_dirty] and clean tests I guess

        let revision = self.revision.expect("incremental tests require a list of revisions");

        // Incremental workproduct directory should have already been created.
        let incremental_dir = self.incremental_dir();
        assert!(incremental_dir.exists(), "init_incremental_test failed to create incremental dir");

        // Add an extra flag pointing at the incremental directory.
        let mut revision_props = self.props.clone();
        revision_props.incremental_dir = Some(incremental_dir);

        let revision_cx = TestCx {
            config: self.config,
            props: &revision_props,
            testpaths: self.testpaths,
            revision: self.revision,
        };

        if self.config.verbose {
            print!("revision={:?} revision_props={:#?}", revision, revision_props);
        }

        if revision.starts_with("rpass") {
            revision_cx.run_rpass_test();
        } else if revision.starts_with("rfail") {
            revision_cx.run_rfail_test();
        } else if revision.starts_with("cfail") {
            revision_cx.run_cfail_test();
        } else {
            revision_cx.fatal(
                "revision name must begin with rpass, rfail, or cfail");
        }
    }

    /// Directory where incremental work products are stored.
    fn incremental_dir(&self) -> PathBuf {
        self.output_base_name().with_extension("incremental")
    }

    fn run_rmake_test(&self) {
        // FIXME(#11094): we should fix these tests
        if self.config.host != self.config.target {
            return
        }

        let cwd = env::current_dir().unwrap();
        let src_root = self.config.src_base.parent().unwrap()
                                           .parent().unwrap()
                                           .parent().unwrap();
        let src_root = cwd.join(&src_root);

        let tmpdir = cwd.join(self.output_base_name());
        if tmpdir.exists() {
            self.aggressive_rm_rf(&tmpdir).unwrap();
        }
        self.create_dir_racy(&tmpdir);

        let mut cmd = Command::new("make");
        cmd.current_dir(&self.testpaths.file)
           .env("TARGET", &self.config.target)
           .env("PYTHON", &self.config.docck_python)
           .env("S", src_root)
           .env("RUST_BUILD_STAGE", &self.config.stage_id)
           .env("RUSTC", cwd.join(&self.config.rustc_path))
           .env("RUSTDOC", cwd.join(&self.config.rustdoc_path))
           .env("TMPDIR", &tmpdir)
           .env("LD_LIB_PATH_ENVVAR", procsrv::dylib_env_var())
           .env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path))
           .env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path))
           .env("LLVM_COMPONENTS", &self.config.llvm_components)
           .env("LLVM_CXXFLAGS", &self.config.llvm_cxxflags);

        if self.config.target.contains("msvc") {
            // We need to pass a path to `lib.exe`, so assume that `cc` is `cl.exe`
            // and that `lib.exe` lives next to it.
            let lib = Path::new(&self.config.cc).parent().unwrap().join("lib.exe");

            // MSYS doesn't like passing flags of the form `/foo` as it thinks it's
            // a path and instead passes `C:\msys64\foo`, so convert all
            // `/`-arguments to MSVC here to `-` arguments.
            let cflags = self.config.cflags.split(' ').map(|s| s.replace("/", "-"))
                                                 .collect::<Vec<_>>().join(" ");

            cmd.env("IS_MSVC", "1")
               .env("MSVC_LIB", format!("'{}' -nologo", lib.display()))
               .env("CC", format!("'{}' {}", self.config.cc, cflags))
               .env("CXX", &self.config.cxx);
        } else {
            cmd.env("CC", format!("{} {}", self.config.cc, self.config.cflags))
               .env("CXX", format!("{} {}", self.config.cxx, self.config.cflags));
        }

        let output = cmd.output().expect("failed to spawn `make`");
        if !output.status.success() {
            let res = ProcRes {
                status: Status::Normal(output.status),
                stdout: String::from_utf8_lossy(&output.stdout).into_owned(),
                stderr: String::from_utf8_lossy(&output.stderr).into_owned(),
                cmdline: format!("{:?}", cmd),
            };
            self.fatal_proc_rec("make failed", &res);
        }
    }

    fn aggressive_rm_rf(&self, path: &Path) -> io::Result<()> {
        for e in try!(path.read_dir()) {
            let entry = try!(e);
            let path = entry.path();
            if try!(entry.file_type()).is_dir() {
                try!(self.aggressive_rm_rf(&path));
            } else {
                // Remove readonly files as well on windows (by default we can't)
                try!(fs::remove_file(&path).or_else(|e| {
                    if cfg!(windows) && e.kind() == io::ErrorKind::PermissionDenied {
                        let mut meta = try!(entry.metadata()).permissions();
                        meta.set_readonly(false);
                        try!(fs::set_permissions(&path, meta));
                        fs::remove_file(&path)
                    } else {
                        Err(e)
                    }
                }))
            }
        }
        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, &expected_stdout);
        errors += self.compare_output("stderr", &normalized_stderr, &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_proc_rec(&format!("{} errors occurred comparing output.", errors),
                                &proc_res);
        }
    }

    fn run_mir_opt_test(&self) {
        let proc_res = self.compile_test();

        if !proc_res.status.success() {
            self.fatal_proc_rec("compilation failed!", &proc_res);
        }

        let proc_res = self.exec_compiled_test();

        if !proc_res.status.success() {
            self.fatal_proc_rec("test run failed!", &proc_res);
        }
        self.check_mir_dump();
    }

    fn check_mir_dump(&self) {
        let mut test_file_contents = String::new();
        fs::File::open(self.testpaths.file.clone()).unwrap()
                                                   .read_to_string(&mut test_file_contents)
                                                   .unwrap();
        if let Some(idx) =  test_file_contents.find("// END RUST SOURCE") {
            let (_, tests_text) = test_file_contents.split_at(idx + "// END_RUST SOURCE".len());
            let tests_text_str = String::from(tests_text);
            let mut curr_test : Option<&str> = None;
            let mut curr_test_contents = Vec::new();
            for l in tests_text_str.lines() {
                debug!("line: {:?}", l);
                if l.starts_with("// START ") {
                    let (_, t) = l.split_at("// START ".len());
                    curr_test = Some(t);
                } else if l.starts_with("// END") {
                    let (_, t) = l.split_at("// END ".len());
                    if Some(t) != curr_test {
                        panic!("mismatched START END test name");
                    }
                    self.compare_mir_test_output(curr_test.unwrap(), &curr_test_contents);
                    curr_test = None;
                    curr_test_contents.clear();
                } else if l.is_empty() {
                    // ignore
                } else if l.starts_with("// ") {
                    let (_, test_content) = l.split_at("// ".len());
                    curr_test_contents.push(test_content);
                }
            }
        }
    }

    fn compare_mir_test_output(&self, test_name: &str, expected_content: &Vec<&str>) {
        let mut output_file = PathBuf::new();
        output_file.push(self.get_mir_dump_dir());
        output_file.push(test_name);
        debug!("comparing the contests of: {:?}", output_file);
        debug!("with: {:?}", expected_content);

        let mut dumped_file = fs::File::open(output_file.clone()).unwrap();
        let mut dumped_string = String::new();
        dumped_file.read_to_string(&mut dumped_string).unwrap();
        let mut dumped_lines = dumped_string.lines().filter(|l| !l.is_empty());
        let mut expected_lines = expected_content.iter().filter(|l| !l.is_empty());

        // We expect each non-empty line from expected_content to appear
        // in the dump in order, but there may be extra lines interleaved
        while let Some(expected_line) = expected_lines.next() {
            let e_norm = normalize_mir_line(expected_line);
            if e_norm.is_empty() {
                continue;
            };
            let mut found = false;
            while let Some(dumped_line) = dumped_lines.next() {
                let d_norm = normalize_mir_line(dumped_line);
                debug!("found: {:?}", d_norm);
                debug!("expected: {:?}", e_norm);
                if e_norm == d_norm {
                    found = true;
                    break;
                };
            }
            if !found {
                panic!("ran out of mir dump output to match against");
            }
        }
    }

    fn get_mir_dump_dir(&self) -> PathBuf {
        let mut mir_dump_dir = PathBuf::from(self.config.build_base
                                                    .as_path()
                                                    .to_str()
                                                    .unwrap());
        debug!("input_file: {:?}", self.testpaths.file);
        mir_dump_dir.push(self.testpaths.file.file_stem().unwrap().to_str().unwrap());
        mir_dump_dir
    }

    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("\\", "/") // normalize for paths on windows
              .replace("\r\n", "\n") // normalize for linebreaks on windows
              .replace("\t", "\\t") // makes tabs visible
    }

    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) -> String {
        if !path.exists() {
            return String::new();
        }

        let mut result = String::new();
        match File::open(path).and_then(|mut f| f.read_to_string(&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: &str, expected: &str) -> usize {
        if actual == expected {
            return 0;
        }

        println!("normalized {}:\n{}\n", kind, actual);
        println!("expected {}:\n{}\n", kind, expected);
        println!("diff of {}:\n", kind);
        for line in uidiff::diff_lines(actual, expected) {
            println!("{}", line);
        }

        let output_file = self.output_base_name().with_extension(kind);
        match File::create(&output_file).and_then(|mut f| f.write_all(actual.as_bytes())) {
            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 {
    prog: String,
    args: Vec<String>,
}

pub struct ProcRes {
    status: Status,
    stdout: String,
    stderr: String,
    cmdline: String,
}

enum Status {
    Parsed(i32),
    Normal(ExitStatus),
}

impl ProcRes {
    pub fn fatal(&self, err: Option<&str>) -> ! {
        if let Some(e) = err {
            println!("\nerror: {}", e);
        }
        print!("\
            status: {}\n\
            command: {}\n\
            stdout:\n\
            ------------------------------------------\n\
            {}\n\
            ------------------------------------------\n\
            stderr:\n\
            ------------------------------------------\n\
            {}\n\
            ------------------------------------------\n\
            \n",
               self.status, self.cmdline, self.stdout,
               self.stderr);
        panic!();
    }
}

impl Status {
    fn code(&self) -> Option<i32> {
        match *self {
            Status::Parsed(i) => Some(i),
            Status::Normal(ref e) => e.code(),
        }
    }

    fn success(&self) -> bool {
        match *self {
            Status::Parsed(i) => i == 0,
            Status::Normal(ref e) => e.success(),
        }
    }
}

impl fmt::Display for Status {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Status::Parsed(i) => write!(f, "exit code: {}", i),
            Status::Normal(ref e) => e.fmt(f),
        }
    }
}

enum TargetLocation {
    ThisFile(PathBuf),
    ThisDirectory(PathBuf),
}

fn normalize_mir_line(line: &str) -> String {
    let no_comments = if let Some(idx) = line.find("//") {
        let (l, _) = line.split_at(idx);
        l
    } else {
        line
    };
    no_comments.replace(char::is_whitespace, "")
}
