blob: b2c354a3eeadef7a57f8cf1304a15044cab295fe [file] [log] [blame]
Lukasz Anforowiczbda1cfe2022-09-20 06:25:43 -07001// Part of the Crubit project, under the Apache License v2.0 with LLVM
2// Exceptions. See /LICENSE for license information.
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
Lukasz Anforowicz2293ef12022-09-29 13:37:05 -07005#![feature(never_type)]
Lukasz Anforowiczbda1cfe2022-09-20 06:25:43 -07006#![feature(rustc_private)]
7#![deny(rustc::internal)]
8
Lukasz Anforowiczbda1cfe2022-09-20 06:25:43 -07009extern crate rustc_driver;
10extern crate rustc_error_codes;
11extern crate rustc_errors;
Lukasz Anforowicz5bddf182022-09-30 16:06:59 -070012extern crate rustc_feature;
Lukasz Anforowiczbda1cfe2022-09-20 06:25:43 -070013extern crate rustc_hir;
14extern crate rustc_interface;
Lukasz Anforowicz88bde9b2022-10-14 14:48:07 -070015extern crate rustc_lint_defs;
Lukasz Anforowiczbda1cfe2022-09-20 06:25:43 -070016extern crate rustc_middle;
17extern crate rustc_session;
18extern crate rustc_span;
Lukasz Anforowicze4333062022-10-17 14:47:53 -070019extern crate rustc_target;
Lukasz Anforowiczbda1cfe2022-09-20 06:25:43 -070020
Lukasz Anforowicz0bef2642023-01-05 09:20:31 -080021// TODO(b/254679226): `bindings`, `cmdline`, and `run_compiler` should be
22// separate crates.
Lukasz Anforowicze7874b52022-09-30 16:52:28 -070023mod bindings;
Lukasz Anforowiczbf5a4ee2022-09-22 07:38:33 -070024mod cmdline;
Lukasz Anforowicz0bef2642023-01-05 09:20:31 -080025mod run_compiler;
Lukasz Anforowiczbf5a4ee2022-09-22 07:38:33 -070026
Lukasz Anforowicz1093f782022-09-28 12:45:10 -070027use anyhow::Context;
Lukasz Anforowiczbda1cfe2022-09-20 06:25:43 -070028use itertools::Itertools;
Lukasz Anforowicz0bef2642023-01-05 09:20:31 -080029use rustc_middle::ty::TyCtxt; // See also <internal link>/ty.html#import-conventions
Lukasz Anforowicz1093f782022-09-28 12:45:10 -070030use std::path::Path;
Lukasz Anforowiczbda1cfe2022-09-20 06:25:43 -070031
Lukasz Anforowicz1093f782022-09-28 12:45:10 -070032use cmdline::Cmdline;
Lukasz Anforowicz0bef2642023-01-05 09:20:31 -080033use run_compiler::run_compiler;
Lukasz Anforowicz5c081b22022-11-11 08:40:17 -080034use token_stream_printer::{
35 cc_tokens_to_formatted_string, rs_tokens_to_formatted_string, RustfmtConfig,
36};
Lukasz Anforowiczbda1cfe2022-09-20 06:25:43 -070037
Lukasz Anforowicz1093f782022-09-28 12:45:10 -070038fn write_file(path: &Path, content: &str) -> anyhow::Result<()> {
39 std::fs::write(path, content)
40 .with_context(|| format!("Error when writing to {}", path.display()))
41}
42
43fn run_with_tcx(cmdline: &Cmdline, tcx: TyCtxt) -> anyhow::Result<()> {
Lukasz Anforowiczbe25c762023-01-17 12:43:52 -080044 use bindings::*;
45 let Output { h_body, rs_body } = {
Lukasz Anforowicza782bda2023-01-17 14:04:50 -080046 let crubit_support_path = cmdline.crubit_support_path.as_str().into();
47 let input = Input { tcx, crubit_support_path, _features: (), _crate_to_include_map: () };
Lukasz Anforowiczbe25c762023-01-17 12:43:52 -080048 generate_bindings(&input)?
49 };
Lukasz Anforowicze7a25002022-11-10 06:21:42 -080050
Lukasz Anforowicz5c081b22022-11-11 08:40:17 -080051 {
Lukasz Anforowiczdf363ee2022-12-16 14:56:38 -080052 let h_body = cc_tokens_to_formatted_string(h_body, &cmdline.clang_format_exe_path)?;
Lukasz Anforowicz5c081b22022-11-11 08:40:17 -080053 write_file(&cmdline.h_out, &h_body)?;
54 }
55
56 {
57 let rustfmt_config =
58 RustfmtConfig::new(&cmdline.rustfmt_exe_path, cmdline.rustfmt_config_path.as_deref());
Lukasz Anforowiczdf363ee2022-12-16 14:56:38 -080059 let rs_body = rs_tokens_to_formatted_string(rs_body, &rustfmt_config)?;
Lukasz Anforowicz5c081b22022-11-11 08:40:17 -080060 write_file(&cmdline.rs_out, &rs_body)?;
61 }
Lukasz Anforowicze7a25002022-11-10 06:21:42 -080062
63 Ok(())
Lukasz Anforowicz1093f782022-09-28 12:45:10 -070064}
65
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -070066/// Main entrypoint that (unlike `main`) doesn't do any intitializations that
67/// should only happen once for the binary (e.g. it doesn't call
Lukasz Anforowicz5bf49432022-12-12 12:17:24 -080068/// `init_env_logger`) and therefore can be used from the tests module below.
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -070069fn run_with_cmdline_args(args: &[String]) -> anyhow::Result<()> {
70 let cmdline = Cmdline::new(args)?;
Lukasz Anforowicz0bef2642023-01-05 09:20:31 -080071 run_compiler(&cmdline.rustc_args, |tcx| {
Lukasz Anforowicz1093f782022-09-28 12:45:10 -070072 run_with_tcx(&cmdline, tcx)
73 })
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -070074}
75
Lukasz Anforowicz581fd752022-09-21 11:30:15 -070076fn main() -> anyhow::Result<()> {
Lukasz Anforowiczbda1cfe2022-09-20 06:25:43 -070077 // TODO: Investigate if we should install a signal handler here. See also how
78 // compiler/rustc_driver/src/lib.rs calls `signal_handler::install()`.
79
Lukasz Anforowicz13794df2022-10-21 07:56:34 -070080 // TODO(b/254689400): Provide Crubit-specific panic hook message (we shouldn't use
Lukasz Anforowiczca87e472022-10-14 14:58:30 -070081 // `rustc_driver::install_ice_hook` because it's message asks to file bugs at
82 // https://github.com/rust-lang/rust/issues/new.
Lukasz Anforowiczbda1cfe2022-09-20 06:25:43 -070083
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -070084 // `std::env::args()` will panic if any of the cmdline arguments are not valid
85 // Unicode. This seems okay.
86 let args = std::env::args().collect_vec();
Lukasz Anforowiczbda1cfe2022-09-20 06:25:43 -070087
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -070088 run_with_cmdline_args(&args)
Lukasz Anforowiczd1a00dc2022-09-29 13:21:51 -070089 .map_err(|anyhow_err| match anyhow_err.downcast::<clap::Error>() {
90 // Explicitly call `clap::Error::exit`, because 1) it results in *colored* output and
91 // 2) it uses a zero exit code for specific "errors" (e.g. for `--help` output).
Lukasz Anforowiczd1a00dc2022-09-29 13:21:51 -070092 Ok(clap_err) => {
Lukasz Anforowicz2293ef12022-09-29 13:37:05 -070093 let _ : ! = clap_err.exit();
Lukasz Anforowiczd1a00dc2022-09-29 13:21:51 -070094 },
95
96 // Return `other_err` from `main`. This will print the error message (no color codes
97 // though) and terminate the process with a non-zero exit code.
98 Err(other_err) => other_err,
99 })
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700100}
101
102#[cfg(test)]
103mod tests {
104 use super::run_with_cmdline_args;
105
Lukasz Anforowicz0bef2642023-01-05 09:20:31 -0800106 use crate::run_compiler::tests::get_sysroot_for_testing;
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700107 use itertools::Itertools;
Lukasz Anforowicz4a554762022-12-12 09:35:00 -0800108 use regex::{Regex, RegexBuilder};
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700109 use std::path::PathBuf;
110 use tempfile::{tempdir, TempDir};
Lukasz Anforowicz5bf49432022-12-12 12:17:24 -0800111 use token_stream_printer::{CLANG_FORMAT_EXE_PATH_FOR_TESTING, RUSTFMT_EXE_PATH_FOR_TESTING};
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700112
113 /// Test data builder (see also
114 /// https://testing.googleblog.com/2018/02/testing-on-toilet-cleanly-create-test.html).
115 struct TestArgs {
116 h_path: Option<String>,
117 extra_crubit_args: Vec<String>,
Lukasz Anforowicz24160d52022-10-19 06:45:45 -0700118
119 /// Arg for the following `rustc` flag: `--codegen=panic=<arg>`.
120 panic_mechanism: String,
121
122 /// Other `rustc` flags.
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700123 extra_rustc_args: Vec<String>,
Lukasz Anforowicz24160d52022-10-19 06:45:45 -0700124
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700125 tempdir: TempDir,
126 }
127
Lukasz Anforowiczed1c4f02022-09-29 11:11:20 -0700128 /// Result of `TestArgs::run` that helps tests access test outputs (e.g. the
129 /// internally generated `h_path` and/or `rs_input_path`).
130 #[derive(Debug)]
131 struct TestResult {
132 h_path: PathBuf,
Lukasz Anforowicze7a25002022-11-10 06:21:42 -0800133 rs_path: PathBuf,
Lukasz Anforowiczed1c4f02022-09-29 11:11:20 -0700134 }
135
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700136 impl TestArgs {
137 fn default_args() -> anyhow::Result<Self> {
138 Ok(Self {
139 h_path: None,
140 extra_crubit_args: vec![],
Lukasz Anforowicz24160d52022-10-19 06:45:45 -0700141 panic_mechanism: "abort".to_string(),
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700142 extra_rustc_args: vec![],
143 tempdir: tempdir()?,
144 })
145 }
146
147 /// Use the specified `h_path` rather than auto-generating one in
148 /// `self`-managed temporary directory.
149 fn with_h_path(mut self, h_path: &str) -> Self {
150 self.h_path = Some(h_path.to_string());
151 self
152 }
153
Lukasz Anforowicz24160d52022-10-19 06:45:45 -0700154 /// Replaces the default `--codegen=panic=abort` with the specified
155 /// `panic_mechanism`.
156 fn with_panic_mechanism(mut self, panic_mechanism: &str) -> Self {
157 self.panic_mechanism = panic_mechanism.to_string();
158 self
159 }
160
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700161 /// Appends `extra_rustc_args` at the end of the cmdline (i.e. as
162 /// additional rustc args, in addition to `--sysroot`,
163 /// `--crate-type=...`, etc.).
Lukasz Anforowiczdf363ee2022-12-16 14:56:38 -0800164 fn with_extra_rustc_args(mut self, extra_rustc_args: &[&str]) -> Self {
165 self.extra_rustc_args = extra_rustc_args.iter().map(|t| t.to_string()).collect_vec();
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700166 self
167 }
168
169 /// Appends `extra_crubit_args` before the first `--`.
Lukasz Anforowiczdf363ee2022-12-16 14:56:38 -0800170 fn with_extra_crubit_args(mut self, extra_crubit_args: &[&str]) -> Self {
171 self.extra_crubit_args = extra_crubit_args.iter().map(|t| t.to_string()).collect_vec();
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700172 self
173 }
174
175 /// Invokes `super::run_with_cmdline_args` with default `test_crate.rs`
176 /// input (and with other default args + args gathered by
177 /// `self`).
178 ///
179 /// Returns the path to the `h_out` file. The file's lifetime is the
180 /// same as `&self`.
Lukasz Anforowiczed1c4f02022-09-29 11:11:20 -0700181 fn run(&self) -> anyhow::Result<TestResult> {
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700182 let h_path = match self.h_path.as_ref() {
Lukasz Anforowiczed1c4f02022-09-29 11:11:20 -0700183 None => self.tempdir.path().join("test_crate_cc_api.h"),
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700184 Some(s) => PathBuf::from(s),
185 };
Lukasz Anforowicze7a25002022-11-10 06:21:42 -0800186 let rs_path = self.tempdir.path().join("test_crate_cc_api_impl.rs");
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700187
188 let rs_input_path = self.tempdir.path().join("test_crate.rs");
189 std::fs::write(
190 &rs_input_path,
Lukasz Anforowicza577d822022-12-12 15:00:46 -0800191 r#" pub mod public_module {
192 pub fn public_function() {
193 private_function()
194 }
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700195
Lukasz Anforowicza577d822022-12-12 15:00:46 -0800196 fn private_function() {}
197 }
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700198 "#,
199 )?;
200
201 let mut args = vec![
202 "cc_bindings_from_rs_unittest_executable".to_string(),
Lukasz Anforowicza18aab82022-09-29 11:18:06 -0700203 format!("--h-out={}", h_path.display()),
Lukasz Anforowicze7a25002022-11-10 06:21:42 -0800204 format!("--rs-out={}", rs_path.display()),
Lukasz Anforowicza782bda2023-01-17 14:04:50 -0800205 format!("--crubit-support-path=crubit/support/for/tests"),
Lukasz Anforowicz5bf49432022-12-12 12:17:24 -0800206 format!("--clang-format-exe-path={CLANG_FORMAT_EXE_PATH_FOR_TESTING}"),
Lukasz Anforowicz5c081b22022-11-11 08:40:17 -0800207 format!("--rustfmt-exe-path={RUSTFMT_EXE_PATH_FOR_TESTING}"),
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700208 ];
209 args.extend(self.extra_crubit_args.iter().cloned());
210 args.extend([
211 "--".to_string(),
Lukasz Anforowicz24160d52022-10-19 06:45:45 -0700212 format!("--codegen=panic={}", &self.panic_mechanism),
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700213 "--crate-type=lib".to_string(),
214 format!("--sysroot={}", get_sysroot_for_testing().display()),
215 rs_input_path.display().to_string(),
216 ]);
217 args.extend(self.extra_rustc_args.iter().cloned());
218
219 run_with_cmdline_args(&args)?;
220
Lukasz Anforowicze7a25002022-11-10 06:21:42 -0800221 Ok(TestResult { h_path, rs_path })
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700222 }
223 }
224
Lukasz Anforowicz4a554762022-12-12 09:35:00 -0800225 // TODO(b/261074843): Go back to exact string matching (and hardcoding thunk
226 // names) once we are using stable name mangling (which may be coming in Q1
227 // 2023). ("Go back" = more or less revert cl/492292910 + manual review and
228 // tweaks.)
229 fn assert_body_matches(actual: &str, expected: &str) {
230 fn build_regex(expected_body: &str) -> Regex {
231 let patt = regex::escape(expected_body);
232 let patt = format!("^{patt}"); // Not always matching $ enables prefix checks below.
233 let patt = patt.replace("ANY_IDENTIFIER_CHARACTERS", "[a-zA-Z0-9_]*");
234 RegexBuilder::new(&patt).multi_line(false).dot_matches_new_line(false).build().unwrap()
235 }
236 let is_whole_h_body_matching = {
237 match build_regex(expected).shortest_match(&actual) {
238 None => false,
239 Some(len) => len == actual.len(),
240 }
241 };
242 if !is_whole_h_body_matching {
243 let longest_matching_expectation_len = (0..=expected.len())
244 .rev() // Iterating from longest to shortest prefix
245 .filter(|&len| {
246 expected
247 .get(0..len) // Only valid UTF-8 boundaries
248 .filter(|prefix| build_regex(prefix).is_match(&actual))
249 .is_some()
250 })
251 .next() // Getting the first regex that matched
252 .unwrap(); // We must get a match at least for 0-length expected body
253 let longest_matching_regex =
254 build_regex(&expected[0..longest_matching_expectation_len]);
255 let len_of_longest_match = longest_matching_regex.shortest_match(&actual).unwrap(); // Again - we must get a match at least for 0-length expected body
256 let mut marked_body = actual.to_string();
257 marked_body.insert_str(len_of_longest_match, "!!!>>>");
258 let mut marked_pattern = expected.to_string();
259 marked_pattern.insert_str(longest_matching_expectation_len, "!!!>>>");
260 panic!(
Lukasz Anforowicza577d822022-12-12 15:00:46 -0800261 "Mismatched expectations:\n\
Lukasz Anforowicz4a554762022-12-12 09:35:00 -0800262 #### Actual body (first mismatch follows the \"!!!>>>\" marker):\n\
263 {marked_body}\n\
264 #### Mismatched pattern (mismatch follows the \"!!!>>>\" marker):\n\
265 {marked_pattern}"
266 );
267 }
268 }
269
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700270 #[test]
271 fn test_happy_path() -> anyhow::Result<()> {
272 let test_args = TestArgs::default_args()?;
Lukasz Anforowiczed1c4f02022-09-29 11:11:20 -0700273 let test_result = test_args.run().expect("Default args should succeed");
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700274
Lukasz Anforowiczed1c4f02022-09-29 11:11:20 -0700275 assert!(test_result.h_path.exists());
Googler47fd9572023-01-20 09:57:32 -0800276 let temp_dir_str = test_args.tempdir.path().to_str().unwrap();
Lukasz Anforowiczed1c4f02022-09-29 11:11:20 -0700277 let h_body = std::fs::read_to_string(&test_result.h_path)?;
Googler47fd9572023-01-20 09:57:32 -0800278 #[rustfmt::skip]
Lukasz Anforowicz4a554762022-12-12 09:35:00 -0800279 assert_body_matches(
280 &h_body,
Googler47fd9572023-01-20 09:57:32 -0800281 &format!(
282 "{}\n{}\n{}",
283r#"// Automatically @generated C++ bindings for the following Rust crate:
Lukasz Anforowicz4aa1ff92022-10-10 11:22:22 -0700284// test_crate
285
Lukasz Anforowicz31b29cd2022-10-10 11:33:41 -0700286#pragma once
287
Lukasz Anforowiczbad99632022-11-18 16:39:13 -0800288namespace test_crate {
Lukasz Anforowicza0502fb2023-02-13 15:33:18 -0800289
290namespace public_module {
291"#,
Lukasz Anforowicz6753d402023-02-10 16:41:23 -0800292 // TODO(b/261185414): Avoid assuming that all source code paths are google3 paths.
Lukasz Anforowicz1f233912023-02-14 08:50:26 -0800293format!("// Generated from: google3/{temp_dir_str}/test_crate.rs;l=2"),
Lukasz Anforowicz6753d402023-02-10 16:41:23 -0800294r#"inline void public_function();
Lukasz Anforowicza0502fb2023-02-13 15:33:18 -0800295
Lukasz Anforowicz2f849cf2022-11-17 15:52:39 -0800296namespace __crubit_internal {
Lukasz Anforowicz4a554762022-12-12 09:35:00 -0800297extern "C" void
298__crubit_thunk__ANY_IDENTIFIER_CHARACTERS();
Lukasz Anforowicz6753d402023-02-10 16:41:23 -0800299}
300inline void public_function() {
Lukasz Anforowiczbad99632022-11-18 16:39:13 -0800301 return __crubit_internal::
Lukasz Anforowicz4a554762022-12-12 09:35:00 -0800302 __crubit_thunk__ANY_IDENTIFIER_CHARACTERS();
Lukasz Anforowicz2f849cf2022-11-17 15:52:39 -0800303}
Lukasz Anforowicza0502fb2023-02-13 15:33:18 -0800304
Lukasz Anforowicza577d822022-12-12 15:00:46 -0800305} // namespace public_module
Lukasz Anforowicza0502fb2023-02-13 15:33:18 -0800306
307} // namespace test_crate
308"#
Googler47fd9572023-01-20 09:57:32 -0800309 ),
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700310 );
Lukasz Anforowicze7a25002022-11-10 06:21:42 -0800311
312 assert!(test_result.rs_path.exists());
313 let rs_body = std::fs::read_to_string(&test_result.rs_path)?;
Lukasz Anforowicz4a554762022-12-12 09:35:00 -0800314 assert_body_matches(
315 &rs_body,
Lukasz Anforowicze7a25002022-11-10 06:21:42 -0800316 r#"// Automatically @generated C++ bindings for the following Rust crate:
317// test_crate
Lukasz Anforowicz2f849cf2022-11-17 15:52:39 -0800318
Lukasz Anforowiczd16b6bf2022-11-22 18:35:08 -0800319#![allow(improper_ctypes_definitions)]
320
Lukasz Anforowicz2f849cf2022-11-17 15:52:39 -0800321#[no_mangle]
Lukasz Anforowicza577d822022-12-12 15:00:46 -0800322extern "C" fn __crubit_thunk__ANY_IDENTIFIER_CHARACTERS()
323-> () {
324 ::test_crate::public_module::public_function()
Lukasz Anforowicz2f849cf2022-11-17 15:52:39 -0800325}
Lukasz Anforowicz4a554762022-12-12 09:35:00 -0800326"#,
Lukasz Anforowicze7a25002022-11-10 06:21:42 -0800327 );
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700328 Ok(())
329 }
330
Lukasz Anforowicz4c19ad92022-12-16 15:23:14 -0800331 /// `test_cmdline_error_propagation` tests that errors from `Cmdline::new` get
332 /// propagated. More detailed test coverage of various specific error types
333 /// can be found in tests in `cmdline.rs`.
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700334 #[test]
335 fn test_cmdline_error_propagation() -> anyhow::Result<()> {
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700336 let err = TestArgs::default_args()?
Lukasz Anforowiczdf363ee2022-12-16 14:56:38 -0800337 .with_extra_crubit_args(&["--unrecognized-crubit-flag"])
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700338 .run()
339 .expect_err("--unrecognized_crubit_flag should trigger an error");
340
Lukasz Anforowiczca87e472022-10-14 14:58:30 -0700341 let msg = format!("{err:#}");
Lukasz Anforowicza18aab82022-09-29 11:18:06 -0700342 assert!(
343 msg.contains("Found argument '--unrecognized-crubit-flag' which wasn't expected"),
344 "msg = {}",
345 msg,
346 );
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700347 Ok(())
348 }
349
Lukasz Anforowicz0bef2642023-01-05 09:20:31 -0800350 /// `test_run_compiler_error_propagation` tests that errors from
351 /// `run_compiler` get propagated. More detailed test coverage of
352 /// various specific error types can be found in tests in `run_compiler.
353 /// rs`.
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700354 #[test]
Lukasz Anforowicz0bef2642023-01-05 09:20:31 -0800355 fn test_run_compiler_error_propagation() -> anyhow::Result<()> {
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700356 let err = TestArgs::default_args()?
Lukasz Anforowiczdf363ee2022-12-16 14:56:38 -0800357 .with_extra_rustc_args(&["--unrecognized-rustc-flag"])
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700358 .run()
359 .expect_err("--unrecognized-rustc-flag should trigger an error");
360
Lukasz Anforowiczca87e472022-10-14 14:58:30 -0700361 let msg = format!("{err:#}");
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700362 assert_eq!("Errors reported by Rust compiler.", msg);
363 Ok(())
364 }
365
Lukasz Anforowicz4c19ad92022-12-16 15:23:14 -0800366 /// `test_rustc_unsupported_panic_mechanism` tests that `panic=unwind` results
367 /// in an error.
Lukasz Anforowicz0bef2642023-01-05 09:20:31 -0800368 ///
369 /// This is tested at the `cc_bindings_from_rs.rs` level instead of at the `bindings.rs` level,
370 /// because `run_compiler::tests::run_compiler_for_testing` doesn't support specifying a custom
371 /// panic mechanism.
Lukasz Anforowicz76e26232022-10-18 17:26:28 -0700372 #[test]
Lukasz Anforowicz24160d52022-10-19 06:45:45 -0700373 fn test_rustc_unsupported_panic_mechanism() -> anyhow::Result<()> {
Lukasz Anforowicz24160d52022-10-19 06:45:45 -0700374 let err = TestArgs::default_args()?
375 .with_panic_mechanism("unwind")
376 .run()
377 .expect_err("panic=unwind should trigger an error");
378
379 let msg = format!("{err:#}");
380 assert_eq!("No support for panic=unwind strategy (b/254049425)", msg);
381 Ok(())
382 }
383
Lukasz Anforowicz4c19ad92022-12-16 15:23:14 -0800384 /// `test_invalid_h_out_path` tests not only the specific problem of an invalid
385 /// `--h-out` argument, but also tests that errors from `run_with_tcx` are
386 /// propagated.
Lukasz Anforowicz24160d52022-10-19 06:45:45 -0700387 #[test]
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700388 fn test_invalid_h_out_path() -> anyhow::Result<()> {
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700389 let err = TestArgs::default_args()?
390 .with_h_path("../..")
391 .run()
Lukasz Anforowicza18aab82022-09-29 11:18:06 -0700392 .expect_err("Unwriteable --h-out should trigger an error");
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700393
Lukasz Anforowiczca87e472022-10-14 14:58:30 -0700394 let msg = format!("{err:#}");
395 assert_eq!("Error when writing to ../..: Is a directory (os error 21)", msg);
Lukasz Anforowiczf018e4d2022-09-28 07:35:59 -0700396 Ok(())
397 }
Lukasz Anforowiczbda1cfe2022-09-20 06:25:43 -0700398}