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>
198 lines
5.1 KiB
Python
198 lines
5.1 KiB
Python
"""
|
||
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 обнаружил изменение одного бита.") |