/*
* AquaVM Workflow Engine
*
* Copyright (C) 2024 Fluence DAO
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation version 3 of the
* License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
use air::no_error_object;
use air::ExecutionCidState;
use air_test_framework::AirScriptExecutor;
use air_test_utils::prelude::*;
#[tokio::test]
async fn fail_with_rebubble_error() {
let peer_id = "peer_id";
let script = r#"
(seq
(xor
(xor
(match 1 2 (null) )
(fail :error:)
)
(call "peer_id" ("m" "f1") [:error:] scalar1) ; dbg_behaviour = echo
)
(call "peer_id" ("m" "f2") [:error:] scalar2) ; dbg_behaviour = echo
)
"#
.to_string();
let executor = AirScriptExecutor::from_annotated(TestRunParameters::from_init_peer_id(peer_id), &script)
.await
.expect("invalid test AIR script");
let result = executor.execute_all(peer_id).await.unwrap();
let actual_trace = trace_from_result(&result.last().unwrap());
let mut cid_tracker: ExecutionCidState = ExecutionCidState::new();
let expected_error_json = {
json!({
"error_code": 10001,
"instruction": "match 1 2",
"message": "compared values do not match"
})
};
let expected_trace: Vec = vec![
scalar_tracked!(
expected_error_json.clone(),
cid_tracker,
peer_name = peer_id,
service = "m..0",
function = "f1",
args = [expected_error_json]
),
scalar_tracked!(
no_error_object(),
cid_tracker,
peer_name = peer_id,
service = "m..1",
function = "f2",
args = [no_error_object()]
),
];
assert_eq!(actual_trace, expected_trace,);
}
#[tokio::test]
async fn rebubble_error_from_xor_right_branch() {
let peer_id = "peer_id";
let script = r#"
(seq
(xor
(xor
(xor
(match 1 2 (null) )
(fail :error:)
)
(seq
(call "peer_id" ("m" "f1") [:error:] scalar1) ; behaviour = echo
(match 3 2 (null) )
)
)
(call "peer_id" ("m" "f2") [:error:] scalar2) ; behaviour = echo
)
(call "peer_id" ("m" "f3") [:error:] scalar3) ; behaviour = echo
)
"#
.to_string();
let executor = AirScriptExecutor::from_annotated(TestRunParameters::from_init_peer_id(peer_id), &script)
.await
.expect("invalid test AIR script");
let result = executor.execute_all(peer_id).await.unwrap();
let actual_trace = trace_from_result(&result.last().unwrap());
let mut cid_tracker: ExecutionCidState = ExecutionCidState::new();
let inner_expected_error_json = {
json!({
"error_code": 10001,
"instruction": "match 1 2",
"message": "compared values do not match"
})
};
let outer_expected_error_json = {
json!({
"error_code": 10001,
"instruction": "match 3 2",
"message": "compared values do not match"
})
};
let expected_trace: Vec = vec![
scalar_tracked!(
inner_expected_error_json.clone(),
cid_tracker,
peer_name = peer_id,
service = "m..0",
function = "f1",
args = [inner_expected_error_json]
),
scalar_tracked!(
outer_expected_error_json.clone(),
cid_tracker,
peer_name = peer_id,
service = "m..1",
function = "f2",
args = [outer_expected_error_json]
),
scalar_tracked!(
no_error_object(),
cid_tracker,
peer_name = peer_id,
service = "m..2",
function = "f3",
args = [no_error_object()]
),
];
print_trace(&result.last().unwrap(), "");
assert_eq!(actual_trace, expected_trace);
}