chore: update tests and add avl tests
Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
parent
518ee5b970
commit
f66dec1e03
3 changed files with 233 additions and 7 deletions
228
test_avl.py
Normal file
228
test_avl.py
Normal file
|
@ -0,0 +1,228 @@
|
|||
from avl import AVLTree
|
||||
|
||||
import hypothesis
|
||||
import hypothesis.strategies as st
|
||||
import logging
|
||||
import pytest
|
||||
import random
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def test_empty() -> None:
|
||||
tree = AVLTree()
|
||||
|
||||
assert tree.root is None
|
||||
assert tree.is_correct
|
||||
|
||||
|
||||
def test_one_node() -> None:
|
||||
tree = AVLTree()
|
||||
tree.insert(1)
|
||||
|
||||
assert tree.root is not None
|
||||
assert 1 == tree.root.value
|
||||
assert 0 == tree.root.rank
|
||||
assert tree.root.left is None
|
||||
assert tree.root.right is None
|
||||
|
||||
assert tree.is_correct
|
||||
|
||||
|
||||
@pytest.mark.parametrize("values", [[1, 2], [1, 2, 0]])
|
||||
def test_no_rebalance_needed(values):
|
||||
tree = AVLTree()
|
||||
|
||||
for value in values:
|
||||
tree.insert(value)
|
||||
assert tree.is_correct
|
||||
|
||||
|
||||
def test_three_nodes_rebalanced():
|
||||
tree = AVLTree()
|
||||
|
||||
for value in (1, 2, 3):
|
||||
print(tree)
|
||||
tree.insert(value)
|
||||
|
||||
assert tree.is_correct
|
||||
|
||||
|
||||
def test_bigger_tree():
|
||||
tree = AVLTree()
|
||||
|
||||
for i in range(50):
|
||||
tree.insert(i)
|
||||
assert tree.is_correct
|
||||
|
||||
|
||||
def test_bigger_tree_reversed():
|
||||
tree = AVLTree()
|
||||
|
||||
for i in range(50):
|
||||
tree.insert(-i)
|
||||
assert tree.is_correct
|
||||
|
||||
|
||||
def test_promote():
|
||||
tree = AVLTree()
|
||||
|
||||
for value in (0, 1, -1):
|
||||
tree.insert(value)
|
||||
assert tree.is_correct
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"values",
|
||||
[
|
||||
[0, 1, -2, -1, -3],
|
||||
[0, 1, -2, -1, -3, -4, 4, 9, 7],
|
||||
[0, 1, -2, -1, -3, -4, 4, 9, 7, 5, -5, 8],
|
||||
],
|
||||
)
|
||||
def test_rotate(values):
|
||||
tree = AVLTree()
|
||||
|
||||
for value in values:
|
||||
tree.insert(value)
|
||||
assert tree.is_correct
|
||||
|
||||
|
||||
@hypothesis.settings(max_examples=1000, deadline=None)
|
||||
@hypothesis.given(values=st.sets(st.integers()))
|
||||
def test_insert_random(values):
|
||||
tree = AVLTree()
|
||||
|
||||
for value in values:
|
||||
tree.insert(value)
|
||||
assert tree.is_correct
|
||||
assert tree.search(value) is not None
|
||||
|
||||
|
||||
@st.composite
|
||||
def delete_strategy(draw):
|
||||
values = list(draw(st.sets(st.integers())))
|
||||
delete_order = values.copy()
|
||||
random.shuffle(delete_order)
|
||||
return (values, delete_order)
|
||||
|
||||
|
||||
def _report(t_before: str, t_after: str) -> None:
|
||||
with open("before.dot", "w") as before, open("after.dot", "w") as after:
|
||||
print(t_before, file=before)
|
||||
print(t_after, file=after)
|
||||
|
||||
|
||||
@hypothesis.settings(max_examples=100000, deadline=None)
|
||||
@hypothesis.given(config=delete_strategy())
|
||||
def test_delete_random(config):
|
||||
values, delete_order = config
|
||||
|
||||
tree = AVLTree()
|
||||
|
||||
for value in values:
|
||||
tree.insert(value)
|
||||
|
||||
for value in delete_order:
|
||||
before = str(tree)
|
||||
tree.delete(value)
|
||||
after = str(tree)
|
||||
|
||||
try:
|
||||
assert tree.is_correct
|
||||
except AssertionError:
|
||||
logger.info(
|
||||
f"[FAIL] Delete {value} from {values} in order {delete_order}"
|
||||
)
|
||||
_report(before, after)
|
||||
logger.info(f"Before:\n{before}")
|
||||
logger.info(f"After:\n{after}")
|
||||
raise
|
||||
|
||||
|
||||
# @unittest.skip("Only for replicating hypothesis")
|
||||
@pytest.mark.parametrize(
|
||||
"values, delete_order",
|
||||
[
|
||||
([4, 2, 5, 0, 3], [5, 0, 4, 2, 3]),
|
||||
([1, 2, 3, 4, 5], [5]),
|
||||
([0, 1, 2, -15, 17, -2, -1], [17, 2, 1, 0, -2, -15, -1]),
|
||||
(
|
||||
[
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
128,
|
||||
1536,
|
||||
7,
|
||||
25223,
|
||||
1159,
|
||||
16,
|
||||
32915,
|
||||
148,
|
||||
147,
|
||||
24,
|
||||
26,
|
||||
220,
|
||||
-1,
|
||||
-9,
|
||||
-8,
|
||||
-6,
|
||||
-5,
|
||||
-4,
|
||||
-3,
|
||||
-2,
|
||||
],
|
||||
[
|
||||
24,
|
||||
0,
|
||||
-3,
|
||||
-9,
|
||||
1536,
|
||||
128,
|
||||
7,
|
||||
16,
|
||||
-4,
|
||||
-6,
|
||||
4,
|
||||
2,
|
||||
-5,
|
||||
3,
|
||||
-1,
|
||||
32915,
|
||||
-8,
|
||||
1159,
|
||||
-2,
|
||||
26,
|
||||
220,
|
||||
25223,
|
||||
1,
|
||||
147,
|
||||
148,
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_delete_minimal(values, delete_order):
|
||||
tree = AVLTree()
|
||||
|
||||
for value in values:
|
||||
tree.insert(value)
|
||||
|
||||
for value in delete_order:
|
||||
before = str(tree)
|
||||
tree.delete(value)
|
||||
after = str(tree)
|
||||
|
||||
try:
|
||||
assert tree.is_correct
|
||||
except AssertionError:
|
||||
logger.info(
|
||||
f"[FAIL] Delete {value} from {values} in order {delete_order}"
|
||||
)
|
||||
_report(before, after)
|
||||
logger.info(f"Before:\n{before}")
|
||||
logger.info(f"After:\n{after}")
|
||||
raise
|
|
@ -1,4 +1,4 @@
|
|||
from node import Node, NodeType
|
||||
from node import Node
|
||||
|
||||
|
||||
def test_default_rank():
|
||||
|
@ -10,6 +10,6 @@ def test_default_rank():
|
|||
assert node.right is None
|
||||
|
||||
assert 0 == node.rank
|
||||
assert 0 == Node.rank(node)
|
||||
assert 0 == Node.get_rank(node)
|
||||
assert -1 == Node.difference(node)
|
||||
assert (1, 1) == Node.differences(node)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
from node import Node, NodeType
|
||||
from wavl import WAVLTree
|
||||
|
||||
import hypothesis
|
||||
|
@ -6,7 +5,6 @@ import hypothesis.strategies as st
|
|||
import logging
|
||||
import pytest
|
||||
import random
|
||||
import unittest
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -126,7 +124,7 @@ def delete_strategy(draw):
|
|||
return (values, delete_order)
|
||||
|
||||
|
||||
@hypothesis.settings(max_examples=100000, deadline=None)
|
||||
@hypothesis.settings(max_examples=10000, deadline=None)
|
||||
@hypothesis.given(config=delete_strategy())
|
||||
def test_delete_random(config):
|
||||
values, delete_order = config
|
||||
|
@ -145,7 +143,7 @@ def test_delete_random(config):
|
|||
assert tree.is_correct
|
||||
except AssertionError:
|
||||
logger.info(
|
||||
f"[FAIL] Deleting of {value} from {values} in order {delete_order}"
|
||||
f"[FAIL] Delete {value} from {values} in order {delete_order}"
|
||||
)
|
||||
logger.info(f"Before:\n{before}")
|
||||
logger.info(f"After:\n{after}")
|
||||
|
@ -178,7 +176,7 @@ def test_delete_minimal(values, delete_order):
|
|||
assert tree.is_correct
|
||||
except AssertionError:
|
||||
logger.info(
|
||||
f"[FAIL] Deleting of {value} from {values} in order {delete_order}"
|
||||
f"[FAIL] Delete {value} from {values} in order {delete_order}"
|
||||
)
|
||||
logger.info(f"Before:\n{before}")
|
||||
logger.info(f"After:\n{after}")
|
||||
|
|
Loading…
Reference in a new issue