test(mounts): compare host paths separator-agnostically in provisioner and mount suites (#5413)

* test(mounts): compare host paths separator-agnostically in provisioner and mount suites

The provisioner deliberately preserves host filesystem style
(join_host_path keeps native separators and os.path.normpath re-spells
POSIX inputs on Windows), and the docker --mount args and review-CLI
PYTHONPATH inherit that spelling. Six assertions across
test_provisioner_pvc_volumes, test_three_way_skills_mount_e2e and
test_review_changed_public_skills compared those strings against
POSIX-style literals, so they fail on Windows hosts while passing on
Linux CI. Normalize the host-native side before comparing; the replace
is a no-op on POSIX, so CI expectations are unchanged.

* test(mounts): share the host-path normalization helper

Both review suggestions: define posix_path once in
backend/tests/_host_path_helpers.py (matching the existing _xxx_helpers
convention) instead of three spellings across suites, and wrap the last
raw hostPath assertion (test_hostpath_userdata_includes_thread_id) so
the whole provisioner class stays separator-agnostic.
This commit is contained in:
Shxiao 2026-09-14 12:10:41 +09:00 committed by GitHub
parent 9861c296d4
commit daf32cd246
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 25 additions and 8 deletions

View File

@ -0,0 +1,14 @@
"""Helpers for asserting on paths the codebase spells in host-native style.
The provisioner's ``join_host_path`` deliberately preserves the host
filesystem style (explicit ``PureWindowsPath`` branch), and
``os.path.normpath`` re-spells POSIX inputs with backslashes on Windows, so
hostPath volume strings, docker ``--mount`` args and ``PYTHONPATH`` entries
carry ``\\`` on a Windows host where POSIX CI sees ``/``. Tests that match
segments inside such strings normalize with :func:`posix_path` instead of
hard-coding one separator; the replace is a no-op on POSIX inputs.
"""
def posix_path(path: str) -> str:
return path.replace("\\", "/")

View File

@ -1,6 +1,7 @@
"""Regression tests for provisioner three-way skills + PVC volume support."""
import pytest
from _host_path_helpers import posix_path
def _thread_skill_mounts(
@ -39,7 +40,7 @@ class TestBuildVolumes:
pub = volumes[0]
assert pub.name == "skills-public"
assert pub.host_path is not None
assert pub.host_path.path.endswith("/skills_view/public")
assert posix_path(pub.host_path.path).endswith("/skills_view/public")
assert pub.host_path.type == "Directory"
assert pub.persistent_volume_claim is None
@ -50,7 +51,7 @@ class TestBuildVolumes:
custom = volumes[1]
assert custom.name == "skills-custom"
assert custom.host_path is not None
assert "users/user-7/skills_view/custom" in custom.host_path.path
assert "users/user-7/skills_view/custom" in posix_path(custom.host_path.path)
assert custom.host_path.type == "Directory"
def test_hostpath_skills_legacy_volume(self, provisioner_module):
@ -63,7 +64,7 @@ class TestBuildVolumes:
legacy = volumes[2]
assert legacy.name == "skills-legacy"
assert legacy.host_path is not None
assert "users/default/skills_view/legacy" in legacy.host_path.path
assert "users/default/skills_view/legacy" in posix_path(legacy.host_path.path)
assert legacy.host_path.type == "Directory"
def test_hostpath_without_legacy_flag_still_has_empty_capable_mount(self, provisioner_module):
@ -82,7 +83,7 @@ class TestBuildVolumes:
provisioner_module.USERDATA_PVC_NAME = ""
volumes = provisioner_module._build_volumes("my-thread-42")
userdata_vol = volumes[-1]
path = userdata_vol.host_path.path
path = posix_path(userdata_vol.host_path.path)
assert "my-thread-42" in path
assert path.endswith("user-data")
assert userdata_vol.host_path.type == "DirectoryOrCreate"
@ -149,7 +150,7 @@ class TestBuildVolumes:
assert len(volumes) == 5
extra_vol = volumes[-1]
assert extra_vol.name == "extra-0"
assert extra_vol.host_path.path == "/state/users/alice/integrations/lark-cli/config"
assert posix_path(extra_vol.host_path.path) == "/state/users/alice/integrations/lark-cli/config"
assert extra_vol.host_path.type == "DirectoryOrCreate"
def test_extra_mount_uses_userdata_pvc_when_configured(self, provisioner_module):

View File

@ -5,6 +5,7 @@ from pathlib import Path, PurePosixPath
import pytest
import review_changed_public_skills as runner
from _host_path_helpers import posix_path
from skill_review_waivers import EMPTY_MANIFEST, WaiverManifest
@ -302,7 +303,7 @@ def test_main_exits_nonzero_when_review_cli_reports_error(tmp_path: Path, monkey
"never",
]
assert kwargs["cwd"] == tmp_path
assert "backend/packages/harness" in kwargs["env"]["PYTHONPATH"]
assert "backend/packages/harness" in posix_path(kwargs["env"]["PYTHONPATH"])
assert kwargs["capture_output"] is True
assert kwargs["text"] is True
assert kwargs["check"] is False

View File

@ -15,6 +15,7 @@ from types import SimpleNamespace
from unittest.mock import patch
import pytest
from _host_path_helpers import posix_path
from deerflow.config.extensions_config import ExtensionsConfig, SkillStateConfig
from deerflow.config.paths import Paths
@ -602,11 +603,11 @@ class TestThreeWayMountEndToEnd:
assert "/mnt/skills/custom" in mount_entries
assert "dst=/mnt/skills/custom" in mount_entries["/mnt/skills/custom"]
assert "users/noob/skills_view/custom" in mount_entries["/mnt/skills/custom"]
assert "users/noob/skills_view/custom" in posix_path(mount_entries["/mnt/skills/custom"])
assert "/mnt/skills/integrations" in mount_entries
assert "dst=/mnt/skills/integrations" in mount_entries["/mnt/skills/integrations"]
assert "users/noob/skills_view/integrations" in mount_entries["/mnt/skills/integrations"]
assert "users/noob/skills_view/integrations" in posix_path(mount_entries["/mnt/skills/integrations"])
# noob has no per-user custom → legacy is mounted
assert "/mnt/skills/legacy" in mount_entries