start/sniff-start: refuse to run in Windows-hosted shells
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.
This commit is contained in:
1 parent
8a7bfe87d1
commit
5a41de092c
11 files changed
+124
-11
No files matched your search
@@ -0,0 +1,71 @@
|
||||
"""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()
|
||||
Reference in new issue
Block a user