Skip to main content
Glama
lib.rs12.8 kB
extern crate proc_macro; mod dal_test; mod expand; mod sdf_test; use std::collections::HashSet; use proc_macro::TokenStream; use syn::{ Ident, ItemFn, Path, Token, parse::{ Parse, ParseStream, }, parse_macro_input, punctuated::Punctuated, }; const LOG_ENV_VAR: &str = "SI_TEST_LOG"; const SPAN_EVENTS_ENV_VAR: &str = "SI_TEST_LOG_SPAN_EVENTS"; const RT_DEFAULT_WORKER_THREADS: usize = 2; const RT_DEFAULT_THREAD_STACK_SIZE: usize = 2 * 1024 * 1024 * 3; #[allow(dead_code)] // We aren't current using args on the macro, but when we do we can drop this // line struct Args { pub(crate) vars: HashSet<Ident>, } impl Parse for Args { fn parse(input: ParseStream) -> syn::Result<Self> { let vars = Punctuated::<Ident, Token![,]>::parse_terminated(input)?; Ok(Self { vars: vars.into_iter().collect(), }) } } fn path_as_string(path: &Path) -> String { path.segments .iter() .map(|s| s.ident.to_string()) .collect::<Vec<_>>() .join("::") } /// A procedural macro which helps to streamline, setup, and manage DAL object-related tests. /// /// The attribute is intended to replace the default `#[test]` attribute, the augmented /// `#[tokio::test]` attribute provided by Tokio, and even the `#[test_log::test]` attribute which /// configures optional tracing/logging output. /// /// # Examples /// /// ## Optional Support for Results /// /// You can opt to return an `eyre_color::Result<()>` type, allowing for the question mark /// operator: /// /// ```ignore /// use color_eyre::Result; /// use crate::dal::test; /// /// #[test] /// async fn good_defaults() -> Result<()> { /// // ... /// Ok(()) /// } /// ``` /// /// ## Reasonable Default /// /// Writing a test which begins with: /// /// * a fully signed up workspace /// * with an open change set /// * with the workspace's tenancy /// * with the `SystemInit` history actor /// /// ```ignore /// use dal::DalContext; /// use crate::dal::test; /// /// #[test] /// async fn good_defaults(ctx: DalContext) { /// // ... /// } /// ``` /// /// ## Mutating Default Context /// /// If the context needs to be mutated in place, it can also be mutably into the test: /// /// ```ignore /// use dal::DalContext; /// use crate::dal::test; /// /// #[test] /// async fn good_defaults(mut ctx: DalContext) { /// ctx.update_to_head(); /// // ... /// } /// ``` /// /// ## Borrowed Default Context /// /// It might make sense to have an immutably borrowed context, which is also supported: /// /// ```ignore /// use dal::DalContext; /// use crate::dal::test; /// /// #[test] /// async fn good_defaults(ctx: &DalContext) { /// // ... /// } /// ``` /// /// ## Mutating Default Borrowed Context /// /// Finallayy, if the borrowed context needs to be mutated in place, it can also be mutably /// borrowed into the test: /// /// ```ignore /// use dal::DalContext; /// use crate::dal::test; /// /// #[test] /// async fn good_defaults(ctx: &mut DalContext) { /// ctx.update_to_head(); /// // ... /// } /// ``` /// /// # Owned Types /// /// The following types can be used as test function arguments as owned types, provided by the /// internal setup code generated by the attribute: /// /// * `ctx: DalContext`: a DAL context for the created workspace with an open change /// set /// * `mut ctx: DalContext`: a mutable DAL context for the created workspace with an open /// change set /// * `builder: DalContextBuilder`: the builder to create DAL context objects /// * `DalContextHead(ctx): DalContextHead`: a DAL context for a workspace for a visibility /// which is not in a change set. `ctx` is **owned**. /// * `DalContextHeadRef(ctx): DalContextHeadRef<'_>`: a reference to a DAL context for a workspace /// for a visibility which is not in a change set /// * `DalContextHeadMutRef(ctx): DalContextHeadMutRef<'_>`: a mutable reference to a DAL context /// for a workspace for a visibility which is not in a change set /// * `services_ctx: ServicesContext`: a services context object, used to create DAL contexts /// * `wid: WorkspacePk: the workspace PK created for this test /// * `nw: WorkspaceSignup`: the full "new-workspace" data structure, created for this /// test /// /// # Referenced/Borrowed Types /// /// The following types can be used as test function arguments as borrowed types, provided by the /// internal setup code generated by the attribute: /// /// * `ctx: &DalContext`: a reference to the the default DAL context /// * `ctx: &mut DalContext`: a mutable reference to the the default DAL context /// * `builder: &DalContextBuilder`: a reference to the builder to create DAL context objects /// * `services_ctx: &ServicesContext`: a reference to a services context object, used to create /// DAL contexts /// * `nw: &WorkspaceSignup`: a reference to the full "new-workspace" data structure, /// created for this test /// /// # Customized Tokio Runtime /// /// The attribute uses a similar strategy to the stock `#[tokio::test]` attribute, except that this /// attribute runs a threaded runtime as opposed to the current thread runtime, allowing for future /// stack size cusomization. Currently the runtime uses a default thread stack size of **3** times /// the system default (implementation constant is located in `src/dal_test.rs` from /// `RT_DEFAULT_THREAD_STACK_SIZE`). /// /// # Optional and Configurable Logging Output for Tests /// /// As with the `test-env-log` and `test-log` crates, this attribute also sets up tracing support /// to log to console in the presence of certain environment variables. /// /// To enable logging output, the `SI_TEST_LOG` environment variable must be set, and if you wish /// to see all logging output, even when the tests pass, then you must also use the `--nocapture` /// flag with `cargo test`. For example: /// /// ```ignore /// env SI_TEST_LOG=info cargo test -- --nocapture /// ``` /// /// Additionally, tracing spans can be enabled and configured via the `SI_TEST_LOG_SPAN_EVENTS` /// environment variable. For example, to see the "new" and "close" span events in the logging /// output: /// /// ```ignore /// env SI_TEST_LOG=info SI_TEST_LOG_SPAN_EVENTS=new,close cargo test -- --nocapture /// ``` /// Note that for span events, the following are valid: /// /// * `new` /// * `enter` /// * `exit` /// * `close` /// * `active` /// * `full` /// /// The implementation for tracing is located in `src/extract.rs` in the `expand_tracing_init()` /// function. #[proc_macro_attribute] pub fn dal_test(attr: TokenStream, input: TokenStream) -> TokenStream { let args = parse_macro_input!(attr as Args); let item = parse_macro_input!(input as ItemFn); dal_test::expand(item, args).into() } /// A procedural macro which helps to streamline, setup, and manage SDF-related tests. /// /// The attribute is intended to replace the default `#[test]` attribute, the augmented /// `#[tokio::test]` attribute provided by Tokio, and even the `#[test_log::test]` attribute which /// configures optional tracing/logging output. /// /// # Examples /// /// ## Optional Support for Results /// /// You can opt to return an `eyre_color::Result<()>` type, allowing for the question mark /// operator: /// /// ```ignore /// use color_eyre::Result; /// use dal_test::sdf_test as test; /// /// #[test] /// async fn good_defaults() -> Result<()> { /// // ... /// Ok(()) /// } /// ``` /// /// ## Reasonable Default /// /// Writing a test which begins with: /// /// * a fully signed up workspace /// * with an open change set /// * with the workspace's tenancy /// * with the `SystemInit` history actor /// /// ```ignore /// use dal::DalContext; /// use dal_test::sdf_test as test; /// /// #[test] /// async fn good_defaults(ctx: DalContext) { /// // ... /// } /// ``` /// /// ## Mutating Default Context /// /// If the context needs to be mutated in place, it can also be mutably into the test: /// /// ```ignore /// use dal::DalContext; /// use dal_test::sdf_test as test; /// /// #[test] /// async fn good_defaults(mut ctx: DalContext) { /// ctx.update_to_head(); /// // ... /// } /// ``` /// /// ## Borrowed Default Context /// /// It might make sense to have an immutably borrowed context, which is also supported: /// /// ```ignore /// use dal::DalContext; /// use dal_test::sdf_test as test; /// /// #[test] /// async fn good_defaults(ctx: &DalContext) { /// // ... /// } /// ``` /// /// ## Mutating Default Borrowed Context /// /// Finallayy, if the borrowed context needs to be mutated in place, it can also be mutably /// borrowed into the test: /// /// ```ignore /// use dal::DalContext; /// use dal_test::sdf_test as test; /// /// #[test] /// async fn good_defaults(ctx: &mut DalContext) { /// ctx.update_to_head(); /// // ... /// } /// ``` /// /// # Owned Types /// /// The following types can be used as test function arguments as owned types, provided by the /// internal setup code generated by the attribute: /// /// * `AuthToken(auth_token): AuthToken`: an auth token string which can be passed to SDF to make /// requests /// * `AuthTokenRef(auth_token): AuthTokenRef`: a reference to an auth token string slice which can /// be passed to SDF to make requests /// * `ctx: DalContext`: a DAL context for the created workspace with an open change /// set /// * `mut ctx: DalContext`: a mutable DAL context for the created workspace with an open /// change set /// * `builder: DalContextBuilder`: the builder to create DAL context objects /// * `DalContextHead(ctx): DalContextHead`: a DAL context for a workspace for a visibility /// which is not in a change set. `ctx` is **owned**. /// * `DalContextHeadRef(ctx): DalContextHeadRef<'_>`: a reference to a DAL context for a workspace /// for a visibility which is not in a change set /// * `DalContextHeadMutRef(ctx): DalContextHeadMutRef<'_>`: a mutable reference to a DAL context /// for a workspace for a visibility which is not in a change set /// * `services_ctx: ServicesContext`: a services context object, used to create DAL contexts /// * `wid: WorkspacePk: the workspace PK created for this test /// * `nw: WorkspaceSignup`: the full "new-workspace" data structure, created for this /// test /// /// # Referenced/Borrowed Types /// /// The following types can be used as test function arguments as borrowed types, provided by the /// internal setup code generated by the attribute: /// /// * `ctx: &DalContext`: a reference to the the default DAL context /// * `ctx: &mut DalContext`: a mutable reference to the the default DAL context /// * `builder: &DalContextBuilder`: a reference to the builder to create DAL context objects /// * `services_ctx: &ServicesContext`: a reference to a services context object, used to create /// DAL contexts /// * `nw: &WorkspaceSignup`: a reference to the full "new-workspace" data structure, /// created for this test /// /// # Customized Tokio Runtime /// /// The attribute uses a similar strategy to the stock `#[tokio::test]` attribute, except that this /// attribute runs a threaded runtime as opposed to the current thread runtime, allowing for future /// stack size cusomization. Currently the runtime uses a default thread stack size of **3** times /// the system default (implementation constant is located in `src/dal_test.rs` from /// `RT_DEFAULT_THREAD_STACK_SIZE`). /// /// # Optional and Configurable Logging Output for Tests /// /// As with the `test-env-log` and `test-log` crates, this attribute also sets up tracing support /// to log to console in the presence of certain environment variables. /// /// To enable logging output, the `SI_TEST_LOG` environment variable must be set, and if you wish /// to see all logging output, even when the tests pass, then you must also use the `--nocapture` /// flag with `cargo test`. For example: /// /// ```ignore /// env SI_TEST_LOG=info cargo test -- --nocapture /// ``` /// /// Additionally, tracing spans can be enabled and configured via the `SI_TEST_LOG_SPAN_EVENTS` /// environment variable. For example, to see the "new" and "close" span events in the logging /// output: /// /// ```ignore /// env SI_TEST_LOG=info SI_TEST_LOG_SPAN_EVENTS=new,close cargo test -- --nocapture /// ``` /// Note that for span events, the following are valid: /// /// * `new` /// * `enter` /// * `exit` /// * `close` /// * `active` /// * `full` /// /// The implementation for tracing is located in `src/extract.rs` in the `expand_tracing_init()` /// function. #[proc_macro_attribute] pub fn sdf_test(attr: TokenStream, input: TokenStream) -> TokenStream { let args = parse_macro_input!(attr as Args); let item = parse_macro_input!(input as ItemFn); sdf_test::expand(item, args).into() }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systeminit/si'

If you have feedback or need assistance with the MCP directory API, please join our Discord server