use super::*;
use utils::{RemainingNodes, RemovedNodes};
#[track_caller]
pub(super) fn assert_removed_nodes_props(
consumed: Key,
removed_nodes: RemovedNodes,
remaining_nodes: &RemainingNodes,
marked_consumed_nodes: &BTreeSet<Key>,
) {
if removed_nodes.is_empty() {
return;
}
assert_not_removed_node_type(consumed, remaining_nodes);
assert_only_cut_node_removed(consumed, &removed_nodes);
assert_another_root_not_removed(consumed, &removed_nodes);
assert_unspec_nodes_amount(&removed_nodes);
assert_removed_nodes_have_no_lock(&removed_nodes);
assert_removed_nodes_have_no_system_reserve(&removed_nodes);
assert_removed_nodes_are_consumed(consumed, marked_consumed_nodes, &removed_nodes);
assert_removed_nodes_form_path(consumed, remaining_nodes, removed_nodes);
}
#[track_caller]
fn assert_not_removed_node_type(consumed: Key, remaining_nodes: &RemainingNodes) {
if let Some(consumed) = remaining_nodes.get(&consumed) {
assert!(consumed.is_external() || consumed.is_reserved() || consumed.is_specified_local());
}
}
#[track_caller]
fn assert_unspec_nodes_amount(removed_nodes: &RemovedNodes) {
let removed_unspec_count = removed_nodes
.values()
.filter(|node| node.is_unspecified_local())
.count();
assert!(removed_unspec_count <= 1);
}
#[track_caller]
fn assert_removed_nodes_are_consumed(
consumed: Key,
marked_consumed_nodes: &BTreeSet<Key>,
removed_nodes: &RemovedNodes,
) {
for (id, node) in removed_nodes {
if *id != consumed {
assert!(node.is_consumed());
assert!(node.refs() == 1);
} else {
assert!(node.refs() == 0);
}
assert!(marked_consumed_nodes.contains(id))
}
}
#[track_caller]
fn assert_removed_nodes_have_no_lock(removed_nodes: &RemovedNodes) {
for node in removed_nodes.values() {
let lock = node.lock();
assert!(lock.is_zero());
}
}
#[track_caller]
fn assert_removed_nodes_have_no_system_reserve(removed_nodes: &RemovedNodes) {
for node in removed_nodes.values() {
let system_reserve = node.system_reserve();
if !node.is_system_reservable() {
assert!(system_reserve.is_none());
} else {
assert_eq!(system_reserve, Some(0));
}
}
}
#[track_caller]
fn assert_removed_nodes_form_path(
consumed: Key,
remaining_nodes: &RemainingNodes,
removed_nodes: RemovedNodes,
) {
let mut not_checked_parents_count = removed_nodes.len();
let mut node = removed_nodes
.get(&consumed)
.expect("consumed node is absent in removed nodes map");
while not_checked_parents_count > 1 {
if let Some(parent) = node.parent() {
assert!(!remaining_nodes.contains_key(&parent));
assert!(removed_nodes.contains_key(&parent));
not_checked_parents_count -= 1;
node = removed_nodes.get(&parent).expect("checked");
}
}
if let Some(parent) = node.parent() {
assert!(remaining_nodes.contains_key(&parent));
}
}
#[track_caller]
fn assert_only_cut_node_removed(consumed: Key, removed_nodes: &RemovedNodes) {
if let Some(node) = removed_nodes.get(&consumed) {
if node.is_cut() {
assert_eq!(removed_nodes.len(), 1);
}
}
}
#[track_caller]
pub(super) fn assert_root_children_removed(
root_node: impl Into<Key>,
remaining_nodes: &RemainingNodes,
) {
let root_node = root_node.into();
let is_child = |id: GasNodeId<_, _>| {
let origin_id = Gas::get_origin_key(id).unwrap();
origin_id == root_node
};
if Gas::get_node(root_node).is_none() {
assert_eq!(
remaining_nodes
.iter()
.filter(|(id, _node)| is_child(**id))
.count(),
0
);
};
}
#[track_caller]
fn assert_another_root_not_removed(consumed: Key, removed_nodes: &RemovedNodes) {
if let Some(node) = removed_nodes.get(&consumed) {
if node.is_external() || node.is_reserved() {
assert_eq!(
removed_nodes
.iter()
.filter(|(_, v)| v.is_external() || v.is_reserved())
.count(),
1 );
}
}
}
#[track_caller]
pub(super) fn assert_not_invariant_error(err: super::Error) {
use super::Error::*;
match err {
ParentIsLost
| ParentHasNoChildren
| UnexpectedConsumeOutput
| UnexpectedNodeType
| ValueIsNotCaught
| ValueIsBlocked
| ValueIsNotBlocked => panic!("Invariant error occurred {:?}", err),
_ => log::error!("Non invariant error occurred: {:?}", err),
}
}