"""Unit tests for Tracksolid API MD5 signature generation.""" import sys import os sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(__file__)))) os.environ.setdefault("TRACKSOLID_APP_KEY", "test_key") os.environ.setdefault("TRACKSOLID_APP_SECRET", "test_secret") os.environ.setdefault("TRACKSOLID_USER_ID", "test_user") os.environ.setdefault("TRACKSOLID_PWD_MD5", "test_md5") os.environ.setdefault("DATABASE_URL", "postgresql://test:test@localhost:5432/test") from ts_shared_rev import build_sign class TestBuildSign: def test_basic_signature(self): """Known input + secret produces expected MD5.""" params = {"method": "jimi.test", "app_key": "mykey", "v": "1.0"} secret = "mysecret" result = build_sign(params, secret) # Verify it's a 32-char uppercase hex string assert len(result) == 32 assert result == result.upper() assert all(c in "0123456789ABCDEF" for c in result) def test_sign_key_excluded(self): """The 'sign' key itself must be excluded from signing.""" params_with = {"method": "test", "sign": "old_sign", "v": "1.0"} params_without = {"method": "test", "v": "1.0"} secret = "secret" assert build_sign(params_with, secret) == build_sign(params_without, secret) def test_none_values_excluded(self): """Keys with None values are excluded from signing.""" params_with_none = {"method": "test", "optional": None, "v": "1.0"} params_without_none = {"method": "test", "v": "1.0"} secret = "secret" assert build_sign(params_with_none, secret) == build_sign(params_without_none, secret) def test_alphabetical_key_ordering(self): """Keys are sorted alphabetically for consistent signing.""" params_abc = {"a": "1", "b": "2", "c": "3"} params_cba = {"c": "3", "b": "2", "a": "1"} secret = "secret" assert build_sign(params_abc, secret) == build_sign(params_cba, secret) def test_different_secrets_produce_different_signs(self): params = {"method": "test"} assert build_sign(params, "secret1") != build_sign(params, "secret2") def test_known_hash(self): """Verify against a manually computed hash.""" import hashlib params = {"app_key": "ABC", "method": "test", "v": "1.0"} secret = "XYZ" sorted_keys = sorted(params.keys()) raw = secret + "".join(f"{k}{params[k]}" for k in sorted_keys) + secret expected = hashlib.md5(raw.encode("utf-8")).hexdigest().upper() assert build_sign(params, secret) == expected