u-boot/test/py/tests/test_cleanup_build.py
Tobias Deiminger 42c0e5bb05 test: Find leftovers after clean/mrproper
Docs describe 'make clean' to delete most generated files, 'make
mrproper' to delete current configuration and all generated files. This
test tries to assert it.

Idea is to search remaining files by patterns in copies of the initial
out-of-source build, which has two advantages:
- looking in an out-of-source build dir allows to tell generated source
  code from committed source code
- copying is fast (compared to rebuilding each time) which allows to do
  a "world clean"

Signed-off-by: Tobias Deiminger <tdmg@linutronix.de>
2023-07-07 16:25:56 -04:00

105 lines
3.1 KiB
Python

# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2023 Tobias Deiminger <tdmg@linutronix.de>
"""Test for unexpected leftovers after make clean"""
import itertools
import os
import pathlib
import shutil
import sys
import pytest
# pylint: disable=redefined-outer-name
@pytest.fixture
def tmp_copy_of_builddir(u_boot_config, tmp_path):
"""For each test, provide a temporary copy of the initial build directory."""
shutil.copytree(
u_boot_config.build_dir,
tmp_path,
symlinks=True,
dirs_exist_ok=True,
)
return tmp_path
@pytest.fixture(scope="module")
def run_make(u_boot_log):
"""Provide function to run and log make without connecting to u-boot console."""
runner = u_boot_log.get_runner("make", sys.stdout)
def _run_make(build_dir, target):
cmd = ["make", f"O={build_dir}", target]
runner.run(cmd)
yield _run_make
runner.close()
@pytest.fixture(scope="module")
def most_generated_files():
"""Path.glob style patterns to describe what should be removed by 'make clean'."""
return (
"**/*.c",
"**/*.dtb",
"**/*.dtbo",
"**/*.o",
"**/*.py",
"**/*.pyc",
"**/*.so",
"**/*.srec",
"u-boot*",
"[svt]pl/u-boot*",
)
@pytest.fixture(scope="module")
def all_generated_files(most_generated_files):
"""Path.glob style patterns to describe what should be removed by 'make mrproper'."""
return most_generated_files + (".config", "**/*.h")
def find_files(search_dir, include_patterns, exclude_dirs=None):
"""Find files matching include_patterns, unless it's in one of exclude_dirs.
include_patterns -- Path.glob style pattern relative to search dir
exclude_dir -- directories to exclude, expected relative to search dir
"""
matches = []
exclude_dirs = [] if exclude_dirs is None else exclude_dirs
for abs_path in itertools.chain.from_iterable(
pathlib.Path(search_dir).glob(pattern) for pattern in include_patterns
):
if abs_path.is_dir():
continue
rel_path = pathlib.Path(os.path.relpath(abs_path, search_dir))
if not any(
rel_path.is_relative_to(exclude_dir) for exclude_dir in exclude_dirs
):
matches.append(rel_path)
return matches
def test_clean(run_make, tmp_copy_of_builddir, most_generated_files):
"""Test if 'make clean' deletes most generated files."""
run_make(tmp_copy_of_builddir, "clean")
leftovers = find_files(
tmp_copy_of_builddir,
most_generated_files,
exclude_dirs=["scripts", "test/overlay"],
)
assert not leftovers, f"leftovers: {', '.join(map(str, leftovers))}"
def test_mrproper(run_make, tmp_copy_of_builddir, all_generated_files):
"""Test if 'make mrproper' deletes current configuration and all generated files."""
run_make(tmp_copy_of_builddir, "mrproper")
leftovers = find_files(
tmp_copy_of_builddir,
all_generated_files,
exclude_dirs=["test/overlay"],
)
assert not leftovers, f"leftovers: {', '.join(map(str, leftovers))}"