mirror of
https://github.com/facebook/sapling.git
synced 2024-10-06 14:58:03 +03:00
update the usage of pexpect to work on Windows
Summary: Update the integration test code that uses pexpect to use the more modern pexpect APIs. The top-level `pexpect.spawn()` function is considered legacy now, and is only provided for backwards compatibility on Unix platforms. Reviewed By: wez Differential Revision: D21214640 fbshipit-source-id: 941da5435c4f8afaf22e8053f4c344175d7b1a7f
This commit is contained in:
parent
cadcd0ab39
commit
c13f0ac5f7
@ -15,7 +15,7 @@ from eden.fs.cli.daemon import wait_for_shutdown
|
||||
|
||||
from .lib import edenclient, testcase
|
||||
from .lib.find_executables import FindExe
|
||||
from .lib.pexpect import PexpectAssertionMixin
|
||||
from .lib.pexpect import PexpectAssertionMixin, PexpectSpawnType, pexpect_spawn
|
||||
from .lib.service_test_case import ServiceTestCaseBase, service_test
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ class HealthTest(testcase.EdenTestCase):
|
||||
class HealthOfFakeEdenFSTest(ServiceTestCaseBase, PexpectAssertionMixin):
|
||||
def setUp(self) -> None:
|
||||
super().setUp()
|
||||
self.temp_dir = pathlib.Path(self.make_temporary_directory())
|
||||
self.temp_dir = self.make_temp_dir()
|
||||
|
||||
def test_healthy_daemon_is_healthy(self) -> None:
|
||||
with self.spawn_fake_edenfs(self.temp_dir):
|
||||
@ -68,9 +68,8 @@ class HealthOfFakeEdenFSTest(ServiceTestCaseBase, PexpectAssertionMixin):
|
||||
status_process.expect_exact("eden running normally")
|
||||
self.assert_process_succeeds(status_process)
|
||||
|
||||
def spawn_status(self, extra_args: typing.List[str]) -> "pexpect.spawn[str]":
|
||||
return pexpect.spawn(
|
||||
# pyre-ignore[6]: T38947910
|
||||
def spawn_status(self, extra_args: typing.List[str]) -> PexpectSpawnType:
|
||||
return pexpect_spawn(
|
||||
FindExe.EDEN_CLI,
|
||||
["--config-dir", str(self.temp_dir)]
|
||||
+ self.get_required_eden_cli_args()
|
||||
|
@ -6,13 +6,28 @@
|
||||
|
||||
import abc
|
||||
import shlex
|
||||
import sys
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
import pexpect
|
||||
|
||||
|
||||
if sys.platform == "win32":
|
||||
import pexpect.popen_spawn
|
||||
|
||||
PexpectSpawnType = pexpect.popen_spawn.PopenSpawn
|
||||
|
||||
pexpect_spawn = pexpect.popen_spawn.PopenSpawn
|
||||
else:
|
||||
import pexpect.pty_spawn
|
||||
|
||||
PexpectSpawnType = pexpect.pty_spawn.spawn
|
||||
|
||||
pexpect_spawn = pexpect.pty_spawn.spawn
|
||||
|
||||
|
||||
class PexpectAssertionMixin(metaclass=abc.ABCMeta):
|
||||
def assert_process_succeeds(self, process: pexpect.spawn):
|
||||
def assert_process_succeeds(self, process: PexpectSpawnType):
|
||||
actual_exit_code = wait_for_pexpect_process(process)
|
||||
self.assertEqual(
|
||||
actual_exit_code,
|
||||
@ -21,7 +36,7 @@ class PexpectAssertionMixin(metaclass=abc.ABCMeta):
|
||||
)
|
||||
|
||||
def assert_process_fails(
|
||||
self, process: pexpect.spawn, exit_code: Optional[int] = None
|
||||
self, process: PexpectSpawnType, exit_code: Optional[int] = None
|
||||
):
|
||||
if exit_code is None:
|
||||
actual_exit_code = wait_for_pexpect_process(process)
|
||||
@ -34,7 +49,7 @@ class PexpectAssertionMixin(metaclass=abc.ABCMeta):
|
||||
else:
|
||||
self.assert_process_exit_code(process, exit_code)
|
||||
|
||||
def assert_process_exit_code(self, process: pexpect.spawn, exit_code: int):
|
||||
def assert_process_exit_code(self, process: PexpectSpawnType, exit_code: int):
|
||||
actual_exit_code = wait_for_pexpect_process(process)
|
||||
self.assertEqual(
|
||||
actual_exit_code,
|
||||
@ -52,17 +67,23 @@ class PexpectAssertionMixin(metaclass=abc.ABCMeta):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
def pexpect_process_shell_command(process: pexpect.spawn) -> str:
|
||||
def pexpect_process_shell_command(process: PexpectSpawnType) -> str:
|
||||
def str_from_strlike(s: Union[bytes, str]) -> str:
|
||||
if isinstance(s, str):
|
||||
return s
|
||||
else:
|
||||
return s.decode("utf-8")
|
||||
|
||||
command_parts = [process.command] + [str_from_strlike(arg) for arg in process.args]
|
||||
return " ".join(map(shlex.quote, command_parts))
|
||||
command = process.command
|
||||
args = process.args
|
||||
if command is None:
|
||||
return "<no pexpect command set>"
|
||||
else:
|
||||
assert args is not None
|
||||
command_parts = [command] + [str_from_strlike(arg) for arg in args]
|
||||
return " ".join(map(shlex.quote, command_parts))
|
||||
|
||||
|
||||
def wait_for_pexpect_process(process: pexpect.spawn) -> int:
|
||||
def wait_for_pexpect_process(process: PexpectSpawnType) -> int:
|
||||
process.expect_exact(pexpect.EOF)
|
||||
return process.wait()
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import typing
|
||||
from typing import Optional
|
||||
|
||||
import eden.thrift
|
||||
@ -15,7 +16,7 @@ from eden.fs.cli.config import EdenInstance
|
||||
from eden.fs.cli.util import HealthStatus
|
||||
|
||||
from .lib.find_executables import FindExe
|
||||
from .lib.pexpect import PexpectAssertionMixin
|
||||
from .lib.pexpect import PexpectAssertionMixin, PexpectSpawnType, pexpect_spawn
|
||||
from .lib.service_test_case import (
|
||||
ServiceTestCaseBase,
|
||||
SystemdServiceTest,
|
||||
@ -40,7 +41,7 @@ class RestartTestBase(ServiceTestCaseBase):
|
||||
|
||||
self.addCleanup(ensure_stopped)
|
||||
|
||||
def _spawn_restart(self, *args: str) -> "pexpect.spawn[bytes]":
|
||||
def _spawn_restart(self, *args: str) -> PexpectSpawnType:
|
||||
restart_cmd = (
|
||||
[FindExe.EDEN_CLI, "--config-dir", str(self.eden_dir)]
|
||||
+ self.get_required_eden_cli_args()
|
||||
@ -50,7 +51,7 @@ class RestartTestBase(ServiceTestCaseBase):
|
||||
restart_cmd.extend(args)
|
||||
|
||||
print("Retarting eden: %r" % (restart_cmd,))
|
||||
return pexpect.spawn(
|
||||
return pexpect_spawn(
|
||||
restart_cmd[0], restart_cmd[1:], logfile=sys.stdout.buffer, timeout=5
|
||||
)
|
||||
|
||||
@ -74,7 +75,6 @@ class RestartTest(RestartTestBase, PexpectAssertionMixin):
|
||||
p.expect_exact("Eden is not currently running. Starting it...")
|
||||
p.expect_exact("Starting fake edenfs daemon")
|
||||
p.expect(r"Started edenfs \(pid ([0-9]+)\)")
|
||||
int(p.match.group(1))
|
||||
p.wait()
|
||||
self.assertEqual(p.exitstatus, 0)
|
||||
|
||||
@ -109,7 +109,9 @@ class RestartTest(RestartTestBase, PexpectAssertionMixin):
|
||||
|
||||
p = self._spawn_restart("--force")
|
||||
p.expect(r"Started edenfs \(pid (?P<pid>\d+)\)")
|
||||
new_pid_from_restart: int = int(p.match.group("pid"))
|
||||
match = typing.cast(Optional[typing.Match], p.match)
|
||||
assert match is not None
|
||||
new_pid_from_restart: int = int(match.group("pid"))
|
||||
new_pid_from_health_check: Optional[int] = self._check_edenfs_health().pid
|
||||
|
||||
self.assertIsNotNone(new_pid_from_health_check, "EdenFS should be alive")
|
||||
|
@ -18,7 +18,12 @@ from eden.fs.cli.daemon import wait_for_process_exit
|
||||
from eden.fs.cli.util import poll_until
|
||||
|
||||
from .lib.find_executables import FindExe
|
||||
from .lib.pexpect import PexpectAssertionMixin, wait_for_pexpect_process
|
||||
from .lib.pexpect import (
|
||||
PexpectAssertionMixin,
|
||||
PexpectSpawnType,
|
||||
pexpect_spawn,
|
||||
wait_for_pexpect_process,
|
||||
)
|
||||
from .lib.service_test_case import (
|
||||
ServiceTestCaseBase,
|
||||
SystemdServiceTest,
|
||||
@ -42,9 +47,8 @@ class StopTestBase(ServiceTestCaseBase):
|
||||
self.eden_dir = self.tmp_dir / "eden"
|
||||
self.eden_dir.mkdir()
|
||||
|
||||
def spawn_stop(self, extra_args: List[str]) -> "pexpect.spawn[str]":
|
||||
return pexpect.spawn(
|
||||
# pyre-ignore[6]: T38947910
|
||||
def spawn_stop(self, extra_args: List[str]) -> PexpectSpawnType:
|
||||
return pexpect_spawn(
|
||||
FindExe.EDEN_CLI,
|
||||
["--config-dir", str(self.eden_dir)]
|
||||
+ self.get_required_eden_cli_args()
|
||||
|
@ -11,13 +11,14 @@ import subprocess
|
||||
import sys
|
||||
import typing
|
||||
import unittest
|
||||
from typing import Optional
|
||||
|
||||
import pexpect
|
||||
import toml
|
||||
from eden.test_support.testcase import EdenTestCaseBase
|
||||
|
||||
from .lib.find_executables import FindExe
|
||||
from .lib.pexpect import PexpectAssertionMixin
|
||||
from .lib.pexpect import PexpectAssertionMixin, PexpectSpawnType, pexpect_spawn
|
||||
from .lib.service_test_case import SystemdServiceTest, systemd_test
|
||||
|
||||
|
||||
@ -93,10 +94,10 @@ class SystemdTest(SystemdServiceTest, PexpectAssertionMixin):
|
||||
r"error: Starting the fb-edenfs@.+?\.service systemd service "
|
||||
r"failed \(reason: exit-code\)"
|
||||
)
|
||||
before = typing.cast(Optional[str], start_process.before)
|
||||
assert before is not None
|
||||
self.assertNotIn(
|
||||
"journalctl",
|
||||
start_process.before,
|
||||
"journalctl doesn't work and should not be mentioned",
|
||||
"journalctl", before, "journalctl doesn't work and should not be mentioned"
|
||||
)
|
||||
remaining_output = start_process.read()
|
||||
self.assertNotIn(
|
||||
@ -161,9 +162,8 @@ class SystemdTest(SystemdServiceTest, PexpectAssertionMixin):
|
||||
|
||||
def spawn_start_with_fake_edenfs(
|
||||
self, extra_args: typing.Sequence[str] = ()
|
||||
) -> "pexpect.spawn[str]":
|
||||
return pexpect.spawn(
|
||||
# pyre-ignore[6]: T38947910
|
||||
) -> PexpectSpawnType:
|
||||
return pexpect_spawn(
|
||||
FindExe.EDEN_CLI,
|
||||
self.get_required_eden_cli_args()
|
||||
# pyre-ignore[6]: T38947910
|
||||
|
Loading…
Reference in New Issue
Block a user