mirror of
https://github.com/fluencelabs/marine-rs-sdk-test
synced 2024-12-04 23:30:18 +00:00
Implement marine_test for services integration (first part) (#61)
This commit is contained in:
parent
715e2f0e7e
commit
631c6d9885
@ -15,10 +15,17 @@
|
||||
*/
|
||||
|
||||
use darling::FromMeta;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Describes attributes of `marine_test` macro.
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) enum MTestAttributes {
|
||||
SingleService(ServiceDescription),
|
||||
MultipleServices(HashMap<String, ServiceDescription>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, FromMeta)]
|
||||
pub(crate) struct MTestAttributes {
|
||||
pub(crate) struct ServiceDescription {
|
||||
/// Path to a config file of a tested service.
|
||||
pub(crate) config_path: String,
|
||||
|
||||
@ -26,3 +33,24 @@ pub(crate) struct MTestAttributes {
|
||||
#[darling(default)]
|
||||
pub(crate) modules_dir: Option<String>,
|
||||
}
|
||||
|
||||
impl FromMeta for MTestAttributes {
|
||||
fn from_list(items: &[syn::NestedMeta]) -> darling::Result<Self> {
|
||||
let single_service = ServiceDescription::from_list(items);
|
||||
let multiple_services = HashMap::<String, ServiceDescription>::from_list(items);
|
||||
match (single_service, multiple_services) {
|
||||
(Ok(modules), Err(_)) => Ok(Self::SingleService(modules)),
|
||||
(Err(_), Ok(services)) if !services.is_empty() => Ok(Self::MultipleServices(services)),
|
||||
(Err(_), Ok(_)) => Err(darling::Error::custom(
|
||||
r#"Need to specify "config_path" and "modules_dir" or several named services with these fields "#,
|
||||
)),
|
||||
(Err(error_single), Err(error_multiple)) => Err(darling::error::Error::multiple(vec![
|
||||
error_single,
|
||||
error_multiple,
|
||||
])),
|
||||
(Ok(_), Ok(_)) => Err(darling::Error::custom(
|
||||
"internal sdk error: marine_test attributes are ambiguous",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,6 +56,9 @@ pub enum TestGeneratorError {
|
||||
|
||||
#[error("Duplicate module: {0}")]
|
||||
DuplicateModuleName(String),
|
||||
|
||||
#[error("No modules loaded for a service")]
|
||||
NoModulesInService,
|
||||
}
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
|
@ -14,13 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::TResult;
|
||||
use crate::{TResult, TestGeneratorError};
|
||||
|
||||
use fluence_app_service::TomlAppServiceConfig;
|
||||
use marine_it_parser::module_it_interface;
|
||||
use marine_it_parser::it_interface::IModuleInterface;
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::path::{PathBuf, Path};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub(super) struct Module<'m> {
|
||||
@ -34,12 +34,36 @@ impl<'m> Module<'m> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ConfigWrapper {
|
||||
pub config: TomlAppServiceConfig,
|
||||
pub resolved_modules_dir: PathBuf,
|
||||
}
|
||||
|
||||
pub(crate) fn load_config(
|
||||
config_path: &str,
|
||||
modules_dir: Option<String>,
|
||||
file_path: &Path,
|
||||
) -> TResult<ConfigWrapper> {
|
||||
let config_path_buf = file_path.join(&config_path);
|
||||
|
||||
let marine_config = TomlAppServiceConfig::load(&config_path_buf)?;
|
||||
let modules_dir = match resolve_modules_dir(&marine_config, modules_dir) {
|
||||
Some(modules_dir) => modules_dir,
|
||||
None => return Err(TestGeneratorError::ModulesDirUnspecified),
|
||||
};
|
||||
|
||||
Ok(ConfigWrapper {
|
||||
config: marine_config,
|
||||
resolved_modules_dir: modules_dir,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns all modules the provided config consists of.
|
||||
pub(super) fn collect_modules(
|
||||
config: &TomlAppServiceConfig,
|
||||
modules_dir: PathBuf,
|
||||
) -> TResult<Vec<Module<'_>>> {
|
||||
let module_paths = collect_module_paths(config, modules_dir);
|
||||
pub(super) fn collect_modules<'config>(
|
||||
config: &'config TomlAppServiceConfig,
|
||||
modules_dir: &Path,
|
||||
) -> TResult<Vec<Module<'config>>> {
|
||||
let module_paths = collect_module_paths(config, &modules_dir);
|
||||
|
||||
module_paths
|
||||
.into_iter()
|
||||
@ -48,10 +72,10 @@ pub(super) fn collect_modules(
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
fn collect_module_paths(
|
||||
config: &TomlAppServiceConfig,
|
||||
modules_dir: PathBuf,
|
||||
) -> Vec<(&str, PathBuf)> {
|
||||
fn collect_module_paths<'config>(
|
||||
config: &'config TomlAppServiceConfig,
|
||||
modules_dir: &Path,
|
||||
) -> Vec<(&'config str, PathBuf)> {
|
||||
config
|
||||
.toml_faas_config
|
||||
.module
|
||||
|
@ -14,20 +14,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::attributes::MTestAttributes;
|
||||
use crate::TResult;
|
||||
use crate::TestGeneratorError;
|
||||
use crate::attributes::{MTestAttributes, ServiceDescription};
|
||||
use crate::marine_test;
|
||||
use crate::marine_test::config_utils;
|
||||
use crate::marine_test::{config_utils, token_stream_generator};
|
||||
use crate::TestGeneratorError;
|
||||
use crate::TResult;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use fluence_app_service::TomlAppServiceConfig;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use quote::ToTokens;
|
||||
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use syn::FnArg;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Generates glue code for tests.
|
||||
/// F.e. for this test for the greeting service
|
||||
@ -116,23 +115,35 @@ use syn::FnArg;
|
||||
pub(super) fn generate_test_glue_code(
|
||||
func_item: syn::ItemFn,
|
||||
attrs: MTestAttributes,
|
||||
file_path: PathBuf,
|
||||
test_file_path: PathBuf,
|
||||
) -> TResult<TokenStream> {
|
||||
let config_path = file_path.join(&attrs.config_path);
|
||||
match attrs {
|
||||
MTestAttributes::MultipleServices(services) => {
|
||||
generate_test_glue_code_multiple_eservices(func_item, services, test_file_path)
|
||||
}
|
||||
MTestAttributes::SingleService(service) => {
|
||||
generate_test_glue_code_single_service(func_item, service, test_file_path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let marine_config = TomlAppServiceConfig::load(&config_path)?;
|
||||
let modules_dir = match config_utils::resolve_modules_dir(&marine_config, attrs.modules_dir) {
|
||||
Some(modules_dir) => modules_dir,
|
||||
None => return Err(TestGeneratorError::ModulesDirUnspecified),
|
||||
};
|
||||
|
||||
let app_service_ctor = generate_app_service_ctor(&attrs.config_path, &modules_dir)?;
|
||||
let modules_dir = file_path.join(modules_dir);
|
||||
fn generate_test_glue_code_single_service(
|
||||
func_item: syn::ItemFn,
|
||||
service: ServiceDescription,
|
||||
test_file_path: PathBuf,
|
||||
) -> TResult<TokenStream> {
|
||||
let config_wrapper =
|
||||
config_utils::load_config(&service.config_path, service.modules_dir, &test_file_path)?;
|
||||
let modules_dir_test_relative = test_file_path.join(&config_wrapper.resolved_modules_dir);
|
||||
let module_interfaces =
|
||||
marine_test::config_utils::collect_modules(&marine_config, modules_dir)?;
|
||||
let linked_modules = marine_test::modules_linker::link_modules(&module_interfaces)?;
|
||||
config_utils::collect_modules(&config_wrapper.config, &modules_dir_test_relative)?;
|
||||
let linked_modules = marine_test::modules_linker::link_modules(
|
||||
module_interfaces
|
||||
.iter()
|
||||
.map(|module| (module.name, &module.interface)),
|
||||
)?;
|
||||
|
||||
let module_definitions = marine_test::module_generator::generate_module_definitions(
|
||||
let module_definitions = token_stream_generator::generate_module_definitions(
|
||||
module_interfaces.iter(),
|
||||
&linked_modules,
|
||||
)?;
|
||||
@ -143,7 +154,10 @@ pub(super) fn generate_test_glue_code(
|
||||
let inputs = &signature.inputs;
|
||||
let arg_names = generate_arg_names(inputs.iter())?;
|
||||
let module_ctors = generate_module_ctors(inputs.iter())?;
|
||||
|
||||
let app_service_ctor = token_stream_generator::generate_app_service_ctor(
|
||||
&service.config_path,
|
||||
&config_wrapper.resolved_modules_dir,
|
||||
)?;
|
||||
let glue_code = quote! {
|
||||
#[test]
|
||||
fn #name() {
|
||||
@ -170,62 +184,34 @@ pub(super) fn generate_test_glue_code(
|
||||
Ok(glue_code)
|
||||
}
|
||||
|
||||
fn generate_app_service_ctor(config_path: &str, modules_dir: &Path) -> TResult<TokenStream> {
|
||||
let modules_dir = modules_dir
|
||||
.to_str()
|
||||
.ok_or_else(|| TestGeneratorError::InvalidUTF8Path(modules_dir.to_path_buf()))?;
|
||||
fn generate_test_glue_code_multiple_eservices(
|
||||
func_item: syn::ItemFn,
|
||||
services: HashMap<String, ServiceDescription>,
|
||||
test_file_path: PathBuf,
|
||||
) -> TResult<TokenStream> {
|
||||
let service_definitions =
|
||||
token_stream_generator::generate_service_definitions(services, &test_file_path)?;
|
||||
|
||||
let service_ctor = quote! {
|
||||
let tmp_dir = std::env::temp_dir();
|
||||
let service_id = marine_rs_sdk_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 module_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
let mut file_path = std::path::Path::new(file!()).components();
|
||||
|
||||
let mut truncated_file_path = Vec::new();
|
||||
loop {
|
||||
if module_path.ends_with(file_path.as_path()) {
|
||||
break;
|
||||
let original_block = func_item.block;
|
||||
let signature = func_item.sig;
|
||||
let name = &signature.ident;
|
||||
let glue_code = quote! {
|
||||
#[test]
|
||||
fn #name() {
|
||||
// definitions for services specified in attributes
|
||||
pub mod marine_test_env {
|
||||
#(#service_definitions)*
|
||||
}
|
||||
|
||||
let (file_path_, remainder) = match file_path.next_back().and_then(|p| match p {
|
||||
std::path::Component::Normal(_) | std::path::Component::CurDir | std::path::Component::ParentDir => Some((file_path, p)),
|
||||
_ => None,
|
||||
}) {
|
||||
Some(t) => t,
|
||||
None => break,
|
||||
};
|
||||
file_path = file_path_;
|
||||
fn test_func() {
|
||||
#original_block
|
||||
}
|
||||
|
||||
truncated_file_path.push(remainder);
|
||||
test_func()
|
||||
}
|
||||
|
||||
for path in truncated_file_path.iter().rev() {
|
||||
module_path.push(path);
|
||||
}
|
||||
|
||||
let _ = module_path.pop();
|
||||
|
||||
let config_path = module_path.join(#config_path);
|
||||
let modules_dir = module_path.join(#modules_dir);
|
||||
let modules_dir = modules_dir.to_str().expect("modules_dir contains invalid UTF8 string");
|
||||
|
||||
let mut __m_generated_marine_config = marine_rs_sdk_test::internal::TomlAppServiceConfig::load(&config_path)
|
||||
.unwrap_or_else(|e| panic!("app service config located at `{:?}` can't be loaded: {}", config_path, e));
|
||||
__m_generated_marine_config.service_base_dir = Some(tmp_dir);
|
||||
__m_generated_marine_config.toml_faas_config.modules_dir = Some(modules_dir.to_string());
|
||||
|
||||
let marine = marine_rs_sdk_test::internal::AppService::new_with_empty_facade(__m_generated_marine_config, service_id, std::collections::HashMap::new())
|
||||
.unwrap_or_else(|e| panic!("app service can't be created: {}", e));
|
||||
|
||||
let marine = std::rc::Rc::new(std::cell::RefCell::new(marine));
|
||||
};
|
||||
|
||||
Ok(service_ctor)
|
||||
Ok(glue_code)
|
||||
}
|
||||
|
||||
fn generate_module_ctors<'inputs>(
|
||||
|
@ -17,7 +17,7 @@
|
||||
mod config_utils;
|
||||
mod marine_test_impl;
|
||||
mod glue_code_generator;
|
||||
mod module_generator;
|
||||
mod token_stream_generator;
|
||||
mod utils;
|
||||
mod modules_linker;
|
||||
|
||||
|
@ -14,10 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::marine_test::config_utils::Module;
|
||||
use crate::{TResult, TestGeneratorError};
|
||||
|
||||
use marine_it_parser::it_interface::IRecordTypes;
|
||||
use marine_it_parser::it_interface::{IRecordTypes, IModuleInterface};
|
||||
use marine_it_parser::it_interface::it::{IType, IRecordType};
|
||||
|
||||
use itertools::zip;
|
||||
@ -28,16 +27,16 @@ use std::rc::Rc;
|
||||
use static_assertions::const_assert;
|
||||
|
||||
pub(super) fn link_modules<'modules>(
|
||||
modules: &'modules [Module<'_>],
|
||||
modules: impl ExactSizeIterator<Item = (&'modules str, &'modules IModuleInterface)>,
|
||||
) -> TResult<LinkedModules<'modules>> {
|
||||
let mut all_record_types = HashMap::<IRecordTypeClosed<'_>, &str>::new();
|
||||
let mut linked_modules = HashMap::<&str, LinkedModule<'_>>::new();
|
||||
|
||||
for module in modules {
|
||||
for (name, interface) in modules {
|
||||
let mut linking_module = LinkedModule::default();
|
||||
for (_, record_type) in &module.interface.record_types {
|
||||
for record_type in interface.record_types.values() {
|
||||
let record_type_ex =
|
||||
IRecordTypeClosed::new(record_type.clone(), &module.interface.record_types);
|
||||
IRecordTypeClosed::new(record_type.clone(), &interface.record_types);
|
||||
|
||||
let entry = match all_record_types.get(&record_type_ex) {
|
||||
Some(owner_module) => RecordEntry::Use(UseDescription {
|
||||
@ -45,7 +44,7 @@ pub(super) fn link_modules<'modules>(
|
||||
name: &record_type.name,
|
||||
}),
|
||||
None => {
|
||||
all_record_types.insert(record_type_ex.clone(), module.name);
|
||||
all_record_types.insert(record_type_ex.clone(), name);
|
||||
RecordEntry::Declare(record_type_ex)
|
||||
}
|
||||
};
|
||||
@ -53,10 +52,8 @@ pub(super) fn link_modules<'modules>(
|
||||
linking_module.records.push(entry);
|
||||
}
|
||||
|
||||
if linked_modules.insert(module.name, linking_module).is_some() {
|
||||
return Err(TestGeneratorError::DuplicateModuleName(
|
||||
module.name.to_string(),
|
||||
));
|
||||
if linked_modules.insert(name, linking_module).is_some() {
|
||||
return Err(TestGeneratorError::DuplicateModuleName(name.to_string()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,14 +17,20 @@
|
||||
mod methods_generator;
|
||||
mod methods_generator_utils;
|
||||
mod record_type_generator;
|
||||
mod service_generator;
|
||||
mod service_generation_utils;
|
||||
|
||||
use crate::marine_test::utils;
|
||||
use crate::marine_test::config_utils::Module;
|
||||
use crate::marine_test::modules_linker::{LinkedModule, LinkedModules, UseDescription};
|
||||
use crate::marine_test::utils;
|
||||
use crate::TResult;
|
||||
use crate::marine_test::modules_linker::{LinkedModules, LinkedModule};
|
||||
|
||||
pub(super) use service_generator::generate_service_definitions;
|
||||
pub(super) use service_generation_utils::generate_app_service_ctor;
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use crate::marine_test::utils::new_ident;
|
||||
|
||||
/// Generates definitions of modules and records of this modules.
|
||||
/// F.e. for the greeting service the following definitions would be generated:
|
||||
@ -61,47 +67,59 @@ pub(super) fn generate_module_definitions<'i>(
|
||||
) -> TResult<Vec<TokenStream>> {
|
||||
modules
|
||||
.into_iter()
|
||||
.map(|value| generate_module_definition(value, linked_modules.get(&value.name).unwrap())) // linked_modules are built from modules
|
||||
.map(|value| {
|
||||
// linked_modules are built from modules, so unwrap is safe
|
||||
let content = generate_module_definition(
|
||||
value,
|
||||
linked_modules.get(&value.name).unwrap(),
|
||||
module_import_generator,
|
||||
)?;
|
||||
let module_ident = new_ident(&value.name)?;
|
||||
Ok(quote! {
|
||||
pub mod #module_ident {
|
||||
#content
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect::<TResult<Vec<_>>>()
|
||||
}
|
||||
|
||||
fn generate_module_definition(
|
||||
module: &Module<'_>,
|
||||
linked_module: &'_ LinkedModule<'_>,
|
||||
import_generator: fn(info: &UseDescription<'_>) -> TResult<TokenStream>,
|
||||
) -> TResult<TokenStream> {
|
||||
let module_name = module.name;
|
||||
let module_ident = utils::new_ident(module_name)?;
|
||||
let struct_ident = utils::new_ident("ModuleInterface")?;
|
||||
|
||||
let module_interface = &module.interface;
|
||||
let module_records = record_type_generator::generate_records(linked_module)?;
|
||||
let module_records = record_type_generator::generate_records(linked_module, import_generator)?;
|
||||
let module_functions = methods_generator::generate_module_methods(
|
||||
module_name,
|
||||
module_interface.function_signatures.iter(),
|
||||
&module_interface.record_types,
|
||||
module.name,
|
||||
module.interface.function_signatures.iter(),
|
||||
&module.interface.record_types,
|
||||
)?;
|
||||
|
||||
let module_definition = quote! {
|
||||
// it's a sort of hack: this module structure allows user to import structs by
|
||||
// using marine_env_test::module_name::StructName;
|
||||
pub mod #module_ident {
|
||||
#(#module_records)*
|
||||
#(#module_records)*
|
||||
|
||||
pub struct #struct_ident {
|
||||
marine: std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>, >,
|
||||
}
|
||||
pub struct #struct_ident {
|
||||
marine: std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>, >,
|
||||
}
|
||||
|
||||
impl #struct_ident {
|
||||
pub fn new(marine: std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>, >) -> Self {
|
||||
Self { marine }
|
||||
}
|
||||
impl #struct_ident {
|
||||
pub fn new(marine: std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>, >) -> Self {
|
||||
Self { marine }
|
||||
}
|
||||
}
|
||||
|
||||
impl #struct_ident {
|
||||
#(#module_functions)*
|
||||
}
|
||||
impl #struct_ident {
|
||||
#(#module_functions)*
|
||||
}
|
||||
};
|
||||
|
||||
Ok(module_definition)
|
||||
}
|
||||
|
||||
fn module_import_generator(info: &UseDescription<'_>) -> TResult<TokenStream> {
|
||||
let from_module_ident = utils::new_ident(info.from)?;
|
||||
let record_name_ident = utils::new_ident(info.name)?;
|
||||
Ok(quote! {pub use super::#from_module_ident::#record_name_ident;})
|
||||
}
|
@ -46,3 +46,26 @@ pub(super) fn generate_module_methods<'m, 'r>(
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn generate_facade_methods<'m, 'r>(
|
||||
method_signatures: impl ExactSizeIterator<Item = &'m IFunctionSignature>,
|
||||
records: &'r IRecordTypes,
|
||||
) -> TResult<Vec<proc_macro2::TokenStream>> {
|
||||
use CallParametersSettings::*;
|
||||
|
||||
let methods_count = 2 * method_signatures.len();
|
||||
method_signatures
|
||||
.sorted_by(|lhs, rhs| lhs.name.cmp(&rhs.name))
|
||||
.try_fold::<_, _, TResult<_>>(
|
||||
Vec::with_capacity(methods_count),
|
||||
|mut methods, signature| {
|
||||
let default_cp = generate_module_method_forward(&signature, Default, records)?;
|
||||
let user_cp = generate_module_method_forward(&signature, UserDefined, records)?;
|
||||
|
||||
methods.push(default_cp);
|
||||
methods.push(user_cp);
|
||||
|
||||
Ok(methods)
|
||||
},
|
||||
)
|
||||
}
|
@ -42,25 +42,28 @@ pub(super) fn generate_module_method(
|
||||
let output_type = generate_output_type(&signature.outputs, records)?;
|
||||
let mcall = generate_marine_call(module_name, cp_setting, &signature, records)?;
|
||||
|
||||
let (cp, func_name) = match cp_setting {
|
||||
CallParametersSettings::Default => {
|
||||
let func_name = new_ident(&signature.name)?;
|
||||
(TokenStream::new(), func_name)
|
||||
}
|
||||
CallParametersSettings::UserDefined => {
|
||||
let maybe_comma = if signature.arguments.is_empty() {
|
||||
TokenStream::new()
|
||||
} else {
|
||||
quote! { , }
|
||||
};
|
||||
let (cp, func_name) = generate_call_parameters(&cp_setting, signature)?;
|
||||
|
||||
let cp = quote! { #maybe_comma cp: marine_rs_sdk_test::CallParameters };
|
||||
let func_name = format!("{}_cp", signature.name);
|
||||
let func_name = new_ident(&func_name)?;
|
||||
(cp, func_name)
|
||||
let module_method = quote! {
|
||||
pub fn #func_name(&mut self, #(#arguments),* #cp) #output_type {
|
||||
#mcall
|
||||
}
|
||||
};
|
||||
|
||||
Ok(module_method)
|
||||
}
|
||||
|
||||
pub(super) fn generate_module_method_forward(
|
||||
signature: &IFunctionSignature,
|
||||
cp_setting: CallParametersSettings,
|
||||
records: &IRecordTypes,
|
||||
) -> TResult<TokenStream> {
|
||||
let arguments = generate_arguments(signature.arguments.iter(), records)?;
|
||||
let output_type = generate_output_type(&signature.outputs, records)?;
|
||||
let mcall = generate_forward_call(cp_setting, &signature)?;
|
||||
|
||||
let (cp, func_name) = generate_call_parameters(&cp_setting, signature)?;
|
||||
|
||||
let module_method = quote! {
|
||||
pub fn #func_name(&mut self, #(#arguments),* #cp) #output_type {
|
||||
#mcall
|
||||
@ -100,6 +103,30 @@ fn generate_marine_call(
|
||||
Ok(function_call)
|
||||
}
|
||||
|
||||
fn generate_forward_call(
|
||||
cp_settings: CallParametersSettings,
|
||||
method_signature: &IFunctionSignature,
|
||||
) -> TResult<TokenStream> {
|
||||
let mut args = method_signature
|
||||
.arguments
|
||||
.iter()
|
||||
.map(|a| new_ident(a.name.as_str()))
|
||||
.collect::<TResult<Vec<syn::Ident>>>()?;
|
||||
|
||||
let method_name = if let CallParametersSettings::UserDefined = cp_settings {
|
||||
args.push(new_ident("cp")?);
|
||||
new_ident(format!("{}_cp", method_signature.name.as_str()).as_str())?
|
||||
} else {
|
||||
new_ident(method_signature.name.as_str())?
|
||||
};
|
||||
|
||||
let function_call = quote! {
|
||||
self.__facade.#method_name(#(#args,)*)
|
||||
};
|
||||
|
||||
Ok(function_call)
|
||||
}
|
||||
|
||||
/// Generates type convertor to json because of AppService receives them in json.
|
||||
fn generate_arguments_converter<'a>(
|
||||
args: impl ExactSizeIterator<Item = &'a str>,
|
||||
@ -192,3 +219,27 @@ fn get_output_type(output_types: &[IType]) -> TResult<Option<&IType>> {
|
||||
_ => Err(ManyFnOutputsUnsupported),
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_call_parameters(
|
||||
cp_setting: &CallParametersSettings,
|
||||
signature: &IFunctionSignature,
|
||||
) -> TResult<(TokenStream, syn::Ident)> {
|
||||
match cp_setting {
|
||||
CallParametersSettings::Default => {
|
||||
let func_name = new_ident(&signature.name)?;
|
||||
Ok((TokenStream::new(), func_name))
|
||||
}
|
||||
CallParametersSettings::UserDefined => {
|
||||
let maybe_comma = if signature.arguments.is_empty() {
|
||||
TokenStream::new()
|
||||
} else {
|
||||
quote! { , }
|
||||
};
|
||||
|
||||
let cp = quote! { #maybe_comma cp: marine_rs_sdk_test::CallParameters };
|
||||
let func_name = format!("{}_cp", signature.name);
|
||||
let func_name = new_ident(&func_name)?;
|
||||
Ok((cp, func_name))
|
||||
}
|
||||
}
|
||||
}
|
@ -23,21 +23,20 @@ use marine_it_parser::it_interface::IRecordTypes;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
use crate::marine_test::modules_linker::{LinkedModule, RecordEntry};
|
||||
use crate::marine_test::modules_linker::{LinkedModule, RecordEntry, UseDescription};
|
||||
use itertools::Itertools;
|
||||
|
||||
pub(super) fn generate_records(linked_module: &LinkedModule<'_>) -> TResult<Vec<TokenStream>> {
|
||||
pub(super) fn generate_records(
|
||||
linked_module: &LinkedModule<'_>,
|
||||
import_generator: fn(info: &UseDescription<'_>) -> TResult<TokenStream>,
|
||||
) -> TResult<Vec<TokenStream>> {
|
||||
linked_module.records
|
||||
.iter()
|
||||
.sorted()
|
||||
.map(|record| -> TResult<_> {
|
||||
use RecordEntry::*;
|
||||
match record {
|
||||
Use(use_info) => {
|
||||
let from_module_ident = utils::new_ident(use_info.from)?;
|
||||
let record_name_ident = utils::new_ident(use_info.name)?;
|
||||
Ok(quote! {pub use super::#from_module_ident::#record_name_ident;})
|
||||
},
|
||||
Use(use_info) => import_generator(use_info),
|
||||
Declare(record) => {
|
||||
let record_name_ident = utils::new_ident(&record.record_type.name)?;
|
||||
let fields = prepare_field(record.record_type.fields.iter(), record.records)?;
|
@ -0,0 +1,204 @@
|
||||
use crate::TResult;
|
||||
use crate::TestGeneratorError;
|
||||
use crate::marine_test::config_utils::Module;
|
||||
use crate::marine_test::utils::new_ident;
|
||||
use crate::marine_test::{modules_linker, config_utils};
|
||||
use crate::marine_test::modules_linker::{LinkedModule, UseDescription};
|
||||
use super::service_generator::{ProcessedService, get_facace};
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
use std::path::Path;
|
||||
use itertools::Itertools;
|
||||
|
||||
pub(crate) fn generate_app_service_ctor(
|
||||
config_path: &str,
|
||||
modules_dir: &Path,
|
||||
) -> TResult<TokenStream> {
|
||||
let modules_dir = modules_dir
|
||||
.to_str()
|
||||
.ok_or_else(|| TestGeneratorError::InvalidUTF8Path(modules_dir.to_path_buf()))?;
|
||||
|
||||
let service_ctor = quote! {
|
||||
let tmp_dir = std::env::temp_dir();
|
||||
let service_id = marine_rs_sdk_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 module_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
let mut file_path = std::path::Path::new(file!()).components();
|
||||
|
||||
let mut truncated_file_path = Vec::new();
|
||||
loop {
|
||||
if module_path.ends_with(file_path.as_path()) {
|
||||
break;
|
||||
}
|
||||
|
||||
let (file_path_, remainder) = match file_path.next_back().and_then(|p| match p {
|
||||
std::path::Component::Normal(_) | std::path::Component::CurDir | std::path::Component::ParentDir => Some((file_path, p)),
|
||||
_ => None,
|
||||
}) {
|
||||
Some(t) => t,
|
||||
None => break,
|
||||
};
|
||||
file_path = file_path_;
|
||||
|
||||
truncated_file_path.push(remainder);
|
||||
}
|
||||
|
||||
for path in truncated_file_path.iter().rev() {
|
||||
module_path.push(path);
|
||||
}
|
||||
|
||||
let _ = module_path.pop();
|
||||
|
||||
let config_path = module_path.join(#config_path);
|
||||
let modules_dir = module_path.join(#modules_dir);
|
||||
let modules_dir = modules_dir.to_str().expect("modules_dir contains invalid UTF8 string");
|
||||
|
||||
let mut __m_generated_marine_config = marine_rs_sdk_test::internal::TomlAppServiceConfig::load(&config_path)
|
||||
.unwrap_or_else(|e| panic!("app service config located at `{:?}` can't be loaded: {}", config_path, e));
|
||||
__m_generated_marine_config.service_base_dir = Some(tmp_dir);
|
||||
__m_generated_marine_config.toml_faas_config.modules_dir = Some(modules_dir.to_string());
|
||||
|
||||
let marine = marine_rs_sdk_test::internal::AppService::new_with_empty_facade(__m_generated_marine_config, service_id, std::collections::HashMap::new())
|
||||
.unwrap_or_else(|e| panic!("app service can't be created: {}", e));
|
||||
|
||||
let marine = std::rc::Rc::new(std::cell::RefCell::new(marine));
|
||||
};
|
||||
|
||||
Ok(service_ctor)
|
||||
}
|
||||
|
||||
pub(super) fn generate_service_definition(
|
||||
service: &ProcessedService,
|
||||
test_file_path: &Path,
|
||||
linked_facade: &LinkedModule<'_>,
|
||||
) -> TResult<TokenStream> {
|
||||
let modules_dir_test_relative = test_file_path.join(&service.config.resolved_modules_dir);
|
||||
let modules =
|
||||
config_utils::collect_modules(&service.config.config, &modules_dir_test_relative)?;
|
||||
let linked_modules = modules_linker::link_modules(
|
||||
modules
|
||||
.iter()
|
||||
.map(|module| (module.name, &module.interface)),
|
||||
)?;
|
||||
|
||||
let service_mod = new_ident(&service.name)?;
|
||||
let module_definitions = super::generate_module_definitions(modules.iter(), &linked_modules)?;
|
||||
|
||||
let facade = get_facace(&modules)?;
|
||||
|
||||
let facade_interface = super::methods_generator::generate_facade_methods(
|
||||
facade.interface.function_signatures.iter(),
|
||||
&facade.interface.record_types,
|
||||
)?;
|
||||
|
||||
let facade_override =
|
||||
super::generate_module_definition(facade, linked_facade, service_import_generator)?;
|
||||
let facade_override_ident = new_ident("__facade_override")?;
|
||||
let facade_structs = generate_facade_structs(facade, &facade_override_ident)?;
|
||||
|
||||
let app_service_ctor =
|
||||
generate_app_service_ctor(&service.config_path, &service.config.resolved_modules_dir)?;
|
||||
let modules_type = generate_modules_type(&modules)?;
|
||||
|
||||
let service_definition = quote! {
|
||||
pub mod #service_mod {
|
||||
pub mod modules {
|
||||
#(#module_definitions)*
|
||||
}
|
||||
|
||||
pub mod #facade_override_ident {
|
||||
#facade_override
|
||||
}
|
||||
|
||||
#(#facade_structs)*
|
||||
|
||||
#modules_type
|
||||
|
||||
pub struct ServiceInterface {
|
||||
pub modules: __GeneratedModules,
|
||||
__facade: #facade_override_ident::ModuleInterface,
|
||||
marine: std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>, >
|
||||
}
|
||||
|
||||
impl ServiceInterface {
|
||||
pub fn new() -> Self {
|
||||
#app_service_ctor
|
||||
let modules = __GeneratedModules::new(marine.clone());
|
||||
let __facade = #facade_override_ident::ModuleInterface::new(marine.clone());
|
||||
Self {
|
||||
marine,
|
||||
modules,
|
||||
__facade
|
||||
}
|
||||
}
|
||||
|
||||
#(#facade_interface)*
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(service_definition)
|
||||
}
|
||||
|
||||
fn service_import_generator(info: &UseDescription<'_>) -> TResult<TokenStream> {
|
||||
let from_module_ident = new_ident(info.from)?;
|
||||
let record_name_ident = new_ident(info.name)?;
|
||||
Ok(quote! {pub use super::super::#from_module_ident::#record_name_ident;})
|
||||
}
|
||||
|
||||
fn generate_facade_structs(
|
||||
module: &Module<'_>,
|
||||
module_name: &syn::Ident,
|
||||
) -> TResult<Vec<TokenStream>> {
|
||||
module
|
||||
.interface
|
||||
.record_types
|
||||
.iter()
|
||||
.sorted_by_key(|(_, record)| &record.name)
|
||||
.map(|(_, record)| -> TResult<TokenStream> {
|
||||
let record_name = new_ident(&record.name)?;
|
||||
let result = quote! {pub use #module_name::#record_name;};
|
||||
Ok(result)
|
||||
})
|
||||
.collect::<TResult<Vec<TokenStream>>>()
|
||||
}
|
||||
|
||||
fn generate_modules_type(module_interfaces: &[Module<'_>]) -> TResult<TokenStream> {
|
||||
let fields = module_interfaces
|
||||
.iter()
|
||||
.map(|module| -> TResult<TokenStream> {
|
||||
let name = new_ident(module.name)?;
|
||||
Ok(quote! {pub #name: modules::#name::ModuleInterface})
|
||||
})
|
||||
.collect::<TResult<Vec<TokenStream>>>()?;
|
||||
|
||||
let ctors = module_interfaces
|
||||
.iter()
|
||||
.map(|module| -> TResult<TokenStream> {
|
||||
let name = new_ident(module.name)?;
|
||||
Ok(quote! {#name: modules::#name::ModuleInterface::new(marine.clone())})
|
||||
})
|
||||
.collect::<TResult<Vec<TokenStream>>>()?;
|
||||
|
||||
let ty = quote! {
|
||||
pub struct __GeneratedModules {
|
||||
#(#fields,)*
|
||||
}
|
||||
|
||||
impl __GeneratedModules {
|
||||
fn new(marine: std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>, >) -> Self {
|
||||
Self {
|
||||
#(#ctors,)*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(ty)
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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::{ServiceDescription};
|
||||
use crate::TResult;
|
||||
use crate::TestGeneratorError;
|
||||
use crate::marine_test::config_utils::{Module, ConfigWrapper, load_config};
|
||||
use crate::marine_test::{modules_linker, config_utils};
|
||||
use crate::marine_test::modules_linker::LinkedModules;
|
||||
use super::service_generation_utils::generate_service_definition;
|
||||
|
||||
use marine_it_parser::it_interface::IModuleInterface;
|
||||
use proc_macro2::TokenStream;
|
||||
use itertools::{Itertools, zip};
|
||||
|
||||
use std::path::Path;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub(crate) fn generate_service_definitions(
|
||||
services: HashMap<String, ServiceDescription>,
|
||||
file_path: &Path,
|
||||
) -> TResult<Vec<TokenStream>> {
|
||||
let services = services
|
||||
.into_iter()
|
||||
.sorted_by(|lhs, rhs| lhs.0.cmp(&rhs.0)) // deterministic output required for tests
|
||||
.map(|(name, service)| ProcessedService::new(service, name, file_path))
|
||||
.collect::<TResult<Vec<ProcessedService>>>()?;
|
||||
|
||||
let service_modules = services
|
||||
.iter()
|
||||
.map(|service| {
|
||||
let modules_dir_test_relative = file_path.join(&service.config.resolved_modules_dir);
|
||||
let modules =
|
||||
config_utils::collect_modules(&service.config.config, &modules_dir_test_relative)?;
|
||||
Ok(modules)
|
||||
})
|
||||
.collect::<TResult<Vec<Vec<Module<'_>>>>>()?;
|
||||
|
||||
let link_info = link_services(zip(&services, &service_modules))?;
|
||||
services
|
||||
.iter()
|
||||
.map(|service| -> TResult<TokenStream> {
|
||||
// entry with service.name was added in link_services(...), so unwrap is safe
|
||||
generate_service_definition(
|
||||
&service,
|
||||
file_path,
|
||||
link_info.get::<str>(&service.name).unwrap(),
|
||||
)
|
||||
})
|
||||
.collect::<TResult<Vec<TokenStream>>>()
|
||||
}
|
||||
|
||||
pub(super) fn get_facace<'modules, 'm>(
|
||||
modules: &'modules [Module<'m>],
|
||||
) -> TResult<&'modules Module<'m>> {
|
||||
match modules.last() {
|
||||
Some(module) => Ok(module),
|
||||
None => Err(TestGeneratorError::NoModulesInService),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct ProcessedService {
|
||||
pub(super) config: ConfigWrapper,
|
||||
pub(super) config_path: String,
|
||||
pub(super) name: String,
|
||||
}
|
||||
|
||||
impl ProcessedService {
|
||||
pub(crate) fn new(
|
||||
service: ServiceDescription,
|
||||
name: String,
|
||||
file_path: &Path,
|
||||
) -> TResult<Self> {
|
||||
let config_wrapper = load_config(&service.config_path, service.modules_dir, &file_path)?;
|
||||
|
||||
Ok(Self {
|
||||
config: config_wrapper,
|
||||
config_path: service.config_path,
|
||||
name,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn link_services<'modules>(
|
||||
services: impl ExactSizeIterator<
|
||||
Item = (&'modules ProcessedService, &'modules Vec<Module<'modules>>),
|
||||
>,
|
||||
) -> TResult<LinkedModules<'modules>> {
|
||||
let facade_modules = services
|
||||
.map(|(service, modules)| {
|
||||
let facade = get_facace(modules)?;
|
||||
Ok((service.name.as_str(), &facade.interface))
|
||||
})
|
||||
.collect::<TResult<Vec<(&str, &IModuleInterface)>>>()?;
|
||||
|
||||
modules_linker::link_modules(facade_modules.iter().copied())
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
modules_dir = "artifacts/"
|
||||
|
||||
[[module]]
|
||||
name = "greeting"
|
||||
mem_pages_count = 50
|
||||
logger_enabled = false
|
Binary file not shown.
@ -0,0 +1,504 @@
|
||||
#[test]
|
||||
fn test() {
|
||||
pub mod marine_test_env {
|
||||
pub mod empty_func {
|
||||
pub mod modules {
|
||||
pub mod greeting {
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct CallParameters {
|
||||
pub init_peer_id: String,
|
||||
pub service_id: String,
|
||||
pub service_creator_peer_id: String,
|
||||
pub host_id: String,
|
||||
pub particle_id: String,
|
||||
pub tetraplets: Vec<Vec<SecurityTetraplet>>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: Vec<u8>,
|
||||
pub stderr: Vec<u8>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryStringResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: String,
|
||||
pub stderr: String
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct SecurityTetraplet {
|
||||
pub peer_pk: String,
|
||||
pub service_id: String,
|
||||
pub function_name: String,
|
||||
pub json_path: String
|
||||
}
|
||||
pub struct ModuleInterface {
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>,
|
||||
}
|
||||
impl ModuleInterface {
|
||||
pub fn new(
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>
|
||||
) -> Self {
|
||||
Self { marine }
|
||||
}
|
||||
}
|
||||
impl ModuleInterface {}
|
||||
}
|
||||
}
|
||||
pub mod __facade_override {
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct CallParameters {
|
||||
pub init_peer_id: String,
|
||||
pub service_id: String,
|
||||
pub service_creator_peer_id: String,
|
||||
pub host_id: String,
|
||||
pub particle_id: String,
|
||||
pub tetraplets: Vec<Vec<SecurityTetraplet>>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: Vec<u8>,
|
||||
pub stderr: Vec<u8>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryStringResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: String,
|
||||
pub stderr: String
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct SecurityTetraplet {
|
||||
pub peer_pk: String,
|
||||
pub service_id: String,
|
||||
pub function_name: String,
|
||||
pub json_path: String
|
||||
}
|
||||
pub struct ModuleInterface {
|
||||
marine:
|
||||
std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>,
|
||||
}
|
||||
impl ModuleInterface {
|
||||
pub fn new(
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>
|
||||
) -> Self {
|
||||
Self { marine }
|
||||
}
|
||||
}
|
||||
impl ModuleInterface {}
|
||||
}
|
||||
pub use __facade_override::CallParameters;
|
||||
pub use __facade_override::MountedBinaryResult;
|
||||
pub use __facade_override::MountedBinaryStringResult;
|
||||
pub use __facade_override::SecurityTetraplet;
|
||||
pub struct __GeneratedModules {
|
||||
pub greeting: modules::greeting::ModuleInterface,
|
||||
}
|
||||
impl __GeneratedModules {
|
||||
fn new(
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>
|
||||
) -> Self {
|
||||
Self {
|
||||
greeting: modules::greeting::ModuleInterface::new(marine.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
pub struct ServiceInterface {
|
||||
pub modules: __GeneratedModules,
|
||||
__facade: __facade_override::ModuleInterface,
|
||||
marine: std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>, >
|
||||
}
|
||||
impl ServiceInterface {
|
||||
pub fn new() -> Self {
|
||||
let tmp_dir = std::env::temp_dir();
|
||||
let service_id = marine_rs_sdk_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 module_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
let mut file_path = std::path::Path::new(file!()).components();
|
||||
let mut truncated_file_path = Vec::new();
|
||||
loop {
|
||||
if module_path.ends_with(file_path.as_path()) {
|
||||
break;
|
||||
}
|
||||
let (file_path_, remainder) =
|
||||
match file_path.next_back().and_then(|p| match p {
|
||||
std::path::Component::Normal(_)
|
||||
| std::path::Component::CurDir
|
||||
| std::path::Component::ParentDir => Some((file_path, p)),
|
||||
_ => None,
|
||||
}) {
|
||||
Some(t) => t,
|
||||
None => break,
|
||||
};
|
||||
file_path = file_path_;
|
||||
truncated_file_path.push(remainder);
|
||||
}
|
||||
for path in truncated_file_path.iter().rev() {
|
||||
module_path.push(path);
|
||||
}
|
||||
let _ = module_path.pop();
|
||||
let config_path = module_path.join("empty_func/Config.toml");
|
||||
let modules_dir = module_path.join("empty_func/artifacts");
|
||||
let modules_dir = modules_dir
|
||||
.to_str()
|
||||
.expect("modules_dir contains invalid UTF8 string");
|
||||
let mut __m_generated_marine_config =
|
||||
marine_rs_sdk_test::internal::TomlAppServiceConfig::load(&config_path)
|
||||
.unwrap_or_else(|e|
|
||||
panic!(
|
||||
"app service config located at `{:?}` can't be loaded: {}",
|
||||
config_path, e
|
||||
)
|
||||
);
|
||||
__m_generated_marine_config.service_base_dir = Some(tmp_dir);
|
||||
__m_generated_marine_config.toml_faas_config.modules_dir =
|
||||
Some(modules_dir.to_string());
|
||||
let marine = marine_rs_sdk_test::internal::AppService::new_with_empty_facade(
|
||||
__m_generated_marine_config,
|
||||
service_id,
|
||||
std::collections::HashMap::new()
|
||||
)
|
||||
.unwrap_or_else(|e| panic!("app service can't be created: {}", e));
|
||||
let marine = std::rc::Rc::new(std::cell::RefCell::new(marine));
|
||||
let modules = __GeneratedModules::new(marine.clone());
|
||||
let __facade = __facade_override::ModuleInterface::new(marine.clone());
|
||||
Self {
|
||||
marine,
|
||||
modules,
|
||||
__facade
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pub mod mounted_binary {
|
||||
pub mod modules {
|
||||
pub mod greeting {
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct CallParameters {
|
||||
pub init_peer_id: String,
|
||||
pub service_id: String,
|
||||
pub service_creator_peer_id: String,
|
||||
pub host_id: String,
|
||||
pub particle_id: String,
|
||||
pub tetraplets: Vec<Vec<SecurityTetraplet>>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: Vec<u8>,
|
||||
pub stderr: Vec<u8>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryStringResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: String,
|
||||
pub stderr: String
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct SecurityTetraplet {
|
||||
pub peer_pk: String,
|
||||
pub service_id: String,
|
||||
pub function_name: String,
|
||||
pub json_path: String
|
||||
}
|
||||
pub struct ModuleInterface {
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>,
|
||||
}
|
||||
impl ModuleInterface {
|
||||
pub fn new(
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>
|
||||
) -> Self {
|
||||
Self { marine }
|
||||
}
|
||||
}
|
||||
impl ModuleInterface {
|
||||
pub fn download(&mut self, url: String) -> String {
|
||||
use std::ops::DerefMut;
|
||||
let arguments = marine_rs_sdk_test::internal::serde_json::json!([url]);
|
||||
let result = self
|
||||
.marine
|
||||
.as_ref()
|
||||
.borrow_mut()
|
||||
.call_module("greeting", "download", arguments, <_>::default())
|
||||
.expect("call to Marine failed");
|
||||
let result: String =
|
||||
marine_rs_sdk_test::internal::serde_json::from_value(result)
|
||||
.expect("the default deserializer shouldn't fail");
|
||||
result
|
||||
}
|
||||
pub fn download_cp(
|
||||
&mut self,
|
||||
url: String,
|
||||
cp: marine_rs_sdk_test::CallParameters
|
||||
) -> String {
|
||||
use std::ops::DerefMut;
|
||||
let arguments = marine_rs_sdk_test::internal::serde_json::json!([url]);
|
||||
let result = self
|
||||
.marine
|
||||
.as_ref()
|
||||
.borrow_mut()
|
||||
.call_module("greeting", "download", arguments, cp)
|
||||
.expect("call to Marine failed");
|
||||
let result: String =
|
||||
marine_rs_sdk_test::internal::serde_json::from_value(result)
|
||||
.expect("the default deserializer shouldn't fail");
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pub mod __facade_override {
|
||||
pub use super::super::empty_func::CallParameters;
|
||||
pub use super::super::empty_func::MountedBinaryResult;
|
||||
pub use super::super::empty_func::MountedBinaryStringResult;
|
||||
pub use super::super::empty_func::SecurityTetraplet;
|
||||
pub struct ModuleInterface {
|
||||
marine:
|
||||
std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>,
|
||||
}
|
||||
impl ModuleInterface {
|
||||
pub fn new(
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>
|
||||
) -> Self {
|
||||
Self { marine }
|
||||
}
|
||||
}
|
||||
impl ModuleInterface {
|
||||
pub fn download(&mut self, url: String) -> String {
|
||||
use std::ops::DerefMut;
|
||||
let arguments = marine_rs_sdk_test::internal::serde_json::json!([url]);
|
||||
let result = self
|
||||
.marine
|
||||
.as_ref()
|
||||
.borrow_mut()
|
||||
.call_module("greeting", "download", arguments, <_>::default())
|
||||
.expect("call to Marine failed");
|
||||
let result: String =
|
||||
marine_rs_sdk_test::internal::serde_json::from_value(result)
|
||||
.expect("the default deserializer shouldn't fail");
|
||||
result
|
||||
}
|
||||
pub fn download_cp(
|
||||
&mut self,
|
||||
url: String,
|
||||
cp: marine_rs_sdk_test::CallParameters
|
||||
) -> String {
|
||||
use std::ops::DerefMut;
|
||||
let arguments = marine_rs_sdk_test::internal::serde_json::json!([url]);
|
||||
let result = self
|
||||
.marine
|
||||
.as_ref()
|
||||
.borrow_mut()
|
||||
.call_module("greeting", "download", arguments, cp)
|
||||
.expect("call to Marine failed");
|
||||
let result: String =
|
||||
marine_rs_sdk_test::internal::serde_json::from_value(result)
|
||||
.expect("the default deserializer shouldn't fail");
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
||||
pub use __facade_override::CallParameters;
|
||||
pub use __facade_override::MountedBinaryResult;
|
||||
pub use __facade_override::MountedBinaryStringResult;
|
||||
pub use __facade_override::SecurityTetraplet;
|
||||
pub struct __GeneratedModules {
|
||||
pub greeting: modules::greeting::ModuleInterface,
|
||||
}
|
||||
impl __GeneratedModules {
|
||||
fn new(
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>
|
||||
) -> Self {
|
||||
Self {
|
||||
greeting: modules::greeting::ModuleInterface::new(marine.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
pub struct ServiceInterface {
|
||||
pub modules: __GeneratedModules,
|
||||
__facade: __facade_override::ModuleInterface,
|
||||
marine: std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>, >
|
||||
}
|
||||
impl ServiceInterface {
|
||||
pub fn new() -> Self {
|
||||
let tmp_dir = std::env::temp_dir();
|
||||
let service_id = marine_rs_sdk_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 module_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
let mut file_path = std::path::Path::new(file!()).components();
|
||||
let mut truncated_file_path = Vec::new();
|
||||
loop {
|
||||
if module_path.ends_with(file_path.as_path()) {
|
||||
break;
|
||||
}
|
||||
let (file_path_, remainder) =
|
||||
match file_path.next_back().and_then(|p| match p {
|
||||
std::path::Component::Normal(_)
|
||||
| std::path::Component::CurDir
|
||||
| std::path::Component::ParentDir => Some((file_path, p)),
|
||||
_ => None,
|
||||
}) {
|
||||
Some(t) => t,
|
||||
None => break,
|
||||
};
|
||||
file_path = file_path_;
|
||||
truncated_file_path.push(remainder);
|
||||
}
|
||||
for path in truncated_file_path.iter().rev() {
|
||||
module_path.push(path);
|
||||
}
|
||||
let _ = module_path.pop();
|
||||
let config_path = module_path.join("mounted_binary/Config.toml");
|
||||
let modules_dir = module_path.join("mounted_binary/artifacts");
|
||||
let modules_dir = modules_dir
|
||||
.to_str()
|
||||
.expect("modules_dir contains invalid UTF8 string");
|
||||
let mut __m_generated_marine_config =
|
||||
marine_rs_sdk_test::internal::TomlAppServiceConfig::load(&config_path)
|
||||
.unwrap_or_else(|e|
|
||||
panic!(
|
||||
"app service config located at `{:?}` can't be loaded: {}",
|
||||
config_path, e
|
||||
)
|
||||
);
|
||||
__m_generated_marine_config.service_base_dir = Some(tmp_dir);
|
||||
__m_generated_marine_config.toml_faas_config.modules_dir =
|
||||
Some(modules_dir.to_string());
|
||||
let marine = marine_rs_sdk_test::internal::AppService::new_with_empty_facade(
|
||||
__m_generated_marine_config,
|
||||
service_id,
|
||||
std::collections::HashMap::new()
|
||||
)
|
||||
.unwrap_or_else(|e| panic!("app service can't be created: {}", e));
|
||||
let marine = std::rc::Rc::new(std::cell::RefCell::new(marine));
|
||||
let modules = __GeneratedModules::new(marine.clone());
|
||||
let __facade = __facade_override::ModuleInterface::new(marine.clone());
|
||||
Self {
|
||||
marine,
|
||||
modules,
|
||||
__facade
|
||||
}
|
||||
}
|
||||
pub fn download(&mut self, url: String) -> String {
|
||||
self.__facade.download(url,)
|
||||
}
|
||||
pub fn download_cp(
|
||||
&mut self,
|
||||
url: String,
|
||||
cp: marine_rs_sdk_test::CallParameters
|
||||
) -> String {
|
||||
self.__facade.download_cp(url, cp,)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fn test_func() {
|
||||
{
|
||||
let mut greeting = marine_test_env::greeting::ServiceInterface::new();
|
||||
let _ = greeting.download("duckduckgo.com");
|
||||
}
|
||||
}
|
||||
test_func()
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
fn test() {
|
||||
let mut greeting = marine_test_env::greeting::ServiceInterface::new();
|
||||
let _ = greeting.download("duckduckgo.com");
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
modules_dir = "artifacts/"
|
||||
|
||||
[[module]]
|
||||
name = "greeting"
|
||||
mem_pages_count = 50
|
||||
logger_enabled = false
|
||||
[module.mounted_binaries]
|
||||
echo = "/usr/bin/curl"
|
Binary file not shown.
@ -0,0 +1,6 @@
|
||||
modules_dir = "artifacts/"
|
||||
|
||||
[[module]]
|
||||
name = "greeting"
|
||||
mem_pages_count = 50
|
||||
logger_enabled = false
|
Binary file not shown.
@ -0,0 +1,242 @@
|
||||
#[test]
|
||||
fn empty_test() {
|
||||
pub mod marine_test_env {
|
||||
pub mod empty_func {
|
||||
pub mod modules {
|
||||
pub mod greeting {
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct CallParameters {
|
||||
pub init_peer_id: String,
|
||||
pub service_id: String,
|
||||
pub service_creator_peer_id: String,
|
||||
pub host_id: String,
|
||||
pub particle_id: String,
|
||||
pub tetraplets: Vec<Vec<SecurityTetraplet>>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: Vec<u8>,
|
||||
pub stderr: Vec<u8>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryStringResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: String,
|
||||
pub stderr: String
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct SecurityTetraplet {
|
||||
pub peer_pk: String,
|
||||
pub service_id: String,
|
||||
pub function_name: String,
|
||||
pub json_path: String
|
||||
}
|
||||
pub struct ModuleInterface {
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>,
|
||||
}
|
||||
impl ModuleInterface {
|
||||
pub fn new(
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>
|
||||
) -> Self {
|
||||
Self { marine }
|
||||
}
|
||||
}
|
||||
impl ModuleInterface {}
|
||||
}
|
||||
}
|
||||
pub mod __facade_override {
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct CallParameters {
|
||||
pub init_peer_id: String,
|
||||
pub service_id: String,
|
||||
pub service_creator_peer_id: String,
|
||||
pub host_id: String,
|
||||
pub particle_id: String,
|
||||
pub tetraplets: Vec<Vec<SecurityTetraplet>>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: Vec<u8>,
|
||||
pub stderr: Vec<u8>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryStringResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: String,
|
||||
pub stderr: String
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct SecurityTetraplet {
|
||||
pub peer_pk: String,
|
||||
pub service_id: String,
|
||||
pub function_name: String,
|
||||
pub json_path: String
|
||||
}
|
||||
pub struct ModuleInterface {
|
||||
marine:
|
||||
std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>,
|
||||
}
|
||||
impl ModuleInterface {
|
||||
pub fn new(
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>
|
||||
) -> Self {
|
||||
Self { marine }
|
||||
}
|
||||
}
|
||||
impl ModuleInterface {}
|
||||
}
|
||||
pub use __facade_override::CallParameters;
|
||||
pub use __facade_override::MountedBinaryResult;
|
||||
pub use __facade_override::MountedBinaryStringResult;
|
||||
pub use __facade_override::SecurityTetraplet;
|
||||
pub struct __GeneratedModules {
|
||||
pub greeting: modules::greeting::ModuleInterface,
|
||||
}
|
||||
impl __GeneratedModules {
|
||||
fn new(
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>
|
||||
) -> Self {
|
||||
Self {
|
||||
greeting: modules::greeting::ModuleInterface::new(marine.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
pub struct ServiceInterface {
|
||||
pub modules: __GeneratedModules,
|
||||
__facade: __facade_override::ModuleInterface,
|
||||
marine: std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>, >
|
||||
}
|
||||
impl ServiceInterface {
|
||||
pub fn new() -> Self {
|
||||
let tmp_dir = std::env::temp_dir();
|
||||
let service_id = marine_rs_sdk_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 module_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
let mut file_path = std::path::Path::new(file!()).components();
|
||||
let mut truncated_file_path = Vec::new();
|
||||
loop {
|
||||
if module_path.ends_with(file_path.as_path()) {
|
||||
break;
|
||||
}
|
||||
let (file_path_, remainder) =
|
||||
match file_path.next_back().and_then(|p| match p {
|
||||
std::path::Component::Normal(_)
|
||||
| std::path::Component::CurDir
|
||||
| std::path::Component::ParentDir => Some((file_path, p)),
|
||||
_ => None,
|
||||
}) {
|
||||
Some(t) => t,
|
||||
None => break,
|
||||
};
|
||||
file_path = file_path_;
|
||||
truncated_file_path.push(remainder);
|
||||
}
|
||||
for path in truncated_file_path.iter().rev() {
|
||||
module_path.push(path);
|
||||
}
|
||||
let _ = module_path.pop();
|
||||
let config_path = module_path.join("empty_func/Config.toml");
|
||||
let modules_dir = module_path.join("empty_func/artifacts");
|
||||
let modules_dir = modules_dir
|
||||
.to_str()
|
||||
.expect("modules_dir contains invalid UTF8 string");
|
||||
let mut __m_generated_marine_config =
|
||||
marine_rs_sdk_test::internal::TomlAppServiceConfig::load(&config_path)
|
||||
.unwrap_or_else(|e|
|
||||
panic!(
|
||||
"app service config located at `{:?}` can't be loaded: {}",
|
||||
config_path, e
|
||||
)
|
||||
);
|
||||
__m_generated_marine_config.service_base_dir = Some(tmp_dir);
|
||||
__m_generated_marine_config.toml_faas_config.modules_dir =
|
||||
Some(modules_dir.to_string());
|
||||
let marine = marine_rs_sdk_test::internal::AppService::new_with_empty_facade(
|
||||
__m_generated_marine_config,
|
||||
service_id,
|
||||
std::collections::HashMap::new()
|
||||
)
|
||||
.unwrap_or_else(|e| panic!("app service can't be created: {}", e));
|
||||
let marine = std::rc::Rc::new(std::cell::RefCell::new(marine));
|
||||
let modules = __GeneratedModules::new(marine.clone());
|
||||
let __facade = __facade_override::ModuleInterface::new(marine.clone());
|
||||
Self {
|
||||
marine,
|
||||
modules,
|
||||
__facade
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fn test_func() {
|
||||
{}
|
||||
}
|
||||
test_func()
|
||||
}
|
@ -0,0 +1 @@
|
||||
fn empty_test() {}
|
@ -17,6 +17,8 @@
|
||||
mod utils;
|
||||
|
||||
use utils::test_marine_test_token_streams;
|
||||
use utils::TestServiceDescription;
|
||||
use utils::test_marine_test_token_streams_multiservice;
|
||||
|
||||
#[test]
|
||||
fn test_empty_func() {
|
||||
@ -47,3 +49,38 @@ fn test_multiple_modules() {
|
||||
"artifacts"
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiservice_single() {
|
||||
let descriptions = vec![TestServiceDescription {
|
||||
modules_dir: "empty_func/artifacts",
|
||||
config_path: "empty_func/Config.toml",
|
||||
name: "empty_func",
|
||||
}];
|
||||
assert!(test_marine_test_token_streams_multiservice(
|
||||
"tests/generation_tests/multi-service-single/marine_test.rs",
|
||||
"tests/generation_tests/multi-service-single/expanded.rs",
|
||||
descriptions
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiservice_multiple() {
|
||||
let descriptions = vec![
|
||||
TestServiceDescription {
|
||||
modules_dir: "empty_func/artifacts",
|
||||
config_path: "empty_func/Config.toml",
|
||||
name: "empty_func",
|
||||
},
|
||||
TestServiceDescription {
|
||||
modules_dir: "mounted_binary/artifacts",
|
||||
config_path: "mounted_binary/Config.toml",
|
||||
name: "mounted_binary",
|
||||
},
|
||||
];
|
||||
assert!(test_marine_test_token_streams_multiservice(
|
||||
"tests/generation_tests/multi-service-multiple/marine_test.rs",
|
||||
"tests/generation_tests/multi-service-multiple/expanded.rs",
|
||||
descriptions
|
||||
));
|
||||
}
|
||||
|
@ -33,7 +33,56 @@ where
|
||||
let marine_item = stream_from_file(&marine_path);
|
||||
let test_token_stream = quote::quote! { #marine_item };
|
||||
let buf = marine_path.as_ref().to_path_buf();
|
||||
let attrs = quote::quote! {config_path = #config_path, modules_dir = #modules_dir};
|
||||
let attrs = quote::quote! {
|
||||
config_path = #config_path,
|
||||
modules_dir = #modules_dir,
|
||||
};
|
||||
let marine_token_streams = marine_test_impl(
|
||||
attrs,
|
||||
test_token_stream,
|
||||
buf.parent().unwrap().to_path_buf(),
|
||||
)
|
||||
.unwrap_or_else(|e| panic!("failed to apply the marine macro due {}", e));
|
||||
|
||||
let expanded_item = items_from_file(&expanded_path);
|
||||
let marine_item = to_syn_item(marine_token_streams.clone());
|
||||
|
||||
marine_item == expanded_item
|
||||
}
|
||||
|
||||
pub struct TestServiceDescription {
|
||||
pub config_path: &'static str,
|
||||
pub modules_dir: &'static str,
|
||||
pub name: &'static str,
|
||||
}
|
||||
|
||||
pub fn test_marine_test_token_streams_multiservice<FP, EP>(
|
||||
marine_path: FP,
|
||||
expanded_path: EP,
|
||||
services: Vec<TestServiceDescription>,
|
||||
) -> bool
|
||||
where
|
||||
FP: AsRef<Path>,
|
||||
EP: AsRef<Path>,
|
||||
{
|
||||
let marine_item = stream_from_file(&marine_path);
|
||||
let test_token_stream = quote::quote! { #marine_item };
|
||||
let buf = marine_path.as_ref().to_path_buf();
|
||||
let service_declarations = services
|
||||
.iter()
|
||||
.map(|desc| {
|
||||
let config_path = desc.config_path;
|
||||
let modules_dir = desc.modules_dir;
|
||||
let name = syn::parse_str::<syn::Ident>(desc.name)?;
|
||||
Ok(quote::quote! {#name(config_path = #config_path, modules_dir = #modules_dir)})
|
||||
})
|
||||
.collect::<Result<Vec<_>, syn::Error>>()
|
||||
.unwrap_or_else(|e| panic!("failed to parse test arguments due to {}", e));
|
||||
|
||||
let attrs = quote::quote! {
|
||||
#(#service_declarations,)*
|
||||
};
|
||||
|
||||
let marine_token_streams = marine_test_impl(
|
||||
attrs,
|
||||
test_token_stream,
|
||||
|
Loading…
Reference in New Issue
Block a user