mirror of
https://github.com/fluencelabs/aquavm
synced 2024-12-04 23:20:18 +00:00
Do not clear %last_error% in match/mismatch (#71)
This commit is contained in:
parent
73fe4d9d3b
commit
7356f03fa9
@ -53,6 +53,31 @@ macro_rules! execute {
|
||||
};
|
||||
}
|
||||
|
||||
/// Executes match/mismatch instructions and updates last error if error type wasn't
|
||||
/// MatchWithoutXorError or MismatchWithoutXorError.
|
||||
macro_rules! execute_match_mismatch {
|
||||
($self:expr, $instr:expr, $exec_ctx:ident, $trace_ctx:ident) => {
|
||||
match $instr.execute($exec_ctx, $trace_ctx) {
|
||||
Err(e) => {
|
||||
use std::borrow::Borrow;
|
||||
|
||||
if !$exec_ctx.last_error_could_be_set
|
||||
|| matches!(&*e.borrow(), ExecutionError::MatchWithoutXorError)
|
||||
|| matches!(&*e.borrow(), ExecutionError::MismatchWithoutXorError)
|
||||
{
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
let instruction = format!("{}", $self);
|
||||
let last_error = LastErrorDescriptor::new(e.clone(), instruction, None);
|
||||
$exec_ctx.last_error = Some(last_error);
|
||||
Err(e)
|
||||
}
|
||||
v => v,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) trait ExecutableInstruction<'i> {
|
||||
fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, trace_ctx: &mut ExecutionTraceCtx) -> ExecutionResult<()>;
|
||||
}
|
||||
@ -63,14 +88,18 @@ impl<'i> ExecutableInstruction<'i> for Instruction<'i> {
|
||||
// call isn't wrapped by the execute macro because
|
||||
// it internally sets last_error with resolved triplet
|
||||
Instruction::Call(call) => call.execute(exec_ctx, trace_ctx),
|
||||
|
||||
Instruction::Fold(fold) => execute!(self, fold, exec_ctx, trace_ctx),
|
||||
Instruction::Next(next) => execute!(self, next, exec_ctx, trace_ctx),
|
||||
Instruction::Null(null) => execute!(self, null, exec_ctx, trace_ctx),
|
||||
Instruction::Par(par) => execute!(self, par, exec_ctx, trace_ctx),
|
||||
Instruction::Seq(seq) => execute!(self, seq, exec_ctx, trace_ctx),
|
||||
Instruction::Xor(xor) => execute!(self, xor, exec_ctx, trace_ctx),
|
||||
Instruction::Match(match_) => execute!(self, match_, exec_ctx, trace_ctx),
|
||||
Instruction::MisMatch(mismatch) => execute!(self, mismatch, exec_ctx, trace_ctx),
|
||||
|
||||
// match/mismatch shouldn't rewrite last_error
|
||||
Instruction::Match(match_) => execute_match_mismatch!(self, match_, exec_ctx, trace_ctx),
|
||||
Instruction::MisMatch(mismatch) => execute_match_mismatch!(self, mismatch, exec_ctx, trace_ctx),
|
||||
|
||||
Instruction::Error => unreachable!("should not execute if parsing succeeded. QED."),
|
||||
}
|
||||
}
|
||||
|
@ -19,14 +19,10 @@ use aqua_test_utils::create_aqua_vm;
|
||||
use aqua_test_utils::set_variables_call_service;
|
||||
use aqua_test_utils::unit_call_service;
|
||||
|
||||
use interpreter_lib::execution_trace::ExecutionTrace;
|
||||
|
||||
use serde_json::json;
|
||||
|
||||
#[test]
|
||||
fn non_wait_on_json_path() {
|
||||
use log::LevelFilter::Info;
|
||||
|
||||
let status = json!({
|
||||
"err_msg": "",
|
||||
"is_authenticated": 1,
|
||||
|
@ -23,7 +23,15 @@ use aqua_test_utils::IValue;
|
||||
use aqua_test_utils::NEVec;
|
||||
use interpreter_lib::SecurityTetraplet;
|
||||
|
||||
fn create_check_service_closure() -> CallServiceClosure {
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
type ArgToCheck<T> = Rc<RefCell<Option<T>>>;
|
||||
|
||||
fn create_check_service_closure(
|
||||
args_to_check: ArgToCheck<Vec<String>>,
|
||||
tetraplets_to_check: ArgToCheck<Vec<Vec<SecurityTetraplet>>>,
|
||||
) -> CallServiceClosure {
|
||||
Box::new(move |_, args| -> Option<IValue> {
|
||||
let call_args = match &args[2] {
|
||||
IValue::String(str) => str,
|
||||
@ -40,16 +48,8 @@ fn create_check_service_closure() -> CallServiceClosure {
|
||||
let de_tetraplets: Vec<Vec<SecurityTetraplet>> =
|
||||
serde_json::from_str(tetraplets).expect("json deserialization shouldn't fail");
|
||||
|
||||
assert_eq!(
|
||||
call_args[0],
|
||||
r#"{"error":"Local service error: ret_code is 1, error message is 'error'","instruction":"call \"failible_peer_id\" ("falliable_call_service" "") [service_id] client_result"}"#
|
||||
);
|
||||
|
||||
let triplet = &de_tetraplets[0][0].triplet;
|
||||
assert_eq!(triplet.peer_pk, "failible_peer_id");
|
||||
assert_eq!(triplet.service_id, "failiable_call_service");
|
||||
assert_eq!(triplet.function_name, "");
|
||||
assert_eq!(de_tetraplets[0][0].json_path, "");
|
||||
*args_to_check.borrow_mut() = Some(call_args);
|
||||
*tetraplets_to_check.borrow_mut() = Some(de_tetraplets);
|
||||
|
||||
Some(IValue::Record(
|
||||
NEVec::new(vec![IValue::S32(0), IValue::String(tetraplets.clone())]).unwrap(),
|
||||
@ -62,20 +62,111 @@ fn last_error_tetraplets() {
|
||||
let set_variable_peer_id = "set_variable";
|
||||
let mut set_variable_vm = create_aqua_vm(unit_call_service(), set_variable_peer_id);
|
||||
|
||||
let faillible_peer_id = "failible_peer_id";
|
||||
let mut faillible_vm = create_aqua_vm(fallible_call_service("falliable_call_service"), faillible_peer_id);
|
||||
let fallible_peer_id = "fallible_peer_id";
|
||||
let mut fallible_vm = create_aqua_vm(fallible_call_service("fallible_call_service"), fallible_peer_id);
|
||||
|
||||
let local_peer_id = "local_peer_id";
|
||||
let mut local_vm = create_aqua_vm(create_check_service_closure(), local_peer_id);
|
||||
|
||||
let args = Rc::new(RefCell::new(None));
|
||||
let tetraplets = Rc::new(RefCell::new(None));
|
||||
let mut local_vm = create_aqua_vm(
|
||||
create_check_service_closure(args.clone(), tetraplets.clone()),
|
||||
local_peer_id,
|
||||
);
|
||||
|
||||
let script = format!(
|
||||
include_str!("scripts/create_service_with_xor.clj"),
|
||||
set_variable_peer_id, faillible_peer_id, local_peer_id
|
||||
set_variable_peer_id, fallible_peer_id, local_peer_id
|
||||
);
|
||||
|
||||
let res = call_vm!(set_variable_vm, "asd", script.clone(), "", "");
|
||||
let res = call_vm!(faillible_vm, "asd", script.clone(), "", res.data);
|
||||
|
||||
// assert is done on the 'create_check_service_closure' call service closure
|
||||
let res = call_vm!(fallible_vm, "asd", script.clone(), "", res.data);
|
||||
let _ = call_vm!(local_vm, "asd", script, "", res.data);
|
||||
|
||||
assert_eq!(
|
||||
(*args.borrow()).as_ref().unwrap()[0],
|
||||
r#"{"error":"Local service error: ret_code is 1, error message is 'error'","instruction":"call \"fallible_peer_id\" (\"fallible_call_service\" \"\") [service_id] client_result"}"#
|
||||
);
|
||||
|
||||
let triplet = (*tetraplets.borrow()).as_ref().unwrap()[0][0].triplet.clone();
|
||||
assert_eq!(triplet.peer_pk, fallible_peer_id);
|
||||
assert_eq!(triplet.service_id, "fallible_call_service");
|
||||
assert_eq!(triplet.function_name, "");
|
||||
assert_eq!(&(*tetraplets.borrow()).as_ref().unwrap()[0][0].json_path, "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn not_clear_last_error_in_match() {
|
||||
let set_variable_peer_id = "set_variable";
|
||||
let mut set_variable_vm = create_aqua_vm(unit_call_service(), set_variable_peer_id);
|
||||
|
||||
let local_peer_id = "local_peer_id";
|
||||
|
||||
let args = Rc::new(RefCell::new(None));
|
||||
let tetraplets = Rc::new(RefCell::new(None));
|
||||
let mut local_vm = create_aqua_vm(
|
||||
create_check_service_closure(args.clone(), tetraplets.clone()),
|
||||
local_peer_id,
|
||||
);
|
||||
|
||||
let script = format!(
|
||||
r#"
|
||||
(seq
|
||||
(call "{0}" ("" "") [] relayVariableName)
|
||||
(xor
|
||||
(match relayVariableName ""
|
||||
(call "unknown_peer" ("" "") [%last_error%])
|
||||
)
|
||||
(seq
|
||||
(call "{1}" ("op" "identity") [])
|
||||
(call "{1}" ("" "") [%last_error%])
|
||||
)
|
||||
)
|
||||
)
|
||||
"#,
|
||||
set_variable_peer_id, local_peer_id
|
||||
);
|
||||
|
||||
let res = call_vm!(set_variable_vm, "asd", &script, "", "");
|
||||
let _ = call_vm!(local_vm, "asd", &script, "", res.data);
|
||||
|
||||
assert_eq!((*args.borrow()).as_ref().unwrap()[0], "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn not_clear_last_error_in_mismatch() {
|
||||
let set_variable_peer_id = "set_variable";
|
||||
let mut set_variable_vm = create_aqua_vm(unit_call_service(), set_variable_peer_id);
|
||||
|
||||
let local_peer_id = "local_peer_id";
|
||||
|
||||
let args = Rc::new(RefCell::new(None));
|
||||
let tetraplets = Rc::new(RefCell::new(None));
|
||||
let mut local_vm = create_aqua_vm(
|
||||
create_check_service_closure(args.clone(), tetraplets.clone()),
|
||||
local_peer_id,
|
||||
);
|
||||
|
||||
let script = format!(
|
||||
r#"
|
||||
(seq
|
||||
(call "{0}" ("" "") [] relayVariableName)
|
||||
(xor
|
||||
(mismatch relayVariableName "test"
|
||||
(call "unknown_peer" ("" "") [%last_error%])
|
||||
)
|
||||
(seq
|
||||
(call "{1}" ("op" "identity") [])
|
||||
(call "{1}" ("" "") [%last_error%])
|
||||
)
|
||||
)
|
||||
)
|
||||
"#,
|
||||
set_variable_peer_id, local_peer_id
|
||||
);
|
||||
|
||||
let res = call_vm!(set_variable_vm, "asd", &script, "", "");
|
||||
let _ = call_vm!(local_vm, "asd", &script, "", res.data);
|
||||
|
||||
assert_eq!((*args.borrow()).as_ref().unwrap()[0], "");
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
(call "{0}" ("dist" "add_blueprint") [blueprint] blueprint_id)
|
||||
(seq
|
||||
(call "{0}" ("srv" "create") [blueprint_id] service_id)
|
||||
(call "{1}" ("failiable_call_service" "") [service_id] client_result)
|
||||
(call "{1}" ("fallible_call_service" "") [service_id] client_result)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user