diff options
Diffstat (limited to 'third_party/rust/uniffi_bindgen/src/bindings/kotlin/test.rs')
-rw-r--r-- | third_party/rust/uniffi_bindgen/src/bindings/kotlin/test.rs | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/test.rs b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/test.rs new file mode 100644 index 0000000000..7b78540741 --- /dev/null +++ b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/test.rs @@ -0,0 +1,131 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use crate::{ + bindings::{RunScriptOptions, TargetLanguage}, + library_mode::generate_bindings, +}; +use anyhow::{bail, Context, Result}; +use camino::{Utf8Path, Utf8PathBuf}; +use std::env; +use std::process::Command; +use uniffi_testing::UniFFITestHelper; + +/// Run Kotlin tests for a UniFFI test fixture +pub fn run_test(tmp_dir: &str, fixture_name: &str, script_file: &str) -> Result<()> { + run_script( + tmp_dir, + fixture_name, + script_file, + vec![], + &RunScriptOptions::default(), + ) +} + +/// Run a Kotlin script +/// +/// This function will set things up so that the script can import the UniFFI bindings for a crate +pub fn run_script( + tmp_dir: &str, + crate_name: &str, + script_file: &str, + args: Vec<String>, + options: &RunScriptOptions, +) -> Result<()> { + let script_path = Utf8Path::new(".").join(script_file); + let test_helper = UniFFITestHelper::new(crate_name)?; + let out_dir = test_helper.create_out_dir(tmp_dir, &script_path)?; + let cdylib_path = test_helper.copy_cdylib_to_out_dir(&out_dir)?; + generate_bindings( + &cdylib_path, + None, + &[TargetLanguage::Kotlin], + &out_dir, + false, + )?; + let jar_file = build_jar(crate_name, &out_dir, options)?; + + let mut command = kotlinc_command(options); + command + .arg("-classpath") + .arg(calc_classpath(vec![&out_dir, &jar_file])) + // Enable runtime assertions, for easy testing etc. + .arg("-J-ea") + // Our test scripts should not produce any warnings. + .arg("-Werror") + .arg("-script") + .arg(script_path) + .args(if args.is_empty() { + vec![] + } else { + std::iter::once(String::from("--")).chain(args).collect() + }); + + let status = command + .spawn() + .context("Failed to spawn `kotlinc` to run Kotlin script")? + .wait() + .context("Failed to wait for `kotlinc` when running Kotlin script")?; + if !status.success() { + anyhow::bail!("running `kotlinc` failed") + } + Ok(()) +} + +/// Generate kotlin bindings for the given namespace, then use the kotlin +/// command-line tools to compile them into a .jar file. +fn build_jar( + crate_name: &str, + out_dir: &Utf8Path, + options: &RunScriptOptions, +) -> Result<Utf8PathBuf> { + let mut jar_file = Utf8PathBuf::from(out_dir); + jar_file.push(format!("{crate_name}.jar")); + let sources = glob::glob(out_dir.join("**/*.kt").as_str())? + .flatten() + .map(|p| String::from(p.to_string_lossy())) + .collect::<Vec<String>>(); + if sources.is_empty() { + bail!("No kotlin sources found in {out_dir}") + } + + let mut command = kotlinc_command(options); + command + // Our generated bindings should not produce any warnings; fail tests if they do. + .arg("-Werror") + .arg("-d") + .arg(&jar_file) + .arg("-classpath") + .arg(calc_classpath(vec![])) + .args(sources); + + let status = command + .spawn() + .context("Failed to spawn `kotlinc` to compile the bindings")? + .wait() + .context("Failed to wait for `kotlinc` when compiling the bindings")?; + if !status.success() { + bail!("running `kotlinc` failed") + } + Ok(jar_file) +} + +fn kotlinc_command(options: &RunScriptOptions) -> Command { + let mut command = Command::new("kotlinc"); + if !options.show_compiler_messages { + command.arg("-nowarn"); + } + command +} + +fn calc_classpath(extra_paths: Vec<&Utf8Path>) -> String { + extra_paths + .into_iter() + .map(|p| p.to_string()) + // Add the system classpath as a component, using the fact that env::var returns an Option, + // which implement Iterator + .chain(env::var("CLASSPATH")) + .collect::<Vec<String>>() + .join(":") +} |