mirror of
https://github.com/fluencelabs/aquavm
synced 2025-03-15 20:40:50 +00:00
feat(testing-framework): tetraplet behavior (#396)
`behavior=tetraplet` annotation crates a service that returns call's tetraplets
This commit is contained in:
parent
9fe7afb897
commit
e5837e9171
129
crates/testing-framework/src/asserts/behavior.rs
Normal file
129
crates/testing-framework/src/asserts/behavior.rs
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 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 air_test_utils::{
|
||||||
|
prelude::{echo_call_service, unit_call_service},
|
||||||
|
CallServiceResult,
|
||||||
|
};
|
||||||
|
use nom::IResult;
|
||||||
|
use serde_json::json;
|
||||||
|
use strum::{AsRefStr, EnumDiscriminants, EnumString};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, EnumDiscriminants)]
|
||||||
|
#[strum_discriminants(strum(serialize_all = "snake_case"))]
|
||||||
|
#[strum_discriminants(derive(AsRefStr, EnumString))]
|
||||||
|
#[strum_discriminants(name(BehaviorTagName))]
|
||||||
|
pub enum Behavior {
|
||||||
|
Echo,
|
||||||
|
Unit,
|
||||||
|
Service,
|
||||||
|
Function,
|
||||||
|
Arg(usize),
|
||||||
|
Tetraplet,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn parse_behaviour(inp: &str) -> IResult<&str, Behavior, super::parser::ParseError> {
|
||||||
|
use nom::branch::alt;
|
||||||
|
use nom::bytes::complete::tag;
|
||||||
|
use nom::character::complete::u32 as u32_parse;
|
||||||
|
use nom::combinator::{map, value};
|
||||||
|
use nom::sequence::{pair, preceded};
|
||||||
|
|
||||||
|
alt((
|
||||||
|
value(Behavior::Echo, tag(BehaviorTagName::Echo.as_ref())),
|
||||||
|
value(Behavior::Unit, tag(BehaviorTagName::Unit.as_ref())),
|
||||||
|
value(Behavior::Function, tag(BehaviorTagName::Function.as_ref())),
|
||||||
|
value(Behavior::Service, tag(BehaviorTagName::Service.as_ref())),
|
||||||
|
map(
|
||||||
|
preceded(
|
||||||
|
pair(tag(BehaviorTagName::Arg.as_ref()), tag(".")),
|
||||||
|
u32_parse,
|
||||||
|
),
|
||||||
|
|n| Behavior::Arg(n as _),
|
||||||
|
),
|
||||||
|
value(
|
||||||
|
Behavior::Tetraplet,
|
||||||
|
tag(BehaviorTagName::Tetraplet.as_ref()),
|
||||||
|
),
|
||||||
|
))(inp)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Behavior {
|
||||||
|
pub(crate) fn call(&self, params: air_test_utils::CallRequestParams) -> CallServiceResult {
|
||||||
|
use Behavior::*;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
Echo => echo_call_service()(params),
|
||||||
|
Unit => unit_call_service()(params),
|
||||||
|
Function => CallServiceResult::ok(params.function_name.into()),
|
||||||
|
Service => CallServiceResult::ok(params.service_id.into()),
|
||||||
|
Arg(n) => match params.arguments.get(*n) {
|
||||||
|
Some(val) => CallServiceResult::ok(val.clone()),
|
||||||
|
None => CallServiceResult::err(
|
||||||
|
// TODO test-utils uses just json!{ "default" } value.
|
||||||
|
42,
|
||||||
|
json!("not enough arguments"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
Tetraplet => CallServiceResult::ok(serde_json::to_value(¶ms.tetraplets).unwrap()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_behavior_echo() {
|
||||||
|
let res = parse_behaviour("echo");
|
||||||
|
assert_eq!(
|
||||||
|
res,
|
||||||
|
Ok(("", Behavior::Echo)),
|
||||||
|
"{:?}",
|
||||||
|
BehaviorTagName::Echo.as_ref()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_behavior_unit() {
|
||||||
|
let res = parse_behaviour("unit");
|
||||||
|
assert_eq!(res, Ok(("", Behavior::Unit)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_behavior_service() {
|
||||||
|
let res = parse_behaviour("service");
|
||||||
|
assert_eq!(res, Ok(("", Behavior::Service)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_behavior_function() {
|
||||||
|
let res = parse_behaviour("function");
|
||||||
|
assert_eq!(res, Ok(("", Behavior::Function)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_behavior_arg() {
|
||||||
|
let res = parse_behaviour("arg.42");
|
||||||
|
assert_eq!(res, Ok(("", Behavior::Arg(42))));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_behavior_tetraplet() {
|
||||||
|
let res = parse_behaviour("tetraplet");
|
||||||
|
assert_eq!(res, Ok(("", Behavior::Tetraplet)));
|
||||||
|
}
|
||||||
|
}
|
@ -14,20 +14,20 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
mod behavior;
|
||||||
mod json;
|
mod json;
|
||||||
pub(crate) mod parser;
|
pub(crate) mod parser;
|
||||||
|
|
||||||
use crate::services::JValue;
|
use crate::services::JValue;
|
||||||
|
|
||||||
use air_test_utils::{
|
use air_test_utils::{CallRequestParams, CallServiceResult};
|
||||||
prelude::{echo_call_service, unit_call_service},
|
|
||||||
CallRequestParams, CallServiceResult,
|
|
||||||
};
|
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use strum::{AsRefStr, EnumDiscriminants, EnumString};
|
use strum::{AsRefStr, EnumDiscriminants, EnumString};
|
||||||
|
|
||||||
use std::{borrow::Cow, cell::Cell, collections::HashMap};
|
use std::{borrow::Cow, cell::Cell, collections::HashMap};
|
||||||
|
|
||||||
|
use self::behavior::Behavior;
|
||||||
|
|
||||||
/// Service definition in the testing framework comment DSL.
|
/// Service definition in the testing framework comment DSL.
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, EnumDiscriminants)]
|
#[derive(Debug, PartialEq, Eq, Clone, EnumDiscriminants)]
|
||||||
#[strum_discriminants(derive(AsRefStr, EnumString))]
|
#[strum_discriminants(derive(AsRefStr, EnumString))]
|
||||||
@ -53,7 +53,7 @@ pub enum ServiceDefinition {
|
|||||||
},
|
},
|
||||||
/// Some known service by name: "echo", "unit" (more to follow).
|
/// Some known service by name: "echo", "unit" (more to follow).
|
||||||
#[strum_discriminants(strum(serialize = "behaviour"))]
|
#[strum_discriminants(strum(serialize = "behaviour"))]
|
||||||
Behaviour(String),
|
Behaviour(Behavior),
|
||||||
/// Maps first argument to a value
|
/// Maps first argument to a value
|
||||||
#[strum_discriminants(strum(serialize = "map"))]
|
#[strum_discriminants(strum(serialize = "map"))]
|
||||||
Map(HashMap<String, JValue>),
|
Map(HashMap<String, JValue>),
|
||||||
@ -82,8 +82,8 @@ impl ServiceDefinition {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn behaviour(name: impl Into<String>) -> Self {
|
pub fn behaviour(name: Behavior) -> Self {
|
||||||
Self::Behaviour(name.into())
|
Self::Behaviour(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn map(map: HashMap<String, JValue>) -> Self {
|
pub fn map(map: HashMap<String, JValue>) -> Self {
|
||||||
@ -102,7 +102,7 @@ impl ServiceDefinition {
|
|||||||
ref call_number_seq,
|
ref call_number_seq,
|
||||||
call_map,
|
call_map,
|
||||||
} => call_seq_error(call_number_seq, call_map),
|
} => call_seq_error(call_number_seq, call_map),
|
||||||
ServiceDefinition::Behaviour(name) => call_named_service(name, params),
|
ServiceDefinition::Behaviour(name) => name.call(params),
|
||||||
ServiceDefinition::Map(map) => call_map_service(map, params),
|
ServiceDefinition::Map(map) => call_map_service(map, params),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -149,14 +149,6 @@ fn call_seq_error(
|
|||||||
.clone()
|
.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_named_service(name: &str, params: CallRequestParams) -> CallServiceResult {
|
|
||||||
match name {
|
|
||||||
"echo" => echo_call_service()(params),
|
|
||||||
"unit" => unit_call_service()(params),
|
|
||||||
_ => unreachable!("shoudn't be allowed by a parser"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call_map_service(
|
fn call_map_service(
|
||||||
map: &HashMap<String, serde_json::Value>,
|
map: &HashMap<String, serde_json::Value>,
|
||||||
args: CallRequestParams,
|
args: CallRequestParams,
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use super::{ServiceDefinition, ServiceTagName};
|
use super::{ServiceDefinition, ServiceTagName};
|
||||||
use crate::services::JValue;
|
|
||||||
use crate::transform::parser::delim_ws;
|
use crate::transform::parser::delim_ws;
|
||||||
|
|
||||||
use air_test_utils::CallServiceResult;
|
use air_test_utils::CallServiceResult;
|
||||||
@ -23,7 +22,7 @@ use nom::{error::VerboseError, IResult};
|
|||||||
|
|
||||||
use std::{collections::HashMap, str::FromStr};
|
use std::{collections::HashMap, str::FromStr};
|
||||||
|
|
||||||
type ParseError<'inp> = VerboseError<&'inp str>;
|
pub(crate) type ParseError<'inp> = VerboseError<&'inp str>;
|
||||||
|
|
||||||
impl FromStr for ServiceDefinition {
|
impl FromStr for ServiceDefinition {
|
||||||
type Err = String;
|
type Err = String;
|
||||||
@ -38,12 +37,12 @@ impl FromStr for ServiceDefinition {
|
|||||||
// kw "=" val
|
// kw "=" val
|
||||||
// example: "id=firstcall"
|
// example: "id=firstcall"
|
||||||
pub fn parse_kw(inp: &str) -> IResult<&str, ServiceDefinition, ParseError> {
|
pub fn parse_kw(inp: &str) -> IResult<&str, ServiceDefinition, ParseError> {
|
||||||
|
use super::behavior::parse_behaviour;
|
||||||
use nom::branch::alt;
|
use nom::branch::alt;
|
||||||
use nom::bytes::complete::tag;
|
use nom::bytes::complete::tag;
|
||||||
use nom::character::complete::alphanumeric1;
|
use nom::combinator::{cut, map, map_res, recognize};
|
||||||
use nom::combinator::{cut, map_res, recognize};
|
|
||||||
use nom::error::context;
|
use nom::error::context;
|
||||||
use nom::sequence::separated_pair;
|
use nom::sequence::{pair, preceded};
|
||||||
|
|
||||||
let equal = || delim_ws(tag("="));
|
let equal = || delim_ws(tag("="));
|
||||||
let json_value = || {
|
let json_value = || {
|
||||||
@ -59,45 +58,56 @@ pub fn parse_kw(inp: &str) -> IResult<&str, ServiceDefinition, ParseError> {
|
|||||||
))
|
))
|
||||||
};
|
};
|
||||||
|
|
||||||
delim_ws(map_res(
|
delim_ws(alt((
|
||||||
alt((
|
map_res(
|
||||||
separated_pair(tag(ServiceTagName::Ok.as_ref()), equal(), json_value()),
|
preceded(
|
||||||
separated_pair(tag(ServiceTagName::Error.as_ref()), equal(), json_map()),
|
pair(tag(ServiceTagName::Ok.as_ref()), equal()),
|
||||||
separated_pair(tag(ServiceTagName::SeqOk.as_ref()), equal(), json_map()),
|
json_value(),
|
||||||
separated_pair(tag(ServiceTagName::SeqError.as_ref()), equal(), json_map()),
|
|
||||||
separated_pair(
|
|
||||||
tag(ServiceTagName::Behaviour.as_ref()),
|
|
||||||
equal(),
|
|
||||||
cut(alphanumeric1),
|
|
||||||
),
|
),
|
||||||
separated_pair(tag(ServiceTagName::Map.as_ref()), equal(), json_map()),
|
|value| serde_json::from_str(value).map(ServiceDefinition::Ok),
|
||||||
)),
|
),
|
||||||
|(tag, value): (&str, &str)| {
|
map_res(
|
||||||
let value = value.trim();
|
preceded(
|
||||||
match ServiceTagName::from_str(tag) {
|
pair(tag(ServiceTagName::Error.as_ref()), equal()),
|
||||||
Ok(ServiceTagName::Ok) => {
|
json_map(),
|
||||||
serde_json::from_str::<JValue>(value).map(ServiceDefinition::ok)
|
),
|
||||||
}
|
|value| serde_json::from_str::<CallServiceResult>(value).map(ServiceDefinition::Error),
|
||||||
Ok(ServiceTagName::Error) => {
|
),
|
||||||
serde_json::from_str::<CallServiceResult>(value).map(ServiceDefinition::error)
|
map_res(
|
||||||
}
|
preceded(
|
||||||
Ok(ServiceTagName::SeqOk) => {
|
pair(tag(ServiceTagName::SeqOk.as_ref()), equal()),
|
||||||
serde_json::from_str(value).map(ServiceDefinition::seq_ok)
|
json_map(),
|
||||||
}
|
),
|
||||||
Ok(ServiceTagName::SeqError) => {
|
|value| serde_json::from_str(value).map(ServiceDefinition::seq_ok),
|
||||||
serde_json::from_str::<HashMap<String, CallServiceResult>>(value)
|
),
|
||||||
.map(ServiceDefinition::seq_error)
|
map_res(
|
||||||
}
|
preceded(
|
||||||
Ok(ServiceTagName::Behaviour) => Ok(ServiceDefinition::behaviour(value)),
|
pair(tag(ServiceTagName::SeqError.as_ref()), equal()),
|
||||||
Ok(ServiceTagName::Map) => serde_json::from_str(value).map(ServiceDefinition::map),
|
json_map(),
|
||||||
Err(_) => unreachable!("unknown tag {:?}", tag),
|
),
|
||||||
}
|
|value| {
|
||||||
},
|
serde_json::from_str::<HashMap<String, CallServiceResult>>(value)
|
||||||
))(inp)
|
.map(ServiceDefinition::seq_error)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
map(
|
||||||
|
preceded(
|
||||||
|
pair(tag(ServiceTagName::Behaviour.as_ref()), equal()),
|
||||||
|
cut(parse_behaviour),
|
||||||
|
),
|
||||||
|
ServiceDefinition::Behaviour,
|
||||||
|
),
|
||||||
|
map_res(
|
||||||
|
preceded(pair(tag(ServiceTagName::Map.as_ref()), equal()), json_map()),
|
||||||
|
|value| serde_json::from_str(value).map(ServiceDefinition::Map),
|
||||||
|
),
|
||||||
|
)))(inp)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use crate::asserts::behavior::Behavior;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
@ -217,7 +227,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_behaviour() {
|
fn test_behaviour() {
|
||||||
let res = ServiceDefinition::from_str(r#"behaviour=echo"#);
|
let res = ServiceDefinition::from_str(r#"behaviour=echo"#);
|
||||||
assert_eq!(res, Ok(ServiceDefinition::Behaviour("echo".to_owned())),);
|
assert_eq!(res, Ok(ServiceDefinition::Behaviour(Behavior::Echo)),);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -542,10 +542,7 @@ mod tests {
|
|||||||
impl MarineService for Service {
|
impl MarineService for Service {
|
||||||
fn call(&self, _params: CallRequestParams) -> crate::services::FunctionOutcome {
|
fn call(&self, _params: CallRequestParams) -> crate::services::FunctionOutcome {
|
||||||
let mut cell = self.state.borrow_mut();
|
let mut cell = self.state.borrow_mut();
|
||||||
crate::services::FunctionOutcome::ServiceResult(
|
crate::services::FunctionOutcome::from_value(cell.next().unwrap())
|
||||||
CallServiceResult::ok(cell.next().unwrap()),
|
|
||||||
<_>::default(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let service = Service {
|
let service = Service {
|
||||||
@ -606,4 +603,110 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_behaviour_service() {
|
||||||
|
let peer = "peer1";
|
||||||
|
let exec = AirScriptExecutor::new(
|
||||||
|
TestRunParameters::from_init_peer_id(peer),
|
||||||
|
vec![],
|
||||||
|
std::iter::empty(),
|
||||||
|
r#"(call "peer1" ("service" "func") [1 22] arg) ; behaviour=service"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let result_init: Vec<_> = exec.execution_iter(peer).unwrap().collect();
|
||||||
|
|
||||||
|
assert_eq!(result_init.len(), 1);
|
||||||
|
let outcome = &result_init[0];
|
||||||
|
assert_eq!(outcome.ret_code, 0);
|
||||||
|
assert_eq!(outcome.error_message, "");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
trace_from_result(outcome),
|
||||||
|
ExecutionTrace::from(vec![scalar_string("service"),]),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_behaviour_function() {
|
||||||
|
let peer = "peer1";
|
||||||
|
let exec = AirScriptExecutor::new(
|
||||||
|
TestRunParameters::from_init_peer_id(peer),
|
||||||
|
vec![],
|
||||||
|
std::iter::empty(),
|
||||||
|
r#"(call "peer1" ("service" "func") [1 22] arg) ; behaviour=function"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let result_init: Vec<_> = exec.execution_iter(peer).unwrap().collect();
|
||||||
|
|
||||||
|
assert_eq!(result_init.len(), 1);
|
||||||
|
let outcome = &result_init[0];
|
||||||
|
assert_eq!(outcome.ret_code, 0);
|
||||||
|
assert_eq!(outcome.error_message, "");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
trace_from_result(outcome),
|
||||||
|
ExecutionTrace::from(vec![scalar_string("func"),]),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_behaviour_arg() {
|
||||||
|
let peer = "peer1";
|
||||||
|
let exec = AirScriptExecutor::new(
|
||||||
|
TestRunParameters::from_init_peer_id(peer),
|
||||||
|
vec![],
|
||||||
|
std::iter::empty(),
|
||||||
|
r#"(call "peer1" ("service" "func") [1 22] arg) ; behaviour=arg.1"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let result_init: Vec<_> = exec.execution_iter(peer).unwrap().collect();
|
||||||
|
|
||||||
|
assert_eq!(result_init.len(), 1);
|
||||||
|
let outcome = &result_init[0];
|
||||||
|
assert_eq!(outcome.ret_code, 0);
|
||||||
|
assert_eq!(outcome.error_message, "");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
trace_from_result(outcome),
|
||||||
|
ExecutionTrace::from(vec![scalar_number(22),]),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_behaviour_tetraplet() {
|
||||||
|
let peer = "peer1";
|
||||||
|
let exec = AirScriptExecutor::new(
|
||||||
|
TestRunParameters::from_init_peer_id(peer),
|
||||||
|
vec![],
|
||||||
|
std::iter::empty(),
|
||||||
|
r#"(call "peer1" ("service" "func") [1 22] arg) ; behaviour=tetraplet"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let result_init: Vec<_> = exec.execution_iter(peer).unwrap().collect();
|
||||||
|
|
||||||
|
assert_eq!(result_init.len(), 1);
|
||||||
|
let outcome = &result_init[0];
|
||||||
|
assert_eq!(outcome.ret_code, 0);
|
||||||
|
assert_eq!(outcome.error_message, "");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
trace_from_result(outcome),
|
||||||
|
ExecutionTrace::from(vec![scalar(json!([[{
|
||||||
|
"function_name": "",
|
||||||
|
"json_path": "",
|
||||||
|
"peer_pk": "peer1",
|
||||||
|
"service_id": "",
|
||||||
|
}], [{
|
||||||
|
"function_name": "",
|
||||||
|
"json_path": "",
|
||||||
|
"peer_pk": "peer1",
|
||||||
|
"service_id": "",
|
||||||
|
}]]))]),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,16 @@ pub enum FunctionOutcome {
|
|||||||
Empty,
|
Empty,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FunctionOutcome {
|
||||||
|
pub fn from_service_result(service_result: CallServiceResult) -> Self {
|
||||||
|
FunctionOutcome::ServiceResult(service_result, Duration::ZERO)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_value(value: JValue) -> Self {
|
||||||
|
Self::from_service_result(CallServiceResult::ok(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A mocked Marine service.
|
/// A mocked Marine service.
|
||||||
pub trait MarineService {
|
pub trait MarineService {
|
||||||
fn call(&self, params: CallRequestParams) -> FunctionOutcome;
|
fn call(&self, params: CallRequestParams) -> FunctionOutcome;
|
||||||
|
@ -19,7 +19,7 @@ use crate::asserts::ServiceDefinition;
|
|||||||
|
|
||||||
use air_test_utils::CallRequestParams;
|
use air_test_utils::CallRequestParams;
|
||||||
|
|
||||||
use std::{cell::RefCell, collections::HashMap, rc::Rc, time::Duration};
|
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Eq)]
|
#[derive(Clone, Debug, Default, PartialEq, Eq)]
|
||||||
pub(crate) struct ResultStore {
|
pub(crate) struct ResultStore {
|
||||||
@ -36,18 +36,23 @@ impl ResultStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MarineService for ResultStore {
|
impl MarineService for ResultStore {
|
||||||
fn call(&self, params: CallRequestParams) -> FunctionOutcome {
|
fn call(&self, mut params: CallRequestParams) -> FunctionOutcome {
|
||||||
let results = self.results.borrow();
|
let results = self.results.borrow();
|
||||||
if let Some((_, suffix)) = params.service_id.split_once("..") {
|
|
||||||
if let Ok(key) = suffix.parse() {
|
let (real_service_id, suffix) = match params.service_id.rsplit_once("..") {
|
||||||
let service_desc = results.get(&key).expect("Unknown result id");
|
Some(split) => split,
|
||||||
let service_result = service_desc.call(params);
|
None => return FunctionOutcome::NotDefined,
|
||||||
FunctionOutcome::ServiceResult(service_result, Duration::ZERO)
|
};
|
||||||
} else {
|
|
||||||
// Pass malformed service names further in a chain
|
if let Ok(result_id) = suffix.parse::<usize>() {
|
||||||
FunctionOutcome::NotDefined
|
let service_desc = results
|
||||||
}
|
.get(&result_id)
|
||||||
|
.unwrap_or_else(|| panic!("failed to parse service name {:?}", params.service_id));
|
||||||
|
// hide the artificial service_id
|
||||||
|
params.service_id = real_service_id.to_owned();
|
||||||
|
FunctionOutcome::from_service_result(service_desc.call(params))
|
||||||
} else {
|
} else {
|
||||||
|
// Pass malformed service names further in a chain
|
||||||
FunctionOutcome::NotDefined
|
FunctionOutcome::NotDefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user