Skip to content

Commit

Permalink
clean up tests, add more cases, and clean up prints
Browse files Browse the repository at this point in the history
  • Loading branch information
AlpinYukseloglu committed Apr 2, 2024
1 parent 3f10207 commit 2867ab5
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 83 deletions.
21 changes: 1 addition & 20 deletions contracts/sumtree-orderbook/src/sumtree/test/test_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,12 @@ struct TestNodeInsertCase {
}

// Asserts all values of internal nodes are as expected
fn assert_internal_values(
pub fn assert_internal_values(
test_name: &'static str,
deps: Deps,
internals: Vec<&TreeNode>,
should_be_balanced: bool,
) {
println!("Length of internals: {}", internals.len());
for internal_node in internals {
let left_node = internal_node.get_left(deps.storage).unwrap();
let right_node = internal_node.get_right(deps.storage).unwrap();
Expand Down Expand Up @@ -2170,29 +2169,11 @@ fn test_node_insert_large_quantity() {
// Ensure all internal nodes are correctly summed and contain correct ranges
let internals: Vec<&TreeNode> = result.iter().filter(|x| x.is_internal()).collect();
let leaves: Vec<&TreeNode> = result.iter().filter(|x| !x.is_internal()).collect();
println!("{}", leaves.len());
assert_internal_values("Large amount of nodes", deps.as_ref(), internals, true);

println!("Number of nodes inserted: {}", nodes_count);
println!("Final expected prefix sum: {}", expected_prefix_sum);

// Ensure prefix sum functions correctly
let root_node = get_root_node(deps.as_mut().storage, book_id, tick_id).unwrap();
println!("Root Node Min Range: {}", root_node.get_min_range());
println!("Root Node Max Range: {}", root_node.get_max_range());
println!("Root Node Value: {}", root_node.get_value());

if let Some(left_child) = root_node.get_left(deps.as_ref().storage).unwrap() {
println!("Left Child Min Range: {}", left_child.get_min_range());
println!("Left Child Max Range: {}", left_child.get_max_range());
println!("Left Child Value: {}", left_child.get_value());
}

if let Some(right_child) = root_node.get_right(deps.as_ref().storage).unwrap() {
println!("Right Child Min Range: {}", right_child.get_min_range());
println!("Right Child Max Range: {}", right_child.get_max_range());
println!("Right Child Value: {}", right_child.get_value());
}
let prefix_sum = get_prefix_sum(deps.as_mut().storage, root_node, target_etas).unwrap();
assert_eq!(expected_prefix_sum, prefix_sum);
}
Expand Down
162 changes: 135 additions & 27 deletions contracts/sumtree-orderbook/src/sumtree/test/test_tree.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
use crate::sumtree::node::{generate_node_id, NodeType, TreeNode, NODES};
use crate::sumtree::test::test_node::print_tree;
use crate::sumtree::tree::get_prefix_sum;
use crate::sumtree::test::test_node::assert_internal_values;
use crate::sumtree::tree::{get_prefix_sum, get_root_node, TREE};
use cosmwasm_std::{testing::mock_dependencies, Decimal256};

struct TestPrefixSumCase {
name: &'static str,
nodes: Vec<NodeType>,
target_etas: Decimal256,
print: bool,
expected_sum: Decimal256,
}

Expand All @@ -20,7 +19,13 @@ fn test_get_prefix_sum_valid() {
name: "Single node, target ETAS equal to node ETAS",
nodes: vec![NodeType::leaf_uint256(10u128, 5u128)],
target_etas: Decimal256::from_ratio(10u128, 1u128),
print: true,

// We expect the full value of the node because the prefix
// sum is intended to return "all nodes that overlap with
// the target ETAS".
//
// Since node ranges are inclusive of the
// lower bound, the node here should be included in the sum.
expected_sum: Decimal256::from_ratio(5u128, 1u128),
},
TestPrefixSumCase {
Expand All @@ -31,7 +36,7 @@ fn test_get_prefix_sum_valid() {
NodeType::leaf_uint256(35u128, 30u128),
],
target_etas: Decimal256::from_ratio(20u128, 1u128),
print: true,

expected_sum: Decimal256::from_ratio(30u128, 1u128),
},
TestPrefixSumCase {
Expand All @@ -42,7 +47,7 @@ fn test_get_prefix_sum_valid() {
NodeType::leaf_uint256(40u128, 30u128),
],
target_etas: Decimal256::from_ratio(5u128, 1u128),
print: true,

expected_sum: Decimal256::zero(),
},
TestPrefixSumCase {
Expand All @@ -53,27 +58,117 @@ fn test_get_prefix_sum_valid() {
NodeType::leaf_uint256(40u128, 30u128),
],
target_etas: Decimal256::from_ratio(45u128, 1u128),
print: true,

expected_sum: Decimal256::from_ratio(60u128, 1u128), // Sum of all nodes
},
TestPrefixSumCase {
name: "Nodes inserted in reverse order",
nodes: vec![
NodeType::leaf_uint256(30u128, 10u128),
NodeType::leaf_uint256(20u128, 5u128),
NodeType::leaf_uint256(10u128, 5u128),
],
target_etas: Decimal256::from_ratio(25u128, 1u128),

expected_sum: Decimal256::from_ratio(10u128, 1u128),
},
TestPrefixSumCase {
name: "Nodes inserted in shuffled order",
nodes: vec![
NodeType::leaf_uint256(30u128, 10u128),
NodeType::leaf_uint256(10u128, 5u128),
NodeType::leaf_uint256(20u128, 5u128),
],
target_etas: Decimal256::from_ratio(25u128, 1u128),

expected_sum: Decimal256::from_ratio(10u128, 1u128),
},
TestPrefixSumCase {
name: "Nodes inserted in shuffled order, target ETAS at node lower bound",
nodes: vec![
NodeType::leaf_uint256(30u128, 11u128),
NodeType::leaf_uint256(10u128, 7u128),
NodeType::leaf_uint256(20u128, 5u128),
],
target_etas: Decimal256::from_ratio(20u128, 1u128),

// We expect the sum of the 2nd and 3rd nodes, so 7 + 5
expected_sum: Decimal256::from_ratio(12u128, 1u128),
},
TestPrefixSumCase {
name: "Nodes with large gaps between ranges",
nodes: vec![
NodeType::leaf_uint256(10u128, 10u128),
NodeType::leaf_uint256(50u128, 20u128),
NodeType::leaf_uint256(100u128, 30u128),
],
target_etas: Decimal256::from_ratio(75u128, 1u128),

expected_sum: Decimal256::from_ratio(30u128, 1u128),
},
TestPrefixSumCase {
name: "Nodes with adjacent ranges",
nodes: vec![
NodeType::leaf_uint256(10u128, 10u128),
NodeType::leaf_uint256(20u128, 10u128),
NodeType::leaf_uint256(30u128, 10u128),
],
target_etas: Decimal256::from_ratio(25u128, 1u128),

expected_sum: Decimal256::from_ratio(20u128, 1u128),
},
TestPrefixSumCase {
name: "Single node, target ETAS below node range",
nodes: vec![NodeType::leaf_uint256(50u128, 20u128)],
target_etas: Decimal256::from_ratio(25u128, 1u128),

expected_sum: Decimal256::zero(),
},
TestPrefixSumCase {
name: "Single node, target ETAS above node range",
nodes: vec![NodeType::leaf_uint256(10u128, 10u128)],
target_etas: Decimal256::from_ratio(30u128, 1u128),

expected_sum: Decimal256::from_ratio(10u128, 1u128),
},
TestPrefixSumCase {
name: "Complex case with many nodes (shuffled, adjacent, spaced out)",
nodes: vec![
NodeType::leaf_uint256(10u128, 5u128), // 10-15
NodeType::leaf_uint256(121u128, 19u128), // 121-140
NodeType::leaf_uint256(15u128, 4u128), // 15-19 adjacent to the first
NodeType::leaf_uint256(50u128, 10u128), // 50-60
NodeType::leaf_uint256(61u128, 9u128), // 61-70
NodeType::leaf_uint256(100u128, 20u128), // 100-120
NodeType::leaf_uint256(200u128, 50u128), // 200-250
NodeType::leaf_uint256(260u128, 40u128), // 260-300
NodeType::leaf_uint256(301u128, 29u128), // 301-330
NodeType::leaf_uint256(400u128, 100u128), // 400-500
NodeType::leaf_uint256(600u128, 150u128), // 600-750
],
// Target includes everything except the last two nodes
target_etas: Decimal256::from_ratio(305u128, 1u128),

// Sum of all nodes except the last two:
// 5 + 19 + 4 + 10 + 9 + 20 + 50 + 40 + 29 = 186
expected_sum: Decimal256::from_ratio(186u128, 1u128),
},
];

for test in test_cases {
println!("\n--------------------------------");
println!("Running test: {}", test.name);
println!("\n--------------------------------");
let mut deps = mock_dependencies();

let root_id = generate_node_id(deps.as_mut().storage, book_id, tick_id).unwrap();
let mut root_id = generate_node_id(deps.as_mut().storage, book_id, tick_id).unwrap();
let mut tree = TreeNode::new(book_id, tick_id, root_id, NodeType::default());
TREE.save(deps.as_mut().storage, &(book_id, tick_id), &root_id)
.unwrap();
NODES
.save(deps.as_mut().storage, &(book_id, tick_id, tree.key), &tree)
.unwrap();

// Insert nodes into tree
for (idx, node) in test.nodes.iter().enumerate() {
for node in test.nodes.iter() {
let new_node_id = generate_node_id(deps.as_mut().storage, book_id, tick_id).unwrap();
println!("New node ID: {}", new_node_id);
let mut tree_node = TreeNode::new(book_id, tick_id, new_node_id, node.clone());
NODES
.save(
Expand All @@ -83,30 +178,43 @@ fn test_get_prefix_sum_valid() {
)
.unwrap();

// Why does it seem like insertions are overwriting each other?
println!("Inserting node");
// Process insertion
tree.insert(deps.as_mut().storage, &mut tree_node).unwrap();

if idx >= 2 {
print_tree("Inserted node:", test.name, &tree, &deps.as_ref());
}
// Refetch tree. We do this manually to avoid using higher level orderbook
// functions in low level sumtree tests.
root_id = TREE
.load(deps.as_mut().storage, &(book_id, tick_id))
.unwrap();
tree = NODES
.load(deps.as_mut().storage, &(book_id, tick_id, root_id))
.unwrap();
}

let root_node = NODES
.load(deps.as_mut().storage, &(book_id, tick_id, root_id))
.unwrap();

if test.print {
print_tree("Final tree:", test.name, &root_node, &deps.as_ref());
}
// Assert that the resulting tree maintains basic sumtree invariants
let tree_nodes = tree.traverse(deps.as_ref().storage).unwrap();
let internals: Vec<&TreeNode> = tree_nodes.iter().filter(|x| x.is_internal()).collect();
assert_internal_values(test.name, deps.as_ref(), internals, true);

let prefix_sum =
get_prefix_sum(deps.as_ref().storage, root_node, test.target_etas).unwrap();
// System under test: get prefix sum
let prefix_sum = get_prefix_sum(deps.as_ref().storage, tree, test.target_etas).unwrap();

// Assert that the correct value was returned
assert_eq!(
test.expected_sum, prefix_sum,
"{}: Expected prefix sum {}, got {}",
test.name, test.expected_sum, prefix_sum
);

// Refetch tree and assert that its nodes were unchanged
let tree = NODES
.load(deps.as_mut().storage, &(book_id, tick_id, root_id))
.unwrap();
let tree_nodes_post = tree.traverse(deps.as_ref().storage).unwrap();
assert_eq!(
tree_nodes, tree_nodes_post,
"Prefix sum mutated tree. Test case: {}",
test.name
);
}
}
Loading

0 comments on commit 2867ab5

Please sign in to comment.