初始化奇妙小屏幕控制器项目

This commit is contained in:
2026-09-08 22:56:52 +08:00
commit 8d368de3b5
491 changed files with 67678 additions and 0 deletions
@@ -0,0 +1,225 @@
from __future__ import annotations
import gzip
import hashlib
import io
import json
import os
from pathlib import Path
import tarfile
import pytest
from scripts.image_kernel_payload import (
ImageKernelPayloadError,
stage_payload,
verify_staged_payload,
)
from scripts.image_bootstrap_payload import (
APP_RELATIVE,
TARGET_RELATIVE,
ImageBootstrapPayloadError,
stage_payload as stage_bootstrap_payload,
verify_staged_payload as verify_bootstrap_payload,
)
from scripts.kernel_artifact import (
ARTIFACT_NAME,
KERNEL_RELEASE,
REQUIRED_BOOT_FILES,
SOURCE_ARCHIVE_SHA256,
SOURCE_COMMIT,
KernelArtifactError,
sha256_file,
verify_kernel_dependency,
verify_source_dependency,
)
SOURCE_ROOT = Path(__file__).resolve().parents[1]
PROJECT_ROOT = SOURCE_ROOT.parent
def _dependency(
root: Path,
*,
release_marker: str = KERNEL_RELEASE,
source_marker: str = SOURCE_COMMIT,
extra_member: tarfile.TarInfo | None = None,
) -> Path:
root.mkdir()
files = {
"boot/Image-matrix-axp313a1": f"prefix Linux version {KERNEL_RELEASE} suffix".encode(),
"boot/sun50i-h616-walnutpi-1b-matrix-axp313a1.dtb": b"dtb-sd",
"boot/sun50i-h616-walnutpi-1b-emmc-matrix-axp313a1.dtb": b"dtb-emmc",
f"boot/System.map-{KERNEL_RELEASE}": b"system-map",
f"boot/config-{KERNEL_RELEASE}": b"config",
"KERNEL_RELEASE": f"{release_marker}\n".encode(),
"SOURCE_COMMIT": f"{source_marker}\n".encode(),
f"lib/modules/{KERNEL_RELEASE}/kernel/example.ko": b"module",
}
sums = "".join(
f"{hashlib.sha256(body).hexdigest()} {name}\n" for name, body in sorted(files.items())
).encode()
files["SHA256SUMS"] = sums
artifact = root / ARTIFACT_NAME
with artifact.open("wb") as raw:
with gzip.GzipFile(filename="", mode="wb", fileobj=raw, mtime=0) as compressed:
with tarfile.open(fileobj=compressed, mode="w", format=tarfile.PAX_FORMAT) as archive:
for name, body in sorted(files.items()):
info = tarfile.TarInfo(name)
info.size = len(body)
info.uid = info.gid = 0
info.mtime = 0
archive.addfile(info, io.BytesIO(body))
if extra_member is not None:
extra_member.uid = extra_member.gid = 0
extra_member.mtime = 0
archive.addfile(extra_member)
digest = sha256_file(artifact)
(root / "SHA256SUMS").write_text(f"{digest} {ARTIFACT_NAME}\n", encoding="ascii")
metadata = {
"schema_version": 1,
"architecture": "aarch64",
"kernel_release": KERNEL_RELEASE,
"source_commit": SOURCE_COMMIT,
"source_archive_sha256": SOURCE_ARCHIVE_SHA256,
"artifact": ARTIFACT_NAME,
"artifact_bytes": artifact.stat().st_size,
"artifact_sha256": digest,
"unpacked_file_bytes": sum(len(body) for body in files.values()),
"regular_file_count": len(files),
"module_file_count": 1,
"provenance": "synthetic test payload",
}
(root / "METADATA.json").write_text(json.dumps(metadata), encoding="utf-8")
return root
def test_registered_kernel_and_source_dependencies_are_complete():
kernel = PROJECT_ROOT / "发布更新相关/其他依赖/aarch64-kernel/6.1.31-matrix-axp313a1"
source = PROJECT_ROOT / "发布更新相关/其他依赖/kernel-source/walnutpi-linux-6.1.31-30ff3fd5"
if os.environ.get("MATRIX_SOURCE_ONLY_UPDATE_TESTS") == "1":
if not kernel.exists() and not source.exists():
pytest.skip("source-only update payload intentionally omits image build dependencies")
info = verify_kernel_dependency(kernel)
assert info.module_file_count == 3048
assert info.regular_file_count == 3056
assert info.unpacked_file_bytes == 160051604
assert verify_source_dependency(source)["archive_bytes"] == 249095239
registry = json.loads((PROJECT_ROOT / "发布更新相关/其他依赖/DEPENDENCIES.json").read_text(encoding="utf-8"))
active = {item["id"]: item for item in registry["active"]}
assert active["axp313a-kernel-runtime"]["path"] == "aarch64-kernel/6.1.31-matrix-axp313a1"
assert active["walnutpi-linux-kernel-source"]["path"] == (
"kernel-source/walnutpi-linux-6.1.31-30ff3fd5"
)
def test_synthetic_kernel_dependency_round_trip(tmp_path: Path):
info = verify_kernel_dependency(_dependency(tmp_path / "kernel"))
assert info.kernel_release == KERNEL_RELEASE
assert info.module_file_count == 1
assert REQUIRED_BOOT_FILES
def test_kernel_dependency_rejects_outer_digest_damage(tmp_path: Path):
dependency = _dependency(tmp_path / "kernel")
artifact = dependency / ARTIFACT_NAME
body = bytearray(artifact.read_bytes())
body[-1] ^= 0xFF
artifact.write_bytes(body)
with pytest.raises(KernelArtifactError, match="SHA-256 mismatch"):
verify_kernel_dependency(dependency)
def test_kernel_dependency_rejects_wrong_release_marker(tmp_path: Path):
dependency = _dependency(tmp_path / "kernel", release_marker="wrong-release")
with pytest.raises(KernelArtifactError, match="release marker"):
verify_kernel_dependency(dependency)
def test_kernel_dependency_rejects_wrong_source_marker_and_missing_binary(tmp_path: Path):
dependency = _dependency(tmp_path / "wrong", source_marker="0" * 40)
with pytest.raises(KernelArtifactError, match="source commit marker"):
verify_kernel_dependency(dependency)
missing = _dependency(tmp_path / "missing")
(missing / ARTIFACT_NAME).unlink()
with pytest.raises(KernelArtifactError, match="binary is missing"):
verify_kernel_dependency(missing)
@pytest.mark.parametrize(
("name", "kind", "message"),
(
("unsafe-link", tarfile.SYMTYPE, "link or special file"),
("../escape", tarfile.REGTYPE, "unsafe archive path"),
("secret.txt", tarfile.REGTYPE, "unowned file"),
),
)
def test_kernel_dependency_rejects_links_and_unsafe_paths(
tmp_path: Path, name: str, kind: bytes, message: str
):
extra = tarfile.TarInfo(name)
extra.type = kind
if kind == tarfile.SYMTYPE:
extra.linkname = "boot/Image-matrix-axp313a1"
dependency = _dependency(tmp_path / "kernel", extra_member=extra)
with pytest.raises(KernelArtifactError, match=message):
verify_kernel_dependency(dependency)
def test_image_root_payload_stage_verify_and_corruption(tmp_path: Path):
dependency = _dependency(tmp_path / "kernel")
root = tmp_path / "root"
root.mkdir()
result = stage_payload(root, dependency, reserve_bytes=0)
assert result["kernel_release"] == KERNEL_RELEASE
assert verify_staged_payload(root, dependency) == result
staged = root / "opt/matrix-image-bootstrap/axp313a" / ARTIFACT_NAME
staged.write_bytes(staged.read_bytes() + b"damage")
with pytest.raises(KernelArtifactError, match="SHA-256 mismatch"):
verify_staged_payload(root, dependency)
def test_image_root_payload_refuses_existing_target_and_insufficient_space(tmp_path: Path):
dependency = _dependency(tmp_path / "kernel")
existing_root = tmp_path / "existing"
existing_root.mkdir()
stage_payload(existing_root, dependency, reserve_bytes=0)
with pytest.raises(ImageKernelPayloadError, match="already exists"):
stage_payload(existing_root, dependency, reserve_bytes=0)
small_root = tmp_path / "small"
small_root.mkdir()
with pytest.raises(ImageKernelPayloadError, match="lacks room"):
stage_payload(small_root, dependency, reserve_bytes=10**30)
def test_image_bootstrap_stages_application_and_kernel_together(tmp_path: Path):
dependency = _dependency(tmp_path / "kernel")
bundle = tmp_path / "MSCBOOT.TGZ"
bundle.write_bytes(b"application-bundle")
root = tmp_path / "root"
root.mkdir()
result = stage_bootstrap_payload(root, bundle, dependency, reserve_bytes=0)
assert result["bundle_bytes"] == len(b"application-bundle")
assert result["bundle_path"] == "opt/matrix-image-bootstrap/app/MSCBOOT.TGZ"
assert verify_bootstrap_payload(root, bundle, dependency) == result
assert (root / TARGET_RELATIVE / APP_RELATIVE).read_bytes() == bundle.read_bytes()
def test_image_bootstrap_rejects_damage_existing_target_and_combined_space(tmp_path: Path):
dependency = _dependency(tmp_path / "kernel")
bundle = tmp_path / "MSCBOOT.TGZ"
bundle.write_bytes(b"application-bundle")
root = tmp_path / "root"
root.mkdir()
stage_bootstrap_payload(root, bundle, dependency, reserve_bytes=0)
with pytest.raises(ImageBootstrapPayloadError, match="already exists"):
stage_bootstrap_payload(root, bundle, dependency, reserve_bytes=0)
staged = root / TARGET_RELATIVE / APP_RELATIVE
staged.write_bytes(b"damaged")
with pytest.raises(ImageBootstrapPayloadError, match="differs"):
verify_bootstrap_payload(root, bundle, dependency)
small_root = tmp_path / "small"
small_root.mkdir()
with pytest.raises(ImageBootstrapPayloadError, match="both offline payloads"):
stage_bootstrap_payload(small_root, bundle, dependency, reserve_bytes=10**30)