mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-06-03 15:01:16 -03:00
test_driver: don't chdir in async driver
The test driver is async now; so we can't change the process-wide working directory without causing unpredictable behavior. For example, given these two tests: $ cat tests/checks/a.fish #RUN: %fish %s #REQUIRES: sleep 1 pwd >/tmp/pwd-of-a $ cat tests/checks/b.fish #RUN: %fish %s pwd >/tmp/pwd-of-b running them may give both fish processes the same working directory. $ tests/test_driver.py target/debug tests/checks/a.fish tests/checks/b.fish tests/checks/b.fish PASSED 13 ms tests/checks/a.fish PASSED 1019 ms 2 / 2 passed (0 skipped) $ grep . /tmp/pwd-of-a /tmp/pwd-of-b /tmp/pwd-of-a:/tmp/fishtest-root-1q_tnyqa/fishtest-s9cyqkgz /tmp/pwd-of-b:/tmp/fishtest-root-1q_tnyqa/fishtest-s9cyqkgz
This commit is contained in:
@@ -387,16 +387,16 @@ def runproc(cmd, env=None):
|
||||
return asyncio.run(runproc_async(cmd, env=env))
|
||||
|
||||
|
||||
async def runproc_async(cmd, env=None):
|
||||
async def runproc_async(cmd, env=None, cwd=None):
|
||||
"""Wrapper around subprocess.Popen to save typing"""
|
||||
PIPE = asyncio.subprocess.PIPE
|
||||
return await asyncio.create_subprocess_shell(
|
||||
cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env
|
||||
cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env, cwd=cwd
|
||||
)
|
||||
|
||||
|
||||
class TestRun(object):
|
||||
def __init__(self, name, runcmd, checker, subs, config, env=None):
|
||||
def __init__(self, name, runcmd, checker, subs, config, env=None, cwd=None):
|
||||
self.name = name
|
||||
self.runcmd = runcmd
|
||||
self.subbed_command = perform_substitution(runcmd.args, subs)
|
||||
@@ -404,6 +404,7 @@ class TestRun(object):
|
||||
self.subs = subs
|
||||
self.config = config
|
||||
self.env = env
|
||||
self.cwd = cwd
|
||||
|
||||
def check(self, lines, checks):
|
||||
# Reverse our lines and checks so we can pop off the end.
|
||||
@@ -493,7 +494,7 @@ class TestRun(object):
|
||||
|
||||
if self.config.verbose:
|
||||
print(self.subbed_command)
|
||||
proc = await runproc_async(self.subbed_command, env=self.env)
|
||||
proc = await runproc_async(self.subbed_command, env=self.env, cwd=self.cwd)
|
||||
stdout, stderr = await proc.communicate()
|
||||
|
||||
# Work around type system limitations / bad API design which makes the typechecker unhappy.
|
||||
@@ -684,7 +685,9 @@ def check_file(input_file, name, subs, config, failure_handler, env=None):
|
||||
)
|
||||
|
||||
|
||||
async def check_file_async(input_file, name, subs, config, failure_handler, env=None):
|
||||
async def check_file_async(
|
||||
input_file, name, subs, config, failure_handler, env=None, cwd=None
|
||||
):
|
||||
"""Check a single file. Return a True on success, False on error."""
|
||||
success = True
|
||||
lines = Line.readfile(input_file, name)
|
||||
@@ -693,7 +696,9 @@ async def check_file_async(input_file, name, subs, config, failure_handler, env=
|
||||
# Run all the REQUIRES lines first,
|
||||
# if any of them fail it's a SKIP
|
||||
for reqcmd in checker.requirecmds:
|
||||
proc = await runproc_async(perform_substitution(reqcmd.args, subs), env=env)
|
||||
proc = await runproc_async(
|
||||
perform_substitution(reqcmd.args, subs), env=env, cwd=cwd
|
||||
)
|
||||
await proc.communicate()
|
||||
# Work around type system limitations / bad API design which makes the typechecker unhappy.
|
||||
if proc.returncode is None:
|
||||
@@ -709,7 +714,7 @@ async def check_file_async(input_file, name, subs, config, failure_handler, env=
|
||||
# Only then run the RUN lines.
|
||||
for runcmd in checker.runcmds:
|
||||
failure = await TestRun(
|
||||
name, runcmd, checker, subs, config, env=env
|
||||
name, runcmd, checker, subs, config, env=env, cwd=cwd
|
||||
).run_async()
|
||||
if failure:
|
||||
failure_handler(failure)
|
||||
@@ -721,9 +726,11 @@ def check_path(path, subs, config, failure_handler, env=None):
|
||||
return asyncio.run(check_path_async(path, subs, config, failure_handler, env=env))
|
||||
|
||||
|
||||
async def check_path_async(path, subs, config, failure_handler, env=None):
|
||||
async def check_path_async(path, subs, config, failure_handler, env=None, cwd=None):
|
||||
with io.open(path, encoding="utf-8") as fd:
|
||||
return await check_file_async(fd, path, subs, config, failure_handler, env=env)
|
||||
return await check_file_async(
|
||||
fd, path, subs, config, failure_handler, env=env, cwd=cwd
|
||||
)
|
||||
|
||||
|
||||
def parse_subs(subs):
|
||||
|
||||
@@ -297,7 +297,6 @@ async def run_test(
|
||||
starttime = datetime.now()
|
||||
home = Path(tempfile.mkdtemp(prefix="fishtest-", dir=tmp_root))
|
||||
test_env = makeenv(script_path, home)
|
||||
os.chdir(home)
|
||||
if test_file_path.endswith(".fish"):
|
||||
subs = def_subs.copy()
|
||||
subs.update(
|
||||
@@ -309,7 +308,12 @@ async def run_test(
|
||||
|
||||
# littlecheck
|
||||
ret = await littlecheck.check_path_async(
|
||||
test_file_path, subs, lconfig, lambda x: print(x.message()), env=test_env
|
||||
test_file_path,
|
||||
subs,
|
||||
lconfig,
|
||||
lambda x: print(x.message()),
|
||||
env=test_env,
|
||||
cwd=home,
|
||||
)
|
||||
endtime = datetime.now()
|
||||
duration_ms = round((endtime - starttime).total_seconds() * 1000)
|
||||
@@ -339,6 +343,7 @@ async def run_test(
|
||||
stdout=PIPE,
|
||||
stderr=PIPE,
|
||||
env=test_env,
|
||||
cwd=home,
|
||||
)
|
||||
stdout, stderr = await proc.communicate()
|
||||
endtime = datetime.now()
|
||||
|
||||
Reference in New Issue
Block a user