Files
SDR-Rover/experiments/lab003_crc32.py
LittleSam129 c486039053 Split experiments from tests
The tests/ directory held 50 laboratory programs and no tests. They model
channels, run hundreds of repetitions and write CSV, PNG and reports;
calling that a test suite blocked introducing a real one, because any
pytest run would have collected the labs and re-executed every
experiment.

- move all 50 lab programs to experiments/ with git mv, preserving history
- rewrite the 38 cross-imports between labs from tests.labNNN to
  experiments.labNNN
- leave tests/ empty for actual fast checks of protocol/
- point quick_gate and the hook at the new layout and add experiments/ to
  the syntax sweep
- update the paths quoted in the Lab042 specification and the verifier
  agent definition

This also defuses the import-time work finding without touching 41 files:
the labs still create directories and write files on import, but nothing
imports them now except the gate, which does so deliberately.

Gate passes: syntax clean, protocol imports, 15 lab modules import, 2
functional suites run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 14:34:58 +03:00

198 lines
5.1 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.
"""
Lab003. Обнаружение повреждения пакета с помощью CRC-32.
Цель:
1. Сформировать пакет с CRC-32.
2. Проверить исправный пакет.
3. Изменить один бит полезной нагрузки.
4. Убедиться, что CRC обнаруживает повреждение.
"""
import struct
import zlib
# ============================================================
# Константы протокола
# ============================================================
SYNC_WORD = 0xAA55
PROTOCOL_VERSION = 1
MESSAGE_TYPE_TEXT = 1
HEADER_FORMAT = ">HBBHH"
CRC_FORMAT = ">I"
CRC_SIZE = struct.calcsize(CRC_FORMAT)
# ============================================================
# Формирование исходного пакета
# ============================================================
message = "ПРИВЕТ SDR"
payload = message.encode("utf-8")
sequence_number = 1
payload_length = len(payload)
header = struct.pack(
HEADER_FORMAT,
SYNC_WORD,
PROTOCOL_VERSION,
MESSAGE_TYPE_TEXT,
sequence_number,
payload_length,
)
# CRC вычисляется по заголовку и полезной нагрузке.
packet_without_crc = header + payload
crc_value = zlib.crc32(packet_without_crc) & 0xFFFFFFFF
crc_bytes = struct.pack(
CRC_FORMAT,
crc_value,
)
packet = packet_without_crc + crc_bytes
print("Исходное сообщение:")
print(message)
print("\nCRC-32 исходного пакета:")
print(f"0x{crc_value:08X}")
print("\nПолный пакет:")
print(packet.hex(" "))
print("\nДлина полного пакета:")
print(len(packet), "байт")
# ============================================================
# Проверка исправного пакета
# ============================================================
received_data = packet[:-CRC_SIZE]
received_crc_bytes = packet[-CRC_SIZE:]
(received_crc,) = struct.unpack(
CRC_FORMAT,
received_crc_bytes,
)
calculated_crc = zlib.crc32(received_data) & 0xFFFFFFFF
print("\n--- Проверка исправного пакета ---")
print(f"CRC из пакета: 0x{received_crc:08X}")
print(f"CRC вычисленный: 0x{calculated_crc:08X}")
assert received_crc == calculated_crc
print("Результат: пакет не повреждён.")
# ============================================================
# Имитация повреждения одного бита
# ============================================================
corrupted_packet = bytearray(packet)
header_size = struct.calcsize(HEADER_FORMAT)
# Буква S находится по индексу 13 внутри PAYLOAD.
payload_byte_index = 13
packet_byte_index = header_size + payload_byte_index
original_byte = corrupted_packet[packet_byte_index]
# Меняем младший бит:
# S = 0x53
# R = 0x52
corrupted_packet[packet_byte_index] ^= 0x01
corrupted_byte = corrupted_packet[packet_byte_index]
print("\n--- Повреждение одного бита ---")
print(
f"До повреждения: "
f"0x{original_byte:02X} = {original_byte:08b}"
)
print(
f"После повреждения: "
f"0x{corrupted_byte:02X} = {corrupted_byte:08b}"
)
# ============================================================
# Проверка повреждённого пакета
# ============================================================
corrupted_data = bytes(
corrupted_packet[:-CRC_SIZE]
)
corrupted_crc_bytes = bytes(
corrupted_packet[-CRC_SIZE:]
)
(received_crc_after_corruption,) = struct.unpack(
CRC_FORMAT,
corrupted_crc_bytes,
)
calculated_crc_after_corruption = (
zlib.crc32(corrupted_data) & 0xFFFFFFFF
)
print("\n--- Проверка повреждённого пакета ---")
print(
f"CRC из пакета: "
f"0x{received_crc_after_corruption:08X}"
)
print(
f"CRC вычисленный: "
f"0x{calculated_crc_after_corruption:08X}"
)
if received_crc_after_corruption != calculated_crc_after_corruption:
print("\nРезультат: CRC обнаружил повреждение пакета.")
else:
print("\nРезультат: повреждение не обнаружено.")
# ============================================================
# Показываем повреждённое сообщение
# ============================================================
corrupted_payload = corrupted_data[header_size:]
corrupted_message = corrupted_payload.decode("utf-8")
print("\nСообщение внутри повреждённого пакета:")
print(corrupted_message)
# ============================================================
# Автоматические проверки
# ============================================================
assert corrupted_message == "ПРИВЕТ RDR"
assert (
received_crc_after_corruption
!= calculated_crc_after_corruption
)
print("\nПроверка пройдена: CRC-32 обнаружил изменение одного бита.")