summaryrefslogtreecommitdiffstats
path: root/third_party/rust/uniffi_macros/src/test.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/uniffi_macros/src/test.rs')
-rw-r--r--third_party/rust/uniffi_macros/src/test.rs90
1 files changed, 90 insertions, 0 deletions
diff --git a/third_party/rust/uniffi_macros/src/test.rs b/third_party/rust/uniffi_macros/src/test.rs
new file mode 100644
index 0000000000..ddcbf46000
--- /dev/null
+++ b/third_party/rust/uniffi_macros/src/test.rs
@@ -0,0 +1,90 @@
+/* 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 camino::{Utf8Path, Utf8PathBuf};
+use proc_macro::TokenStream;
+use quote::{format_ident, quote};
+use std::env;
+use syn::{parse_macro_input, punctuated::Punctuated, LitStr, Token};
+
+pub(crate) fn build_foreign_language_testcases(tokens: TokenStream) -> TokenStream {
+ let input = parse_macro_input!(tokens as BuildForeignLanguageTestCaseInput);
+ // we resolve each path relative to the crate root directory.
+ let pkg_dir = env::var("CARGO_MANIFEST_DIR")
+ .expect("Missing $CARGO_MANIFEST_DIR, cannot build tests for generated bindings");
+
+ // For each test file found, generate a matching testcase.
+ let test_functions = input
+ .test_scripts
+ .iter()
+ .map(|file_path| {
+ let test_file_pathbuf: Utf8PathBuf = [&pkg_dir, file_path].iter().collect();
+ let test_file_path = test_file_pathbuf.to_string();
+ let test_file_name = test_file_pathbuf
+ .file_name()
+ .expect("Test file has no name, cannot build tests for generated bindings");
+ let test_name = format_ident!(
+ "uniffi_foreign_language_testcase_{}",
+ test_file_name.replace(|c: char| !c.is_alphanumeric(), "_")
+ );
+ let run_test = match test_file_pathbuf.extension() {
+ Some("kts") => quote! {
+ uniffi::kotlin_run_test
+ },
+ Some("swift") => quote! {
+ uniffi::swift_run_test
+ },
+ Some("py") => quote! {
+ uniffi::python_run_test
+ },
+ Some("rb") => quote! {
+ uniffi::ruby_run_test
+ },
+ _ => panic!("Unexpected extension for test script: {test_file_name}"),
+ };
+ let maybe_ignore = if should_skip_path(&test_file_pathbuf) {
+ quote! { #[ignore] }
+ } else {
+ quote! {}
+ };
+ quote! {
+ #maybe_ignore
+ #[test]
+ fn #test_name () -> uniffi::deps::anyhow::Result<()> {
+ #run_test(
+ std::env!("CARGO_TARGET_TMPDIR"),
+ std::env!("CARGO_PKG_NAME"),
+ #test_file_path)
+ }
+ }
+ })
+ .collect::<Vec<proc_macro2::TokenStream>>();
+ let test_module = quote! {
+ #(#test_functions)*
+ };
+ TokenStream::from(test_module)
+}
+
+// UNIFFI_TESTS_DISABLE_EXTENSIONS contains a comma-sep'd list of extensions (without leading `.`)
+fn should_skip_path(path: &Utf8Path) -> bool {
+ let ext = path.extension().expect("File has no extension!");
+ env::var("UNIFFI_TESTS_DISABLE_EXTENSIONS")
+ .map(|v| v.split(',').any(|look| look == ext))
+ .unwrap_or(false)
+}
+
+struct BuildForeignLanguageTestCaseInput {
+ test_scripts: Vec<String>,
+}
+
+impl syn::parse::Parse for BuildForeignLanguageTestCaseInput {
+ fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
+ let test_scripts = Punctuated::<LitStr, Token![,]>::parse_terminated(input)?
+ .iter()
+ .map(|s| s.value())
+ .collect();
+
+ Ok(Self { test_scripts })
+ }
+}