summaryrefslogtreecommitdiff
path: root/test/t/conftest.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/t/conftest.py')
-rw-r--r--test/t/conftest.py81
1 files changed, 64 insertions, 17 deletions
diff --git a/test/t/conftest.py b/test/t/conftest.py
index 0969a313..20942e87 100644
--- a/test/t/conftest.py
+++ b/test/t/conftest.py
@@ -2,6 +2,7 @@ import difflib
import os
import re
import shlex
+import subprocess
from typing import Iterable, List, Optional, Tuple, Union
import pexpect
@@ -81,7 +82,7 @@ def bash(request) -> pexpect.spawn:
logfile = None
if os.environ.get("BASHCOMP_TEST_LOGFILE"):
- logfile = open(os.environ.get("BASHCOMP_TEST_LOGFILE"), "w")
+ logfile = open(os.environ["BASHCOMP_TEST_LOGFILE"], "w")
testdir = os.path.abspath(
os.path.join(os.path.dirname(__file__), os.pardir)
)
@@ -93,8 +94,6 @@ def bash(request) -> pexpect.spawn:
PS1=PS1,
INPUTRC="%s/config/inputrc" % testdir,
TERM="dumb",
- BASH_COMPLETION_COMPAT_DIR="%s/fixtures/shared/empty_dir"
- % testdir,
LC_COLLATE="C", # to match Python's default locale unaware sort
)
)
@@ -123,7 +122,7 @@ def bash(request) -> pexpect.spawn:
assert_bash_exec(bash, "source '%s/../bash_completion'" % testdir)
# Use command name from marker if set, or grab from test filename
- cmd = None
+ cmd = None # type: Optional[str]
cmd_found = False
marker = request.node.get_closest_marker("bashcomp")
if marker:
@@ -132,7 +131,7 @@ def bash(request) -> pexpect.spawn:
# Run pre-test commands, early so they're usable in skipif
for pre_cmd in marker.kwargs.get("pre_cmds", []):
assert_bash_exec(bash, pre_cmd)
- # Process skip conditions
+ # Process skip and xfail conditions
skipif = marker.kwargs.get("skipif")
if skipif:
try:
@@ -142,7 +141,14 @@ def bash(request) -> pexpect.spawn:
else:
bash.close()
pytest.skip(skipif)
- return
+ xfail = marker.kwargs.get("xfail")
+ if xfail:
+ try:
+ assert_bash_exec(bash, xfail)
+ except AssertionError:
+ pass
+ else:
+ pytest.xfail(xfail)
if not cmd_found:
match = re.search(
r"^test_(.+)\.py$", os.path.basename(str(request.fspath))
@@ -150,6 +156,8 @@ def bash(request) -> pexpect.spawn:
if match:
cmd = match.group(1)
+ request.cls.cmd = cmd
+
if (cmd_found and cmd is None) or is_testable(bash, cmd):
before_env = get_env(bash)
yield bash
@@ -178,16 +186,14 @@ def is_testable(bash: pexpect.spawn, cmd: str) -> bool:
if not cmd:
pytest.fail("Could not resolve name of command to test")
return False
- if not is_bash_type(bash, cmd):
- pytest.skip("Command %s not found" % cmd)
- return False
if not load_completion_for(bash, cmd):
pytest.skip("No completion for command %s" % cmd)
- return False
return True
-def is_bash_type(bash: pexpect.spawn, cmd: str) -> bool:
+def is_bash_type(bash: pexpect.spawn, cmd: Optional[str]) -> bool:
+ if not cmd:
+ return False
typecmd = "type %s &>/dev/null && echo -n 0 || echo -n 1" % cmd
bash.sendline(typecmd)
bash.expect_exact(typecmd + "\r\n")
@@ -208,7 +214,7 @@ def load_completion_for(bash: pexpect.spawn, cmd: str) -> bool:
def assert_bash_exec(
- bash: pexpect.spawn, cmd: str, want_output: bool = False
+ bash: pexpect.spawn, cmd: str, want_output: bool = False, want_newline=True
) -> str:
# Send command
@@ -216,7 +222,7 @@ def assert_bash_exec(
bash.expect_exact(cmd)
# Find prompt, output is before it
- bash.expect_exact("\r\n" + PS1)
+ bash.expect_exact("%s%s" % ("\r\n" if want_newline else "", PS1))
output = bash.before
# Retrieve exit status
@@ -318,7 +324,7 @@ class CompletionResult:
Defining __eq__ this way is quite ugly, but facilitates concise
testing code.
"""
- expiter = [expected] if isinstance(expected, str) else sorted(expected)
+ expiter = [expected] if isinstance(expected, str) else expected
if self._items is not None:
return self._items == expiter
return bool(
@@ -370,7 +376,14 @@ def assert_complete(
pass
else:
pytest.skip(skipif)
- return CompletionResult("", [])
+ xfail = kwargs.get("xfail")
+ if xfail:
+ try:
+ assert_bash_exec(bash, xfail)
+ except AssertionError:
+ pass
+ else:
+ pytest.xfail(xfail)
cwd = kwargs.get("cwd")
if cwd:
assert_bash_exec(bash, "cd '%s'" % cwd)
@@ -441,11 +454,45 @@ def completion(request, bash: pexpect.spawn) -> CompletionResult:
return CompletionResult("", [])
for pre_cmd in marker.kwargs.get("pre_cmds", []):
assert_bash_exec(bash, pre_cmd)
+ cmd = getattr(request.cls, "cmd", None)
+ if marker.kwargs.get("require_longopt"):
+ # longopt completions require both command presence and that it
+ # responds something useful to --help
+ if "require_cmd" not in marker.kwargs:
+ marker.kwargs["require_cmd"] = True
+ if "xfail" not in marker.kwargs:
+ marker.kwargs["xfail"] = (
+ "! %s --help &>/dev/null || "
+ "! %s --help 2>&1 | command grep -qF -- --help"
+ ) % ((cmd,) * 2)
+ if marker.kwargs.get("require_cmd") and not is_bash_type(bash, cmd):
+ pytest.skip("Command not found")
return assert_complete(bash, marker.args[0], **marker.kwargs)
-def in_docker() -> bool:
- return os.path.exists("/.dockerenv")
+def in_container() -> bool:
+ try:
+ container = subprocess.check_output(
+ "virt-what || systemd-detect-virt --container",
+ stderr=subprocess.DEVNULL,
+ shell=True,
+ ).strip()
+ except subprocess.CalledProcessError:
+ container = b""
+ if container and container != b"none":
+ return True
+ if os.path.exists("/.dockerenv"):
+ return True
+ try:
+ with open("/proc/1/environ", "rb") as f:
+ # LXC, others?
+ if any(
+ x.startswith(b"container=") for x in f.readline().split(b"\0")
+ ):
+ return True
+ except OSError:
+ pass
+ return False
class TestUnitBase: