mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-16 00:33:22 +08:00
158 lines
7.2 KiB
Python
158 lines
7.2 KiB
Python
"""Exercise CI Xmake selection with isolated executable and Actions-output mocks."""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
import shutil
|
|
import subprocess
|
|
import tempfile
|
|
import unittest
|
|
|
|
|
|
SCRIPT = Path(__file__).resolve().parents[1] / "actions/ensure-xmake/check-version.sh"
|
|
BASH = shutil.which("bash")
|
|
|
|
|
|
@unittest.skipUnless(BASH, "Bash is required to exercise the CI version check")
|
|
class XmakeVersionCheckTest(unittest.TestCase):
|
|
def check(self, version_output=None, *, minimum="3.1.1", status=0, arguments=()):
|
|
with tempfile.TemporaryDirectory(prefix="crossdesk-xmake-check-") as directory:
|
|
root = Path(directory)
|
|
output_file = root / "github-output"
|
|
output_file.write_text("existing-output=preserved\n", encoding="utf-8")
|
|
arguments_file = root / "arguments"
|
|
if version_output is not None:
|
|
executable = root / "xmake"
|
|
executable.write_text(
|
|
"#!/bin/sh\n"
|
|
'printf "%s\\n" "$@" > "$XMAKE_TEST_ARGUMENTS"\n'
|
|
'printf "%s" "$XMAKE_TEST_OUTPUT"\n'
|
|
'exit "$XMAKE_TEST_STATUS"\n',
|
|
encoding="utf-8",
|
|
)
|
|
executable.chmod(0o755)
|
|
environment = {
|
|
**os.environ,
|
|
# The checker only needs shell builtins. Isolating PATH also
|
|
# guarantees that missing-tool tests cannot find a real xmake.
|
|
"PATH": str(root),
|
|
"GITHUB_OUTPUT": str(output_file),
|
|
"XMAKE_TEST_ARGUMENTS": str(arguments_file),
|
|
"XMAKE_TEST_OUTPUT": version_output or "",
|
|
"XMAKE_TEST_STATUS": str(status),
|
|
}
|
|
if minimum is None:
|
|
environment.pop("XMAKE_MIN_VERSION", None)
|
|
else:
|
|
environment["XMAKE_MIN_VERSION"] = minimum
|
|
result = subprocess.run(
|
|
[BASH, str(SCRIPT), *arguments],
|
|
env=environment,
|
|
capture_output=True,
|
|
text=True,
|
|
check=False,
|
|
)
|
|
outputs = dict(
|
|
line.split("=", 1)
|
|
for line in output_file.read_text(encoding="utf-8").splitlines()
|
|
)
|
|
invocation = (
|
|
arguments_file.read_text(encoding="utf-8").splitlines()
|
|
if arguments_file.exists() else None
|
|
)
|
|
self.assertEqual(outputs["existing-output"], "preserved")
|
|
return result, outputs, invocation
|
|
|
|
def test_keeps_minimum_and_newer_versions(self):
|
|
for version in ("3.1.1", "3.1.2", "3.1.10", "3.2.0", "3.10.0", "4.0.0"):
|
|
with self.subTest(version=version):
|
|
result, outputs, invocation = self.check(f"xmake v{version}\n")
|
|
self.assertEqual(result.returncode, 0, result.stderr)
|
|
self.assertEqual(outputs["needs-upgrade"], "false")
|
|
self.assertEqual(outputs["detected-version"], version)
|
|
self.assertEqual(invocation, ["--root", "--version"])
|
|
self.assertIn("Keeping installed Xmake", result.stdout)
|
|
|
|
def test_older_versions_require_upgrade(self):
|
|
for version in ("3.1.0", "3.0.99", "2.99.99"):
|
|
with self.subTest(version=version):
|
|
result, outputs, _ = self.check(f"xmake v{version}\n")
|
|
self.assertEqual(result.returncode, 0, result.stderr)
|
|
self.assertEqual(outputs["needs-upgrade"], "true")
|
|
self.assertIn("Install Xmake 3.1.1 or newer", result.stdout)
|
|
|
|
def test_components_are_compared_numerically(self):
|
|
for installed, minimum, expected in (
|
|
("3.1.10", "3.1.9", "false"),
|
|
("3.1.9", "3.1.10", "true"),
|
|
("3.2.0", "3.1.99", "false"),
|
|
("3.1.99", "3.2.0", "true"),
|
|
("3.01.009", "3.1.9", "false"),
|
|
("3.1.999999999999999999999", "3.1.9", "false"),
|
|
):
|
|
with self.subTest(installed=installed, minimum=minimum):
|
|
result, outputs, _ = self.check(f"xmake v{installed}", minimum=minimum)
|
|
self.assertEqual(result.returncode, 0, result.stderr)
|
|
self.assertEqual(outputs["needs-upgrade"], expected)
|
|
|
|
def test_parses_ansi_colors_build_suffix_and_windows_line_endings(self):
|
|
result, outputs, _ = self.check(
|
|
"Xmake banner\r\n"
|
|
"\x1b[1;38;5;10mxmake\x1b[0m v\x1b[1m3.1.10\x1b[0m+HEAD.abcdef, A build utility\r\n"
|
|
)
|
|
self.assertEqual(result.returncode, 0, result.stderr)
|
|
self.assertEqual(outputs["needs-upgrade"], "false")
|
|
self.assertEqual(outputs["detected-version"], "3.1.10")
|
|
|
|
def test_missing_broken_and_unrecognizable_tools_require_upgrade(self):
|
|
cases = (
|
|
(None, 0),
|
|
("xmake v9.9.9\n", 17),
|
|
("", 0),
|
|
("xmake version unknown\n", 0),
|
|
("xmake v3.1\n", 0),
|
|
("xmake v3.1.1invalid\n", 0),
|
|
("xmake v3.1.1-rc.1\n", 0),
|
|
("otherxmake v9.9.9\n", 0),
|
|
)
|
|
for output, status in cases:
|
|
with self.subTest(output=output, status=status):
|
|
result, outputs, _ = self.check(output, status=status)
|
|
self.assertEqual(result.returncode, 0, result.stderr)
|
|
self.assertEqual(outputs["needs-upgrade"], "true")
|
|
self.assertEqual(outputs["detected-version"], "")
|
|
self.assertIn("Install Xmake 3.1.1 or newer", result.stdout)
|
|
|
|
def test_verification_fails_when_install_did_not_provide_required_version(self):
|
|
for output, status in ((None, 0), ("xmake v3.1.0", 0), ("unknown", 0), ("xmake v3.1.1", 5)):
|
|
with self.subTest(output=output, status=status):
|
|
result, outputs, _ = self.check(output, status=status, arguments=("--verify",))
|
|
self.assertEqual(result.returncode, 1)
|
|
self.assertEqual(outputs["needs-upgrade"], "true")
|
|
self.assertIn("Xmake verification failed", result.stderr)
|
|
self.assertIn("3.1.1 or newer", result.stderr)
|
|
|
|
def test_verification_accepts_newer_version(self):
|
|
result, outputs, _ = self.check("xmake v4.0.0", arguments=("--verify",))
|
|
self.assertEqual(result.returncode, 0, result.stderr)
|
|
self.assertEqual(outputs["needs-upgrade"], "false")
|
|
|
|
def test_invalid_minimum_fails_before_running_xmake(self):
|
|
for minimum in (None, "", "3.1", "v3.1.1", "3.1.1+HEAD", "3.1.1\n", "3.a.1"):
|
|
with self.subTest(minimum=minimum):
|
|
result, outputs, invocation = self.check("xmake v3.1.1", minimum=minimum)
|
|
self.assertEqual(result.returncode, 2)
|
|
self.assertNotIn("needs-upgrade", outputs)
|
|
self.assertIsNone(invocation)
|
|
self.assertIn("XMAKE_MIN_VERSION", result.stderr)
|
|
|
|
def test_unknown_arguments_fail_before_running_xmake(self):
|
|
result, outputs, invocation = self.check("xmake v3.1.1", arguments=("--install",))
|
|
self.assertEqual(result.returncode, 2)
|
|
self.assertNotIn("needs-upgrade", outputs)
|
|
self.assertIsNone(invocation)
|
|
self.assertIn("Usage:", result.stderr)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|