import unittest
import tempfile
import shutil
from prollytree import ProllyTree, TreeConfig
class TestProllyTree(unittest.TestCase):
def setUp(self):
self.tree = ProllyTree(storage_type="memory")
self.temp_dir = tempfile.mkdtemp()
def tearDown(self):
shutil.rmtree(self.temp_dir)
def test_insert_and_find(self):
self.tree.insert(b"test_key", b"test_value")
value = self.tree.find(b"test_key")
self.assertEqual(value, b"test_value")
value = self.tree.find(b"non_existent")
self.assertIsNone(value)
def test_batch_operations(self):
items = [
(b"key1", b"value1"),
(b"key2", b"value2"),
(b"key3", b"value3"),
]
self.tree.insert_batch(items)
self.assertEqual(self.tree.size(), 3)
self.assertEqual(self.tree.find(b"key2"), b"value2")
self.tree.delete_batch([b"key1", b"key3"])
self.assertEqual(self.tree.size(), 1)
self.assertIsNone(self.tree.find(b"key1"))
self.assertIsNone(self.tree.find(b"key3"))
self.assertEqual(self.tree.find(b"key2"), b"value2")
def test_update(self):
self.tree.insert(b"key", b"original_value")
self.tree.update(b"key", b"updated_value")
self.assertEqual(self.tree.find(b"key"), b"updated_value")
def test_delete(self):
self.tree.insert(b"key", b"value")
self.tree.delete(b"key")
self.assertIsNone(self.tree.find(b"key"))
self.assertEqual(self.tree.size(), 0)
def test_tree_properties(self):
self.assertEqual(self.tree.size(), 0)
self.assertIsInstance(self.tree.depth(), int)
self.assertIsInstance(self.tree.get_root_hash(), bytes)
for i in range(10):
self.tree.insert(f"key{i}".encode(), f"value{i}".encode())
self.assertEqual(self.tree.size(), 10)
self.assertGreater(self.tree.depth(), 0)
initial_hash = self.tree.get_root_hash()
self.tree.insert(b"new_key", b"new_value")
new_hash = self.tree.get_root_hash()
self.assertNotEqual(initial_hash, new_hash)
def test_merkle_proof(self):
self.tree.insert(b"key", b"value")
proof = self.tree.generate_proof(b"key")
self.assertIsInstance(proof, bytes)
self.assertTrue(self.tree.verify_proof(proof, b"key", b"value"))
self.assertFalse(self.tree.verify_proof(proof, b"key", b"wrong_value"))
def test_tree_diff(self):
tree2 = ProllyTree(storage_type="memory")
self.tree.insert(b"shared", b"value1")
self.tree.insert(b"only_in_tree1", b"value2")
self.tree.insert(b"modified", b"original")
tree2.insert(b"shared", b"value1")
tree2.insert(b"only_in_tree2", b"value3")
tree2.insert(b"modified", b"changed")
diff = self.tree.diff(tree2)
self.assertIn("added", diff)
self.assertIn("removed", diff)
self.assertIn("modified", diff)
self.assertEqual(len(diff["added"]), 0)
self.assertEqual(len(diff["removed"]), 0)
self.assertEqual(len(diff["modified"]), 0)
def test_file_storage(self):
path = f"{self.temp_dir}/test_tree"
config = TreeConfig(base=4, modulus=64)
tree = ProllyTree(storage_type="file", path=path, config=config)
tree.insert(b"persistent", b"data")
tree.save_config()
import os
self.assertTrue(os.path.exists(path))
def test_custom_config(self):
config = TreeConfig(
base=8,
modulus=128,
min_chunk_size=2,
max_chunk_size=8192,
pattern=42
)
tree = ProllyTree(storage_type="memory", config=config)
tree.insert(b"key", b"value")
self.assertEqual(tree.find(b"key"), b"value")
def test_stats(self):
for i in range(5):
self.tree.insert(f"key{i}".encode(), f"value{i}".encode())
stats = self.tree.stats()
self.assertIsInstance(stats, dict)
self.assertGreater(len(stats), 0)
def test_traverse(self):
self.tree.insert(b"a", b"1")
self.tree.insert(b"b", b"2")
self.tree.insert(b"c", b"3")
traversal = self.tree.traverse()
self.assertIsInstance(traversal, str)
self.assertGreater(len(traversal), 0)
if __name__ == "__main__":
unittest.main()