Lukasz Anforowicz | bda1cfe | 2022-09-20 06:25:43 -0700 | [diff] [blame] | 1 | // 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 Anforowicz | 2293ef1 | 2022-09-29 13:37:05 -0700 | [diff] [blame] | 5 | #![feature(never_type)] |
Lukasz Anforowicz | bda1cfe | 2022-09-20 06:25:43 -0700 | [diff] [blame] | 6 | #![feature(rustc_private)] |
| 7 | #![deny(rustc::internal)] |
| 8 | |
Lukasz Anforowicz | bda1cfe | 2022-09-20 06:25:43 -0700 | [diff] [blame] | 9 | extern crate rustc_driver; |
| 10 | extern crate rustc_error_codes; |
| 11 | extern crate rustc_errors; |
Lukasz Anforowicz | 5bddf18 | 2022-09-30 16:06:59 -0700 | [diff] [blame] | 12 | extern crate rustc_feature; |
Lukasz Anforowicz | bda1cfe | 2022-09-20 06:25:43 -0700 | [diff] [blame] | 13 | extern crate rustc_hir; |
| 14 | extern crate rustc_interface; |
Lukasz Anforowicz | 88bde9b | 2022-10-14 14:48:07 -0700 | [diff] [blame] | 15 | extern crate rustc_lint_defs; |
Lukasz Anforowicz | bda1cfe | 2022-09-20 06:25:43 -0700 | [diff] [blame] | 16 | extern crate rustc_middle; |
| 17 | extern crate rustc_session; |
| 18 | extern crate rustc_span; |
Lukasz Anforowicz | e433306 | 2022-10-17 14:47:53 -0700 | [diff] [blame] | 19 | extern crate rustc_target; |
Lukasz Anforowicz | bda1cfe | 2022-09-20 06:25:43 -0700 | [diff] [blame] | 20 | |
Lukasz Anforowicz | 0bef264 | 2023-01-05 09:20:31 -0800 | [diff] [blame] | 21 | // TODO(b/254679226): `bindings`, `cmdline`, and `run_compiler` should be |
| 22 | // separate crates. |
Lukasz Anforowicz | e7874b5 | 2022-09-30 16:52:28 -0700 | [diff] [blame] | 23 | mod bindings; |
Lukasz Anforowicz | bf5a4ee | 2022-09-22 07:38:33 -0700 | [diff] [blame] | 24 | mod cmdline; |
Lukasz Anforowicz | 0bef264 | 2023-01-05 09:20:31 -0800 | [diff] [blame] | 25 | mod run_compiler; |
Lukasz Anforowicz | bf5a4ee | 2022-09-22 07:38:33 -0700 | [diff] [blame] | 26 | |
Lukasz Anforowicz | 1093f78 | 2022-09-28 12:45:10 -0700 | [diff] [blame] | 27 | use anyhow::Context; |
Lukasz Anforowicz | bda1cfe | 2022-09-20 06:25:43 -0700 | [diff] [blame] | 28 | use itertools::Itertools; |
Lukasz Anforowicz | 0bef264 | 2023-01-05 09:20:31 -0800 | [diff] [blame] | 29 | use rustc_middle::ty::TyCtxt; // See also <internal link>/ty.html#import-conventions |
Lukasz Anforowicz | 1093f78 | 2022-09-28 12:45:10 -0700 | [diff] [blame] | 30 | use std::path::Path; |
Lukasz Anforowicz | bda1cfe | 2022-09-20 06:25:43 -0700 | [diff] [blame] | 31 | |
Lukasz Anforowicz | 1093f78 | 2022-09-28 12:45:10 -0700 | [diff] [blame] | 32 | use cmdline::Cmdline; |
Lukasz Anforowicz | 0bef264 | 2023-01-05 09:20:31 -0800 | [diff] [blame] | 33 | use run_compiler::run_compiler; |
Lukasz Anforowicz | 5c081b2 | 2022-11-11 08:40:17 -0800 | [diff] [blame] | 34 | use token_stream_printer::{ |
| 35 | cc_tokens_to_formatted_string, rs_tokens_to_formatted_string, RustfmtConfig, |
| 36 | }; |
Lukasz Anforowicz | bda1cfe | 2022-09-20 06:25:43 -0700 | [diff] [blame] | 37 | |
Lukasz Anforowicz | 1093f78 | 2022-09-28 12:45:10 -0700 | [diff] [blame] | 38 | fn 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 | |
| 43 | fn run_with_tcx(cmdline: &Cmdline, tcx: TyCtxt) -> anyhow::Result<()> { |
Lukasz Anforowicz | be25c76 | 2023-01-17 12:43:52 -0800 | [diff] [blame] | 44 | use bindings::*; |
| 45 | let Output { h_body, rs_body } = { |
Lukasz Anforowicz | a782bda | 2023-01-17 14:04:50 -0800 | [diff] [blame] | 46 | 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 Anforowicz | be25c76 | 2023-01-17 12:43:52 -0800 | [diff] [blame] | 48 | generate_bindings(&input)? |
| 49 | }; |
Lukasz Anforowicz | e7a2500 | 2022-11-10 06:21:42 -0800 | [diff] [blame] | 50 | |
Lukasz Anforowicz | 5c081b2 | 2022-11-11 08:40:17 -0800 | [diff] [blame] | 51 | { |
Lukasz Anforowicz | df363ee | 2022-12-16 14:56:38 -0800 | [diff] [blame] | 52 | let h_body = cc_tokens_to_formatted_string(h_body, &cmdline.clang_format_exe_path)?; |
Lukasz Anforowicz | 5c081b2 | 2022-11-11 08:40:17 -0800 | [diff] [blame] | 53 | 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 Anforowicz | df363ee | 2022-12-16 14:56:38 -0800 | [diff] [blame] | 59 | let rs_body = rs_tokens_to_formatted_string(rs_body, &rustfmt_config)?; |
Lukasz Anforowicz | 5c081b2 | 2022-11-11 08:40:17 -0800 | [diff] [blame] | 60 | write_file(&cmdline.rs_out, &rs_body)?; |
| 61 | } |
Lukasz Anforowicz | e7a2500 | 2022-11-10 06:21:42 -0800 | [diff] [blame] | 62 | |
| 63 | Ok(()) |
Lukasz Anforowicz | 1093f78 | 2022-09-28 12:45:10 -0700 | [diff] [blame] | 64 | } |
| 65 | |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 66 | /// 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 Anforowicz | 5bf4943 | 2022-12-12 12:17:24 -0800 | [diff] [blame] | 68 | /// `init_env_logger`) and therefore can be used from the tests module below. |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 69 | fn run_with_cmdline_args(args: &[String]) -> anyhow::Result<()> { |
| 70 | let cmdline = Cmdline::new(args)?; |
Lukasz Anforowicz | 0bef264 | 2023-01-05 09:20:31 -0800 | [diff] [blame] | 71 | run_compiler(&cmdline.rustc_args, |tcx| { |
Lukasz Anforowicz | 1093f78 | 2022-09-28 12:45:10 -0700 | [diff] [blame] | 72 | run_with_tcx(&cmdline, tcx) |
| 73 | }) |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 74 | } |
| 75 | |
Lukasz Anforowicz | 581fd75 | 2022-09-21 11:30:15 -0700 | [diff] [blame] | 76 | fn main() -> anyhow::Result<()> { |
Lukasz Anforowicz | bda1cfe | 2022-09-20 06:25:43 -0700 | [diff] [blame] | 77 | // 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 Anforowicz | 13794df | 2022-10-21 07:56:34 -0700 | [diff] [blame] | 80 | // TODO(b/254689400): Provide Crubit-specific panic hook message (we shouldn't use |
Lukasz Anforowicz | ca87e47 | 2022-10-14 14:58:30 -0700 | [diff] [blame] | 81 | // `rustc_driver::install_ice_hook` because it's message asks to file bugs at |
| 82 | // https://github.com/rust-lang/rust/issues/new. |
Lukasz Anforowicz | bda1cfe | 2022-09-20 06:25:43 -0700 | [diff] [blame] | 83 | |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 84 | // `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 Anforowicz | bda1cfe | 2022-09-20 06:25:43 -0700 | [diff] [blame] | 87 | |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 88 | run_with_cmdline_args(&args) |
Lukasz Anforowicz | d1a00dc | 2022-09-29 13:21:51 -0700 | [diff] [blame] | 89 | .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 Anforowicz | d1a00dc | 2022-09-29 13:21:51 -0700 | [diff] [blame] | 92 | Ok(clap_err) => { |
Lukasz Anforowicz | 2293ef1 | 2022-09-29 13:37:05 -0700 | [diff] [blame] | 93 | let _ : ! = clap_err.exit(); |
Lukasz Anforowicz | d1a00dc | 2022-09-29 13:21:51 -0700 | [diff] [blame] | 94 | }, |
| 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 Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 100 | } |
| 101 | |
| 102 | #[cfg(test)] |
| 103 | mod tests { |
| 104 | use super::run_with_cmdline_args; |
| 105 | |
Lukasz Anforowicz | 0bef264 | 2023-01-05 09:20:31 -0800 | [diff] [blame] | 106 | use crate::run_compiler::tests::get_sysroot_for_testing; |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 107 | use itertools::Itertools; |
Lukasz Anforowicz | 4a55476 | 2022-12-12 09:35:00 -0800 | [diff] [blame] | 108 | use regex::{Regex, RegexBuilder}; |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 109 | use std::path::PathBuf; |
| 110 | use tempfile::{tempdir, TempDir}; |
Lukasz Anforowicz | 5bf4943 | 2022-12-12 12:17:24 -0800 | [diff] [blame] | 111 | use token_stream_printer::{CLANG_FORMAT_EXE_PATH_FOR_TESTING, RUSTFMT_EXE_PATH_FOR_TESTING}; |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 112 | |
| 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 Anforowicz | 24160d5 | 2022-10-19 06:45:45 -0700 | [diff] [blame] | 118 | |
| 119 | /// Arg for the following `rustc` flag: `--codegen=panic=<arg>`. |
| 120 | panic_mechanism: String, |
| 121 | |
| 122 | /// Other `rustc` flags. |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 123 | extra_rustc_args: Vec<String>, |
Lukasz Anforowicz | 24160d5 | 2022-10-19 06:45:45 -0700 | [diff] [blame] | 124 | |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 125 | tempdir: TempDir, |
| 126 | } |
| 127 | |
Lukasz Anforowicz | ed1c4f0 | 2022-09-29 11:11:20 -0700 | [diff] [blame] | 128 | /// 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 Anforowicz | e7a2500 | 2022-11-10 06:21:42 -0800 | [diff] [blame] | 133 | rs_path: PathBuf, |
Lukasz Anforowicz | ed1c4f0 | 2022-09-29 11:11:20 -0700 | [diff] [blame] | 134 | } |
| 135 | |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 136 | impl TestArgs { |
| 137 | fn default_args() -> anyhow::Result<Self> { |
| 138 | Ok(Self { |
| 139 | h_path: None, |
| 140 | extra_crubit_args: vec![], |
Lukasz Anforowicz | 24160d5 | 2022-10-19 06:45:45 -0700 | [diff] [blame] | 141 | panic_mechanism: "abort".to_string(), |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 142 | 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 Anforowicz | 24160d5 | 2022-10-19 06:45:45 -0700 | [diff] [blame] | 154 | /// 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 Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 161 | /// 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 Anforowicz | df363ee | 2022-12-16 14:56:38 -0800 | [diff] [blame] | 164 | 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 Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 166 | self |
| 167 | } |
| 168 | |
| 169 | /// Appends `extra_crubit_args` before the first `--`. |
Lukasz Anforowicz | df363ee | 2022-12-16 14:56:38 -0800 | [diff] [blame] | 170 | 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 Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 172 | 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 Anforowicz | ed1c4f0 | 2022-09-29 11:11:20 -0700 | [diff] [blame] | 181 | fn run(&self) -> anyhow::Result<TestResult> { |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 182 | let h_path = match self.h_path.as_ref() { |
Lukasz Anforowicz | ed1c4f0 | 2022-09-29 11:11:20 -0700 | [diff] [blame] | 183 | None => self.tempdir.path().join("test_crate_cc_api.h"), |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 184 | Some(s) => PathBuf::from(s), |
| 185 | }; |
Lukasz Anforowicz | e7a2500 | 2022-11-10 06:21:42 -0800 | [diff] [blame] | 186 | let rs_path = self.tempdir.path().join("test_crate_cc_api_impl.rs"); |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 187 | |
| 188 | let rs_input_path = self.tempdir.path().join("test_crate.rs"); |
| 189 | std::fs::write( |
| 190 | &rs_input_path, |
Lukasz Anforowicz | a577d82 | 2022-12-12 15:00:46 -0800 | [diff] [blame] | 191 | r#" pub mod public_module { |
| 192 | pub fn public_function() { |
| 193 | private_function() |
| 194 | } |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 195 | |
Lukasz Anforowicz | a577d82 | 2022-12-12 15:00:46 -0800 | [diff] [blame] | 196 | fn private_function() {} |
| 197 | } |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 198 | "#, |
| 199 | )?; |
| 200 | |
| 201 | let mut args = vec![ |
| 202 | "cc_bindings_from_rs_unittest_executable".to_string(), |
Lukasz Anforowicz | a18aab8 | 2022-09-29 11:18:06 -0700 | [diff] [blame] | 203 | format!("--h-out={}", h_path.display()), |
Lukasz Anforowicz | e7a2500 | 2022-11-10 06:21:42 -0800 | [diff] [blame] | 204 | format!("--rs-out={}", rs_path.display()), |
Lukasz Anforowicz | a782bda | 2023-01-17 14:04:50 -0800 | [diff] [blame] | 205 | format!("--crubit-support-path=crubit/support/for/tests"), |
Lukasz Anforowicz | 5bf4943 | 2022-12-12 12:17:24 -0800 | [diff] [blame] | 206 | format!("--clang-format-exe-path={CLANG_FORMAT_EXE_PATH_FOR_TESTING}"), |
Lukasz Anforowicz | 5c081b2 | 2022-11-11 08:40:17 -0800 | [diff] [blame] | 207 | format!("--rustfmt-exe-path={RUSTFMT_EXE_PATH_FOR_TESTING}"), |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 208 | ]; |
| 209 | args.extend(self.extra_crubit_args.iter().cloned()); |
| 210 | args.extend([ |
| 211 | "--".to_string(), |
Lukasz Anforowicz | 24160d5 | 2022-10-19 06:45:45 -0700 | [diff] [blame] | 212 | format!("--codegen=panic={}", &self.panic_mechanism), |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 213 | "--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 Anforowicz | e7a2500 | 2022-11-10 06:21:42 -0800 | [diff] [blame] | 221 | Ok(TestResult { h_path, rs_path }) |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 222 | } |
| 223 | } |
| 224 | |
Lukasz Anforowicz | 4a55476 | 2022-12-12 09:35:00 -0800 | [diff] [blame] | 225 | // 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 Anforowicz | a577d82 | 2022-12-12 15:00:46 -0800 | [diff] [blame] | 261 | "Mismatched expectations:\n\ |
Lukasz Anforowicz | 4a55476 | 2022-12-12 09:35:00 -0800 | [diff] [blame] | 262 | #### 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 Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 270 | #[test] |
| 271 | fn test_happy_path() -> anyhow::Result<()> { |
| 272 | let test_args = TestArgs::default_args()?; |
Lukasz Anforowicz | ed1c4f0 | 2022-09-29 11:11:20 -0700 | [diff] [blame] | 273 | let test_result = test_args.run().expect("Default args should succeed"); |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 274 | |
Lukasz Anforowicz | ed1c4f0 | 2022-09-29 11:11:20 -0700 | [diff] [blame] | 275 | assert!(test_result.h_path.exists()); |
Googler | 47fd957 | 2023-01-20 09:57:32 -0800 | [diff] [blame] | 276 | let temp_dir_str = test_args.tempdir.path().to_str().unwrap(); |
Lukasz Anforowicz | ed1c4f0 | 2022-09-29 11:11:20 -0700 | [diff] [blame] | 277 | let h_body = std::fs::read_to_string(&test_result.h_path)?; |
Googler | 47fd957 | 2023-01-20 09:57:32 -0800 | [diff] [blame] | 278 | #[rustfmt::skip] |
Lukasz Anforowicz | 4a55476 | 2022-12-12 09:35:00 -0800 | [diff] [blame] | 279 | assert_body_matches( |
| 280 | &h_body, |
Googler | 47fd957 | 2023-01-20 09:57:32 -0800 | [diff] [blame] | 281 | &format!( |
| 282 | "{}\n{}\n{}", |
| 283 | r#"// Automatically @generated C++ bindings for the following Rust crate: |
Lukasz Anforowicz | 4aa1ff9 | 2022-10-10 11:22:22 -0700 | [diff] [blame] | 284 | // test_crate |
| 285 | |
Lukasz Anforowicz | 31b29cd | 2022-10-10 11:33:41 -0700 | [diff] [blame] | 286 | #pragma once |
| 287 | |
Lukasz Anforowicz | bad9963 | 2022-11-18 16:39:13 -0800 | [diff] [blame] | 288 | namespace test_crate { |
Lukasz Anforowicz | a0502fb | 2023-02-13 15:33:18 -0800 | [diff] [blame] | 289 | |
| 290 | namespace public_module { |
| 291 | "#, |
Lukasz Anforowicz | 6753d40 | 2023-02-10 16:41:23 -0800 | [diff] [blame] | 292 | // TODO(b/261185414): Avoid assuming that all source code paths are google3 paths. |
Lukasz Anforowicz | 1f23391 | 2023-02-14 08:50:26 -0800 | [diff] [blame] | 293 | format!("// Generated from: google3/{temp_dir_str}/test_crate.rs;l=2"), |
Lukasz Anforowicz | 6753d40 | 2023-02-10 16:41:23 -0800 | [diff] [blame] | 294 | r#"inline void public_function(); |
Lukasz Anforowicz | a0502fb | 2023-02-13 15:33:18 -0800 | [diff] [blame] | 295 | |
Lukasz Anforowicz | 2f849cf | 2022-11-17 15:52:39 -0800 | [diff] [blame] | 296 | namespace __crubit_internal { |
Lukasz Anforowicz | 4a55476 | 2022-12-12 09:35:00 -0800 | [diff] [blame] | 297 | extern "C" void |
| 298 | __crubit_thunk__ANY_IDENTIFIER_CHARACTERS(); |
Lukasz Anforowicz | 6753d40 | 2023-02-10 16:41:23 -0800 | [diff] [blame] | 299 | } |
| 300 | inline void public_function() { |
Lukasz Anforowicz | bad9963 | 2022-11-18 16:39:13 -0800 | [diff] [blame] | 301 | return __crubit_internal:: |
Lukasz Anforowicz | 4a55476 | 2022-12-12 09:35:00 -0800 | [diff] [blame] | 302 | __crubit_thunk__ANY_IDENTIFIER_CHARACTERS(); |
Lukasz Anforowicz | 2f849cf | 2022-11-17 15:52:39 -0800 | [diff] [blame] | 303 | } |
Lukasz Anforowicz | a0502fb | 2023-02-13 15:33:18 -0800 | [diff] [blame] | 304 | |
Lukasz Anforowicz | a577d82 | 2022-12-12 15:00:46 -0800 | [diff] [blame] | 305 | } // namespace public_module |
Lukasz Anforowicz | a0502fb | 2023-02-13 15:33:18 -0800 | [diff] [blame] | 306 | |
| 307 | } // namespace test_crate |
| 308 | "# |
Googler | 47fd957 | 2023-01-20 09:57:32 -0800 | [diff] [blame] | 309 | ), |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 310 | ); |
Lukasz Anforowicz | e7a2500 | 2022-11-10 06:21:42 -0800 | [diff] [blame] | 311 | |
| 312 | assert!(test_result.rs_path.exists()); |
| 313 | let rs_body = std::fs::read_to_string(&test_result.rs_path)?; |
Lukasz Anforowicz | 4a55476 | 2022-12-12 09:35:00 -0800 | [diff] [blame] | 314 | assert_body_matches( |
| 315 | &rs_body, |
Lukasz Anforowicz | e7a2500 | 2022-11-10 06:21:42 -0800 | [diff] [blame] | 316 | r#"// Automatically @generated C++ bindings for the following Rust crate: |
| 317 | // test_crate |
Lukasz Anforowicz | 2f849cf | 2022-11-17 15:52:39 -0800 | [diff] [blame] | 318 | |
Lukasz Anforowicz | d16b6bf | 2022-11-22 18:35:08 -0800 | [diff] [blame] | 319 | #![allow(improper_ctypes_definitions)] |
| 320 | |
Lukasz Anforowicz | 2f849cf | 2022-11-17 15:52:39 -0800 | [diff] [blame] | 321 | #[no_mangle] |
Lukasz Anforowicz | a577d82 | 2022-12-12 15:00:46 -0800 | [diff] [blame] | 322 | extern "C" fn __crubit_thunk__ANY_IDENTIFIER_CHARACTERS() |
| 323 | -> () { |
| 324 | ::test_crate::public_module::public_function() |
Lukasz Anforowicz | 2f849cf | 2022-11-17 15:52:39 -0800 | [diff] [blame] | 325 | } |
Lukasz Anforowicz | 4a55476 | 2022-12-12 09:35:00 -0800 | [diff] [blame] | 326 | "#, |
Lukasz Anforowicz | e7a2500 | 2022-11-10 06:21:42 -0800 | [diff] [blame] | 327 | ); |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 328 | Ok(()) |
| 329 | } |
| 330 | |
Lukasz Anforowicz | 4c19ad9 | 2022-12-16 15:23:14 -0800 | [diff] [blame] | 331 | /// `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 Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 334 | #[test] |
| 335 | fn test_cmdline_error_propagation() -> anyhow::Result<()> { |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 336 | let err = TestArgs::default_args()? |
Lukasz Anforowicz | df363ee | 2022-12-16 14:56:38 -0800 | [diff] [blame] | 337 | .with_extra_crubit_args(&["--unrecognized-crubit-flag"]) |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 338 | .run() |
| 339 | .expect_err("--unrecognized_crubit_flag should trigger an error"); |
| 340 | |
Lukasz Anforowicz | ca87e47 | 2022-10-14 14:58:30 -0700 | [diff] [blame] | 341 | let msg = format!("{err:#}"); |
Lukasz Anforowicz | a18aab8 | 2022-09-29 11:18:06 -0700 | [diff] [blame] | 342 | assert!( |
| 343 | msg.contains("Found argument '--unrecognized-crubit-flag' which wasn't expected"), |
| 344 | "msg = {}", |
| 345 | msg, |
| 346 | ); |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 347 | Ok(()) |
| 348 | } |
| 349 | |
Lukasz Anforowicz | 0bef264 | 2023-01-05 09:20:31 -0800 | [diff] [blame] | 350 | /// `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 Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 354 | #[test] |
Lukasz Anforowicz | 0bef264 | 2023-01-05 09:20:31 -0800 | [diff] [blame] | 355 | fn test_run_compiler_error_propagation() -> anyhow::Result<()> { |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 356 | let err = TestArgs::default_args()? |
Lukasz Anforowicz | df363ee | 2022-12-16 14:56:38 -0800 | [diff] [blame] | 357 | .with_extra_rustc_args(&["--unrecognized-rustc-flag"]) |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 358 | .run() |
| 359 | .expect_err("--unrecognized-rustc-flag should trigger an error"); |
| 360 | |
Lukasz Anforowicz | ca87e47 | 2022-10-14 14:58:30 -0700 | [diff] [blame] | 361 | let msg = format!("{err:#}"); |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 362 | assert_eq!("Errors reported by Rust compiler.", msg); |
| 363 | Ok(()) |
| 364 | } |
| 365 | |
Lukasz Anforowicz | 4c19ad9 | 2022-12-16 15:23:14 -0800 | [diff] [blame] | 366 | /// `test_rustc_unsupported_panic_mechanism` tests that `panic=unwind` results |
| 367 | /// in an error. |
Lukasz Anforowicz | 0bef264 | 2023-01-05 09:20:31 -0800 | [diff] [blame] | 368 | /// |
| 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 Anforowicz | 76e2623 | 2022-10-18 17:26:28 -0700 | [diff] [blame] | 372 | #[test] |
Lukasz Anforowicz | 24160d5 | 2022-10-19 06:45:45 -0700 | [diff] [blame] | 373 | fn test_rustc_unsupported_panic_mechanism() -> anyhow::Result<()> { |
Lukasz Anforowicz | 24160d5 | 2022-10-19 06:45:45 -0700 | [diff] [blame] | 374 | 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 Anforowicz | 4c19ad9 | 2022-12-16 15:23:14 -0800 | [diff] [blame] | 384 | /// `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 Anforowicz | 24160d5 | 2022-10-19 06:45:45 -0700 | [diff] [blame] | 387 | #[test] |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 388 | fn test_invalid_h_out_path() -> anyhow::Result<()> { |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 389 | let err = TestArgs::default_args()? |
| 390 | .with_h_path("../..") |
| 391 | .run() |
Lukasz Anforowicz | a18aab8 | 2022-09-29 11:18:06 -0700 | [diff] [blame] | 392 | .expect_err("Unwriteable --h-out should trigger an error"); |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 393 | |
Lukasz Anforowicz | ca87e47 | 2022-10-14 14:58:30 -0700 | [diff] [blame] | 394 | let msg = format!("{err:#}"); |
| 395 | assert_eq!("Error when writing to ../..: Is a directory (os error 21)", msg); |
Lukasz Anforowicz | f018e4d | 2022-09-28 07:35:59 -0700 | [diff] [blame] | 396 | Ok(()) |
| 397 | } |
Lukasz Anforowicz | bda1cfe | 2022-09-20 06:25:43 -0700 | [diff] [blame] | 398 | } |