Refactor tests (#104)

This commit is contained in:
Mike Voronov 2021-05-16 22:52:22 +03:00 committed by GitHub
parent b96ee517f3
commit 7cb636a02e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
55 changed files with 2102 additions and 2606 deletions

View File

@ -26,7 +26,7 @@ jobs:
(cd air-interpreter; marine build --features marine)
# build Wasm binaries for tests
(cd air/tests/; ./build_test_binaries.sh)
(cd air/tests/test_module/integration; ./build_test_binaries.sh)
cargo fmt --all -- --check --color always
cargo check

View File

@ -133,7 +133,7 @@ jobs:
run: |
PATH="~/.cargo/bin:$PATH"
(
cd interpreter
cd air-interpreter
toml set Cargo.toml package.version "${{ env.FINAL_VERSION }}" | sponge Cargo.toml
)
(

3
Cargo.lock generated
View File

@ -84,8 +84,9 @@ dependencies = [
[[package]]
name = "air-test-utils"
version = "0.1.0"
version = "0.2.0"
dependencies = [
"air",
"avm-server",
"fluence",
"serde_json",

View File

@ -11,8 +11,8 @@ members = [
]
exclude = [
"air/tests/security_tetraplets/auth_module",
"air/tests/security_tetraplets/log_storage",
"air/tests/test_module/integration/security_tetraplets/auth_module",
"air/tests/test_module/integration/security_tetraplets/log_storage",
"crates/air-interpreter-wasm",
]

View File

@ -7,6 +7,7 @@ edition = "2018"
[lib]
name = "air"
path = "src/lib.rs"
doctest = false
[dependencies]
air-parser = { path = "../crates/air-parser" }

View File

@ -18,6 +18,7 @@ mod executed_state;
pub use executed_state::CallResult;
pub use executed_state::ExecutedState;
pub use executed_state::ParResult;
use serde::Deserialize;
use serde::Serialize;

View File

@ -20,6 +20,10 @@ use serde::Deserialize;
use serde::Serialize;
use std::rc::Rc;
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ParResult(pub usize, pub usize);
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum CallResult {
@ -36,17 +40,23 @@ pub enum CallResult {
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ExecutedState {
Par(usize, usize),
Par(ParResult),
Call(CallResult),
}
impl ExecutedState {
pub fn par(left: usize, right: usize) -> Self {
Self::Par(ParResult(left, right))
}
}
impl std::fmt::Display for ExecutedState {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use CallResult::*;
use ExecutedState::*;
match self {
Par(left, right) => write!(f, "Par({}, {})", left, right),
Par(ParResult(left, right)) => write!(f, "Par({}, {})", left, right),
Call(RequestSentBy(peer_id)) => write!(f, "RequestSentBy({})", peer_id),
Call(Executed(result)) => write!(f, "Executed({:?})", result),
Call(CallServiceFailed(ret_code, err_msg)) => write!(f, "CallServiceFailed({}, {})", ret_code, err_msg),

View File

@ -22,6 +22,7 @@ pub mod execution_trace {
pub use super::execution_trace_context::ExecutedState;
pub use super::execution_trace_context::ExecutionTrace;
pub(crate) use super::execution_trace_context::ExecutionTraceCtx;
pub use super::execution_trace_context::ParResult;
}
pub(crate) mod execution {

View File

@ -65,178 +65,3 @@ fn set_last_error<'i>(
exec_ctx.last_error = Some(last_error);
exec_ctx.last_error_could_be_set = false;
}
#[cfg(test)]
mod tests {
use crate::contexts::execution_trace::ExecutionTrace;
use crate::JValue;
use air_test_utils::call_vm;
use air_test_utils::create_avm;
use air_test_utils::echo_string_call_service;
use air_test_utils::set_variable_call_service;
use air_test_utils::unit_call_service;
use air_test_utils::CallServiceClosure;
use air_test_utils::IValue;
use air_test_utils::NEVec;
use std::rc::Rc;
// Check that %init_peer_id% alias works correctly (by comparing result with it and explicit peer id).
// Additionally, check that empty string for data does the same as empty call path.
#[test]
fn current_peer_id_call() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
let vm_peer_id = String::from("test_peer_id");
let mut vm = create_avm(unit_call_service(), vm_peer_id.clone());
let service_id = String::from("local_service_id");
let function_name = String::from("local_fn_name");
let script = format!(
r#"
(call %init_peer_id% ("{}" "{}") [] result_name)
"#,
service_id, function_name
);
let res = call_vm!(vm, vm_peer_id.clone(), script.clone(), "[]", "[]");
let call_path: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be a valid json");
let executed_call_state = Call(Executed(Rc::new(JValue::String(String::from("test")))));
assert_eq!(call_path.len(), 1);
assert_eq!(call_path[0], executed_call_state);
assert!(res.next_peer_pks.is_empty());
let script = format!(
r#"
(call "{}" ("{}" "{}") [] result_name)
"#,
vm_peer_id, service_id, function_name
);
let res = call_vm!(vm, "asd", script.clone(), "[]", "[]");
// test that empty string for data works
let res_with_empty_string = call_vm!(vm, "asd", script, "", "");
assert_eq!(res_with_empty_string, res);
}
// Check that specifying remote peer id in call will result its appearing in next_peer_pks.
#[test]
fn remote_peer_id_call() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
let some_local_peer_id = String::from("some_local_peer_id");
let mut vm = create_avm(echo_string_call_service(), some_local_peer_id.clone());
let remote_peer_id = String::from("some_remote_peer_id");
let script = format!(
r#"(call "{}" ("local_service_id" "local_fn_name") ["arg"] result_name)"#,
remote_peer_id
);
let res = call_vm!(vm, "asd", script, "[]", "[]");
let call_path: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be a valid json");
assert_eq!(call_path.len(), 1);
assert_eq!(call_path[0], Call(RequestSentBy(some_local_peer_id)));
assert_eq!(res.next_peer_pks, vec![remote_peer_id]);
}
// Check that setting variables works as expected.
#[test]
fn variables() {
let mut vm = create_avm(unit_call_service(), "remote_peer_id");
let mut set_variable_vm = create_avm(set_variable_call_service(r#""remote_peer_id""#), "set_variable");
let script = format!(
r#"
(seq
(call "set_variable" ("some_service_id" "local_fn_name") [] remote_peer_id)
(call remote_peer_id ("some_service_id" "local_fn_name") [] result_name)
)
"#,
);
let res = call_vm!(set_variable_vm, "asd", script.clone(), "[]", "[]");
let res = call_vm!(vm, "asd", script, "[]", res.data);
assert!(res.next_peer_pks.is_empty());
}
// Check that duplicate variables are impossible.
#[test]
fn duplicate_variables() {
let mut vm = create_avm(unit_call_service(), "some_peer_id");
let script = format!(
r#"
(seq
(call "some_peer_id" ("some_service_id" "local_fn_name") [] modules)
(call "some_peer_id" ("some_service_id" "local_fn_name") [] modules)
)
"#,
);
let res = call_vm!(vm, "asd", script, "", "");
assert_eq!(res.ret_code, 1005);
assert!(res.next_peer_pks.is_empty());
}
// Check that string literals can be used as call parameters.
#[test]
fn string_parameters() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
let call_service: CallServiceClosure = Box::new(|_, args| -> Option<IValue> {
let arg = match &args[2] {
IValue::String(str) => str,
_ => unreachable!(),
};
Some(IValue::Record(
NEVec::new(vec![IValue::S32(0), IValue::String(arg.clone())]).unwrap(),
))
});
let vm_peer_id = String::from("A");
let mut vm = create_avm(call_service, vm_peer_id.clone());
let set_variable_vm_peer_id = String::from("set_variable");
let mut set_variable_vm = create_avm(
set_variable_call_service(r#""arg3_value""#),
set_variable_vm_peer_id.clone(),
);
let service_id = String::from("some_service_id");
let function_name = String::from("local_fn_name");
let script = format!(
r#"
(seq
(call "{}" ("{}" "{}") [] arg3)
(call "{}" ("{}" "{}") ["arg1" "arg2" arg3] result)
)
"#,
set_variable_vm_peer_id, service_id, function_name, vm_peer_id, service_id, function_name
);
let res = call_vm!(set_variable_vm, "asd", script.clone(), "[]", "[]");
let res = call_vm!(vm, "asd", script, "[]", res.data);
let call_path: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be a valid json");
assert_eq!(call_path.len(), 2);
assert_eq!(
call_path[1],
Call(Executed(Rc::new(JValue::Array(vec![
JValue::String(String::from("arg1")),
JValue::String(String::from("arg2")),
JValue::String(String::from("arg3_value")),
]))))
);
}
}

View File

@ -153,402 +153,3 @@ fn cleanup_variables(exec_ctx: &mut ExecutionCtx<'_>, iterator: &str) {
exec_ctx.data_cache.extend(upper_fold_values);
}
}
#[cfg(test)]
mod tests {
use crate::contexts::execution_trace::ExecutionTrace;
use crate::JValue;
use air_test_utils::call_vm;
use air_test_utils::create_avm;
use air_test_utils::echo_number_call_service;
use air_test_utils::echo_string_call_service;
use air_test_utils::set_variable_call_service;
use air_test_utils::AVMError;
use air_test_utils::InterpreterOutcome;
use serde_json::json;
use std::rc::Rc;
#[test]
fn lfold() {
env_logger::try_init().ok();
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
let mut vm = create_avm(echo_number_call_service(), "A");
let mut set_variable_vm = create_avm(set_variable_call_service(r#"["1","2","3","4","5"]"#), "set_variable");
let lfold = String::from(
r#"
(seq
(call "set_variable" ("" "") [] Iterable)
(fold Iterable i
(seq
(call "A" ("" "") [i] $acc)
(next i)
)
)
)"#,
);
let res = call_vm!(set_variable_vm, "", lfold.clone(), "[]", "[]");
let res = call_vm!(vm, "", lfold, "[]", res.data);
let res: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid executed trace");
assert_eq!(res.len(), 6);
assert_eq!(res[0], Call(Executed(Rc::new(json!(["1", "2", "3", "4", "5"])))));
for i in 1..=5 {
assert_eq!(res[i], Call(Executed(Rc::new(JValue::Number(i.into())))));
}
}
#[test]
fn rfold() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
let mut vm = create_avm(echo_number_call_service(), "A");
let mut set_variable_vm = create_avm(set_variable_call_service(r#"["1","2","3","4","5"]"#), "set_variable");
let rfold = String::from(
r#"
(seq
(call "set_variable" ("" "") [] Iterable)
(fold Iterable i
(seq
(next i)
(call "A" ("" "") [i] $acc)
)
)
)"#,
);
let res = call_vm!(set_variable_vm, "", rfold.clone(), "[]", "[]");
let res = call_vm!(vm, "", rfold, "[]", res.data);
let res: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid executed trace");
assert_eq!(res.len(), 6);
assert_eq!(res[0], Call(Executed(Rc::new(json!(["1", "2", "3", "4", "5"])))));
for i in 1..=5 {
assert_eq!(res[i], Call(Executed(Rc::new(JValue::Number((6 - i).into())))));
}
}
#[test]
fn inner_fold() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
let mut vm = create_avm(echo_number_call_service(), "A");
let mut set_variable_vm = create_avm(set_variable_call_service(r#"["1","2","3","4","5"]"#), "set_variable");
let script = String::from(
r#"
(seq
(seq
(call "set_variable" ("" "") [] Iterable1)
(call "set_variable" ("" "") [] Iterable2)
)
(fold Iterable1 i
(seq
(fold Iterable2 j
(seq
(call "A" ("" "") [i] $acc)
(next j)
)
)
(next i)
)
)
)"#,
);
let res = call_vm!(set_variable_vm, "", script.clone(), "[]", "[]");
let res = call_vm!(vm, "", script, "[]", res.data);
let res: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid executed trace");
assert_eq!(res.len(), 27);
assert_eq!(res[0], Call(Executed(Rc::new(json!(["1", "2", "3", "4", "5"])))));
assert_eq!(res[1], Call(Executed(Rc::new(json!(["1", "2", "3", "4", "5"])))));
for i in 1..=5 {
for j in 1..=5 {
assert_eq!(
res[1 + 5 * (i - 1) + j],
Call(Executed(Rc::new(JValue::Number(i.into()))))
);
}
}
}
#[test]
fn inner_fold_with_same_iterator() {
let mut vm = create_avm(set_variable_call_service(r#"["1","2","3","4","5"]"#), "set_variable");
let script = String::from(
r#"
(seq
(seq
(call "set_variable" ("" "") [] Iterable1)
(call "set_variable" ("" "") [] Iterable2)
)
(fold Iterable1 i
(seq
(fold Iterable2 i
(seq
(call "A" ("" "") [i] $acc)
(next i)
)
)
(next i)
)
)
)"#,
);
let res = call_vm!(vm, "", script, "[]", "[]");
assert_eq!(res.ret_code, 1012);
}
#[test]
fn empty_fold() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
let mut vm = create_avm(echo_number_call_service(), "A");
let mut set_variable_vm = create_avm(set_variable_call_service(r#"[]"#), "set_variable");
let empty_fold = String::from(
r#"
(seq
(call "set_variable" ("" "") [] Iterable)
(fold Iterable i
(seq
(call "A" ("" "") [i] $acc)
(next i)
)
)
)"#,
);
let res = call_vm!(set_variable_vm, "", empty_fold.clone(), "[]", "[]");
let res = call_vm!(vm, "", empty_fold, "[]", res.data);
let res: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid executed trace");
assert_eq!(res.len(), 1);
assert_eq!(res[0], Call(Executed(Rc::new(json!([])))));
}
#[test]
fn empty_fold_json_path() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
let mut vm = create_avm(echo_number_call_service(), "A");
let mut set_variable_vm = create_avm(set_variable_call_service(r#"{ "messages": [] }"#), "set_variable");
let empty_fold = r#"
(seq
(call "set_variable" ("" "") [] messages)
(fold messages.$.messages! i
(seq
(call "A" ("" "") [i] $acc)
(next i)
)
)
)"#;
let res = call_vm!(set_variable_vm, "", empty_fold, "", "");
let res = call_vm!(vm, "", empty_fold, "", res.data);
let res: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid executed trace");
assert_eq!(res.len(), 1);
assert_eq!(res[0], Call(Executed(Rc::new(json!({ "messages": [] })))));
}
// Check that fold works with the join behaviour without hanging up.
#[test]
fn fold_with_join() {
let mut vm = create_avm(echo_number_call_service(), "A");
let mut set_variable_vm = create_avm(set_variable_call_service(r#"["1","2"]"#), "set_variable");
let fold_with_join = String::from(
r#"
(seq
(call "set_variable" ("" "") [] iterable)
(par
(call "unknown_peer" ("" "") [] lazy_def_variable)
(fold iterable i
(seq
(call "A" ("" "") [lazy_def_variable.$.hash!] $acc)
(next i)
)
)
)
)"#,
);
let res = call_vm!(set_variable_vm, "", &fold_with_join, "", "");
let res = call_vm!(vm, "", fold_with_join, "", res.data);
let res: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid executed trace");
assert_eq!(res.len(), 3);
}
#[test]
fn json_path() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
let mut vm = create_avm(echo_number_call_service(), "A");
let mut set_variable_vm = create_avm(
set_variable_call_service(r#"{ "array": ["1","2","3","4","5"] }"#),
"set_variable",
);
let lfold = String::from(
r#"
(seq
(call "set_variable" ("" "") [] iterable)
(fold iterable.$.array! i
(seq
(call "A" ("" "") [i] $acc)
(next i)
)
)
)"#,
);
let res = call_vm!(set_variable_vm, "", lfold.clone(), "[]", "[]");
let res = call_vm!(vm, "", lfold, "[]", res.data);
let res: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid executed trace");
assert_eq!(res.len(), 6);
assert_eq!(
res[0],
Call(Executed(Rc::new(json!({ "array": ["1", "2", "3", "4", "5"] }))))
);
for i in 1..=5 {
assert_eq!(res[i], Call(Executed(Rc::new(JValue::Number(i.into())))));
}
}
#[test]
fn shadowing() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
let mut set_variables_vm = create_avm(set_variable_call_service(r#"["1","2"]"#), "set_variable");
let mut vm_a = create_avm(echo_string_call_service(), "A");
let mut vm_b = create_avm(echo_string_call_service(), "B");
let script = String::from(
r#"
(seq
(seq
(call "set_variable" ("" "") [] iterable1)
(call "set_variable" ("" "") [] iterable2)
)
(fold iterable1 i
(seq
(seq
(fold iterable2 j
(seq
(seq
(call "A" ("" "") [i] local_j)
(call "B" ("" "") [local_j])
)
(next j)
)
)
(par
(call "A" ("" "") [i] local_i)
(call "B" ("" "") [i])
)
)
(next i)
)
)
)"#,
);
let res = call_vm!(set_variables_vm, "", script.clone(), "[]", "[]");
let res = call_vm!(vm_a, "", script.clone(), "[]", res.data);
let res = call_vm!(vm_b, "", script.clone(), "[]", res.data);
let res = call_vm!(vm_a, "", script.clone(), "[]", res.data);
let res = call_vm!(vm_b, "", script.clone(), "[]", res.data);
let res = call_vm!(vm_a, "", script.clone(), "[]", res.data);
let res = call_vm!(vm_b, "", script, "[]", res.data);
let res: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid executed trace");
assert_eq!(res.len(), 12);
for i in 2..11 {
assert!(matches!(res[i], Call(Executed(_))) || matches!(res[i], Par(..)));
}
}
#[test]
fn shadowing_scope() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
fn execute_script(script: String) -> Result<InterpreterOutcome, AVMError> {
let mut set_variables_vm = create_avm(set_variable_call_service(r#"["1","2"]"#), "set_variable");
let mut vm_a = create_avm(echo_string_call_service(), "A");
let mut vm_b = create_avm(echo_string_call_service(), "B");
let res = call_vm!(set_variables_vm, "", script.clone(), "[]", "[]");
let res = call_vm!(vm_a, "", script.clone(), "[]", res.data);
let res = call_vm!(vm_b, "", script.clone(), "[]", res.data);
let res = call_vm!(vm_a, "", script.clone(), "[]", res.data);
let res = call_vm!(vm_b, "", script.clone(), "[]", res.data);
vm_a.call_with_prev_data("", script, "[]", res.data)
}
let variable_shadowing_script = String::from(
r#"
(seq
(seq
(call "set_variable" ("" "") [] iterable1)
(call "set_variable" ("" "") [] iterable2)
)
(fold iterable1 i
(seq
(seq
(call "A" ("" "") ["value"] local_j)
(seq
(fold iterable2 j
(seq
(seq
(call "A" ("" "") [i] local_j)
(call "B" ("" "") [local_j])
)
(next j)
)
)
(call "A" ("" "") [local_j])
)
)
(next i)
)
)
)"#,
);
let res = execute_script(variable_shadowing_script).unwrap();
let res: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid executed trace");
assert_eq!(res.len(), 11);
for i in 0..10 {
assert!(matches!(res[i], Call(Executed(_))));
}
}
}

View File

@ -40,253 +40,3 @@ impl<'i> super::ExecutableInstruction<'i> for Match<'i> {
self.instruction.execute(exec_ctx, trace_ctx)
}
}
#[cfg(test)]
mod tests {
use crate::contexts::execution_trace::ExecutionTrace;
use crate::JValue;
use air_test_utils::create_avm;
use air_test_utils::echo_string_call_service;
use air_test_utils::{call_vm, set_variable_call_service};
use std::rc::Rc;
#[test]
fn match_equal() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
let set_variable_peer_id = "set_variable_peer_id";
let mut set_variable_vm = create_avm(echo_string_call_service(), set_variable_peer_id);
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = format!(
r#"
(seq
(seq
(call "{0}" ("" "") ["value_1"] value_1)
(call "{0}" ("" "") ["value_1"] value_2)
)
(xor
(match value_1 value_2
(call "{1}" ("service_id_2" "local_fn_name") ["result_1"] result_1)
)
(call "{1}" ("service_id_2" "local_fn_name") ["result_2"] result_2)
)
)"#,
set_variable_peer_id, local_peer_id
);
let res = call_vm!(set_variable_vm, "asd", script.clone(), "", "");
let res = call_vm!(vm, "asd", script, "", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
let expected_executed_call_result = Call(Executed(Rc::new(JValue::String(String::from("result_1")))));
assert_eq!(actual_trace.len(), 3);
assert_eq!(actual_trace[2], expected_executed_call_result);
}
#[test]
fn match_not_equal() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
let set_variable_peer_id = "set_variable_peer_id";
let mut set_variable_vm = create_avm(echo_string_call_service(), set_variable_peer_id);
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = format!(
r#"
(seq
(seq
(call "{0}" ("" "") ["value_1"] value_1)
(call "{0}" ("" "") ["value_2"] value_2)
)
(xor
(match value_1 value_2
(call "{1}" ("service_id_2" "local_fn_name") ["result_1"] result_1)
)
(call "{1}" ("service_id_2" "local_fn_name") ["result_2"] result_2)
)
)"#,
set_variable_peer_id, local_peer_id
);
let res = call_vm!(set_variable_vm, "asd", script.clone(), "", "");
let res = call_vm!(vm, "asd", script, "", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
let expected_executed_call_result = Call(Executed(Rc::new(JValue::String(String::from("result_2")))));
assert_eq!(actual_trace.len(), 3);
assert_eq!(actual_trace[2], expected_executed_call_result);
}
#[test]
fn match_with_string() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
let set_variable_peer_id = "set_variable_peer_id";
let mut set_variable_vm = create_avm(echo_string_call_service(), set_variable_peer_id);
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = format!(
r#"
(seq
(call "{0}" ("" "") ["value_1"] value_1)
(xor
(match value_1 "value_1"
(call "{1}" ("service_id_2" "local_fn_name") ["result_1"] result_1)
)
(call "{1}" ("service_id_2" "local_fn_name") ["result_2"] result_2)
)
)"#,
set_variable_peer_id, local_peer_id
);
let res = call_vm!(set_variable_vm, "asd", script.clone(), "", "");
let res = call_vm!(vm, "asd", script, "", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
let expected_executed_call_result = Call(Executed(Rc::new(JValue::String(String::from("result_1")))));
assert_eq!(actual_trace.len(), 2);
assert_eq!(actual_trace[1], expected_executed_call_result);
}
#[test]
fn match_with_init_peer_id() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
let set_variable_peer_id = "set_variable_peer_id";
let mut set_variable_vm = create_avm(echo_string_call_service(), set_variable_peer_id);
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = format!(
r#"
(seq
(call "{0}" ("" "") ["{1}"] value_1)
(xor
(match value_1 %init_peer_id%
(call "{1}" ("service_id_2" "local_fn_name") ["result_1"] result_1)
)
(call "{1}" ("service_id_2" "local_fn_name") ["result_2"] result_2)
)
)"#,
set_variable_peer_id, local_peer_id
);
let res = call_vm!(set_variable_vm, local_peer_id, script.clone(), "", "");
let res = call_vm!(vm, local_peer_id, script, "", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
let expected_executed_call_result = Call(Executed(Rc::new(JValue::String(String::from("result_1")))));
assert_eq!(actual_trace.len(), 2);
assert_eq!(actual_trace[1], expected_executed_call_result);
}
#[test]
fn match_with_equal_numbers() {
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = "
(xor
(match 1 1
(null)
)
(null)
)";
let res = call_vm!(vm, "asd", script, "", "");
assert_eq!(res.ret_code, 0);
}
#[test]
fn match_without_xor() {
let set_variable_peer_id = "set_variable_peer_id";
let mut set_variable_vm = create_avm(echo_string_call_service(), set_variable_peer_id);
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = format!(
r#"
(seq
(seq
(call "{0}" ("" "") ["value_1"] value_1)
(call "{0}" ("" "") ["value_2"] value_2)
)
(match value_1 value_2
(call "{1}" ("service_id_2" "local_fn_name") ["result_1"] result_1)
)
)"#,
set_variable_peer_id, local_peer_id
);
let res = call_vm!(set_variable_vm, "asd", script.clone(), "", "");
let res = call_vm!(vm, "asd", script.clone(), "", res.data);
assert_eq!(res.ret_code, 1015);
let res = call_vm!(vm, "asd", script, "", res.data);
assert_eq!(res.ret_code, 1015);
}
#[test]
fn match_with_two_xors() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
let local_peer_id = "local_peer_id";
let mut vm = create_avm(
set_variable_call_service(serde_json::json!(false).to_string()),
local_peer_id,
);
let local_peer_id_2 = "local_peer_id_2";
let script = format!(
r#"
(xor
(seq
(seq
(call "{0}" ("getDataSrv" "condition") [] condition)
(call "{0}" ("getDataSrv" "relay") [] relay)
)
(xor
(match condition true
(call "{0}" ("println" "print") ["it is true"])
)
(call "{1}" ("println" "print") ["it is false"])
)
)
(call "{0}" ("errorHandlingSrv" "error") [%last_error%])
)
"#,
local_peer_id, local_peer_id_2
);
let res = call_vm!(vm, "", script, "", "");
let mut trace: ExecutionTrace =
serde_json::from_slice(&res.data).expect("the interpreter should provide correct trace");
let expected_executed_call_result = Call(RequestSentBy(local_peer_id.to_string()));
assert_eq!(res.ret_code, 0);
assert_eq!(trace.pop_back().unwrap(), expected_executed_call_result);
}
}

View File

@ -40,202 +40,3 @@ impl<'i> super::ExecutableInstruction<'i> for MisMatch<'i> {
self.instruction.execute(exec_ctx, trace_ctx)
}
}
#[cfg(test)]
mod tests {
use crate::contexts::execution_trace::ExecutionTrace;
use crate::JValue;
use air_test_utils::call_vm;
use air_test_utils::create_avm;
use air_test_utils::echo_string_call_service;
use air_test_utils::set_variable_call_service;
use std::rc::Rc;
#[test]
fn mismatch_equal() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
let set_variable_peer_id = "set_variable_peer_id";
let mut set_variable_vm = create_avm(echo_string_call_service(), set_variable_peer_id);
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = format!(
r#"
(seq
(seq
(call "{0}" ("" "") ["value_1"] value_1)
(call "{0}" ("" "") ["value_1"] value_2)
)
(xor
(mismatch value_1 value_2
(call "{1}" ("service_id_2" "local_fn_name") ["result_1"] result_1)
)
(call "{1}" ("service_id_2" "local_fn_name") ["result_2"] result_2)
)
)"#,
set_variable_peer_id, local_peer_id
);
let res = call_vm!(set_variable_vm, "asd", script.clone(), "", "");
let res = call_vm!(vm, "asd", script, "", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
let expected_executed_call_result = Call(Executed(Rc::new(JValue::String(String::from("result_2")))));
assert_eq!(actual_trace.len(), 3);
assert_eq!(actual_trace[2], expected_executed_call_result);
}
#[test]
fn mismatch_not_equal() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
let set_variable_peer_id = "set_variable_peer_id";
let mut set_variable_vm = create_avm(echo_string_call_service(), set_variable_peer_id);
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = format!(
r#"
(seq
(seq
(call "{0}" ("" "") ["value_1"] value_1)
(call "{0}" ("" "") ["value_2"] value_2)
)
(xor
(mismatch value_1 value_2
(call "{1}" ("service_id_2" "local_fn_name") ["result_1"] result_1)
)
(call "{1}" ("service_id_2" "local_fn_name") ["result_2"] result_2)
)
)"#,
set_variable_peer_id, local_peer_id
);
let res = call_vm!(set_variable_vm, "asd", script.clone(), "", "");
let res = call_vm!(vm, "asd", script, "", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
let expected_executed_call_result = Call(Executed(Rc::new(JValue::String(String::from("result_1")))));
assert_eq!(actual_trace.len(), 3);
assert_eq!(actual_trace[2], expected_executed_call_result);
}
#[test]
fn mismatch_with_string() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
let set_variable_peer_id = "set_variable_peer_id";
let mut set_variable_vm = create_avm(echo_string_call_service(), set_variable_peer_id);
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = format!(
r#"
(seq
(call "{0}" ("" "") ["value_1"] value_1)
(xor
(mismatch value_1 "value_1"
(call "{1}" ("service_id_2" "local_fn_name") ["result_1"] result_1)
)
(call "{1}" ("service_id_2" "local_fn_name") ["result_2"] result_2)
)
)"#,
set_variable_peer_id, local_peer_id
);
let res = call_vm!(set_variable_vm, "asd", script.clone(), "", "");
let res = call_vm!(vm, "asd", script, "", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
let expected_executed_call_result = Call(Executed(Rc::new(JValue::String(String::from("result_2")))));
assert_eq!(actual_trace.len(), 2);
assert_eq!(actual_trace[1], expected_executed_call_result);
}
#[test]
fn mismatch_without_xor() {
let set_variable_peer_id = "set_variable_peer_id";
let mut set_variable_vm = create_avm(echo_string_call_service(), set_variable_peer_id);
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = format!(
r#"
(seq
(seq
(call "{0}" ("" "") ["value_1"] value_1)
(call "{0}" ("" "") ["value_1"] value_2)
)
(mismatch value_1 value_2
(call "{1}" ("service_id_2" "local_fn_name") ["result_1"] result_1)
)
)"#,
set_variable_peer_id, local_peer_id
);
let res = call_vm!(set_variable_vm, "asd", script.clone(), "", "");
let res = call_vm!(vm, "asd", script.clone(), "", res.data);
assert_eq!(res.ret_code, 1016);
let res = call_vm!(vm, "asd", script, "", res.data);
assert_eq!(res.ret_code, 1016);
}
#[test]
fn mismatch_with_two_xors() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
let local_peer_id = "local_peer_id";
let mut vm = create_avm(
set_variable_call_service(serde_json::json!(false).to_string()),
local_peer_id,
);
let local_peer_id_2 = "local_peer_id_2";
let script = format!(
r#"
(xor
(seq
(seq
(call "{0}" ("getDataSrv" "condition") [] condition)
(call "{0}" ("getDataSrv" "relay") [] relay)
)
(xor
(mismatch condition true
(call "{1}" ("println" "print") ["it is false"])
)
(call "{0}" ("println" "print") ["it is true"])
)
)
(call "{0}" ("errorHandlingSrv" "error") [%last_error%])
)
"#,
local_peer_id, local_peer_id_2
);
let res = call_vm!(vm, "", script, "", "");
let mut trace: ExecutionTrace =
serde_json::from_slice(&res.data).expect("the interpreter should provide correct trace");
let expected_executed_call_result = Call(RequestSentBy(local_peer_id.to_string()));
assert_eq!(res.ret_code, 0);
assert_eq!(trace.pop_back().unwrap(), expected_executed_call_result);
}
}

View File

@ -20,6 +20,7 @@ use super::ExecutionResult;
use super::ExecutionTraceCtx;
use super::Instruction;
use crate::contexts::execution_trace::ExecutedState;
use crate::contexts::execution_trace::ParResult;
use crate::log_instruction;
use crate::log_targets::EXECUTED_STATE_CHANGING;
@ -48,7 +49,7 @@ impl<'i> ExecutableInstruction<'i> for Par<'i> {
let (left_subtree_size, right_subtree_size) = extract_subtree_sizes(trace_ctx)?;
let par_pos = trace_ctx.new_trace.len();
trace_ctx.new_trace.push_back(ExecutedState::Par(0, 0));
trace_ctx.new_trace.push_back(ExecutedState::par(0, 0));
// execute a left subtree of this par
execute_subtree(&self.0, left_subtree_size, exec_ctx, trace_ctx, par_pos, Left)?;
@ -82,7 +83,7 @@ fn extract_subtree_sizes(trace_ctx: &mut ExecutionTraceCtx) -> ExecutionResult<(
// unwrap is safe here because of length's been checked
match trace_ctx.current_trace.pop_front().unwrap() {
ExecutedState::Par(left, right) => Ok((left, right)),
ExecutedState::Par(ParResult(left, right)) => Ok((left, right)),
state => crate::exec_err!(InvalidExecutedState(String::from("par"), state)),
}
}
@ -146,7 +147,7 @@ fn update_par_state(
// unwrap is safe here, because this par is added at the beginning of this par instruction.
let par_state = trace_ctx.new_trace.get_mut(current_par_pos).unwrap();
match par_state {
ExecutedState::Par(left, right) => {
ExecutedState::Par(ParResult(left, right)) => {
if let SubtreeType::Left = subtree_type {
*left = new_subtree_size;
} else {
@ -163,52 +164,3 @@ fn update_par_state(
_ => unreachable!("current_pas_pos must point to a par state"),
}
}
#[cfg(test)]
mod tests {
use air_test_utils::call_vm;
use air_test_utils::create_avm;
use air_test_utils::unit_call_service;
#[test]
fn par_remote_remote() {
use std::collections::HashSet;
let mut vm = create_avm(unit_call_service(), "");
let script = String::from(
r#"
(par
(call "remote_peer_id_1" ("local_service_id" "local_fn_name") [] result_name)
(call "remote_peer_id_2" ("service_id" "fn_name") [] g)
)"#,
);
let mut res = call_vm!(vm, "", script, "[]", "[]");
let peers_result: HashSet<_> = res.next_peer_pks.drain(..).collect();
let peers_right: HashSet<_> =
maplit::hashset!(String::from("remote_peer_id_1"), String::from("remote_peer_id_2"));
assert_eq!(peers_result, peers_right);
}
#[test]
fn par_local_remote() {
let local_peer_id = "local_peer_id";
let mut vm = create_avm(unit_call_service(), local_peer_id);
let script = format!(
r#"
(par
(call "{}" ("local_service_id" "local_fn_name") [] result_name)
(call "remote_peer_id_2" ("service_id" "fn_name") [] g)
)"#,
local_peer_id
);
let res = call_vm!(vm, "", script, "[]", "[]");
assert_eq!(res.next_peer_pks, vec![String::from("remote_peer_id_2")]);
}
}

View File

@ -35,50 +35,3 @@ impl<'i> super::ExecutableInstruction<'i> for Seq<'i> {
Ok(())
}
}
#[cfg(test)]
mod tests {
use air_test_utils::call_vm;
use air_test_utils::create_avm;
use air_test_utils::unit_call_service;
use serde_json::json;
#[test]
fn seq_remote_remote() {
let mut vm = create_avm(unit_call_service(), "");
let script = String::from(
r#"
(seq
(call "remote_peer_id_1" ("local_service_id" "local_fn_name") [] result_name)
(call "remote_peer_id_2" ("service_id" "fn_name") [] g)
)"#,
);
let res = call_vm!(vm, "asd", script.clone(), "[]", "[]");
assert_eq!(res.next_peer_pks, vec![String::from("remote_peer_id_1")]);
let res = call_vm!(vm, "asd", script, "[]", json!([{"call": {"executed": ""}}]).to_string());
assert_eq!(res.next_peer_pks, vec![String::from("remote_peer_id_2")]);
}
#[test]
fn seq_local_remote() {
let local_peer_id = "local_peer_id";
let remote_peer_id = String::from("remote_peer_id");
let mut vm = create_avm(unit_call_service(), local_peer_id);
let script = format!(
r#"
(seq
(call "{}" ("local_service_id" "local_fn_name") [] result_name)
(call "{}" ("service_id" "fn_name") [] g)
)"#,
local_peer_id, remote_peer_id
);
let res = call_vm!(vm, "asd", script, "[]", "[]");
assert_eq!(res.next_peer_pks, vec![remote_peer_id]);
}
}

View File

@ -56,206 +56,3 @@ fn print_xor_log(e: &ExecutionError) {
e => log::warn!("xor caught an error: {}", e),
}
}
#[cfg(test)]
mod tests {
use crate::contexts::execution_trace::ExecutionTrace;
use crate::JValue;
use air_test_utils::call_vm;
use air_test_utils::create_avm;
use air_test_utils::fallible_call_service;
use std::rc::Rc;
#[test]
fn xor() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
let local_peer_id = "local_peer_id";
let fallible_service_id = String::from("service_id_1");
let mut vm = create_avm(fallible_call_service(fallible_service_id), local_peer_id);
let script = format!(
r#"
(xor
(call "{0}" ("service_id_1" "local_fn_name") [] result_1)
(call "{0}" ("service_id_2" "local_fn_name") [] result_2)
)"#,
local_peer_id,
);
let res = call_vm!(vm, "asd", script, "[]", "[]");
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
let executed_call_result = Call(Executed(Rc::new(JValue::String(String::from("res")))));
assert_eq!(actual_trace.len(), 2);
assert_eq!(
actual_trace[0],
Call(CallServiceFailed(1, Rc::new(String::from(r#"error"#))))
);
assert_eq!(actual_trace[1], executed_call_result);
let script = format!(
r#"
(xor
(call "{0}" ("service_id_2" "local_fn_name") [] result_1)
(call "{0}" ("service_id_1" "local_fn_name") [] result_2)
)"#,
local_peer_id
);
let res = call_vm!(vm, "asd", script, "[]", "[]");
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
assert_eq!(actual_trace.len(), 1);
assert_eq!(actual_trace[0], executed_call_result);
}
#[test]
fn xor_var_not_found() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
use air_test_utils::echo_string_call_service;
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = format!(
r#"
(xor
(par
(call "unknown_peer" ("service_id_1" "local_fn_name") [] lazy_defined_variable)
(call "{0}" ("service_id_1" "local_fn_name") [lazy_defined_variable] result)
)
(call "{0}" ("service_id_2" "local_fn_name") ["expected"] result)
)"#,
local_peer_id,
);
let res = call_vm!(vm, "asd", script, "[]", "[]");
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
assert_eq!(actual_trace[0], Par(1, 0));
assert_eq!(actual_trace[1], Call(RequestSentBy(String::from("local_peer_id"))));
}
#[test]
fn xor_multiple_variables_found() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
use air_test_utils::echo_string_call_service;
let set_variables_peer_id = "set_variables_peer_id";
let mut set_variables_vm = create_avm(echo_string_call_service(), set_variables_peer_id);
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let test_string_1 = String::from("some_string");
let test_string_2 = String::from("expected_string");
let script = format!(
r#"
(seq
(call "{0}" ("service_id_1" "local_fn_name") ["{2}"] result_1)
(xor
(call "{1}" ("service_id_1" "local_fn_name") [""] result_1)
(call "{1}" ("service_id_2" "local_fn_name") ["{3}"] result_2)
)
)"#,
set_variables_peer_id, local_peer_id, test_string_1, test_string_2
);
let res = call_vm!(set_variables_vm, "asd", script.clone(), "[]", "[]");
let res = call_vm!(vm, "asd", script, "[]", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
assert_eq!(actual_trace.len(), 2);
assert_eq!(actual_trace[0], Call(Executed(Rc::new(JValue::String(test_string_1)))));
assert_eq!(actual_trace[1], Call(Executed(Rc::new(JValue::String(test_string_2)))));
}
#[test]
fn xor_par() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
let fallible_service_id = String::from("service_id_1");
let local_peer_id = "local_peer_id";
let mut vm = create_avm(fallible_call_service(fallible_service_id.clone()), local_peer_id);
let script = format!(
r#"
(xor
(par
(seq
(call "{0}" ("service_id_2" "local_fn_name") [] result_1)
(call "{0}" ("service_id_2" "local_fn_name") [] result_2)
)
(par
(call "{0}" ("service_id_1" "local_fn_name") [] result_3)
(call "{0}" ("service_id_2" "local_fn_name") [] result_4)
)
)
(seq
(call "{0}" ("service_id_2" "local_fn_name") [] result_4)
(call "{0}" ("service_id_2" "local_fn_name") [] result_5)
)
)"#,
local_peer_id
);
let result = call_vm!(vm, "asd", script.clone(), "[]", "[]");
let actual_trace: ExecutionTrace = serde_json::from_slice(&result.data).expect("should be valid json");
let res = String::from("res");
let executed_call_result = Rc::new(JValue::String(res));
let expected_trace = vec![
Par(2, 2),
Call(Executed(executed_call_result.clone())),
Call(Executed(executed_call_result.clone())),
Par(1, 0),
Call(CallServiceFailed(1, Rc::new(String::from(r#"error"#)))),
Call(Executed(executed_call_result.clone())),
Call(Executed(executed_call_result.clone())),
];
assert_eq!(actual_trace, expected_trace);
let result = call_vm!(vm, "asd", script, "[]", result.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&result.data).expect("should be valid json");
assert_eq!(actual_trace, expected_trace);
}
#[test]
fn last_error_with_xor() {
use crate::contexts::execution_trace::CallResult::*;
use crate::contexts::execution_trace::ExecutedState::*;
use air_test_utils::echo_string_call_service;
let faillible_peer_id = "failible_peer_id";
let mut faillible_vm = create_avm(fallible_call_service("service_id_1"), faillible_peer_id);
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = format!(
r#"
(xor
(call "{0}" ("service_id_1" "local_fn_name") [] result)
(call "{1}" ("service_id_2" "local_fn_name") [%last_error%] result)
)"#,
faillible_peer_id, local_peer_id,
);
let res = call_vm!(faillible_vm, "asd", script.clone(), "", "");
let res = call_vm!(vm, "asd", script, "", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
let expected_state = Call(Executed(Rc::new(JValue::String(String::from(
"{\"error\":\"Local service error: ret_code is 1, error message is \'error\'\",\"instruction\":\"call \\\"failible_peer_id\\\" (\\\"service_id_1\\\" \\\"local_fn_name\\\") [] result\"}"
)))));
assert_eq!(actual_trace[1], expected_state);
}
}

View File

@ -45,6 +45,7 @@ pub mod execution_trace {
pub use crate::contexts::execution_trace::CallResult;
pub use crate::contexts::execution_trace::ExecutedState;
pub use crate::contexts::execution_trace::ExecutionTrace;
pub use crate::contexts::execution_trace::ParResult;
}
pub mod parser {

View File

@ -18,6 +18,7 @@ use super::CallResult;
use super::DataMergingError;
use super::ExecutedState;
use super::ExecutionTrace;
use super::ParResult;
use crate::log_targets::EXECUTED_TRACE_MERGE;
type MergeResult<T> = Result<T, DataMergingError>;
@ -75,10 +76,10 @@ fn merge_subtree(
let resulted_call = merge_call(prev_call, call)?;
result_trace.push_back(Call(resulted_call));
}
(Some(Par(prev_left, prev_right)), Some(Par(current_left, current_right))) => {
(Some(Par(ParResult(prev_left, prev_right))), Some(Par(ParResult(current_left, current_right)))) => {
let par_position = result_trace.len();
// place temporary Par value to avoid insert in the middle
result_trace.push_back(Par(0, 0));
result_trace.push_back(ExecutedState::par(0, 0));
let before_result_len = result_trace.len();
@ -89,7 +90,7 @@ fn merge_subtree(
let right_par_size = result_trace.len() - left_par_size - before_result_len;
// update temporary Par with final values
result_trace[par_position] = Par(left_par_size, right_par_size);
result_trace[par_position] = ExecutedState::par(left_par_size, right_par_size);
prev_subtree_size -= prev_left + prev_right;
current_subtree_size -= current_left + current_right;
@ -156,135 +157,3 @@ fn merge_call(prev_call_result: CallResult, current_call_result: CallResult) ->
(Executed(..), CallServiceFailed(..)) => Err(IncompatibleCallResults(prev_call_result, current_call_result)),
}
}
#[cfg(test)]
mod tests {
use super::merge_execution_traces;
use super::CallResult;
use super::ExecutedState;
use super::ExecutionTrace;
use crate::JValue;
use std::rc::Rc;
#[test]
fn merge_call_states_1() {
use CallResult::*;
use ExecutedState::*;
let mut prev_trace = ExecutionTrace::new();
prev_trace.push_back(Par(1, 1));
prev_trace.push_back(Call(RequestSentBy(String::from("peer_1"))));
prev_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
prev_trace.push_back(Par(1, 1));
prev_trace.push_back(Call(RequestSentBy(String::from("peer_3"))));
prev_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
let mut current_trace = ExecutionTrace::new();
current_trace.push_back(Par(1, 1));
current_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
current_trace.push_back(Call(RequestSentBy(String::from("peer_2"))));
current_trace.push_back(Par(1, 1));
current_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
current_trace.push_back(Call(RequestSentBy(String::from("peer_4"))));
let actual_merged_trace =
merge_execution_traces(prev_trace, current_trace).expect("merging should be successful");
let mut expected_merged_trace = ExecutionTrace::new();
expected_merged_trace.push_back(Par(1, 1));
expected_merged_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
expected_merged_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
expected_merged_trace.push_back(Par(1, 1));
expected_merged_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
expected_merged_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
assert_eq!(actual_merged_trace, expected_merged_trace);
}
#[test]
fn merge_call_states_2() {
use CallResult::*;
use ExecutedState::*;
let mut prev_trace = ExecutionTrace::new();
prev_trace.push_back(Par(1, 0));
prev_trace.push_back(Call(RequestSentBy(String::from("peer_1"))));
prev_trace.push_back(Par(1, 1));
prev_trace.push_back(Call(RequestSentBy(String::from("peer_2"))));
prev_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
let mut current_trace = ExecutionTrace::new();
current_trace.push_back(Par(2, 2));
current_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
current_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
current_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
current_trace.push_back(Call(RequestSentBy(String::from("peer_1"))));
current_trace.push_back(Par(1, 1));
current_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
current_trace.push_back(Call(RequestSentBy(String::from("peer_2"))));
let actual_merged_trace =
merge_execution_traces(prev_trace, current_trace).expect("merging should be successful");
let mut expected_merged_trace = ExecutionTrace::new();
expected_merged_trace.push_back(Par(2, 2));
expected_merged_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
expected_merged_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
expected_merged_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
expected_merged_trace.push_back(Call(RequestSentBy(String::from("peer_1"))));
expected_merged_trace.push_back(Par(1, 1));
expected_merged_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
expected_merged_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
assert_eq!(actual_merged_trace, expected_merged_trace);
}
#[test]
fn merge_call_states_3() {
use CallResult::*;
use ExecutedState::*;
let mut prev_trace = ExecutionTrace::new();
prev_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
prev_trace.push_back(Par(2, 0));
prev_trace.push_back(Par(1, 0));
prev_trace.push_back(Call(RequestSentBy(String::from("peer_1"))));
prev_trace.push_back(Par(1, 2));
prev_trace.push_back(Call(RequestSentBy(String::from("peer_1"))));
prev_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
prev_trace.push_back(Call(RequestSentBy(String::from("peer_1"))));
let mut current_trace = ExecutionTrace::new();
current_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
current_trace.push_back(Par(3, 3));
current_trace.push_back(Par(1, 1));
current_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
current_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
current_trace.push_back(Par(1, 1));
current_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
current_trace.push_back(Call(RequestSentBy(String::from("peer_1"))));
current_trace.push_back(Par(1, 1));
current_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
current_trace.push_back(Call(RequestSentBy(String::from("peer_1"))));
let actual_merged_trace =
merge_execution_traces(prev_trace, current_trace).expect("merging should be successful");
let mut expected_merged_trace = ExecutionTrace::new();
expected_merged_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
expected_merged_trace.push_back(Par(3, 3));
expected_merged_trace.push_back(Par(1, 1));
expected_merged_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
expected_merged_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
expected_merged_trace.push_back(Par(1, 1));
expected_merged_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
expected_merged_trace.push_back(Call(RequestSentBy(String::from("peer_1"))));
expected_merged_trace.push_back(Par(1, 2));
expected_merged_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
expected_merged_trace.push_back(Call(Executed(Rc::new(JValue::Null))));
expected_merged_trace.push_back(Call(RequestSentBy(String::from("peer_1"))));
assert_eq!(actual_merged_trace, expected_merged_trace);
}
}

View File

@ -17,6 +17,8 @@
mod data_merging;
mod errors;
mod preparation;
#[cfg(tests)]
mod tests;
pub(crate) use errors::DataMergingError;
pub(crate) use errors::PreparationError;
@ -28,4 +30,5 @@ pub(self) use crate::contexts::execution_trace::CallResult;
pub(self) use crate::contexts::execution_trace::ExecutedState;
pub(self) use crate::contexts::execution_trace::ExecutionTrace;
pub(self) use crate::contexts::execution_trace::ExecutionTraceCtx;
pub(self) use crate::contexts::execution_trace::ParResult;
pub(self) use data_merging::merge_execution_traces;

View File

@ -0,0 +1,128 @@
use super::merge_execution_traces;
use crate::JValue;
use air_test_utils::executed_state::*;
use air_test_utils::ExecutionTrace;
use std::rc::Rc;
#[test]
fn merge_call_states_1() {
let mut prev_trace = vec![
par(1, 1),
request_sent_by("peer_1"),
scalar_jvalue(JValue::Null),
par(1, 1),
request_sent_by("peer_3"),
scalar_jvalue(JValue::Null),
];
let current_trace = vec![
par(1, 1),
scalar_jvalue(JValue::Null),
request_sent_by("peer_2"),
par(1, 1),
scalar_jvalue(JValue::Null),
request_sent_by("peer_4"),
];
let actual_merged_trace =
merge_execution_traces(prev_trace.into(), current_trace.into()).expect("merging should be successful");
let expected_merged_trace = vec![
par(1, 1),
scalar_jvalue(JValue::Null),
scalar_jvalue(JValue::Null),
par(1, 1),
scalar_jvalue(JValue::Null),
scalar_jvalue(JValue::Null),
];
assert_eq!(actual_merged_trace, expected_merged_trace);
}
#[test]
fn merge_call_states_2() {
let prev_trace = vec![
par(1, 0),
request_sent_by("peer_1"),
par(1, 1),
request_sent_by("peer_2"),
scalar_jvalue(JValue::Null),
];
let current_trace = vec![
par(2, 2),
scalar_jvalue(JValue::Null),
scalar_jvalue(JValue::Null),
scalar_jvalue(JValue::Null),
request_sent_by("peer_1"),
par(1, 1),
scalar_jvalue(JValue::Null),
request_sent_by("peer_2"),
];
let actual_merged_trace =
merge_execution_traces(prev_trace.into(), current_trace.into()).expect("merging should be successful");
let expected_merged_trace = vec![
par(2, 2),
scalar_jvalue(JValue::Null),
scalar_jvalue(JValue::Null),
scalar_jvalue(JValue::Null),
scalar_jvalue(JValue::Null),
par(1, 1),
scalar_jvalue(JValue::Null),
scalar_jvalue(JValue::Null),
];
assert_eq!(actual_merged_trace, expected_merged_trace);
}
#[test]
fn merge_call_states_3() {
let prev_trace = vec![
scalar_jvalue(JValue::Null),
par(2, 0),
par(1, 0),
request_sent_by("peer_1"),
par(1, 2),
request_sent_by("peer_1"),
scalar_jvalue(JValue::Null),
request_sent_by("peer_1"),
];
let current_trace = vec![
scalar_jvalue(JValue::Null),
par(3, 3),
par(1, 1),
scalar_jvalue(JValue::Null),
scalar_jvalue(JValue::Null),
par(1, 1),
scalar_jvalue(JValue::Null),
request_sent_by("peer_1"),
par(1, 1),
scalar_jvalue(JValue::Null),
request_sent_by("peer_1"),
];
let actual_merged_trace =
merge_execution_traces(prev_trace.into(), current_trace.into()).expect("merging should be successful");
let expected_merged_trace = vec![
scalar_jvalue(JValue::Null),
par(3, 3),
par(1, 1),
scalar_jvalue(JValue::Null),
scalar_jvalue(JValue::Null),
par(1, 1),
scalar_jvalue(JValue::Null),
request_sent_by("peer_1"),
par(1, 2),
scalar_jvalue(JValue::Null),
scalar_jvalue(JValue::Null),
request_sent_by("peer_1"),
];
assert_eq!(actual_merged_trace, expected_merged_trace);
}

View File

@ -1,428 +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 air_test_utils::call_vm;
use air_test_utils::create_avm;
use air_test_utils::echo_number_call_service;
use air_test_utils::unit_call_service;
use air_test_utils::CallServiceClosure;
use air_test_utils::IValue;
use air_test_utils::NEVec;
use serde_json::json;
use std::rc::Rc;
type JValue = serde_json::Value;
#[test]
fn executed_trace_seq_par_call() {
use air::execution_trace::CallResult::*;
use air::execution_trace::ExecutedState::{self, *};
let local_peer_id = "local_peer_id";
let mut vm = create_avm(unit_call_service(), local_peer_id);
let script = format!(
r#"
(seq
(par
(call "{0}" ("local_service_id" "local_fn_name") [] result_1)
(call "remote_peer_id" ("service_id" "fn_name") [] g)
)
(call "{0}" ("local_service_id" "local_fn_name") [] result_2)
)"#,
local_peer_id
);
let initial_state = json!([
{ "par": [1,1] },
{ "call": {"executed": "test"} },
{ "call": {"executed": "test"} },
])
.to_string();
let res = call_vm!(vm, "asd", script, "[]", initial_state);
let actual_trace: Vec<ExecutedState> =
serde_json::from_slice(&res.data).expect("interpreter should return valid json");
let test_string = String::from("test");
let expected_trace = vec![
Par(1, 1),
Call(Executed(Rc::new(JValue::String(test_string.clone())))),
Call(Executed(Rc::new(JValue::String(test_string.clone())))),
Call(Executed(Rc::new(JValue::String(test_string)))),
];
assert_eq!(actual_trace, expected_trace);
assert!(res.next_peer_pks.is_empty());
}
#[test]
fn executed_trace_par_par_call() {
use air::execution_trace::CallResult::*;
use air::execution_trace::ExecutedState::{self, *};
let local_peer_id = "local_peer_id";
let mut vm = create_avm(unit_call_service(), local_peer_id);
let script = format!(
r#"
(par
(par
(call "local_peer_id" ("local_service_id" "local_fn_name") [] result_1)
(call "remote_peer_id" ("service_id" "fn_name") [] g)
)
(call "{}" ("local_service_id" "local_fn_name") [] result_2)
)"#,
local_peer_id,
);
let initial_state = json!([
{ "par": [3,0] },
{ "par": [1,0] },
{ "call": {"request_sent_by": "peer_id_1"} },
{ "call": {"executed": "test"} },
])
.to_string();
let res = call_vm!(vm, "asd", script, "[]", initial_state);
let actual_trace: Vec<ExecutedState> =
serde_json::from_slice(&res.data).expect("interpreter should return valid json");
let test_string = String::from("test");
let expected_trace = vec![
Par(3, 1),
Par(1, 1),
Call(Executed(Rc::new(JValue::String(test_string.clone())))),
Call(RequestSentBy(local_peer_id.to_string())),
Call(Executed(Rc::new(JValue::String(test_string)))),
];
assert_eq!(actual_trace, expected_trace);
assert_eq!(res.next_peer_pks, vec![String::from("remote_peer_id")]);
}
#[test]
fn executed_trace_seq_seq() {
use air::execution_trace::CallResult::*;
use air::execution_trace::ExecutedState::{self, *};
let peer_id_1 = String::from("12D3KooWHk9BjDQBUqnavciRPhAYFvqKBe4ZiPPvde7vDaqgn5er");
let peer_id_2 = String::from("12D3KooWAzJcYitiZrerycVB4Wryrx22CFKdDGx7c4u31PFdfTbR");
let mut vm1 = create_avm(unit_call_service(), peer_id_1.clone());
let mut vm2 = create_avm(unit_call_service(), peer_id_2.clone());
let script = format!(
r#"
(seq
(call "{}" ("identity" "") [] void0)
(seq
(call "{}" ("add_blueprint" "") [] blueprint_id)
(call "{}" ("addBlueprint-14d8488e-d10d-474d-96b2-878f6a7d74c8" "") [] void1)
)
)
"#,
peer_id_1, peer_id_1, peer_id_2
);
let res = call_vm!(vm2, "asd", script.clone(), "[]", "[]");
assert_eq!(res.next_peer_pks, vec![peer_id_1.clone()]);
let res = call_vm!(vm1, "asd", script.clone(), "[]", res.data);
assert_eq!(res.next_peer_pks, vec![peer_id_2.clone()]);
let res = call_vm!(vm2, "asd", script, "[]", res.data);
let actual_trace: Vec<ExecutedState> =
serde_json::from_slice(&res.data).expect("interpreter should return valid json");
let test_string = String::from("test");
let expected_trace = vec![
Call(Executed(Rc::new(JValue::String(test_string.clone())))),
Call(Executed(Rc::new(JValue::String(test_string.clone())))),
Call(Executed(Rc::new(JValue::String(test_string)))),
];
assert_eq!(actual_trace, expected_trace);
}
#[test]
fn executed_trace_create_service() {
use air::execution_trace::CallResult::*;
use air::execution_trace::ExecutedState::{self, *};
let module = "greeting";
let module_config = json!(
{
"name": module,
"mem_pages_count": 100,
"logger_enabled": true,
"wasi": {
"envs": json!({}),
"preopened_files": vec!["/tmp"],
"mapped_dirs": json!({}),
}
}
);
let module_bytes = json!([1, 2]);
let blueprint = json!({ "name": "blueprint", "dependencies": [module]});
let add_module_response = String::from("add_module response");
let add_blueprint_response = String::from("add_blueprint response");
let create_response = String::from("create response");
let call_service: CallServiceClosure = Box::new(move |_, args| -> Option<IValue> {
let builtin_service = match &args[0] {
IValue::String(str) => str,
_ => unreachable!(),
};
let response = match builtin_service.as_str() {
"add_module" => add_module_response.clone(),
"add_blueprint" => add_blueprint_response.clone(),
"create" => create_response.clone(),
_ => String::from("unknown response"),
};
Some(IValue::Record(
NEVec::new(vec![IValue::S32(0), IValue::String(format!("\"{}\"", response))]).unwrap(),
))
});
let mut vm = create_avm(call_service, "A");
let script = include_str!("./scripts/create_service.clj");
let add_module_response = String::from("add_module response");
let add_blueprint_response = String::from("add_blueprint response");
let create_response = String::from("create response");
let expected_trace = vec![
Call(Executed(Rc::new(module_bytes))),
Call(Executed(Rc::new(module_config))),
Call(Executed(Rc::new(blueprint))),
Call(Executed(Rc::new(JValue::String(add_module_response)))),
Call(Executed(Rc::new(JValue::String(add_blueprint_response)))),
Call(Executed(Rc::new(JValue::String(create_response)))),
Call(Executed(Rc::new(JValue::String(String::from("test"))))),
];
let res = call_vm!(vm, "init_peer_id", script, "[]", json!(expected_trace).to_string());
let actual_trace: Vec<ExecutedState> = serde_json::from_slice(&res.data).expect("should be a correct json");
assert_eq!(actual_trace, expected_trace);
assert!(res.next_peer_pks.is_empty());
}
#[test]
fn executed_trace_par_seq_fold_call() {
let return_numbers_call_service: CallServiceClosure = Box::new(|_, _| -> Option<IValue> {
Some(IValue::Record(
NEVec::new(vec![
IValue::S32(0),
IValue::String(String::from(
"[\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"10\"]",
)),
])
.unwrap(),
))
});
let mut vm1 = create_avm(return_numbers_call_service, "some_peer_id_1");
let mut vm2 = create_avm(echo_number_call_service(), "some_peer_id_2");
let mut vm3 = create_avm(unit_call_service(), "some_peer_id_3");
let script = String::from(
r#"
(par
(seq
(call "some_peer_id_1" ("local_service_id" "local_fn_name") [] IterableResultPeer1)
(fold IterableResultPeer1 i
(par
(call "some_peer_id_2" ("local_service_id" "local_fn_name") [i] $acc)
(next i)
)
)
)
(call "some_peer_id_3" ("local_service_id" "local_fn_name") [] result_2)
)"#,
);
let res = call_vm!(vm2, "asd", script.clone(), "[]", "[]");
let res = call_vm!(vm1, "asd", script.clone(), "[]", res.data);
let mut data = res.data;
for _ in 0..100 {
let res = call_vm!(vm2, "asd", script.clone(), "[]", data);
data = res.data;
}
let res = call_vm!(vm3, "asd", script, "[]", data);
let actual_trace: JValue = serde_json::from_slice(&res.data).expect("a valid json");
let expected_json = json!( [
{ "par": [21,1] },
{ "call": { "executed": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"] } },
{ "par": [1,18] },
{ "call": { "executed": 1 } },
{ "par": [1,16] },
{ "call": { "executed": 2 } },
{ "par": [1,14] },
{ "call": { "executed": 3 } },
{ "par": [1,12] },
{ "call": { "executed": 4 } },
{ "par": [1,10] },
{ "call": { "executed": 5 } },
{ "par": [1,8] },
{ "call": { "executed": 6 } },
{ "par": [1,6] },
{ "call": { "executed": 7 } },
{ "par": [1,4] },
{ "call": { "executed": 8 } },
{ "par": [1,2] },
{ "call": { "executed": 9 } },
{ "par": [1,0] },
{ "call": { "executed": 10 } },
{ "call": { "executed": "test" } },
]);
assert_eq!(actual_trace, expected_json);
assert!(res.next_peer_pks.is_empty());
}
#[test]
fn executed_trace_par_seq_fold_in_cycle_call() {
let return_numbers_call_service: CallServiceClosure = Box::new(|_, _| -> Option<IValue> {
Some(IValue::Record(
NEVec::new(vec![
IValue::S32(0),
IValue::String(String::from(
"[\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"10\"]",
)),
])
.unwrap(),
))
});
let mut vm1 = create_avm(return_numbers_call_service, "some_peer_id_1");
let mut vm2 = create_avm(echo_number_call_service(), "some_peer_id_2");
let mut vm3 = create_avm(unit_call_service(), "some_peer_id_3");
let script = String::from(
r#"
(par
(seq
(call "some_peer_id_1" ("local_service_id" "local_fn_name") [] IterableResultPeer1)
(fold IterableResultPeer1 i
(par
(call "some_peer_id_2" ("local_service_id" "local_fn_name") [i] $acc)
(next i)
)
)
)
(call "some_peer_id_3" ("local_service_id" "local_fn_name") [] result_2)
)"#,
);
let mut data = vec![];
for _ in 0..100 {
let res = call_vm!(vm1, "asd", script.clone(), "[]", data);
let res = call_vm!(vm2, "asd", script.clone(), "[]", res.data);
let res = call_vm!(vm3, "asd", script.clone(), "[]", res.data);
data = res.data;
}
let resulted_json: JValue = serde_json::from_slice(&data).expect("interpreter should return valid json");
let expected_json = json!( [
{ "par": [21,1] },
{ "call": { "executed": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"] } },
{ "par": [1,18] },
{ "call": { "executed": 1 } },
{ "par": [1,16] },
{ "call": { "executed": 2 } },
{ "par": [1,14] },
{ "call": { "executed": 3 } },
{ "par": [1,12] },
{ "call": { "executed": 4 } },
{ "par": [1,10] },
{ "call": { "executed": 5 } },
{ "par": [1,8] },
{ "call": { "executed": 6 } },
{ "par": [1,6] },
{ "call": { "executed": 7 } },
{ "par": [1,4] },
{ "call": { "executed": 8 } },
{ "par": [1,2] },
{ "call": { "executed": 9 } },
{ "par": [1,0] },
{ "call": { "executed": 10 } },
{ "call": { "executed": "test" } },
]);
assert_eq!(resulted_json, expected_json);
}
#[test]
fn executed_trace_seq_par_seq_seq() {
let peer_id_1 = String::from("12D3KooWHk9BjDQBUqnavciRPhAYFvqKBe4ZiPPvde7vDaqgn5er");
let peer_id_2 = String::from("12D3KooWAzJcYitiZrerycVB4Wryrx22CFKdDGx7c4u31PFdfTbR");
let mut vm1 = create_avm(unit_call_service(), peer_id_1.clone());
let mut vm2 = create_avm(unit_call_service(), peer_id_2.clone());
let script = format!(
r#"
(seq
(par
(seq
(call "{}" ("" "") [] result_1)
(call "{}" ("" "") [] result_2)
)
(seq
(call "{}" ("" "") [] result_3)
(call "{}" ("" "") [] result_4)
)
)
(call "{}" ("" "") [] result_5)
)
"#,
peer_id_1, peer_id_2, peer_id_2, peer_id_1, peer_id_2
);
let res = call_vm!(vm2, "asd", script.clone(), "[]", "[]");
assert_eq!(res.next_peer_pks, vec![peer_id_1.clone()]);
let res = call_vm!(vm1, "asd", script.clone(), "[]", res.data);
assert_eq!(res.next_peer_pks, vec![peer_id_2.clone()]);
let res = call_vm!(vm2, "asd", script, "[]", res.data);
let resulted_json: JValue = serde_json::from_slice(&res.data).expect("interpreter should return valid json");
let expected_json = json!( [
{ "par": [2,2] },
{ "call": {"executed" : "test" } },
{ "call": {"executed" : "test" } },
{ "call": {"executed" : "test" } },
{ "call": {"executed" : "test" } },
{ "call": {"executed" : "test" } },
]);
assert_eq!(resulted_json, expected_json);
assert!(res.next_peer_pks.is_empty());
}

View File

@ -1,313 +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 air::ResolvedTriplet;
use air::SecurityTetraplet;
use air_test_utils::call_vm;
use air_test_utils::create_avm;
use air_test_utils::CallServiceClosure;
use air_test_utils::IValue;
use air_test_utils::NEVec;
use std::cell::RefCell;
use std::rc::Rc;
type ArgTetraplets = Vec<Vec<SecurityTetraplet>>;
fn arg_host_function() -> (CallServiceClosure, Rc<RefCell<ArgTetraplets>>) {
let arg_tetraplets = Rc::new(RefCell::new(ArgTetraplets::new()));
let arg_tetraplets_inner = arg_tetraplets.clone();
let host_function: CallServiceClosure = Box::new(move |_, args| -> Option<IValue> {
let tetraplets = match &args[3] {
IValue::String(str) => str,
_ => unreachable!(),
};
let de_tetraplets: ArgTetraplets =
serde_json::from_str(tetraplets).expect("json deserialization shouldn't fail");
*arg_tetraplets_inner.borrow_mut() = de_tetraplets;
Some(IValue::Record(
NEVec::new(vec![IValue::S32(0), IValue::String(tetraplets.clone())]).unwrap(),
))
});
(host_function, arg_tetraplets)
}
#[test]
fn simple_fold() {
let return_numbers_call_service: CallServiceClosure = Box::new(|_, _| -> Option<IValue> {
Some(IValue::Record(
NEVec::new(vec![
IValue::S32(0),
IValue::String(String::from(
"[\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"10\"]",
)),
])
.unwrap(),
))
});
let set_variable_vm_peer_id = String::from("some_peer_id_1");
let mut set_variable_vm = create_avm(return_numbers_call_service, set_variable_vm_peer_id.clone());
let mut client_vms = Vec::new();
for i in 1..=10 {
let (arg_host_func, arg_tetraplets) = arg_host_function();
let vm = create_avm(arg_host_func, i.to_string());
client_vms.push((vm, arg_tetraplets))
}
let service_id = String::from("some_service_id");
let function_name = String::from("some_function_name");
let script = format!(
r#"
(seq
(call "{}" ("{}" "{}") [] IterableResultPeer1)
(fold IterableResultPeer1 i
(par
(call i ("local_service_id" "local_fn_name") [i "some_text_literal"] $acc)
(next i)
)
)
)
"#,
set_variable_vm_peer_id, service_id, function_name
);
let init_peer_id = String::from("some_init_peer_id");
let res = call_vm!(set_variable_vm, init_peer_id.clone(), script.clone(), "", "");
let mut data = res.data;
let first_arg_triplet = ResolvedTriplet {
peer_pk: set_variable_vm_peer_id,
service_id,
function_name,
};
let first_arg_triplet = Rc::new(first_arg_triplet);
let first_arg_tetraplet = SecurityTetraplet {
triplet: first_arg_triplet,
json_path: String::new(),
};
let second_arg_triplet = ResolvedTriplet {
peer_pk: init_peer_id.clone(),
service_id: String::new(),
function_name: String::new(),
};
let second_arg_triplet = Rc::new(second_arg_triplet);
let second_arg_tetraplet = SecurityTetraplet {
triplet: second_arg_triplet,
json_path: String::new(),
};
let expected_tetraplets = vec![vec![first_arg_tetraplet], vec![second_arg_tetraplet]];
let expected_tetraplets = Rc::new(RefCell::new(expected_tetraplets));
for i in 0..10 {
let res = call_vm!(client_vms[i].0, init_peer_id.clone(), script.clone(), "[]", data);
data = res.data;
assert_eq!(client_vms[i].1, expected_tetraplets);
}
}
#[test]
fn fold_json_path() {
let return_numbers_call_service: CallServiceClosure = Box::new(|_, _| -> Option<IValue> {
Some(IValue::Record(
NEVec::new(vec![
IValue::S32(0),
IValue::String(String::from(
"{\"arg\": [\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"10\"]}",
)),
])
.unwrap(),
))
});
let set_variable_vm_peer_id = String::from("some_peer_id_1");
let mut set_variable_vm = create_avm(return_numbers_call_service, set_variable_vm_peer_id.clone());
let (arg_host_func, arg_tetraplets) = arg_host_function();
let client_peer_id = String::from("client_id");
let mut client_vm = create_avm(arg_host_func, client_peer_id.clone());
let service_id = String::from("some_service_id");
let function_name = String::from("some_function_name");
let script = format!(
r#"
(seq
(call "{}" ("{}" "{}") [] IterableResultPeer1)
(fold IterableResultPeer1.$.arg i
(par
(call "{}" ("local_service_id" "local_fn_name") [i "some_text_literal"] $acc)
(next i)
)
)
)
"#,
set_variable_vm_peer_id, service_id, function_name, client_peer_id
);
let init_peer_id = String::from("some_init_peer_id");
let res = call_vm!(set_variable_vm, init_peer_id.clone(), script.clone(), "", "");
let first_arg_triplet = ResolvedTriplet {
peer_pk: set_variable_vm_peer_id,
service_id,
function_name,
};
let first_arg_triplet = Rc::new(first_arg_triplet);
let first_arg_tetraplet = SecurityTetraplet {
triplet: first_arg_triplet,
json_path: String::from("$.arg"),
};
let second_arg_triplet = ResolvedTriplet {
peer_pk: init_peer_id.clone(),
service_id: String::new(),
function_name: String::new(),
};
let second_arg_triplet = Rc::new(second_arg_triplet);
let second_arg_tetraplet = SecurityTetraplet {
triplet: second_arg_triplet,
json_path: String::new(),
};
let expected_tetraplets = vec![vec![first_arg_tetraplet], vec![second_arg_tetraplet]];
let expected_tetraplets = Rc::new(RefCell::new(expected_tetraplets));
call_vm!(client_vm, init_peer_id.clone(), script.clone(), "[]", res.data);
assert_eq!(arg_tetraplets, expected_tetraplets);
}
use fluence_app_service::AppService;
use fluence_app_service::AppServiceConfig;
use fluence_app_service::FaaSConfig;
use fluence_app_service::ModuleDescriptor;
use air::execution_trace::CallResult;
use air::execution_trace::ExecutedState;
use air::execution_trace::ExecutionTrace;
use std::path::PathBuf;
fn construct_service_config(module_name: impl Into<String>) -> AppServiceConfig {
let module_name = module_name.into();
let module_path = format!("./tests/security_tetraplets/{}/target/wasm32-wasi/debug/", module_name);
let module_descriptor = ModuleDescriptor {
file_name: module_name.clone() + ".wasm",
import_name: module_name,
..<_>::default()
};
let faas_config = FaaSConfig {
modules_dir: Some(PathBuf::from(module_path)),
modules_config: vec![module_descriptor],
default_modules_config: None,
};
let service_base_dir = std::env::temp_dir();
let config = AppServiceConfig {
service_base_dir,
faas_config,
};
config
}
#[test]
fn tetraplet_with_wasm_modules() {
use fluence::CallParameters;
use fluence::SecurityTetraplet as SDKTetraplet;
let auth_module_name = String::from("auth_module");
let auth_service_config = construct_service_config(auth_module_name.clone());
let auth_service = AppService::new(auth_service_config, auth_module_name.clone(), <_>::default()).unwrap();
let log_module_name = String::from("log_storage");
let log_service_config = construct_service_config(log_module_name.clone());
let log_service = AppService::new(log_service_config, log_module_name.clone(), <_>::default()).unwrap();
let services = maplit::hashmap!(
"auth" => auth_service,
"log_storage" => log_service,
);
let services = Rc::new(RefCell::new(services));
let services_inner = services.clone();
const ADMIN_PEER_PK: &str = "12D3KooWEXNUbCXooUwHrHBbrmjsrpHXoEphPwbjQXEGyzbqKnE1";
let host_func: CallServiceClosure = Box::new(move |_, args: Vec<IValue>| -> Option<IValue> {
let service_id = match &args[0] {
IValue::String(str) => str,
_ => unreachable!(),
};
let function_name = match &args[1] {
IValue::String(str) => str,
_ => unreachable!(),
};
let service_args = match &args[2] {
IValue::String(str) => str,
_ => unreachable!(),
};
let tetraplets = match &args[3] {
IValue::String(str) => str,
_ => unreachable!(),
};
let tetraplets: Vec<Vec<SDKTetraplet>> = serde_json::from_str(tetraplets).unwrap();
let mut call_parameters = CallParameters::default();
call_parameters.init_peer_id = ADMIN_PEER_PK.to_string();
call_parameters.tetraplets = tetraplets;
let service_args = serde_json::from_str(service_args).unwrap();
let mut service = services_inner.borrow_mut();
let service: &mut AppService = service.get_mut(service_id.as_str()).unwrap();
let result = service.call(function_name, service_args, call_parameters).unwrap();
Some(IValue::Record(
NEVec::new(vec![IValue::S32(0), IValue::String(result.to_string())]).unwrap(),
))
});
let local_peer_id = "local_peer_id";
let script = format!(
r#"
(seq
(call "{0}" ("auth" "is_authorized") [] auth_result)
(call "{0}" ("log_storage" "delete") [auth_result.$.is_authorized "1"])
)
"#,
local_peer_id,
);
let mut vm = create_avm(host_func, local_peer_id);
let result = call_vm!(vm, ADMIN_PEER_PK, script, "", "");
let actual_trace: ExecutionTrace = serde_json::from_slice(&result.data).unwrap();
let expected_state = ExecutedState::Call(CallResult::Executed(Rc::new(serde_json::Value::String(String::from(
"Ok",
)))));
assert_eq!(actual_trace[1], expected_state)
}

View File

@ -0,0 +1,173 @@
/*
* 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 air_test_utils::call_vm;
use air_test_utils::create_avm;
use air_test_utils::echo_string_call_service;
use air_test_utils::executed_state;
use air_test_utils::set_variable_call_service;
use air_test_utils::unit_call_service;
use air_test_utils::CallServiceClosure;
use air_test_utils::ExecutionTrace;
use air_test_utils::IValue;
use air_test_utils::NEVec;
// Check that %init_peer_id% alias works correctly (by comparing result with it and explicit peer id).
// Additionally, check that empty string for data does the same as empty call path.
#[test]
fn current_peer_id_call() {
let vm_peer_id = String::from("test_peer_id");
let mut vm = create_avm(unit_call_service(), vm_peer_id.clone());
let service_id = String::from("local_service_id");
let function_name = String::from("local_fn_name");
let script = format!(
r#"
(call %init_peer_id% ("{}" "{}") [] result_name)
"#,
service_id, function_name
);
let res = call_vm!(vm, vm_peer_id.clone(), script.clone(), "[]", "[]");
let call_path: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be a valid json");
let expected_state = executed_state::scalar_string("test");
assert_eq!(call_path.len(), 1);
assert_eq!(call_path[0], expected_state);
assert!(res.next_peer_pks.is_empty());
let script = format!(
r#"
(call "{}" ("{}" "{}") [] result_name)
"#,
vm_peer_id, service_id, function_name
);
let res = call_vm!(vm, "asd", script.clone(), "[]", "[]");
// test that empty string for data works
let res_with_empty_string = call_vm!(vm, "asd", script, "", "");
assert_eq!(res_with_empty_string, res);
}
// Check that specifying remote peer id in call will result its appearing in next_peer_pks.
#[test]
fn remote_peer_id_call() {
let some_local_peer_id = String::from("some_local_peer_id");
let mut vm = create_avm(echo_string_call_service(), some_local_peer_id.clone());
let remote_peer_id = String::from("some_remote_peer_id");
let script = format!(
r#"(call "{}" ("local_service_id" "local_fn_name") ["arg"] result_name)"#,
remote_peer_id
);
let res = call_vm!(vm, "asd", script, "[]", "[]");
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be a valid json");
let expected_state = executed_state::request_sent_by(some_local_peer_id);
assert_eq!(actual_trace.len(), 1);
assert_eq!(actual_trace[0], expected_state);
assert_eq!(res.next_peer_pks, vec![remote_peer_id]);
}
// Check that setting variables works as expected.
#[test]
fn variables() {
let mut vm = create_avm(unit_call_service(), "remote_peer_id");
let mut set_variable_vm = create_avm(set_variable_call_service(r#""remote_peer_id""#), "set_variable");
let script = format!(
r#"
(seq
(call "set_variable" ("some_service_id" "local_fn_name") [] remote_peer_id)
(call remote_peer_id ("some_service_id" "local_fn_name") [] result_name)
)
"#,
);
let res = call_vm!(set_variable_vm, "asd", script.clone(), "[]", "[]");
let res = call_vm!(vm, "asd", script, "[]", res.data);
assert!(res.next_peer_pks.is_empty());
}
// Check that duplicate variables are impossible.
#[test]
fn duplicate_variables() {
let mut vm = create_avm(unit_call_service(), "some_peer_id");
let script = format!(
r#"
(seq
(call "some_peer_id" ("some_service_id" "local_fn_name") [] modules)
(call "some_peer_id" ("some_service_id" "local_fn_name") [] modules)
)
"#,
);
let res = call_vm!(vm, "asd", script, "", "");
assert_eq!(res.ret_code, 1005);
assert!(res.next_peer_pks.is_empty());
}
// Check that string literals can be used as call parameters.
#[test]
fn string_parameters() {
let call_service: CallServiceClosure = Box::new(|_, args| -> Option<IValue> {
let arg = match &args[2] {
IValue::String(str) => str,
_ => unreachable!(),
};
Some(IValue::Record(
NEVec::new(vec![IValue::S32(0), IValue::String(arg.clone())]).unwrap(),
))
});
let vm_peer_id = String::from("A");
let mut vm = create_avm(call_service, vm_peer_id.clone());
let set_variable_vm_peer_id = String::from("set_variable");
let mut set_variable_vm = create_avm(
set_variable_call_service(r#""arg3_value""#),
set_variable_vm_peer_id.clone(),
);
let service_id = String::from("some_service_id");
let function_name = String::from("local_fn_name");
let script = format!(
r#"
(seq
(call "{}" ("{}" "{}") [] arg3)
(call "{}" ("{}" "{}") ["arg1" "arg2" arg3] result)
)
"#,
set_variable_vm_peer_id, service_id, function_name, vm_peer_id, service_id, function_name
);
let res = call_vm!(set_variable_vm, "asd", script.clone(), "[]", "[]");
let res = call_vm!(vm, "asd", script, "[]", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be a valid json");
let expected_state = executed_state::scalar_string_array(vec!["arg1", "arg2", "arg3_value"]);
assert_eq!(actual_trace.len(), 2);
assert_eq!(actual_trace[1], expected_state);
}

View File

@ -0,0 +1,413 @@
/*
* 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 air_test_utils::call_vm;
use air_test_utils::create_avm;
use air_test_utils::echo_number_call_service;
use air_test_utils::echo_string_call_service;
use air_test_utils::executed_state;
use air_test_utils::set_variable_call_service;
use air_test_utils::AVMError;
use air_test_utils::ExecutionTrace;
use air_test_utils::InterpreterOutcome;
use serde_json::json;
#[test]
fn lfold() {
let mut vm = create_avm(echo_number_call_service(), "A");
let mut set_variable_vm = create_avm(set_variable_call_service(r#"["1","2","3","4","5"]"#), "set_variable");
let lfold = String::from(
r#"
(seq
(call "set_variable" ("" "") [] Iterable)
(fold Iterable i
(seq
(call "A" ("" "") [i] $acc)
(next i)
)
)
)"#,
);
let res = call_vm!(set_variable_vm, "", lfold.clone(), "[]", "[]");
let res = call_vm!(vm, "", lfold, "[]", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid executed trace");
let expected_state = executed_state::scalar_string_array(vec!["1", "2", "3", "4", "5"]);
assert_eq!(actual_trace.len(), 6);
assert_eq!(actual_trace[0], expected_state);
for i in 1..=5 {
let expected_state = executed_state::stream_number(i, "$acc");
assert_eq!(actual_trace[i], expected_state);
}
}
#[test]
fn rfold() {
let mut vm = create_avm(echo_number_call_service(), "A");
let mut set_variable_vm = create_avm(set_variable_call_service(r#"["1","2","3","4","5"]"#), "set_variable");
let rfold = String::from(
r#"
(seq
(call "set_variable" ("" "") [] Iterable)
(fold Iterable i
(seq
(next i)
(call "A" ("" "") [i] $acc)
)
)
)"#,
);
let res = call_vm!(set_variable_vm, "", rfold.clone(), "[]", "[]");
let res = call_vm!(vm, "", rfold, "[]", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid executed trace");
assert_eq!(actual_trace.len(), 6);
let expected_state = executed_state::scalar_string_array(vec!["1", "2", "3", "4", "5"]);
assert_eq!(actual_trace[0], expected_state);
for i in 1..=5 {
let expected_state = executed_state::stream_number(6 - i, "$acc");
assert_eq!(actual_trace[i], expected_state);
}
}
#[test]
fn inner_fold() {
let mut vm = create_avm(echo_number_call_service(), "A");
let mut set_variable_vm = create_avm(set_variable_call_service(r#"["1","2","3","4","5"]"#), "set_variable");
let script = String::from(
r#"
(seq
(seq
(call "set_variable" ("" "") [] Iterable1)
(call "set_variable" ("" "") [] Iterable2)
)
(fold Iterable1 i
(seq
(fold Iterable2 j
(seq
(call "A" ("" "") [i] $acc)
(next j)
)
)
(next i)
)
)
)"#,
);
let res = call_vm!(set_variable_vm, "", script.clone(), "[]", "[]");
let res = call_vm!(vm, "", script, "[]", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid executed trace");
assert_eq!(actual_trace.len(), 27);
let expected_state = executed_state::scalar_string_array(vec!["1", "2", "3", "4", "5"]);
assert_eq!(actual_trace[0], expected_state);
assert_eq!(actual_trace[1], expected_state);
for i in 1..=5 {
for j in 1..=5 {
let expected_state = executed_state::stream_number(i, "$acc");
assert_eq!(actual_trace[1 + 5 * (i - 1) + j], expected_state);
}
}
}
#[test]
fn inner_fold_with_same_iterator() {
let mut vm = create_avm(set_variable_call_service(r#"["1","2","3","4","5"]"#), "set_variable");
let script = String::from(
r#"
(seq
(seq
(call "set_variable" ("" "") [] Iterable1)
(call "set_variable" ("" "") [] Iterable2)
)
(fold Iterable1 i
(seq
(fold Iterable2 i
(seq
(call "A" ("" "") [i] $acc)
(next i)
)
)
(next i)
)
)
)"#,
);
let res = call_vm!(vm, "", script, "[]", "[]");
assert_eq!(res.ret_code, 1012);
}
#[test]
fn empty_fold() {
let mut vm = create_avm(echo_number_call_service(), "A");
let mut set_variable_vm = create_avm(set_variable_call_service(r#"[]"#), "set_variable");
let empty_fold = String::from(
r#"
(seq
(call "set_variable" ("" "") [] Iterable)
(fold Iterable i
(seq
(call "A" ("" "") [i] $acc)
(next i)
)
)
)"#,
);
let res = call_vm!(set_variable_vm, "", empty_fold.clone(), "[]", "[]");
let res = call_vm!(vm, "", empty_fold, "[]", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid executed trace");
let expected_state = executed_state::scalar_jvalue(json!([]));
assert_eq!(actual_trace.len(), 1);
assert_eq!(actual_trace[0], expected_state);
}
#[test]
fn empty_fold_json_path() {
let mut vm = create_avm(echo_number_call_service(), "A");
let mut set_variable_vm = create_avm(set_variable_call_service(r#"{ "messages": [] }"#), "set_variable");
let empty_fold = r#"
(seq
(call "set_variable" ("" "") [] messages)
(fold messages.$.messages! i
(seq
(call "A" ("" "") [i] $acc)
(next i)
)
)
)"#;
let res = call_vm!(set_variable_vm, "", empty_fold, "", "");
let res = call_vm!(vm, "", empty_fold, "", res.data);
let res: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid executed trace");
assert_eq!(res.len(), 1);
assert_eq!(res[0], executed_state::scalar_jvalue(json!({ "messages": [] })));
}
// Check that fold works with the join behaviour without hanging up.
#[test]
fn fold_with_join() {
let mut vm = create_avm(echo_number_call_service(), "A");
let mut set_variable_vm = create_avm(set_variable_call_service(r#"["1","2"]"#), "set_variable");
let fold_with_join = String::from(
r#"
(seq
(call "set_variable" ("" "") [] iterable)
(par
(call "unknown_peer" ("" "") [] lazy_def_variable)
(fold iterable i
(seq
(call "A" ("" "") [lazy_def_variable.$.hash!] $acc)
(next i)
)
)
)
)"#,
);
let res = call_vm!(set_variable_vm, "", &fold_with_join, "", "");
let res = call_vm!(vm, "", fold_with_join, "", res.data);
let res: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid executed trace");
assert_eq!(res.len(), 3);
}
#[test]
fn json_path() {
let mut vm = create_avm(echo_number_call_service(), "A");
let mut set_variable_vm = create_avm(
set_variable_call_service(r#"{ "array": ["1","2","3","4","5"] }"#),
"set_variable",
);
let lfold = String::from(
r#"
(seq
(call "set_variable" ("" "") [] iterable)
(fold iterable.$.array! i
(seq
(call "A" ("" "") [i] $acc)
(next i)
)
)
)"#,
);
let res = call_vm!(set_variable_vm, "", lfold.clone(), "[]", "[]");
let res = call_vm!(vm, "", lfold, "[]", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid executed trace");
let expected_state = executed_state::scalar_jvalue(json!({ "array": ["1", "2", "3", "4", "5"] }));
assert_eq!(actual_trace.len(), 6);
assert_eq!(actual_trace[0], expected_state);
for i in 1..=5 {
let expected_state = executed_state::stream_number(i, "$acc");
assert_eq!(actual_trace[i], expected_state);
}
}
#[test]
fn shadowing() {
use executed_state::*;
let mut set_variables_vm = create_avm(set_variable_call_service(r#"["1","2"]"#), "set_variable");
let mut vm_a = create_avm(echo_string_call_service(), "A");
let mut vm_b = create_avm(echo_string_call_service(), "B");
let script = String::from(
r#"
(seq
(seq
(call "set_variable" ("" "") [] iterable1)
(call "set_variable" ("" "") [] iterable2)
)
(fold iterable1 i
(seq
(seq
(fold iterable2 j
(seq
(seq
(call "A" ("" "") [i] local_j)
(call "B" ("" "") [local_j])
)
(next j)
)
)
(par
(call "A" ("" "") [i] local_i)
(call "B" ("" "") [i])
)
)
(next i)
)
)
)"#,
);
let res = call_vm!(set_variables_vm, "", script.clone(), "[]", "[]");
let res = call_vm!(vm_a, "", script.clone(), "[]", res.data);
let res = call_vm!(vm_b, "", script.clone(), "[]", res.data);
let res = call_vm!(vm_a, "", script.clone(), "[]", res.data);
let res = call_vm!(vm_b, "", script.clone(), "[]", res.data);
let res = call_vm!(vm_a, "", script.clone(), "[]", res.data);
let res = call_vm!(vm_b, "", script, "[]", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid executed trace");
let expected_trace = vec![
scalar_string_array(vec!["1", "2"]),
scalar_string_array(vec!["1", "2"]),
scalar_string("1"),
scalar_string("1"),
scalar_string("1"),
scalar_string("1"),
par(1, 1),
scalar_string("1"),
scalar_string("1"),
scalar_string("2"),
scalar_string("2"),
request_sent_by("B"),
];
assert_eq!(actual_trace, expected_trace);
}
#[test]
fn shadowing_scope() {
use executed_state::*;
fn execute_script(script: String) -> Result<InterpreterOutcome, AVMError> {
let mut set_variables_vm = create_avm(set_variable_call_service(r#"["1","2"]"#), "set_variable");
let mut vm_a = create_avm(echo_string_call_service(), "A");
let mut vm_b = create_avm(echo_string_call_service(), "B");
let res = call_vm!(set_variables_vm, "", script.clone(), "[]", "[]");
let res = call_vm!(vm_a, "", script.clone(), "[]", res.data);
let res = call_vm!(vm_b, "", script.clone(), "[]", res.data);
let res = call_vm!(vm_a, "", script.clone(), "[]", res.data);
let res = call_vm!(vm_b, "", script.clone(), "[]", res.data);
vm_a.call_with_prev_data("", script, "[]", res.data)
}
let variable_shadowing_script = String::from(
r#"
(seq
(seq
(call "set_variable" ("" "") [] iterable1)
(call "set_variable" ("" "") [] iterable2)
)
(fold iterable1 i
(seq
(seq
(call "A" ("" "") ["value"] local_j)
(seq
(fold iterable2 j
(seq
(seq
(call "A" ("" "") [i] local_j)
(call "B" ("" "") [local_j])
)
(next j)
)
)
(call "A" ("" "") [local_j])
)
)
(next i)
)
)
)"#,
);
let res = execute_script(variable_shadowing_script).unwrap();
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid executed trace");
let expected_trace = vec![
scalar_string_array(vec!["1", "2"]),
scalar_string_array(vec!["1", "2"]),
scalar_string("value"),
scalar_string("1"),
scalar_string("1"),
scalar_string("1"),
scalar_string("1"),
scalar_string("value"),
scalar_string("value"),
scalar_string("2"),
request_sent_by("A"),
];
assert_eq!(actual_trace, expected_trace);
}

View File

@ -0,0 +1,246 @@
/*
* 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 air_test_utils::call_vm;
use air_test_utils::create_avm;
use air_test_utils::echo_string_call_service;
use air_test_utils::executed_state;
use air_test_utils::ExecutionTrace;
#[test]
fn match_equal() {
let set_variable_peer_id = "set_variable_peer_id";
let mut set_variable_vm = create_avm(echo_string_call_service(), set_variable_peer_id);
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = format!(
r#"
(seq
(seq
(call "{0}" ("" "") ["value_1"] value_1)
(call "{0}" ("" "") ["value_1"] value_2)
)
(xor
(match value_1 value_2
(call "{1}" ("service_id_2" "local_fn_name") ["result_1"] result_1)
)
(call "{1}" ("service_id_2" "local_fn_name") ["result_2"] result_2)
)
)"#,
set_variable_peer_id, local_peer_id
);
let res = call_vm!(set_variable_vm, "asd", script.clone(), "", "");
let res = call_vm!(vm, "asd", script, "", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
let expected_state = executed_state::scalar_string("result_1");
assert_eq!(actual_trace.len(), 3);
assert_eq!(actual_trace[2], expected_state);
}
#[test]
fn match_not_equal() {
let set_variable_peer_id = "set_variable_peer_id";
let mut set_variable_vm = create_avm(echo_string_call_service(), set_variable_peer_id);
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = format!(
r#"
(seq
(seq
(call "{0}" ("" "") ["value_1"] value_1)
(call "{0}" ("" "") ["value_2"] value_2)
)
(xor
(match value_1 value_2
(call "{1}" ("service_id_2" "local_fn_name") ["result_1"] result_1)
)
(call "{1}" ("service_id_2" "local_fn_name") ["result_2"] result_2)
)
)"#,
set_variable_peer_id, local_peer_id
);
let res = call_vm!(set_variable_vm, "asd", script.clone(), "", "");
let res = call_vm!(vm, "asd", script, "", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
let expected_state = executed_state::scalar_string("result_2");
assert_eq!(actual_trace.len(), 3);
assert_eq!(actual_trace[2], expected_state);
}
#[test]
fn match_with_string() {
let set_variable_peer_id = "set_variable_peer_id";
let mut set_variable_vm = create_avm(echo_string_call_service(), set_variable_peer_id);
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = format!(
r#"
(seq
(call "{0}" ("" "") ["value_1"] value_1)
(xor
(match value_1 "value_1"
(call "{1}" ("service_id_2" "local_fn_name") ["result_1"] result_1)
)
(call "{1}" ("service_id_2" "local_fn_name") ["result_2"] result_2)
)
)"#,
set_variable_peer_id, local_peer_id
);
let res = call_vm!(set_variable_vm, "asd", script.clone(), "", "");
let res = call_vm!(vm, "asd", script, "", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
let expected_state = executed_state::scalar_string("result_1");
assert_eq!(actual_trace.len(), 2);
assert_eq!(actual_trace[1], expected_state);
}
#[test]
fn match_with_init_peer_id() {
let set_variable_peer_id = "set_variable_peer_id";
let mut set_variable_vm = create_avm(echo_string_call_service(), set_variable_peer_id);
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = format!(
r#"
(seq
(call "{0}" ("" "") ["{1}"] value_1)
(xor
(match value_1 %init_peer_id%
(call "{1}" ("service_id_2" "local_fn_name") ["result_1"] result_1)
)
(call "{1}" ("service_id_2" "local_fn_name") ["result_2"] result_2)
)
)"#,
set_variable_peer_id, local_peer_id
);
let res = call_vm!(set_variable_vm, local_peer_id, script.clone(), "", "");
let res = call_vm!(vm, local_peer_id, script, "", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
let expected_executed_call_result = executed_state::scalar_string("result_1");
assert_eq!(actual_trace.len(), 2);
assert_eq!(actual_trace[1], expected_executed_call_result);
}
#[test]
fn match_with_equal_numbers() {
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = "
(xor
(match 1 1
(null)
)
(null)
)";
let res = call_vm!(vm, "asd", script, "", "");
assert_eq!(res.ret_code, 0);
}
#[test]
fn match_without_xor() {
let set_variable_peer_id = "set_variable_peer_id";
let mut set_variable_vm = create_avm(echo_string_call_service(), set_variable_peer_id);
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = format!(
r#"
(seq
(seq
(call "{0}" ("" "") ["value_1"] value_1)
(call "{0}" ("" "") ["value_2"] value_2)
)
(match value_1 value_2
(call "{1}" ("service_id_2" "local_fn_name") ["result_1"] result_1)
)
)"#,
set_variable_peer_id, local_peer_id
);
let res = call_vm!(set_variable_vm, "asd", script.clone(), "", "");
let res = call_vm!(vm, "asd", script.clone(), "", res.data);
assert_eq!(res.ret_code, 1015);
let res = call_vm!(vm, "asd", script, "", res.data);
assert_eq!(res.ret_code, 1015);
}
#[test]
fn match_with_two_xors() {
use air_test_utils::set_variable_call_service;
let local_peer_id = "local_peer_id";
let mut vm = create_avm(
set_variable_call_service(serde_json::json!(false).to_string()),
local_peer_id,
);
let local_peer_id_2 = "local_peer_id_2";
let script = format!(
r#"
(xor
(seq
(seq
(call "{0}" ("getDataSrv" "condition") [] condition)
(call "{0}" ("getDataSrv" "relay") [] relay)
)
(xor
(match condition true
(call "{0}" ("println" "print") ["it is true"])
)
(call "{1}" ("println" "print") ["it is false"])
)
)
(call "{0}" ("errorHandlingSrv" "error") [%last_error%])
)
"#,
local_peer_id, local_peer_id_2
);
let res = call_vm!(vm, "", script, "", "");
let mut trace: ExecutionTrace =
serde_json::from_slice(&res.data).expect("the interpreter should provide correct trace");
let expected_executed_call_result = executed_state::request_sent_by(local_peer_id);
assert_eq!(res.ret_code, 0);
assert_eq!(trace.pop_back().unwrap(), expected_executed_call_result);
}

View File

@ -0,0 +1,197 @@
/*
* 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 air_test_utils::call_vm;
use air_test_utils::create_avm;
use air_test_utils::echo_string_call_service;
use air_test_utils::executed_state;
use air_test_utils::ExecutionTrace;
#[test]
fn mismatch_equal() {
let set_variable_peer_id = "set_variable_peer_id";
let mut set_variable_vm = create_avm(echo_string_call_service(), set_variable_peer_id);
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = format!(
r#"
(seq
(seq
(call "{0}" ("" "") ["value_1"] value_1)
(call "{0}" ("" "") ["value_1"] value_2)
)
(xor
(mismatch value_1 value_2
(call "{1}" ("service_id_2" "local_fn_name") ["result_1"] result_1)
)
(call "{1}" ("service_id_2" "local_fn_name") ["result_2"] result_2)
)
)"#,
set_variable_peer_id, local_peer_id
);
let res = call_vm!(set_variable_vm, "asd", script.clone(), "", "");
let res = call_vm!(vm, "asd", script, "", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
let expected_state = executed_state::scalar_string("result_2");
assert_eq!(actual_trace.len(), 3);
assert_eq!(actual_trace[2], expected_state);
}
#[test]
fn mismatch_not_equal() {
let set_variable_peer_id = "set_variable_peer_id";
let mut set_variable_vm = create_avm(echo_string_call_service(), set_variable_peer_id);
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = format!(
r#"
(seq
(seq
(call "{0}" ("" "") ["value_1"] value_1)
(call "{0}" ("" "") ["value_2"] value_2)
)
(xor
(mismatch value_1 value_2
(call "{1}" ("service_id_2" "local_fn_name") ["result_1"] result_1)
)
(call "{1}" ("service_id_2" "local_fn_name") ["result_2"] result_2)
)
)"#,
set_variable_peer_id, local_peer_id
);
let res = call_vm!(set_variable_vm, "asd", script.clone(), "", "");
let res = call_vm!(vm, "asd", script, "", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
let expected_state = executed_state::scalar_string("result_1");
assert_eq!(actual_trace.len(), 3);
assert_eq!(actual_trace[2], expected_state);
}
#[test]
fn mismatch_with_string() {
let set_variable_peer_id = "set_variable_peer_id";
let mut set_variable_vm = create_avm(echo_string_call_service(), set_variable_peer_id);
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = format!(
r#"
(seq
(call "{0}" ("" "") ["value_1"] value_1)
(xor
(mismatch value_1 "value_1"
(call "{1}" ("service_id_2" "local_fn_name") ["result_1"] result_1)
)
(call "{1}" ("service_id_2" "local_fn_name") ["result_2"] result_2)
)
)"#,
set_variable_peer_id, local_peer_id
);
let res = call_vm!(set_variable_vm, "asd", script.clone(), "", "");
let res = call_vm!(vm, "asd", script, "", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
let expected_state = executed_state::scalar_string("result_2");
assert_eq!(actual_trace.len(), 2);
assert_eq!(actual_trace[1], expected_state);
}
#[test]
fn mismatch_without_xor() {
let set_variable_peer_id = "set_variable_peer_id";
let mut set_variable_vm = create_avm(echo_string_call_service(), set_variable_peer_id);
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = format!(
r#"
(seq
(seq
(call "{0}" ("" "") ["value_1"] value_1)
(call "{0}" ("" "") ["value_1"] value_2)
)
(mismatch value_1 value_2
(call "{1}" ("service_id_2" "local_fn_name") ["result_1"] result_1)
)
)"#,
set_variable_peer_id, local_peer_id
);
let res = call_vm!(set_variable_vm, "asd", script.clone(), "", "");
let res = call_vm!(vm, "asd", script.clone(), "", res.data);
assert_eq!(res.ret_code, 1016);
let res = call_vm!(vm, "asd", script, "", res.data);
assert_eq!(res.ret_code, 1016);
}
#[test]
fn mismatch_with_two_xors() {
use air_test_utils::set_variable_call_service;
let local_peer_id = "local_peer_id";
let mut vm = create_avm(
set_variable_call_service(serde_json::json!(false).to_string()),
local_peer_id,
);
let local_peer_id_2 = "local_peer_id_2";
let script = format!(
r#"
(xor
(seq
(seq
(call "{0}" ("getDataSrv" "condition") [] condition)
(call "{0}" ("getDataSrv" "relay") [] relay)
)
(xor
(mismatch condition true
(call "{1}" ("println" "print") ["it is false"])
)
(call "{0}" ("println" "print") ["it is true"])
)
)
(call "{0}" ("errorHandlingSrv" "error") [%last_error%])
)
"#,
local_peer_id, local_peer_id_2
);
let res = call_vm!(vm, "", script, "", "");
let mut trace: ExecutionTrace =
serde_json::from_slice(&res.data).expect("the interpreter should provide correct trace");
let expected_executed_call_result = executed_state::request_sent_by(local_peer_id);
assert_eq!(res.ret_code, 0);
assert_eq!(trace.pop_back().unwrap(), expected_executed_call_result);
}

View File

@ -0,0 +1,23 @@
/*
* 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.
*/
mod call;
mod fold;
mod match_;
mod mismatch;
mod par;
mod seq;
mod xor;

View File

@ -0,0 +1,60 @@
/*
* 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 air_test_utils::call_vm;
use air_test_utils::create_avm;
use air_test_utils::unit_call_service;
#[test]
fn par_remote_remote() {
use std::collections::HashSet;
let mut vm = create_avm(unit_call_service(), "");
let script = String::from(
r#"
(par
(call "remote_peer_id_1" ("local_service_id" "local_fn_name") [] result_name)
(call "remote_peer_id_2" ("service_id" "fn_name") [] g)
)"#,
);
let mut res = call_vm!(vm, "", script, "[]", "[]");
let peers_result: HashSet<_> = res.next_peer_pks.drain(..).collect();
let peers_right: HashSet<_> = maplit::hashset!(String::from("remote_peer_id_1"), String::from("remote_peer_id_2"));
assert_eq!(peers_result, peers_right);
}
#[test]
fn par_local_remote() {
let local_peer_id = "local_peer_id";
let mut vm = create_avm(unit_call_service(), local_peer_id);
let script = format!(
r#"
(par
(call "{}" ("local_service_id" "local_fn_name") [] result_name)
(call "remote_peer_id_2" ("service_id" "fn_name") [] g)
)"#,
local_peer_id
);
let res = call_vm!(vm, "", script, "[]", "[]");
assert_eq!(res.next_peer_pks, vec![String::from("remote_peer_id_2")]);
}

View File

@ -0,0 +1,61 @@
/*
* 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 air_test_utils::call_vm;
use air_test_utils::create_avm;
use air_test_utils::executed_state;
use air_test_utils::unit_call_service;
#[test]
fn seq_remote_remote() {
let mut vm = create_avm(unit_call_service(), "");
let script = String::from(
r#"
(seq
(call "remote_peer_id_1" ("local_service_id" "local_fn_name") [] result_name)
(call "remote_peer_id_2" ("service_id" "fn_name") [] g)
)"#,
);
let res = call_vm!(vm, "asd", script.clone(), "", "");
assert_eq!(res.next_peer_pks, vec![String::from("remote_peer_id_1")]);
let initial_data = vec![executed_state::scalar_string("")];
let initial_data = serde_json::to_string(&initial_data).expect("default serializer shouldn't fail");
let res = call_vm!(vm, "asd", script, "", initial_data);
assert_eq!(res.next_peer_pks, vec![String::from("remote_peer_id_2")]);
}
#[test]
fn seq_local_remote() {
let local_peer_id = "local_peer_id";
let remote_peer_id = String::from("remote_peer_id");
let mut vm = create_avm(unit_call_service(), local_peer_id);
let script = format!(
r#"
(seq
(call "{}" ("local_service_id" "local_fn_name") [] result_name)
(call "{}" ("service_id" "fn_name") [] g)
)"#,
local_peer_id, remote_peer_id
);
let res = call_vm!(vm, "asd", script, "[]", "[]");
assert_eq!(res.next_peer_pks, vec![remote_peer_id]);
}

View File

@ -0,0 +1,195 @@
/*
* 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 air_test_utils::call_vm;
use air_test_utils::create_avm;
use air_test_utils::echo_string_call_service;
use air_test_utils::executed_state;
use air_test_utils::fallible_call_service;
use air_test_utils::ExecutionTrace;
#[test]
fn xor() {
let local_peer_id = "local_peer_id";
let fallible_service_id = String::from("service_id_1");
let mut vm = create_avm(fallible_call_service(fallible_service_id), local_peer_id);
let script = format!(
r#"
(xor
(call "{0}" ("service_id_1" "local_fn_name") [] result_1)
(call "{0}" ("service_id_2" "local_fn_name") [] result_2)
)"#,
local_peer_id,
);
let res = call_vm!(vm, "asd", script, "[]", "[]");
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
let expected_call_result = executed_state::scalar_string("res");
assert_eq!(actual_trace.len(), 2);
assert_eq!(actual_trace[0], executed_state::service_failed(1, "error"));
assert_eq!(actual_trace[1], expected_call_result);
let script = format!(
r#"
(xor
(call "{0}" ("service_id_2" "local_fn_name") [] result_1)
(call "{0}" ("service_id_1" "local_fn_name") [] result_2)
)"#,
local_peer_id
);
let res = call_vm!(vm, "asd", script, "[]", "[]");
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
assert_eq!(actual_trace.len(), 1);
assert_eq!(actual_trace[0], expected_call_result);
}
#[test]
fn xor_var_not_found() {
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = format!(
r#"
(xor
(par
(call "unknown_peer" ("service_id_1" "local_fn_name") [] lazy_defined_variable)
(call "{0}" ("service_id_1" "local_fn_name") [lazy_defined_variable] result)
)
(call "{0}" ("service_id_2" "local_fn_name") ["expected"] result)
)"#,
local_peer_id,
);
let res = call_vm!(vm, "asd", script, "[]", "[]");
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
assert_eq!(actual_trace[0], executed_state::par(1, 0));
assert_eq!(actual_trace[1], executed_state::request_sent_by(local_peer_id));
}
#[test]
fn xor_multiple_variables_found() {
let set_variables_peer_id = "set_variables_peer_id";
let mut set_variables_vm = create_avm(echo_string_call_service(), set_variables_peer_id);
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let some_string = String::from("some_string");
let expected_string = String::from("expected_string");
let script = format!(
r#"
(seq
(call "{0}" ("service_id_1" "local_fn_name") ["{2}"] result_1)
(xor
(call "{1}" ("service_id_1" "local_fn_name") [""] result_1)
(call "{1}" ("service_id_2" "local_fn_name") ["{3}"] result_2)
)
)"#,
set_variables_peer_id, local_peer_id, some_string, expected_string
);
let res = call_vm!(set_variables_vm, "asd", script.clone(), "[]", "[]");
let res = call_vm!(vm, "asd", script, "[]", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
let some_string_call_result = executed_state::scalar_string(some_string);
let expected_string_call_result = executed_state::scalar_string(expected_string);
assert_eq!(actual_trace.len(), 2);
assert_eq!(actual_trace[0], some_string_call_result);
assert_eq!(actual_trace[1], expected_string_call_result);
}
#[test]
fn xor_par() {
use executed_state::*;
let fallible_service_id = String::from("service_id_1");
let local_peer_id = "local_peer_id";
let mut vm = create_avm(fallible_call_service(fallible_service_id.clone()), local_peer_id);
let script = format!(
r#"
(xor
(par
(seq
(call "{0}" ("service_id_2" "local_fn_name") [] result_1)
(call "{0}" ("service_id_2" "local_fn_name") [] result_2)
)
(par
(call "{0}" ("service_id_1" "local_fn_name") [] result_3)
(call "{0}" ("service_id_2" "local_fn_name") [] result_4)
)
)
(seq
(call "{0}" ("service_id_2" "local_fn_name") [] result_4)
(call "{0}" ("service_id_2" "local_fn_name") [] result_5)
)
)"#,
local_peer_id
);
let result = call_vm!(vm, "asd", script.clone(), "[]", "[]");
let actual_trace: ExecutionTrace = serde_json::from_slice(&result.data).expect("should be valid json");
let res = String::from("res");
let expected_trace = vec![
par(2, 2),
scalar_string(&res),
scalar_string(&res),
par(1, 0),
service_failed(1, "error"),
scalar_string(&res),
scalar_string(&res),
];
assert_eq!(actual_trace, expected_trace);
let result = call_vm!(vm, "asd", script, "[]", result.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&result.data).expect("should be valid json");
assert_eq!(actual_trace, expected_trace);
}
#[test]
fn last_error_with_xor() {
use air_test_utils::echo_string_call_service;
let faillible_peer_id = "failible_peer_id";
let mut faillible_vm = create_avm(fallible_call_service("service_id_1"), faillible_peer_id);
let local_peer_id = "local_peer_id";
let mut vm = create_avm(echo_string_call_service(), local_peer_id);
let script = format!(
r#"
(xor
(call "{0}" ("service_id_1" "local_fn_name") [] result)
(call "{1}" ("service_id_2" "local_fn_name") [%last_error%] result)
)"#,
faillible_peer_id, local_peer_id,
);
let res = call_vm!(faillible_vm, "asd", script.clone(), "", "");
let res = call_vm!(vm, "asd", script, "", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
let expected_state = executed_state::scalar_string("{\"error\":\"Local service error: ret_code is 1, error message is \'error\'\",\"instruction\":\"call \\\"failible_peer_id\\\" (\\\"service_id_1\\\" \\\"local_fn_name\\\") [] result\"}");
assert_eq!(actual_trace[1], expected_state);
}

View File

@ -14,8 +14,10 @@
* limitations under the License.
*/
use air::execution_trace::ExecutionTrace;
use air_test_utils::call_vm;
use air_test_utils::create_avm;
use air_test_utils::executed_state;
use air_test_utils::set_variables_call_service;
use air_test_utils::unit_call_service;
use air_test_utils::CallServiceClosure;
@ -24,15 +26,8 @@ use air_test_utils::NEVec;
use serde_json::json;
use std::rc::Rc;
type JValue = serde_json::Value;
#[test]
fn seq_par_call() {
use air::execution_trace::CallResult::*;
use air::execution_trace::ExecutedState::{self, *};
let vm_peer_id = String::from("some_peer_id");
let mut vm = create_avm(unit_call_service(), vm_peer_id.clone());
@ -49,15 +44,14 @@ fn seq_par_call() {
);
let res = call_vm!(vm, "asd", script, "[]", "[]");
let actual_trace: Vec<ExecutedState> =
serde_json::from_slice(&res.data).expect("interpreter should return valid json");
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("interpreter should return valid json");
let test_string = String::from("test");
let test_string = "test";
let expected_trace = vec![
Par(1, 1),
Call(Executed(Rc::new(JValue::String(test_string.clone())))),
Call(RequestSentBy(vm_peer_id)),
Call(Executed(Rc::new(JValue::String(test_string.clone())))),
executed_state::par(1, 1),
executed_state::scalar_string(test_string),
executed_state::request_sent_by(vm_peer_id),
executed_state::scalar_string(test_string),
];
assert_eq!(actual_trace, expected_trace);
@ -66,9 +60,6 @@ fn seq_par_call() {
#[test]
fn par_par_call() {
use air::execution_trace::CallResult::*;
use air::execution_trace::ExecutedState::{self, *};
let vm_peer_id = String::from("some_peer_id");
let mut vm = create_avm(unit_call_service(), vm_peer_id.clone());
@ -85,16 +76,16 @@ fn par_par_call() {
);
let res = call_vm!(vm, "asd", script, "[]", "[]");
let resulted_trace: Vec<ExecutedState> =
let resulted_trace: ExecutionTrace =
serde_json::from_slice(&res.data).expect("interpreter should return valid json");
let test_string = String::from("test");
let test_string = "test";
let expected_trace = vec![
Par(3, 1),
Par(1, 1),
Call(Executed(Rc::new(JValue::String(test_string.clone())))),
Call(RequestSentBy(vm_peer_id)),
Call(Executed(Rc::new(JValue::String(test_string.clone())))),
executed_state::par(3, 1),
executed_state::par(1, 1),
executed_state::scalar_string(test_string),
executed_state::request_sent_by(vm_peer_id),
executed_state::scalar_string(test_string),
];
assert_eq!(resulted_trace, expected_trace);
@ -103,9 +94,6 @@ fn par_par_call() {
#[test]
fn create_service() {
use air::execution_trace::CallResult::*;
use air::execution_trace::ExecutedState::{self, *};
let module = "greeting";
let module_config = json!(
{
@ -160,18 +148,18 @@ fn create_service() {
let res = call_vm!(set_variables_vm, "init_peer_id", script.clone(), "[]", "[]");
let res = call_vm!(vm, "init_peer_id", script, "[]", res.data);
let add_module_response = String::from("add_module response");
let add_blueprint_response = String::from("add_blueprint response");
let create_response = String::from("create response");
let actual_trace: Vec<ExecutedState> = serde_json::from_slice(&res.data).expect("should be a correct json");
let add_module_response = "add_module response";
let add_blueprint_response = "add_blueprint response";
let create_response = "create response";
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be a correct json");
let expected_trace = vec![
Call(Executed(Rc::new(module_bytes))),
Call(Executed(Rc::new(module_config))),
Call(Executed(Rc::new(blueprint))),
Call(Executed(Rc::new(JValue::String(add_module_response)))),
Call(Executed(Rc::new(JValue::String(add_blueprint_response)))),
Call(Executed(Rc::new(JValue::String(create_response)))),
Call(RequestSentBy(String::from("A"))),
executed_state::scalar_jvalue(module_bytes),
executed_state::scalar_jvalue(module_config),
executed_state::scalar_jvalue(blueprint),
executed_state::scalar_string(add_module_response),
executed_state::scalar_string(add_blueprint_response),
executed_state::scalar_string(create_response),
executed_state::request_sent_by("A"),
];
assert_eq!(actual_trace, expected_trace);

View File

@ -16,8 +16,11 @@
use air_test_utils::call_vm;
use air_test_utils::create_avm;
use air_test_utils::executed_state;
use air_test_utils::set_variable_call_service;
use air_test_utils::set_variables_call_service;
use air_test_utils::CallServiceClosure;
use air_test_utils::ExecutionTrace;
use air_test_utils::IValue;
use air_test_utils::NEVec;
@ -28,6 +31,8 @@ type JValue = serde_json::Value;
#[test]
fn data_merge() {
use executed_state::*;
let neighborhood_call_service1: CallServiceClosure = Box::new(|_, _| -> Option<IValue> {
Some(IValue::Record(
NEVec::new(vec![IValue::S32(0), IValue::String(String::from("[\"A\", \"B\"]"))]).unwrap(),
@ -56,13 +61,13 @@ fn data_merge() {
)
)
(fold neighborhood i
(par
(par
(call i ("get_providers" "") [] $providers)
(next i)
)
)
)
(seq
(seq
(call "A" ("identity" "") [] $void)
(call "B" ("" "") [] none)
)
@ -77,79 +82,83 @@ fn data_merge() {
let res3 = call_vm!(vm1, "asd", script.clone(), res1.data.clone(), res2.data.clone());
let res4 = call_vm!(vm2, "asd", script, res1.data.clone(), res2.data.clone());
let resulted_json1: JValue = serde_json::from_slice(&res1.data).expect("interpreter should return valid json");
let actual_trace_1: ExecutionTrace =
serde_json::from_slice(&res1.data).expect("interpreter should return valid json");
let expected_json1 = json!( [
{ "call": { "executed": ["A", "B"] } },
{ "par": [1,2] },
{ "call": { "executed": ["A", "B"] } },
{ "par": [1,0] },
{ "call": { "request_sent_by": "A" } },
{ "par": [1,2] },
{ "call": { "executed": ["A", "B"] } },
{ "par": [1,0] },
{ "call": { "request_sent_by": "A" } },
{ "call": { "executed": ["A", "B"] } },
{ "call": { "request_sent_by": "A" } },
]);
let expected_trace_1 = vec![
scalar_string_array(vec!["A", "B"]),
par(1, 2),
stream_string_array(vec!["A", "B"], "$void"),
par(1, 0),
request_sent_by("A"),
par(1, 2),
stream_string_array(vec!["A", "B"], "$providers"),
par(1, 0),
request_sent_by("A"),
stream_string_array(vec!["A", "B"], "$void"),
request_sent_by("A"),
];
assert_eq!(resulted_json1, expected_json1);
assert_eq!(actual_trace_1, expected_trace_1);
assert_eq!(res1.next_peer_pks, vec![String::from("B")]);
let resulted_json2: JValue = serde_json::from_slice(&res2.data).expect("interpreter should return valid json");
let actual_trace_2: ExecutionTrace =
serde_json::from_slice(&res2.data).expect("interpreter should return valid json");
let expected_json2 = json!( [
{ "call": { "executed": ["A", "B"] } },
{ "par": [1,2] },
{ "call": { "request_sent_by": "B" } },
{ "par": [1,0] },
{ "call": { "executed": ["A", "B"] } },
{ "par": [1,2] },
{ "call": { "request_sent_by": "B" } },
{ "par": [1,0] },
{ "call": { "executed": ["A", "B"] } },
{ "call": { "request_sent_by": "B" } },
]);
let expected_trace_2 = vec![
scalar_string_array(vec!["A", "B"]),
par(1, 2),
request_sent_by("B"),
par(1, 0),
stream_string_array(vec!["A", "B"], "$void"),
par(1, 2),
request_sent_by("B"),
par(1, 0),
stream_string_array(vec!["A", "B"], "$providers"),
request_sent_by("B"),
];
assert_eq!(resulted_json2, expected_json2);
assert_eq!(actual_trace_2, expected_trace_2);
assert_eq!(res2.next_peer_pks, vec![String::from("A")]);
let resulted_json3: JValue = serde_json::from_slice(&res3.data).expect("interpreter should return valid json");
let actual_trace_3: ExecutionTrace =
serde_json::from_slice(&res3.data).expect("interpreter should return valid json");
let expected_json3 = json!( [
{ "call": { "executed": ["A", "B"] } },
{ "par": [1,2] },
{ "call": { "executed": ["A", "B"] } },
{ "par": [1,0] },
{ "call": { "executed": ["A", "B"] } },
{ "par": [1,2] },
{ "call": { "executed": ["A", "B"] } },
{ "par": [1,0] },
{ "call": { "executed": ["A", "B"] } },
{ "call": { "executed": ["A", "B"] } },
{ "call": { "request_sent_by": "A" } },
]);
let expected_trace_3 = vec![
scalar_string_array(vec!["A", "B"]),
par(1, 2),
stream_string_array(vec!["A", "B"], "$void"),
par(1, 0),
stream_string_array(vec!["A", "B"], "$void"),
par(1, 2),
stream_string_array(vec!["A", "B"], "$providers"),
par(1, 0),
stream_string_array(vec!["A", "B"], "$providers"),
stream_string_array(vec!["A", "B"], "$void"),
request_sent_by("A"),
];
assert_eq!(resulted_json3, expected_json3);
assert_eq!(actual_trace_3, expected_trace_3);
assert!(res3.next_peer_pks.is_empty());
let resulted_json4: JValue = serde_json::from_slice(&res4.data).expect("interpreter should return valid json");
let actual_trace_4: ExecutionTrace =
serde_json::from_slice(&res4.data).expect("interpreter should return valid json");
let expected_json4 = json!( [
{ "call": { "executed": ["A", "B"] } },
{ "par": [1,2] },
{ "call": { "executed": ["A", "B"] } },
{ "par": [1,0] },
{ "call": { "executed": ["A", "B"] } },
{ "par": [1,2] },
{ "call": { "executed": ["A", "B"] } },
{ "par": [1,0] },
{ "call": { "executed": ["A", "B"] } },
{ "call": { "executed": ["A", "B"] } },
{ "call": { "executed": ["A", "B"] } },
]);
let expected_trace_4 = vec![
scalar_string_array(vec!["A", "B"]),
par(1, 2),
stream_string_array(vec!["A", "B"], "$void"),
par(1, 0),
stream_string_array(vec!["A", "B"], "$void"),
par(1, 2),
stream_string_array(vec!["A", "B"], "$providers"),
par(1, 0),
stream_string_array(vec!["A", "B"], "$providers"),
stream_string_array(vec!["A", "B"], "$void"),
scalar_string_array(vec!["A", "B"]),
];
assert_eq!(resulted_json4, expected_json4);
assert_eq!(actual_trace_4, expected_trace_4);
assert!(res4.next_peer_pks.is_empty());
}
@ -210,3 +219,42 @@ fn acc_merge() {
let res = call_vm!(vm1, "asd", script.clone(), "[]", "[]");
call_vm!(vm2, "asd", script, "[]", res.data);
}
#[test]
#[ignore]
fn fold_merge() {
let set_variable_vm_id = "set_variable";
let local_vm_id = "local_vm";
let variables = maplit::hashmap! {
"stream1".to_string() => r#"["s1", "s2", "s3"]"#.to_string(),
"stream2".to_string() => r#"["s4", "s5", "s6"]"#.to_string(),
};
let local_vm_service_call: CallServiceClosure = Box::new(|_, values| -> Option<IValue> {
let args = match &values[2] {
IValue::String(str) => str,
_ => unreachable!(),
};
println!("args {:?}", args);
Some(IValue::Record(
NEVec::new(vec![IValue::S32(0), IValue::String(format!("{}", args))]).unwrap(),
))
});
let mut set_variable_vm = create_avm(set_variables_call_service(variables), set_variable_vm_id);
let mut local_vm = create_avm(local_vm_service_call, local_vm_id);
let script = format!(
include_str!("./scripts/inner_folds_v1.clj"),
set_variable_vm_id, local_vm_id
);
let res = call_vm!(set_variable_vm, "", script.clone(), "", "");
let res = call_vm!(local_vm, "", script, "", res.data);
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("interpreter should return valid json");
// println!("res is {:?}", actual_trace);
}

View File

@ -14,18 +14,17 @@
* limitations under the License.
*/
use air::execution_trace::ExecutionTrace;
use air_test_utils::call_vm;
use air_test_utils::create_avm;
use air_test_utils::executed_state;
use air_test_utils::unit_call_service;
use air_test_utils::CallServiceClosure;
use air_test_utils::IValue;
use air_test_utils::NEVec;
use pretty_assertions::assert_eq;
use serde_json::json;
type JValue = serde_json::Value;
#[test]
fn join_chat() {
use std::collections::HashSet;
@ -55,7 +54,7 @@ fn join_chat() {
(seq
(call "Remote" ("920e3ba3-cbdf-4ae3-8972-0fa2f31fffd9" "get_users") [] members)
(fold members m
(par
(par
(seq
(call m.$.[1]! ("identity" "") [] $void)
(call m.$.[0]! ("fgemb3" "add") [] $void3)
@ -71,43 +70,41 @@ fn join_chat() {
let client_1_res = call_vm!(client_1, "asd", script.clone(), "[]", "[]");
let client_1_res_json: JValue =
let client_1_actual_trace: ExecutionTrace =
serde_json::from_slice(&client_1_res.data).expect("interpreter should return valid json");
let client_1_expected_json = json!([
{ "call": {"request_sent_by": "A" } },
]);
let client_1_expected_trace = vec![executed_state::request_sent_by("A")];
assert_eq!(client_1_res_json, client_1_expected_json);
assert_eq!(client_1_actual_trace, client_1_expected_trace);
assert_eq!(client_1_res.next_peer_pks, vec![String::from("Relay1")]);
let relay_1_res = call_vm!(relay_1, "asd", script.clone(), client_1_res.data, "[]");
let relay_1_res_json: JValue =
let relay_1_actual_trace: ExecutionTrace =
serde_json::from_slice(&relay_1_res.data).expect("interpreter should return valid json");
let relay_1_expected_json = json!( [
{ "call": { "executed" : "test" } },
{ "call": { "request_sent_by": "Relay1" } },
]);
let relay_1_expected_trace = vec![
executed_state::stream_string("test", "void1"),
executed_state::request_sent_by("Relay1"),
];
assert_eq!(relay_1_res_json, relay_1_expected_json);
assert_eq!(relay_1_actual_trace, relay_1_expected_trace);
assert_eq!(relay_1_res.next_peer_pks, vec![String::from("Remote")]);
let remote_res = call_vm!(remote, "asd", script.clone(), relay_1_res.data, "[]");
let remote_res_json: JValue =
let remote_actual_trace: ExecutionTrace =
serde_json::from_slice(&remote_res.data).expect("interpreter should return valid json");
let remote_expected_json = json!( [
{ "call": { "executed" : "test" } },
{ "call": { "executed" : [["A", "Relay1"], ["B", "Relay2"]]} },
{ "call": { "executed" : [["A", "Relay1"], ["B", "Relay2"]]} },
{ "par": [1, 2] },
{ "call": { "request_sent_by" : "Remote" } },
{ "par": [1, 0] },
{ "call": { "request_sent_by" : "Remote" } },
]);
let remote_expected_trace = vec![
executed_state::stream_string("test", "void1"),
executed_state::stream_jvalue(json!([["A", "Relay1"], ["B", "Relay2"]]), "void2"),
executed_state::scalar_jvalue(json!([["A", "Relay1"], ["B", "Relay2"]])),
executed_state::par(1, 2),
executed_state::request_sent_by("Remote"),
executed_state::par(1, 0),
executed_state::request_sent_by("Remote"),
];
let remote_res_next_peer_pks: HashSet<_> = remote_res.next_peer_pks.iter().map(|s| s.as_str()).collect();
let next_peer_pks_right = maplit::hashset! {
@ -115,83 +112,82 @@ fn join_chat() {
"Relay2",
};
assert_eq!(remote_res_json, remote_expected_json);
assert_eq!(remote_actual_trace, remote_expected_trace);
assert_eq!(remote_res_next_peer_pks, next_peer_pks_right);
let relay_1_res = call_vm!(relay_1, "asd", script.clone(), remote_res.data.clone(), "[]");
let relay_1_res_json: JValue =
let relay_1_actual_trace: ExecutionTrace =
serde_json::from_slice(&relay_1_res.data).expect("interpreter should return valid json");
let relay_1_expected_trace = vec![
executed_state::stream_string("test", "void1"),
executed_state::stream_jvalue(json!([["A", "Relay1"], ["B", "Relay2"]]), "void2"),
executed_state::scalar_jvalue(json!([["A", "Relay1"], ["B", "Relay2"]])),
executed_state::par(2, 2),
executed_state::stream_string("test", "void"),
executed_state::request_sent_by("Relay1"),
executed_state::par(1, 0),
executed_state::request_sent_by("Remote"),
];
let relay_1_expected_json = json!( [
{ "call": { "executed" : "test" } },
{ "call": { "executed" : [["A", "Relay1"], ["B", "Relay2"]]} },
{ "call": { "executed" : [["A", "Relay1"], ["B", "Relay2"]]} },
{ "par": [2, 2] },
{ "call": { "executed" : "test" } },
{ "call": { "request_sent_by" : "Relay1" } },
{ "par": [1, 0] },
{ "call": { "request_sent_by" : "Remote" } },
]);
assert_eq!(relay_1_res_json, relay_1_expected_json);
assert_eq!(relay_1_actual_trace, relay_1_expected_trace);
assert_eq!(relay_1_res.next_peer_pks, vec![String::from("A")]);
let client_1_res = call_vm!(client_1, "asd", script.clone(), relay_1_res.data, "[]");
let client_1_res_json: JValue =
let client_1_actual_trace: ExecutionTrace =
serde_json::from_slice(&client_1_res.data).expect("interpreter should return valid json");
let client_1_expected_json = json!( [
{ "call": { "executed" : "test" } },
{ "call": { "executed" : [["A", "Relay1"], ["B", "Relay2"]]} },
{ "call": { "executed" : [["A", "Relay1"], ["B", "Relay2"]]} },
{ "par": [2, 2] },
{ "call": { "executed" : "test" } },
{ "call": { "executed" : "test" } },
{ "par": [1, 0] },
{ "call": { "request_sent_by" : "Remote" } },
]);
let client_1_expected_trace = vec![
executed_state::stream_string("test", "void1"),
executed_state::stream_jvalue(json!([["A", "Relay1"], ["B", "Relay2"]]), "void2"),
executed_state::scalar_jvalue(json!([["A", "Relay1"], ["B", "Relay2"]])),
executed_state::par(2, 2),
executed_state::stream_string("test", "void"),
executed_state::stream_string("test", "void3"),
executed_state::par(1, 0),
executed_state::request_sent_by("Remote"),
];
assert_eq!(client_1_res_json, client_1_expected_json);
assert_eq!(client_1_actual_trace, client_1_expected_trace);
assert_eq!(client_1_res.next_peer_pks, Vec::<String>::new());
let relay_2_res = call_vm!(relay_2, "asd", script.clone(), remote_res.data, "[]");
let relay_2_res_json: JValue =
let relay_2_actual_trace: ExecutionTrace =
serde_json::from_slice(&relay_2_res.data).expect("interpreter should return valid json");
let relay_2_expected_json = json!( [
{ "call": { "executed" : "test" } },
{ "call": { "executed" : [["A", "Relay1"], ["B", "Relay2"]]} },
{ "call": { "executed" : [["A", "Relay1"], ["B", "Relay2"]]} },
{ "par": [1, 3] },
{ "call": { "request_sent_by" : "Remote" } },
{ "par": [2, 0] },
{ "call": { "executed" : "test" } },
{ "call": { "request_sent_by" : "Relay2" } },
]);
let relay_2_expected_trace = vec![
executed_state::stream_string("test", "void1"),
executed_state::stream_jvalue(json!([["A", "Relay1"], ["B", "Relay2"]]), "void2"),
executed_state::scalar_jvalue(json!([["A", "Relay1"], ["B", "Relay2"]])),
executed_state::par(1, 3),
executed_state::request_sent_by("Remote"),
executed_state::par(2, 0),
executed_state::stream_string("test", "void"),
executed_state::request_sent_by("Relay2"),
];
assert_eq!(relay_2_res_json, relay_2_expected_json);
assert_eq!(relay_2_actual_trace, relay_2_expected_trace);
assert_eq!(relay_2_res.next_peer_pks, vec![String::from("B")]);
let client_2_res = call_vm!(client_2, "asd", script, relay_2_res.data, "[]");
let client_2_res_json: JValue =
let client_2_actual_trace: ExecutionTrace =
serde_json::from_slice(&client_2_res.data).expect("interpreter should return valid json");
let client_2_expected_json = json!( [
{ "call": { "executed" : "test" } },
{ "call": { "executed" : [["A", "Relay1"], ["B", "Relay2"]]} },
{ "call": { "executed" : [["A", "Relay1"], ["B", "Relay2"]]} },
{ "par": [1, 3] },
{ "call": { "request_sent_by" : "Remote" } },
{ "par": [2, 0] },
{ "call": { "executed" : "test" } },
{ "call": { "executed" : "test" } },
]);
let client_2_expected_trace = vec![
executed_state::stream_string("test", "void1"),
executed_state::stream_jvalue(json!([["A", "Relay1"], ["B", "Relay2"]]), "void2"),
executed_state::scalar_jvalue(json!([["A", "Relay1"], ["B", "Relay2"]])),
executed_state::par(1, 3),
executed_state::request_sent_by("Remote"),
executed_state::par(2, 0),
executed_state::stream_string("test", "void"),
executed_state::stream_string("test", "void3"),
];
assert_eq!(client_2_res_json, client_2_expected_json);
assert_eq!(client_2_actual_trace, client_2_expected_trace);
assert_eq!(client_2_res.next_peer_pks, Vec::<String>::new());
}
@ -214,7 +210,7 @@ fn join() {
(seq
(call "Remote" ("920e3ba3-cbdf-4ae3-8972-0fa2f31fffd9" "get_users") [] members)
(fold members m
(par
(par
(seq
(call "Relay1" ("identity" "") [] $void)
(call "A" ("fgemb3" "add") [m] $void3)
@ -233,21 +229,21 @@ fn join() {
let relay_1_res = call_vm!(relay_1, "asd", script.clone(), remote_res.data, "[]");
let client_1_res = call_vm!(client_1, "asd", script, relay_1_res.data, "[]");
let client_1_res_json: JValue =
let client_1_actual_trace: ExecutionTrace =
serde_json::from_slice(&client_1_res.data).expect("interpreter should return valid json");
let client_1_expected_json = json!( [
{ "call": { "executed" : "test" } },
{ "call": { "executed" : [["A"], ["B"]]} },
{ "par": [2, 3] },
{ "call": { "executed" : "test" } },
{ "call": { "executed" : "test" } },
{ "par": [2, 0] },
{ "call": { "executed" : "test" } },
{ "call": { "executed" : "test" } },
]);
let client_1_expected_trace = vec![
executed_state::stream_string("test", "void1"),
executed_state::scalar_jvalue(json!([["A"], ["B"]])),
executed_state::par(2, 3),
executed_state::stream_string("test", "void"),
executed_state::stream_string("test", "void3"),
executed_state::par(2, 0),
executed_state::stream_string("test", "void"),
executed_state::stream_string("test", "void3"),
];
assert_eq!(client_1_res_json, client_1_expected_json);
assert_eq!(client_1_actual_trace, client_1_expected_trace);
assert_eq!(client_1_res.next_peer_pks, Vec::<String>::new());
}
@ -313,41 +309,41 @@ fn init_peer_id() {
""
);
let client_1_res_json: JValue =
let client_1_actual_trace: ExecutionTrace =
serde_json::from_slice(&client_1_res.data).expect("interpreter should return valid json");
let client_1_expected_json = json!( [
{ "call": { "executed" : "test" } },
{ "call": { "executed" : [["A"], ["B"]]} },
{ "par": [2, 3] },
{ "call": { "executed" : "test" } },
{ "call": { "executed" : "test" } },
{ "par": [2, 0] },
{ "call": { "executed" : "test" } },
{ "call": { "executed" : "test" } },
{ "call": { "request_sent_by" : "A" } },
]);
let client_1_expected_trace = vec![
executed_state::scalar_string("test"),
executed_state::scalar_jvalue(json!([["A"], ["B"]])),
executed_state::par(2, 3),
executed_state::scalar_string("test"),
executed_state::scalar_string("test"),
executed_state::par(2, 0),
executed_state::scalar_string("test"),
executed_state::scalar_string("test"),
executed_state::request_sent_by("A"),
];
assert_eq!(client_1_res_json, client_1_expected_json);
assert_eq!(client_1_actual_trace, client_1_expected_trace);
assert_eq!(client_1_res.next_peer_pks, vec![initiator_peer_id.clone()]);
let initiator_1_res = call_vm!(initiator, initiator_peer_id, script, client_1_res.data, "");
let initiator_1_res_json: JValue =
let initiator_1_actual_trace: ExecutionTrace =
serde_json::from_slice(&initiator_1_res.data).expect("interpreter should return valid json");
let initiator_1_expected_json = json!( [
{ "call": { "executed" : "test" } },
{ "call": { "executed" : [["A"], ["B"]]} },
{ "par": [2, 3] },
{ "call": { "executed" : "test" } },
{ "call": { "executed" : "test" } },
{ "par": [2, 0] },
{ "call": { "executed" : "test" } },
{ "call": { "executed" : "test" } },
{ "call": { "executed" : "test" } },
]);
let initiator_1_expected_trace = vec![
executed_state::scalar_string("test"),
executed_state::scalar_jvalue(json!([["A"], ["B"]])),
executed_state::par(2, 3),
executed_state::scalar_string("test"),
executed_state::scalar_string("test"),
executed_state::par(2, 0),
executed_state::scalar_string("test"),
executed_state::scalar_string("test"),
executed_state::scalar_string("test"),
];
assert_eq!(initiator_1_res_json, initiator_1_expected_json);
assert_eq!(initiator_1_actual_trace, initiator_1_expected_trace);
assert_eq!(initiator_1_res.next_peer_pks, Vec::<String>::new());
}

View File

@ -0,0 +1,24 @@
/*
* 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.
*/
mod air_basic;
mod dashboard;
mod data_merge;
mod flattening;
mod join;
mod join_behaviour;
mod last_error;
mod network_explore;

View File

@ -0,0 +1,33 @@
(seq
(seq
(call "{0}" ("" "") ["stream1"] stream1)
(call "{0}" ("" "") ["stream2"] stream2)
)
(fold stream1 v1
(seq
(fold stream2 v2
(seq
(call "{1}" ("" "") [v1 v2] stream_out1[])
(seq
(call "{1}" ("" "") [v1 v2] stream_out2[])
(seq
(next v2)
(seq
(call "{1}" ("" "") [v1 v2] stream_out3[])
(seq
(call "{1}" ("" "") [v1 v2] stream_out4[])
(seq
(call "{1}" ("" "") [v1 v2] stream_out5[])
(call "{1}" ("" "") [v1 v2] stream_out6[])
)
)
)
)
)
)
)
(next v1)
)
)
)

View File

@ -4,9 +4,9 @@ version = 3
[[package]]
name = "aho-corasick"
version = "0.7.15"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr",
]
@ -145,15 +145,15 @@ checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9"
[[package]]
name = "bumpalo"
version = "3.4.0"
version = "3.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"
checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe"
[[package]]
name = "byteorder"
version = "1.4.2"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cfg-if"
@ -207,9 +207,9 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
[[package]]
name = "crossbeam-utils"
version = "0.8.1"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
checksum = "4feb231f0d4d6af81aed15928e58ecf5816aa62a2393e2c82f46973e92a9a278"
dependencies = [
"autocfg",
"cfg-if 1.0.0",
@ -267,16 +267,6 @@ dependencies = [
"termcolor",
]
[[package]]
name = "fce-timestamp-macro"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c59a6302902583b2c84e87de9d72b949da4396a369baf0aaa49e97021600bb0"
dependencies = [
"chrono",
"quote",
]
[[package]]
name = "fixedbitset"
version = "0.2.0"
@ -285,13 +275,13 @@ checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
[[package]]
name = "fluence"
version = "0.6.1"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54b2f78a2432dcd10e7113f9f08aac004373dee610a3b4ca692d5b12a3e7c867"
checksum = "bd1f159a4da6aef89e8e4a0bf061a8031d669d03d9928266942581a52df03f56"
dependencies = [
"fce-timestamp-macro",
"fluence-sdk-macro",
"fluence-sdk-main",
"marine-macro",
"marine-timestamp-macro",
"serde",
]
@ -305,40 +295,17 @@ dependencies = [
"serde",
]
[[package]]
name = "fluence-sdk-macro"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb43d2f51f1becb70e2125ef8ca9759597900f95cc22ce7dca981a7d6ccd7dde"
dependencies = [
"fluence-sdk-wit",
]
[[package]]
name = "fluence-sdk-main"
version = "0.6.1"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a78910d85e3cdcb9c2baf56144f20a99925c67ac445d4156220c005bfd2f9604"
checksum = "b3a5d1ca20ada064379d959a9a82f9c006e4d9388533cf06010186fef6dd583b"
dependencies = [
"fluence-sdk-macro",
"log",
"marine-macro",
"serde",
]
[[package]]
name = "fluence-sdk-wit"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eab3ed39703b72e0e52bce9e1760746c73f65a5694c8da4dec751d3bfdec15b8"
dependencies = [
"proc-macro2",
"quote",
"serde",
"serde_json",
"syn",
"uuid",
]
[[package]]
name = "getrandom"
version = "0.1.16"
@ -352,9 +319,9 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4060f4657be78b8e766215b02b18a2e862d83745545de804638e2b545e81aee6"
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
dependencies = [
"cfg-if 1.0.0",
"libc",
@ -369,9 +336,9 @@ checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
[[package]]
name = "hermit-abi"
version = "0.1.17"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
dependencies = [
"libc",
]
@ -387,9 +354,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "1.6.1"
version = "1.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b"
checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"
dependencies = [
"autocfg",
"hashbrown",
@ -469,24 +436,57 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.82"
version = "0.2.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929"
checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
[[package]]
name = "log"
version = "0.4.13"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcf3805d4480bb5b86070dcfeb9e2cb2ebc148adb753c5cca5f884d1d65a42b2"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if 0.1.10",
"cfg-if 1.0.0",
]
[[package]]
name = "marine-macro"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c1652b6ac1bbdde9a66c16c8a2f9cd34d005a1f1b211a538c5b28764faa6ef4"
dependencies = [
"marine-macro-impl",
]
[[package]]
name = "marine-macro-impl"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80fee75eaf1a97ee9fe2d382c0537c06a79e5d7ab9d81bda6cb263fb8fd1a15a"
dependencies = [
"proc-macro2",
"quote",
"serde",
"serde_json",
"syn",
"uuid",
]
[[package]]
name = "marine-timestamp-macro"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6feb612ccd3fd39ec3d50c9a1a96885e1fd32d36a92cf674a0fbe6f7c452613"
dependencies = [
"chrono",
"quote",
]
[[package]]
name = "memchr"
version = "2.3.4"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
[[package]]
name = "multimap"
@ -543,9 +543,9 @@ dependencies = [
[[package]]
name = "pico-args"
version = "0.4.0"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d70072c20945e1ab871c472a285fc772aefd4f5407723c206242f2c6f94595d6"
checksum = "7d7afeb98c5a10e0bffcc7fc16e105b04d06729fac5fd6384aebf7ff5cb5a67d"
[[package]]
name = "polyplets"
@ -563,9 +563,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]]
name = "proc-macro2"
version = "1.0.24"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
dependencies = [
"unicode-xid",
]
@ -604,21 +604,20 @@ dependencies = [
[[package]]
name = "regex"
version = "1.4.3"
version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
"thread_local",
]
[[package]]
name = "regex-syntax"
version = "0.6.22"
version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "rust-argon2"
@ -672,9 +671,9 @@ dependencies = [
[[package]]
name = "siphasher"
version = "0.3.3"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa8f3741c7372e75519bd9346068370c9cdaabcc1f9599cbcf2a2719352286b7"
checksum = "cbce6d4507c7e4a3962091436e56e95290cb71fa302d0d270e32130b75fbff27"
[[package]]
name = "string_cache"
@ -690,9 +689,9 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.67"
version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6498a9efc342871f91cc2d0d694c674368b4ceb40f62b65a7a08c3792935e702"
checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82"
dependencies = [
"proc-macro2",
"quote",
@ -721,33 +720,24 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.23"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76cc616c6abf8c8928e2fdcc0dbfab37175edd8fb49a4641066ad1364fdab146"
checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.23"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1"
checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "thread_local"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb9bc092d0d51e76b2b19d9d85534ffc9ec2db959a2523cdae0697e2972cd447"
dependencies = [
"lazy_static",
]
[[package]]
name = "time"
version = "0.1.44"
@ -776,9 +766,9 @@ checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
[[package]]
name = "unicode-xid"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "uuid"
@ -786,7 +776,7 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
dependencies = [
"getrandom 0.2.1",
"getrandom 0.2.2",
]
[[package]]

View File

@ -9,7 +9,7 @@ name = "auth_module"
path = "src/main.rs"
[dependencies]
air = { path = "../../../../air" }
air = { path = "../../../../../../air" }
fluence = "0.6.5"
[workspace]

View File

@ -4,9 +4,9 @@ version = 3
[[package]]
name = "aho-corasick"
version = "0.7.15"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr",
]
@ -137,15 +137,15 @@ checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9"
[[package]]
name = "bumpalo"
version = "3.4.0"
version = "3.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"
checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe"
[[package]]
name = "byteorder"
version = "1.4.2"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cfg-if"
@ -199,9 +199,9 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
[[package]]
name = "crossbeam-utils"
version = "0.8.1"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
checksum = "4feb231f0d4d6af81aed15928e58ecf5816aa62a2393e2c82f46973e92a9a278"
dependencies = [
"autocfg",
"cfg-if 1.0.0",
@ -259,16 +259,6 @@ dependencies = [
"termcolor",
]
[[package]]
name = "fce-timestamp-macro"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c59a6302902583b2c84e87de9d72b949da4396a369baf0aaa49e97021600bb0"
dependencies = [
"chrono",
"quote",
]
[[package]]
name = "fixedbitset"
version = "0.2.0"
@ -277,13 +267,13 @@ checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
[[package]]
name = "fluence"
version = "0.6.1"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54b2f78a2432dcd10e7113f9f08aac004373dee610a3b4ca692d5b12a3e7c867"
checksum = "bd1f159a4da6aef89e8e4a0bf061a8031d669d03d9928266942581a52df03f56"
dependencies = [
"fce-timestamp-macro",
"fluence-sdk-macro",
"fluence-sdk-main",
"marine-macro",
"marine-timestamp-macro",
"serde",
]
@ -297,40 +287,17 @@ dependencies = [
"serde",
]
[[package]]
name = "fluence-sdk-macro"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb43d2f51f1becb70e2125ef8ca9759597900f95cc22ce7dca981a7d6ccd7dde"
dependencies = [
"fluence-sdk-wit",
]
[[package]]
name = "fluence-sdk-main"
version = "0.6.1"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a78910d85e3cdcb9c2baf56144f20a99925c67ac445d4156220c005bfd2f9604"
checksum = "b3a5d1ca20ada064379d959a9a82f9c006e4d9388533cf06010186fef6dd583b"
dependencies = [
"fluence-sdk-macro",
"log",
"marine-macro",
"serde",
]
[[package]]
name = "fluence-sdk-wit"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eab3ed39703b72e0e52bce9e1760746c73f65a5694c8da4dec751d3bfdec15b8"
dependencies = [
"proc-macro2",
"quote",
"serde",
"serde_json",
"syn",
"uuid",
]
[[package]]
name = "getrandom"
version = "0.1.16"
@ -344,9 +311,9 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4060f4657be78b8e766215b02b18a2e862d83745545de804638e2b545e81aee6"
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
dependencies = [
"cfg-if 1.0.0",
"libc",
@ -361,9 +328,9 @@ checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
[[package]]
name = "hermit-abi"
version = "0.1.17"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
dependencies = [
"libc",
]
@ -379,9 +346,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "1.6.1"
version = "1.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b"
checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"
dependencies = [
"autocfg",
"hashbrown",
@ -461,17 +428,17 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.82"
version = "0.2.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929"
checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
[[package]]
name = "log"
version = "0.4.13"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcf3805d4480bb5b86070dcfeb9e2cb2ebc148adb753c5cca5f884d1d65a42b2"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if 0.1.10",
"cfg-if 1.0.0",
]
[[package]]
@ -483,10 +450,43 @@ dependencies = [
]
[[package]]
name = "memchr"
version = "2.3.4"
name = "marine-macro"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
checksum = "1c1652b6ac1bbdde9a66c16c8a2f9cd34d005a1f1b211a538c5b28764faa6ef4"
dependencies = [
"marine-macro-impl",
]
[[package]]
name = "marine-macro-impl"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80fee75eaf1a97ee9fe2d382c0537c06a79e5d7ab9d81bda6cb263fb8fd1a15a"
dependencies = [
"proc-macro2",
"quote",
"serde",
"serde_json",
"syn",
"uuid",
]
[[package]]
name = "marine-timestamp-macro"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6feb612ccd3fd39ec3d50c9a1a96885e1fd32d36a92cf674a0fbe6f7c452613"
dependencies = [
"chrono",
"quote",
]
[[package]]
name = "memchr"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
[[package]]
name = "multimap"
@ -543,9 +543,9 @@ dependencies = [
[[package]]
name = "pico-args"
version = "0.4.0"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d70072c20945e1ab871c472a285fc772aefd4f5407723c206242f2c6f94595d6"
checksum = "7d7afeb98c5a10e0bffcc7fc16e105b04d06729fac5fd6384aebf7ff5cb5a67d"
[[package]]
name = "polyplets"
@ -563,9 +563,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]]
name = "proc-macro2"
version = "1.0.24"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
dependencies = [
"unicode-xid",
]
@ -604,21 +604,20 @@ dependencies = [
[[package]]
name = "regex"
version = "1.4.3"
version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
"thread_local",
]
[[package]]
name = "regex-syntax"
version = "0.6.22"
version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "rust-argon2"
@ -672,9 +671,9 @@ dependencies = [
[[package]]
name = "siphasher"
version = "0.3.3"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa8f3741c7372e75519bd9346068370c9cdaabcc1f9599cbcf2a2719352286b7"
checksum = "cbce6d4507c7e4a3962091436e56e95290cb71fa302d0d270e32130b75fbff27"
[[package]]
name = "string_cache"
@ -690,9 +689,9 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.67"
version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6498a9efc342871f91cc2d0d694c674368b4ceb40f62b65a7a08c3792935e702"
checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82"
dependencies = [
"proc-macro2",
"quote",
@ -721,33 +720,24 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.23"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76cc616c6abf8c8928e2fdcc0dbfab37175edd8fb49a4641066ad1364fdab146"
checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.23"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1"
checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "thread_local"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb9bc092d0d51e76b2b19d9d85534ffc9ec2db959a2523cdae0697e2972cd447"
dependencies = [
"lazy_static",
]
[[package]]
name = "time"
version = "0.1.44"
@ -776,9 +766,9 @@ checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
[[package]]
name = "unicode-xid"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "uuid"
@ -786,7 +776,7 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
dependencies = [
"getrandom 0.2.1",
"getrandom 0.2.2",
]
[[package]]

View File

@ -9,7 +9,7 @@ name = "log_storage"
path = "src/main.rs"
[dependencies]
air = { path = "../../../../air" }
air = { path = "../../../../../../air" }
fluence = "0.6.5"
[workspace]

View File

@ -0,0 +1,19 @@
/*
* 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.
*/
// https://matklad.github.io/2021/02/27/delete-cargo-integration-tests.html
mod instructions;
mod integration;

View File

@ -1,6 +1,6 @@
[package]
name = "air-test-utils"
version = "0.1.0"
version = "0.2.0"
authors = ["Fluence Labs"]
edition = "2018"
license = "Apache-2.0"
@ -12,4 +12,6 @@ path = "src/lib.rs"
[dependencies]
fluence = "0.6.5"
avm-server = { path = "../../avm/server", features = ["raw-avm-api"] }
air = { path = "../../air" }
serde_json = "1.0.56"

View File

@ -0,0 +1,81 @@
/*
* 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 super::JValue;
use air::execution_trace::CallResult;
use air::execution_trace::ExecutedState;
use air::execution_trace::ParResult;
use std::rc::Rc;
pub fn scalar_jvalue(result: JValue) -> ExecutedState {
ExecutedState::Call(CallResult::Executed(Rc::new(result)))
}
pub fn stream_jvalue(result: JValue, _stream_name: impl Into<String>) -> ExecutedState {
ExecutedState::Call(CallResult::Executed(Rc::new(result)))
}
pub fn scalar_string(result: impl Into<String>) -> ExecutedState {
ExecutedState::Call(CallResult::Executed(Rc::new(JValue::String(result.into()))))
}
pub fn scalar_string_array(result: Vec<impl Into<String>>) -> ExecutedState {
let result = result
.into_iter()
.map(|s| JValue::String(s.into()))
.collect::<Vec<_>>();
ExecutedState::Call(CallResult::Executed(Rc::new(JValue::Array(result))))
}
pub fn stream_string(result: impl Into<String>, _stream_name: impl Into<String>) -> ExecutedState {
ExecutedState::Call(CallResult::Executed(Rc::new(JValue::String(result.into()))))
}
pub fn stream_number(
result: impl Into<serde_json::Number>,
_stream_name: impl Into<String>,
) -> ExecutedState {
ExecutedState::Call(CallResult::Executed(Rc::new(JValue::Number(result.into()))))
}
pub fn stream_string_array(
result: Vec<impl Into<String>>,
_stream_name: impl Into<String>,
) -> ExecutedState {
let result = result
.into_iter()
.map(|s| JValue::String(s.into()))
.collect::<Vec<_>>();
ExecutedState::Call(CallResult::Executed(Rc::new(JValue::Array(result))))
}
pub fn request_sent_by(sender: impl Into<String>) -> ExecutedState {
ExecutedState::Call(CallResult::RequestSentBy(sender.into()))
}
pub fn par(left: usize, right: usize) -> ExecutedState {
ExecutedState::Par(ParResult(left, right))
}
pub fn service_failed(ret_code: i32, error_message: impl Into<String>) -> ExecutedState {
ExecutedState::Call(CallResult::CallServiceFailed(
ret_code,
Rc::new(error_message.into()),
))
}

View File

@ -25,6 +25,8 @@
unreachable_patterns
)]
pub mod executed_state;
pub use avm_server::ne_vec::NEVec;
pub use avm_server::AVMConfig;
pub use avm_server::AVMError;
@ -35,10 +37,12 @@ pub use avm_server::InterpreterOutcome;
pub use avm_server::ParticleParameters;
pub use avm_server::AVM;
pub use air::execution_trace::ExecutionTrace;
use std::collections::HashMap;
use std::path::PathBuf;
type JValue = serde_json::Value;
pub(self) type JValue = serde_json::Value;
pub fn create_avm(call_service: CallServiceClosure, current_peer_id: impl Into<String>) -> AVM {
let tmp_dir = std::env::temp_dir();