mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-24 04:57:00 +01:00
providing server configuration in the testkit::test macro (#1953)
This commit is contained in:
parent
51d016cfb3
commit
c742497866
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -4265,6 +4265,7 @@ dependencies = [
|
||||||
name = "testkit-macros"
|
name = "testkit-macros"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"kanidmd_core",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.28",
|
"syn 2.0.28",
|
||||||
|
|
|
@ -245,6 +245,13 @@ impl Configuration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_for_test() -> Self {
|
||||||
|
Configuration {
|
||||||
|
threads: 1,
|
||||||
|
..Configuration::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update_online_backup(&mut self, cfg: &Option<OnlineBackup>) {
|
pub fn update_online_backup(&mut self, cfg: &Option<OnlineBackup>) {
|
||||||
match cfg {
|
match cfg {
|
||||||
None => {}
|
None => {}
|
||||||
|
|
|
@ -7,6 +7,7 @@ edition = "2021"
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
kanidmd_core.workspace = true
|
||||||
proc-macro2 = { workspace = true }
|
proc-macro2 = { workspace = true }
|
||||||
quote = { workspace = true }
|
quote = { workspace = true }
|
||||||
syn = { workspace = true }
|
syn = { workspace = true }
|
||||||
|
|
|
@ -1,10 +1,25 @@
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use proc_macro2::{Ident, Span};
|
use proc_macro2::{Ident, Span};
|
||||||
use syn::spanned::Spanned;
|
use syn::{parse::Parser, punctuated::Punctuated, spanned::Spanned, ExprAssign, Token};
|
||||||
|
|
||||||
use quote::{quote, quote_spanned, ToTokens};
|
use quote::{quote, quote_spanned, ToTokens};
|
||||||
|
|
||||||
fn parse_knobs(input: &syn::ItemFn) -> TokenStream {
|
// for now we only allow a subset of the configuration to be tweaked, but it can be expanded in the future as needed
|
||||||
|
|
||||||
|
const ALLOWED_ATTRIBUTES: &[&str] = &[
|
||||||
|
"threads",
|
||||||
|
"db_path",
|
||||||
|
"maximum_request",
|
||||||
|
"trust_x_forward_for",
|
||||||
|
"role",
|
||||||
|
"output_mode",
|
||||||
|
"log_level",
|
||||||
|
];
|
||||||
|
|
||||||
|
fn parse_knobs(
|
||||||
|
input: &syn::ItemFn,
|
||||||
|
server_config: &Punctuated<ExprAssign, syn::token::Comma>,
|
||||||
|
) -> TokenStream {
|
||||||
// If type mismatch occurs, the current rustc points to the last statement.
|
// If type mismatch occurs, the current rustc points to the last statement.
|
||||||
let (last_stmt_start_span, _last_stmt_end_span) = {
|
let (last_stmt_start_span, _last_stmt_end_span) = {
|
||||||
let mut last_stmt = input
|
let mut last_stmt = input
|
||||||
|
@ -23,6 +38,22 @@ fn parse_knobs(input: &syn::ItemFn) -> TokenStream {
|
||||||
(start, end)
|
(start, end)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// here we gather all the provided configuration in a struct like declaration
|
||||||
|
// By now we have already checked that the configurations provided belong to the allowed subset
|
||||||
|
let mut field_modifications = quote! {};
|
||||||
|
server_config.pairs().for_each(|p| {
|
||||||
|
let field_name = p.value().left.to_token_stream(); // here we can use to_token_stream as we know we're iterating over ExprAssigns
|
||||||
|
let field_value = p.value().right.to_token_stream();
|
||||||
|
field_modifications.extend(quote! {
|
||||||
|
#field_name: #field_value,})
|
||||||
|
});
|
||||||
|
|
||||||
|
// Setup the config filling the remaining fields with the default values
|
||||||
|
let default_config_struct = quote!(kanidmd_core::config::Configuration {
|
||||||
|
#field_modifications
|
||||||
|
..kanidmd_core::config::Configuration::new_for_test()
|
||||||
|
});
|
||||||
|
|
||||||
let rt = quote_spanned! {last_stmt_start_span=>
|
let rt = quote_spanned! {last_stmt_start_span=>
|
||||||
tokio::runtime::Builder::new_current_thread()
|
tokio::runtime::Builder::new_current_thread()
|
||||||
};
|
};
|
||||||
|
@ -43,7 +74,7 @@ fn parse_knobs(input: &syn::ItemFn) -> TokenStream {
|
||||||
#header
|
#header
|
||||||
fn #test_driver() {
|
fn #test_driver() {
|
||||||
let body = async {
|
let body = async {
|
||||||
let (rsclient, mut core_handle) = kanidmd_testkit::setup_async_test().await;
|
let (rsclient, mut core_handle) = kanidmd_testkit::setup_async_test(#default_config_struct).await;
|
||||||
#fn_name(rsclient).await;
|
#fn_name(rsclient).await;
|
||||||
core_handle.shutdown().await;
|
core_handle.shutdown().await;
|
||||||
};
|
};
|
||||||
|
@ -66,7 +97,7 @@ fn token_stream_with_error(mut tokens: TokenStream, error: syn::Error) -> TokenS
|
||||||
tokens
|
tokens
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn test(_args: &TokenStream, item: TokenStream) -> TokenStream {
|
pub(crate) fn test(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
// If any of the steps for this macro fail, we still want to expand to an item that is as close
|
// If any of the steps for this macro fail, we still want to expand to an item that is as close
|
||||||
// to the expected output as possible. This helps out IDEs such that completions and other
|
// to the expected output as possible. This helps out IDEs such that completions and other
|
||||||
// related features keep working.
|
// related features keep working.
|
||||||
|
@ -84,6 +115,31 @@ pub(crate) fn test(_args: &TokenStream, item: TokenStream) -> TokenStream {
|
||||||
let msg = "the `async` keyword is missing from the function declaration";
|
let msg = "the `async` keyword is missing from the function declaration";
|
||||||
return token_stream_with_error(item, syn::Error::new_spanned(input.sig.fn_token, msg));
|
return token_stream_with_error(item, syn::Error::new_spanned(input.sig.fn_token, msg));
|
||||||
}
|
}
|
||||||
|
let args: Punctuated<ExprAssign, syn::token::Comma> =
|
||||||
parse_knobs(&input)
|
match Punctuated::<ExprAssign, Token![,]>::parse_terminated.parse(args.clone()) {
|
||||||
|
Ok(it) => it,
|
||||||
|
Err(e) => return token_stream_with_error(args, e),
|
||||||
|
};
|
||||||
|
let args_are_allowed = args.pairs().all(|p| {
|
||||||
|
ALLOWED_ATTRIBUTES.to_vec().contains(
|
||||||
|
&p.value()
|
||||||
|
.left
|
||||||
|
.span()
|
||||||
|
.source_text()
|
||||||
|
.unwrap_or_default()
|
||||||
|
.as_str(),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
if !args_are_allowed {
|
||||||
|
let msg =
|
||||||
|
"Currently only a subset of all the server configs can be set. Here is the full list";
|
||||||
|
return token_stream_with_error(
|
||||||
|
item,
|
||||||
|
syn::Error::new_spanned(
|
||||||
|
input.sig.fn_token,
|
||||||
|
format!("{}: {}", msg, ALLOWED_ATTRIBUTES.join(", ")),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
parse_knobs(&input, &args)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,5 +19,5 @@ use proc_macro::TokenStream;
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
|
pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
entry::test(&args, item)
|
entry::test(args, item)
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ use std::sync::atomic::{AtomicU16, Ordering};
|
||||||
|
|
||||||
use kanidm_client::{KanidmClient, KanidmClientBuilder};
|
use kanidm_client::{KanidmClient, KanidmClientBuilder};
|
||||||
use kanidm_proto::v1::{Filter, Modify, ModifyList};
|
use kanidm_proto::v1::{Filter, Modify, ModifyList};
|
||||||
use kanidmd_core::config::{Configuration, IntegrationTestConfig, ServerRole};
|
use kanidmd_core::config::{Configuration, IntegrationTestConfig};
|
||||||
use kanidmd_core::{create_server_core, CoreHandle};
|
use kanidmd_core::{create_server_core, CoreHandle};
|
||||||
use tokio::task;
|
use tokio::task;
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ pub fn is_free_port(port: u16) -> bool {
|
||||||
|
|
||||||
// allowed because the use of this function is behind a test gate
|
// allowed because the use of this function is behind a test gate
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub async fn setup_async_test() -> (KanidmClient, CoreHandle) {
|
pub async fn setup_async_test(mut config: Configuration) -> (KanidmClient, CoreHandle) {
|
||||||
sketching::test_init();
|
sketching::test_init();
|
||||||
|
|
||||||
let mut counter = 0;
|
let mut counter = 0;
|
||||||
|
@ -61,14 +61,11 @@ pub async fn setup_async_test() -> (KanidmClient, CoreHandle) {
|
||||||
|
|
||||||
let addr = format!("http://localhost:{}", port);
|
let addr = format!("http://localhost:{}", port);
|
||||||
|
|
||||||
// Setup the config ...
|
// Setup the address and origin..
|
||||||
let mut config = Configuration::new();
|
|
||||||
config.address = format!("127.0.0.1:{}", port);
|
config.address = format!("127.0.0.1:{}", port);
|
||||||
config.integration_test_config = Some(int_config);
|
config.integration_test_config = Some(int_config);
|
||||||
config.role = ServerRole::WriteReplica;
|
|
||||||
config.domain = "localhost".to_string();
|
config.domain = "localhost".to_string();
|
||||||
config.origin = addr.clone();
|
config.origin = addr.clone();
|
||||||
config.threads = 1;
|
|
||||||
|
|
||||||
let core_handle = match create_server_core(config, false).await {
|
let core_handle = match create_server_core(config, false).await {
|
||||||
Ok(val) => val,
|
Ok(val) => val,
|
||||||
|
|
Loading…
Reference in a new issue