"""Unit tests for src/my_deepagent/hash.py.""" import re import pytest from my_deepagent.hash import canonicalize, sha256 # --------------------------------------------------------------------------- # canonicalize: key ordering # --------------------------------------------------------------------------- def test_canonicalize_sorts_keys() -> None: assert canonicalize({"b": 1, "a": 2}) == '{"a":2,"b":1}' def test_canonicalize_nested_sorts_keys() -> None: result = canonicalize({"x": {"b": 2, "a": 1}}) assert result == '{"x":{"a":1,"b":2}}' def test_canonicalize_empty_dict() -> None: assert canonicalize({}) == "{}" def test_canonicalize_empty_list() -> None: assert canonicalize([]) == "[]" def test_canonicalize_none() -> None: assert canonicalize(None) == "null" def test_canonicalize_integer() -> None: assert canonicalize(42) == "42" def test_canonicalize_float() -> None: # 0.1 has a known floating-point representation result = canonicalize(0.1) assert result == "0.1" def test_canonicalize_no_whitespace() -> None: result = canonicalize({"a": 1, "b": 2}) assert " " not in result def test_canonicalize_list_preserves_order() -> None: # Lists should not be reordered assert canonicalize([3, 1, 2]) == "[3,1,2]" def test_canonicalize_string_value() -> None: assert canonicalize("hello") == '"hello"' def test_canonicalize_boolean() -> None: assert canonicalize(True) == "true" assert canonicalize(False) == "false" def test_canonicalize_nan_raises() -> None: import math with pytest.raises(ValueError): canonicalize(math.nan) # --------------------------------------------------------------------------- # sha256: determinism # --------------------------------------------------------------------------- def test_sha256_deterministic() -> None: value = {"a": 1, "b": [1, 2, 3]} results = [sha256(value) for _ in range(100)] assert len(set(results)) == 1 def test_sha256_returns_64_char_hex() -> None: result = sha256({"a": 1}) assert re.fullmatch(r"[0-9a-f]{64}", result) is not None def test_sha256_different_inputs_different_hash() -> None: h1 = sha256({"a": 1}) h2 = sha256({"a": 2}) assert h1 != h2 def test_sha256_key_order_irrelevant() -> None: # Same content, different insertion order → same hash h1 = sha256({"a": 1, "b": 2}) h2 = sha256({"b": 2, "a": 1}) assert h1 == h2 def test_sha256_empty_dict() -> None: result = sha256({}) assert re.fullmatch(r"[0-9a-f]{64}", result) is not None def test_sha256_none() -> None: result = sha256(None) assert re.fullmatch(r"[0-9a-f]{64}", result) is not None def test_sha256_nested() -> None: h1 = sha256({"x": {"a": 1, "b": 2}}) h2 = sha256({"x": {"b": 2, "a": 1}}) assert h1 == h2 def test_sha256_known_value() -> None: # Pre-computed: sha256('{"a":1}') in UTF-8 import hashlib expected = hashlib.sha256(b'{"a":1}').hexdigest() assert sha256({"a": 1}) == expected