mirror of
https://github.com/fluencelabs/aquavm
synced 2024-12-04 23:20:18 +00:00
Introduce mismatch (#62)
This commit is contained in:
parent
611bee0836
commit
709b5e0a52
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -57,7 +57,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aquamarine"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"fluence",
|
||||
"log",
|
||||
@ -1693,7 +1693,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "stepper-lib"
|
||||
version = "0.4.0"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"air-parser",
|
||||
"aqua-test-utils",
|
||||
|
@ -31,7 +31,15 @@ Instr: Box<Instruction<'input>> = {
|
||||
|
||||
"(" xor <l:Instr> <r:Instr> ")" => Box::new(Instruction::Xor(Xor(l, r))),
|
||||
|
||||
"(" match_ <l:Matchable> <r:Matchable> <i:Instr> ")" => Box::new(Instruction::Match(Match(l, r, i))),
|
||||
"(" match_ <l:Matchable> <r:Matchable> <i:Instr> ")" => {
|
||||
let match_ = Match { left_value: l, right_value: r, instruction: i};
|
||||
Box::new(Instruction::Match(match_))
|
||||
},
|
||||
|
||||
"(" mismatch <l:Matchable> <r:Matchable> <i:Instr> ")" => {
|
||||
let mismatch = MisMatch { left_value: l, right_value: r, instruction: i};
|
||||
Box::new(Instruction::MisMatch(mismatch))
|
||||
},
|
||||
|
||||
! => { errors.push(<>); Box::new(Instruction::Error) },
|
||||
}
|
||||
@ -112,5 +120,6 @@ extern {
|
||||
xor => Token::Xor,
|
||||
next => Token::Next,
|
||||
match_ => Token::Match,
|
||||
mismatch => Token::MisMatch,
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -28,6 +28,7 @@ pub enum Instruction<'i> {
|
||||
Par(Par<'i>),
|
||||
Xor(Xor<'i>),
|
||||
Match(Match<'i>),
|
||||
MisMatch(MisMatch<'i>),
|
||||
Fold(Fold<'i>),
|
||||
Next(Next<'i>),
|
||||
Error,
|
||||
@ -91,11 +92,18 @@ pub struct Par<'i>(pub Box<Instruction<'i>>, pub Box<Instruction<'i>>);
|
||||
pub struct Xor<'i>(pub Box<Instruction<'i>>, pub Box<Instruction<'i>>);
|
||||
|
||||
#[derive(Serialize, Debug, PartialEq, Eq)]
|
||||
pub struct Match<'i>(
|
||||
pub MatchableValue<'i>,
|
||||
pub MatchableValue<'i>,
|
||||
pub Box<Instruction<'i>>,
|
||||
);
|
||||
pub struct Match<'i> {
|
||||
pub left_value: MatchableValue<'i>,
|
||||
pub right_value: MatchableValue<'i>,
|
||||
pub instruction: Box<Instruction<'i>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug, PartialEq, Eq)]
|
||||
pub struct MisMatch<'i> {
|
||||
pub left_value: MatchableValue<'i>,
|
||||
pub right_value: MatchableValue<'i>,
|
||||
pub instruction: Box<Instruction<'i>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug, PartialEq, Eq)]
|
||||
pub struct Fold<'i> {
|
||||
|
@ -181,6 +181,7 @@ fn string_to_token(input: &str, start_pos: usize) -> Result<Token, LexerError> {
|
||||
XOR_INSTR => Ok(Token::Xor),
|
||||
NEXT_INSTR => Ok(Token::Next),
|
||||
MATCH_INSTR => Ok(Token::Match),
|
||||
MISMATCH_INSTR => Ok(Token::MisMatch),
|
||||
|
||||
INIT_PEER_ID => Ok(Token::InitPeerId),
|
||||
|
||||
@ -236,6 +237,7 @@ const FOLD_INSTR: &str = "fold";
|
||||
const XOR_INSTR: &str = "xor";
|
||||
const NEXT_INSTR: &str = "next";
|
||||
const MATCH_INSTR: &str = "match";
|
||||
const MISMATCH_INSTR: &str = "mismatch";
|
||||
|
||||
const INIT_PEER_ID: &str = "%init_peer_id%";
|
||||
|
||||
|
@ -103,6 +103,32 @@ fn air_instructions() {
|
||||
Ok((5, Token::CloseRoundBracket, 6))
|
||||
]
|
||||
);
|
||||
|
||||
let match_tokens = run_lexer("match");
|
||||
assert_eq!(match_tokens, vec![Ok((0, Token::Match, 5))]);
|
||||
|
||||
let match_tokens = run_lexer("(match)");
|
||||
assert_eq!(
|
||||
match_tokens,
|
||||
vec![
|
||||
Ok((0, Token::OpenRoundBracket, 1)),
|
||||
Ok((1, Token::Match, 6)),
|
||||
Ok((6, Token::CloseRoundBracket, 7))
|
||||
]
|
||||
);
|
||||
|
||||
let mismatch_tokens = run_lexer("mismatch");
|
||||
assert_eq!(mismatch_tokens, vec![Ok((0, Token::MisMatch, 8))]);
|
||||
|
||||
let mismatch_tokens = run_lexer("(mismatch)");
|
||||
assert_eq!(
|
||||
mismatch_tokens,
|
||||
vec![
|
||||
Ok((0, Token::OpenRoundBracket, 1)),
|
||||
Ok((1, Token::MisMatch, 9)),
|
||||
Ok((9, Token::CloseRoundBracket, 10))
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -36,4 +36,5 @@ pub enum Token<'input> {
|
||||
Xor,
|
||||
Next,
|
||||
Match,
|
||||
MisMatch,
|
||||
}
|
||||
|
@ -244,6 +244,34 @@ fn parse_fold() {
|
||||
assert_eq!(instruction, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_match() {
|
||||
use ast::MatchableValue::Variable;
|
||||
|
||||
let source_code = r#"
|
||||
(match v1 v2
|
||||
(null)
|
||||
)
|
||||
"#;
|
||||
let instruction = parse(&source_code.as_ref());
|
||||
let expected = match_(Variable("v1"), Variable("v2"), null());
|
||||
assert_eq!(instruction, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_mismatch() {
|
||||
use ast::MatchableValue::Variable;
|
||||
|
||||
let source_code = r#"
|
||||
(mismatch v1 v2
|
||||
(null)
|
||||
)
|
||||
"#;
|
||||
let instruction = parse(&source_code.as_ref());
|
||||
let expected = mismatch(Variable("v1"), Variable("v2"), null());
|
||||
assert_eq!(instruction, expected);
|
||||
}
|
||||
|
||||
fn source_fold_with(name: &str) -> String {
|
||||
f!(r#"(fold iterable i
|
||||
({name} (null) (null))
|
||||
@ -516,18 +544,23 @@ fn comments() {
|
||||
fn seq<'a>(l: Instruction<'a>, r: Instruction<'a>) -> Instruction<'a> {
|
||||
Instruction::Seq(ast::Seq(Box::new(l), Box::new(r)))
|
||||
}
|
||||
|
||||
fn par<'a>(l: Instruction<'a>, r: Instruction<'a>) -> Instruction<'a> {
|
||||
Instruction::Par(ast::Par(Box::new(l), Box::new(r)))
|
||||
}
|
||||
|
||||
fn xor<'a>(l: Instruction<'a>, r: Instruction<'a>) -> Instruction<'a> {
|
||||
Instruction::Xor(ast::Xor(Box::new(l), Box::new(r)))
|
||||
}
|
||||
|
||||
fn seqnn() -> Instruction<'static> {
|
||||
seq(null(), null())
|
||||
}
|
||||
|
||||
fn null() -> Instruction<'static> {
|
||||
Instruction::Null(ast::Null)
|
||||
}
|
||||
|
||||
fn fold<'a>(
|
||||
iterable: ast::IterableValue<'a>,
|
||||
iterator: &'a str,
|
||||
@ -539,6 +572,31 @@ fn fold<'a>(
|
||||
instruction: std::rc::Rc::new(instruction),
|
||||
})
|
||||
}
|
||||
|
||||
fn match_<'a>(
|
||||
left_value: ast::MatchableValue<'a>,
|
||||
right_value: ast::MatchableValue<'a>,
|
||||
instruction: Instruction<'a>,
|
||||
) -> Instruction<'a> {
|
||||
Instruction::Match(ast::Match {
|
||||
left_value,
|
||||
right_value,
|
||||
instruction: Box::new(instruction),
|
||||
})
|
||||
}
|
||||
|
||||
fn mismatch<'a>(
|
||||
left_value: ast::MatchableValue<'a>,
|
||||
right_value: ast::MatchableValue<'a>,
|
||||
instruction: Instruction<'a>,
|
||||
) -> Instruction<'a> {
|
||||
Instruction::MisMatch(ast::MisMatch {
|
||||
left_value,
|
||||
right_value,
|
||||
instruction: Box::new(instruction),
|
||||
})
|
||||
}
|
||||
|
||||
fn binary_instruction<'a, 'b>(
|
||||
name: &'a str,
|
||||
) -> impl Fn(Instruction<'b>, Instruction<'b>) -> Instruction<'b> {
|
||||
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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 crate::contexts::execution::ExecutionCtx;
|
||||
use crate::execution::air::ExecutionResult;
|
||||
use crate::execution::utils::resolve_to_jvaluable;
|
||||
use crate::JValue;
|
||||
|
||||
use air_parser::ast::MatchableValue;
|
||||
|
||||
pub(crate) fn are_matchable_eq<'ctx>(
|
||||
left: &MatchableValue<'_>,
|
||||
right: &MatchableValue<'_>,
|
||||
exec_ctx: &'ctx ExecutionCtx<'_>,
|
||||
) -> ExecutionResult<bool> {
|
||||
use MatchableValue::*;
|
||||
|
||||
match (left, right) {
|
||||
(Literal(name), matchable) => compare_matchable_and_literal(matchable, name, exec_ctx),
|
||||
(matchable, Literal(name)) => compare_matchable_and_literal(matchable, name, exec_ctx),
|
||||
(Variable(left_name), Variable(right_name)) => {
|
||||
let left_jvaluable = resolve_to_jvaluable(left_name, exec_ctx)?;
|
||||
let left_value = left_jvaluable.as_jvalue();
|
||||
|
||||
let right_jvaluable = resolve_to_jvaluable(right_name, exec_ctx)?;
|
||||
let right_value = right_jvaluable.as_jvalue();
|
||||
|
||||
Ok(left_value == right_value)
|
||||
}
|
||||
(JsonPath { variable: lv, path: lp }, JsonPath { variable: rv, path: rp }) => {
|
||||
let left_jvaluable = resolve_to_jvaluable(lv, exec_ctx)?;
|
||||
let left_value = left_jvaluable.apply_json_path(lp)?;
|
||||
|
||||
let right_jvaluable = resolve_to_jvaluable(rv, exec_ctx)?;
|
||||
let right_value = right_jvaluable.apply_json_path(rp)?;
|
||||
|
||||
Ok(left_value == right_value)
|
||||
}
|
||||
_ => Ok(false),
|
||||
}
|
||||
}
|
||||
|
||||
fn compare_matchable_and_literal<'ctx>(
|
||||
matchable: &MatchableValue<'_>,
|
||||
string_literal: &str,
|
||||
exec_ctx: &'ctx ExecutionCtx<'_>,
|
||||
) -> ExecutionResult<bool> {
|
||||
use std::borrow::Cow;
|
||||
use MatchableValue::*;
|
||||
|
||||
fn compare_jvalue_and_literal(jvalue: Cow<'_, JValue>, string_literal: &str) -> bool {
|
||||
use std::ops::Deref;
|
||||
|
||||
match jvalue.deref() {
|
||||
JValue::String(value) => value == string_literal,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
match matchable {
|
||||
Literal(name) => Ok(name == &string_literal),
|
||||
Variable(name) => {
|
||||
let jvaluable = resolve_to_jvaluable(name, exec_ctx)?;
|
||||
let jvalue = jvaluable.as_jvalue();
|
||||
Ok(compare_jvalue_and_literal(jvalue, string_literal))
|
||||
}
|
||||
JsonPath { variable, path } => {
|
||||
let jvaluable = resolve_to_jvaluable(variable, exec_ctx)?;
|
||||
let jvalues = jvaluable.apply_json_path(path)?;
|
||||
if jvalues.len() != 1 {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
Ok(compare_jvalue_and_literal(Cow::Borrowed(jvalues[0]), string_literal))
|
||||
}
|
||||
}
|
||||
}
|
19
stepper-lib/src/execution/air/compare_matchable/mod.rs
Normal file
19
stepper-lib/src/execution/air/compare_matchable/mod.rs
Normal 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.
|
||||
*/
|
||||
|
||||
mod compare_matchable;
|
||||
|
||||
pub(super) use compare_matchable::are_matchable_eq;
|
@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use super::compare_matchable::are_matchable_eq;
|
||||
use super::ExecutionCtx;
|
||||
use super::ExecutionError;
|
||||
use super::ExecutionResult;
|
||||
@ -21,92 +22,18 @@ use super::ExecutionTraceCtx;
|
||||
use crate::log_instruction;
|
||||
|
||||
use air_parser::ast::Match;
|
||||
use air_parser::ast::MatchableValue;
|
||||
|
||||
impl<'i> super::ExecutableInstruction<'i> for Match<'i> {
|
||||
fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, trace_ctx: &mut ExecutionTraceCtx) -> ExecutionResult<()> {
|
||||
log_instruction!(match_, exec_ctx, trace_ctx);
|
||||
|
||||
let left_value = &self.0;
|
||||
let right_value = &self.1;
|
||||
let is_equal_values = compare_matchable(left_value, right_value, exec_ctx)?;
|
||||
let are_values_equal = are_matchable_eq(&self.left_value, &self.right_value, exec_ctx)?;
|
||||
|
||||
if !is_equal_values {
|
||||
if !are_values_equal {
|
||||
return Err(ExecutionError::MatchWithoutXorError);
|
||||
}
|
||||
|
||||
self.2.execute(exec_ctx, trace_ctx)
|
||||
}
|
||||
}
|
||||
|
||||
use crate::execution::utils::resolve_to_jvaluable;
|
||||
use crate::JValue;
|
||||
|
||||
fn compare_matchable<'ctx>(
|
||||
left: &MatchableValue<'_>,
|
||||
right: &MatchableValue<'_>,
|
||||
exec_ctx: &'ctx ExecutionCtx<'_>,
|
||||
) -> ExecutionResult<bool> {
|
||||
use MatchableValue::*;
|
||||
|
||||
match (left, right) {
|
||||
(Literal(name), matchable) => compare_matchable_and_literal(matchable, name, exec_ctx),
|
||||
(matchable, Literal(name)) => compare_matchable_and_literal(matchable, name, exec_ctx),
|
||||
(Variable(left_name), Variable(right_name)) => {
|
||||
let left_jvaluable = resolve_to_jvaluable(left_name, exec_ctx)?;
|
||||
let left_value = left_jvaluable.as_jvalue();
|
||||
|
||||
let right_jvaluable = resolve_to_jvaluable(right_name, exec_ctx)?;
|
||||
let right_value = right_jvaluable.as_jvalue();
|
||||
|
||||
Ok(left_value == right_value)
|
||||
}
|
||||
(JsonPath { variable: lv, path: lp }, JsonPath { variable: rv, path: rp }) => {
|
||||
let left_jvaluable = resolve_to_jvaluable(lv, exec_ctx)?;
|
||||
let left_value = left_jvaluable.apply_json_path(lp)?;
|
||||
|
||||
let right_jvaluable = resolve_to_jvaluable(rv, exec_ctx)?;
|
||||
let right_value = right_jvaluable.apply_json_path(rp)?;
|
||||
|
||||
Ok(left_value == right_value)
|
||||
}
|
||||
_ => Ok(false),
|
||||
}
|
||||
}
|
||||
|
||||
fn compare_matchable_and_literal<'ctx>(
|
||||
matchable: &MatchableValue<'_>,
|
||||
string_literal: &str,
|
||||
exec_ctx: &'ctx ExecutionCtx<'_>,
|
||||
) -> ExecutionResult<bool> {
|
||||
use std::borrow::Cow;
|
||||
use MatchableValue::*;
|
||||
|
||||
fn compare_jvalue_and_literal(jvalue: Cow<'_, JValue>, string_literal: &str) -> bool {
|
||||
use std::ops::Deref;
|
||||
|
||||
match jvalue.deref() {
|
||||
JValue::String(value) => value == string_literal,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
match matchable {
|
||||
Literal(name) => Ok(name == &string_literal),
|
||||
Variable(name) => {
|
||||
let jvaluable = resolve_to_jvaluable(name, exec_ctx)?;
|
||||
let jvalue = jvaluable.as_jvalue();
|
||||
Ok(compare_jvalue_and_literal(jvalue, string_literal))
|
||||
}
|
||||
JsonPath { variable, path } => {
|
||||
let jvaluable = resolve_to_jvaluable(variable, exec_ctx)?;
|
||||
let jvalues = jvaluable.apply_json_path(path)?;
|
||||
if jvalues.len() != 1 {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
Ok(compare_jvalue_and_literal(Cow::Borrowed(jvalues[0]), string_literal))
|
||||
}
|
||||
self.instruction.execute(exec_ctx, trace_ctx)
|
||||
}
|
||||
}
|
||||
|
||||
|
193
stepper-lib/src/execution/air/mismatch.rs
Normal file
193
stepper-lib/src/execution/air/mismatch.rs
Normal file
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* 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::compare_matchable::are_matchable_eq;
|
||||
use super::ExecutionCtx;
|
||||
use super::ExecutionError;
|
||||
use super::ExecutionResult;
|
||||
use super::ExecutionTraceCtx;
|
||||
use crate::log_instruction;
|
||||
|
||||
use air_parser::ast::MisMatch;
|
||||
|
||||
impl<'i> super::ExecutableInstruction<'i> for MisMatch<'i> {
|
||||
fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, trace_ctx: &mut ExecutionTraceCtx) -> ExecutionResult<()> {
|
||||
log_instruction!(match_, exec_ctx, trace_ctx);
|
||||
|
||||
let are_values_equal = are_matchable_eq(&self.left_value, &self.right_value, exec_ctx)?;
|
||||
|
||||
if are_values_equal {
|
||||
return Err(ExecutionError::MatchWithoutXorError);
|
||||
}
|
||||
|
||||
self.instruction.execute(exec_ctx, trace_ctx)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::contexts::execution_trace::ExecutionTrace;
|
||||
use crate::JValue;
|
||||
|
||||
use aqua_test_utils::call_vm;
|
||||
use aqua_test_utils::create_aqua_vm;
|
||||
use aqua_test_utils::echo_string_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_aqua_vm(echo_string_call_service(), set_variable_peer_id);
|
||||
|
||||
let local_peer_id = "local_peer_id";
|
||||
let mut vm = create_aqua_vm(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_aqua_vm(echo_string_call_service(), set_variable_peer_id);
|
||||
|
||||
let local_peer_id = "local_peer_id";
|
||||
let mut vm = create_aqua_vm(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_aqua_vm(echo_string_call_service(), set_variable_peer_id);
|
||||
|
||||
let local_peer_id = "local_peer_id";
|
||||
let mut vm = create_aqua_vm(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_aqua_vm(echo_string_call_service(), set_variable_peer_id);
|
||||
|
||||
let local_peer_id = "local_peer_id";
|
||||
let mut vm = create_aqua_vm(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, 1015);
|
||||
|
||||
let res = call_vm!(vm, "asd", script, "", res.data);
|
||||
|
||||
assert_eq!(res.ret_code, 1015);
|
||||
}
|
||||
}
|
@ -15,8 +15,10 @@
|
||||
*/
|
||||
|
||||
mod call;
|
||||
mod compare_matchable;
|
||||
mod fold;
|
||||
mod match_;
|
||||
mod mismatch;
|
||||
mod null;
|
||||
mod par;
|
||||
mod seq;
|
||||
@ -46,6 +48,7 @@ impl<'i> ExecutableInstruction<'i> for Instruction<'i> {
|
||||
Instruction::Seq(seq) => seq.execute(exec_ctx, trace_ctx),
|
||||
Instruction::Xor(xor) => xor.execute(exec_ctx, trace_ctx),
|
||||
Instruction::Match(match_) => match_.execute(exec_ctx, trace_ctx),
|
||||
Instruction::MisMatch(mismatch) => mismatch.execute(exec_ctx, trace_ctx),
|
||||
Instruction::Error => unreachable!("should not execute if parsing succeeded. QED."),
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user