fix(tests): skip POSIX-host-bound contract tests on Windows dev hosts (#5931)

22 backend tests assert facilities that only exist on a POSIX host and
hard-fail on Windows (CI is ubuntu-latest, so upstream never sees them):

- test_extension_dependency_sync.py: 11 tests spawn bare 'make -n';
  hosts without GNU make get WinError 2 (make is not part of the
  documented Windows setup).
- test_lark_broker.py: 10 tests execute the '#!' fake lark-cli / shim /
  launcher scripts; CreateProcess cannot run shebang scripts
  (WinError 193).
- test_bench_sandbox_provider.py: the boxlite shim workaround test
  asserts POSIX exec-bit semantics after os.chmod; Windows has no
  execute bit and boxlite sandboxes are Linux-only.

Each now skips with an explicit reason when its facility is absent;
Linux/CI coverage is unchanged. On a Windows host the three files go
from 22 failed to 0 failed / 22 skipped.

Fixes #5930
This commit is contained in:
xiaodu55 2026-09-27 10:43:19 +08:00 committed by GitHub
parent 5d3972791d
commit 0f4c05bf28
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 37 additions and 0 deletions

View File

@ -1,10 +1,13 @@
from __future__ import annotations
import importlib.util
import os
import sys
from pathlib import Path
from typing import Any
import pytest
def _load_module(name: str, relative: str):
path = Path(__file__).resolve().parents[1] / relative
@ -276,6 +279,10 @@ def test_boxlite_factory_restores_module_state(monkeypatch):
assert _FactoryProvider._create_box is original_create_box
@pytest.mark.skipif(
os.name == "nt",
reason="asserts POSIX exec-bit semantics (os.chmod cannot toggle execute bits on Windows); boxlite sandboxes are Linux-only",
)
def test_boxlite_shim_workaround_retries_after_fixing_permissions(monkeypatch, tmp_path):
boxes_dir = tmp_path / "boxes"
shim = boxes_dir / "deadbeef" / "bin" / "boxlite-shim"

View File

@ -4,6 +4,7 @@ from __future__ import annotations
import os
import re
import shutil
import subprocess
import tomllib
import zipfile
@ -14,6 +15,12 @@ import pytest
REPO_ROOT = Path(__file__).resolve().parents[2]
BACKEND_ROOT = REPO_ROOT / "backend"
_MAKE_ON_PATH = shutil.which("make") is not None
_skip_without_make = pytest.mark.skipif(
not _MAKE_ON_PATH,
reason="these contract tests dry-run the root Makefile through 'make -n'; GNU make is not installed on this host",
)
def _make_recipe(path: Path, target: str) -> str:
content = path.read_text(encoding="utf-8")
@ -202,6 +209,7 @@ def test_root_extension_shortcuts_are_cross_platform_and_keep_trust_confirmation
assert "--yes" not in _make_recipe(makefile, "extension-upgrade")
@_skip_without_make
def test_root_extension_shortcuts_reject_ambient_environment_arguments() -> None:
environment = os.environ.copy()
@ -233,6 +241,7 @@ def test_root_extension_shortcuts_reject_ambient_environment_arguments() -> None
("extension-remove", "NAME", "--name-env __deerflow_extension_name__"),
],
)
@_skip_without_make
def test_root_extension_shortcuts_keep_command_line_arguments_out_of_the_shell_recipe(
target: str,
variable: str,
@ -266,6 +275,7 @@ def test_root_extension_shortcuts_keep_command_line_arguments_out_of_the_shell_r
("extension-remove", "NAME", "--name-env __deerflow_extension_name__"),
],
)
@_skip_without_make
def test_root_extension_shortcuts_keep_values_out_of_the_cmd_recipe_on_windows(
target: str,
variable: str,

View File

@ -17,6 +17,16 @@ import pytest
from deerflow.integrations import lark_broker
from deerflow.integrations.lark_broker import BrokerConfig, run_lark_cli, serve
# Several tests execute the broker's POSIX artifacts directly: the fake
# ``lark-cli`` binary, the shim, and the launcher are ``#!`` scripts (the real
# ones target POSIX sandbox images), and Windows CreateProcess cannot execute a
# shebang script (WinError 193 / ENOEXEC). CI runs on Linux and keeps the
# coverage; Windows dev hosts skip these instead of hard-failing.
_skip_windows = pytest.mark.skipif(
os.name == "nt",
reason="spawns '#!' scripts (fake lark-cli / shim / launcher) that only a POSIX host can execute",
)
def _fake_lark_cli(tmp_path: Path) -> str:
"""A stub 'lark-cli' that echoes argv, stdin, and the credential env.
@ -58,6 +68,7 @@ def _config(tmp_path: Path, port: int = 0) -> BrokerConfig:
# ── run_lark_cli (in-process, no server) ───────────────────────────────────
@_skip_windows
def test_run_lark_cli_forwards_argv_stdin_and_credential_env(tmp_path: Path) -> None:
config = _config(tmp_path)
result = run_lark_cli(config, ["auth", "status", "--json"], b"piped-input")
@ -72,11 +83,13 @@ def test_run_lark_cli_forwards_argv_stdin_and_credential_env(tmp_path: Path) ->
assert result.stderr == b"ERR:auth status --json\n"
@_skip_windows
def test_run_lark_cli_propagates_exit_code(tmp_path: Path) -> None:
result = run_lark_cli(_config(tmp_path), ["do", "--boom"], b"")
assert result.exit_code == 7
@_skip_windows
def test_run_lark_cli_never_shell_interprets_args(tmp_path: Path) -> None:
# A shell metacharacter must reach the binary as one literal arg, not run a
# second command (shell=False, argv list).
@ -120,6 +133,7 @@ def _post_exec(host: str, port: int, body: dict) -> tuple[int, dict]:
return resp.status, parsed
@_skip_windows
def test_exec_endpoint_round_trips(broker_server) -> None:
host, port = broker_server
status, body = _post_exec(host, port, {"args": ["ping"], "stdin_b64": base64.b64encode(b"hi").decode()})
@ -130,6 +144,7 @@ def test_exec_endpoint_round_trips(broker_server) -> None:
assert payload["stdin"] == "hi"
@_skip_windows
def test_exec_endpoint_ignores_client_supplied_credential_paths(broker_server) -> None:
host, port = broker_server
# Even if a malicious client tries to smuggle env-like args, the broker sets
@ -171,6 +186,7 @@ def test_exec_endpoint_returns_500_json_on_unexpected_error(broker_server, monke
# ── Shim script ─────────────────────────────────────────────────────────────
@_skip_windows
def test_shim_forwards_and_replays_exit_code(broker_server, tmp_path: Path) -> None:
host, port = broker_server
shim = tmp_path / "lark-cli"
@ -230,6 +246,7 @@ def test_install_shim_writes_runtime_layout(tmp_path: Path) -> None:
assert marker == {"version": "v1.0.65", "kind": "shim"}
@_skip_windows
def test_launcher_resolves_python_and_forwards(broker_server, tmp_path: Path) -> None:
"""The /bin/sh launcher finds python3 on PATH and execs the shim body."""
host, port = broker_server
@ -253,6 +270,7 @@ def test_launcher_resolves_python_and_forwards(broker_server, tmp_path: Path) ->
assert b"ERR:do --boom" in completed.stderr
@_skip_windows
def test_launcher_can_pin_interpreter_via_env(broker_server, tmp_path: Path) -> None:
"""DEERFLOW_LARK_BROKER_PYTHON pins the interpreter for images with no python3
on PATH (the launcher must not silently ENOEXEC)."""
@ -276,6 +294,7 @@ def test_launcher_can_pin_interpreter_via_env(broker_server, tmp_path: Path) ->
assert completed.returncode == 0
@_skip_windows
def test_launcher_fails_loudly_without_python(tmp_path: Path) -> None:
"""With no python interpreter resolvable, the launcher exits 127 with an
actionable message rather than an opaque ENOEXEC."""
@ -344,6 +363,7 @@ def test_denied_subcommand_matches_through_leading_flags(tmp_path: Path) -> None
assert result.exit_code == 126
@_skip_windows
def test_allowed_subcommand_still_runs_with_denylist(tmp_path: Path) -> None:
config = BrokerConfig(
lark_cli_path=_fake_lark_cli(tmp_path),