docs: add generated tutorial compatibility matrix (#212)

* docs: declare tutorial compatibility requirements

* docs: generate tutorial compatibility matrix

* fix: correct BPF Arena minimum kernel

* refactor: simplify compatibility validation

---------

Co-authored-by: LinuxDev9002 <i@littlefisher.me>
This commit is contained in:
云微
2026-07-14 05:00:48 -07:00
committed by GitHub
parent e08f604769
commit 37375ff87e
78 changed files with 1167 additions and 13 deletions

View File

@@ -0,0 +1,129 @@
import tempfile
import unittest
from pathlib import Path
from scripts.generate_compatibility import (
REQUIRED_FIELDS,
collect_tutorials,
parse_config,
render,
validate_metadata,
)
class CompatibilityMetadataTests(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.project_root = Path(__file__).resolve().parent.parent
cls.tutorials = collect_tutorials(cls.project_root / "src")
def test_every_tutorial_has_valid_metadata(self):
config_paths = list((self.project_root / "src").rglob(".config"))
self.assertTrue(config_paths)
self.assertEqual(len(config_paths), len(self.tutorials))
for path in config_paths:
metadata = parse_config(path)
self.assertTrue(set(REQUIRED_FIELDS) <= set(metadata), path)
def test_bilingual_tables_contain_every_tutorial(self):
for chinese in (False, True):
table = render(self.tutorials, chinese=chinese)
self.assertEqual(len(self.tutorials), table.count("| ["))
for tutorial in self.tutorials:
readme = "README.zh.md" if chinese else "README.md"
expected = f"{tutorial['relative'].as_posix()}/{readme}"
self.assertIn(expected, table)
def test_missing_field_is_rejected(self):
metadata = {
"kernel_min": "5.15",
"kernel_min_basis": "required-feature",
"architectures": "x86_64",
"btf": "optional",
"kernel_config": "CONFIG_BPF=y",
"hardware": "none",
"root": "required",
}
with self.assertRaisesRegex(ValueError, "test_status"):
validate_metadata(Path("example/.config"), metadata)
def test_required_btf_config_is_enforced(self):
metadata = {
"kernel_min": "5.15",
"kernel_min_basis": "required-feature",
"architectures": "x86_64",
"btf": "required",
"kernel_config": "CONFIG_BPF=y",
"hardware": "none",
"root": "required",
"test_status": "not-in-ci",
}
with self.assertRaisesRegex(ValueError, "CONFIG_DEBUG_INFO_BTF"):
validate_metadata(Path("example/.config"), metadata)
def test_duplicate_config_field_is_rejected(self):
with tempfile.TemporaryDirectory() as directory:
path = Path(directory) / ".config"
path.write_text("level=Basic\nlevel=Depth\n", encoding="utf-8")
with self.assertRaisesRegex(ValueError, "duplicate field level"):
parse_config(path)
def test_empty_csv_item_is_rejected(self):
metadata = {
"kernel_min": "5.15",
"kernel_min_basis": "repository-baseline",
"architectures": "x86_64,,arm64",
"btf": "optional",
"kernel_config": "CONFIG_BPF=y",
"hardware": "none",
"root": "required",
"test_status": "not-in-ci",
}
with self.assertRaisesRegex(ValueError, "architectures"):
validate_metadata(Path("example/.config"), metadata)
def test_per_arch_kernel_min_covers_all_architectures(self):
metadata = {
"kernel_min": "x86_64:5.5",
"kernel_min_basis": "documented",
"architectures": "x86_64,arm64",
"btf": "optional",
"kernel_config": "CONFIG_BPF=y",
"hardware": "none",
"root": "required",
"test_status": "not-in-ci",
}
with self.assertRaisesRegex(ValueError, "kernel_min"):
validate_metadata(Path("example/.config"), metadata)
def test_not_applicable_basis_requires_not_applicable_kernel(self):
metadata = {
"kernel_min": "5.15",
"kernel_min_basis": "not-applicable",
"architectures": "x86_64",
"btf": "optional",
"kernel_config": "CONFIG_BPF=y",
"hardware": "none",
"root": "required",
"test_status": "not-in-ci",
}
with self.assertRaisesRegex(ValueError, "disagree"):
validate_metadata(Path("example/.config"), metadata)
def test_repository_baseline_is_consistent(self):
metadata = {
"kernel_min": "5.15",
"kernel_min_basis": "repository-baseline",
"architectures": "x86_64",
"btf": "optional",
"kernel_config": "CONFIG_BPF=y,CONFIG_BPF_SYSCALL=y",
"hardware": "none",
"root": "required",
"test_status": "not-in-ci",
}
with self.assertRaisesRegex(ValueError, "repository-baseline must be 4.8"):
validate_metadata(Path("example/.config"), metadata)
if __name__ == "__main__":
unittest.main()