diff --git a/Cargo.lock b/Cargo.lock
index ce57bbc..f6ced0c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -13,9 +13,9 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.42"
+version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486"
+checksum = "28ae2b3dec75a406790005a200b1bd89785afc02517a00ca99ecfe093ee9e6cf"
[[package]]
name = "arrayref"
@@ -57,9 +57,9 @@ dependencies = [
[[package]]
name = "bitflags"
-version = "1.2.1"
+version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "blake3"
@@ -101,9 +101,9 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.0.69"
+version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2"
+checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0"
[[package]]
name = "cfg-if"
@@ -278,9 +278,9 @@ dependencies = [
[[package]]
name = "ctor"
-version = "0.1.20"
+version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d"
+checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa"
dependencies = [
"quote",
"syn",
@@ -425,13 +425,14 @@ dependencies = [
[[package]]
name = "fluence-it-types"
-version = "0.3.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5006d09553345421af5dd2334cc945fc34dc2a73d7c1ed842a39a3803699619d"
+checksum = "047f670b4807cab8872550a607b1515daff08b3e3bb7576ce8f45971fd811a4e"
dependencies = [
"it-to-bytes",
"nom",
"serde",
+ "variant_count",
"wast",
]
@@ -638,9 +639,9 @@ dependencies = [
[[package]]
name = "itoa"
-version = "0.4.7"
+version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
+checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "lazy_static"
@@ -669,9 +670,9 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.98"
+version = "0.2.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
+checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21"
[[package]]
name = "lock_api"
@@ -705,7 +706,7 @@ checksum = "e62f29b16bbdb0763a04f8561c954624ee9cd9f558af4e67b95eb00880da11ec"
dependencies = [
"cargo_toml",
"it-lilo",
- "marine-it-parser 0.6.5",
+ "marine-it-parser",
"marine-macro-impl 0.6.10",
"once_cell",
"serde",
@@ -715,16 +716,6 @@ dependencies = [
"wasmer-interface-types-fl",
]
-[[package]]
-name = "marine-it-interfaces"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97c533789e72808630cc35b5d14d286382236282525f82ddce8fb47eb9d659e8"
-dependencies = [
- "multimap",
- "wasmer-interface-types-fl",
-]
-
[[package]]
name = "marine-it-interfaces"
version = "0.4.0"
@@ -735,23 +726,6 @@ dependencies = [
"wasmer-interface-types-fl",
]
-[[package]]
-name = "marine-it-parser"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e59c7067a18b9e4aebe67bee033638fae97d6fe4fb00f70f9a509eb5d03d1c5d"
-dependencies = [
- "anyhow",
- "marine-it-interfaces 0.3.0",
- "nom",
- "semver 0.11.0",
- "serde",
- "thiserror",
- "walrus",
- "wasmer-interface-types-fl",
- "wasmer-runtime-core-fl",
-]
-
[[package]]
name = "marine-it-parser"
version = "0.6.5"
@@ -760,7 +734,7 @@ checksum = "19a6606e472587b2e7b759b16d037a4ea951facc2a6650f668f22403978c2442"
dependencies = [
"anyhow",
"itertools 0.10.1",
- "marine-it-interfaces 0.4.0",
+ "marine-it-interfaces",
"marine-module-interface",
"nom",
"semver 0.11.0",
@@ -805,6 +779,7 @@ dependencies = [
name = "marine-macro-impl"
version = "0.6.11"
dependencies = [
+ "marine-macro-testing-utils",
"pretty_assertions",
"proc-macro2",
"quote",
@@ -814,6 +789,15 @@ dependencies = [
"uuid",
]
+[[package]]
+name = "marine-macro-testing-utils"
+version = "0.1.0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "marine-module-info-parser"
version = "0.2.0"
@@ -838,7 +822,7 @@ checksum = "d8a5936273bebb523ed169863282dbc19fc66bb983c7031c5b8b0556584f2401"
dependencies = [
"anyhow",
"itertools 0.10.1",
- "marine-it-interfaces 0.4.0",
+ "marine-it-interfaces",
"nom",
"semver 0.11.0",
"serde",
@@ -895,12 +879,13 @@ dependencies = [
[[package]]
name = "marine-rs-sdk-test"
-version = "0.1.11"
+version = "0.2.0"
dependencies = [
"fluence-app-service",
"marine-test-macro",
"serde",
"serde_json",
+ "trybuild",
"uuid",
]
@@ -915,8 +900,8 @@ dependencies = [
"it-lilo",
"log",
"marine-it-generator",
- "marine-it-interfaces 0.4.0",
- "marine-it-parser 0.6.5",
+ "marine-it-interfaces",
+ "marine-it-parser",
"marine-module-info-parser",
"marine-module-interface",
"marine-utils",
@@ -936,7 +921,7 @@ dependencies = [
[[package]]
name = "marine-test-macro"
-version = "0.1.11"
+version = "0.2.0"
dependencies = [
"marine-test-macro-impl",
"proc-macro-error",
@@ -947,14 +932,17 @@ dependencies = [
[[package]]
name = "marine-test-macro-impl"
-version = "0.1.11"
+version = "0.2.0"
dependencies = [
"darling",
"fluence-app-service",
- "marine-it-parser 0.5.0",
+ "itertools 0.10.1",
+ "marine-it-parser",
+ "marine-macro-testing-utils",
"proc-macro-error",
"proc-macro2",
"quote",
+ "static_assertions",
"syn",
"thiserror",
]
@@ -985,9 +973,9 @@ checksum = "8dc5838acba84ce4d802d672afd0814fae0ae7098021ae5b06d975e70d09f812"
[[package]]
name = "memchr"
-version = "2.4.0"
+version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
+checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]]
name = "memmap"
@@ -1177,9 +1165,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.28"
+version = "1.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612"
+checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d"
dependencies = [
"unicode-xid",
]
@@ -1347,9 +1335,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.66"
+version = "1.0.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "336b10da19a12ad094b59d870ebde26a45402e5b470add4b5fd03c5048a32127"
+checksum = "a7f9e390c27c3c0ce8bc5d725f6e4d30a29d26659494aa4b17535f7522c5c950"
dependencies = [
"itoa",
"ryu",
@@ -1358,9 +1346,9 @@ dependencies = [
[[package]]
name = "simple_logger"
-version = "1.12.1"
+version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28475b72d7e5da6ad80c6d284aa557821bb4f7f788b9f607632635e3783a8608"
+checksum = "b7de33c687404ec3045d4a0d437580455257c0436f858d702f244e7d652f9f07"
dependencies = [
"atty",
"chrono",
@@ -1395,9 +1383,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "syn"
-version = "1.0.74"
+version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c"
+checksum = "b7f58f7e8eaa0009c5fec437aabf511bd9933e4b2d7407bd05273c01a8906ea7"
dependencies = [
"proc-macro2",
"quote",
@@ -1421,18 +1409,18 @@ dependencies = [
[[package]]
name = "thiserror"
-version = "1.0.26"
+version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2"
+checksum = "283d5230e63df9608ac7d9691adc1dfb6e701225436eb64d0b9a7f0a5a04f6ec"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.26"
+version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745"
+checksum = "fa3884228611f5cd3608e2d409bf7dce832e4eb3135e3f11addbd7e41bd68e71"
dependencies = [
"proc-macro2",
"quote",
@@ -1461,9 +1449,9 @@ dependencies = [
[[package]]
name = "trybuild"
-version = "1.0.43"
+version = "1.0.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c02c413315329fc96167f922b46fd0caa3a43f4697b7a7896b183c7142635832"
+checksum = "5bdaf2a1d317f3d58b44b31c7f6436b9b9acafe7bddfeace50897c2b804d7792"
dependencies = [
"glob",
"lazy_static",
@@ -1530,6 +1518,16 @@ dependencies = [
"getrandom 0.2.3",
]
+[[package]]
+name = "variant_count"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aae2faf80ac463422992abf4de234731279c058aaf33171ca70277c98406b124"
+dependencies = [
+ "quote",
+ "syn",
+]
+
[[package]]
name = "version_check"
version = "0.9.3"
diff --git a/crates/macro-testing-utils/Cargo.toml b/crates/macro-testing-utils/Cargo.toml
new file mode 100644
index 0000000..54b876b
--- /dev/null
+++ b/crates/macro-testing-utils/Cargo.toml
@@ -0,0 +1,21 @@
+[package]
+name = "marine-macro-testing-utils"
+version = "0.1.0"
+edition = "2018"
+description = "Some functions for testing procedural macros"
+documentation = "https://docs.rs/fluence/marine-macro-testing-utils"
+repository = "https://github.com/fluencelabs/marine-rs-sdk/tree/master/crates/marine-macro-testing-utils"
+authors = ["Fluence Labs"]
+keywords = ["fluence", "marine", "sdk", "webassembly"]
+categories = ["development-tools::testing"]
+license = "Apache-2.0"
+
+[lib]
+path = "src/lib.rs"
+crate-type = ["rlib"]
+doctest = false
+
+[dependencies]
+quote = "1.0.9"
+proc-macro2 = "1.0.26"
+syn = { version = '1.0.64', features = ['full'] }
diff --git a/crates/macro-testing-utils/src/lib.rs b/crates/macro-testing-utils/src/lib.rs
new file mode 100644
index 0000000..d3af384
--- /dev/null
+++ b/crates/macro-testing-utils/src/lib.rs
@@ -0,0 +1,44 @@
+/*
+ * 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 std::io::Read;
+use std::path::Path;
+
+pub fn stream_from_file
(path: P) -> proc_macro2::TokenStream
+where
+ P: AsRef,
+{
+ let items = items_from_file(path);
+ quote::quote! { #(#items)* }
+}
+
+pub fn items_from_file(path: P) -> Vec
+where
+ P: AsRef,
+{
+ let mut file = std::fs::File::open(path).expect("Unable to open file");
+
+ let mut src = String::new();
+ file.read_to_string(&mut src).expect("Unable to read file");
+
+ let token_file = syn::parse_file(&src).expect("Unable to parse file");
+ token_file.items
+}
+
+pub fn to_syn_item(token_stream: proc_macro2::TokenStream) -> Vec {
+ let file: syn::File = syn::parse2(token_stream).expect("token stream should be parsed");
+ file.items
+}
diff --git a/crates/marine-macro-impl/Cargo.toml b/crates/marine-macro-impl/Cargo.toml
index db0e227..7ea2abd 100644
--- a/crates/marine-macro-impl/Cargo.toml
+++ b/crates/marine-macro-impl/Cargo.toml
@@ -23,3 +23,4 @@ uuid = { version = "0.8.2", features = ["v4"] }
[dev-dependencies]
pretty_assertions = "0.7.1"
+marine-macro-testing-utils = {path = "../macro-testing-utils"}
diff --git a/crates/marine-macro-impl/tests/utils.rs b/crates/marine-macro-impl/tests/utils.rs
index 788ed0a..df252ba 100644
--- a/crates/marine-macro-impl/tests/utils.rs
+++ b/crates/marine-macro-impl/tests/utils.rs
@@ -16,7 +16,8 @@
use marine_macro_impl::marine;
-use std::io::Read;
+use marine_macro_testing_utils::{items_from_file, stream_from_file, to_syn_item};
+
use std::path::Path;
pub fn test_marine_token_streams(marine_path: FP, expanded_path: EP) -> bool
@@ -34,29 +35,3 @@ where
marine_item == expanded_item
}
-
-fn stream_from_file(path: P) -> proc_macro2::TokenStream
-where
- P: AsRef,
-{
- let items = items_from_file(path);
- quote::quote! { #(#items)* }
-}
-
-fn items_from_file(path: P) -> Vec
-where
- P: AsRef,
-{
- let mut file = std::fs::File::open(path).expect("Unable to open file");
-
- let mut src = String::new();
- file.read_to_string(&mut src).expect("Unable to read file");
-
- let token_file = syn::parse_file(&src).expect("Unable to parse file");
- token_file.items
-}
-
-fn to_syn_item(token_stream: proc_macro2::TokenStream) -> Vec {
- let file: syn::File = syn::parse2(token_stream).expect("token stream should be parsed");
- file.items
-}
diff --git a/crates/marine-test-macro-impl/Cargo.toml b/crates/marine-test-macro-impl/Cargo.toml
index 1fee2ce..9d3a074 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.1.11" # remember to update html_root_url
+version = "0.2.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"
@@ -15,11 +15,15 @@ all-features = true
[dependencies]
fluence-app-service = { version = "0.9.0", features = ["raw-module-api"] }
-marine-it-parser = "0.5.0"
-
+marine-it-parser = "0.6.5"
+itertools = "0.10.1"
darling = "0.12.2"
quote = "1.0.9"
proc-macro2 = "1.0.26"
proc-macro-error = { version = "1.0.4", default-features = false }
syn = { version = '1.0.64', features = ['full'] }
thiserror = "1.0.24"
+static_assertions = "1.1.0"
+
+[dev-dependencies]
+marine-macro-testing-utils = {path = "../macro-testing-utils"}
diff --git a/crates/marine-test-macro-impl/src/errors.rs b/crates/marine-test-macro-impl/src/errors.rs
index 72a0421..a84b7d2 100644
--- a/crates/marine-test-macro-impl/src/errors.rs
+++ b/crates/marine-test-macro-impl/src/errors.rs
@@ -50,6 +50,12 @@ pub enum TestGeneratorError {
#[error("{0} is invalid UTF8 path")]
InvalidUTF8Path(PathBuf),
+
+ #[error(r#"a "self" argument found and it is not supported in test function"#)]
+ UnexpectedSelf,
+
+ #[error("Duplicate module: {0}")]
+ DuplicateModuleName(String),
}
#[derive(Debug, ThisError)]
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 87dd52a..9750952 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
@@ -17,19 +17,19 @@
use crate::TResult;
use fluence_app_service::TomlAppServiceConfig;
-use marine_it_parser::module_raw_interface;
-use marine_it_parser::interface::MModuleInterface;
+use marine_it_parser::module_it_interface;
+use marine_it_parser::it_interface::IModuleInterface;
use std::path::PathBuf;
#[derive(Debug, Clone, PartialEq, Eq)]
pub(super) struct Module<'m> {
pub name: &'m str,
- pub interface: MModuleInterface,
+ pub interface: IModuleInterface,
}
impl<'m> Module<'m> {
- fn new(name: &'m str, interface: MModuleInterface) -> Self {
+ fn new(name: &'m str, interface: IModuleInterface) -> Self {
Self { name, interface }
}
}
@@ -43,9 +43,7 @@ pub(super) fn collect_modules(
module_paths
.into_iter()
- .map(|(name, path)| {
- module_raw_interface(path).map(|interface| Module::new(name, interface))
- })
+ .map(|(name, path)| module_it_interface(path).map(|interface| Module::new(name, interface)))
.collect::, _>>()
.map_err(Into::into)
}
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 5d90b31..c775e67 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
@@ -23,9 +23,11 @@ use crate::marine_test::config_utils;
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;
/// Generates glue code for tests.
/// F.e. for this test for the greeting service
@@ -128,30 +130,40 @@ pub(super) fn generate_test_glue_code(
let modules_dir = file_path.join(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)?;
- let module_definitions =
- marine_test::module_generator::generate_module_definitions(module_interfaces.iter())?;
-
- let module_iter = module_interfaces.iter().map(|module| module.name);
- let module_ctors = generate_module_ctors(module_iter)?;
+ let module_definitions = marine_test::module_generator::generate_module_definitions(
+ module_interfaces.iter(),
+ &linked_modules,
+ )?;
let original_block = func_item.block;
let signature = func_item.sig;
+ let name = &signature.ident;
+ let inputs = &signature.inputs;
+ let arg_names = generate_arg_names(inputs.iter())?;
+ let module_ctors = generate_module_ctors(inputs.iter())?;
let glue_code = quote! {
#[test]
- #signature {
+ fn #name() {
// definitions for wasm modules specified in config
- #(#module_definitions)*
-
+ pub mod marine_test_env {
+ #(#module_definitions)*
+ }
// AppService constructor and instantiation to implicit `marine` variable
#app_service_ctor
// constructors of all modules of the tested service
#(#module_ctors)*
- // original test function as is
- #original_block
+ fn test_func(#inputs) {
+ #(let mut #arg_names = #arg_names;)*
+ // original test function as is
+ #original_block
+ }
+
+ test_func(#(#arg_names,)*)
}
};
@@ -181,9 +193,7 @@ fn generate_app_service_ctor(config_path: &str, modules_dir: &Path) -> TResult {
- Some((file_path, p))
- }
+ std::path::Component::Normal(_) | std::path::Component::CurDir | std::path::Component::ParentDir => Some((file_path, p)),
_ => None,
}) {
Some(t) => t,
@@ -218,21 +228,32 @@ fn generate_app_service_ctor(config_path: &str, modules_dir: &Path) -> TResult(
- module_names: impl ExactSizeIterator- ,
+fn generate_module_ctors<'inputs>(
+ inputs: impl Iterator
- ,
) -> TResult> {
- module_names
- .map(|name| -> TResult<_> {
- // TODO: optimize these two call because they are called twice for each module name
- // and internally allocate memory in format call.
- let module_name = marine_test::utils::generate_structs_module_ident(&name)?;
- let struct_name = marine_test::utils::generate_struct_name(&name)?;
- let name_for_user = marine_test::utils::new_ident(&name)?;
-
- let module_ctor =
- quote! { let mut #name_for_user = #module_name::#struct_name::new(marine.clone()); };
-
- Ok(module_ctor)
+ inputs
+ .map(|x| -> TResult<_> {
+ match x {
+ FnArg::Receiver(_) => Err(TestGeneratorError::UnexpectedSelf),
+ FnArg::Typed(x) => {
+ let pat = &x.pat;
+ let ty = &x.ty;
+ Ok(quote! {let mut #pat = #ty::new(marine.clone());})
+ }
+ }
+ })
+ .collect::>()
+}
+
+fn generate_arg_names<'inputs>(
+ inputs: impl Iterator
- ,
+) -> TResult> {
+ inputs
+ .map(|x| -> TResult<_> {
+ match x {
+ FnArg::Receiver(_) => Err(TestGeneratorError::UnexpectedSelf),
+ FnArg::Typed(x) => Ok(x.pat.to_token_stream()),
+ }
})
.collect::>()
}
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 ffb4434..8b98009 100644
--- a/crates/marine-test-macro-impl/src/marine_test/mod.rs
+++ b/crates/marine-test-macro-impl/src/marine_test/mod.rs
@@ -19,5 +19,6 @@ mod marine_test_impl;
mod glue_code_generator;
mod module_generator;
mod utils;
+mod modules_linker;
pub use marine_test_impl::marine_test_impl;
diff --git a/crates/marine-test-macro-impl/src/marine_test/module_generator.rs b/crates/marine-test-macro-impl/src/marine_test/module_generator.rs
index 80940bb..a41022a 100644
--- a/crates/marine-test-macro-impl/src/marine_test/module_generator.rs
+++ b/crates/marine-test-macro-impl/src/marine_test/module_generator.rs
@@ -21,6 +21,7 @@ mod record_type_generator;
use crate::marine_test::utils;
use crate::marine_test::config_utils::Module;
use crate::TResult;
+use crate::marine_test::modules_linker::{LinkedModules, LinkedModule};
use proc_macro2::TokenStream;
use quote::quote;
@@ -56,21 +57,24 @@ use quote::quote;
///```
pub(super) fn generate_module_definitions<'i>(
modules: impl ExactSizeIterator
- >,
+ linked_modules: &'i LinkedModules<'_>,
) -> TResult> {
modules
.into_iter()
- .map(generate_module_definition)
+ .map(|value| generate_module_definition(value, linked_modules.get(&value.name).unwrap())) // linked_modules are built from modules
.collect::>>()
}
-fn generate_module_definition(module: &Module<'_>) -> TResult {
+fn generate_module_definition(
+ module: &Module<'_>,
+ linked_module: &'_ LinkedModule<'_>,
+) -> TResult {
let module_name = module.name;
- let module_ident = utils::generate_module_ident(module_name)?;
- let structs_module_ident = utils::generate_structs_module_ident(module_name)?;
- let struct_ident = utils::generate_struct_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(&module_interface.record_types)?;
+ let module_records = record_type_generator::generate_records(linked_module)?;
let module_functions = methods_generator::generate_module_methods(
module_name,
module_interface.function_signatures.iter(),
@@ -79,26 +83,22 @@ fn generate_module_definition(module: &Module<'_>) -> TResult {
let module_definition = quote! {
// it's a sort of hack: this module structure allows user to import structs by
- // use module_name_structs::StructName;
- pub mod #structs_module_ident {
- pub use #module_ident::*;
+ // using marine_env_test::module_name::StructName;
+ pub mod #module_ident {
+ #(#module_records)*
- pub mod #module_ident {
- #(#module_records)*
+ pub struct #struct_ident {
+ marine: std::rc::Rc, >,
+ }
- pub struct #struct_ident {
- marine: std::rc::Rc>,
+ impl #struct_ident {
+ pub fn new(marine: std::rc::Rc, >) -> Self {
+ Self { marine }
}
+ }
- impl #struct_ident {
- pub fn new(marine: std::rc::Rc>) -> Self {
- Self { marine }
- }
- }
-
- impl #struct_ident {
- #(#module_functions)*
- }
+ impl #struct_ident {
+ #(#module_functions)*
}
}
};
diff --git a/crates/marine-test-macro-impl/src/marine_test/module_generator/methods_generator.rs b/crates/marine-test-macro-impl/src/marine_test/module_generator/methods_generator.rs
index 9799025..893cffa 100644
--- a/crates/marine-test-macro-impl/src/marine_test/module_generator/methods_generator.rs
+++ b/crates/marine-test-macro-impl/src/marine_test/module_generator/methods_generator.rs
@@ -17,27 +17,32 @@
use super::methods_generator_utils::*;
use crate::TResult;
-use marine_it_parser::interface::MRecordTypes;
-use marine_it_parser::interface::MFunctionSignature;
+use marine_it_parser::it_interface::IFunctionSignature;
+use marine_it_parser::it_interface::IRecordTypes;
+
+use itertools::Itertools;
pub(super) fn generate_module_methods<'m, 'r>(
module_name: &str,
- mut method_signatures: impl ExactSizeIterator
- ,
- records: &'r MRecordTypes,
+ method_signatures: impl ExactSizeIterator
- ,
+ records: &'r IRecordTypes,
) -> TResult> {
use CallParametersSettings::*;
let methods_count = 2 * method_signatures.len();
- method_signatures.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)?;
+ 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(module_name, &signature, Default, records)?;
+ let user_cp =
+ generate_module_method(module_name, &signature, UserDefined, records)?;
- methods.push(default_cp);
- methods.push(user_cp);
+ methods.push(default_cp);
+ methods.push(user_cp);
- Ok(methods)
- },
- )
+ Ok(methods)
+ },
+ )
}
diff --git a/crates/marine-test-macro-impl/src/marine_test/module_generator/methods_generator_utils.rs b/crates/marine-test-macro-impl/src/marine_test/module_generator/methods_generator_utils.rs
index ff1be4d..9156381 100644
--- a/crates/marine-test-macro-impl/src/marine_test/module_generator/methods_generator_utils.rs
+++ b/crates/marine-test-macro-impl/src/marine_test/module_generator/methods_generator_utils.rs
@@ -18,10 +18,10 @@ use crate::marine_test::utils::new_ident;
use crate::marine_test::utils::itype_to_tokens;
use crate::TResult;
-use marine_it_parser::interface::it::IType;
-use marine_it_parser::interface::it::IFunctionArg;
-use marine_it_parser::interface::MRecordTypes;
-use marine_it_parser::interface::MFunctionSignature;
+use marine_it_parser::it_interface::it::IType;
+use marine_it_parser::it_interface::it::IFunctionArg;
+use marine_it_parser::it_interface::IRecordTypes;
+use marine_it_parser::it_interface::IFunctionSignature;
use proc_macro2::TokenStream;
use quote::quote;
@@ -34,9 +34,9 @@ pub(super) enum CallParametersSettings {
pub(super) fn generate_module_method(
module_name: &str,
- signature: &MFunctionSignature,
+ signature: &IFunctionSignature,
cp_setting: CallParametersSettings,
- records: &MRecordTypes,
+ records: &IRecordTypes,
) -> TResult {
let arguments = generate_arguments(signature.arguments.iter(), records)?;
let output_type = generate_output_type(&signature.outputs, records)?;
@@ -73,8 +73,8 @@ pub(super) fn generate_module_method(
fn generate_marine_call(
module_name: &str,
cp_settings: CallParametersSettings,
- method_signature: &MFunctionSignature,
- records: &MRecordTypes,
+ method_signature: &IFunctionSignature,
+ records: &IRecordTypes,
) -> TResult {
let args = method_signature.arguments.iter().map(|a| a.name.as_str());
let convert_arguments = generate_arguments_converter(args)?;
@@ -133,7 +133,7 @@ fn generate_set_result(output_type: &Option<&IType>) -> TokenStream {
fn generate_convert_to_output(
output_type: &Option<&IType>,
- records: &MRecordTypes,
+ records: &IRecordTypes,
) -> TResult {
let result_stream = match output_type {
Some(ty) => {
@@ -157,7 +157,7 @@ fn generate_ret(output_type: &Option<&IType>) -> TokenStream {
fn generate_arguments<'a, 'r>(
arguments: impl ExactSizeIterator
- ,
- records: &'r MRecordTypes,
+ records: &'r IRecordTypes,
) -> TResult> {
arguments
.map(|argument| -> TResult<_> {
@@ -170,7 +170,7 @@ fn generate_arguments<'a, 'r>(
.collect::>>()
}
-fn generate_output_type(output_types: &[IType], records: &MRecordTypes) -> TResult {
+fn generate_output_type(output_types: &[IType], records: &IRecordTypes) -> TResult {
let output_type = get_output_type(output_types)?;
match output_type {
None => Ok(TokenStream::new()),
diff --git a/crates/marine-test-macro-impl/src/marine_test/module_generator/record_type_generator.rs b/crates/marine-test-macro-impl/src/marine_test/module_generator/record_type_generator.rs
index df529f6..1e7bd16 100644
--- a/crates/marine-test-macro-impl/src/marine_test/module_generator/record_type_generator.rs
+++ b/crates/marine-test-macro-impl/src/marine_test/module_generator/record_type_generator.rs
@@ -17,35 +17,47 @@
use crate::marine_test::utils;
use crate::TResult;
-use marine_it_parser::interface::it::IRecordFieldType;
-use marine_it_parser::interface::MRecordTypes;
+use marine_it_parser::it_interface::it::IRecordFieldType;
+use marine_it_parser::it_interface::IRecordTypes;
use proc_macro2::TokenStream;
use quote::quote;
-pub(super) fn generate_records(records: &MRecordTypes) -> TResult> {
- use std::ops::Deref;
+use crate::marine_test::modules_linker::{LinkedModule, RecordEntry};
+use itertools::Itertools;
- records.iter().map(|(_, record)| -> TResult<_> {
- let record_name_ident = utils::generate_record_name(&record.name)?;
- let fields = prepare_field(record.fields.deref().iter(), records)?;
+pub(super) fn generate_records(linked_module: &LinkedModule<'_>) -> TResult> {
+ 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;})
+ },
+ Declare(record) => {
+ let record_name_ident = utils::new_ident(&record.record_type.name)?;
+ let fields = prepare_field(record.record_type.fields.iter(), record.records)?;
- let generated_record = quote! {
- #[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 #record_name_ident {
- #(pub #fields),*
+ Ok(quote! {
+ #[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 #record_name_ident {
+ #(pub #fields),*
+ }
+ })
+ }
}
- };
-
- Ok(generated_record)
- }
- ).collect::>>()
+ })
+ .collect::>>()
}
fn prepare_field<'f>(
fields: impl ExactSizeIterator
- ,
- records: &MRecordTypes,
+ records: &IRecordTypes,
) -> TResult> {
fields
.map(|field| -> TResult<_> {
diff --git a/crates/marine-test-macro-impl/src/marine_test/modules_linker.rs b/crates/marine-test-macro-impl/src/marine_test/modules_linker.rs
new file mode 100644
index 0000000..23894e6
--- /dev/null
+++ b/crates/marine-test-macro-impl/src/marine_test/modules_linker.rs
@@ -0,0 +1,198 @@
+/*
+ * 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::marine_test::config_utils::Module;
+use crate::{TResult, TestGeneratorError};
+
+use marine_it_parser::it_interface::IRecordTypes;
+use marine_it_parser::it_interface::it::{IType, IRecordType};
+
+use itertools::zip;
+use std::cmp::Ordering;
+use std::collections::HashMap;
+use std::hash::Hasher;
+use std::rc::Rc;
+use static_assertions::const_assert;
+
+pub(super) fn link_modules<'modules>(
+ modules: &'modules [Module<'_>],
+) -> TResult> {
+ let mut all_record_types = HashMap::, &str>::new();
+ let mut linked_modules = HashMap::<&str, LinkedModule<'_>>::new();
+
+ for module in modules {
+ let mut linking_module = LinkedModule::default();
+ for (_, record_type) in &module.interface.record_types {
+ let record_type_ex =
+ IRecordTypeClosed::new(record_type.clone(), &module.interface.record_types);
+
+ let entry = match all_record_types.get(&record_type_ex) {
+ Some(owner_module) => RecordEntry::Use(UseDescription {
+ from: owner_module,
+ name: &record_type.name,
+ }),
+ None => {
+ all_record_types.insert(record_type_ex.clone(), module.name);
+ RecordEntry::Declare(record_type_ex)
+ }
+ };
+
+ linking_module.records.push(entry);
+ }
+
+ if linked_modules.insert(module.name, linking_module).is_some() {
+ return Err(TestGeneratorError::DuplicateModuleName(
+ module.name.to_string(),
+ ));
+ }
+ }
+
+ Ok(linked_modules)
+}
+
+struct ITypeClosed<'r> {
+ ty: &'r IType,
+ records: &'r IRecordTypes,
+}
+
+impl<'r> ITypeClosed<'r> {
+ fn new(ty: &'r IType, records: &'r IRecordTypes) -> Self {
+ Self { ty, records }
+ }
+}
+
+impl PartialEq for ITypeClosed<'_> {
+ fn eq(&self, other: &Self) -> bool {
+ use IType::*;
+ // check if new variants require special handling in the match below
+ #[allow(unused)]
+ const LAST_VERIFIED_ITYPE_SIZE: usize = 17;
+ const_assert!(IType::VARIANT_COUNT == LAST_VERIFIED_ITYPE_SIZE);
+
+ match (&self.ty, &other.ty) {
+ (Array(self_ty), Array(other_ty)) => {
+ ITypeClosed::new(self_ty, self.records) == ITypeClosed::new(other_ty, other.records)
+ }
+ (Record(self_record), Record(other_record)) => {
+ let self_record = self.records.get(self_record);
+ let other_record = other.records.get(other_record);
+
+ // ID from Record(ID) potentially may not be in .records, if it happens comparision is always FALSE
+ match (self_record, other_record) {
+ (None, _) => false,
+ (_, None) => false,
+ (Some(self_record), Some(other_record)) => {
+ IRecordTypeClosed::new(self_record.clone(), self.records)
+ == IRecordTypeClosed::new(other_record.clone(), other.records)
+ }
+ }
+ }
+ (lhs, rhs) if lhs == rhs => true,
+ _ => false,
+ }
+ }
+}
+
+#[derive(Clone)]
+pub struct IRecordTypeClosed<'r> {
+ pub record_type: Rc,
+ pub records: &'r IRecordTypes,
+}
+
+impl<'r> IRecordTypeClosed<'r> {
+ fn new(record_type: Rc, records: &'r IRecordTypes) -> Self {
+ Self {
+ record_type,
+ records,
+ }
+ }
+}
+
+impl PartialEq for IRecordTypeClosed<'_> {
+ fn eq(&self, other: &Self) -> bool {
+ let names_are_equal = self.record_type.name == other.record_type.name;
+ names_are_equal && fields_are_equal(self, other)
+ }
+}
+
+fn fields_are_equal(lhs: &IRecordTypeClosed<'_>, rhs: &IRecordTypeClosed<'_>) -> bool {
+ let same_fields_count = lhs.record_type.fields.len() == rhs.record_type.fields.len();
+ same_fields_count
+ && zip(lhs.record_type.fields.iter(), rhs.record_type.fields.iter()).all(
+ |(lhs_field, rhs_field)| -> bool {
+ lhs_field.name == rhs_field.name
+ && ITypeClosed::new(&lhs_field.ty, lhs.records)
+ == ITypeClosed::new(&rhs_field.ty, rhs.records)
+ },
+ )
+}
+
+impl PartialOrd for IRecordTypeClosed<'_> {
+ fn partial_cmp(&self, other: &Self) -> Option {
+ Some(self.cmp(other))
+ }
+}
+
+impl Ord for IRecordTypeClosed<'_> {
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.record_type.name.cmp(&other.record_type.name)
+ }
+}
+
+impl Eq for IRecordTypeClosed<'_> {}
+
+impl std::hash::Hash for IRecordTypeClosed<'_> {
+ fn hash(&self, state: &mut H) {
+ self.record_type.name.hash(state);
+ }
+}
+
+pub type LinkedModules<'r> = HashMap<&'r str, LinkedModule<'r>>;
+
+#[derive(Ord, PartialOrd, Eq, PartialEq, Hash)]
+pub struct UseDescription<'r> {
+ pub from: &'r str,
+ pub name: &'r str,
+}
+
+#[derive(PartialEq, Eq)]
+pub enum RecordEntry<'r> {
+ Use(UseDescription<'r>),
+ Declare(IRecordTypeClosed<'r>),
+}
+
+impl PartialOrd for RecordEntry<'_> {
+ fn partial_cmp(&self, other: &Self) -> Option {
+ Some(self.cmp(other))
+ }
+}
+
+impl Ord for RecordEntry<'_> {
+ fn cmp(&self, other: &Self) -> Ordering {
+ use RecordEntry::*;
+ match (self, other) {
+ (Use(_), Declare(_)) => Ordering::Less,
+ (Declare(_), Use(_)) => Ordering::Greater,
+ (Use(lhs), Use(rhs)) => lhs.cmp(rhs),
+ (Declare(lhs), Declare(rhs)) => lhs.record_type.name.cmp(&rhs.record_type.name),
+ }
+ }
+}
+
+#[derive(Default)]
+pub struct LinkedModule<'all> {
+ pub records: Vec>,
+}
diff --git a/crates/marine-test-macro-impl/src/marine_test/utils.rs b/crates/marine-test-macro-impl/src/marine_test/utils.rs
index f609cae..30eadfb 100644
--- a/crates/marine-test-macro-impl/src/marine_test/utils.rs
+++ b/crates/marine-test-macro-impl/src/marine_test/utils.rs
@@ -15,38 +15,18 @@
*/
use crate::TResult;
-use marine_it_parser::interface::MRecordTypes;
-use marine_it_parser::interface::it::IType;
+use marine_it_parser::it_interface::IRecordTypes;
+use marine_it_parser::it_interface::it::IType;
use proc_macro2::TokenStream;
use quote::quote;
-pub(super) fn generate_module_ident(module_name: &str) -> TResult {
- let generated_module_name = format!("__m_generated_{}", module_name);
- new_ident(&generated_module_name)
-}
-
-pub(super) fn generate_structs_module_ident(module_name: &str) -> TResult {
- let generated_module_name = format!("{}_structs", module_name);
- new_ident(&generated_module_name)
-}
-
-pub(super) fn generate_record_name(record_name: &str) -> TResult {
- let extended_record_name = record_name.to_string();
- new_ident(&extended_record_name)
-}
-
-pub(super) fn generate_struct_name(struct_name: &str) -> TResult {
- let extended_struct_name = format!("MGeneratedStruct{}", struct_name);
- new_ident(&extended_struct_name)
-}
-
pub(super) fn new_ident(ident_str: &str) -> TResult {
let ident_str = ident_str.replace('-', "_");
syn::parse_str::(&ident_str).map_err(Into::into)
}
-pub(super) fn itype_to_tokens(itype: &IType, records: &MRecordTypes) -> TResult {
+pub(super) fn itype_to_tokens(itype: &IType, records: &IRecordTypes) -> TResult {
let token_stream = match itype {
IType::Record(record_id) => {
let record = records
diff --git a/crates/marine-test-macro-impl/tests/generation_tests/empty_func/Config.toml b/crates/marine-test-macro-impl/tests/generation_tests/empty_func/Config.toml
new file mode 100644
index 0000000..2e740e3
--- /dev/null
+++ b/crates/marine-test-macro-impl/tests/generation_tests/empty_func/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/empty_func/artifacts/greeting.wasm b/crates/marine-test-macro-impl/tests/generation_tests/empty_func/artifacts/greeting.wasm
new file mode 100755
index 0000000..20cd5a2
Binary files /dev/null and b/crates/marine-test-macro-impl/tests/generation_tests/empty_func/artifacts/greeting.wasm differ
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
new file mode 100644
index 0000000..e48e13b
--- /dev/null
+++ b/crates/marine-test-macro-impl/tests/generation_tests/empty_func/expanded.rs
@@ -0,0 +1,128 @@
+#[test]
+fn empty_string() {
+ pub mod marine_test_env {
+ 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, >,
+ }
+ impl ModuleInterface {
+ pub fn new(
+ marine: std::rc::Rc<
+ std::cell::RefCell,>
+ ) -> Self {
+ Self { marine }
+ }
+ }
+ impl ModuleInterface {}
+ }
+ }
+ 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.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));
+ fn test_func() {
+ {}
+ }
+ test_func()
+}
diff --git a/crates/marine-test-macro-impl/tests/generation_tests/empty_func/marine_test.rs b/crates/marine-test-macro-impl/tests/generation_tests/empty_func/marine_test.rs
new file mode 100644
index 0000000..a8c58fd
--- /dev/null
+++ b/crates/marine-test-macro-impl/tests/generation_tests/empty_func/marine_test.rs
@@ -0,0 +1 @@
+fn empty_string() {}
diff --git a/crates/marine-test-macro-impl/tests/generation_tests/mounted_binary/Config.toml b/crates/marine-test-macro-impl/tests/generation_tests/mounted_binary/Config.toml
new file mode 100644
index 0000000..a2db194
--- /dev/null
+++ b/crates/marine-test-macro-impl/tests/generation_tests/mounted_binary/Config.toml
@@ -0,0 +1,8 @@
+modules_dir = "artifacts/"
+
+[[module]]
+ name = "greeting"
+ mem_pages_count = 1
+ logger_enabled = false
+ [module.mounted_binaries]
+ echo = "/usr/bin/curl"
diff --git a/crates/marine-test-macro-impl/tests/generation_tests/mounted_binary/artifacts/greeting.wasm b/crates/marine-test-macro-impl/tests/generation_tests/mounted_binary/artifacts/greeting.wasm
new file mode 100755
index 0000000..7f605b6
Binary files /dev/null and b/crates/marine-test-macro-impl/tests/generation_tests/mounted_binary/artifacts/greeting.wasm differ
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
new file mode 100644
index 0000000..4b23eb7
--- /dev/null
+++ b/crates/marine-test-macro-impl/tests/generation_tests/mounted_binary/expanded.rs
@@ -0,0 +1,167 @@
+#[test]
+fn test() {
+ pub mod marine_test_env {
+ 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, >,
+ }
+ impl ModuleInterface {
+ pub fn new(
+ marine: std::rc::Rc<
+ std::cell::RefCell,
+ >
+ ) -> 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
+ }
+ }
+ }
+ }
+ 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.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 mut greeting = marine_test_env::greeting::ModuleInterface::new(marine.clone());
+ fn test_func(greeting: marine_test_env::greeting::ModuleInterface) {
+ let mut greeting = greeting;
+ {
+ let _ = greeting.download("duckduckgo.com");
+ }
+ }
+ test_func(greeting,)
+}
diff --git a/crates/marine-test-macro-impl/tests/generation_tests/mounted_binary/marine_test.rs b/crates/marine-test-macro-impl/tests/generation_tests/mounted_binary/marine_test.rs
new file mode 100644
index 0000000..47bb39c
--- /dev/null
+++ b/crates/marine-test-macro-impl/tests/generation_tests/mounted_binary/marine_test.rs
@@ -0,0 +1,3 @@
+fn test(greeting: marine_test_env::greeting::ModuleInterface) {
+ let _ = greeting.download("duckduckgo.com");
+}
diff --git a/crates/marine-test-macro-impl/tests/generation_tests/multiple_modules/Config.toml b/crates/marine-test-macro-impl/tests/generation_tests/multiple_modules/Config.toml
new file mode 100644
index 0000000..3927911
--- /dev/null
+++ b/crates/marine-test-macro-impl/tests/generation_tests/multiple_modules/Config.toml
@@ -0,0 +1,10 @@
+modules_dir = "artifacts/"
+[[module]]
+ name = "greeting"
+ mem_pages_count = 1
+ logger_enabled = false
+
+[[module]]
+ name = "call_parameters"
+ mem_pages_count = 1
+ logger_enabled = false
diff --git a/crates/marine-test-macro-impl/tests/generation_tests/multiple_modules/artifacts/call_parameters.wasm b/crates/marine-test-macro-impl/tests/generation_tests/multiple_modules/artifacts/call_parameters.wasm
new file mode 100755
index 0000000..27ec9a7
Binary files /dev/null and b/crates/marine-test-macro-impl/tests/generation_tests/multiple_modules/artifacts/call_parameters.wasm differ
diff --git a/crates/marine-test-macro-impl/tests/generation_tests/multiple_modules/artifacts/greeting.wasm b/crates/marine-test-macro-impl/tests/generation_tests/multiple_modules/artifacts/greeting.wasm
new file mode 100755
index 0000000..cb54970
Binary files /dev/null and b/crates/marine-test-macro-impl/tests/generation_tests/multiple_modules/artifacts/greeting.wasm differ
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
new file mode 100644
index 0000000..7c0a886
--- /dev/null
+++ b/crates/marine-test-macro-impl/tests/generation_tests/multiple_modules/expanded.rs
@@ -0,0 +1,321 @@
+#[test]
+fn empty_string() {
+ pub mod marine_test_env {
+ 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, >,
+ }
+ impl ModuleInterface {
+ pub fn new(
+ marine: std::rc::Rc<
+ std::cell::RefCell,
+ >
+ ) -> Self {
+ Self { marine }
+ }
+ }
+ 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
+ .as_ref()
+ .borrow_mut()
+ .call_module("greeting", "greeting", 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 greeting_cp(
+ &mut self,
+ 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
+ .as_ref()
+ .borrow_mut()
+ .call_module("greeting", "greeting", 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 call_parameters {
+ pub use super::greeting::CallParameters;
+ pub use super::greeting::SecurityTetraplet;
+ 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 fn call_parameters(&mut self, ) -> String {
+ use std::ops::DerefMut;
+ let arguments = marine_rs_sdk_test::internal::serde_json::json!([]);
+ let result = self
+ .marine
+ .as_ref()
+ .borrow_mut()
+ .call_module(
+ "call_parameters",
+ "call_parameters",
+ 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 call_parameters_cp(
+ &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
+ .as_ref()
+ .borrow_mut()
+ .call_module("call_parameters", "call_parameters", 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 fn return_string(&mut self,) -> String {
+ use std::ops::DerefMut;
+ let arguments = marine_rs_sdk_test::internal::serde_json::json!([]);
+ let result = self
+ .marine
+ .as_ref()
+ .borrow_mut()
+ .call_module(
+ "call_parameters",
+ "return_string",
+ 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 return_string_cp(
+ &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
+ .as_ref()
+ .borrow_mut()
+ .call_module("call_parameters", "return_string", 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 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
+ .as_ref()
+ .borrow_mut()
+ .call_module(
+ "call_parameters",
+ "test_array_refs",
+ arguments,
+ <_>::default()
+ )
+ .expect("call to Marine failed");
+ let result: Vec =
+ marine_rs_sdk_test::internal::serde_json::from_value(result)
+ .expect("the default deserializer shouldn't fail");
+ result
+ }
+ pub fn test_array_refs_cp(
+ &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
+ .as_ref()
+ .borrow_mut()
+ .call_module("call_parameters", "test_array_refs", arguments, cp)
+ .expect("call to Marine failed");
+ let result: Vec =
+ marine_rs_sdk_test::internal::serde_json::from_value(result)
+ .expect("the default deserializer shouldn't fail");
+ result
+ }
+ }
+ }
+ }
+ 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.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 mut greeting_m = marine_test_env::greeting::ModuleInterface::new(marine.clone());
+ let mut call_parameters_m =
+ marine_test_env::call_parameters::ModuleInterface::new(marine.clone());
+ fn test_func(
+ greeting_m: marine_test_env::greeting::ModuleInterface,
+ call_parameters_m: marine_test_env::call_parameters::ModuleInterface
+ ) {
+ let mut greeting_m = greeting_m;
+ let mut call_parameters_m = call_parameters_m;
+ {
+ let init_peer_id = "init_peer_id";
+ let service_id = "service_id";
+ let service_creator_peer_id = "service_creator_peer_id";
+ let host_id = "host_id";
+ let particle_id = "particle_id";
+ let greeting = greeting_m.greeting("asd");
+ let mut tetraplet = SecurityTetraplet::default();
+ tetraplet.function_name = "some_func_name".to_string();
+ tetraplet.json_path = "some_json_path".to_string();
+ let tetraplets = vec![vec![tetraplet]];
+ let cp = CallParameters {
+ init_peer_id: init_peer_id.to_string(),
+ service_id: service_id.to_string(),
+ service_creator_peer_id: service_creator_peer_id.to_string(),
+ host_id: host_id.to_string(),
+ particle_id: particle_id.to_string(),
+ tetraplets: tetraplets.clone(),
+ };
+ let actual = call_parameters_m.call_parameters_cp(cp);
+ let expected = format!(
+ "{}\n{}\n{}\n{}\n{}\n{:?}",
+ init_peer_id, service_id, service_creator_peer_id, host_id, particle_id, tetraplets
+ );
+ assert_eq!(actual, expected);
+ }
+ }
+ test_func(greeting_m, call_parameters_m, )
+}
diff --git a/crates/marine-test-macro-impl/tests/generation_tests/multiple_modules/marine_test.rs b/crates/marine-test-macro-impl/tests/generation_tests/multiple_modules/marine_test.rs
new file mode 100644
index 0000000..07af15e
--- /dev/null
+++ b/crates/marine-test-macro-impl/tests/generation_tests/multiple_modules/marine_test.rs
@@ -0,0 +1,29 @@
+fn empty_string(greeting_m: marine_test_env::greeting::ModuleInterface, call_parameters_m: marine_test_env::call_parameters::ModuleInterface) {
+ let init_peer_id = "init_peer_id";
+ let service_id = "service_id";
+ let service_creator_peer_id = "service_creator_peer_id";
+ let host_id = "host_id";
+ let particle_id = "particle_id";
+
+ let greeting = greeting_m.greeting("asd");
+ let mut tetraplet = SecurityTetraplet::default();
+ tetraplet.function_name = "some_func_name".to_string();
+ tetraplet.json_path = "some_json_path".to_string();
+ let tetraplets = vec![vec![tetraplet]];
+
+ let cp = CallParameters {
+ init_peer_id: init_peer_id.to_string(),
+ service_id: service_id.to_string(),
+ service_creator_peer_id: service_creator_peer_id.to_string(),
+ host_id: host_id.to_string(),
+ particle_id: particle_id.to_string(),
+ tetraplets: tetraplets.clone(),
+ };
+
+ let actual = call_parameters_m.call_parameters_cp(cp);
+ let expected = format!(
+ "{}\n{}\n{}\n{}\n{}\n{:?}",
+ init_peer_id, service_id, service_creator_peer_id, host_id, particle_id, tetraplets
+ );
+ assert_eq!(actual, expected);
+}
diff --git a/crates/marine-test-macro-impl/tests/generation_tests_runner.rs b/crates/marine-test-macro-impl/tests/generation_tests_runner.rs
new file mode 100644
index 0000000..e10d6c1
--- /dev/null
+++ b/crates/marine-test-macro-impl/tests/generation_tests_runner.rs
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2021 Fluence Labs Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+mod utils;
+
+use utils::test_marine_test_token_streams;
+
+#[test]
+fn test_empty_func() {
+ assert!(test_marine_test_token_streams(
+ "tests/generation_tests/empty_func/marine_test.rs",
+ "tests/generation_tests/empty_func/expanded.rs",
+ "Config.toml",
+ "artifacts"
+ ));
+}
+
+#[test]
+fn test_mounted_binary() {
+ assert!(test_marine_test_token_streams(
+ "tests/generation_tests/mounted_binary/marine_test.rs",
+ "tests/generation_tests/mounted_binary/expanded.rs",
+ "Config.toml",
+ "artifacts"
+ ));
+}
+
+#[test]
+fn test_multiple_modules() {
+ assert!(test_marine_test_token_streams(
+ "tests/generation_tests/multiple_modules/marine_test.rs",
+ "tests/generation_tests/multiple_modules/expanded.rs",
+ "Config.toml",
+ "artifacts"
+ ));
+}
diff --git a/crates/marine-test-macro-impl/tests/utils.rs b/crates/marine-test-macro-impl/tests/utils.rs
new file mode 100644
index 0000000..68a3384
--- /dev/null
+++ b/crates/marine-test-macro-impl/tests/utils.rs
@@ -0,0 +1,48 @@
+/*
+ * 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 marine_test_macro_impl::marine_test_impl;
+
+use marine_macro_testing_utils::{items_from_file, stream_from_file, to_syn_item};
+
+use std::path::Path;
+
+pub fn test_marine_test_token_streams(
+ marine_path: FP,
+ expanded_path: EP,
+ config_path: &str,
+ modules_dir: &str,
+) -> bool
+where
+ FP: AsRef,
+ EP: AsRef,
+{
+ 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 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
+}
diff --git a/crates/marine-test-macro/Cargo.toml b/crates/marine-test-macro/Cargo.toml
index 2ac2829..0d51a4f 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.1.11" # remember to update html_root_url
+version = "0.2.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.1.11" }
+marine-test-macro-impl = { path = "../marine-test-macro-impl", version = "=0.2.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 39de54f..754d3ac 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.1.11")]
+#![doc(html_root_url = "https://docs.rs/sdk-test-macro/0.2.0")]
#![deny(
dead_code,
nonstandard_style,
@@ -36,7 +36,7 @@ use syn::spanned::Spanned;
/// This macro allows user to write tests for services in the following form:
///```rust
/// #[marine_test(config = "/path/to/Config.toml", modules_dir = "path/to/service/modules")]
-/// fn test() {
+/// fn test(greeting: marine_test_env::greeting::ModuleInterface) {
/// let service_result = greeting.greeting("John".to_string());
/// assert_eq!(&service_result, "Hi, name!");
/// }
diff --git a/sdk-test/Cargo.toml b/sdk-test/Cargo.toml
index b77da26..b0a92d2 100644
--- a/sdk-test/Cargo.toml
+++ b/sdk-test/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "marine-rs-sdk-test"
-version = "0.1.11" # remember to update html_root_url
+version = "0.2.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/tree/master/fluence-test"
@@ -17,8 +17,11 @@ all-features = true
path = "src/lib.rs"
doctest = false
+[dev-dependencies]
+trybuild = "1.0"
+
[dependencies]
-marine-test-macro = { path = "../crates/marine-test-macro", version = "=0.1.11" }
+marine-test-macro = { path = "../crates/marine-test-macro", version = "=0.2.0" }
fluence-app-service = { version = "0.9.0", features = ["raw-module-api"] }
serde = { version = "1.0.118", features = ["derive"] }
diff --git a/sdk-test/src/lib.rs b/sdk-test/src/lib.rs
index 2bbd124..4a0b6dc 100644
--- a/sdk-test/src/lib.rs
+++ b/sdk-test/src/lib.rs
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#![doc(html_root_url = "https://docs.rs/sdk-test/0.1.11")]
+#![doc(html_root_url = "https://docs.rs/sdk-test/0.2.0")]
#![deny(
dead_code,
nonstandard_style,