diff --git a/Cargo.lock b/Cargo.lock index 68f7ec9..e995a55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -661,6 +661,13 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" +[[package]] +name = "marine-build-rs-generator" +version = "0.4.0" +dependencies = [ + "marine-test-macro-impl", +] + [[package]] name = "marine-it-generator" version = "0.5.3" @@ -801,9 +808,10 @@ dependencies = [ [[package]] name = "marine-rs-sdk-test" -version = "0.3.0" +version = "0.4.0" dependencies = [ "fluence-app-service", + "marine-build-rs-generator", "marine-test-macro", "serde", "serde_json", @@ -843,7 +851,7 @@ dependencies = [ [[package]] name = "marine-test-macro" -version = "0.3.0" +version = "0.4.0" dependencies = [ "marine-test-macro-impl", "proc-macro-error", @@ -854,7 +862,7 @@ dependencies = [ [[package]] name = "marine-test-macro-impl" -version = "0.3.0" +version = "0.4.0" dependencies = [ "darling", "fluence-app-service", diff --git a/Cargo.toml b/Cargo.toml index 4f3d6bb..e20d203 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "marine-rs-sdk-test" -version = "0.3.0" # remember to update html_root_url +version = "0.4.0" # remember to update html_root_url description = "Backend SDK that allows testing modules for the Marine runtime" documentation = "https://docs.rs/marine-rs-sdk-test" repository = "https://github.com/fluencelabs/marine-rs-sdk-test" @@ -21,7 +21,8 @@ doctest = false trybuild = "1.0" [dependencies] -marine-test-macro = { path = "crates/marine-test-macro", version = "=0.3.0" } +marine-test-macro = { path = "crates/marine-test-macro", version = "=0.4.0" } +marine-build-rs-generator = { path = "crates/marine-build-rs-generator", version = "=0.4.0" } fluence-app-service = { version = "0.9.0", features = ["raw-module-api"] } serde = { version = "1.0.118", features = ["derive"] } @@ -32,4 +33,5 @@ uuid = { version = "0.8.2", features = ["v4"] } members = [ "crates/marine-test-macro", "crates/marine-test-macro-impl", - ] \ No newline at end of file + "crates/marine-build-rs-generator", + ] diff --git a/crates/marine-build-rs-generator/Cargo.toml b/crates/marine-build-rs-generator/Cargo.toml new file mode 100644 index 0000000..ef7ce21 --- /dev/null +++ b/crates/marine-build-rs-generator/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "marine-build-rs-generator" +version = "0.4.0" # remember to update html_root_url +edition = "2018" +description = "Tools for generating marine_test_env in build scripts" +documentation = "https://docs.rs/marine-build-rs-generator" +repository = "https://github.com/fluencelabs/marine-rs-sdk-test/tree/master/crates/marine-build-rs-generator" +authors = ["Fluence Labs"] +keywords = ["fluence", "marine", "sdk", "webassembly"] +categories = ["api-bindings", "wasm", "development-tools::testing"] +license = "Apache-2.0" + +[package.metadata.docs.rs] +all-features = true + +[lib] +doctest = false + +[dependencies] +marine-test-macro-impl = { path = "../marine-test-macro-impl", version = "=0.4.0" } + diff --git a/crates/marine-build-rs-generator/src/lib.rs b/crates/marine-build-rs-generator/src/lib.rs new file mode 100644 index 0000000..be1dc18 --- /dev/null +++ b/crates/marine-build-rs-generator/src/lib.rs @@ -0,0 +1,68 @@ +/* + * 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. + */ + +#![doc(html_root_url = "https://docs.rs/marine-build-rs-generator/0.4.0")] +#![deny( + dead_code, + nonstandard_style, + unused_imports, + unused_mut, + unused_variables, + unused_unsafe, + unreachable_patterns +)] +#![warn(rust_2018_idioms)] +#![recursion_limit = "1024"] + +use marine_test_macro_impl::generate_marine_test_env_impl; +pub use marine_test_macro_impl::ServiceDescription; + +use std::path::{PathBuf, Path}; +use std::{fs, env}; + +pub fn generate_marine_test_env( + services: impl IntoIterator, + filename: &str, + build_rs_file_path: &str, +) { + // build_rs_file_path expected to be obtained from file!() macro, which returns path with filename, + // but underlying code expects path without filename, so we are removing last part + let mut build_rs_file_path = PathBuf::from(build_rs_file_path); + let _ = build_rs_file_path.pop(); + + match generate_marine_test_env_impl(services, &build_rs_file_path) { + Ok(stream) => { + let out_dir = env::var_os("OUT_DIR") + .expect("cannot write marine_test_env: OUT_DIR env var must be set"); + let dest_path = Path::new(&out_dir).join(filename); + + match fs::write(dest_path, stream.to_string()) { + Ok(result) => result, + Err(e) => { + std::panic::panic_any(format!("cannot write marine_test_env on disk: {}", e)) + } + } + } + Err(error) => std::panic::panic_any(format!("marine_test_env generation error: {}", error)), + } +} + +#[macro_export] +macro_rules! include_test_env { + ($filename:expr) => { + include!(concat!(env!("OUT_DIR"), $filename)); + }; +} diff --git a/crates/marine-test-macro-impl/Cargo.toml b/crates/marine-test-macro-impl/Cargo.toml index 3d96b6d..154c97c 100644 --- a/crates/marine-test-macro-impl/Cargo.toml +++ b/crates/marine-test-macro-impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "marine-test-macro-impl" -version = "0.3.0" # remember to update html_root_url +version = "0.4.0" # remember to update html_root_url edition = "2018" description = "Implementation of the `#[marine_test]` macro" documentation = "https://docs.rs/fluence/marine-test-macro-impl" diff --git a/crates/marine-test-macro-impl/src/attributes.rs b/crates/marine-test-macro-impl/src/attributes.rs index 17a83f9..3ef993d 100644 --- a/crates/marine-test-macro-impl/src/attributes.rs +++ b/crates/marine-test-macro-impl/src/attributes.rs @@ -25,13 +25,13 @@ pub(crate) enum MTestAttributes { } #[derive(Debug, Default, Clone, FromMeta)] -pub(crate) struct ServiceDescription { +pub struct ServiceDescription { /// Path to a config file of a tested service. - pub(crate) config_path: String, + pub config_path: String, /// Path to compiled modules of a service. #[darling(default)] - pub(crate) modules_dir: Option, + pub modules_dir: Option, } impl FromMeta for MTestAttributes { diff --git a/crates/marine-test-macro-impl/src/errors.rs b/crates/marine-test-macro-impl/src/errors.rs index 48402db..9c9361f 100644 --- a/crates/marine-test-macro-impl/src/errors.rs +++ b/crates/marine-test-macro-impl/src/errors.rs @@ -59,6 +59,12 @@ pub enum TestGeneratorError { #[error("No modules loaded for a service")] NoModulesInService, + + #[error("Multi-service variant must be applied to a mod or fn")] + ExpectedModOrFn, + + #[error("Single-service variant must be applied to a fn")] + ExpectedFn, } #[derive(Debug, ThisError)] diff --git a/crates/marine-test-macro-impl/src/lib.rs b/crates/marine-test-macro-impl/src/lib.rs index ae3d902..5992850 100644 --- a/crates/marine-test-macro-impl/src/lib.rs +++ b/crates/marine-test-macro-impl/src/lib.rs @@ -31,6 +31,8 @@ mod errors; mod marine_test; pub use marine_test::marine_test_impl; +pub use marine_test::generate_marine_test_env_impl; pub use errors::TestGeneratorError; +pub use attributes::ServiceDescription; pub(crate) type TResult = std::result::Result; diff --git a/crates/marine-test-macro-impl/src/marine_test/config_utils.rs b/crates/marine-test-macro-impl/src/marine_test/config_utils.rs index 7300ba7..6061335 100644 --- a/crates/marine-test-macro-impl/src/marine_test/config_utils.rs +++ b/crates/marine-test-macro-impl/src/marine_test/config_utils.rs @@ -63,7 +63,7 @@ pub(super) fn collect_modules<'config>( config: &'config TomlAppServiceConfig, modules_dir: &Path, ) -> TResult>> { - let module_paths = collect_module_paths(config, &modules_dir); + let module_paths = collect_module_paths(config, modules_dir); module_paths .into_iter() diff --git a/crates/marine-test-macro-impl/src/marine_test/glue_code_generator.rs b/crates/marine-test-macro-impl/src/marine_test/glue_code_generator.rs index efc6ca7..72c0ce8 100644 --- a/crates/marine-test-macro-impl/src/marine_test/glue_code_generator.rs +++ b/crates/marine-test-macro-impl/src/marine_test/glue_code_generator.rs @@ -20,13 +20,12 @@ use crate::marine_test::{config_utils, token_stream_generator}; use crate::TestGeneratorError; use crate::TResult; -use std::path::PathBuf; +use std::path::{PathBuf, Path}; use proc_macro2::TokenStream; use quote::quote; use quote::ToTokens; use syn::FnArg; -use std::collections::HashMap; /// Generates glue code for tests. /// F.e. for this test for the greeting service @@ -113,25 +112,30 @@ use std::collections::HashMap; /// [(2), (3)] - module_ctors* /// [(3), (4)] - original_block pub(super) fn generate_test_glue_code( - func_item: syn::ItemFn, + item: syn::Item, attrs: MTestAttributes, test_file_path: PathBuf, ) -> TResult { match attrs { MTestAttributes::MultipleServices(services) => { - generate_test_glue_code_multiple_services(func_item, services, test_file_path) + generate_test_glue_code_multiple_services(item, services, test_file_path) } MTestAttributes::SingleService(service) => { - generate_test_glue_code_single_service(func_item, service, test_file_path) + generate_test_glue_code_single_service(item, service, test_file_path) } } } fn generate_test_glue_code_single_service( - func_item: syn::ItemFn, + item: syn::Item, service: ServiceDescription, test_file_path: PathBuf, ) -> TResult { + let func_item = match item { + syn::Item::Fn(func_item) => func_item, + _ => return Err(TestGeneratorError::ExpectedFn), + }; + 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); @@ -157,6 +161,7 @@ fn generate_test_glue_code_single_service( let app_service_ctor = token_stream_generator::generate_app_service_ctor( &service.config_path, &config_wrapper.resolved_modules_dir, + &test_file_path, )?; let glue_code = quote! { #[test] @@ -185,23 +190,81 @@ fn generate_test_glue_code_single_service( } fn generate_test_glue_code_multiple_services( - func_item: syn::ItemFn, - services: HashMap, + item: syn::Item, + services: impl IntoIterator, test_file_path: PathBuf, ) -> TResult { - let service_definitions = - token_stream_generator::generate_service_definitions(services, &test_file_path)?; + let service_definitions = token_stream_generator::generate_service_definitions( + services, + &test_file_path, + &test_file_path, + )?; + let marine_test_env = quote! { + pub mod marine_test_env { + #(#service_definitions)* + } + }; + + let glue_code = match item { + syn::Item::Fn(func_item) => wrap_fn_multiservice(func_item, marine_test_env), + syn::Item::Mod(mod_item) => wrap_mod_multiservice(mod_item, marine_test_env), + _ => return Err(TestGeneratorError::ExpectedModOrFn), + }; + + Ok(glue_code) +} + +pub(super) fn generate_marine_test_env_for_build_script( + services: impl IntoIterator, + build_rs_file_path: &Path, +) -> TResult { + let current_file_path = Path::new("."); + let service_definitions = token_stream_generator::generate_service_definitions( + services, + current_file_path, + build_rs_file_path, + )?; + + let marine_test_env = quote! { + #[allow(dead_code)] + pub mod marine_test_env { + #(#service_definitions)* + } + }; + + Ok(marine_test_env) +} + +fn wrap_mod_multiservice(mod_item: syn::ItemMod, marine_test_env: TokenStream) -> TokenStream { + let mod_content = mod_item + .content + .map_or(TokenStream::default(), |(_, items)| { + quote! {#(#items)*} + }); + + let mod_ident = mod_item.ident; + let mod_vis = mod_item.vis; + let mod_attrib = mod_item.attrs; + quote! { + #(#mod_attrib)* + #mod_vis mod #mod_ident { + #marine_test_env + + #mod_content + } + } +} + +fn wrap_fn_multiservice(func_item: syn::ItemFn, marine_test_env: TokenStream) -> TokenStream { let original_block = func_item.block; let signature = func_item.sig; let name = &signature.ident; - let glue_code = quote! { + quote! { #[test] fn #name() { // definitions for services specified in attributes - pub mod marine_test_env { - #(#service_definitions)* - } + #marine_test_env fn test_func() { #original_block @@ -209,9 +272,7 @@ fn generate_test_glue_code_multiple_services( test_func() } - }; - - Ok(glue_code) + } } fn generate_module_ctors<'inputs>( diff --git a/crates/marine-test-macro-impl/src/marine_test/marine_test_impl.rs b/crates/marine-test-macro-impl/src/marine_test/marine_test_impl.rs index 832fc5a..c81aff9 100644 --- a/crates/marine-test-macro-impl/src/marine_test/marine_test_impl.rs +++ b/crates/marine-test-macro-impl/src/marine_test/marine_test_impl.rs @@ -14,14 +14,15 @@ * limitations under the License. */ -use crate::attributes::MTestAttributes; +use crate::attributes::{MTestAttributes, ServiceDescription}; use crate::TResult; use crate::marine_test::glue_code_generator::generate_test_glue_code; +use crate::marine_test::glue_code_generator::generate_marine_test_env_for_build_script; use proc_macro2::TokenStream; use darling::FromMeta; use syn::parse::Parser; -use std::path::PathBuf; +use std::path::{PathBuf, Path}; pub fn marine_test_impl( attrs: TokenStream, @@ -34,7 +35,14 @@ pub fn marine_test_impl( let attrs: Vec = attrs.into_iter().collect(); let attrs = MTestAttributes::from_list(&attrs)?; - let func_item = syn::parse2::(input)?; + let item = syn::parse2::(input)?; - generate_test_glue_code(func_item, attrs, file_path) + generate_test_glue_code(item, attrs, file_path) +} + +pub fn generate_marine_test_env_impl( + services: impl IntoIterator, + build_rs_file_path: &Path, +) -> TResult { + generate_marine_test_env_for_build_script(services, build_rs_file_path) } diff --git a/crates/marine-test-macro-impl/src/marine_test/mod.rs b/crates/marine-test-macro-impl/src/marine_test/mod.rs index 7ca8eb2..68e3cec 100644 --- a/crates/marine-test-macro-impl/src/marine_test/mod.rs +++ b/crates/marine-test-macro-impl/src/marine_test/mod.rs @@ -22,3 +22,4 @@ mod utils; mod modules_linker; pub use marine_test_impl::marine_test_impl; +pub use marine_test_impl::generate_marine_test_env_impl; diff --git a/crates/marine-test-macro-impl/src/marine_test/token_stream_generator.rs b/crates/marine-test-macro-impl/src/marine_test/token_stream_generator.rs index 5396301..245b6b7 100644 --- a/crates/marine-test-macro-impl/src/marine_test/token_stream_generator.rs +++ b/crates/marine-test-macro-impl/src/marine_test/token_stream_generator.rs @@ -74,7 +74,7 @@ pub(super) fn generate_module_definitions<'i>( linked_modules.get(&value.name).unwrap(), module_import_generator, )?; - let module_ident = new_ident(&value.name)?; + let module_ident = new_ident(value.name)?; Ok(quote! { pub mod #module_ident { #content diff --git a/crates/marine-test-macro-impl/src/marine_test/token_stream_generator/methods_generator.rs b/crates/marine-test-macro-impl/src/marine_test/token_stream_generator/methods_generator.rs index c458958..3f085d5 100644 --- a/crates/marine-test-macro-impl/src/marine_test/token_stream_generator/methods_generator.rs +++ b/crates/marine-test-macro-impl/src/marine_test/token_stream_generator/methods_generator.rs @@ -35,9 +35,8 @@ pub(super) fn generate_module_methods<'m, 'r>( .try_fold::<_, _, TResult<_>>( Vec::with_capacity(methods_count), |mut methods, signature| { - let default_cp = generate_module_method(module_name, &signature, Default, records)?; - let user_cp = - generate_module_method(module_name, &signature, UserDefined, records)?; + let default_cp = generate_module_method(module_name, signature, Default, records)?; + let user_cp = generate_module_method(module_name, signature, UserDefined, records)?; methods.push(default_cp); methods.push(user_cp); @@ -59,8 +58,8 @@ pub fn generate_facade_methods<'m, 'r>( .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)?; + 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); diff --git a/crates/marine-test-macro-impl/src/marine_test/token_stream_generator/methods_generator_utils.rs b/crates/marine-test-macro-impl/src/marine_test/token_stream_generator/methods_generator_utils.rs index 91def5c..03aebd4 100644 --- a/crates/marine-test-macro-impl/src/marine_test/token_stream_generator/methods_generator_utils.rs +++ b/crates/marine-test-macro-impl/src/marine_test/token_stream_generator/methods_generator_utils.rs @@ -40,7 +40,7 @@ pub(super) fn generate_module_method( ) -> TResult { let arguments = generate_arguments(signature.arguments.iter(), records)?; let output_type = generate_output_type(&signature.outputs, records)?; - let mcall = generate_marine_call(module_name, cp_setting, &signature, records)?; + let mcall = generate_marine_call(module_name, cp_setting, signature, records)?; let (cp, func_name) = generate_call_parameters(&cp_setting, signature)?; @@ -60,7 +60,7 @@ pub(super) fn generate_module_method_forward( ) -> TResult { 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 mcall = generate_forward_call(cp_setting, signature)?; let (cp, func_name) = generate_call_parameters(&cp_setting, signature)?; @@ -89,8 +89,6 @@ fn generate_marine_call( let ret = generate_ret(&output_type); let function_call = quote! { - use std::ops::DerefMut; - #convert_arguments #set_result #function_call @@ -202,7 +200,7 @@ fn generate_output_type(output_types: &[IType], records: &IRecordTypes) -> TResu match output_type { None => Ok(TokenStream::new()), Some(ty) => { - let output_type = itype_to_tokens(&ty, records)?; + let output_type = itype_to_tokens(ty, records)?; let output_type = quote! { -> #output_type }; Ok(output_type) diff --git a/crates/marine-test-macro-impl/src/marine_test/token_stream_generator/service_generation_utils.rs b/crates/marine-test-macro-impl/src/marine_test/token_stream_generator/service_generation_utils.rs index 6d09490..ea58979 100644 --- a/crates/marine-test-macro-impl/src/marine_test/token_stream_generator/service_generation_utils.rs +++ b/crates/marine-test-macro-impl/src/marine_test/token_stream_generator/service_generation_utils.rs @@ -15,11 +15,16 @@ use itertools::Itertools; pub(crate) fn generate_app_service_ctor( config_path: &str, modules_dir: &Path, + test_file_path: &Path, ) -> TResult { let modules_dir = modules_dir .to_str() .ok_or_else(|| TestGeneratorError::InvalidUTF8Path(modules_dir.to_path_buf()))?; + let test_file_path = test_file_path + .to_str() + .ok_or_else(|| TestGeneratorError::InvalidUTF8Path(test_file_path.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(); @@ -29,7 +34,7 @@ pub(crate) fn generate_app_service_ctor( 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 file_path = std::path::Path::new(#test_file_path).components(); let mut truncated_file_path = Vec::new(); loop { @@ -53,8 +58,6 @@ pub(crate) fn generate_app_service_ctor( 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"); @@ -77,6 +80,7 @@ pub(super) fn generate_service_definition( service: &ProcessedService, test_file_path: &Path, linked_facade: &LinkedModule<'_>, + file_path_for_app_service: &Path, ) -> TResult { let modules_dir_test_relative = test_file_path.join(&service.config.resolved_modules_dir); let modules = @@ -102,8 +106,11 @@ pub(super) fn generate_service_definition( 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 app_service_ctor = generate_app_service_ctor( + &service.config_path, + &service.config.resolved_modules_dir, + file_path_for_app_service, + )?; let modules_type = generate_modules_type(&modules)?; let service_definition = quote! { diff --git a/crates/marine-test-macro-impl/src/marine_test/token_stream_generator/service_generator.rs b/crates/marine-test-macro-impl/src/marine_test/token_stream_generator/service_generator.rs index ee2cf63..3a48a13 100644 --- a/crates/marine-test-macro-impl/src/marine_test/token_stream_generator/service_generator.rs +++ b/crates/marine-test-macro-impl/src/marine_test/token_stream_generator/service_generator.rs @@ -27,11 +27,11 @@ use proc_macro2::TokenStream; use itertools::{Itertools, zip}; use std::path::Path; -use std::collections::HashMap; pub(crate) fn generate_service_definitions( - services: HashMap, + services: impl IntoIterator, file_path: &Path, + file_path_for_app_service: &Path, ) -> TResult> { let services = services .into_iter() @@ -55,9 +55,10 @@ pub(crate) fn generate_service_definitions( .map(|service| -> TResult { // entry with service.name was added in link_services(...), so unwrap is safe generate_service_definition( - &service, + service, file_path, link_info.get::(&service.name).unwrap(), + file_path_for_app_service, ) }) .collect::>>() @@ -84,7 +85,7 @@ impl ProcessedService { name: String, file_path: &Path, ) -> TResult { - let config_wrapper = load_config(&service.config_path, service.modules_dir, &file_path)?; + let config_wrapper = load_config(&service.config_path, service.modules_dir, file_path)?; Ok(Self { config: config_wrapper, diff --git a/crates/marine-test-macro-impl/tests/generation_tests/empty_func/expanded.rs b/crates/marine-test-macro-impl/tests/generation_tests/empty_func/expanded.rs index e48e13b..f8dbd06 100644 --- a/crates/marine-test-macro-impl/tests/generation_tests/empty_func/expanded.rs +++ b/crates/marine-test-macro-impl/tests/generation_tests/empty_func/expanded.rs @@ -77,7 +77,7 @@ fn empty_string() { 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 file_path = std::path::Path::new("tests/generation_tests/empty_func").components(); let mut truncated_file_path = Vec::new(); loop { if module_path.ends_with(file_path.as_path()) { @@ -98,7 +98,6 @@ fn empty_string() { for path in truncated_file_path.iter().rev() { module_path.push(path); } - let _ = module_path.pop(); let config_path = module_path.join("Config.toml"); let modules_dir = module_path.join("artifacts"); let modules_dir = modules_dir diff --git a/crates/marine-test-macro-impl/tests/generation_tests/mounted_binary/expanded.rs b/crates/marine-test-macro-impl/tests/generation_tests/mounted_binary/expanded.rs index 4b23eb7..417daaf 100644 --- a/crates/marine-test-macro-impl/tests/generation_tests/mounted_binary/expanded.rs +++ b/crates/marine-test-macro-impl/tests/generation_tests/mounted_binary/expanded.rs @@ -71,7 +71,6 @@ fn test() { } 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 @@ -89,7 +88,6 @@ fn test() { 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 @@ -111,7 +109,7 @@ fn test() { 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 file_path = std::path::Path::new("tests/generation_tests/mounted_binary").components(); let mut truncated_file_path = Vec::new(); loop { if module_path.ends_with(file_path.as_path()) { @@ -132,7 +130,6 @@ fn test() { for path in truncated_file_path.iter().rev() { module_path.push(path); } - let _ = module_path.pop(); let config_path = module_path.join("Config.toml"); let modules_dir = module_path.join("artifacts"); let modules_dir = modules_dir diff --git a/crates/marine-test-macro-impl/tests/generation_tests/multi-service-empty_mod/Config.toml b/crates/marine-test-macro-impl/tests/generation_tests/multi-service-empty_mod/Config.toml new file mode 100644 index 0000000..2e740e3 --- /dev/null +++ b/crates/marine-test-macro-impl/tests/generation_tests/multi-service-empty_mod/Config.toml @@ -0,0 +1,6 @@ +modules_dir = "artifacts/" + +[[module]] + name = "greeting" + mem_pages_count = 1 + logger_enabled = false diff --git a/crates/marine-test-macro-impl/tests/generation_tests/multi-service-empty_mod/artifacts/greeting.wasm b/crates/marine-test-macro-impl/tests/generation_tests/multi-service-empty_mod/artifacts/greeting.wasm new file mode 100755 index 0000000..20cd5a2 Binary files /dev/null and b/crates/marine-test-macro-impl/tests/generation_tests/multi-service-empty_mod/artifacts/greeting.wasm differ diff --git a/crates/marine-test-macro-impl/tests/generation_tests/multi-service-empty_mod/expanded.rs b/crates/marine-test-macro-impl/tests/generation_tests/multi-service-empty_mod/expanded.rs new file mode 100644 index 0000000..c246dab --- /dev/null +++ b/crates/marine-test-macro-impl/tests/generation_tests/multi-service-empty_mod/expanded.rs @@ -0,0 +1,241 @@ +#[attribute] +pub mod tests { + pub mod marine_test_env { + pub mod empty_mod { + 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> + } + #[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, + pub stderr: Vec + } + #[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, + >, + } + impl ModuleInterface { + pub fn new( + marine: std::rc::Rc< + std::cell::RefCell, + > + ) -> 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> + } + #[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, + pub stderr: Vec + } + #[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, + >, + } + impl ModuleInterface { + pub fn new( + marine: std::rc::Rc< + std::cell::RefCell, + > + ) -> 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, + > + ) -> Self { + Self { + greeting: modules::greeting::ModuleInterface::new(marine.clone()), + } + } + } + pub struct ServiceInterface { + pub modules: __GeneratedModules, + __facade: __facade_override::ModuleInterface, + marine: std::rc::Rc, > + } + 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("tests/generation_tests/multi-service-empty_mod").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 config_path = module_path.join("Config.toml"); + let modules_dir = module_path.join("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 some_mod1; + pub mod some_mod2 {} + pub fn some_fn() {} + const SOME_CONST: i32 = 1; +} diff --git a/crates/marine-test-macro-impl/tests/generation_tests/multi-service-empty_mod/marine_test.rs b/crates/marine-test-macro-impl/tests/generation_tests/multi-service-empty_mod/marine_test.rs new file mode 100644 index 0000000..210ca77 --- /dev/null +++ b/crates/marine-test-macro-impl/tests/generation_tests/multi-service-empty_mod/marine_test.rs @@ -0,0 +1,7 @@ +#[attribute] +pub mod tests { + pub mod some_mod1; + pub mod some_mod2 {} + pub fn some_fn() {} + const SOME_CONST: i32 = 1; +} diff --git a/crates/marine-test-macro-impl/tests/generation_tests/multi-service-multiple/expanded.rs b/crates/marine-test-macro-impl/tests/generation_tests/multi-service-multiple/expanded.rs index b9381a7..0e068d9 100644 --- a/crates/marine-test-macro-impl/tests/generation_tests/multi-service-multiple/expanded.rs +++ b/crates/marine-test-macro-impl/tests/generation_tests/multi-service-multiple/expanded.rs @@ -178,7 +178,7 @@ fn test() { 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 file_path = std::path::Path::new("tests/generation_tests/multi-service-multiple").components(); let mut truncated_file_path = Vec::new(); loop { if module_path.ends_with(file_path.as_path()) { @@ -200,7 +200,6 @@ fn test() { 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 @@ -307,7 +306,6 @@ fn test() { } 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 @@ -325,7 +323,6 @@ fn test() { 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 @@ -362,7 +359,6 @@ fn test() { } 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 @@ -380,7 +376,6 @@ fn test() { 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 @@ -427,7 +422,7 @@ fn test() { 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 file_path = std::path::Path::new("tests/generation_tests/multi-service-multiple").components(); let mut truncated_file_path = Vec::new(); loop { if module_path.ends_with(file_path.as_path()) { @@ -449,7 +444,6 @@ fn test() { 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 diff --git a/crates/marine-test-macro-impl/tests/generation_tests/multi-service-single/expanded.rs b/crates/marine-test-macro-impl/tests/generation_tests/multi-service-single/expanded.rs index 4c3c7cc..6f70cfa 100644 --- a/crates/marine-test-macro-impl/tests/generation_tests/multi-service-single/expanded.rs +++ b/crates/marine-test-macro-impl/tests/generation_tests/multi-service-single/expanded.rs @@ -178,7 +178,7 @@ fn empty_test() { 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 file_path = std::path::Path::new("tests/generation_tests/multi-service-single").components(); let mut truncated_file_path = Vec::new(); loop { if module_path.ends_with(file_path.as_path()) { @@ -200,7 +200,6 @@ fn empty_test() { 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 diff --git a/crates/marine-test-macro-impl/tests/generation_tests/multiple_modules/expanded.rs b/crates/marine-test-macro-impl/tests/generation_tests/multiple_modules/expanded.rs index 7c0a886..57dea47 100644 --- a/crates/marine-test-macro-impl/tests/generation_tests/multiple_modules/expanded.rs +++ b/crates/marine-test-macro-impl/tests/generation_tests/multiple_modules/expanded.rs @@ -70,7 +70,6 @@ fn empty_string() { } impl ModuleInterface { pub fn greeting(&mut self, name: String) -> String { - use std::ops::DerefMut; let arguments = marine_rs_sdk_test::internal::serde_json::json!([name]); let result = self .marine @@ -88,7 +87,6 @@ fn empty_string() { name: String, cp: marine_rs_sdk_test::CallParameters ) -> String { - use std::ops::DerefMut; let arguments = marine_rs_sdk_test::internal::serde_json::json!([name]); let result = self .marine @@ -120,7 +118,6 @@ fn empty_string() { } impl ModuleInterface { pub fn call_parameters(&mut self, ) -> String { - use std::ops::DerefMut; let arguments = marine_rs_sdk_test::internal::serde_json::json!([]); let result = self .marine @@ -142,7 +139,6 @@ fn empty_string() { &mut self, cp: marine_rs_sdk_test::CallParameters ) -> String { - use std::ops::DerefMut; let arguments = marine_rs_sdk_test::internal::serde_json::json!([]); let result = self .marine @@ -156,7 +152,6 @@ fn empty_string() { result } pub fn return_string(&mut self,) -> String { - use std::ops::DerefMut; let arguments = marine_rs_sdk_test::internal::serde_json::json!([]); let result = self .marine @@ -178,7 +173,6 @@ fn empty_string() { &mut self, cp: marine_rs_sdk_test::CallParameters ) -> String { - use std::ops::DerefMut; let arguments = marine_rs_sdk_test::internal::serde_json::json!([]); let result = self .marine @@ -192,7 +186,6 @@ fn empty_string() { result } pub fn test_array_refs(&mut self, ) -> Vec { - use std::ops::DerefMut; let arguments = marine_rs_sdk_test::internal::serde_json::json!([]); let result = self .marine @@ -214,7 +207,6 @@ fn empty_string() { &mut self, cp: marine_rs_sdk_test::CallParameters ) -> Vec { - use std::ops::DerefMut; let arguments = marine_rs_sdk_test::internal::serde_json::json!([]); let result = self .marine @@ -236,7 +228,7 @@ fn empty_string() { 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 file_path = std::path::Path::new("tests/generation_tests/multiple_modules").components(); let mut truncated_file_path = Vec::new(); loop { if module_path.ends_with(file_path.as_path()) { @@ -257,7 +249,6 @@ fn empty_string() { for path in truncated_file_path.iter().rev() { module_path.push(path); } - let _ = module_path.pop(); let config_path = module_path.join("Config.toml"); let modules_dir = module_path.join("artifacts"); let modules_dir = modules_dir diff --git a/crates/marine-test-macro-impl/tests/generation_tests_runner.rs b/crates/marine-test-macro-impl/tests/generation_tests_runner.rs index 53221ea..f3343b8 100644 --- a/crates/marine-test-macro-impl/tests/generation_tests_runner.rs +++ b/crates/marine-test-macro-impl/tests/generation_tests_runner.rs @@ -84,3 +84,17 @@ fn test_multiservice_multiple() { descriptions )); } + +#[test] +fn test_multiservice_empty_mod() { + let descriptions = vec![TestServiceDescription { + modules_dir: "artifacts", + config_path: "Config.toml", + name: "empty_mod", + }]; + assert!(test_marine_test_token_streams_multiservice( + "tests/generation_tests/multi-service-empty_mod/marine_test.rs", + "tests/generation_tests/multi-service-empty_mod/expanded.rs", + descriptions + )); +} diff --git a/crates/marine-test-macro/Cargo.toml b/crates/marine-test-macro/Cargo.toml index 74639a2..607b9cb 100644 --- a/crates/marine-test-macro/Cargo.toml +++ b/crates/marine-test-macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "marine-test-macro" -version = "0.3.0" # remember to update html_root_url +version = "0.4.0" # remember to update html_root_url edition = "2018" description = "Definition of the `#[marine_test]` macro" documentation = "https://docs.rs/fluence/marine-test-macro" @@ -18,7 +18,7 @@ proc-macro = true doctest = false [dependencies] -marine-test-macro-impl = { path = "../marine-test-macro-impl", version = "=0.3.0" } +marine-test-macro-impl = { path = "../marine-test-macro-impl", version = "=0.4.0" } quote = "1.0.9" proc-macro2 = "1.0.24" diff --git a/crates/marine-test-macro/src/lib.rs b/crates/marine-test-macro/src/lib.rs index 4befd57..ebdf075 100644 --- a/crates/marine-test-macro/src/lib.rs +++ b/crates/marine-test-macro/src/lib.rs @@ -14,7 +14,7 @@ * limitations under the License. */ -#![doc(html_root_url = "https://docs.rs/sdk-test-macro/0.3.0")] +#![doc(html_root_url = "https://docs.rs/marine-test-macro/0.4.0")] #![deny( dead_code, nonstandard_style, diff --git a/src/lib.rs b/src/lib.rs index 1d3b080..be328e6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,7 +14,7 @@ * limitations under the License. */ -#![doc(html_root_url = "https://docs.rs/sdk-test/0.3.0")] +#![doc(html_root_url = "https://docs.rs/marine-rs-sdk-test/0.4.0")] #![deny( dead_code, nonstandard_style, @@ -29,6 +29,10 @@ pub use marine_test_macro::marine_test; pub use marine_test_macro::fce_test; +pub use marine_build_rs_generator::generate_marine_test_env; +pub use marine_build_rs_generator::ServiceDescription; +pub use marine_build_rs_generator::include_test_env; + pub use fluence_app_service::CallParameters; pub use fluence_app_service::SecurityTetraplet;