mirror of
https://github.com/fluencelabs/marine-rs-sdk-test
synced 2024-12-04 15:20:18 +00:00
Pass module interfaces as args in marine-test macro (#54)
This commit is contained in:
parent
84d5c2af66
commit
2ee2cf3a2c
130
Cargo.lock
generated
130
Cargo.lock
generated
@ -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"
|
||||
|
21
crates/macro-testing-utils/Cargo.toml
Normal file
21
crates/macro-testing-utils/Cargo.toml
Normal file
@ -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'] }
|
44
crates/macro-testing-utils/src/lib.rs
Normal file
44
crates/macro-testing-utils/src/lib.rs
Normal file
@ -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<P>(path: P) -> proc_macro2::TokenStream
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let items = items_from_file(path);
|
||||
quote::quote! { #(#items)* }
|
||||
}
|
||||
|
||||
pub fn items_from_file<P>(path: P) -> Vec<syn::Item>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
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<syn::Item> {
|
||||
let file: syn::File = syn::parse2(token_stream).expect("token stream should be parsed");
|
||||
file.items
|
||||
}
|
@ -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"}
|
||||
|
@ -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<FP, EP>(marine_path: FP, expanded_path: EP) -> bool
|
||||
@ -34,29 +35,3 @@ where
|
||||
|
||||
marine_item == expanded_item
|
||||
}
|
||||
|
||||
fn stream_from_file<P>(path: P) -> proc_macro2::TokenStream
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let items = items_from_file(path);
|
||||
quote::quote! { #(#items)* }
|
||||
}
|
||||
|
||||
fn items_from_file<P>(path: P) -> Vec<syn::Item>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
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<syn::Item> {
|
||||
let file: syn::File = syn::parse2(token_stream).expect("token stream should be parsed");
|
||||
file.items
|
||||
}
|
||||
|
@ -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"}
|
||||
|
@ -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)]
|
||||
|
@ -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::<Result<Vec<_>, _>>()
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
@ -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<T
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
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<T
|
||||
Ok(service_ctor)
|
||||
}
|
||||
|
||||
fn generate_module_ctors<'n>(
|
||||
module_names: impl ExactSizeIterator<Item = &'n str>,
|
||||
fn generate_module_ctors<'inputs>(
|
||||
inputs: impl Iterator<Item = &'inputs FnArg>,
|
||||
) -> TResult<Vec<TokenStream>> {
|
||||
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::<TResult<_>>()
|
||||
}
|
||||
|
||||
fn generate_arg_names<'inputs>(
|
||||
inputs: impl Iterator<Item = &'inputs FnArg>,
|
||||
) -> TResult<Vec<TokenStream>> {
|
||||
inputs
|
||||
.map(|x| -> TResult<_> {
|
||||
match x {
|
||||
FnArg::Receiver(_) => Err(TestGeneratorError::UnexpectedSelf),
|
||||
FnArg::Typed(x) => Ok(x.pat.to_token_stream()),
|
||||
}
|
||||
})
|
||||
.collect::<TResult<_>>()
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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<Item = &'i Module<'i>>,
|
||||
linked_modules: &'i LinkedModules<'_>,
|
||||
) -> TResult<Vec<TokenStream>> {
|
||||
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::<TResult<Vec<_>>>()
|
||||
}
|
||||
|
||||
fn generate_module_definition(module: &Module<'_>) -> TResult<TokenStream> {
|
||||
fn generate_module_definition(
|
||||
module: &Module<'_>,
|
||||
linked_module: &'_ LinkedModule<'_>,
|
||||
) -> TResult<TokenStream> {
|
||||
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<TokenStream> {
|
||||
|
||||
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<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>, >,
|
||||
}
|
||||
|
||||
pub struct #struct_ident {
|
||||
marine: std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>>,
|
||||
impl #struct_ident {
|
||||
pub fn new(marine: std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>, >) -> Self {
|
||||
Self { marine }
|
||||
}
|
||||
}
|
||||
|
||||
impl #struct_ident {
|
||||
pub fn new(marine: std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>>) -> Self {
|
||||
Self { marine }
|
||||
}
|
||||
}
|
||||
|
||||
impl #struct_ident {
|
||||
#(#module_functions)*
|
||||
}
|
||||
impl #struct_ident {
|
||||
#(#module_functions)*
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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<Item = &'m MFunctionSignature>,
|
||||
records: &'r MRecordTypes,
|
||||
method_signatures: impl ExactSizeIterator<Item = &'m IFunctionSignature>,
|
||||
records: &'r IRecordTypes,
|
||||
) -> TResult<Vec<proc_macro2::TokenStream>> {
|
||||
use CallParametersSettings::*;
|
||||
|
||||
let methods_count = 2 * method_signatures.len();
|
||||
method_signatures.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)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -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<TokenStream> {
|
||||
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<TokenStream> {
|
||||
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<TokenStream> {
|
||||
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<Item = &'a IFunctionArg>,
|
||||
records: &'r MRecordTypes,
|
||||
records: &'r IRecordTypes,
|
||||
) -> TResult<Vec<TokenStream>> {
|
||||
arguments
|
||||
.map(|argument| -> TResult<_> {
|
||||
@ -170,7 +170,7 @@ fn generate_arguments<'a, 'r>(
|
||||
.collect::<TResult<Vec<_>>>()
|
||||
}
|
||||
|
||||
fn generate_output_type(output_types: &[IType], records: &MRecordTypes) -> TResult<TokenStream> {
|
||||
fn generate_output_type(output_types: &[IType], records: &IRecordTypes) -> TResult<TokenStream> {
|
||||
let output_type = get_output_type(output_types)?;
|
||||
match output_type {
|
||||
None => Ok(TokenStream::new()),
|
||||
|
@ -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<Vec<TokenStream>> {
|
||||
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<Vec<TokenStream>> {
|
||||
linked_module.records
|
||||
.iter()
|
||||
.sorted()
|
||||
.map(|record| -> TResult<_> {
|
||||
use RecordEntry::*;
|
||||
match record {
|
||||
Use(use_info) => {
|
||||
let from_module_ident = utils::new_ident(use_info.from)?;
|
||||
let record_name_ident = utils::new_ident(use_info.name)?;
|
||||
Ok(quote! {pub use super::#from_module_ident::#record_name_ident;})
|
||||
},
|
||||
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::<TResult<Vec<_>>>()
|
||||
})
|
||||
.collect::<TResult<Vec<_>>>()
|
||||
}
|
||||
|
||||
fn prepare_field<'f>(
|
||||
fields: impl ExactSizeIterator<Item = &'f IRecordFieldType>,
|
||||
records: &MRecordTypes,
|
||||
records: &IRecordTypes,
|
||||
) -> TResult<Vec<TokenStream>> {
|
||||
fields
|
||||
.map(|field| -> TResult<_> {
|
||||
|
198
crates/marine-test-macro-impl/src/marine_test/modules_linker.rs
Normal file
198
crates/marine-test-macro-impl/src/marine_test/modules_linker.rs
Normal file
@ -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<LinkedModules<'modules>> {
|
||||
let mut all_record_types = HashMap::<IRecordTypeClosed<'_>, &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<IRecordType>,
|
||||
pub records: &'r IRecordTypes,
|
||||
}
|
||||
|
||||
impl<'r> IRecordTypeClosed<'r> {
|
||||
fn new(record_type: Rc<IRecordType>, 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<Ordering> {
|
||||
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<H: Hasher>(&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<Ordering> {
|
||||
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<RecordEntry<'all>>,
|
||||
}
|
@ -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<syn::Ident> {
|
||||
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<syn::Ident> {
|
||||
let generated_module_name = format!("{}_structs", module_name);
|
||||
new_ident(&generated_module_name)
|
||||
}
|
||||
|
||||
pub(super) fn generate_record_name(record_name: &str) -> TResult<syn::Ident> {
|
||||
let extended_record_name = record_name.to_string();
|
||||
new_ident(&extended_record_name)
|
||||
}
|
||||
|
||||
pub(super) fn generate_struct_name(struct_name: &str) -> TResult<syn::Ident> {
|
||||
let extended_struct_name = format!("MGeneratedStruct{}", struct_name);
|
||||
new_ident(&extended_struct_name)
|
||||
}
|
||||
|
||||
pub(super) fn new_ident(ident_str: &str) -> TResult<syn::Ident> {
|
||||
let ident_str = ident_str.replace('-', "_");
|
||||
syn::parse_str::<syn::Ident>(&ident_str).map_err(Into::into)
|
||||
}
|
||||
|
||||
pub(super) fn itype_to_tokens(itype: &IType, records: &MRecordTypes) -> TResult<TokenStream> {
|
||||
pub(super) fn itype_to_tokens(itype: &IType, records: &IRecordTypes) -> TResult<TokenStream> {
|
||||
let token_stream = match itype {
|
||||
IType::Record(record_id) => {
|
||||
let record = records
|
||||
|
@ -0,0 +1,6 @@
|
||||
modules_dir = "artifacts/"
|
||||
|
||||
[[module]]
|
||||
name = "greeting"
|
||||
mem_pages_count = 1
|
||||
logger_enabled = false
|
Binary file not shown.
@ -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<Vec<SecurityTetraplet>>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: Vec<u8>,
|
||||
pub stderr: Vec<u8>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryStringResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: String,
|
||||
pub stderr: String
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct SecurityTetraplet {
|
||||
pub peer_pk: String,
|
||||
pub service_id: String,
|
||||
pub function_name: String,
|
||||
pub json_path: String
|
||||
}
|
||||
pub struct ModuleInterface {
|
||||
marine:
|
||||
std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>, >,
|
||||
}
|
||||
impl ModuleInterface {
|
||||
pub fn new(
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,>
|
||||
) -> Self {
|
||||
Self { marine }
|
||||
}
|
||||
}
|
||||
impl ModuleInterface {}
|
||||
}
|
||||
}
|
||||
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()
|
||||
}
|
@ -0,0 +1 @@
|
||||
fn empty_string() {}
|
@ -0,0 +1,8 @@
|
||||
modules_dir = "artifacts/"
|
||||
|
||||
[[module]]
|
||||
name = "greeting"
|
||||
mem_pages_count = 1
|
||||
logger_enabled = false
|
||||
[module.mounted_binaries]
|
||||
echo = "/usr/bin/curl"
|
Binary file not shown.
@ -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<Vec<SecurityTetraplet>>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: Vec<u8>,
|
||||
pub stderr: Vec<u8>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryStringResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: String,
|
||||
pub stderr: String
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct SecurityTetraplet {
|
||||
pub peer_pk: String,
|
||||
pub service_id: String,
|
||||
pub function_name: String,
|
||||
pub json_path: String
|
||||
}
|
||||
pub struct ModuleInterface {
|
||||
marine:
|
||||
std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>, >,
|
||||
}
|
||||
impl ModuleInterface {
|
||||
pub fn new(
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>
|
||||
) -> Self {
|
||||
Self { marine }
|
||||
}
|
||||
}
|
||||
impl ModuleInterface {
|
||||
pub fn download(&mut self, url: String) -> String {
|
||||
use std::ops::DerefMut;
|
||||
let arguments = marine_rs_sdk_test::internal::serde_json::json!([url]);
|
||||
let result = self
|
||||
.marine
|
||||
.as_ref()
|
||||
.borrow_mut()
|
||||
.call_module("greeting", "download", arguments, <_>::default())
|
||||
.expect("call to Marine failed");
|
||||
let result: String =
|
||||
marine_rs_sdk_test::internal::serde_json::from_value(result)
|
||||
.expect("the default deserializer shouldn't fail");
|
||||
result
|
||||
}
|
||||
pub fn download_cp(
|
||||
&mut self,
|
||||
url: String,
|
||||
cp: marine_rs_sdk_test::CallParameters
|
||||
) -> String {
|
||||
use std::ops::DerefMut;
|
||||
let arguments = marine_rs_sdk_test::internal::serde_json::json!([url]);
|
||||
let result = self
|
||||
.marine
|
||||
.as_ref()
|
||||
.borrow_mut()
|
||||
.call_module("greeting", "download", arguments, cp)
|
||||
.expect("call to Marine failed");
|
||||
let result: String =
|
||||
marine_rs_sdk_test::internal::serde_json::from_value(result)
|
||||
.expect("the default deserializer shouldn't fail");
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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,)
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fn test(greeting: marine_test_env::greeting::ModuleInterface) {
|
||||
let _ = greeting.download("duckduckgo.com");
|
||||
}
|
@ -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
|
Binary file not shown.
Binary file not shown.
@ -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<Vec<SecurityTetraplet>>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: Vec<u8>,
|
||||
pub stderr: Vec<u8>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryStringResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: String,
|
||||
pub stderr: String
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct SecurityTetraplet {
|
||||
pub peer_pk: String,
|
||||
pub service_id: String,
|
||||
pub function_name: String,
|
||||
pub json_path: String
|
||||
}
|
||||
pub struct ModuleInterface {
|
||||
marine: std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>, >,
|
||||
}
|
||||
impl ModuleInterface {
|
||||
pub fn new(
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>
|
||||
) -> Self {
|
||||
Self { marine }
|
||||
}
|
||||
}
|
||||
impl ModuleInterface {
|
||||
pub fn 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<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>, >,
|
||||
}
|
||||
impl ModuleInterface {
|
||||
pub fn new(
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>
|
||||
) -> Self {
|
||||
Self { marine }
|
||||
}
|
||||
}
|
||||
impl ModuleInterface {
|
||||
pub fn 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<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",
|
||||
"test_array_refs",
|
||||
arguments,
|
||||
<_>::default()
|
||||
)
|
||||
.expect("call to Marine failed");
|
||||
let result: Vec<String> =
|
||||
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<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", "test_array_refs", arguments, cp)
|
||||
.expect("call to Marine failed");
|
||||
let result: Vec<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_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, )
|
||||
}
|
@ -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);
|
||||
}
|
@ -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"
|
||||
));
|
||||
}
|
48
crates/marine-test-macro-impl/tests/utils.rs
Normal file
48
crates/marine-test-macro-impl/tests/utils.rs
Normal file
@ -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<FP, EP>(
|
||||
marine_path: FP,
|
||||
expanded_path: EP,
|
||||
config_path: &str,
|
||||
modules_dir: &str,
|
||||
) -> bool
|
||||
where
|
||||
FP: AsRef<Path>,
|
||||
EP: AsRef<Path>,
|
||||
{
|
||||
let marine_item = stream_from_file(&marine_path);
|
||||
let test_token_stream = quote::quote! { #marine_item };
|
||||
let buf = marine_path.as_ref().to_path_buf();
|
||||
let 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
|
||||
}
|
@ -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"
|
||||
|
@ -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!");
|
||||
/// }
|
||||
|
@ -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"] }
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user