mirror of
https://github.com/fluencelabs/marine-rs-sdk
synced 2025-03-15 14:30:48 +00:00
Remove test sdk (#67)
This commit is contained in:
parent
13c0f59d89
commit
2bd0c63a93
@ -18,11 +18,10 @@ jobs:
|
||||
rustup target add wasm32-wasi
|
||||
rustup component add rustfmt
|
||||
rustup component add clippy
|
||||
cargo fmt --all -- --check --color always
|
||||
|
||||
(cd sdk; cargo build -v --target wasm32-wasi --all-features)
|
||||
(cd sdk; cargo clippy -v --target wasm32-wasi)
|
||||
(cd sdk-test; cargo build)
|
||||
cargo fmt --all -- --check --color always
|
||||
cargo build -v --target wasm32-wasi --all-features
|
||||
cargo clippy -v --target wasm32-wasi
|
||||
(cd crates/marine-macro-impl; cargo test)
|
||||
|
||||
TARGET=wasm32-wasi cargo test -v --all-features
|
||||
|
1419
Cargo.lock
generated
1419
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
50
Cargo.toml
50
Cargo.toml
@ -1,11 +1,43 @@
|
||||
[package]
|
||||
name = "marine-rs-sdk"
|
||||
version = "0.6.14" # remember to update html_root_url
|
||||
description = "Fluence backend SDK for developing backend applications for the Fluence network"
|
||||
documentation = "https://docs.rs/fluence"
|
||||
repository = "https://github.com/fluencelabs/marine-rs-sdk"
|
||||
authors = ["Fluence Labs"]
|
||||
keywords = ["fluence", "marine", "sdk", "webassembly"]
|
||||
categories = ["api-bindings", "wasm"]
|
||||
license = "Apache-2.0"
|
||||
edition = "2018"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
[lib]
|
||||
path = "src/lib.rs"
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
marine-macro = { path = "crates/marine-macro", version = "=0.6.14" }
|
||||
marine-rs-sdk-main = { path = "crates/main", version = "=0.6.14" }
|
||||
marine-timestamp-macro = { path = "crates/timestamp-macro", version = "=0.6.14" }
|
||||
|
||||
serde = { version = "1.0.118", features = ["derive"]}
|
||||
|
||||
[dev-dependencies]
|
||||
trybuild = "1.0"
|
||||
|
||||
[features]
|
||||
# Print some internal logs by log_utf8_string
|
||||
debug = ["marine-rs-sdk-main/debug"]
|
||||
|
||||
# Enable logger (this will cause log_utf8_string to appear in imports)
|
||||
logger = ["marine-rs-sdk-main/logger"]
|
||||
|
||||
[workspace]
|
||||
members = [
|
||||
"crates/main",
|
||||
"crates/marine-macro",
|
||||
"crates/marine-macro-impl",
|
||||
"crates/marine-test-macro",
|
||||
"crates/marine-test-macro-impl",
|
||||
"crates/timestamp-macro",
|
||||
"sdk",
|
||||
"sdk-test"
|
||||
]
|
||||
"crates/main",
|
||||
"crates/marine-macro",
|
||||
"crates/marine-macro-impl",
|
||||
"crates/timestamp-macro",
|
||||
]
|
||||
|
@ -1,4 +1,4 @@
|
||||

|
||||
[](https://crates.io/crates/marine-rs-sdk)
|
||||
|
||||
## Marine Rust SDK
|
||||
|
||||
|
@ -1,29 +0,0 @@
|
||||
[package]
|
||||
name = "marine-test-macro-impl"
|
||||
version = "0.3.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"
|
||||
repository = "https://github.com/fluencelabs/marine-rs-sdk/tree/master/crates/marine-test-macro-impl"
|
||||
authors = ["Fluence Labs"]
|
||||
keywords = ["fluence", "marine", "sdk", "webassembly", "procedural_macros"]
|
||||
categories = ["api-bindings", "wasm", "development-tools::testing"]
|
||||
license = "Apache-2.0"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
[dependencies]
|
||||
fluence-app-service = { version = "0.9.0", features = ["raw-module-api"] }
|
||||
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"}
|
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use darling::FromMeta;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Describes attributes of `marine_test` macro.
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) enum MTestAttributes {
|
||||
SingleService(ServiceDescription),
|
||||
MultipleServices(HashMap<String, ServiceDescription>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, FromMeta)]
|
||||
pub(crate) struct ServiceDescription {
|
||||
/// Path to a config file of a tested service.
|
||||
pub(crate) config_path: String,
|
||||
|
||||
/// Path to compiled modules of a service.
|
||||
#[darling(default)]
|
||||
pub(crate) modules_dir: Option<String>,
|
||||
}
|
||||
|
||||
impl FromMeta for MTestAttributes {
|
||||
fn from_list(items: &[syn::NestedMeta]) -> darling::Result<Self> {
|
||||
let single_service = ServiceDescription::from_list(items);
|
||||
let multiple_services = HashMap::<String, ServiceDescription>::from_list(items);
|
||||
match (single_service, multiple_services) {
|
||||
(Ok(modules), Err(_)) => Ok(Self::SingleService(modules)),
|
||||
(Err(_), Ok(services)) if !services.is_empty() => Ok(Self::MultipleServices(services)),
|
||||
(Err(_), Ok(_)) => Err(darling::Error::custom(
|
||||
r#"Need to specify "config_path" and "modules_dir" or several named services with these fields "#,
|
||||
)),
|
||||
(Err(error_single), Err(error_multiple)) => Err(darling::error::Error::multiple(vec![
|
||||
error_single,
|
||||
error_multiple,
|
||||
])),
|
||||
(Ok(_), Ok(_)) => Err(darling::Error::custom(
|
||||
"internal sdk error: marine_test attributes are ambiguous",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use marine_it_parser::ITParserError;
|
||||
use fluence_app_service::AppServiceError;
|
||||
|
||||
use darling::Error as DarlingError;
|
||||
use syn::Error as SynError;
|
||||
use thiserror::Error as ThisError;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum TestGeneratorError {
|
||||
#[error("Can't load Wasm modules into Marine: {0}")]
|
||||
ITParserError(#[from] ITParserError),
|
||||
|
||||
#[error("{0}")]
|
||||
CorruptedITSection(#[from] CorruptedITSection),
|
||||
|
||||
#[error("{0}")]
|
||||
SynError(#[from] SynError),
|
||||
|
||||
#[error("Can't load Wasm modules from the provided config: {0}")]
|
||||
ConfigLoadError(#[from] AppServiceError),
|
||||
|
||||
#[error("{0}")]
|
||||
AttributesError(#[from] DarlingError),
|
||||
|
||||
#[error(
|
||||
"neither modules_dir attribute specified nor service config contains modules_dir, please specify one of them"
|
||||
)]
|
||||
ModulesDirUnspecified,
|
||||
|
||||
#[error("a Wasm file compiled with newer version of sdk that supports multi-value")]
|
||||
ManyFnOutputsUnsupported,
|
||||
|
||||
#[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),
|
||||
|
||||
#[error("No modules loaded for a service")]
|
||||
NoModulesInService,
|
||||
}
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum CorruptedITSection {
|
||||
#[error("record with {0} is absent in embedded IT section")]
|
||||
AbsentRecord(u64),
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#![deny(
|
||||
dead_code,
|
||||
nonstandard_style,
|
||||
unused_imports,
|
||||
unused_mut,
|
||||
unused_variables,
|
||||
unused_unsafe,
|
||||
unreachable_patterns
|
||||
)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
#![recursion_limit = "1024"]
|
||||
|
||||
mod attributes;
|
||||
mod errors;
|
||||
mod marine_test;
|
||||
|
||||
pub use marine_test::marine_test_impl;
|
||||
pub use errors::TestGeneratorError;
|
||||
|
||||
pub(crate) type TResult<T> = std::result::Result<T, TestGeneratorError>;
|
@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::{TResult, TestGeneratorError};
|
||||
|
||||
use fluence_app_service::TomlAppServiceConfig;
|
||||
use marine_it_parser::module_it_interface;
|
||||
use marine_it_parser::it_interface::IModuleInterface;
|
||||
|
||||
use std::path::{PathBuf, Path};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub(super) struct Module<'m> {
|
||||
pub name: &'m str,
|
||||
pub interface: IModuleInterface,
|
||||
}
|
||||
|
||||
impl<'m> Module<'m> {
|
||||
fn new(name: &'m str, interface: IModuleInterface) -> Self {
|
||||
Self { name, interface }
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ConfigWrapper {
|
||||
pub config: TomlAppServiceConfig,
|
||||
pub resolved_modules_dir: PathBuf,
|
||||
}
|
||||
|
||||
pub(crate) fn load_config(
|
||||
config_path: &str,
|
||||
modules_dir: Option<String>,
|
||||
file_path: &Path,
|
||||
) -> TResult<ConfigWrapper> {
|
||||
let config_path_buf = file_path.join(&config_path);
|
||||
|
||||
let marine_config = TomlAppServiceConfig::load(&config_path_buf)?;
|
||||
let modules_dir = match resolve_modules_dir(&marine_config, modules_dir) {
|
||||
Some(modules_dir) => modules_dir,
|
||||
None => return Err(TestGeneratorError::ModulesDirUnspecified),
|
||||
};
|
||||
|
||||
Ok(ConfigWrapper {
|
||||
config: marine_config,
|
||||
resolved_modules_dir: modules_dir,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns all modules the provided config consists of.
|
||||
pub(super) fn collect_modules<'config>(
|
||||
config: &'config TomlAppServiceConfig,
|
||||
modules_dir: &Path,
|
||||
) -> TResult<Vec<Module<'config>>> {
|
||||
let module_paths = collect_module_paths(config, &modules_dir);
|
||||
|
||||
module_paths
|
||||
.into_iter()
|
||||
.map(|(name, path)| module_it_interface(path).map(|interface| Module::new(name, interface)))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
fn collect_module_paths<'config>(
|
||||
config: &'config TomlAppServiceConfig,
|
||||
modules_dir: &Path,
|
||||
) -> Vec<(&'config str, PathBuf)> {
|
||||
config
|
||||
.toml_faas_config
|
||||
.module
|
||||
.iter()
|
||||
.map(|m| {
|
||||
let module_file_name = m.file_name.as_ref().unwrap_or(&m.name);
|
||||
let module_file_name = PathBuf::from(module_file_name);
|
||||
// TODO: is it correct to always have .wasm extension?
|
||||
let module_path = modules_dir.join(module_file_name).with_extension("wasm");
|
||||
|
||||
(m.name.as_str(), module_path)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
/// Tries to determine a dir with compiled Wasm modules according to the following rules:
|
||||
/// - if the modules_dir attribute is specified (by user) it will be chosen,
|
||||
/// - otherwise if modules_dir is specified in AppService config it will be chosen,
|
||||
/// - otherwise None will be returned.
|
||||
pub(super) fn resolve_modules_dir(
|
||||
config: &TomlAppServiceConfig,
|
||||
modules_dir: Option<String>,
|
||||
) -> Option<PathBuf> {
|
||||
match modules_dir {
|
||||
Some(modules_dir) => Some(PathBuf::from(modules_dir)),
|
||||
None => config
|
||||
.toml_faas_config
|
||||
.modules_dir
|
||||
.as_ref()
|
||||
.map(PathBuf::from),
|
||||
}
|
||||
}
|
@ -1,245 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::attributes::{MTestAttributes, ServiceDescription};
|
||||
use crate::marine_test;
|
||||
use crate::marine_test::{config_utils, token_stream_generator};
|
||||
use crate::TestGeneratorError;
|
||||
use crate::TResult;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use quote::ToTokens;
|
||||
use syn::FnArg;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Generates glue code for tests.
|
||||
/// F.e. for this test for the greeting service
|
||||
///```ignore
|
||||
/// #[marine_test(
|
||||
/// config_path = "/path/to/service/config/Config.toml",
|
||||
/// modules_dir = "/path/to/modules/dir"
|
||||
/// )]
|
||||
/// fn test() {
|
||||
/// let result = greeting.greeting("John".to_string());
|
||||
/// assert_eq(result.as_str(), "Hi, John!");
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// the following glue code would be generated:
|
||||
///```ignore
|
||||
/// // (0)
|
||||
/// pub mod __m_generated_greeting {
|
||||
/// struct MGeneratedStructgreeting {
|
||||
/// marine: std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>>,
|
||||
/// }
|
||||
///
|
||||
/// impl MGeneratedStructgreeting {
|
||||
/// pub fn new(marine: std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>>) -> Self {
|
||||
/// Self { marine }
|
||||
/// }
|
||||
///
|
||||
/// 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_with_module_name("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
|
||||
/// }
|
||||
/// }
|
||||
///}
|
||||
/// // (1)
|
||||
/// 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 __m_generated_marine_config = marine_rs_sdk_test::internal::TomlAppServiceConfig::load("/path/to/greeting/Config.toml".to_string())
|
||||
/// .unwrap_or_else(|e| {
|
||||
/// panic!(
|
||||
/// "app service located at `{}` config can't be loaded: {}",
|
||||
/// "/path/to/greeting/Config.toml", e
|
||||
/// )
|
||||
/// });
|
||||
///
|
||||
/// __m_generated_marine_config.service_base_dir = Some("/path/to/tmp".to_string());
|
||||
///
|
||||
/// let marine = marine_rs_sdk_test::internal::AppService::new_with_empty_facade(
|
||||
/// __m_generated_marine_config,
|
||||
/// "3640e972-92e3-47cb-b95f-4e3c5bcf0f14",
|
||||
/// 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));
|
||||
///
|
||||
/// // (2)
|
||||
///
|
||||
/// let mut greeting = __m_generated_greeting::MGeneratedStructgreeting::new(marine);
|
||||
///
|
||||
/// // (3)
|
||||
///
|
||||
/// let result = greeting.greeting("John".to_string());
|
||||
/// assert_eq(result.as_str(), "Hi, John!");
|
||||
///
|
||||
/// // (4)
|
||||
///```
|
||||
///
|
||||
/// Example code above corresponds to the macro definition in the following way:
|
||||
/// [(0), (1)] - module_definitions*
|
||||
/// [(1), (2)] - app_service_ctor
|
||||
/// [(2), (3)] - module_ctors*
|
||||
/// [(3), (4)] - original_block
|
||||
pub(super) fn generate_test_glue_code(
|
||||
func_item: syn::ItemFn,
|
||||
attrs: MTestAttributes,
|
||||
test_file_path: PathBuf,
|
||||
) -> TResult<TokenStream> {
|
||||
match attrs {
|
||||
MTestAttributes::MultipleServices(services) => {
|
||||
generate_test_glue_code_multiple_services(func_item, services, test_file_path)
|
||||
}
|
||||
MTestAttributes::SingleService(service) => {
|
||||
generate_test_glue_code_single_service(func_item, service, test_file_path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_test_glue_code_single_service(
|
||||
func_item: syn::ItemFn,
|
||||
service: ServiceDescription,
|
||||
test_file_path: PathBuf,
|
||||
) -> TResult<TokenStream> {
|
||||
let config_wrapper =
|
||||
config_utils::load_config(&service.config_path, service.modules_dir, &test_file_path)?;
|
||||
let modules_dir_test_relative = test_file_path.join(&config_wrapper.resolved_modules_dir);
|
||||
let module_interfaces =
|
||||
config_utils::collect_modules(&config_wrapper.config, &modules_dir_test_relative)?;
|
||||
let linked_modules = marine_test::modules_linker::link_modules(
|
||||
module_interfaces
|
||||
.iter()
|
||||
.map(|module| (module.name, &module.interface)),
|
||||
)?;
|
||||
|
||||
let module_definitions = token_stream_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 app_service_ctor = token_stream_generator::generate_app_service_ctor(
|
||||
&service.config_path,
|
||||
&config_wrapper.resolved_modules_dir,
|
||||
)?;
|
||||
let glue_code = quote! {
|
||||
#[test]
|
||||
fn #name() {
|
||||
// definitions for wasm modules specified in config
|
||||
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)*
|
||||
|
||||
fn test_func(#inputs) {
|
||||
#(let mut #arg_names = #arg_names;)*
|
||||
// original test function as is
|
||||
#original_block
|
||||
}
|
||||
|
||||
test_func(#(#arg_names,)*)
|
||||
}
|
||||
};
|
||||
|
||||
Ok(glue_code)
|
||||
}
|
||||
|
||||
fn generate_test_glue_code_multiple_services(
|
||||
func_item: syn::ItemFn,
|
||||
services: HashMap<String, ServiceDescription>,
|
||||
test_file_path: PathBuf,
|
||||
) -> TResult<TokenStream> {
|
||||
let service_definitions =
|
||||
token_stream_generator::generate_service_definitions(services, &test_file_path)?;
|
||||
|
||||
let original_block = func_item.block;
|
||||
let signature = func_item.sig;
|
||||
let name = &signature.ident;
|
||||
let glue_code = quote! {
|
||||
#[test]
|
||||
fn #name() {
|
||||
// definitions for services specified in attributes
|
||||
pub mod marine_test_env {
|
||||
#(#service_definitions)*
|
||||
}
|
||||
|
||||
fn test_func() {
|
||||
#original_block
|
||||
}
|
||||
|
||||
test_func()
|
||||
}
|
||||
};
|
||||
|
||||
Ok(glue_code)
|
||||
}
|
||||
|
||||
fn generate_module_ctors<'inputs>(
|
||||
inputs: impl Iterator<Item = &'inputs FnArg>,
|
||||
) -> TResult<Vec<TokenStream>> {
|
||||
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<_>>()
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::attributes::MTestAttributes;
|
||||
use crate::TResult;
|
||||
use crate::marine_test::glue_code_generator::generate_test_glue_code;
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use darling::FromMeta;
|
||||
use syn::parse::Parser;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn marine_test_impl(
|
||||
attrs: TokenStream,
|
||||
input: TokenStream,
|
||||
file_path: PathBuf,
|
||||
) -> TResult<TokenStream> {
|
||||
// from https://github.com/dtolnay/syn/issues/788
|
||||
let parser = syn::punctuated::Punctuated::<syn::NestedMeta, syn::Token![,]>::parse_terminated;
|
||||
let attrs = parser.parse2(attrs)?;
|
||||
let attrs: Vec<syn::NestedMeta> = attrs.into_iter().collect();
|
||||
let attrs = MTestAttributes::from_list(&attrs)?;
|
||||
|
||||
let func_item = syn::parse2::<syn::ItemFn>(input)?;
|
||||
|
||||
generate_test_glue_code(func_item, attrs, file_path)
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
mod config_utils;
|
||||
mod marine_test_impl;
|
||||
mod glue_code_generator;
|
||||
mod token_stream_generator;
|
||||
mod utils;
|
||||
mod modules_linker;
|
||||
|
||||
pub use marine_test_impl::marine_test_impl;
|
@ -1,195 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::{TResult, TestGeneratorError};
|
||||
|
||||
use marine_it_parser::it_interface::{IRecordTypes, IModuleInterface};
|
||||
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: impl ExactSizeIterator<Item = (&'modules str, &'modules IModuleInterface)>,
|
||||
) -> TResult<LinkedModules<'modules>> {
|
||||
let mut all_record_types = HashMap::<IRecordTypeClosed<'_>, &str>::new();
|
||||
let mut linked_modules = HashMap::<&str, LinkedModule<'_>>::new();
|
||||
|
||||
for (name, interface) in modules {
|
||||
let mut linking_module = LinkedModule::default();
|
||||
for record_type in interface.record_types.values() {
|
||||
let record_type_ex =
|
||||
IRecordTypeClosed::new(record_type.clone(), &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(), name);
|
||||
RecordEntry::Declare(record_type_ex)
|
||||
}
|
||||
};
|
||||
|
||||
linking_module.records.push(entry);
|
||||
}
|
||||
|
||||
if linked_modules.insert(name, linking_module).is_some() {
|
||||
return Err(TestGeneratorError::DuplicateModuleName(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>>,
|
||||
}
|
@ -1,125 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
mod methods_generator;
|
||||
mod methods_generator_utils;
|
||||
mod record_type_generator;
|
||||
mod service_generator;
|
||||
mod service_generation_utils;
|
||||
|
||||
use crate::marine_test::config_utils::Module;
|
||||
use crate::marine_test::modules_linker::{LinkedModule, LinkedModules, UseDescription};
|
||||
use crate::marine_test::utils;
|
||||
use crate::TResult;
|
||||
|
||||
pub(super) use service_generator::generate_service_definitions;
|
||||
pub(super) use service_generation_utils::generate_app_service_ctor;
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use crate::marine_test::utils::new_ident;
|
||||
|
||||
/// Generates definitions of modules and records of this modules.
|
||||
/// F.e. for the greeting service the following definitions would be generated:
|
||||
///```ignore
|
||||
/// pub mod __m_generated_greeting {
|
||||
/// struct MGeneratedStructgreeting {
|
||||
/// marine: std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>>,
|
||||
/// }
|
||||
///
|
||||
/// impl MGeneratedStructgreeting {
|
||||
/// pub fn new(marine: std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>>) -> Self {
|
||||
/// Self { marine }
|
||||
/// }
|
||||
///
|
||||
/// 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_with_module_name("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(super) fn generate_module_definitions<'i>(
|
||||
modules: impl ExactSizeIterator<Item = &'i Module<'i>>,
|
||||
linked_modules: &'i LinkedModules<'_>,
|
||||
) -> TResult<Vec<TokenStream>> {
|
||||
modules
|
||||
.into_iter()
|
||||
.map(|value| {
|
||||
// linked_modules are built from modules, so unwrap is safe
|
||||
let content = generate_module_definition(
|
||||
value,
|
||||
linked_modules.get(&value.name).unwrap(),
|
||||
module_import_generator,
|
||||
)?;
|
||||
let module_ident = new_ident(&value.name)?;
|
||||
Ok(quote! {
|
||||
pub mod #module_ident {
|
||||
#content
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect::<TResult<Vec<_>>>()
|
||||
}
|
||||
|
||||
fn generate_module_definition(
|
||||
module: &Module<'_>,
|
||||
linked_module: &'_ LinkedModule<'_>,
|
||||
import_generator: fn(info: &UseDescription<'_>) -> TResult<TokenStream>,
|
||||
) -> TResult<TokenStream> {
|
||||
let struct_ident = utils::new_ident("ModuleInterface")?;
|
||||
let module_records = record_type_generator::generate_records(linked_module, import_generator)?;
|
||||
let module_functions = methods_generator::generate_module_methods(
|
||||
module.name,
|
||||
module.interface.function_signatures.iter(),
|
||||
&module.interface.record_types,
|
||||
)?;
|
||||
|
||||
let module_definition = quote! {
|
||||
#(#module_records)*
|
||||
|
||||
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 {
|
||||
#(#module_functions)*
|
||||
}
|
||||
};
|
||||
|
||||
Ok(module_definition)
|
||||
}
|
||||
|
||||
fn module_import_generator(info: &UseDescription<'_>) -> TResult<TokenStream> {
|
||||
let from_module_ident = utils::new_ident(info.from)?;
|
||||
let record_name_ident = utils::new_ident(info.name)?;
|
||||
Ok(quote! {pub use super::#from_module_ident::#record_name_ident;})
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* 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 super::methods_generator_utils::*;
|
||||
use crate::TResult;
|
||||
|
||||
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,
|
||||
method_signatures: impl ExactSizeIterator<Item = &'m IFunctionSignature>,
|
||||
records: &'r IRecordTypes,
|
||||
) -> TResult<Vec<proc_macro2::TokenStream>> {
|
||||
use CallParametersSettings::*;
|
||||
|
||||
let methods_count = 2 * method_signatures.len();
|
||||
method_signatures
|
||||
.sorted_by(|lhs, rhs| lhs.name.cmp(&rhs.name))
|
||||
.try_fold::<_, _, TResult<_>>(
|
||||
Vec::with_capacity(methods_count),
|
||||
|mut methods, signature| {
|
||||
let default_cp = generate_module_method(module_name, &signature, Default, records)?;
|
||||
let user_cp =
|
||||
generate_module_method(module_name, &signature, UserDefined, records)?;
|
||||
|
||||
methods.push(default_cp);
|
||||
methods.push(user_cp);
|
||||
|
||||
Ok(methods)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn generate_facade_methods<'m, 'r>(
|
||||
method_signatures: impl ExactSizeIterator<Item = &'m IFunctionSignature>,
|
||||
records: &'r IRecordTypes,
|
||||
) -> TResult<Vec<proc_macro2::TokenStream>> {
|
||||
use CallParametersSettings::*;
|
||||
|
||||
let methods_count = 2 * method_signatures.len();
|
||||
method_signatures
|
||||
.sorted_by(|lhs, rhs| lhs.name.cmp(&rhs.name))
|
||||
.try_fold::<_, _, TResult<_>>(
|
||||
Vec::with_capacity(methods_count),
|
||||
|mut methods, signature| {
|
||||
let default_cp = generate_module_method_forward(&signature, Default, records)?;
|
||||
let user_cp = generate_module_method_forward(&signature, UserDefined, records)?;
|
||||
|
||||
methods.push(default_cp);
|
||||
methods.push(user_cp);
|
||||
|
||||
Ok(methods)
|
||||
},
|
||||
)
|
||||
}
|
@ -1,245 +0,0 @@
|
||||
/*
|
||||
* 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::utils::new_ident;
|
||||
use crate::marine_test::utils::itype_to_tokens;
|
||||
use crate::TResult;
|
||||
|
||||
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;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub(super) enum CallParametersSettings {
|
||||
Default,
|
||||
UserDefined,
|
||||
}
|
||||
|
||||
pub(super) fn generate_module_method(
|
||||
module_name: &str,
|
||||
signature: &IFunctionSignature,
|
||||
cp_setting: CallParametersSettings,
|
||||
records: &IRecordTypes,
|
||||
) -> TResult<TokenStream> {
|
||||
let arguments = generate_arguments(signature.arguments.iter(), records)?;
|
||||
let output_type = generate_output_type(&signature.outputs, records)?;
|
||||
let mcall = generate_marine_call(module_name, cp_setting, &signature, records)?;
|
||||
|
||||
let (cp, func_name) = generate_call_parameters(&cp_setting, signature)?;
|
||||
|
||||
let module_method = quote! {
|
||||
pub fn #func_name(&mut self, #(#arguments),* #cp) #output_type {
|
||||
#mcall
|
||||
}
|
||||
};
|
||||
|
||||
Ok(module_method)
|
||||
}
|
||||
|
||||
pub(super) fn generate_module_method_forward(
|
||||
signature: &IFunctionSignature,
|
||||
cp_setting: CallParametersSettings,
|
||||
records: &IRecordTypes,
|
||||
) -> TResult<TokenStream> {
|
||||
let arguments = generate_arguments(signature.arguments.iter(), records)?;
|
||||
let output_type = generate_output_type(&signature.outputs, records)?;
|
||||
let mcall = generate_forward_call(cp_setting, &signature)?;
|
||||
|
||||
let (cp, func_name) = generate_call_parameters(&cp_setting, signature)?;
|
||||
|
||||
let module_method = quote! {
|
||||
pub fn #func_name(&mut self, #(#arguments),* #cp) #output_type {
|
||||
#mcall
|
||||
}
|
||||
};
|
||||
|
||||
Ok(module_method)
|
||||
}
|
||||
|
||||
fn generate_marine_call(
|
||||
module_name: &str,
|
||||
cp_settings: CallParametersSettings,
|
||||
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)?;
|
||||
|
||||
let output_type = get_output_type(&method_signature.outputs)?;
|
||||
let set_result = generate_set_result(&output_type);
|
||||
let function_call = generate_function_call(module_name, &method_signature.name, cp_settings);
|
||||
let convert_result_to_output_type = generate_convert_to_output(&output_type, records)?;
|
||||
let ret = generate_ret(&output_type);
|
||||
|
||||
let function_call = quote! {
|
||||
use std::ops::DerefMut;
|
||||
|
||||
#convert_arguments
|
||||
|
||||
#set_result #function_call
|
||||
|
||||
#convert_result_to_output_type
|
||||
|
||||
#ret
|
||||
};
|
||||
|
||||
Ok(function_call)
|
||||
}
|
||||
|
||||
fn generate_forward_call(
|
||||
cp_settings: CallParametersSettings,
|
||||
method_signature: &IFunctionSignature,
|
||||
) -> TResult<TokenStream> {
|
||||
let mut args = method_signature
|
||||
.arguments
|
||||
.iter()
|
||||
.map(|a| new_ident(a.name.as_str()))
|
||||
.collect::<TResult<Vec<syn::Ident>>>()?;
|
||||
|
||||
let method_name = if let CallParametersSettings::UserDefined = cp_settings {
|
||||
args.push(new_ident("cp")?);
|
||||
new_ident(format!("{}_cp", method_signature.name.as_str()).as_str())?
|
||||
} else {
|
||||
new_ident(method_signature.name.as_str())?
|
||||
};
|
||||
|
||||
let function_call = quote! {
|
||||
self.__facade.#method_name(#(#args,)*)
|
||||
};
|
||||
|
||||
Ok(function_call)
|
||||
}
|
||||
|
||||
/// Generates type convertor to json because of AppService receives them in json.
|
||||
fn generate_arguments_converter<'a>(
|
||||
args: impl ExactSizeIterator<Item = &'a str>,
|
||||
) -> TResult<TokenStream> {
|
||||
let arg_idents: Vec<syn::Ident> = args.map(new_ident).collect::<Result<_, _>>()?;
|
||||
|
||||
let args_converter = quote! { let arguments = marine_rs_sdk_test::internal::serde_json::json!([#(#arg_idents),*]); };
|
||||
|
||||
Ok(args_converter)
|
||||
}
|
||||
|
||||
fn generate_function_call(
|
||||
module_name: &str,
|
||||
method_name: &str,
|
||||
cp_setting: CallParametersSettings,
|
||||
) -> TokenStream {
|
||||
let cp = match cp_setting {
|
||||
CallParametersSettings::Default => quote! { <_>::default() },
|
||||
CallParametersSettings::UserDefined => quote! { cp },
|
||||
};
|
||||
|
||||
quote! { self.marine.as_ref().borrow_mut().call_module(#module_name, #method_name, arguments, #cp).expect("call to Marine failed"); }
|
||||
}
|
||||
|
||||
fn generate_set_result(output_type: &Option<&IType>) -> TokenStream {
|
||||
match output_type {
|
||||
Some(_) => quote! { let result = },
|
||||
None => TokenStream::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_convert_to_output(
|
||||
output_type: &Option<&IType>,
|
||||
records: &IRecordTypes,
|
||||
) -> TResult<TokenStream> {
|
||||
let result_stream = match output_type {
|
||||
Some(ty) => {
|
||||
let ty = itype_to_tokens(ty, records)?;
|
||||
quote! {
|
||||
let result: #ty = marine_rs_sdk_test::internal::serde_json::from_value(result).expect("the default deserializer shouldn't fail");
|
||||
}
|
||||
}
|
||||
None => TokenStream::new(),
|
||||
};
|
||||
|
||||
Ok(result_stream)
|
||||
}
|
||||
|
||||
fn generate_ret(output_type: &Option<&IType>) -> TokenStream {
|
||||
match output_type {
|
||||
Some(_) => quote! { result },
|
||||
None => TokenStream::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_arguments<'a, 'r>(
|
||||
arguments: impl ExactSizeIterator<Item = &'a IFunctionArg>,
|
||||
records: &'r IRecordTypes,
|
||||
) -> TResult<Vec<TokenStream>> {
|
||||
arguments
|
||||
.map(|argument| -> TResult<_> {
|
||||
let arg_name = new_ident(&argument.name)?;
|
||||
let arg_type = itype_to_tokens(&argument.ty, records)?;
|
||||
|
||||
let arg = quote! { #arg_name: #arg_type };
|
||||
Ok(arg)
|
||||
})
|
||||
.collect::<TResult<Vec<_>>>()
|
||||
}
|
||||
|
||||
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()),
|
||||
Some(ty) => {
|
||||
let output_type = itype_to_tokens(&ty, records)?;
|
||||
let output_type = quote! { -> #output_type };
|
||||
|
||||
Ok(output_type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_output_type(output_types: &[IType]) -> TResult<Option<&IType>> {
|
||||
use crate::TestGeneratorError::ManyFnOutputsUnsupported;
|
||||
|
||||
match output_types.len() {
|
||||
0 => Ok(None),
|
||||
1 => Ok(Some(&output_types[0])),
|
||||
_ => Err(ManyFnOutputsUnsupported),
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_call_parameters(
|
||||
cp_setting: &CallParametersSettings,
|
||||
signature: &IFunctionSignature,
|
||||
) -> TResult<(TokenStream, syn::Ident)> {
|
||||
match cp_setting {
|
||||
CallParametersSettings::Default => {
|
||||
let func_name = new_ident(&signature.name)?;
|
||||
Ok((TokenStream::new(), func_name))
|
||||
}
|
||||
CallParametersSettings::UserDefined => {
|
||||
let maybe_comma = if signature.arguments.is_empty() {
|
||||
TokenStream::new()
|
||||
} else {
|
||||
quote! { , }
|
||||
};
|
||||
|
||||
let cp = quote! { #maybe_comma cp: marine_rs_sdk_test::CallParameters };
|
||||
let func_name = format!("{}_cp", signature.name);
|
||||
let func_name = new_ident(&func_name)?;
|
||||
Ok((cp, func_name))
|
||||
}
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* 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::utils;
|
||||
use crate::TResult;
|
||||
|
||||
use marine_it_parser::it_interface::it::IRecordFieldType;
|
||||
use marine_it_parser::it_interface::IRecordTypes;
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
use crate::marine_test::modules_linker::{LinkedModule, RecordEntry, UseDescription};
|
||||
use itertools::Itertools;
|
||||
|
||||
pub(super) fn generate_records(
|
||||
linked_module: &LinkedModule<'_>,
|
||||
import_generator: fn(info: &UseDescription<'_>) -> TResult<TokenStream>,
|
||||
) -> TResult<Vec<TokenStream>> {
|
||||
linked_module.records
|
||||
.iter()
|
||||
.sorted()
|
||||
.map(|record| -> TResult<_> {
|
||||
use RecordEntry::*;
|
||||
match record {
|
||||
Use(use_info) => import_generator(use_info),
|
||||
Declare(record) => {
|
||||
let record_name_ident = utils::new_ident(&record.record_type.name)?;
|
||||
let fields = prepare_field(record.record_type.fields.iter(), record.records)?;
|
||||
|
||||
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),*
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<TResult<Vec<_>>>()
|
||||
}
|
||||
|
||||
fn prepare_field<'f>(
|
||||
fields: impl ExactSizeIterator<Item = &'f IRecordFieldType>,
|
||||
records: &IRecordTypes,
|
||||
) -> TResult<Vec<TokenStream>> {
|
||||
fields
|
||||
.map(|field| -> TResult<_> {
|
||||
let field_name = utils::new_ident(&field.name)?;
|
||||
let field_type = utils::itype_to_tokens(&field.ty, records)?;
|
||||
|
||||
let generated_field = quote! { #field_name: #field_type };
|
||||
|
||||
Ok(generated_field)
|
||||
})
|
||||
.collect::<TResult<Vec<_>>>()
|
||||
}
|
@ -1,204 +0,0 @@
|
||||
use crate::TResult;
|
||||
use crate::TestGeneratorError;
|
||||
use crate::marine_test::config_utils::Module;
|
||||
use crate::marine_test::utils::new_ident;
|
||||
use crate::marine_test::{modules_linker, config_utils};
|
||||
use crate::marine_test::modules_linker::{LinkedModule, UseDescription};
|
||||
use super::service_generator::{ProcessedService, get_facace};
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
use std::path::Path;
|
||||
use itertools::Itertools;
|
||||
|
||||
pub(crate) fn generate_app_service_ctor(
|
||||
config_path: &str,
|
||||
modules_dir: &Path,
|
||||
) -> TResult<TokenStream> {
|
||||
let modules_dir = modules_dir
|
||||
.to_str()
|
||||
.ok_or_else(|| TestGeneratorError::InvalidUTF8Path(modules_dir.to_path_buf()))?;
|
||||
|
||||
let service_ctor = quote! {
|
||||
let tmp_dir = std::env::temp_dir();
|
||||
let service_id = marine_rs_sdk_test::internal::Uuid::new_v4().to_string();
|
||||
|
||||
let tmp_dir = tmp_dir.join(&service_id);
|
||||
let tmp_dir = tmp_dir.to_string_lossy().to_string();
|
||||
std::fs::create_dir(&tmp_dir).expect("can't create a directory for service in tmp");
|
||||
|
||||
let mut module_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
let mut file_path = std::path::Path::new(file!()).components();
|
||||
|
||||
let mut truncated_file_path = Vec::new();
|
||||
loop {
|
||||
if module_path.ends_with(file_path.as_path()) {
|
||||
break;
|
||||
}
|
||||
|
||||
let (file_path_, remainder) = match file_path.next_back().and_then(|p| match p {
|
||||
std::path::Component::Normal(_) | std::path::Component::CurDir | std::path::Component::ParentDir => Some((file_path, p)),
|
||||
_ => None,
|
||||
}) {
|
||||
Some(t) => t,
|
||||
None => break,
|
||||
};
|
||||
file_path = file_path_;
|
||||
|
||||
truncated_file_path.push(remainder);
|
||||
}
|
||||
|
||||
for path in truncated_file_path.iter().rev() {
|
||||
module_path.push(path);
|
||||
}
|
||||
|
||||
let _ = module_path.pop();
|
||||
|
||||
let config_path = module_path.join(#config_path);
|
||||
let modules_dir = module_path.join(#modules_dir);
|
||||
let modules_dir = modules_dir.to_str().expect("modules_dir contains invalid UTF8 string");
|
||||
|
||||
let mut __m_generated_marine_config = marine_rs_sdk_test::internal::TomlAppServiceConfig::load(&config_path)
|
||||
.unwrap_or_else(|e| panic!("app service config located at `{:?}` can't be loaded: {}", config_path, e));
|
||||
__m_generated_marine_config.service_base_dir = Some(tmp_dir);
|
||||
__m_generated_marine_config.toml_faas_config.modules_dir = Some(modules_dir.to_string());
|
||||
|
||||
let marine = marine_rs_sdk_test::internal::AppService::new_with_empty_facade(__m_generated_marine_config, service_id, std::collections::HashMap::new())
|
||||
.unwrap_or_else(|e| panic!("app service can't be created: {}", e));
|
||||
|
||||
let marine = std::rc::Rc::new(std::cell::RefCell::new(marine));
|
||||
};
|
||||
|
||||
Ok(service_ctor)
|
||||
}
|
||||
|
||||
pub(super) fn generate_service_definition(
|
||||
service: &ProcessedService,
|
||||
test_file_path: &Path,
|
||||
linked_facade: &LinkedModule<'_>,
|
||||
) -> TResult<TokenStream> {
|
||||
let modules_dir_test_relative = test_file_path.join(&service.config.resolved_modules_dir);
|
||||
let modules =
|
||||
config_utils::collect_modules(&service.config.config, &modules_dir_test_relative)?;
|
||||
let linked_modules = modules_linker::link_modules(
|
||||
modules
|
||||
.iter()
|
||||
.map(|module| (module.name, &module.interface)),
|
||||
)?;
|
||||
|
||||
let service_mod = new_ident(&service.name)?;
|
||||
let module_definitions = super::generate_module_definitions(modules.iter(), &linked_modules)?;
|
||||
|
||||
let facade = get_facace(&modules)?;
|
||||
|
||||
let facade_interface = super::methods_generator::generate_facade_methods(
|
||||
facade.interface.function_signatures.iter(),
|
||||
&facade.interface.record_types,
|
||||
)?;
|
||||
|
||||
let facade_override =
|
||||
super::generate_module_definition(facade, linked_facade, service_import_generator)?;
|
||||
let facade_override_ident = new_ident("__facade_override")?;
|
||||
let facade_structs = generate_facade_structs(facade, &facade_override_ident)?;
|
||||
|
||||
let app_service_ctor =
|
||||
generate_app_service_ctor(&service.config_path, &service.config.resolved_modules_dir)?;
|
||||
let modules_type = generate_modules_type(&modules)?;
|
||||
|
||||
let service_definition = quote! {
|
||||
pub mod #service_mod {
|
||||
pub mod modules {
|
||||
#(#module_definitions)*
|
||||
}
|
||||
|
||||
pub mod #facade_override_ident {
|
||||
#facade_override
|
||||
}
|
||||
|
||||
#(#facade_structs)*
|
||||
|
||||
#modules_type
|
||||
|
||||
pub struct ServiceInterface {
|
||||
pub modules: __GeneratedModules,
|
||||
__facade: #facade_override_ident::ModuleInterface,
|
||||
marine: std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>, >
|
||||
}
|
||||
|
||||
impl ServiceInterface {
|
||||
pub fn new() -> Self {
|
||||
#app_service_ctor
|
||||
let modules = __GeneratedModules::new(marine.clone());
|
||||
let __facade = #facade_override_ident::ModuleInterface::new(marine.clone());
|
||||
Self {
|
||||
marine,
|
||||
modules,
|
||||
__facade
|
||||
}
|
||||
}
|
||||
|
||||
#(#facade_interface)*
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(service_definition)
|
||||
}
|
||||
|
||||
fn service_import_generator(info: &UseDescription<'_>) -> TResult<TokenStream> {
|
||||
let from_module_ident = new_ident(info.from)?;
|
||||
let record_name_ident = new_ident(info.name)?;
|
||||
Ok(quote! {pub use super::super::#from_module_ident::#record_name_ident;})
|
||||
}
|
||||
|
||||
fn generate_facade_structs(
|
||||
module: &Module<'_>,
|
||||
module_name: &syn::Ident,
|
||||
) -> TResult<Vec<TokenStream>> {
|
||||
module
|
||||
.interface
|
||||
.record_types
|
||||
.iter()
|
||||
.sorted_by_key(|(_, record)| &record.name)
|
||||
.map(|(_, record)| -> TResult<TokenStream> {
|
||||
let record_name = new_ident(&record.name)?;
|
||||
let result = quote! {pub use #module_name::#record_name;};
|
||||
Ok(result)
|
||||
})
|
||||
.collect::<TResult<Vec<TokenStream>>>()
|
||||
}
|
||||
|
||||
fn generate_modules_type(module_interfaces: &[Module<'_>]) -> TResult<TokenStream> {
|
||||
let fields = module_interfaces
|
||||
.iter()
|
||||
.map(|module| -> TResult<TokenStream> {
|
||||
let name = new_ident(module.name)?;
|
||||
Ok(quote! {pub #name: modules::#name::ModuleInterface})
|
||||
})
|
||||
.collect::<TResult<Vec<TokenStream>>>()?;
|
||||
|
||||
let ctors = module_interfaces
|
||||
.iter()
|
||||
.map(|module| -> TResult<TokenStream> {
|
||||
let name = new_ident(module.name)?;
|
||||
Ok(quote! {#name: modules::#name::ModuleInterface::new(marine.clone())})
|
||||
})
|
||||
.collect::<TResult<Vec<TokenStream>>>()?;
|
||||
|
||||
let ty = quote! {
|
||||
pub struct __GeneratedModules {
|
||||
#(#fields,)*
|
||||
}
|
||||
|
||||
impl __GeneratedModules {
|
||||
fn new(marine: std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>, >) -> Self {
|
||||
Self {
|
||||
#(#ctors,)*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(ty)
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::attributes::{ServiceDescription};
|
||||
use crate::TResult;
|
||||
use crate::TestGeneratorError;
|
||||
use crate::marine_test::config_utils::{Module, ConfigWrapper, load_config};
|
||||
use crate::marine_test::{modules_linker, config_utils};
|
||||
use crate::marine_test::modules_linker::LinkedModules;
|
||||
use super::service_generation_utils::generate_service_definition;
|
||||
|
||||
use marine_it_parser::it_interface::IModuleInterface;
|
||||
use proc_macro2::TokenStream;
|
||||
use itertools::{Itertools, zip};
|
||||
|
||||
use std::path::Path;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub(crate) fn generate_service_definitions(
|
||||
services: HashMap<String, ServiceDescription>,
|
||||
file_path: &Path,
|
||||
) -> TResult<Vec<TokenStream>> {
|
||||
let services = services
|
||||
.into_iter()
|
||||
.sorted_by(|lhs, rhs| lhs.0.cmp(&rhs.0)) // deterministic output required for tests
|
||||
.map(|(name, service)| ProcessedService::new(service, name, file_path))
|
||||
.collect::<TResult<Vec<ProcessedService>>>()?;
|
||||
|
||||
let service_modules = services
|
||||
.iter()
|
||||
.map(|service| {
|
||||
let modules_dir_test_relative = file_path.join(&service.config.resolved_modules_dir);
|
||||
let modules =
|
||||
config_utils::collect_modules(&service.config.config, &modules_dir_test_relative)?;
|
||||
Ok(modules)
|
||||
})
|
||||
.collect::<TResult<Vec<Vec<Module<'_>>>>>()?;
|
||||
|
||||
let link_info = link_services(zip(&services, &service_modules))?;
|
||||
services
|
||||
.iter()
|
||||
.map(|service| -> TResult<TokenStream> {
|
||||
// entry with service.name was added in link_services(...), so unwrap is safe
|
||||
generate_service_definition(
|
||||
&service,
|
||||
file_path,
|
||||
link_info.get::<str>(&service.name).unwrap(),
|
||||
)
|
||||
})
|
||||
.collect::<TResult<Vec<TokenStream>>>()
|
||||
}
|
||||
|
||||
pub(super) fn get_facace<'modules, 'm>(
|
||||
modules: &'modules [Module<'m>],
|
||||
) -> TResult<&'modules Module<'m>> {
|
||||
match modules.last() {
|
||||
Some(module) => Ok(module),
|
||||
None => Err(TestGeneratorError::NoModulesInService),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct ProcessedService {
|
||||
pub(super) config: ConfigWrapper,
|
||||
pub(super) config_path: String,
|
||||
pub(super) name: String,
|
||||
}
|
||||
|
||||
impl ProcessedService {
|
||||
pub(crate) fn new(
|
||||
service: ServiceDescription,
|
||||
name: String,
|
||||
file_path: &Path,
|
||||
) -> TResult<Self> {
|
||||
let config_wrapper = load_config(&service.config_path, service.modules_dir, &file_path)?;
|
||||
|
||||
Ok(Self {
|
||||
config: config_wrapper,
|
||||
config_path: service.config_path,
|
||||
name,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn link_services<'modules>(
|
||||
services: impl ExactSizeIterator<
|
||||
Item = (&'modules ProcessedService, &'modules Vec<Module<'modules>>),
|
||||
>,
|
||||
) -> TResult<LinkedModules<'modules>> {
|
||||
let facade_modules = services
|
||||
.map(|(service, modules)| {
|
||||
let facade = get_facace(modules)?;
|
||||
Ok((service.name.as_str(), &facade.interface))
|
||||
})
|
||||
.collect::<TResult<Vec<(&str, &IModuleInterface)>>>()?;
|
||||
|
||||
modules_linker::link_modules(facade_modules.iter().copied())
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::TResult;
|
||||
use marine_it_parser::it_interface::IRecordTypes;
|
||||
use marine_it_parser::it_interface::it::IType;
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
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: &IRecordTypes) -> TResult<TokenStream> {
|
||||
let token_stream = match itype {
|
||||
IType::Record(record_id) => {
|
||||
let record = records
|
||||
.get(record_id)
|
||||
.ok_or_else(|| crate::errors::CorruptedITSection::AbsentRecord(*record_id))?;
|
||||
let record_name = new_ident(&record.name)?;
|
||||
let token_stream = quote! { #record_name };
|
||||
token_stream
|
||||
}
|
||||
IType::Array(ty) => {
|
||||
let inner_ty_token_stream = itype_to_tokens(ty, records)?;
|
||||
let token_stream = quote! { Vec<#inner_ty_token_stream> };
|
||||
token_stream
|
||||
}
|
||||
IType::String => quote! { String },
|
||||
IType::ByteArray => quote! { Vec<u8> },
|
||||
IType::Boolean => quote! { bool },
|
||||
IType::S8 => quote! { i8 },
|
||||
IType::S16 => quote! { i16 },
|
||||
IType::S32 => quote! { i32 },
|
||||
IType::S64 => quote! { i64 },
|
||||
IType::U8 => quote! { u8 },
|
||||
IType::U16 => quote! { u16 },
|
||||
IType::U32 => quote! { u32 },
|
||||
IType::U64 => quote! { u64 },
|
||||
IType::I32 => quote! { i32 },
|
||||
IType::I64 => quote! { i64 },
|
||||
IType::F32 => quote! { f32 },
|
||||
IType::F64 => quote! { f64 },
|
||||
};
|
||||
|
||||
Ok(token_stream)
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
modules_dir = "artifacts/"
|
||||
|
||||
[[module]]
|
||||
name = "greeting"
|
||||
mem_pages_count = 1
|
||||
logger_enabled = false
|
Binary file not shown.
@ -1,128 +0,0 @@
|
||||
#[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()
|
||||
}
|
@ -1 +0,0 @@
|
||||
fn empty_string() {}
|
@ -1,8 +0,0 @@
|
||||
modules_dir = "artifacts/"
|
||||
|
||||
[[module]]
|
||||
name = "greeting"
|
||||
mem_pages_count = 1
|
||||
logger_enabled = false
|
||||
[module.mounted_binaries]
|
||||
echo = "/usr/bin/curl"
|
Binary file not shown.
@ -1,167 +0,0 @@
|
||||
#[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,)
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
fn test(greeting: marine_test_env::greeting::ModuleInterface) {
|
||||
let _ = greeting.download("duckduckgo.com");
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
modules_dir = "artifacts/"
|
||||
|
||||
[[module]]
|
||||
name = "greeting"
|
||||
mem_pages_count = 50
|
||||
logger_enabled = false
|
Binary file not shown.
@ -1,504 +0,0 @@
|
||||
#[test]
|
||||
fn test() {
|
||||
pub mod marine_test_env {
|
||||
pub mod empty_func {
|
||||
pub mod modules {
|
||||
pub mod greeting {
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct CallParameters {
|
||||
pub init_peer_id: String,
|
||||
pub service_id: String,
|
||||
pub service_creator_peer_id: String,
|
||||
pub host_id: String,
|
||||
pub particle_id: String,
|
||||
pub tetraplets: Vec<Vec<SecurityTetraplet>>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: Vec<u8>,
|
||||
pub stderr: Vec<u8>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryStringResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: String,
|
||||
pub stderr: String
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct SecurityTetraplet {
|
||||
pub peer_pk: String,
|
||||
pub service_id: String,
|
||||
pub function_name: String,
|
||||
pub json_path: String
|
||||
}
|
||||
pub struct ModuleInterface {
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>,
|
||||
}
|
||||
impl ModuleInterface {
|
||||
pub fn new(
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>
|
||||
) -> Self {
|
||||
Self { marine }
|
||||
}
|
||||
}
|
||||
impl ModuleInterface {}
|
||||
}
|
||||
}
|
||||
pub mod __facade_override {
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct CallParameters {
|
||||
pub init_peer_id: String,
|
||||
pub service_id: String,
|
||||
pub service_creator_peer_id: String,
|
||||
pub host_id: String,
|
||||
pub particle_id: String,
|
||||
pub tetraplets: Vec<Vec<SecurityTetraplet>>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: Vec<u8>,
|
||||
pub stderr: Vec<u8>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryStringResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: String,
|
||||
pub stderr: String
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct SecurityTetraplet {
|
||||
pub peer_pk: String,
|
||||
pub service_id: String,
|
||||
pub function_name: String,
|
||||
pub json_path: String
|
||||
}
|
||||
pub struct ModuleInterface {
|
||||
marine:
|
||||
std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>,
|
||||
}
|
||||
impl ModuleInterface {
|
||||
pub fn new(
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>
|
||||
) -> Self {
|
||||
Self { marine }
|
||||
}
|
||||
}
|
||||
impl ModuleInterface {}
|
||||
}
|
||||
pub use __facade_override::CallParameters;
|
||||
pub use __facade_override::MountedBinaryResult;
|
||||
pub use __facade_override::MountedBinaryStringResult;
|
||||
pub use __facade_override::SecurityTetraplet;
|
||||
pub struct __GeneratedModules {
|
||||
pub greeting: modules::greeting::ModuleInterface,
|
||||
}
|
||||
impl __GeneratedModules {
|
||||
fn new(
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>
|
||||
) -> Self {
|
||||
Self {
|
||||
greeting: modules::greeting::ModuleInterface::new(marine.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
pub struct ServiceInterface {
|
||||
pub modules: __GeneratedModules,
|
||||
__facade: __facade_override::ModuleInterface,
|
||||
marine: std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>, >
|
||||
}
|
||||
impl ServiceInterface {
|
||||
pub fn new() -> Self {
|
||||
let tmp_dir = std::env::temp_dir();
|
||||
let service_id = marine_rs_sdk_test::internal::Uuid::new_v4().to_string();
|
||||
let tmp_dir = tmp_dir.join(&service_id);
|
||||
let tmp_dir = tmp_dir.to_string_lossy().to_string();
|
||||
std::fs::create_dir(&tmp_dir)
|
||||
.expect("can't create a directory for service in tmp");
|
||||
let mut module_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
let mut file_path = std::path::Path::new(file!()).components();
|
||||
let mut truncated_file_path = Vec::new();
|
||||
loop {
|
||||
if module_path.ends_with(file_path.as_path()) {
|
||||
break;
|
||||
}
|
||||
let (file_path_, remainder) =
|
||||
match file_path.next_back().and_then(|p| match p {
|
||||
std::path::Component::Normal(_)
|
||||
| std::path::Component::CurDir
|
||||
| std::path::Component::ParentDir => Some((file_path, p)),
|
||||
_ => None,
|
||||
}) {
|
||||
Some(t) => t,
|
||||
None => break,
|
||||
};
|
||||
file_path = file_path_;
|
||||
truncated_file_path.push(remainder);
|
||||
}
|
||||
for path in truncated_file_path.iter().rev() {
|
||||
module_path.push(path);
|
||||
}
|
||||
let _ = module_path.pop();
|
||||
let config_path = module_path.join("empty_func/Config.toml");
|
||||
let modules_dir = module_path.join("empty_func/artifacts");
|
||||
let modules_dir = modules_dir
|
||||
.to_str()
|
||||
.expect("modules_dir contains invalid UTF8 string");
|
||||
let mut __m_generated_marine_config =
|
||||
marine_rs_sdk_test::internal::TomlAppServiceConfig::load(&config_path)
|
||||
.unwrap_or_else(|e|
|
||||
panic!(
|
||||
"app service config located at `{:?}` can't be loaded: {}",
|
||||
config_path, e
|
||||
)
|
||||
);
|
||||
__m_generated_marine_config.service_base_dir = Some(tmp_dir);
|
||||
__m_generated_marine_config.toml_faas_config.modules_dir =
|
||||
Some(modules_dir.to_string());
|
||||
let marine = marine_rs_sdk_test::internal::AppService::new_with_empty_facade(
|
||||
__m_generated_marine_config,
|
||||
service_id,
|
||||
std::collections::HashMap::new()
|
||||
)
|
||||
.unwrap_or_else(|e| panic!("app service can't be created: {}", e));
|
||||
let marine = std::rc::Rc::new(std::cell::RefCell::new(marine));
|
||||
let modules = __GeneratedModules::new(marine.clone());
|
||||
let __facade = __facade_override::ModuleInterface::new(marine.clone());
|
||||
Self {
|
||||
marine,
|
||||
modules,
|
||||
__facade
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pub mod mounted_binary {
|
||||
pub mod modules {
|
||||
pub mod greeting {
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct CallParameters {
|
||||
pub init_peer_id: String,
|
||||
pub service_id: String,
|
||||
pub service_creator_peer_id: String,
|
||||
pub host_id: String,
|
||||
pub particle_id: String,
|
||||
pub tetraplets: Vec<Vec<SecurityTetraplet>>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: Vec<u8>,
|
||||
pub stderr: Vec<u8>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryStringResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: String,
|
||||
pub stderr: String
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct SecurityTetraplet {
|
||||
pub peer_pk: String,
|
||||
pub service_id: String,
|
||||
pub function_name: String,
|
||||
pub json_path: String
|
||||
}
|
||||
pub struct ModuleInterface {
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>,
|
||||
}
|
||||
impl ModuleInterface {
|
||||
pub fn new(
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>
|
||||
) -> Self {
|
||||
Self { marine }
|
||||
}
|
||||
}
|
||||
impl ModuleInterface {
|
||||
pub fn download(&mut self, url: String) -> String {
|
||||
use std::ops::DerefMut;
|
||||
let arguments = marine_rs_sdk_test::internal::serde_json::json!([url]);
|
||||
let result = self
|
||||
.marine
|
||||
.as_ref()
|
||||
.borrow_mut()
|
||||
.call_module("greeting", "download", arguments, <_>::default())
|
||||
.expect("call to Marine failed");
|
||||
let result: String =
|
||||
marine_rs_sdk_test::internal::serde_json::from_value(result)
|
||||
.expect("the default deserializer shouldn't fail");
|
||||
result
|
||||
}
|
||||
pub fn download_cp(
|
||||
&mut self,
|
||||
url: String,
|
||||
cp: marine_rs_sdk_test::CallParameters
|
||||
) -> String {
|
||||
use std::ops::DerefMut;
|
||||
let arguments = marine_rs_sdk_test::internal::serde_json::json!([url]);
|
||||
let result = self
|
||||
.marine
|
||||
.as_ref()
|
||||
.borrow_mut()
|
||||
.call_module("greeting", "download", arguments, cp)
|
||||
.expect("call to Marine failed");
|
||||
let result: String =
|
||||
marine_rs_sdk_test::internal::serde_json::from_value(result)
|
||||
.expect("the default deserializer shouldn't fail");
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pub mod __facade_override {
|
||||
pub use super::super::empty_func::CallParameters;
|
||||
pub use super::super::empty_func::MountedBinaryResult;
|
||||
pub use super::super::empty_func::MountedBinaryStringResult;
|
||||
pub use super::super::empty_func::SecurityTetraplet;
|
||||
pub struct ModuleInterface {
|
||||
marine:
|
||||
std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>,
|
||||
}
|
||||
impl ModuleInterface {
|
||||
pub fn new(
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>
|
||||
) -> Self {
|
||||
Self { marine }
|
||||
}
|
||||
}
|
||||
impl ModuleInterface {
|
||||
pub fn download(&mut self, url: String) -> String {
|
||||
use std::ops::DerefMut;
|
||||
let arguments = marine_rs_sdk_test::internal::serde_json::json!([url]);
|
||||
let result = self
|
||||
.marine
|
||||
.as_ref()
|
||||
.borrow_mut()
|
||||
.call_module("greeting", "download", arguments, <_>::default())
|
||||
.expect("call to Marine failed");
|
||||
let result: String =
|
||||
marine_rs_sdk_test::internal::serde_json::from_value(result)
|
||||
.expect("the default deserializer shouldn't fail");
|
||||
result
|
||||
}
|
||||
pub fn download_cp(
|
||||
&mut self,
|
||||
url: String,
|
||||
cp: marine_rs_sdk_test::CallParameters
|
||||
) -> String {
|
||||
use std::ops::DerefMut;
|
||||
let arguments = marine_rs_sdk_test::internal::serde_json::json!([url]);
|
||||
let result = self
|
||||
.marine
|
||||
.as_ref()
|
||||
.borrow_mut()
|
||||
.call_module("greeting", "download", arguments, cp)
|
||||
.expect("call to Marine failed");
|
||||
let result: String =
|
||||
marine_rs_sdk_test::internal::serde_json::from_value(result)
|
||||
.expect("the default deserializer shouldn't fail");
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
||||
pub use __facade_override::CallParameters;
|
||||
pub use __facade_override::MountedBinaryResult;
|
||||
pub use __facade_override::MountedBinaryStringResult;
|
||||
pub use __facade_override::SecurityTetraplet;
|
||||
pub struct __GeneratedModules {
|
||||
pub greeting: modules::greeting::ModuleInterface,
|
||||
}
|
||||
impl __GeneratedModules {
|
||||
fn new(
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>
|
||||
) -> Self {
|
||||
Self {
|
||||
greeting: modules::greeting::ModuleInterface::new(marine.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
pub struct ServiceInterface {
|
||||
pub modules: __GeneratedModules,
|
||||
__facade: __facade_override::ModuleInterface,
|
||||
marine: std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>, >
|
||||
}
|
||||
impl ServiceInterface {
|
||||
pub fn new() -> Self {
|
||||
let tmp_dir = std::env::temp_dir();
|
||||
let service_id = marine_rs_sdk_test::internal::Uuid::new_v4().to_string();
|
||||
let tmp_dir = tmp_dir.join(&service_id);
|
||||
let tmp_dir = tmp_dir.to_string_lossy().to_string();
|
||||
std::fs::create_dir(&tmp_dir)
|
||||
.expect("can't create a directory for service in tmp");
|
||||
let mut module_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
let mut file_path = std::path::Path::new(file!()).components();
|
||||
let mut truncated_file_path = Vec::new();
|
||||
loop {
|
||||
if module_path.ends_with(file_path.as_path()) {
|
||||
break;
|
||||
}
|
||||
let (file_path_, remainder) =
|
||||
match file_path.next_back().and_then(|p| match p {
|
||||
std::path::Component::Normal(_)
|
||||
| std::path::Component::CurDir
|
||||
| std::path::Component::ParentDir => Some((file_path, p)),
|
||||
_ => None,
|
||||
}) {
|
||||
Some(t) => t,
|
||||
None => break,
|
||||
};
|
||||
file_path = file_path_;
|
||||
truncated_file_path.push(remainder);
|
||||
}
|
||||
for path in truncated_file_path.iter().rev() {
|
||||
module_path.push(path);
|
||||
}
|
||||
let _ = module_path.pop();
|
||||
let config_path = module_path.join("mounted_binary/Config.toml");
|
||||
let modules_dir = module_path.join("mounted_binary/artifacts");
|
||||
let modules_dir = modules_dir
|
||||
.to_str()
|
||||
.expect("modules_dir contains invalid UTF8 string");
|
||||
let mut __m_generated_marine_config =
|
||||
marine_rs_sdk_test::internal::TomlAppServiceConfig::load(&config_path)
|
||||
.unwrap_or_else(|e|
|
||||
panic!(
|
||||
"app service config located at `{:?}` can't be loaded: {}",
|
||||
config_path, e
|
||||
)
|
||||
);
|
||||
__m_generated_marine_config.service_base_dir = Some(tmp_dir);
|
||||
__m_generated_marine_config.toml_faas_config.modules_dir =
|
||||
Some(modules_dir.to_string());
|
||||
let marine = marine_rs_sdk_test::internal::AppService::new_with_empty_facade(
|
||||
__m_generated_marine_config,
|
||||
service_id,
|
||||
std::collections::HashMap::new()
|
||||
)
|
||||
.unwrap_or_else(|e| panic!("app service can't be created: {}", e));
|
||||
let marine = std::rc::Rc::new(std::cell::RefCell::new(marine));
|
||||
let modules = __GeneratedModules::new(marine.clone());
|
||||
let __facade = __facade_override::ModuleInterface::new(marine.clone());
|
||||
Self {
|
||||
marine,
|
||||
modules,
|
||||
__facade
|
||||
}
|
||||
}
|
||||
pub fn download(&mut self, url: String) -> String {
|
||||
self.__facade.download(url,)
|
||||
}
|
||||
pub fn download_cp(
|
||||
&mut self,
|
||||
url: String,
|
||||
cp: marine_rs_sdk_test::CallParameters
|
||||
) -> String {
|
||||
self.__facade.download_cp(url, cp,)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fn test_func() {
|
||||
{
|
||||
let mut greeting = marine_test_env::greeting::ServiceInterface::new();
|
||||
let _ = greeting.download("duckduckgo.com");
|
||||
}
|
||||
}
|
||||
test_func()
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
fn test() {
|
||||
let mut greeting = marine_test_env::greeting::ServiceInterface::new();
|
||||
let _ = greeting.download("duckduckgo.com");
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
modules_dir = "artifacts/"
|
||||
|
||||
[[module]]
|
||||
name = "greeting"
|
||||
mem_pages_count = 50
|
||||
logger_enabled = false
|
||||
[module.mounted_binaries]
|
||||
echo = "/usr/bin/curl"
|
Binary file not shown.
@ -1,6 +0,0 @@
|
||||
modules_dir = "artifacts/"
|
||||
|
||||
[[module]]
|
||||
name = "greeting"
|
||||
mem_pages_count = 50
|
||||
logger_enabled = false
|
Binary file not shown.
@ -1,242 +0,0 @@
|
||||
#[test]
|
||||
fn empty_test() {
|
||||
pub mod marine_test_env {
|
||||
pub mod empty_func {
|
||||
pub mod modules {
|
||||
pub mod greeting {
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct CallParameters {
|
||||
pub init_peer_id: String,
|
||||
pub service_id: String,
|
||||
pub service_creator_peer_id: String,
|
||||
pub host_id: String,
|
||||
pub particle_id: String,
|
||||
pub tetraplets: Vec<Vec<SecurityTetraplet>>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: Vec<u8>,
|
||||
pub stderr: Vec<u8>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryStringResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: String,
|
||||
pub stderr: String
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct SecurityTetraplet {
|
||||
pub peer_pk: String,
|
||||
pub service_id: String,
|
||||
pub function_name: String,
|
||||
pub json_path: String
|
||||
}
|
||||
pub struct ModuleInterface {
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>,
|
||||
}
|
||||
impl ModuleInterface {
|
||||
pub fn new(
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>
|
||||
) -> Self {
|
||||
Self { marine }
|
||||
}
|
||||
}
|
||||
impl ModuleInterface {}
|
||||
}
|
||||
}
|
||||
pub mod __facade_override {
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct CallParameters {
|
||||
pub init_peer_id: String,
|
||||
pub service_id: String,
|
||||
pub service_creator_peer_id: String,
|
||||
pub host_id: String,
|
||||
pub particle_id: String,
|
||||
pub tetraplets: Vec<Vec<SecurityTetraplet>>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: Vec<u8>,
|
||||
pub stderr: Vec<u8>
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct MountedBinaryStringResult {
|
||||
pub ret_code: i32,
|
||||
pub error: String,
|
||||
pub stdout: String,
|
||||
pub stderr: String
|
||||
}
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
marine_rs_sdk_test :: internal :: serde :: Serialize,
|
||||
marine_rs_sdk_test :: internal :: serde :: Deserialize
|
||||
)]
|
||||
#[serde(crate = "marine_rs_sdk_test::internal::serde")]
|
||||
pub struct SecurityTetraplet {
|
||||
pub peer_pk: String,
|
||||
pub service_id: String,
|
||||
pub function_name: String,
|
||||
pub json_path: String
|
||||
}
|
||||
pub struct ModuleInterface {
|
||||
marine:
|
||||
std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>,
|
||||
}
|
||||
impl ModuleInterface {
|
||||
pub fn new(
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>
|
||||
) -> Self {
|
||||
Self { marine }
|
||||
}
|
||||
}
|
||||
impl ModuleInterface {}
|
||||
}
|
||||
pub use __facade_override::CallParameters;
|
||||
pub use __facade_override::MountedBinaryResult;
|
||||
pub use __facade_override::MountedBinaryStringResult;
|
||||
pub use __facade_override::SecurityTetraplet;
|
||||
pub struct __GeneratedModules {
|
||||
pub greeting: modules::greeting::ModuleInterface,
|
||||
}
|
||||
impl __GeneratedModules {
|
||||
fn new(
|
||||
marine: std::rc::Rc<
|
||||
std::cell::RefCell<marine_rs_sdk_test::internal::AppService>,
|
||||
>
|
||||
) -> Self {
|
||||
Self {
|
||||
greeting: modules::greeting::ModuleInterface::new(marine.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
pub struct ServiceInterface {
|
||||
pub modules: __GeneratedModules,
|
||||
__facade: __facade_override::ModuleInterface,
|
||||
marine: std::rc::Rc<std::cell::RefCell<marine_rs_sdk_test::internal::AppService>, >
|
||||
}
|
||||
impl ServiceInterface {
|
||||
pub fn new() -> Self {
|
||||
let tmp_dir = std::env::temp_dir();
|
||||
let service_id = marine_rs_sdk_test::internal::Uuid::new_v4().to_string();
|
||||
let tmp_dir = tmp_dir.join(&service_id);
|
||||
let tmp_dir = tmp_dir.to_string_lossy().to_string();
|
||||
std::fs::create_dir(&tmp_dir)
|
||||
.expect("can't create a directory for service in tmp");
|
||||
let mut module_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
let mut file_path = std::path::Path::new(file!()).components();
|
||||
let mut truncated_file_path = Vec::new();
|
||||
loop {
|
||||
if module_path.ends_with(file_path.as_path()) {
|
||||
break;
|
||||
}
|
||||
let (file_path_, remainder) =
|
||||
match file_path.next_back().and_then(|p| match p {
|
||||
std::path::Component::Normal(_)
|
||||
| std::path::Component::CurDir
|
||||
| std::path::Component::ParentDir => Some((file_path, p)),
|
||||
_ => None,
|
||||
}) {
|
||||
Some(t) => t,
|
||||
None => break,
|
||||
};
|
||||
file_path = file_path_;
|
||||
truncated_file_path.push(remainder);
|
||||
}
|
||||
for path in truncated_file_path.iter().rev() {
|
||||
module_path.push(path);
|
||||
}
|
||||
let _ = module_path.pop();
|
||||
let config_path = module_path.join("empty_func/Config.toml");
|
||||
let modules_dir = module_path.join("empty_func/artifacts");
|
||||
let modules_dir = modules_dir
|
||||
.to_str()
|
||||
.expect("modules_dir contains invalid UTF8 string");
|
||||
let mut __m_generated_marine_config =
|
||||
marine_rs_sdk_test::internal::TomlAppServiceConfig::load(&config_path)
|
||||
.unwrap_or_else(|e|
|
||||
panic!(
|
||||
"app service config located at `{:?}` can't be loaded: {}",
|
||||
config_path, e
|
||||
)
|
||||
);
|
||||
__m_generated_marine_config.service_base_dir = Some(tmp_dir);
|
||||
__m_generated_marine_config.toml_faas_config.modules_dir =
|
||||
Some(modules_dir.to_string());
|
||||
let marine = marine_rs_sdk_test::internal::AppService::new_with_empty_facade(
|
||||
__m_generated_marine_config,
|
||||
service_id,
|
||||
std::collections::HashMap::new()
|
||||
)
|
||||
.unwrap_or_else(|e| panic!("app service can't be created: {}", e));
|
||||
let marine = std::rc::Rc::new(std::cell::RefCell::new(marine));
|
||||
let modules = __GeneratedModules::new(marine.clone());
|
||||
let __facade = __facade_override::ModuleInterface::new(marine.clone());
|
||||
Self {
|
||||
marine,
|
||||
modules,
|
||||
__facade
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fn test_func() {
|
||||
{}
|
||||
}
|
||||
test_func()
|
||||
}
|
@ -1 +0,0 @@
|
||||
fn empty_test() {}
|
@ -1,10 +0,0 @@
|
||||
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.
@ -1,321 +0,0 @@
|
||||
#[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, )
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
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);
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
use utils::TestServiceDescription;
|
||||
use utils::test_marine_test_token_streams_multiservice;
|
||||
|
||||
#[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"
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiservice_single() {
|
||||
let descriptions = vec![TestServiceDescription {
|
||||
modules_dir: "empty_func/artifacts",
|
||||
config_path: "empty_func/Config.toml",
|
||||
name: "empty_func",
|
||||
}];
|
||||
assert!(test_marine_test_token_streams_multiservice(
|
||||
"tests/generation_tests/multi-service-single/marine_test.rs",
|
||||
"tests/generation_tests/multi-service-single/expanded.rs",
|
||||
descriptions
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiservice_multiple() {
|
||||
let descriptions = vec![
|
||||
TestServiceDescription {
|
||||
modules_dir: "empty_func/artifacts",
|
||||
config_path: "empty_func/Config.toml",
|
||||
name: "empty_func",
|
||||
},
|
||||
TestServiceDescription {
|
||||
modules_dir: "mounted_binary/artifacts",
|
||||
config_path: "mounted_binary/Config.toml",
|
||||
name: "mounted_binary",
|
||||
},
|
||||
];
|
||||
assert!(test_marine_test_token_streams_multiservice(
|
||||
"tests/generation_tests/multi-service-multiple/marine_test.rs",
|
||||
"tests/generation_tests/multi-service-multiple/expanded.rs",
|
||||
descriptions
|
||||
));
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
}
|
||||
|
||||
pub struct TestServiceDescription {
|
||||
pub config_path: &'static str,
|
||||
pub modules_dir: &'static str,
|
||||
pub name: &'static str,
|
||||
}
|
||||
|
||||
pub fn test_marine_test_token_streams_multiservice<FP, EP>(
|
||||
marine_path: FP,
|
||||
expanded_path: EP,
|
||||
services: Vec<TestServiceDescription>,
|
||||
) -> bool
|
||||
where
|
||||
FP: AsRef<Path>,
|
||||
EP: AsRef<Path>,
|
||||
{
|
||||
let marine_item = stream_from_file(&marine_path);
|
||||
let test_token_stream = quote::quote! { #marine_item };
|
||||
let buf = marine_path.as_ref().to_path_buf();
|
||||
let service_declarations = services
|
||||
.iter()
|
||||
.map(|desc| {
|
||||
let config_path = desc.config_path;
|
||||
let modules_dir = desc.modules_dir;
|
||||
let name = syn::parse_str::<syn::Ident>(desc.name)?;
|
||||
Ok(quote::quote! {#name(config_path = #config_path, modules_dir = #modules_dir)})
|
||||
})
|
||||
.collect::<Result<Vec<_>, syn::Error>>()
|
||||
.unwrap_or_else(|e| panic!("failed to parse test arguments due to {}", e));
|
||||
|
||||
let attrs = quote::quote! {
|
||||
#(#service_declarations,)*
|
||||
};
|
||||
|
||||
let marine_token_streams = marine_test_impl(
|
||||
attrs,
|
||||
test_token_stream,
|
||||
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,26 +0,0 @@
|
||||
[package]
|
||||
name = "marine-test-macro"
|
||||
version = "0.3.0" # remember to update html_root_url
|
||||
edition = "2018"
|
||||
description = "Definition of the `#[marine_test]` macro"
|
||||
documentation = "https://docs.rs/fluence/marine-test-macro"
|
||||
repository = "https://github.com/fluencelabs/marine-rs-sdk/tree/master/crates/marine-test-macro"
|
||||
authors = ["Fluence Labs"]
|
||||
keywords = ["fluence", "marine", "sdk", "webassembly", "procedural_macros"]
|
||||
categories = ["api-bindings", "wasm", "development-tools::testing"]
|
||||
license = "Apache-2.0"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
marine-test-macro-impl = { path = "../marine-test-macro-impl", version = "=0.3.0" }
|
||||
|
||||
quote = "1.0.9"
|
||||
proc-macro2 = "1.0.24"
|
||||
proc-macro-error = { version = "1.0.4", default-features = false }
|
||||
syn = { version = '1.0.64', features = ['full'] }
|
@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/sdk-test-macro/0.3.0")]
|
||||
#![deny(
|
||||
dead_code,
|
||||
nonstandard_style,
|
||||
unused_imports,
|
||||
unused_mut,
|
||||
unused_variables,
|
||||
unused_unsafe,
|
||||
unreachable_patterns
|
||||
)]
|
||||
#![feature(proc_macro_span)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
#![recursion_limit = "1024"]
|
||||
|
||||
use marine_test_macro_impl::marine_test_impl;
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro_error::proc_macro_error;
|
||||
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(greeting: marine_test_env::greeting::ModuleInterface) {
|
||||
/// let service_result = greeting.greeting("John".to_string());
|
||||
/// assert_eq!(&service_result, "Hi, name!");
|
||||
/// }
|
||||
///```
|
||||
#[proc_macro_error]
|
||||
#[proc_macro_attribute]
|
||||
pub fn marine_test(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let attrs: proc_macro2::TokenStream = attrs.into();
|
||||
let attrs_span = attrs.span();
|
||||
// here it obtains a path to the current file where macro is applied
|
||||
let mut file_path = proc_macro::Span::call_site().source_file().path();
|
||||
let _ = file_path.pop();
|
||||
|
||||
match marine_test_impl(attrs, input.into(), file_path) {
|
||||
Ok(stream) => stream.into(),
|
||||
Err(e) => proc_macro_error::abort!(attrs_span, format!("{}", e)),
|
||||
}
|
||||
}
|
||||
|
||||
// deprecated macro for backwards compatibility
|
||||
#[deprecated(since = "0.6.2", note = "please use the #[marine] macro instead")]
|
||||
#[proc_macro_error]
|
||||
#[proc_macro_attribute]
|
||||
pub fn fce_test(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let attrs: proc_macro2::TokenStream = attrs.into();
|
||||
let attrs_span = attrs.span();
|
||||
// here it obtains a path to the current file where macro is applied
|
||||
let mut file_path = proc_macro::Span::call_site().source_file().path();
|
||||
let _ = file_path.pop();
|
||||
|
||||
match marine_test_impl(attrs, input.into(), file_path) {
|
||||
Ok(stream) => stream.into(),
|
||||
Err(e) => proc_macro_error::abort!(attrs_span, format!("{}", e)),
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
## Version 0.3.0 (2021-10-04)
|
||||
[PR 61](https://github.com/fluencelabs/marine-rs-sdk/pull/61):
|
||||
|
||||
Implemented the first part of [Issue 57](https://github.com/fluencelabs/marine-rs-sdk/issues/57): `marine_test` now can take several named services in attributes, then define interface to the services in `marine_test_env`.
|
||||
|
||||
## Version 0.2.0 (2021-09-01)
|
||||
[PR 54](https://github.com/fluencelabs/marine-rs-sdk/pull/54):
|
||||
- previously test function accessed module interfaces through externally defined variables, now module interfaces are passed as arguments.
|
||||
- introduced generated module `marine_test_env` which provides interface for generated structs and functions.
|
@ -1,29 +0,0 @@
|
||||
[package]
|
||||
name = "marine-rs-sdk-test"
|
||||
version = "0.3.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"
|
||||
authors = ["Fluence Labs"]
|
||||
keywords = ["fluence", "marine", "sdk", "webassembly", "test"]
|
||||
categories = ["api-bindings", "wasm", "development-tools::testing"]
|
||||
license = "Apache-2.0"
|
||||
edition = "2018"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
[lib]
|
||||
path = "src/lib.rs"
|
||||
doctest = false
|
||||
|
||||
[dev-dependencies]
|
||||
trybuild = "1.0"
|
||||
|
||||
[dependencies]
|
||||
marine-test-macro = { path = "../crates/marine-test-macro", version = "=0.3.0" }
|
||||
fluence-app-service = { version = "0.9.0", features = ["raw-module-api"] }
|
||||
|
||||
serde = { version = "1.0.118", features = ["derive"] }
|
||||
serde_json = "1.0.64"
|
||||
uuid = { version = "0.8.2", features = ["v4"] }
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/sdk-test/0.3.0")]
|
||||
#![deny(
|
||||
dead_code,
|
||||
nonstandard_style,
|
||||
unused_imports,
|
||||
unused_mut,
|
||||
unused_variables,
|
||||
unused_unsafe,
|
||||
unreachable_patterns
|
||||
)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
pub use marine_test_macro::marine_test;
|
||||
pub use marine_test_macro::fce_test;
|
||||
|
||||
pub use fluence_app_service::CallParameters;
|
||||
pub use fluence_app_service::SecurityTetraplet;
|
||||
|
||||
/// These API functions are intended for internal usage in generated code.
|
||||
/// Normally, you shouldn't use them.
|
||||
pub mod internal {
|
||||
pub use fluence_app_service::AppService;
|
||||
pub use fluence_app_service::TomlAppServiceConfig;
|
||||
|
||||
pub use serde;
|
||||
pub use serde_json;
|
||||
|
||||
pub use uuid::Uuid;
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
[package]
|
||||
name = "marine-rs-sdk"
|
||||
version = "0.6.14" # remember to update html_root_url
|
||||
description = "Fluence backend SDK for developing backend applications for the Fluence network"
|
||||
documentation = "https://docs.rs/fluence"
|
||||
repository = "https://github.com/fluencelabs/marine-rs-sdk"
|
||||
authors = ["Fluence Labs"]
|
||||
keywords = ["fluence", "marine", "sdk", "webassembly"]
|
||||
categories = ["api-bindings", "wasm"]
|
||||
license = "Apache-2.0"
|
||||
edition = "2018"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
[lib]
|
||||
path = "src/lib.rs"
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
marine-macro = { path = "../crates/marine-macro", version = "=0.6.14" }
|
||||
marine-rs-sdk-main = { path = "../crates/main", version = "=0.6.14" }
|
||||
marine-timestamp-macro = { path = "../crates/timestamp-macro", version = "=0.6.14" }
|
||||
|
||||
serde = { version = "1.0.118", features = ["derive"]}
|
||||
|
||||
[dev-dependencies]
|
||||
trybuild = "1.0"
|
||||
|
||||
[features]
|
||||
# Print some internal logs by log_utf8_string
|
||||
debug = ["marine-rs-sdk-main/debug"]
|
||||
|
||||
# Enable logger (this will cause log_utf8_string to appear in imports)
|
||||
logger = ["marine-rs-sdk-main/logger"]
|
Loading…
x
Reference in New Issue
Block a user