use ink_ir::{
ast,
format_err_spanned,
utils::{
duplicate_config_err,
WhitelistedAttributes,
},
};
#[derive(Debug, Default, PartialEq, Eq)]
pub struct E2EConfig {
ws_url: Option<syn::LitStr>,
whitelisted_attributes: WhitelistedAttributes,
additional_contracts: Vec<String>,
}
impl TryFrom<ast::AttributeArgs> for E2EConfig {
type Error = syn::Error;
fn try_from(args: ast::AttributeArgs) -> Result<Self, Self::Error> {
let mut ws_url: Option<(syn::LitStr, ast::MetaNameValue)> = None;
let mut whitelisted_attributes = WhitelistedAttributes::default();
let mut additional_contracts: Option<(syn::LitStr, ast::MetaNameValue)> = None;
for arg in args.into_iter() {
if arg.name.is_ident("ws_url") {
if let Some((_, ast)) = ws_url {
return Err(duplicate_config_err(ast, arg, "ws_url", "e2e test"))
}
if let ast::PathOrLit::Lit(syn::Lit::Str(lit_str)) = &arg.value {
ws_url = Some((lit_str.clone(), arg))
} else {
return Err(format_err_spanned!(
arg,
"expected a string literal for `ws_url` ink! e2e test configuration argument",
))
}
} else if arg.name.is_ident("keep_attr") {
whitelisted_attributes.parse_arg_value(&arg)?;
} else if arg.name.is_ident("additional_contracts") {
if let Some((_, ast)) = additional_contracts {
return Err(duplicate_config_err(
ast,
arg,
"additional_contracts",
"e2e test",
))
}
if let ast::PathOrLit::Lit(syn::Lit::Str(lit_str)) = &arg.value {
additional_contracts = Some((lit_str.clone(), arg))
} else {
return Err(format_err_spanned!(
arg,
"expected a bool literal for `additional_contracts` ink! e2e test configuration argument",
))
}
} else {
return Err(format_err_spanned!(
arg,
"encountered unknown or unsupported ink! configuration argument",
))
}
}
let additional_contracts = additional_contracts
.map(|(value, _)| value.value().split(' ').map(String::from).collect())
.unwrap_or_else(Vec::new);
Ok(E2EConfig {
ws_url: ws_url.map(|(value, _)| value),
additional_contracts,
whitelisted_attributes,
})
}
}
impl E2EConfig {
pub fn ws_url(&self) -> syn::LitStr {
let default_ws_url =
syn::LitStr::new("ws://0.0.0.0:9944", proc_macro2::Span::call_site());
self.ws_url.clone().unwrap_or(default_ws_url)
}
pub fn additional_contracts(&self) -> Vec<String> {
self.additional_contracts.clone()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Environment {
pub path: syn::Path,
}
impl Default for Environment {
fn default() -> Self {
Self {
path: syn::parse_quote! { ::ink_env::DefaultEnvironment },
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn assert_try_from(
input: ast::AttributeArgs,
expected: Result<E2EConfig, &'static str>,
) {
assert_eq!(
<E2EConfig as TryFrom<ast::AttributeArgs>>::try_from(input)
.map_err(|err| err.to_string()),
expected.map_err(ToString::to_string),
);
}
#[test]
fn empty_config_works() {
assert_try_from(syn::parse_quote! {}, Ok(E2EConfig::default()))
}
#[test]
fn unknown_arg_fails() {
assert_try_from(
syn::parse_quote! { unknown = argument },
Err("encountered unknown or unsupported ink! configuration argument"),
);
}
#[test]
fn duplicate_args_fails() {
assert_try_from(
syn::parse_quote! {
additional_contracts = "adder/Cargo.toml",
additional_contracts = "adder/Cargo.toml",
},
Err(
"encountered duplicate ink! e2e test `additional_contracts` configuration argument",
),
);
}
#[test]
fn keep_attr_works() {
let mut attrs = WhitelistedAttributes::default();
attrs.0.insert("foo".to_string(), ());
attrs.0.insert("bar".to_string(), ());
assert_try_from(
syn::parse_quote! {
keep_attr = "foo, bar"
},
Ok(E2EConfig {
ws_url: None,
whitelisted_attributes: attrs,
additional_contracts: Vec::new(),
}),
)
}
#[test]
fn keep_attr_invalid_value_fails() {
assert_try_from(
syn::parse_quote! { keep_attr = 1u16 },
Err("expected a string with attributes separated by `,`"),
);
}
}