"""Регрессии неизвестной границы, CFO и полной задержки доставки Lab049.""" from __future__ import annotations import numpy as np import pytest from experiments import lab049_bpsk_symbol_rate as lab from experiments import lab049_independent_iq as independent def test_fractional_symbol_rate_is_not_silently_rounded() -> None: with pytest.raises(ValueError): lab.phy_mode(20000.5) @pytest.mark.parametrize("rate", (50_000, 100_000)) def test_unknown_frame_start_and_residual_cfo(rate: int) -> None: mode = lab.phy_mode(rate) payload = bytes(range(256)) plan = lab.lab045.build_transmission_plan(payload) iq = lab.lab045.lab044.signed_iq_bytes_to_complex64( lab.build_parameterized_tx_cs8(plan, mode)) iq *= np.exp(1j * (2.7 + 2 * np.pi * 10 * np.arange(iq.size) / mode.sample_rate_hz)).astype(np.complex64) stream = np.pad(iq, (12007, 12003)) result = independent.receive_stream(stream, mode) assert result.termination_reason == "END_OF_STREAM" assert result.crc_pass_count == 1 assert result.accepted_frames[0].reception.payload_bytes == payload assert result.accepted_frames[0].estimated_cfo_hz == pytest.approx(10, abs=1) assert lab.lab045.SYMBOL_RATE == 20_000 assert lab.lab045.lab044.lab043.SAMPLES_PER_SYMBOL == 400 def test_receiver_mode_restores_constants_on_exception() -> None: with pytest.raises(RuntimeError): with independent.receiver_mode(lab.phy_mode(100_000)): raise RuntimeError("контроль выхода") assert lab.lab045.SAMPLES_PER_SYMBOL == 400 assert lab.lab045.lab044.SAMPLES_PER_SYMBOL == 400 def test_noise_only_does_not_produce_a_packet() -> None: generator = np.random.default_rng(49) noise = (generator.standard_normal(180000) + 1j * generator.standard_normal(180000)).astype(np.complex64) result = independent.receive_stream(noise, lab.phy_mode(100_000)) assert result.crc_pass_count == 0 def test_emergency_delivery_includes_its_own_frame() -> None: probe = lab.priority_probe(0.02883) assert probe["emergency_max_video_blocking_ms"] == pytest.approx(28.83) assert probe["emergency_worst_delivery_ms"] == pytest.approx(57.66) assert not probe["emergency_delivery_deadline_met_in_worst_phase"] def test_deadlines_use_complete_delivery_and_drain_is_separate() -> None: result = lab.loaded_scheduler_scenario(0.05766) assert result["deadline_misses"]["CONTROL"] == 6 assert result["deadline_misses"]["EMERGENCY"] == 1 assert result["active_window_delivered_packets"]["TELEMETRY"] == 0 assert result["active_window_delivery_latency"]["TELEMETRY"]["count"] == 0 assert result["delivery_latency_until_drain_end"]["CONTROL"]["max_ms"] == pytest.approx(105.64) assert result["drain_end_seconds"] > result["source_duration_seconds"]