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 `cpass`, `rpass`, `cfail`, or `rfail`
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        //   - if `rfail`, expect compilation to succeed and execution to fail
13        // - create a directory build/foo/bar.incremental
14        // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C rpass1
15        //   - because name of revision starts with "rpass", expect success
16        // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C cfail2
17        //   - because name of revision starts with "cfail", expect an error
18        //   - load expected errors as usual, but filter for those that end in `[rfail2]`
19        // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C rpass3
20        //   - because name of revision starts with "rpass", expect success
21        // - execute build/foo/bar.exe and save output
22        //
23        // FIXME -- use non-incremental mode as an oracle? That doesn't apply
24        // to #[rustc_dirty] and clean tests I guess
25
26        let revision = self.revision.expect("incremental tests require a list of revisions");
27
28        // Incremental workproduct directory should have already been created.
29        let incremental_dir = self.props.incremental_dir.as_ref().unwrap();
30        assert!(incremental_dir.exists(), "init_incremental_test failed to create incremental dir");
31
32        if self.config.verbose {
33            print!("revision={:?} props={:#?}", revision, self.props);
34        }
35
36        if revision.starts_with("cpass") {
37            if self.props.should_ice {
38                self.fatal("can only use should-ice in cfail tests");
39            }
40            self.run_cpass_test();
41        } else if revision.starts_with("rpass") {
42            if self.props.should_ice {
43                self.fatal("can only use should-ice in cfail tests");
44            }
45            self.run_rpass_test();
46        } else if revision.starts_with("rfail") {
47            if self.props.should_ice {
48                self.fatal("can only use should-ice in cfail tests");
49            }
50            self.run_rfail_test();
51        } else if revision.starts_with("cfail") {
52            self.run_cfail_test();
53        } else {
54            self.fatal("revision name must begin with cpass, rpass, rfail, or cfail");
55        }
56    }
57
58    fn run_cpass_test(&self) {
59        let emit_metadata = self.should_emit_metadata(self.pass_mode());
60        let proc_res = self.compile_test(WillExecute::No, emit_metadata);
61
62        if !proc_res.status.success() {
63            self.fatal_proc_rec("compilation failed!", &proc_res);
64        }
65
66        // FIXME(#41968): Move this check to tidy?
67        if !errors::load_errors(&self.testpaths.file, self.revision).is_empty() {
68            self.fatal("compile-pass tests with expected warnings should be moved to ui/");
69        }
70    }
71
72    fn run_rpass_test(&self) {
73        let emit_metadata = self.should_emit_metadata(self.pass_mode());
74        let should_run = self.run_if_enabled();
75        let proc_res = self.compile_test(should_run, emit_metadata);
76
77        if !proc_res.status.success() {
78            self.fatal_proc_rec("compilation failed!", &proc_res);
79        }
80
81        // FIXME(#41968): Move this check to tidy?
82        if !errors::load_errors(&self.testpaths.file, self.revision).is_empty() {
83            self.fatal("run-pass tests with expected warnings should be moved to ui/");
84        }
85
86        if let WillExecute::Disabled = should_run {
87            return;
88        }
89
90        let proc_res = self.exec_compiled_test();
91        if !proc_res.status.success() {
92            self.fatal_proc_rec("test run failed!", &proc_res);
93        }
94    }
95
96    fn run_cfail_test(&self) {
97        let pm = self.pass_mode();
98        let proc_res = self.compile_test(WillExecute::No, self.should_emit_metadata(pm));
99        self.check_if_test_should_compile(Some(FailMode::Build), pm, &proc_res);
100        self.check_no_compiler_crash(&proc_res, self.props.should_ice);
101
102        let output_to_check = self.get_output(&proc_res);
103        let expected_errors = errors::load_errors(&self.testpaths.file, self.revision);
104        if !expected_errors.is_empty() {
105            if !self.props.error_patterns.is_empty() || !self.props.regex_error_patterns.is_empty()
106            {
107                self.fatal("both error pattern and expected errors specified");
108            }
109            self.check_expected_errors(expected_errors, &proc_res);
110        } else {
111            self.check_all_error_patterns(&output_to_check, &proc_res, pm);
112        }
113        if self.props.should_ice {
114            match proc_res.status.code() {
115                Some(101) => (),
116                _ => self.fatal("expected ICE"),
117            }
118        }
119
120        self.check_forbid_output(&output_to_check, &proc_res);
121    }
122
123    fn run_rfail_test(&self) {
124        let pm = self.pass_mode();
125        let should_run = self.run_if_enabled();
126        let proc_res = self.compile_test(should_run, self.should_emit_metadata(pm));
127
128        if !proc_res.status.success() {
129            self.fatal_proc_rec("compilation failed!", &proc_res);
130        }
131
132        if let WillExecute::Disabled = should_run {
133            return;
134        }
135
136        let proc_res = self.exec_compiled_test();
137
138        let output_to_check = self.get_output(&proc_res);
139        self.check_correct_failure_status(&proc_res);
140        self.check_all_error_patterns(&output_to_check, &proc_res, pm);
141    }
142}