summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorMasen Furer <m_github@0x26.net>2023-01-15 20:45:17 -0800
committerGitHub <noreply@github.com>2023-01-15 20:45:17 -0800
commit99b849baca40ca97d7af87ceeb5659edb99f0882 (patch)
tree7cdc141dd887734d75775c4bded04539a30209b4 /tests
parent6fe280aa2677f2760da0d9f59907ec27983cfd99 (diff)
downloadtox-git-99b849baca40ca97d7af87ceeb5659edb99f0882.tar.gz
Recursive replace (#2864)
* test_replace_tox_env: add missing chain cases When a replacement references a replacement in a non-testenv section it should also be expanded * Recursive ini-value substitution Expand substitution expressions that result from a previous subsitution expression replacement value (up to 100 times). Fix #2863 * cr: changelog: fix trailing period * test_replace_tox_env: tests for MAX_REPLACE_DEPTH Create a long chain of substitution values and assert that they stop being processed after some time.
Diffstat (limited to 'tests')
-rw-r--r--tests/config/loader/ini/replace/test_replace_env_var.py2
-rw-r--r--tests/config/loader/ini/replace/test_replace_tox_env.py43
-rw-r--r--tests/config/test_set_env.py2
3 files changed, 45 insertions, 2 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 c9f26400..d2e9fa58 100644
--- a/tests/config/loader/ini/replace/test_replace_env_var.py
+++ b/tests/config/loader/ini/replace/test_replace_env_var.py
@@ -102,7 +102,7 @@ def test_replace_env_var_circular_flip_flop(replace_one: ReplaceOne, monkeypatch
monkeypatch.setenv("TRAGIC", "{env:MAGIC}")
monkeypatch.setenv("MAGIC", "{env:TRAGIC}")
result = replace_one("{env:MAGIC}")
- assert result == "{env:TRAGIC}"
+ assert result == "{env:MAGIC}"
@pytest.mark.parametrize("fallback", [True, False])
diff --git a/tests/config/loader/ini/replace/test_replace_tox_env.py b/tests/config/loader/ini/replace/test_replace_tox_env.py
index 284d6c7c..f7e84fde 100644
--- a/tests/config/loader/ini/replace/test_replace_tox_env.py
+++ b/tests/config/loader/ini/replace/test_replace_tox_env.py
@@ -7,7 +7,9 @@ import pytest
from tests.config.loader.ini.replace.conftest import ReplaceOne
from tests.conftest import ToxIniCreator
+from tox.config.loader.ini.replace import MAX_REPLACE_DEPTH
from tox.config.sets import ConfigSet
+from tox.pytest import LogCaptureFixture
from tox.report import HandledError
EnvConfigCreator = Callable[[str], ConfigSet]
@@ -31,6 +33,47 @@ def test_replace_within_tox_env(example: EnvConfigCreator) -> None:
assert result == "1"
+def test_replace_within_tox_env_chain(example: EnvConfigCreator) -> None:
+ env_config = example("r = 1\no = {r}/2\np = {r} {o}")
+ env_config.add_config(keys="r", of_type=str, default="r", desc="r")
+ env_config.add_config(keys="o", of_type=str, default="o", desc="o")
+ env_config.add_config(keys="p", of_type=str, default="p", desc="p")
+ result = env_config["p"]
+ assert result == "1 1/2"
+
+
+def test_replace_within_section_chain(tox_ini_conf: ToxIniCreator) -> None:
+ config = tox_ini_conf("[vars]\na = 1\nb = {[vars]a}/2\nc = {[vars]a}/3\n[testenv:a]\nd = {[vars]b} {[vars]c}")
+ env_config = config.get_env("a")
+ env_config.add_config(keys="d", of_type=str, default="d", desc="d")
+ result = env_config["d"]
+ assert result == "1/2 1/3"
+
+
+@pytest.mark.parametrize("depth", [5, 99, 100, 101, 150, 256])
+def test_replace_within_section_chain_deep(caplog: LogCaptureFixture, tox_ini_conf: ToxIniCreator, depth: int) -> None:
+ config = tox_ini_conf(
+ "\n".join(
+ [
+ "[vars]",
+ "a0 = 1",
+ *(f"a{ix} = {{[vars]a{ix - 1}}}" for ix in range(1, depth + 1)),
+ "[testenv:a]",
+ "b = {[vars]a%s}" % depth,
+ ],
+ ),
+ )
+ env_config = config.get_env("a")
+ env_config.add_config(keys="b", of_type=str, default="b", desc="b")
+ result = env_config["b"]
+ if depth > MAX_REPLACE_DEPTH:
+ exp_stopped_at = "{[vars]a%s}" % (depth - MAX_REPLACE_DEPTH - 1)
+ assert result == exp_stopped_at
+ assert f"Could not expand {exp_stopped_at} after recursing {MAX_REPLACE_DEPTH + 1} frames" in caplog.messages
+ else:
+ assert result == "1"
+
+
def test_replace_within_tox_env_missing_raises(example: EnvConfigCreator) -> None:
env_config = example("o = {p}")
env_config.add_config(keys="o", of_type=str, default="o", desc="o")
diff --git a/tests/config/test_set_env.py b/tests/config/test_set_env.py
index 453d73ae..ae12a5b8 100644
--- a/tests/config/test_set_env.py
+++ b/tests/config/test_set_env.py
@@ -108,7 +108,7 @@ def test_set_env_circular_use_os_environ(tox_project: ToxProjectCreator) -> None
prj = tox_project({"tox.ini": "[testenv]\npackage=skip\nset_env=a={env:b}\n b={env:a}"})
result = prj.run("c", "-e", "py")
result.assert_success()
- assert "replace failed in py.set_env with ValueError" in result.out, result.out
+ assert "replace failed in py.set_env with MatchRecursionError" in result.out, result.out
assert "circular chain between set env a, b" in result.out, result.out