summaryrefslogtreecommitdiff
path: root/tests/config/loader
diff options
context:
space:
mode:
Diffstat (limited to 'tests/config/loader')
-rw-r--r--tests/config/loader/ini/replace/test_replace_env_var.py14
-rw-r--r--tests/config/loader/test_str_convert.py126
2 files changed, 133 insertions, 7 deletions
diff --git a/tests/config/loader/ini/replace/test_replace_env_var.py b/tests/config/loader/ini/replace/test_replace_env_var.py
index 54438b0d..c5aca717 100644
--- a/tests/config/loader/ini/replace/test_replace_env_var.py
+++ b/tests/config/loader/ini/replace/test_replace_env_var.py
@@ -17,24 +17,24 @@ def test_replace_env_set(replace_one: ReplaceOne, monkeypatch: MonkeyPatch) -> N
def test_replace_env_set_double_bs(replace_one: ReplaceOne, monkeypatch: MonkeyPatch) -> None:
- """Double backslash should escape to single backslash and not affect surrounding replacements."""
+ """Double backslash should remain but not affect surrounding replacements."""
monkeypatch.setenv("MAGIC", "something good")
result = replace_one(r"{env:MAGIC}\\{env:MAGIC}")
- assert result == r"something good\something good"
+ assert result == r"something good\\something good"
def test_replace_env_set_triple_bs(replace_one: ReplaceOne, monkeypatch: MonkeyPatch) -> None:
- """Triple backslash should escape to single backslash also escape subsequent replacement."""
+ """Triple backslash should retain two slashes with the third escaping subsequent replacement."""
monkeypatch.setenv("MAGIC", "something good")
result = replace_one(r"{env:MAGIC}\\\{env:MAGIC}")
- assert result == r"something good\{env:MAGIC}"
+ assert result == r"something good\\{env:MAGIC}"
def test_replace_env_set_quad_bs(replace_one: ReplaceOne, monkeypatch: MonkeyPatch) -> None:
- """Quad backslash should escape to two backslashes and not affect surrounding replacements."""
+ """Quad backslash should remain but not affect surrounding replacements."""
monkeypatch.setenv("MAGIC", "something good")
- result = replace_one(r"\\{env:MAGIC}\\\\{env:MAGIC}\\")
- assert result == r"\something good\\something good" + "\\"
+ result = replace_one(r"\\{env:MAGIC}\\\\{env:MAGIC}" + "\\")
+ assert result == r"\\something good\\\\something good" + "\\"
def test_replace_env_when_value_is_backslash(replace_one: ReplaceOne, monkeypatch: MonkeyPatch) -> None:
diff --git a/tests/config/loader/test_str_convert.py b/tests/config/loader/test_str_convert.py
index 4fe0aaff..1619056d 100644
--- a/tests/config/loader/test_str_convert.py
+++ b/tests/config/loader/test_str_convert.py
@@ -2,12 +2,14 @@ from __future__ import annotations
import sys
from pathlib import Path
+from textwrap import dedent
from typing import Any, Dict, List, Optional, Set, TypeVar, Union
import pytest
from tox.config.loader.str_convert import StrConvert
from tox.config.types import Command, EnvList
+from tox.pytest import MonkeyPatch, SubRequest, ToxProjectCreator
if sys.version_info >= (3, 8): # pragma: no cover (py38+)
from typing import Literal
@@ -80,3 +82,127 @@ def test_str_convert_nok(raw: str, of_type: type[Any], msg: str, exc_type: type[
def test_invalid_shell_expression(value: str, expected: list[str]) -> None:
result = StrConvert().to_command(value).args
assert result == expected
+
+
+SIMPLE_ARGS = [
+ ('foo "bar baz"', ["foo", "bar baz"]),
+ ('foo "bar baz"ext', ["foo", "bar bazext"]),
+ ('foo="bar baz"', ["foo=bar baz"]),
+ ("foo 'bar baz'", ["foo", "bar baz"]),
+ ("foo 'bar baz'ext", ["foo", "bar bazext"]),
+ ("foo='bar baz'", ["foo=bar baz"]),
+ (r"foo=\"bar baz\"", ['foo="bar', 'baz"']),
+ (r'foo="bar baz\"', ['foo="bar baz\\"']),
+ ("foo='bar baz' quuc", ["foo=bar baz", "quuc"]),
+ (r"foo='bar baz\' quuc", ["foo=bar baz\\", "quuc"]),
+ (r"foo=\"bar baz\' quuc", ['foo="bar', "baz'", "quuc"]),
+ (r"foo=\\\"bar baz\"", ['foo=\\"bar', 'baz"']),
+ (r'foo=\\"bar baz\"', [r'foo=\\"bar baz\"']),
+]
+NEWLINE_ARGS = [
+ ('foo\n"bar\nbaz"', ["foo", "bar\nbaz"]),
+]
+INI_CONFIG_NEWLINE_ARGS = [
+ ('foo\\\n "bar\\\n baz"', ["foobarbaz"]), # behavior change from tox 3
+ ('foo\\\n "bar \\\n baz"', ["foobar baz"]), # behavior change from tox 3
+ ('foo \\\n "bar\\\n baz"', ["foo", "barbaz"]),
+ ('foo \\\n "bar \\\n baz"', ["foo", "bar baz"]),
+ ('foo \\\n \\"bar \\\n baz"', ["foo", '"bar', 'baz"']),
+ ("foo \\\n bar \\\n baz", ["foo", "bar", "baz"]),
+]
+WINDOWS_PATH_ARGS = [
+ (r"SPECIAL:\foo\bar --quuz='baz atan'", [r"SPECIAL:\foo\bar", "--quuz=baz atan"]),
+ (r"X:\\foo\\bar --quuz='baz atan'", [r"X:\foo\bar", "--quuz=baz atan"]),
+ ("/foo/bar --quuz='baz atan'", ["/foo/bar", "--quuz=baz atan"]),
+ ('cc --arg "C:\\\\Users\\""', ["cc", "--arg", 'C:\\Users"']),
+ ('cc --arg "C:\\\\Users\\"', ["cc", "--arg", '"C:\\\\Users\\"']),
+ ('cc --arg "C:\\\\Users"', ["cc", "--arg", "C:\\Users"]),
+ ('cc --arg \\"C:\\\\Users"', ["cc", "--arg", '\\"C:\\\\Users"']),
+ ('cc --arg "C:\\\\Users\\ "', ["cc", "--arg", "C:\\Users\\ "]),
+ # ('cc --arg "C:\\\\Users\\ ', ["cc", "--arg", '"C:\\\\Users\\ ']),
+ ('cc --arg "C:\\\\Users\\\\"', ["cc", "--arg", "C:\\Users\\"]),
+ ('cc --arg "C:\\\\Users\\\\ "', ["cc", "--arg", "C:\\Users\\ "]),
+ # ('cc --arg "C:\\\\Users\\\\ ', ["cc", "--arg", '"C:\\\\Users\\\\ ']),
+ (
+ r'cc --arg C:\\Users\\ --arg2 "SPECIAL:\Temp\f o o" --arg3="\\FOO\share\Path name" --arg4 SPECIAL:\Temp\ '[:-1],
+ [
+ "cc",
+ "--arg",
+ "C:\\Users\\",
+ "--arg2",
+ "SPECIAL:\\Temp\\f o o",
+ "--arg3=\\FOO\\share\\Path name",
+ "--arg4",
+ "SPECIAL:\\Temp\\",
+ ],
+ ),
+]
+WACKY_SLASH_ARGS = [
+ ("\\\\\\", ["\\\\\\"]),
+ (" \\'\\'\\ '", [" \\'\\'\\ '"]),
+ ("\\'\\'\\ ", ["'' "]),
+ ("\\'\\ \\\\", ["' \\"]),
+ ("\\'\\ ", ["' "]),
+ ('''"\\'\\"''', ['"\\\'\\"']),
+ ("'\\' \\\\", ["\\", "\\"]),
+ ('"\\\\" \\\\', ["\\", "\\"]),
+]
+
+
+@pytest.fixture(params=["win32", "linux2"])
+def sys_platform(request: SubRequest, monkeypatch: MonkeyPatch) -> str:
+ monkeypatch.setattr(sys, "platform", request.param)
+ return str(request.param)
+
+
+@pytest.mark.parametrize(
+ ("value", "expected"),
+ [
+ *SIMPLE_ARGS,
+ *NEWLINE_ARGS,
+ *WINDOWS_PATH_ARGS,
+ *WACKY_SLASH_ARGS,
+ ],
+)
+def test_shlex_platform_specific(sys_platform: str, value: str, expected: list[str]) -> None:
+ if sys_platform != "win32" and value.startswith("SPECIAL:"):
+ # on non-windows platform, backslash is always an escape, not path separator
+ expected = [exp.replace("\\", "") for exp in expected]
+ result = StrConvert().to_command(value).args
+ assert result == expected
+
+
+@pytest.mark.parametrize(
+ ("value", "expected"),
+ [
+ *SIMPLE_ARGS,
+ *INI_CONFIG_NEWLINE_ARGS,
+ *WINDOWS_PATH_ARGS,
+ # *WACKY_SLASH_ARGS,
+ ],
+)
+def test_shlex_platform_specific_ini(
+ tox_project: ToxProjectCreator,
+ sys_platform: str,
+ value: str,
+ expected: list[str],
+) -> None:
+ if sys_platform != "win32" and value.startswith("SPECIAL:"):
+ # on non-windows platform, backslash is always an escape, not path separator
+ expected = [exp.replace("\\", "") for exp in expected]
+ project = tox_project(
+ {
+ "tox.ini": dedent(
+ """
+ [testenv]
+ commands =
+ %s""",
+ )
+ % value,
+ },
+ )
+ outcome = project.run("c")
+ outcome.assert_success()
+ env_config = outcome.env_conf("py")
+ result = env_config["commands"]
+ assert result == [Command(args=expected)]