from __future__ import annotations import numpy as np import pytest from galileo_rx.io.signalsim_reader import SignalSimReader, SignalSimSampleSpec def test_iq8_signed_i_then_q_and_double_precision(tmp_path) -> None: path = tmp_path / "iq8.bin" path.write_bytes(bytes([0x80, 0x7F, 0xFF, 0x01, 0x02, 0xFE])) samples = SignalSimReader(path, SignalSimSampleSpec("IQ8")).read() assert samples.dtype == np.complex128 np.testing.assert_array_equal(samples, [-128 + 127j, -1 + 1j, 2 - 2j]) def test_iq16_little_endian_scaling_and_qi_order(tmp_path) -> None: path = tmp_path / "iq16.bin" np.asarray([100, -200, -300, 400], dtype=" None: path = tmp_path / "iq4.bin" path.write_bytes(bytes([0x17, 0xA9, 0x80])) np.testing.assert_array_equal(SignalSimReader(path, SignalSimSampleSpec("IQ4")).read(), [1 + 7j, -2 - 1j, 0 + 0j]) def test_iq2_packed_order_and_offset(tmp_path) -> None: path = tmp_path / "iq2.bin" # sample 0: I=+1,Q=-1 -> 0xd; sample 1: I=-1,Q=+1 -> 0x7 path.write_bytes(bytes([0x7D])) reader = SignalSimReader(path, SignalSimSampleSpec("IQ2")) np.testing.assert_array_equal(reader.read(), [1 - 1j, -1 + 1j]) np.testing.assert_array_equal(reader.read(1, 1), [-1 + 1j]) def test_truncation_odd_iq_and_block_streaming(tmp_path) -> None: path = tmp_path / "odd.bin" path.write_bytes(b"\x01\x02\x03") reader = SignalSimReader(path, SignalSimSampleSpec("IQ8")) with pytest.raises(ValueError, match="truncated"): _ = reader.sample_count complete = tmp_path / "complete.bin" complete.write_bytes(bytes(range(12))) reader = SignalSimReader(complete, SignalSimSampleSpec("IQ8"), memory_map=True) blocks = list(reader.blocks(2, offset_samples=1, count=4)) assert [block.size for block in blocks] == [2, 2] np.testing.assert_array_equal(np.concatenate(blocks), [2 + 3j, 4 + 5j, 6 + 7j, 8 + 9j]) with pytest.raises(EOFError, match="only 1 remain"): reader.read(2, 5)