kvs/тесты/тест_бнд/тест_бнд.py

193 lines
7.8 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
import subprocess
import sys
import os
import re
from pathlib import Path
SCRIPT_DIR = Path(__file__).parent.absolute()
PROJECT_ROOT = SCRIPT_DIR.parent.parent
SOURCE_REL = SCRIPT_DIR / "тест_бнд.квс"
def clean():
files = [
"тест_бнд.elf",
"тест_бнд.csv",
"тест_бнд.аст",
"тест_бнд.токены",
"тест_бнд.константа",
"тест_бнд_pass4.log"
]
for f in files:
f_path = SCRIPT_DIR / f
if f_path.exists():
f_path.unlink()
def build():
os.chdir(PROJECT_ROOT)
build = subprocess.run(["python3", "квс_сборка.py", str(SOURCE_REL)],
capture_output=True, text=True)
if build.returncode != 0:
print(f"❌ Ошибка сборки: {build.returncode}", file=sys.stderr)
print(build.stderr, file=sys.stderr)
return False
return True
def test_file_size():
"""Проверка: файл должен быть маленьким (BSS не в файле)"""
print("DEBUG: Проверка размера файла", file=sys.stderr)
elf_path = SCRIPT_DIR / "тест_бнд.elf"
size = elf_path.stat().st_size
max_size = 100 * 1024 # 100 КБ
if size >= max_size:
print(f"❌ Размер файла {size} байт (ожидалось < {max_size})", file=sys.stderr)
return False
print(f"DEBUG: Размер файла {size} байт (OK)", file=sys.stderr)
return True
def test_bss_section():
"""Проверка секции .bss через readelf -S"""
print("DEBUG: Проверка секции .bss", file=sys.stderr)
os.chdir(SCRIPT_DIR)
result = subprocess.run(["readelf", "-S", "тест_бнд.elf"],
capture_output=True, text=True)
lines = result.stdout.split('\n')
expected_size = 1048576 # 1 МБ = 0x100000
for i, line in enumerate(lines):
if '.bss' in line and 'NOBITS' in line:
if i + 1 < len(lines):
size_line = lines[i + 1].strip()
match = re.search(r'^([0-9a-fA-F]+)', size_line)
if match:
size = int(match.group(1), 16)
if size == expected_size:
print(f"DEBUG: Размер .bss = {size} (OK)", file=sys.stderr)
return True
else:
print(f"❌ Размер .bss = {size} (ожидался {expected_size})", file=sys.stderr)
return False
print("❌ Секция .bss не найдена или имеет неверный формат", file=sys.stderr)
return False
def test_load_segment():
"""Проверка сегмента LOAD с BSS"""
print("DEBUG: Проверка сегмента LOAD", file=sys.stderr)
os.chdir(SCRIPT_DIR)
result = subprocess.run(["readelf", "-l", "тест_бнд.elf"],
capture_output=True, text=True)
print("DEBUG: Вывод readelf -l:", file=sys.stderr)
print(result.stdout, file=sys.stderr)
lines = result.stdout.split('\n')
expected_min = 1048576
# Поиск LOAD сегмента с RW
for i, line in enumerate(lines):
print(f"DEBUG: Строка {i}: {repr(line)}", file=sys.stderr)
if 'LOAD' in line and 'RW' in line:
print(f"DEBUG: Найден LOAD RW на строке {i}: {line}", file=sys.stderr)
# Ищем в следующих строках p_memsz
for j in range(i + 1, min(i + 5, len(lines))):
print(f"DEBUG: Строка {j}: {repr(lines[j])}", file=sys.stderr)
# Формат: 0x0000000000000001 0x0000000000101000 RW 0x1000
matches = re.findall(r'0x([0-9a-fA-F]+)', lines[j])
print(f"DEBUG: Найдено hex: {matches}", file=sys.stderr)
if len(matches) >= 2:
filesz = int(matches[0], 16)
memsz = int(matches[1], 16)
print(f"DEBUG: p_filesz = {filesz}, p_memsz = {memsz}", file=sys.stderr)
if memsz >= expected_min:
print(f"DEBUG: p_memsz = {memsz} (OK)", file=sys.stderr)
return True
else:
print(f"❌ p_memsz = {memsz} (ожидалось >= {expected_min})", file=sys.stderr)
return False
break
else:
# Альтернативный поиск: ищем по соответствию с .bss
print("DEBUG: LOAD RW не найден, ищем по соответствию с .bss", file=sys.stderr)
in_mapping = False
for i, line in enumerate(lines):
if 'Соответствие раздел-сегмент' in line:
in_mapping = True
print(f"DEBUG: Найдено 'Соответствие раздел-сегмент' на строке {i}", file=sys.stderr)
continue
if in_mapping and '.bss' in line:
print(f"DEBUG: Найдена строка с .bss: {line}", file=sys.stderr)
# Находим номер сегмента
seg_match = re.search(r'(\d+)', line)
if seg_match:
seg_num = int(seg_match.group(1))
print(f"DEBUG: Сегмент {seg_num} содержит .bss", file=sys.stderr)
# Теперь ищем этот сегмент в заголовках
for k, l in enumerate(lines):
if f'LOAD' in l and k < i:
print(f"DEBUG: Найден LOAD на строке {k}: {l}", file=sys.stderr)
# Проверяем его размер
for m in range(k + 1, min(k + 5, len(lines))):
matches = re.findall(r'0x([0-9a-fA-F]+)', lines[m])
if len(matches) >= 2:
memsz = int(matches[1], 16)
if memsz >= expected_min:
print(f"DEBUG: p_memsz = {memsz} (OK)", file=sys.stderr)
return True
break
print("❌ Не найден LOAD сегмент с BSS", file=sys.stderr)
return False
def test_execution():
"""Проверка: программа должна выполниться и вернуть 0"""
print("DEBUG: Проверка выполнения", file=sys.stderr)
os.chdir(SCRIPT_DIR)
elf_path = SCRIPT_DIR / "тест_бнд.elf"
run = subprocess.run([str(elf_path)], capture_output=True, text=True)
if run.returncode != 0:
print(f"❌ Код возврата {run.returncode} (ожидался 0)", file=sys.stderr)
return False
print("DEBUG: Выполнение успешно", file=sys.stderr)
return True
def main():
print("DEBUG: Начало теста тест_бнд", file=sys.stderr)
if not build():
clean()
sys.exit(1)
tests = [
("Размер файла", test_file_size),
("Секция .bss", test_bss_section),
("Сегмент LOAD", test_load_segment),
("Выполнение", test_execution),
]
all_passed = True
for name, test_func in tests:
if not test_func():
print(f"❌ Провалена проверка: {name}", file=sys.stderr)
all_passed = False
break
clean()
if all_passed:
print("✅", file=sys.stderr)
sys.exit(0)
else:
print("❌", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()