mirror of
https://github.com/fluencelabs/marine-rs-sdk-test
synced 2024-12-04 15:20:18 +00:00
houskeeping
This commit is contained in:
parent
0574adb39a
commit
de2e61e60b
@ -23,7 +23,7 @@ use thiserror::Error as ThisError;
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum TestGeneratorError {
|
||||
#[error("{0}")]
|
||||
#[error("Can't load Wasm modules into FCE: {0}")]
|
||||
WITParserError(#[from] WITParserError),
|
||||
|
||||
#[error("{0}")]
|
||||
@ -32,7 +32,7 @@ pub enum TestGeneratorError {
|
||||
#[error("{0}")]
|
||||
SynError(#[from] SynError),
|
||||
|
||||
#[error("{0}")]
|
||||
#[error("Can't load Wasm modules from the provided config: {0}")]
|
||||
ConfigLoadError(#[from] AppServiceError),
|
||||
|
||||
#[error("{0}")]
|
||||
|
@ -1,451 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::attributes::FCETestAttributes;
|
||||
use crate::{TResult, TestGeneratorError};
|
||||
|
||||
use fluence_app_service::TomlAppServiceConfig;
|
||||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use quote::quote;
|
||||
use quote::ToTokens;
|
||||
|
||||
pub fn fce_test_impl(attrs: TokenStream2, input: TokenStream2) -> TResult<TokenStream2> {
|
||||
use darling::FromMeta;
|
||||
|
||||
// from https://github.com/dtolnay/syn/issues/788
|
||||
let parser = syn::punctuated::Punctuated::<syn::NestedMeta, syn::Token![,]>::parse_terminated;
|
||||
let attrs = parser.parse2(attrs)?;
|
||||
let attrs: Vec<syn::NestedMeta> = attrs.into_iter().collect();
|
||||
let attrs = FCETestAttributes::from_list(&attrs)?;
|
||||
|
||||
let func_item = syn::parse2::<syn::ItemFn>(input)?;
|
||||
|
||||
generate_test_glue_code(func_item, attrs)
|
||||
}
|
||||
|
||||
fn generate_test_glue_code(
|
||||
func_item: syn::ItemFn,
|
||||
attrs: FCETestAttributes,
|
||||
) -> TResult<TokenStream2> {
|
||||
let fce_config = TomlAppServiceConfig::load(&attrs.config_path)?;
|
||||
let modules_dir = match determine_modules_dir(&fce_config, attrs.modules_dir) {
|
||||
Some(modules_dir) => modules_dir,
|
||||
None => return Err(TestGeneratorError::ModulesDirUnspecified),
|
||||
};
|
||||
|
||||
let fce_ctor = generate_fce_ctor(&attrs.config_path, &modules_dir);
|
||||
let module_interfaces = collect_module_interfaces(&fce_config, modules_dir)?;
|
||||
|
||||
let module_definitions = generate_module_definitions(module_interfaces.iter())?;
|
||||
let module_iter = module_interfaces
|
||||
.iter()
|
||||
.map(|(module_name, _)| *module_name);
|
||||
let module_ctors = generate_module_ctors(module_iter)?;
|
||||
let original_block = func_item.block;
|
||||
let signature = func_item.sig;
|
||||
|
||||
let glue_code = quote! {
|
||||
#[test]
|
||||
#signature {
|
||||
#module_definitions
|
||||
|
||||
#fce_ctor
|
||||
|
||||
#module_ctors
|
||||
|
||||
#original_block
|
||||
}
|
||||
};
|
||||
|
||||
Ok(glue_code)
|
||||
}
|
||||
|
||||
fn generate_fce_ctor(config_path: &str, modules_dir: &PathBuf) -> TokenStream2 {
|
||||
let config_path = config_path.to_token_stream();
|
||||
let modules_dir = modules_dir.to_string_lossy().to_string();
|
||||
|
||||
quote! {
|
||||
let tmp_dir = std::env::temp_dir();
|
||||
let service_id = fluence_test::internal::Uuid::new_v4().to_string();
|
||||
|
||||
let tmp_dir = tmp_dir.join(&service_id);
|
||||
let tmp_dir = tmp_dir.to_string_lossy().to_string();
|
||||
std::fs::create_dir(&tmp_dir).expect("can't create a directory for service in tmp");
|
||||
|
||||
let mut __fce_generated_fce_config = fluence_test::internal::TomlAppServiceConfig::load(#config_path.to_string())
|
||||
.unwrap_or_else(|e| panic!("app service located at `{}` config can't be loaded: {}", #config_path, e));
|
||||
__fce_generated_fce_config.service_base_dir = Some(tmp_dir);
|
||||
__fce_generated_fce_config.toml_faas_config.modules_dir = Some(#modules_dir.to_string());
|
||||
|
||||
let fce = fluence_test::internal::AppService::new_with_empty_facade(__fce_generated_fce_config, service_id, std::collections::HashMap::new())
|
||||
.unwrap_or_else(|e| panic!("app service can't be created: {}", e));
|
||||
|
||||
let fce = std::rc::Rc::new(std::cell::RefCell::new(fce));
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_module_ctors<'n>(
|
||||
module_names: impl ExactSizeIterator<Item = &'n str>,
|
||||
) -> TResult<TokenStream2> {
|
||||
let mut module_ctors = Vec::with_capacity(module_names.len());
|
||||
for name in module_names {
|
||||
// TODO: optimize these two call because they are called twice for each module name
|
||||
// and internally allocate memory in format
|
||||
let module_name = generate_module_name(&name)?;
|
||||
let struct_name = generate_struct_name(&name)?;
|
||||
let name_for_user = new_ident(&name)?;
|
||||
|
||||
let module_ctor =
|
||||
quote! { let mut #name_for_user = #module_name::#struct_name { fce: fce.clone() }; };
|
||||
module_ctors.push(module_ctor);
|
||||
}
|
||||
|
||||
let module_ctors = quote! { #(#module_ctors),* };
|
||||
|
||||
Ok(module_ctors)
|
||||
}
|
||||
|
||||
use fce_wit_parser::module_raw_interface;
|
||||
use fce_wit_parser::interface::FCEModuleInterface;
|
||||
use fce_wit_parser::interface::FCERecordTypes;
|
||||
use fce_wit_parser::interface::FCEFunctionSignature;
|
||||
use fce_wit_parser::interface::it::IFunctionArg;
|
||||
use fce_wit_parser::interface::it::IRecordFieldType;
|
||||
use fce_wit_parser::interface::it::IType;
|
||||
|
||||
use std::path::PathBuf;
|
||||
use syn::parse::Parser;
|
||||
|
||||
fn generate_module_definitions<'i>(
|
||||
module_interfaces: impl ExactSizeIterator<Item = &'i (&'i str, FCEModuleInterface)>,
|
||||
) -> TResult<TokenStream2> {
|
||||
let mut module_definitions = Vec::with_capacity(module_interfaces.len());
|
||||
|
||||
for interface in module_interfaces {
|
||||
let module_definition = generate_module_definition(&interface.0, &interface.1)?;
|
||||
module_definitions.push(module_definition);
|
||||
}
|
||||
|
||||
let module_definitions = quote! { #(#module_definitions),*};
|
||||
|
||||
Ok(module_definitions)
|
||||
}
|
||||
|
||||
fn generate_module_definition(
|
||||
module_name: &str,
|
||||
module_interface: &FCEModuleInterface,
|
||||
) -> TResult<TokenStream2> {
|
||||
let module_name_ident = generate_module_name(module_name)?;
|
||||
let struct_name_ident = generate_struct_name(module_name)?;
|
||||
let module_records = generate_records(&module_interface.record_types)?;
|
||||
let module_functions = generate_module_methods(
|
||||
module_name,
|
||||
module_interface.function_signatures.iter(),
|
||||
&module_interface.record_types,
|
||||
)?;
|
||||
|
||||
let module_definition = quote! {
|
||||
pub mod #module_name_ident {
|
||||
#module_records
|
||||
|
||||
pub struct #struct_name_ident {
|
||||
pub fce: std::rc::Rc<std::cell::RefCell<fluence_test::internal::AppService>>,
|
||||
}
|
||||
|
||||
impl #struct_name_ident {
|
||||
#(#module_functions)*
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(module_definition)
|
||||
}
|
||||
|
||||
fn generate_module_methods<'m, 'r>(
|
||||
module_name: &str,
|
||||
method_signatures: impl ExactSizeIterator<Item = &'m FCEFunctionSignature>,
|
||||
records: &'r FCERecordTypes,
|
||||
) -> TResult<Vec<TokenStream2>> {
|
||||
let mut result = Vec::with_capacity(method_signatures.len());
|
||||
|
||||
for signature in method_signatures {
|
||||
let func_name = new_ident(&signature.name)?;
|
||||
let arguments = generate_arguments(signature.arguments.iter(), records)?;
|
||||
let output_type = generate_output_type(&signature.outputs, records)?;
|
||||
let fce_call = generate_fce_call(module_name, &signature, records)?;
|
||||
|
||||
let module_method = quote! {
|
||||
pub fn #func_name(&mut self, #(#arguments),*) #output_type {
|
||||
#fce_call
|
||||
}
|
||||
};
|
||||
|
||||
result.push(module_method);
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn generate_fce_call(
|
||||
module_name: &str,
|
||||
method_signature: &FCEFunctionSignature,
|
||||
records: &FCERecordTypes,
|
||||
) -> TResult<TokenStream2> {
|
||||
let args = method_signature.arguments.iter().map(|a| a.name.as_str());
|
||||
let convert_arguments = generate_arguments_converter(args)?;
|
||||
|
||||
let output_type = get_output_type(&method_signature.outputs);
|
||||
let set_result = generate_set_result(&output_type);
|
||||
let function_call = generate_function_call(module_name, &method_signature.name);
|
||||
let convert_result_to_output_type = generate_convert_to_output(&output_type, records)?;
|
||||
let ret = generate_ret(&output_type);
|
||||
|
||||
let function_call = quote! {
|
||||
use std::ops::DerefMut;
|
||||
|
||||
#convert_arguments
|
||||
|
||||
#set_result #function_call
|
||||
|
||||
#convert_result_to_output_type
|
||||
|
||||
#ret
|
||||
};
|
||||
|
||||
Ok(function_call)
|
||||
}
|
||||
|
||||
fn generate_arguments_converter<'a>(
|
||||
args: impl ExactSizeIterator<Item = &'a str>,
|
||||
) -> TResult<TokenStream2> {
|
||||
let mut arguments = Vec::with_capacity(args.len());
|
||||
|
||||
for arg in args {
|
||||
let arg_ident = new_ident(arg)?;
|
||||
arguments.push(arg_ident);
|
||||
}
|
||||
|
||||
let arguments_serializer =
|
||||
quote! { let arguments = fluence_test::internal::json!([#(#arguments),*]); };
|
||||
Ok(arguments_serializer)
|
||||
}
|
||||
|
||||
fn generate_function_call(module_name: &str, method_name: &str) -> TokenStream2 {
|
||||
quote! { self.fce.as_ref().borrow_mut().call_with_module_name(#module_name, #method_name, arguments, <_>::default()).expect("call to FCE failed"); }
|
||||
}
|
||||
|
||||
fn generate_set_result(output_type: &Option<&IType>) -> TokenStream2 {
|
||||
match output_type {
|
||||
Some(_) => quote! { let result = },
|
||||
None => TokenStream2::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_convert_to_output(
|
||||
output_type: &Option<&IType>,
|
||||
records: &FCERecordTypes,
|
||||
) -> TResult<TokenStream2> {
|
||||
let result_stream = match output_type {
|
||||
Some(ty) => {
|
||||
let ty = itype_to_tokens(ty, records)?;
|
||||
quote! {
|
||||
let result: #ty = serde_json::from_value(result).expect("the default deserializer shouldn't fail");
|
||||
}
|
||||
}
|
||||
None => TokenStream2::new(),
|
||||
};
|
||||
|
||||
Ok(result_stream)
|
||||
}
|
||||
|
||||
fn generate_ret(output_type: &Option<&IType>) -> TokenStream2 {
|
||||
match output_type {
|
||||
Some(_) => quote! { result },
|
||||
None => TokenStream2::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_arguments<'a, 'r>(
|
||||
arguments: impl ExactSizeIterator<Item = &'a IFunctionArg>,
|
||||
records: &'r FCERecordTypes,
|
||||
) -> TResult<Vec<TokenStream2>> {
|
||||
let mut result = Vec::with_capacity(arguments.len());
|
||||
for argument in arguments {
|
||||
let arg_name = new_ident(&argument.name)?;
|
||||
let arg_type = itype_to_tokens(&argument.ty, records)?;
|
||||
|
||||
let arg = quote! { #arg_name: #arg_type };
|
||||
result.push(arg);
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn generate_output_type(output_types: &[IType], records: &FCERecordTypes) -> TResult<TokenStream2> {
|
||||
let output_type = get_output_type(output_types);
|
||||
match output_type {
|
||||
None => Ok(TokenStream2::new()),
|
||||
Some(ty) => {
|
||||
let output_type = itype_to_tokens(&ty, records)?;
|
||||
let output_type = quote! { -> #output_type };
|
||||
|
||||
Ok(output_type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_output_type(output_types: &[IType]) -> Option<&IType> {
|
||||
match output_types.len() {
|
||||
0 => None,
|
||||
1 => Some(&output_types[0]),
|
||||
_ => unimplemented!("function with more than 1 arguments aren't supported now"),
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_records(records: &FCERecordTypes) -> TResult<TokenStream2> {
|
||||
use std::ops::Deref;
|
||||
|
||||
let mut result = TokenStream2::new();
|
||||
|
||||
for (_, record) in records.iter() {
|
||||
let record_name_ident = generate_record_name(&record.name)?;
|
||||
let fields = prepare_field(record.fields.deref(), records)?;
|
||||
|
||||
let record = quote! {
|
||||
#[derive(Clone, fluence_test::internal::Serialize, fluence_test::internal::Deserialize)]
|
||||
pub struct #record_name_ident {
|
||||
#fields
|
||||
}
|
||||
};
|
||||
result.extend(record);
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn prepare_field(fields: &[IRecordFieldType], records: &FCERecordTypes) -> TResult<TokenStream2> {
|
||||
let mut result = TokenStream2::new();
|
||||
|
||||
for field in fields {
|
||||
let field_name = new_ident(&field.name)?;
|
||||
let field_type = itype_to_tokens(&field.ty, records)?;
|
||||
|
||||
let field = quote! { #field_name: #field_type, };
|
||||
result.extend(field);
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn generate_module_name(module_name: &str) -> TResult<syn::Ident> {
|
||||
let extended_module_name = format!("__fce_generated_{}", module_name);
|
||||
new_ident(&extended_module_name)
|
||||
}
|
||||
|
||||
fn generate_record_name(record_name: &str) -> TResult<syn::Ident> {
|
||||
let extended_record_name = format!("{}", record_name);
|
||||
new_ident(&extended_record_name)
|
||||
}
|
||||
|
||||
fn generate_struct_name(struct_name: &str) -> TResult<syn::Ident> {
|
||||
let extended_struct_name = format!("FCEGeneratedStruct{}", struct_name);
|
||||
new_ident(&extended_struct_name)
|
||||
}
|
||||
|
||||
fn new_ident(ident_str: &str) -> TResult<syn::Ident> {
|
||||
syn::parse_str::<syn::Ident>(ident_str).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn itype_to_tokens(itype: &IType, records: &FCERecordTypes) -> TResult<TokenStream2> {
|
||||
let token_stream = match itype {
|
||||
IType::Record(record_id) => {
|
||||
let record = records
|
||||
.get(record_id)
|
||||
.ok_or_else(|| crate::errors::CorruptedITSection::AbsentRecord(*record_id))?;
|
||||
let record_name = new_ident(&record.name)?;
|
||||
let token_stream = quote! { #record_name };
|
||||
token_stream
|
||||
}
|
||||
IType::Array(ty) => {
|
||||
let inner_ty_token_stream = itype_to_tokens(ty, records)?;
|
||||
let token_stream = quote! { Vec<#inner_ty_token_stream> };
|
||||
token_stream
|
||||
}
|
||||
IType::String => quote! { String },
|
||||
IType::S8 => quote! { i8 },
|
||||
IType::S16 => quote! { i16 },
|
||||
IType::S32 => quote! { i32 },
|
||||
IType::S64 => quote! { i64 },
|
||||
IType::U8 => quote! { u8 },
|
||||
IType::U16 => quote! { u16 },
|
||||
IType::U32 => quote! { u32 },
|
||||
IType::U64 => quote! { u64 },
|
||||
IType::I32 => quote! { i32 },
|
||||
IType::I64 => quote! { i64 },
|
||||
IType::F32 => quote! { f32 },
|
||||
IType::F64 => quote! { f64 },
|
||||
IType::Anyref => unimplemented!("anyref isn't supported and will be deleted from IType"),
|
||||
};
|
||||
|
||||
Ok(token_stream)
|
||||
}
|
||||
|
||||
fn collect_module_interfaces(
|
||||
config: &TomlAppServiceConfig,
|
||||
modules_dir: PathBuf,
|
||||
) -> TResult<Vec<(&str, FCEModuleInterface)>> {
|
||||
let module_paths = collect_module_paths(config, modules_dir);
|
||||
println!("module paths: {:?}", module_paths);
|
||||
|
||||
module_paths
|
||||
.into_iter()
|
||||
.map(|(name, path)| module_raw_interface(path).map(|interface| (name, interface)))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
fn collect_module_paths(
|
||||
config: &TomlAppServiceConfig,
|
||||
modules_dir: PathBuf,
|
||||
) -> Vec<(&str, PathBuf)> {
|
||||
config
|
||||
.toml_faas_config
|
||||
.module
|
||||
.iter()
|
||||
.map(|m| {
|
||||
let module_file_name = m.file_name.as_ref().unwrap_or_else(|| &m.name);
|
||||
let module_file_name = PathBuf::from(module_file_name);
|
||||
// TODO: is it right to always have .wasm extension?
|
||||
let module_path = modules_dir.join(module_file_name).with_extension("wasm");
|
||||
|
||||
(m.name.as_str(), module_path)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
fn determine_modules_dir(
|
||||
config: &TomlAppServiceConfig,
|
||||
modules_dir: Option<String>,
|
||||
) -> Option<PathBuf> {
|
||||
match modules_dir {
|
||||
Some(modules_dir) => Some(PathBuf::from(modules_dir)),
|
||||
None => config
|
||||
.toml_faas_config
|
||||
.modules_dir
|
||||
.as_ref()
|
||||
.map(|p| PathBuf::from(p)),
|
||||
}
|
||||
}
|
82
crates/fce-test-macro-impl/src/fce_test/config_worker.rs
Normal file
82
crates/fce-test-macro-impl/src/fce_test/config_worker.rs
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::TResult;
|
||||
|
||||
use fluence_app_service::TomlAppServiceConfig;
|
||||
use fce_wit_parser::module_raw_interface;
|
||||
use fce_wit_parser::interface::FCEModuleInterface;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub(super) struct Module<'m> {
|
||||
pub name: &'m str,
|
||||
pub interface: FCEModuleInterface,
|
||||
}
|
||||
|
||||
impl<'m> Module<'m> {
|
||||
fn new(name: &'m str, interface: FCEModuleInterface) -> Self {
|
||||
Self { name, interface }
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn collect_modules(
|
||||
config: &TomlAppServiceConfig,
|
||||
modules_dir: PathBuf,
|
||||
) -> TResult<Vec<Module<'_>>> {
|
||||
let module_paths = collect_module_paths(config, modules_dir);
|
||||
|
||||
module_paths
|
||||
.into_iter()
|
||||
.map(|(name, path)| {
|
||||
module_raw_interface(path).map(|interface| Module::new(name, interface))
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
fn collect_module_paths(
|
||||
config: &TomlAppServiceConfig,
|
||||
modules_dir: PathBuf,
|
||||
) -> Vec<(&str, PathBuf)> {
|
||||
config
|
||||
.toml_faas_config
|
||||
.module
|
||||
.iter()
|
||||
.map(|m| {
|
||||
let module_file_name = m.file_name.as_ref().unwrap_or_else(|| &m.name);
|
||||
let module_file_name = PathBuf::from(module_file_name);
|
||||
// TODO: is it correct to always have .wasm extension?
|
||||
let module_path = modules_dir.join(module_file_name).with_extension("wasm");
|
||||
|
||||
(m.name.as_str(), module_path)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
pub(super) fn determine_modules_dir(
|
||||
config: &TomlAppServiceConfig,
|
||||
modules_dir: Option<String>,
|
||||
) -> Option<PathBuf> {
|
||||
match modules_dir {
|
||||
Some(modules_dir) => Some(PathBuf::from(modules_dir)),
|
||||
None => config
|
||||
.toml_faas_config
|
||||
.modules_dir
|
||||
.as_ref()
|
||||
.map(|p| PathBuf::from(p)),
|
||||
}
|
||||
}
|
35
crates/fce-test-macro-impl/src/fce_test/fce_test_impl.rs
Normal file
35
crates/fce-test-macro-impl/src/fce_test/fce_test_impl.rs
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::attributes::FCETestAttributes;
|
||||
use crate::TResult;
|
||||
use crate::fce_test::glue_code_generator::generate_test_glue_code;
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use darling::FromMeta;
|
||||
use syn::parse::Parser;
|
||||
|
||||
pub fn fce_test_impl(attrs: TokenStream, input: TokenStream) -> TResult<TokenStream> {
|
||||
// from https://github.com/dtolnay/syn/issues/788
|
||||
let parser = syn::punctuated::Punctuated::<syn::NestedMeta, syn::Token![,]>::parse_terminated;
|
||||
let attrs = parser.parse2(attrs)?;
|
||||
let attrs: Vec<syn::NestedMeta> = attrs.into_iter().collect();
|
||||
let attrs = FCETestAttributes::from_list(&attrs)?;
|
||||
|
||||
let func_item = syn::parse2::<syn::ItemFn>(input)?;
|
||||
|
||||
generate_test_glue_code(func_item, attrs)
|
||||
}
|
109
crates/fce-test-macro-impl/src/fce_test/glue_code_generator.rs
Normal file
109
crates/fce-test-macro-impl/src/fce_test/glue_code_generator.rs
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::attributes::FCETestAttributes;
|
||||
use crate::TResult;
|
||||
use crate::TestGeneratorError;
|
||||
use crate::fce_test;
|
||||
|
||||
use fluence_app_service::TomlAppServiceConfig;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use quote::ToTokens;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub(super) fn generate_test_glue_code(
|
||||
func_item: syn::ItemFn,
|
||||
attrs: FCETestAttributes,
|
||||
) -> TResult<TokenStream> {
|
||||
let fce_config = TomlAppServiceConfig::load(&attrs.config_path)?;
|
||||
let modules_dir =
|
||||
match fce_test::config_worker::determine_modules_dir(&fce_config, attrs.modules_dir) {
|
||||
Some(modules_dir) => modules_dir,
|
||||
None => return Err(TestGeneratorError::ModulesDirUnspecified),
|
||||
};
|
||||
|
||||
let fce_ctor = generate_fce_ctor(&attrs.config_path, &modules_dir);
|
||||
let module_interfaces = fce_test::config_worker::collect_modules(&fce_config, modules_dir)?;
|
||||
|
||||
let module_definitions =
|
||||
fce_test::module_generator::generate_module_definitions(module_interfaces.iter())?;
|
||||
let module_iter = module_interfaces.iter().map(|module| module.name);
|
||||
let module_ctors = generate_module_ctors(module_iter)?;
|
||||
let original_block = func_item.block;
|
||||
let signature = func_item.sig;
|
||||
|
||||
let glue_code = quote! {
|
||||
#[test]
|
||||
#signature {
|
||||
#module_definitions
|
||||
|
||||
#fce_ctor
|
||||
|
||||
#module_ctors
|
||||
|
||||
#original_block
|
||||
}
|
||||
};
|
||||
|
||||
Ok(glue_code)
|
||||
}
|
||||
|
||||
fn generate_fce_ctor(config_path: &str, modules_dir: &PathBuf) -> TokenStream {
|
||||
let config_path = config_path.to_token_stream();
|
||||
let modules_dir = modules_dir.to_string_lossy().to_string();
|
||||
|
||||
quote! {
|
||||
let tmp_dir = std::env::temp_dir();
|
||||
let service_id = fluence_test::internal::Uuid::new_v4().to_string();
|
||||
|
||||
let tmp_dir = tmp_dir.join(&service_id);
|
||||
let tmp_dir = tmp_dir.to_string_lossy().to_string();
|
||||
std::fs::create_dir(&tmp_dir).expect("can't create a directory for service in tmp");
|
||||
|
||||
let mut __fce_generated_fce_config = fluence_test::internal::TomlAppServiceConfig::load(#config_path.to_string())
|
||||
.unwrap_or_else(|e| panic!("app service located at `{}` config can't be loaded: {}", #config_path, e));
|
||||
__fce_generated_fce_config.service_base_dir = Some(tmp_dir);
|
||||
__fce_generated_fce_config.toml_faas_config.modules_dir = Some(#modules_dir.to_string());
|
||||
|
||||
let fce = fluence_test::internal::AppService::new_with_empty_facade(__fce_generated_fce_config, service_id, std::collections::HashMap::new())
|
||||
.unwrap_or_else(|e| panic!("app service can't be created: {}", e));
|
||||
|
||||
let fce = std::rc::Rc::new(std::cell::RefCell::new(fce));
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_module_ctors<'n>(
|
||||
module_names: impl ExactSizeIterator<Item = &'n str>,
|
||||
) -> TResult<TokenStream> {
|
||||
let mut module_ctors = Vec::with_capacity(module_names.len());
|
||||
for name in module_names {
|
||||
// TODO: optimize these two call because they are called twice for each module name
|
||||
// and internally allocate memory in format call.
|
||||
let module_name = fce_test::utils::generate_module_name(&name)?;
|
||||
let struct_name = fce_test::utils::generate_struct_name(&name)?;
|
||||
let name_for_user = fce_test::utils::new_ident(&name)?;
|
||||
|
||||
let module_ctor =
|
||||
quote! { let mut #name_for_user = #module_name::#struct_name { fce: fce.clone() }; };
|
||||
module_ctors.push(module_ctor);
|
||||
}
|
||||
|
||||
let module_ctors = quote! { #(#module_ctors),* };
|
||||
|
||||
Ok(module_ctors)
|
||||
}
|
23
crates/fce-test-macro-impl/src/fce_test/mod.rs
Normal file
23
crates/fce-test-macro-impl/src/fce_test/mod.rs
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
mod config_worker;
|
||||
mod fce_test_impl;
|
||||
mod glue_code_generator;
|
||||
mod module_generator;
|
||||
mod utils;
|
||||
|
||||
pub use fce_test_impl::fce_test_impl;
|
72
crates/fce-test-macro-impl/src/fce_test/module_generator.rs
Normal file
72
crates/fce-test-macro-impl/src/fce_test/module_generator.rs
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
mod methods_generator;
|
||||
mod record_type_generator;
|
||||
|
||||
use crate::fce_test::utils;
|
||||
use crate::fce_test::config_worker::Module;
|
||||
use crate::TResult;
|
||||
|
||||
use fce_wit_parser::interface::FCEModuleInterface;
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
pub(super) fn generate_module_definitions<'i>(
|
||||
modules: impl ExactSizeIterator<Item = &'i Module<'i>>,
|
||||
) -> TResult<TokenStream> {
|
||||
let mut module_definitions = Vec::with_capacity(modules.len());
|
||||
|
||||
for module in modules {
|
||||
let module_definition = generate_module_definition(&module.name, &module.interface)?;
|
||||
module_definitions.push(module_definition);
|
||||
}
|
||||
|
||||
let module_definitions = quote! { #(#module_definitions),*};
|
||||
|
||||
Ok(module_definitions)
|
||||
}
|
||||
|
||||
fn generate_module_definition(
|
||||
module_name: &str,
|
||||
module_interface: &FCEModuleInterface,
|
||||
) -> TResult<TokenStream> {
|
||||
let module_name_ident = utils::generate_module_name(module_name)?;
|
||||
let struct_name_ident = utils::generate_struct_name(module_name)?;
|
||||
let module_records = record_type_generator::generate_records(&module_interface.record_types)?;
|
||||
let module_functions = methods_generator::generate_module_methods(
|
||||
module_name,
|
||||
module_interface.function_signatures.iter(),
|
||||
&module_interface.record_types,
|
||||
)?;
|
||||
|
||||
let module_definition = quote! {
|
||||
pub mod #module_name_ident {
|
||||
#module_records
|
||||
|
||||
pub struct #struct_name_ident {
|
||||
pub fce: std::rc::Rc<std::cell::RefCell<fluence_test::internal::AppService>>,
|
||||
}
|
||||
|
||||
impl #struct_name_ident {
|
||||
#(#module_functions)*
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(module_definition)
|
||||
}
|
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::fce_test::utils;
|
||||
use crate::TResult;
|
||||
|
||||
use fce_wit_parser::interface::it::IType;
|
||||
use fce_wit_parser::interface::it::IFunctionArg;
|
||||
use fce_wit_parser::interface::FCERecordTypes;
|
||||
use fce_wit_parser::interface::FCEFunctionSignature;
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
pub(super) fn generate_module_methods<'m, 'r>(
|
||||
module_name: &str,
|
||||
method_signatures: impl ExactSizeIterator<Item = &'m FCEFunctionSignature>,
|
||||
records: &'r FCERecordTypes,
|
||||
) -> TResult<Vec<TokenStream>> {
|
||||
let mut result = Vec::with_capacity(method_signatures.len());
|
||||
|
||||
for signature in method_signatures {
|
||||
let func_name = utils::new_ident(&signature.name)?;
|
||||
let arguments = generate_arguments(signature.arguments.iter(), records)?;
|
||||
let output_type = generate_output_type(&signature.outputs, records)?;
|
||||
let fce_call = generate_fce_call(module_name, &signature, records)?;
|
||||
|
||||
let module_method = quote! {
|
||||
pub fn #func_name(&mut self, #(#arguments),*) #output_type {
|
||||
#fce_call
|
||||
}
|
||||
};
|
||||
|
||||
result.push(module_method);
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn generate_fce_call(
|
||||
module_name: &str,
|
||||
method_signature: &FCEFunctionSignature,
|
||||
records: &FCERecordTypes,
|
||||
) -> TResult<TokenStream> {
|
||||
let args = method_signature.arguments.iter().map(|a| a.name.as_str());
|
||||
let convert_arguments = generate_arguments_converter(args)?;
|
||||
|
||||
let output_type = get_output_type(&method_signature.outputs);
|
||||
let set_result = generate_set_result(&output_type);
|
||||
let function_call = generate_function_call(module_name, &method_signature.name);
|
||||
let convert_result_to_output_type = generate_convert_to_output(&output_type, records)?;
|
||||
let ret = generate_ret(&output_type);
|
||||
|
||||
let function_call = quote! {
|
||||
use std::ops::DerefMut;
|
||||
|
||||
#convert_arguments
|
||||
|
||||
#set_result #function_call
|
||||
|
||||
#convert_result_to_output_type
|
||||
|
||||
#ret
|
||||
};
|
||||
|
||||
Ok(function_call)
|
||||
}
|
||||
|
||||
fn generate_arguments_converter<'a>(
|
||||
args: impl ExactSizeIterator<Item = &'a str>,
|
||||
) -> TResult<TokenStream> {
|
||||
let mut arguments = Vec::with_capacity(args.len());
|
||||
|
||||
for arg in args {
|
||||
let arg_ident = utils::new_ident(arg)?;
|
||||
arguments.push(arg_ident);
|
||||
}
|
||||
|
||||
let arguments_serializer =
|
||||
quote! { let arguments = fluence_test::internal::json!([#(#arguments),*]); };
|
||||
|
||||
Ok(arguments_serializer)
|
||||
}
|
||||
|
||||
fn generate_function_call(module_name: &str, method_name: &str) -> TokenStream {
|
||||
quote! { self.fce.as_ref().borrow_mut().call_with_module_name(#module_name, #method_name, arguments, <_>::default()).expect("call to FCE failed"); }
|
||||
}
|
||||
|
||||
fn generate_set_result(output_type: &Option<&IType>) -> TokenStream {
|
||||
match output_type {
|
||||
Some(_) => quote! { let result = },
|
||||
None => TokenStream::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_convert_to_output(
|
||||
output_type: &Option<&IType>,
|
||||
records: &FCERecordTypes,
|
||||
) -> TResult<TokenStream> {
|
||||
let result_stream = match output_type {
|
||||
Some(ty) => {
|
||||
let ty = utils::itype_to_tokens(ty, records)?;
|
||||
quote! {
|
||||
let result: #ty = serde_json::from_value(result).expect("the default deserializer shouldn't fail");
|
||||
}
|
||||
}
|
||||
None => TokenStream::new(),
|
||||
};
|
||||
|
||||
Ok(result_stream)
|
||||
}
|
||||
|
||||
fn generate_ret(output_type: &Option<&IType>) -> TokenStream {
|
||||
match output_type {
|
||||
Some(_) => quote! { result },
|
||||
None => TokenStream::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_arguments<'a, 'r>(
|
||||
arguments: impl ExactSizeIterator<Item = &'a IFunctionArg>,
|
||||
records: &'r FCERecordTypes,
|
||||
) -> TResult<Vec<TokenStream>> {
|
||||
let mut result = Vec::with_capacity(arguments.len());
|
||||
for argument in arguments {
|
||||
let arg_name = utils::new_ident(&argument.name)?;
|
||||
let arg_type = utils::itype_to_tokens(&argument.ty, records)?;
|
||||
|
||||
let arg = quote! { #arg_name: #arg_type };
|
||||
result.push(arg);
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn generate_output_type(output_types: &[IType], records: &FCERecordTypes) -> TResult<TokenStream> {
|
||||
let output_type = get_output_type(output_types);
|
||||
match output_type {
|
||||
None => Ok(TokenStream::new()),
|
||||
Some(ty) => {
|
||||
let output_type = utils::itype_to_tokens(&ty, records)?;
|
||||
let output_type = quote! { -> #output_type };
|
||||
|
||||
Ok(output_type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_output_type(output_types: &[IType]) -> Option<&IType> {
|
||||
match output_types.len() {
|
||||
0 => None,
|
||||
1 => Some(&output_types[0]),
|
||||
_ => unimplemented!("function with more than 1 arguments aren't supported now"),
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::fce_test::utils;
|
||||
use crate::TResult;
|
||||
|
||||
use fce_wit_parser::interface::it::IRecordFieldType;
|
||||
use fce_wit_parser::interface::FCERecordTypes;
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
pub(super) fn generate_records(records: &FCERecordTypes) -> TResult<TokenStream> {
|
||||
use std::ops::Deref;
|
||||
|
||||
let mut result = TokenStream::new();
|
||||
|
||||
for (_, record) in records.iter() {
|
||||
let record_name_ident = utils::generate_record_name(&record.name)?;
|
||||
let fields = prepare_field(record.fields.deref().iter(), records)?;
|
||||
|
||||
let record = quote! {
|
||||
#[derive(Clone, fluence_test::internal::Serialize, fluence_test::internal::Deserialize)]
|
||||
pub struct #record_name_ident {
|
||||
#(#fields),*
|
||||
}
|
||||
};
|
||||
result.extend(record);
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn prepare_field<'f>(
|
||||
fields: impl ExactSizeIterator<Item = &'f IRecordFieldType>,
|
||||
records: &FCERecordTypes,
|
||||
) -> TResult<Vec<TokenStream>> {
|
||||
let mut result = Vec::with_capacity(fields.len());
|
||||
|
||||
for field in fields {
|
||||
let field_name = utils::new_ident(&field.name)?;
|
||||
let field_type = utils::itype_to_tokens(&field.ty, records)?;
|
||||
|
||||
let field = quote! { #field_name: #field_type };
|
||||
result.push(field);
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
77
crates/fce-test-macro-impl/src/fce_test/utils.rs
Normal file
77
crates/fce-test-macro-impl/src/fce_test/utils.rs
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::TResult;
|
||||
use fce_wit_parser::interface::FCERecordTypes;
|
||||
use fce_wit_parser::interface::it::IType;
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
pub(super) fn generate_module_name(module_name: &str) -> TResult<syn::Ident> {
|
||||
let extended_module_name = format!("__fce_generated_{}", module_name);
|
||||
new_ident(&extended_module_name)
|
||||
}
|
||||
|
||||
pub(super) fn generate_record_name(record_name: &str) -> TResult<syn::Ident> {
|
||||
let extended_record_name = format!("{}", record_name);
|
||||
new_ident(&extended_record_name)
|
||||
}
|
||||
|
||||
pub(super) fn generate_struct_name(struct_name: &str) -> TResult<syn::Ident> {
|
||||
let extended_struct_name = format!("FCEGeneratedStruct{}", struct_name);
|
||||
new_ident(&extended_struct_name)
|
||||
}
|
||||
|
||||
pub(super) fn new_ident(ident_str: &str) -> TResult<syn::Ident> {
|
||||
syn::parse_str::<syn::Ident>(ident_str).map_err(Into::into)
|
||||
}
|
||||
|
||||
pub(super) fn itype_to_tokens(itype: &IType, records: &FCERecordTypes) -> TResult<TokenStream> {
|
||||
let token_stream = match itype {
|
||||
IType::Record(record_id) => {
|
||||
let record = records
|
||||
.get(record_id)
|
||||
.ok_or_else(|| crate::errors::CorruptedITSection::AbsentRecord(*record_id))?;
|
||||
let record_name = new_ident(&record.name)?;
|
||||
let token_stream = quote! { #record_name };
|
||||
token_stream
|
||||
}
|
||||
IType::Array(ty) => {
|
||||
let inner_ty_token_stream = itype_to_tokens(ty, records)?;
|
||||
let token_stream = quote! { Vec<#inner_ty_token_stream> };
|
||||
token_stream
|
||||
}
|
||||
IType::String => quote! { String },
|
||||
IType::S8 => quote! { i8 },
|
||||
IType::S16 => quote! { i16 },
|
||||
IType::S32 => quote! { i32 },
|
||||
IType::S64 => quote! { i64 },
|
||||
IType::U8 => quote! { u8 },
|
||||
IType::U16 => quote! { u16 },
|
||||
IType::U32 => quote! { u32 },
|
||||
IType::U64 => quote! { u64 },
|
||||
IType::I32 => quote! { i32 },
|
||||
IType::I64 => quote! { i64 },
|
||||
IType::F32 => quote! { f32 },
|
||||
IType::F64 => quote! { f64 },
|
||||
IType::Anyref => {
|
||||
unimplemented!("anyrefs aren't supported and will be deleted from IType soon")
|
||||
}
|
||||
};
|
||||
|
||||
Ok(token_stream)
|
||||
}
|
41
crates/fce-test-macro-impl/src/fce_test_.rs
Normal file
41
crates/fce-test-macro-impl/src/fce_test_.rs
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::attributes::FCETestAttributes;
|
||||
use crate::TResult;
|
||||
use crate::TestGeneratorError;
|
||||
|
||||
use fluence_app_service::TomlAppServiceConfig;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use quote::ToTokens;
|
||||
|
||||
|
||||
|
||||
use fce_wit_parser::module_raw_interface;
|
||||
use fce_wit_parser::interface::FCEModuleInterface;
|
||||
use fce_wit_parser::interface::FCERecordTypes;
|
||||
use fce_wit_parser::interface::FCEFunctionSignature;
|
||||
use fce_wit_parser::interface::it::IFunctionArg;
|
||||
use fce_wit_parser::interface::it::IRecordFieldType;
|
||||
use fce_wit_parser::interface::it::IType;
|
||||
|
||||
use std::path::PathBuf;
|
||||
use syn::parse::Parser;
|
||||
|
||||
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/fluence-sdk-macro/0.5.0")]
|
||||
#![deny(
|
||||
// dead_code,
|
||||
dead_code,
|
||||
nonstandard_style,
|
||||
unused_imports,
|
||||
unused_mut,
|
||||
|
@ -19,7 +19,6 @@ path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
fluence-sdk-test-macro = { path = "../crates/fce-test-macro", version = "=0.5.0" }
|
||||
fluence-sdk-test-macro-impl = { path = "../crates/fce-test-macro-impl", version = "=0.5.0" }
|
||||
fluence-app-service = { version = "0.5.2", features = ["raw-module-api"] }
|
||||
|
||||
serde = { version = "1.0.118", features = ["derive"] }
|
||||
|
@ -27,7 +27,6 @@
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
pub use fluence_sdk_test_macro::fce_test;
|
||||
pub use fluence_sdk_test_macro_impl::fce_test_impl;
|
||||
|
||||
/// These API functions are intended for internal usage in generated code.
|
||||
/// Normally, you shouldn't use them.
|
||||
|
Loading…
Reference in New Issue
Block a user