mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-10-26 13:16:24 +00:00
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:
parent
5d3972791d
commit
0f4c05bf28
@ -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"
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user