- Add tests/crawler_core/test_boss_sign.py: 13 tests for BossSign, _compute_checksum, _generate_uuid - Add tests/crawler_core/test_qcwy_sign.py: 10 tests for Job51Sign and SIGN_KEY - Add tests/crawler_core/test_zhilian_sign.py: 13 tests for ZhilianSign - Add conftest.py at project root to add project root to sys.path - Update pyproject.toml with [tool.pytest.ini_options] pythonpath config - Fix crawler_core/__init__.py: wrap heavy-dep imports in try/except so sign subpackages are importable in lightweight envs without requests_go installed - Remove tests/crawler_core/__init__.py to prevent namespace shadowing of crawler_core package
85 lines
3.0 KiB
Python
85 lines
3.0 KiB
Python
"""Unit tests for crawler_core.boss.sign — BossSign and helper functions.
|
|
|
|
All tests are pure function assertions: no HTTP, no network, no mocks.
|
|
"""
|
|
import sys
|
|
import os
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..'))
|
|
|
|
import re
|
|
import pytest
|
|
from crawler_core.boss.sign import BossSign, _compute_checksum, _generate_uuid, _CHARS
|
|
|
|
|
|
class TestBossSignGenerateTraceid:
|
|
def test_traceid_format(self):
|
|
tid = BossSign.generate_traceid()
|
|
assert re.match(r'^M-W[0-9a-f]{13}[0-9a-zA-Z]{6}[0-9a-zA-Z]{3}$', tid), \
|
|
f"Traceid format wrong: {tid}"
|
|
|
|
def test_traceid_length(self):
|
|
tid = BossSign.generate_traceid()
|
|
assert len(tid) == 25, f"Expected 25 chars, got {len(tid)}: {tid}"
|
|
|
|
def test_traceid_custom_prefix(self):
|
|
tid = BossSign.generate_traceid(prefix="X-Y")
|
|
assert tid.startswith("X-Y"), f"Expected X-Y prefix, got: {tid}"
|
|
|
|
def test_traceid_uniqueness(self):
|
|
t1 = BossSign.generate_traceid()
|
|
t2 = BossSign.generate_traceid()
|
|
assert t1 != t2, "Two calls should return different traceids"
|
|
|
|
def test_bosssign_init_defaults(self):
|
|
sign = BossSign()
|
|
assert sign.mpt == ""
|
|
assert sign.wt2 == ""
|
|
|
|
def test_bosssign_init_with_tokens(self):
|
|
sign = BossSign(mpt="mpt_token", wt2="wt2_token")
|
|
assert sign.mpt == "mpt_token"
|
|
assert sign.wt2 == "wt2_token"
|
|
|
|
|
|
class TestComputeChecksum:
|
|
def test_checksum_length(self):
|
|
checksum = _compute_checksum("1234567890abc456789") # 19 chars
|
|
assert len(checksum) == 3, f"Expected 3 chars, got {len(checksum)}"
|
|
|
|
def test_checksum_chars_in_base62(self):
|
|
checksum = _compute_checksum("1234567890abc456789")
|
|
for ch in checksum:
|
|
assert ch in _CHARS, f"Char {ch!r} not in base62 set"
|
|
|
|
def test_checksum_deterministic(self):
|
|
uuid_str = "1234567890abc456789"
|
|
c1 = _compute_checksum(uuid_str)
|
|
c2 = _compute_checksum(uuid_str)
|
|
assert c1 == c2, "Same input must produce same checksum"
|
|
|
|
def test_checksum_differs_for_different_input(self):
|
|
# Different inputs should (almost always) produce different checksums
|
|
c1 = _compute_checksum("1234567890abc456789")
|
|
c2 = _compute_checksum("9876543210xyz456789")
|
|
# Not guaranteed to differ but extremely likely
|
|
# We test at least that they are valid 3-char strings
|
|
assert len(c1) == 3 and len(c2) == 3
|
|
|
|
|
|
class TestGenerateUuid:
|
|
def test_generate_uuid_length(self):
|
|
uuid = _generate_uuid()
|
|
assert len(uuid) == 19, f"Expected 19 chars, got {len(uuid)}: {uuid}"
|
|
|
|
def test_generate_uuid_hex_prefix(self):
|
|
uuid = _generate_uuid()
|
|
hex_part = uuid[:13]
|
|
assert re.match(r'^[0-9a-f]{13}$', hex_part), \
|
|
f"First 13 chars should be hex: {hex_part}"
|
|
|
|
def test_generate_uuid_base62_suffix(self):
|
|
uuid = _generate_uuid()
|
|
rand_part = uuid[13:]
|
|
for ch in rand_part:
|
|
assert ch in _CHARS, f"Char {ch!r} in random suffix not in base62"
|