summaryrefslogtreecommitdiff
path: root/rola-utils/space-system/macros
diff options
context:
space:
mode:
Diffstat (limited to 'rola-utils/space-system/macros')
-rw-r--r--rola-utils/space-system/macros/Cargo.toml15
-rw-r--r--rola-utils/space-system/macros/src/lib.rs9
-rw-r--r--rola-utils/space-system/macros/src/space_root_test.rs110
3 files changed, 134 insertions, 0 deletions
diff --git a/rola-utils/space-system/macros/Cargo.toml b/rola-utils/space-system/macros/Cargo.toml
new file mode 100644
index 0000000..84ba691
--- /dev/null
+++ b/rola-utils/space-system/macros/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "space-macros"
+version.workspace = true
+edition.workspace = true
+authors.workspace = true
+license.workspace = true
+
+[lib]
+proc-macro = true
+
+[dependencies]
+syn.workspace = true
+quote.workspace = true
+proc-macro2.workspace = true
+just_fmt.workspace = true
diff --git a/rola-utils/space-system/macros/src/lib.rs b/rola-utils/space-system/macros/src/lib.rs
new file mode 100644
index 0000000..838155c
--- /dev/null
+++ b/rola-utils/space-system/macros/src/lib.rs
@@ -0,0 +1,9 @@
+use crate::space_root_test::internal_space_root_test_derive;
+use proc_macro::TokenStream;
+
+mod space_root_test;
+
+#[proc_macro_derive(SpaceRootTest, attributes(space_root_test_generic))]
+pub fn space_root_test_derive(input: TokenStream) -> TokenStream {
+ internal_space_root_test_derive(input)
+}
diff --git a/rola-utils/space-system/macros/src/space_root_test.rs b/rola-utils/space-system/macros/src/space_root_test.rs
new file mode 100644
index 0000000..71c48c0
--- /dev/null
+++ b/rola-utils/space-system/macros/src/space_root_test.rs
@@ -0,0 +1,110 @@
+use proc_macro::TokenStream;
+use quote::quote;
+use syn::{
+ DeriveInput, Token,
+ parse::{Parse, ParseStream},
+ parse_macro_input,
+};
+
+/// Parsed content of `#[space_root_test_generic(...)]`.
+struct GenericArgs {
+ types: Vec<syn::Type>,
+}
+
+impl Parse for GenericArgs {
+ fn parse(input: ParseStream) -> syn::Result<Self> {
+ let mut types = Vec::new();
+ if !input.is_empty() {
+ types.push(input.parse()?);
+ while !input.is_empty() {
+ let _: Token![,] = input.parse()?;
+ if !input.is_empty() {
+ types.push(input.parse()?);
+ }
+ }
+ }
+ Ok(GenericArgs { types })
+ }
+}
+
+pub(crate) fn internal_space_root_test_derive(input: TokenStream) -> TokenStream {
+ let input = parse_macro_input!(input as DeriveInput);
+
+ let name = &input.ident;
+
+ // Extract generic args from `#[space_root_test_generic(...)]`
+ let generics = input
+ .attrs
+ .iter()
+ .find(|attr| attr.path().is_ident("space_root_test_generic"))
+ .and_then(|attr| attr.parse_args::<GenericArgs>().ok())
+ .unwrap_or(GenericArgs { types: Vec::new() });
+
+ // Build the turbofish segment if there are generic args
+ let turbofish = if generics.types.is_empty() {
+ quote! {}
+ } else {
+ let params = &generics.types[..];
+ quote! { ::< #(#params),* > }
+ };
+
+ let test_mod_name = syn::Ident::new(
+ &format!(
+ "test_{}_space_root",
+ just_fmt::snake_case!(name.to_string())
+ ),
+ name.span(),
+ );
+
+ let expanded = quote! {
+ #[cfg(test)]
+ mod #test_mod_name {
+ use super::*;
+ use shared_functions::rola_test_sandbox;
+ use space_system::{Space, SpaceRoot, SpaceRootFindPattern};
+ use std::env::set_current_dir;
+
+ #[tokio::test]
+ async fn test_create_space() {
+ let sandbox = rola_test_sandbox(stringify!(#name));
+ set_current_dir(&*sandbox).unwrap();
+
+ let mut space = Space::new(#name #turbofish ::default());
+
+ match #name #turbofish ::get_pattern() {
+ SpaceRootFindPattern::AbsolutePath(path_buf) => {
+ let dir = sandbox.join("root");
+ println!("Redirect absolute path:");
+ println!(" from: `{}`", path_buf.display());
+ println!(" to: `{}`", dir.display());
+ space.set_override_pattern(Some(
+ SpaceRootFindPattern::AbsolutePath(dir.clone()),
+ ));
+
+ println!("Checking if {} absolute directory does not exist before initialization", stringify!(#name));
+ assert!(!dir.exists());
+
+ space.init_here().await.unwrap();
+
+ println!("Checking if {} absolute directory exists after initialization", stringify!(#name));
+ assert!(dir.exists());
+ println!("\u{001b}[33;1mwarning\u{001b}[0m: Absolute path test completed in isolated environment, may not fully represent system runtime conditions");
+
+ return;
+ },
+ _ => {}
+ }
+
+ println!("Checking if {} does not exist before initialization", stringify!(#name));
+ assert!(space.space_dir_current().is_err());
+
+ space.init_here().await.unwrap();
+
+ println!("Checking if {} exists after initialization", stringify!(#name));
+ assert!(space.space_dir_current().is_ok());
+ }
+ }
+ };
+
+ TokenStream::from(expanded)
+}