Files
kernalix7--winpodx/tests/test_discover_apps_ps1_syntax.py
wehub-resource-sync 3e779be6f3
CI / lint (push) Failing after 13m4s
CI / test (3.11, ubuntu-latest) (push) Failing after 2m4s
CI / test (3.13, ubuntu-latest) (push) Successful in 13m30s
CI / test (3.14, ubuntu-latest) (push) Successful in 17m21s
CI / test (3.12, ubuntu-latest) (push) Successful in 17m55s
CI / discover-apps-ps (push) Successful in 1m56s
CI / test (3.9, ubuntu-latest) (push) Successful in 13m17s
CI / test (3.10, ubuntu-latest) (push) Successful in 26m21s
CI / audit (push) Successful in 13m38s
Deploy site / deploy (push) Has been cancelled
CI / test (3.14, ubuntu-24.04-arm) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:32:37 +08:00

103 lines
4.1 KiB
Python

# SPDX-License-Identifier: MIT
"""Sanity checks for scripts/windows/discover_apps.ps1.
The .ps1 runs inside the Windows guest, so CI can't exercise it end to end.
These checks (a) pwsh-AST-parse it when pwsh is on PATH (CI has it; skipped on
the dev box) so a syntax error in the guest script can't merge silently, and
(b) statically assert the #581 Start-Menu-only scan invariants the host relies
on (the literal sentinel the host patches, and that the two legacy-only sources
are gated behind the full-scan switch).
"""
from __future__ import annotations
import shutil
import subprocess
from pathlib import Path
import pytest
REPO_ROOT = Path(__file__).resolve().parent.parent
DISCOVER_PS1 = REPO_ROOT / "scripts" / "windows" / "discover_apps.ps1"
@pytest.fixture(scope="module")
def discover_source() -> str:
assert DISCOVER_PS1.is_file(), f"discover_apps.ps1 missing at {DISCOVER_PS1}"
return DISCOVER_PS1.read_text(encoding="utf-8")
def test_discover_apps_ps1_exists():
assert DISCOVER_PS1.is_file()
def test_discover_apps_ps1_pwsh_parse():
"""If pwsh is on PATH, the script must parse without errors."""
pwsh = shutil.which("pwsh")
if not pwsh:
pytest.skip("pwsh not installed on this host")
cmd = [
pwsh,
"-NoProfile",
"-NonInteractive",
"-Command",
(
"$errors = $null; "
f"[void][System.Management.Automation.Language.Parser]::ParseFile('{DISCOVER_PS1}', "
"[ref]$null, [ref]$errors); "
"if ($errors -and $errors.Count -gt 0) { "
" $errors | ForEach-Object { Write-Error $_.ToString() }; exit 1 "
"}"
),
]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
assert result.returncode == 0, (
f"pwsh parse failed:\nstdout={result.stdout}\nstderr={result.stderr}"
)
def test_host_patch_sentinel_is_present_and_unique(discover_source: str):
"""The host flips this exact literal to enable full_app_scan (#581); if it
drifts or duplicates, the one-shot replace in core.discovery silently
no-ops or patches the wrong line."""
assert discover_source.count("$WinpodxFullScan = $false") == 1
def test_legacy_sources_are_gated_behind_full_scan(discover_source: str):
"""App Paths (Source 1) and choco/scoop shims (Source 4) must only run in
full-scan mode, else the default would still flood the menu."""
assert "if ($WinpodxFullScan) {" in discover_source
# both legacy-only sources carry the closing marker comment
assert "end if ($WinpodxFullScan) -- Source 1" in discover_source
assert "end if ($WinpodxFullScan) -- Source 4" in discover_source
def test_url_scheme_harvest_functions_present(discover_source: str):
"""#421/#694: the URL-scheme harvest mirrors the file-ext harvest -- guard
that the three functions + both emit sites exist so a refactor can't quietly
drop the guest side of the feature."""
for fn in ("function Add-SchemeTo", "function Build-SchemeMap", "function Get-AppUrlSchemes"):
assert fn in discover_source, f"missing {fn}"
# emitted from both the Win32 (Get-AppUrlSchemes) and UWP (windows.protocol) paths
assert "Get-AppUrlSchemes $path" in discover_source
assert "windows\\.protocol" in discover_source
assert discover_source.count("url_schemes = @(") == 2
def test_uwp_gated_by_startapps_in_default_mode(discover_source: str):
"""Default mode keeps only UWP apps whose AUMID is in Get-StartApps, with
an empty-set fallback so we never hide every UWP app."""
assert "$startAppNames.ContainsKey($aumid)" in discover_source
assert "$startAppNames.Count -gt 0" in discover_source
def test_param_block_stays_first_statement(discover_source: str):
"""The host patches a body line (not a prepend) precisely because `param`
must remain the first statement; guard that nothing crept in before it."""
lines = [
ln.strip()
for ln in discover_source.splitlines()
if ln.strip() and not ln.lstrip().startswith("#")
]
assert lines[0].startswith("[CmdletBinding()]") or lines[0].startswith("param(")