chore(execution-engine): this commit adds a set of trace-related negative tests for UncatchableError [fixes VM-263] (#532)

chore(execution-engine): this commit adds a set of trace-related
negative tests for UncatchableError [fixes VM-263]
This commit is contained in:
raftedproc 2023-03-21 00:31:36 +03:00 committed by GitHub
parent a2ad3b15db
commit 631abd4ec4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 455 additions and 26 deletions

View File

@ -17,4 +17,5 @@
mod execution_step;
mod farewell_step;
mod preparation_step;
mod uncatchable_trace_related;
mod uncatchable_trace_unrelated;

View File

@ -0,0 +1,422 @@
/*
* Copyright 2023 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::UncatchableError;
use air_interpreter_cid::value_to_json_cid;
use air_interpreter_cid::CID;
use air_interpreter_data::FoldSubTraceLore;
use air_interpreter_data::ParResult;
use air_interpreter_data::SubTraceDesc;
use air_test_utils::prelude::*;
use air_trace_handler::merger::ApResultError;
use air_trace_handler::merger::CallResultError;
use air_trace_handler::merger::CanonResultError;
use air_trace_handler::merger::FoldResultError;
use air_trace_handler::merger::MergeCtxType::Current;
use air_trace_handler::DataType::Previous;
use air_trace_handler::KeeperError::*;
use air_trace_handler::StateFSMError::*;
use air_trace_handler::TraceHandlerError::KeeperError;
use air_trace_handler::TraceHandlerError::MergeError;
use air_trace_handler::TraceHandlerError::StateFSMError;
#[test]
fn par_len_underflow() {
let vm_peer_id_1 = "vm_peer_id_1";
let mut peer_vm_1 = create_avm(unit_call_service(), vm_peer_id_1);
let script = f!(r#"
(par
(ap 42 some)
(call "other" ("" "") [some] other)
)
"#);
let trace = vec![
executed_state::par(42, 1),
executed_state::request_sent_by(vm_peer_id_1),
];
let data = raw_data_from_trace(trace, <_>::default());
let result = call_vm!(peer_vm_1, <_>::default(), script, "", data);
let expected_error = UncatchableError::TraceError {
trace_error: StateFSMError(ParLenUnderflow(ParResult::new(42, 1), 1, Current)),
instruction: "par".to_string(),
};
assert!(check_error(&result, expected_error));
}
#[test]
fn set_subtrace_len_and_pos_failed() {
let vm_peer_id_1 = "vm_peer_id_1";
let arg = json!([42, 43]);
let mut peer_vm_1 = create_avm(set_variable_call_service(arg), vm_peer_id_1);
let script = f!(r#"
(par
(call "vm_peer_id_1" ("" "") [] $s)
(fold $s i
(call "vm_peer_id_2" ("" "") [] a)
(next i)
)
)
"#);
let mut tracker = CidTracker::<JValue>::new();
let trace = vec![
executed_state::par(1, 2),
stream_tracked(json!([42, 43]), 0, &mut tracker),
executed_state::fold(vec![executed_state::subtrace_lore(
1,
subtrace_desc(5, 1),
subtrace_desc(4, 0),
)]),
request_sent_by("vm_peer_id_1"),
];
let wrong_data = raw_data_from_trace(trace, tracker);
let result = call_vm!(peer_vm_1, <_>::default(), script, wrong_data, "");
let expected_error = UncatchableError::TraceError {
trace_error: KeeperError(SetSubtraceLenAndPosFailed {
requested_pos: 5.into(),
requested_subtrace_len: 1,
trace_len: 4,
}),
instruction: "fold $s i".to_string(),
};
assert!(check_error(&result, expected_error));
}
#[test]
fn no_element_at_position() {
let vm_peer_id_1 = "vm_peer_id_1";
let mut peer_vm_1 = create_avm(unit_call_service(), vm_peer_id_1);
let script = f!(r#"
(par
(call "vm_peer_id_1" ("" "") [] $s)
(fold $s i
(call "vm_peer_id_2" ("" "") [] a)
(next i)
)
)
"#);
let mut tracker = CidTracker::<JValue>::new();
let trace = vec![
executed_state::par(1, 2),
stream_tracked(json!([42, 43]), 0, &mut tracker),
executed_state::fold(vec![executed_state::subtrace_lore(
42,
subtrace_desc(3, 1),
subtrace_desc(4, 0),
)]),
request_sent_by("vm_peer_id_1"),
];
let wrong_data = raw_data_from_trace(trace, tracker);
let result = call_vm!(peer_vm_1, <_>::default(), script, wrong_data, "");
let expected_error = UncatchableError::TraceError {
trace_error: air_trace_handler::TraceHandlerError::KeeperError(NoElementAtPosition {
position: 42.into(),
trace_len: 4,
}),
instruction: "fold $s i".to_string(),
};
assert!(check_error(&result, expected_error));
}
#[test]
fn no_stream_state() {
let vm_peer_id_1 = "vm_peer_id_1";
let arg = json!([42, 43]);
let mut peer_vm_1 = create_avm(set_variable_call_service(arg), vm_peer_id_1);
let script = f!(r#"
(par
(call "vm_peer_id_1" ("" "") [] $s)
(fold $s i
(call "vm_peer_id_2" ("" "") [] a)
(next i)
)
)
"#);
let mut tracker = CidTracker::<JValue>::new();
let wrong_state = request_sent_by("vm_peer_id_1");
let trace = vec![
executed_state::par(1, 2),
stream_tracked(json!([42, 43]), 0, &mut tracker),
executed_state::fold(vec![executed_state::subtrace_lore(
3,
subtrace_desc(3, 1), // try to change the number of elems to 3
subtrace_desc(4, 0),
)]),
wrong_state.clone(),
];
let wrong_data = raw_data_from_trace(trace, tracker);
let result = call_vm!(peer_vm_1, <_>::default(), script, wrong_data, "");
let expected_error = UncatchableError::TraceError {
trace_error: air_trace_handler::TraceHandlerError::KeeperError(NoStreamState { state: wrong_state }),
instruction: "fold $s i".to_string(),
};
assert!(check_error(&result, expected_error));
}
#[test]
fn incompatible_executed_states() {
let vm_peer_id = "vm_peer_id";
let mut peer_vm_1 = create_avm(echo_call_service(), vm_peer_id);
let script = f!(r#"
(seq
(call "{vm_peer_id}" ("" "") [] scalar)
(ap scalar $stream)
)
"#);
let mut cid_tracker = CidTracker::new();
let prev_trace = vec![
executed_state::scalar_tracked("", &mut cid_tracker),
executed_state::ap(1),
];
let current_trace = vec![executed_state::scalar_string(""), executed_state::scalar_string("")];
let prev_data = raw_data_from_trace(prev_trace, cid_tracker.clone().into());
let current_data = raw_data_from_trace(current_trace, cid_tracker.into());
let result = call_vm!(peer_vm_1, <_>::default(), &script, prev_data, current_data);
let cid = value_to_json_cid(&json!("")).unwrap().into();
let expected_error = UncatchableError::TraceError {
trace_error: MergeError(air_trace_handler::merger::MergeError::IncompatibleExecutedStates(
ExecutedState::Ap(ApResult::new(1)),
ExecutedState::Call(CallResult::Executed(ValueRef::Scalar(cid))),
)),
instruction: "ap scalar $stream".to_string(),
};
assert!(check_error(&result, expected_error));
}
#[test]
fn different_executed_state_expected() {
let vm_peer_id_1 = "vm_peer_id_1";
let arg = json!([42, 43]);
let mut peer_vm_1 = create_avm(set_variable_call_service(arg), vm_peer_id_1);
let script = f!(r#"
(seq
(ap 42 some)
(call "vm_peer_id_2" ("" "") [] $s)
)
"#);
let wrong_state = executed_state::ap(42);
let prev_trace = vec![wrong_state.clone()];
let prev_data = raw_data_from_trace(prev_trace, <_>::default());
let result = call_vm!(peer_vm_1, <_>::default(), &script, prev_data, "");
let expected_error = UncatchableError::TraceError {
trace_error: MergeError(air_trace_handler::merger::MergeError::DifferentExecutedStateExpected(
wrong_state,
Previous,
"call",
)),
instruction: String::from(r#"call "vm_peer_id_2" ("" "") [] $s"#),
};
assert!(check_error(&result, expected_error));
}
#[test]
fn invalid_dst_generations() {
let vm_peer_id_1 = "vm_peer_id_1";
let mut peer_vm_1 = create_avm(unit_call_service(), vm_peer_id_1);
let script = f!(r#"
(ap "a" $s)
"#);
let data = json!(
{
"version": "0.6.3",
"interpreter_version": "1.1.1",
"trace": [
{"ap":
{"gens": [42,42]}
}
],
"streams": {},
"r_streams": {},
"lcid": 0,
"cid_info": {
"value_store": {},
"tetraplet_store": {},
"canon_store": {}
}
});
let data: Vec<u8> = serde_json::to_vec(&data).unwrap();
// let result = peer_vm_1.call(script, "", data, <_>::default()).unwrap();
let result = call_vm!(peer_vm_1, <_>::default(), &script, "", data);
let expected_error = UncatchableError::TraceError {
trace_error: MergeError(air_trace_handler::MergeError::IncorrectApResult(
ApResultError::InvalidDstGenerations(ApResult {
res_generations: vec![42, 42],
}),
)),
instruction: String::from(r#"ap "a" $s"#),
};
assert!(check_error(&result, expected_error));
}
#[test]
fn incorrect_call_result() {
let vm_peer_id_1 = "vm_peer_id_1";
let mut peer_vm_1 = create_avm(unit_call_service(), vm_peer_id_1);
let script = f!(r#"
(call "vm_peer_id_1" ("" "") [] v)
"#);
let prev_call_result = service_failed(42, "some");
let prev_trace = vec![prev_call_result.clone()];
let prev_data = raw_data_from_trace(prev_trace, <_>::default());
let curr_call_result = scalar_string("some");
let curr_trace = vec![curr_call_result.clone()];
let curr_data = raw_data_from_trace(curr_trace, <_>::default());
let result = call_vm!(peer_vm_1, <_>::default(), &script, prev_data, curr_data);
let curr_call_value_ref = ValueRef::Scalar(value_to_json_cid(&json!("some")).unwrap().into());
let expected_error = UncatchableError::TraceError {
trace_error: MergeError(air_trace_handler::MergeError::IncorrectCallResult(
CallResultError::IncompatibleCallResults {
prev_call: air_interpreter_data::CallResult::CallServiceFailed(42, String::from(r#""some""#).into()),
current_call: air_interpreter_data::CallResult::Executed(curr_call_value_ref),
},
)),
instruction: String::from(r#"call "vm_peer_id_1" ("" "") [] v"#),
};
assert!(check_error(&result, expected_error));
}
#[test]
fn canon_result_error() {
let vm_peer_id_1 = "vm_peer_id_1";
let arg = json!([42, 43]);
let mut peer_vm_1 = create_avm(set_variable_call_service(arg.clone()), vm_peer_id_1);
let script = f!(r#"
(canon "vm_peer_id_1" $stream #canon)
"#);
let prev_tetraplet = json!({
"tetraplet": {"function_name": "s", "json_path": "", "peer_pk": "vm_peer_id_1", "service_id": ""},
"values": [
{
"result": 42,
"tetraplet": {"function_name": "s", "json_path": "", "peer_pk": "vm_peer_id_1", "service_id": ""},
"trace_pos": 0,
},
]
});
let prev_trace = vec![executed_state::canon(prev_tetraplet)];
let prev_data = raw_data_from_trace(prev_trace, <_>::default());
let curr_tetraplet = json!({
"tetraplet": {"function_name": "s", "json_path": "", "peer_pk": "vm_peer_id_1", "service_id": ""},
"values": [
{
"result": 43,
"tetraplet": {"function_name": "s", "json_path": "", "peer_pk": "vm_peer_id_1", "service_id": ""},
"trace_pos": 0,
},
]
});
let curr_trace = vec![executed_state::canon(curr_tetraplet)];
let curr_data = raw_data_from_trace(curr_trace, <_>::default());
let result = call_vm!(peer_vm_1, <_>::default(), &script, prev_data, curr_data);
let expected_error = UncatchableError::TraceError {
trace_error: MergeError(air_trace_handler::MergeError::IncorrectCanonResult(
CanonResultError::IncompatibleState {
prev_canon_result: air_interpreter_data::CanonResult {
tetraplet: CID::new("bagaaierasjgckcjojtq3m3aylofqmzqitnostogfwnj2fzyaqsmxnlquf2la").into(),
values: vec![CID::new("bagaaieraxlk56ks2zevx5umgur2xxhf2cuopflnpopps3m6sgldmzquxumvq").into()],
},
current_canon_result: air_interpreter_data::CanonResult {
tetraplet: CID::new("bagaaierasjgckcjojtq3m3aylofqmzqitnostogfwnj2fzyaqsmxnlquf2la").into(),
values: vec![CID::new("bagaaierawwlvodborlxavs7j42eea23dmitophllfxg4kvozwe5ru4ywitea").into()],
},
},
)),
instruction: String::from(r#"canon "vm_peer_id_1" $stream #canon"#),
};
assert!(check_error(&result, expected_error));
}
#[test]
fn several_records_with_same_pos() {
let vm_peer_id_1 = "vm_peer_id_1";
let mut peer_vm_1 = create_avm(unit_call_service(), vm_peer_id_1);
let script = f!(r#"
(par
(call "vm_peer_id_1" ("" "") [] $s)
(fold $s i
(call "vm_peer_id_2" ("" "") [] a)
(next i)
)
)
"#);
let mut tracker = CidTracker::<JValue>::new();
let value_pos = 1;
let trace = vec![
executed_state::par(1, 2),
stream_tracked(json!([42, 43]), 0, &mut tracker),
fold(vec![
subtrace_lore(value_pos, subtrace_desc(3, 1), subtrace_desc(4, 0)),
subtrace_lore(value_pos, subtrace_desc(3, 1), subtrace_desc(4, 0)),
]),
request_sent_by("vm_peer_id_1"),
];
let wrong_data = raw_data_from_trace(trace, tracker);
let result = call_vm!(peer_vm_1, <_>::default(), &script, wrong_data, "");
// let result = peer_vm_1.call(script, wrong_data, "", <_>::default()).unwrap();
let fold_lore = FoldSubTraceLore {
value_pos: value_pos.into(),
subtraces_desc: vec![
SubTraceDesc {
begin_pos: 3.into(),
subtrace_len: 1,
},
SubTraceDesc {
begin_pos: 4.into(),
subtrace_len: 0,
},
],
};
let fold_result = FoldResult {
lore: vec![fold_lore.clone(), fold_lore],
};
let expected_error = UncatchableError::TraceError {
trace_error: MergeError(air_trace_handler::merger::MergeError::IncorrectFoldResult(
FoldResultError::SeveralRecordsWithSamePos(fold_result, value_pos.into()),
)),
instruction: String::from(String::from("fold $s i")),
};
assert!(check_error(&result, expected_error));
}
#[test]
fn values_not_equal() {
let vm_peer_id_1 = "vm_peer_id_1";
let arg = json!([42, 43]);
let mut peer_vm_1 = create_avm(set_variable_call_service(arg), vm_peer_id_1);
let script = f!(r#"
(call "vm_peer_id_1" ("" "") [] $s)
"#);
let prev_value = json!(42);
let prev_trace = vec![scalar(prev_value.clone())];
let prev_data = raw_data_from_trace(prev_trace, <_>::default());
let curr_value = json!(43);
let curr_trace = vec![scalar(curr_value.clone())];
let curr_data = raw_data_from_trace(curr_trace, <_>::default());
let result = call_vm!(peer_vm_1, <_>::default(), &script, prev_data, curr_data);
let prev_value = ValueRef::Scalar(value_to_json_cid(&prev_value).unwrap().into());
let current_value = ValueRef::Scalar(value_to_json_cid(&curr_value).unwrap().into());
let expected_error = UncatchableError::TraceError {
trace_error: MergeError(air_trace_handler::merger::MergeError::IncorrectCallResult(
CallResultError::ValuesNotEqual {
prev_value,
current_value,
},
)),
instruction: String::from(f!(r#"call "{vm_peer_id_1}" ("" "") [] $s"#)),
};
assert!(check_error(&result, expected_error));
}

View File

@ -26,16 +26,16 @@ fn fold_state_not_found() {
let mut peer_vm_1 = create_avm(set_variable_call_service(arg), vm_peer_id_1);
let script = f!(r#"
(seq
(seq
(call "vm_peer_id_1" ("" "") [] some)
(fold some i
(next i)
)
)
(next i)
)
"#);
(seq
(seq
(call "vm_peer_id_1" ("" "") [] some)
(fold some i
(next i)
)
)
(next i)
)
"#);
let result = peer_vm_1.call(script, "", "", <_>::default()).unwrap();
let expected_error = FoldStateNotFound(String::from("i"));
@ -49,13 +49,13 @@ fn iterable_shadowing() {
let mut peer_vm_1 = create_avm(set_variable_call_service(arg), vm_peer_id_1);
let script = f!(r#"
(seq
(call "vm_peer_id_1" ("" "") [] some)
(fold some i
(call "vm_peer_id_1" ("" "") [] i)
)
)
"#);
(seq
(call "vm_peer_id_1" ("" "") [] some)
(fold some i
(call "vm_peer_id_1" ("" "") [] i)
)
)
"#);
let result = peer_vm_1.call(script, "", "", <_>::default()).unwrap();
let expected_error = IterableShadowing(String::from("i"));
@ -69,8 +69,8 @@ fn call_result_not_correspond_to_instr() {
let mut peer_vm_1 = create_avm(set_variable_call_service(arg.clone()), vm_peer_id_1);
let script = f!(r#"
(call "vm_peer_id_1" ("" "") [] $some)
"#);
(call "vm_peer_id_1" ("" "") [] $some)
"#);
let scalar_value = 42;
let wrong_trace = vec![scalar_number(scalar_value)];
@ -88,11 +88,11 @@ fn shadowing_is_not_allowed() {
let mut peer_vm_1 = create_avm(unit_call_service(), vm_peer_id_1);
let var_name = String::from("some");
let script = f!(r#"
(seq
(ap 42 {var_name})
(ap 42 {var_name})
)
"#);
(seq
(ap 42 {var_name})
(ap 42 {var_name})
)
"#);
let result = peer_vm_1.call(script, "", "", <_>::default()).unwrap();
let expected_error = ShadowingIsNotAllowed(var_name);
@ -106,8 +106,8 @@ fn value_for_cid_not_found() {
let mut peer_vm_1 = create_avm(set_variable_call_service(arg), vm_peer_id_1);
let script = f!(r#"
(call "vm_peer_id_1" ("" "") [] some)
"#);
(call "vm_peer_id_1" ("" "") [] some)
"#);
let wrong_trace = vec![scalar_number(42)];
let data = raw_data_from_trace(wrong_trace, <_>::default());

View File

@ -32,9 +32,13 @@ mod handler;
pub mod merger;
mod state_automata;
pub use data_keeper::KeeperError;
pub use errors::GenerationCompatificationError;
pub use errors::TraceHandlerError;
pub use handler::TraceHandler;
pub use merger::DataType;
pub use merger::MergeError;
pub use state_automata::StateFSMError;
pub use state_automata::SubgraphType;
pub type TraceHandlerResult<T> = std::result::Result<T, TraceHandlerError>;

View File

@ -33,6 +33,8 @@ pub use position_mapping::PreparationScheme;
pub use errors::ApResultError;
pub use errors::CallResultError;
pub use errors::CanonResultError;
pub use errors::DataType;
pub use errors::FoldResultError;
pub use errors::MergeError;