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("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