Files
breakshaft/tests/test_edge_cases_names.py
Qwen Code Assistant 4a7fb58b78 docs: добавить TESTING_REPORT.md и бенчмарки
- TESTING_REPORT.md: полный отчёт по тестированию
- benchmarks_production.py: production бенчмарки
- test_edge_cases_names.py: тесты edge cases (unicode, emoji, длинные имена)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-03-28 18:39:19 +00:00

333 lines
11 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Тесты edge cases со странными названиями инжекторов, типов и зависимостей.
Проверяет устойчивость библиотеки к нестандартным именам.
"""
from dataclasses import dataclass
from typing import Any
import pytest
from breakshaft import ConvRepo
from breakshaft.util import hashname, universal_qualname
# =============================================================================
# Тесты hashname
# =============================================================================
class TestHashnameEdgeCases:
"""Тесты hashname со странными значениями."""
def test_hashname_with_special_chars(self):
"""Хэш с специальными символами."""
result = hashname("test-name")
assert isinstance(result, str)
assert "-" not in result
def test_hashname_with_unicode(self):
"""Хэш с unicode символами."""
result = hashname("тест_привет")
assert isinstance(result, str)
def test_hashname_with_emoji(self):
"""Хэш с emoji."""
result = hashname("test_🚀_rocket")
assert isinstance(result, str)
def test_hashname_with_spaces(self):
"""Хэш с пробелами."""
result = hashname("test name with spaces")
assert isinstance(result, str)
def test_hashname_empty_string(self):
"""Хэш пустой строки."""
result = hashname("")
assert isinstance(result, str)
assert len(result) > 0
def test_hashname_very_long_string(self):
"""Хэш очень длинной строки."""
long_name = "a" * 10000
result = hashname(long_name)
assert isinstance(result, str)
assert len(result) < 100
def test_hashname_consistency(self):
"""Хэш должен быть консистентным."""
result1 = hashname("test")
result2 = hashname("test")
assert result1 == result2
# =============================================================================
# Тесты universal_qualname
# =============================================================================
class TestUniversalQualnameEdgeCases:
"""Тесты universal_qualname со странными значениями."""
def test_universal_qualname_with_special_chars(self):
"""qualname с специальными символами."""
result = universal_qualname("test-name")
assert isinstance(result, str)
def test_universal_qualname_with_unicode(self):
"""qualname с unicode."""
result = universal_qualname("тест_привет")
assert isinstance(result, str)
def test_universal_qualname_with_emoji(self):
"""qualname с emoji."""
result = universal_qualname("test_🚀")
assert isinstance(result, str)
def test_universal_qualname_with_brackets(self):
"""qualname с скобками (Generic types)."""
result = universal_qualname("List[int]")
assert isinstance(result, str)
def test_universal_qualname_with_angle_brackets(self):
"""qualname с угловыми скобками."""
result = universal_qualname("Dict[str, int]")
assert isinstance(result, str)
def test_universal_qualname_class(self):
"""qualname класса."""
class TestClass:
pass
result = universal_qualname(TestClass)
assert isinstance(result, str)
assert "TestClass" in result
# =============================================================================
# Тесты странных имён типов
# =============================================================================
class TestStrangeTypeNames:
"""Тесты со странными именами типов."""
def test_type_with_special_chars_in_name(self):
"""Тип с специальными символами в имени."""
StrangeType = type("Type-With-Dash", (), {"value": 42})
repo = ConvRepo()
@repo.mark_injector()
def int_to_strange(i: int) -> StrangeType:
return StrangeType()
def consumer(dep: StrangeType) -> int:
return dep.value
fn = repo.get_conversion((int,), consumer, force_commutative=False)
result = fn(42)
assert result == 42
def test_type_with_unicode_name(self):
"""Тип с unicode именем."""
UnicodeType = type("测试类型", (), {"value": 42})
repo = ConvRepo()
@repo.mark_injector()
def int_to_unicode(i: int) -> UnicodeType:
return UnicodeType()
def consumer(dep: UnicodeType) -> int:
return dep.value
fn = repo.get_conversion((int,), consumer, force_commutative=False)
result = fn(42)
assert result == 42
def test_type_with_very_long_name(self):
"""Тип с очень длинным именем."""
LongType = type("a" * 500, (), {"value": 42})
repo = ConvRepo()
@repo.mark_injector()
def int_to_long(i: int) -> LongType:
return LongType()
def consumer(dep: LongType) -> int:
return dep.value
fn = repo.get_conversion((int,), consumer, force_commutative=False)
result = fn(42)
assert result == 42
def test_type_with_spaces_in_name(self):
"""Тип с пробелами в имени."""
SpaceType = type("Type With Spaces", (), {"value": 42})
repo = ConvRepo()
@repo.mark_injector()
def int_to_space(i: int) -> SpaceType:
return SpaceType()
def consumer(dep: SpaceType) -> int:
return dep.value
fn = repo.get_conversion((int,), consumer, force_commutative=False)
result = fn(42)
assert result == 42
def test_type_with_reserved_word_name(self):
"""Тип с именем зарезервированного слова."""
ClassType = type("class", (), {"value": 42})
repo = ConvRepo()
@repo.mark_injector()
def int_to_class(i: int) -> ClassType:
return ClassType()
def consumer(dep: ClassType) -> int:
return dep.value
fn = repo.get_conversion((int,), consumer, force_commutative=False)
result = fn(42)
assert result == 42
def test_multiple_types_with_same_name(self):
"""Несколько типов с одинаковым именем (в разных scope)."""
Type1 = type("SameType", (), {"value": 1})
Type2 = type("SameType", (), {"value": 2})
repo = ConvRepo()
@repo.mark_injector()
def int_to_type1(i: int) -> Type1:
return Type1()
@repo.mark_injector()
def int_to_type2(i: int) -> Type2:
return Type2()
def consumer1(dep: Type1) -> int:
return dep.value
def consumer2(dep: Type2) -> int:
return dep.value
fn1 = repo.get_conversion((int,), consumer1, force_commutative=False)
result1 = fn1(42)
assert result1 == 1
fn2 = repo.get_conversion((int,), consumer2, force_commutative=False)
result2 = fn2(42)
assert result2 == 2
# =============================================================================
# Тесты странных зависимостей
# =============================================================================
class TestStrangeDependencies:
"""Тесты со странными зависимостями."""
def test_circular_type_dependency(self):
"""Циклическая зависимость типов."""
repo = ConvRepo()
@dataclass
class TypeA:
value: int
@dataclass
class TypeB:
value: int
@repo.mark_injector()
def a_to_b(a: TypeA) -> TypeB:
return TypeB(a.value)
@repo.mark_injector()
def b_to_a(b: TypeB) -> TypeA:
return TypeA(b.value)
def consumer(dep: TypeA) -> int:
return dep.value
# Должно работать без бесконечной рекурсии
fn = repo.get_conversion((TypeA,), consumer, force_commutative=False)
result = fn(TypeA(42))
assert result == 42
def test_many_similar_types(self):
"""Много похожих типов."""
repo = ConvRepo()
# Создаём 50 похожих типов
types = []
for i in range(50):
t = type(f"Type{i}", (), {"value": i})
types.append(t)
def make_injector(idx, type_t):
def injector(i: int) -> type_t:
return type_t()
injector.__name__ = f"int_to_type_{idx}"
return injector
repo.add_injector(make_injector(i, t))
def consumer(dep: types[0]) -> int:
return dep.value
# Должно работать без коллизий
fn = repo.get_conversion((int,), consumer, force_commutative=False)
result = fn(42)
assert result == 0
# =============================================================================
# Тесты коллизий хэшей
# =============================================================================
class TestHashCollisions:
"""Тесты коллизий хэшей."""
def test_hashname_different_types(self):
"""Разные типы должны иметь разные хэши (обычно)."""
h1 = hashname(int)
h2 = hashname(str)
assert isinstance(h1, str)
assert isinstance(h2, str)
def test_universal_qualname_different_types(self):
"""universal_qualname для разных типов."""
q1 = universal_qualname(int)
q2 = universal_qualname(str)
assert q1 != q2
# =============================================================================
# Тесты Any аннотаций
# =============================================================================
class TestAnyAnnotation:
"""Тесты с Any аннотациями."""
def test_injector_with_any_annotation(self):
"""Инжектор с Any аннотацией."""
repo = ConvRepo()
@repo.mark_injector()
def int_to_any(i: int) -> Any:
return i
def consumer(dep: Any) -> int:
return dep
fn = repo.get_conversion((int,), consumer, force_commutative=False)
result = fn(42)
assert result == 42