1 | use super::{FailMode, TestCx, WillExecute}; |
2 | use crate::errors; |
3 | |
4 | impl 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("build-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 | } |
143 | |