"""Дымовой тест: реальная база компонентов (Этап 1) действительно прогоняется. Не проверяет конкретные числа (это будет делать sweep/оптимизатор) — только то, что хотя бы одна разумная комбинация реальных деталей из components/data/*.json физически прогоняется через полную цепочку без исключений, и что честная отбраковка (feasible=False) тоже доступна и не падает, если комбинация неудачная. """ from gausse.components.database import ComponentDatabase from gausse.sim.coilgun import CoilgunConfig, run_coilgun from gausse.sim.stage import ProjectileConfig, StageConfig def _find(items, **kwargs): for item in items: if all(getattr(item, k) == v for k, v in kwargs.items()): return item raise AssertionError(f"не найден компонент с {kwargs} среди {len(items)} записей") def test_real_component_database_loads_and_is_nonempty(): db = ComponentDatabase.load() assert len(db.wires) > 0 assert len(db.capacitors) > 0 assert len(db.switches) > 0 assert len(db.sensors) > 0 assert len(db.projectile_materials) > 0 def test_real_component_combination_runs_end_to_end(): db = ComponentDatabase.load() wire = _find(db.wires, part_id="cu-petv2-1.0mm") capacitor = _find(db.capacitors, part_number="cap-470uf-400v") switch = _find(db.switches, part_number="IRFP250PBF") sensor = _find(db.sensors, part_number="TCST2103") steel = _find(db.projectile_materials, name="Ст3 (конструкционная сталь)") projectile = ProjectileConfig(material=steel, diameter_m=0.008, length_m=0.02) stage = StageConfig( wire=wire, capacitor=capacitor, switch=switch, sensor=sensor, tube_od_m=0.01, turns_per_layer=20, layers=4, sensor_to_coil_distance_m=0.02, charge_voltage_v=350.0, ) config = CoilgunConfig( stages=[stage, stage], inter_stage_gaps_m=[0.05], projectile=projectile, initial_x_m=-0.05, initial_v_mps=5.0, ) result = run_coilgun(config) # Реальные детали могут дать как удачную, так и провальную (feasible=False) # конфигурацию — это тоже честный результат. Тест лишь гарантирует, что # весь путь (реальные JSON -> физика -> цепочка) не падает с исключением # и возвращает осмысленный, самосогласованный результат в любом случае. if result.feasible: assert result.exit_v_mps is not None assert 0.0 <= result.efficiency <= 1.0 else: assert result.reason is not None assert result.failed_stage_index is not None