A Windows user could run the bash launchers from WSL or Git Bash / MSYS2 / MinGW / Cygwin, where the Linux USB assumptions do not hold: WSL cannot reach the Windows SIMtrace2 device, and those shells have no Linux /sys + /dev/bus/usb view for the udev pre-flight. Both launchers now detect a Windows host up front (WSL via /proc/version, the rest via uname -s) and exit 2 with a pointer at the matching .bat launcher, which drives the Windows Python/PyUSB stack. The message goes to stderr; a deliberate WSL/Cygwin flow can still run the Python module directly (noted in the source comment). Tests: tests/test_launchers.py runs each script with a fake mingw uname and asserts exit 2 plus the start.bat/sniff-start.bat pointer, pins the WSL detection, and checks bash -n syntax (skipped when bash is absent). Bumps 2.7.14 (version.py, pyproject, PWA_VERSION), SW cache v96, the README download examples and the release-notes preamble. 561 Python + 80 Node tests.
72 lines
2.7 KiB
Python
72 lines
2.7 KiB
Python
"""Tests for the bash launchers' Windows-hosted-shell guard."""
|
|
|
|
import os
|
|
import shutil
|
|
import stat
|
|
import subprocess
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
REPO = Path(__file__).resolve().parents[1]
|
|
BASH = shutil.which('bash')
|
|
|
|
LAUNCHERS = (
|
|
('start.sh', 'start.bat'),
|
|
('sniff-start.sh', 'sniff-start.bat'),
|
|
)
|
|
|
|
|
|
@unittest.skipUnless(BASH, 'bash is not installed')
|
|
class TestWindowsGuard(unittest.TestCase):
|
|
def _run_as_windows(self, script):
|
|
"""Run *script* with a fake `uname -s` naming a mingw host."""
|
|
with tempfile.TemporaryDirectory() as tmp:
|
|
fake = Path(tmp) / 'uname'
|
|
fake.write_text('#!/bin/sh\necho MINGW64_NT-10.0\n')
|
|
fake.chmod(0o755)
|
|
env = dict(os.environ)
|
|
env['PATH'] = tmp + os.pathsep + env.get('PATH', '')
|
|
return subprocess.run(
|
|
[BASH, str(REPO / script)], cwd=REPO, env=env,
|
|
capture_output=True, text=True, timeout=30)
|
|
|
|
def test_guard_exits_and_names_the_bat_launcher(self):
|
|
for script, bat in LAUNCHERS:
|
|
with self.subTest(script=script):
|
|
res = self._run_as_windows(script)
|
|
self.assertEqual(res.returncode, 2, res.stderr)
|
|
self.assertIn(
|
|
'Error: %s is the Linux/macOS helper and cannot run on '
|
|
'Windows' % script, res.stderr)
|
|
self.assertIn(
|
|
'(WSL / MSYS2 / MinGW / Cygwin detected).', res.stderr)
|
|
self.assertIn(
|
|
'Use %s from a Windows command prompt (cmd.exe / '
|
|
'PowerShell) instead.' % bat, res.stderr)
|
|
|
|
def test_guard_detects_wsl_and_native_windows_shells(self):
|
|
# The mingw/msys/cygwin branch is exercised above; pin the WSL branch
|
|
# and the exit code so a refactor cannot drop either detection.
|
|
for script, _ in LAUNCHERS:
|
|
with self.subTest(script=script):
|
|
src = (REPO / script).read_text()
|
|
self.assertIn('grep -qi microsoft /proc/version', src)
|
|
self.assertIn('MINGW|MSYS|CYGWIN', src)
|
|
self.assertIn('exit 2', src)
|
|
self.assertLess(src.index('Windows guard'),
|
|
src.index('PROJECT_DIR='),
|
|
'the guard must run before the launcher setup')
|
|
|
|
def test_shell_syntax(self):
|
|
for script, _ in LAUNCHERS:
|
|
with self.subTest(script=script):
|
|
res = subprocess.run(
|
|
[BASH, '-n', str(REPO / script)],
|
|
capture_output=True, text=True)
|
|
self.assertEqual(res.returncode, 0, res.stderr)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|