Skip to main content

compiletest/runtest/
incremental.rs

1use super::{FailMode, TestCx, WillExecute};
2use crate::errors;
3
4impl TestCx<'_> {
5    pub(super) fn run_incremental_test(&self) {
6        // Basic plan for a test incremental/foo/bar.rs:
7        // - load list of revisions rpass1, cfail2, rpass3
8        //   - each should begin with `cfail`, `cpass`, or `rpass`
9        //   - if `cpass`, expect compilation to succeed, don't execute
10        //   - if `rpass`, expect compilation and execution to succeed
11        //   - if `cfail`, expect compilation to fail
12        // - create a directory build/foo/bar.incremental
13        // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C rpass1
14        //   - because name of revision starts with "rpass", expect success
15        // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C cfail2
16        //   - because name of revision starts with "cfail", expect an error
17        //   - load expected errors as usual, but filter for those with `[cfail2]`
18        // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C rpass3
19        //   - because name of revision starts with "rpass", expect success
20        // - execute build/foo/bar.exe and save output
21        //
22        // FIXME -- use non-incremental mode as an oracle? That doesn't apply
23        // to #[rustc_clean] tests I guess
24
25        let revision = self.revision.expect("incremental tests require a list of revisions");
26
27        // Incremental workproduct directory should have already been created.
28        let incremental_dir = self.props.incremental_dir.as_ref().unwrap();
29        assert!(incremental_dir.exists(), "init_incremental_test failed to create incremental dir");
30
31        if self.config.verbose {
32            write!(self.stdout, "revision={:?} props={:#?}", revision, self.props);
33        }
34
35        if revision.starts_with("cpass") {
36            if self.props.should_ice {
37                self.fatal("can only use should-ice in cfail tests");
38            }
39            self.run_cpass_test();
40        } else if revision.starts_with("rpass") {
41            if self.props.should_ice {
42                self.fatal("can only use should-ice in cfail tests");
43            }
44            self.run_rpass_test();
45        } else if revision.starts_with("cfail") {
46            self.run_cfail_test();
47        } else {
48            self.fatal("revision name must begin with `cfail`, `cpass`, or `rpass`");
49        }
50    }
51
52    fn run_cpass_test(&self) {
53        let emit_metadata = self.should_emit_metadata(self.pass_mode());
54        let proc_res = self.compile_test(WillExecute::No, emit_metadata);
55
56        if !proc_res.status.success() {
57            self.fatal_proc_rec("compilation failed!", &proc_res);
58        }
59
60        // FIXME(#41968): Move this check to tidy?
61        if !errors::load_errors(&self.testpaths.file, self.revision).is_empty() {
62            self.fatal("build-pass tests with expected warnings should be moved to ui/");
63        }
64    }
65
66    fn run_rpass_test(&self) {
67        let emit_metadata = self.should_emit_metadata(self.pass_mode());
68        let should_run = self.run_if_enabled();
69        let proc_res = self.compile_test(should_run, emit_metadata);
70
71        if !proc_res.status.success() {
72            self.fatal_proc_rec("compilation failed!", &proc_res);
73        }
74
75        // FIXME(#41968): Move this check to tidy?
76        if !errors::load_errors(&self.testpaths.file, self.revision).is_empty() {
77            self.fatal("run-pass tests with expected warnings should be moved to ui/");
78        }
79
80        if let WillExecute::Disabled = should_run {
81            return;
82        }
83
84        let proc_res = self.exec_compiled_test();
85        if !proc_res.status.success() {
86            self.fatal_proc_rec("test run failed!", &proc_res);
87        }
88    }
89
90    fn run_cfail_test(&self) {
91        let pm = self.pass_mode();
92        let proc_res = self.compile_test(WillExecute::No, self.should_emit_metadata(pm));
93        self.check_if_test_should_compile(Some(FailMode::Build), pm, &proc_res);
94        self.check_no_compiler_crash(&proc_res, self.props.should_ice);
95
96        let output_to_check = self.get_output(&proc_res);
97        self.check_expected_errors(&proc_res);
98        self.check_all_error_patterns(&output_to_check, &proc_res);
99        if self.props.should_ice {
100            match proc_res.status.code() {
101                Some(101) => (),
102                _ => self.fatal("expected ICE"),
103            }
104        }
105
106        self.check_forbid_output(&output_to_check, &proc_res);
107    }
108}