|
| 1 | +"""Test the consume plugins with various cli arguments.""" |
| 2 | + |
| 3 | +import re |
| 4 | +import shutil |
| 5 | +from pathlib import Path |
| 6 | +from typing import List |
| 7 | + |
| 8 | +import pytest |
| 9 | +from click.testing import CliRunner |
| 10 | +from pytest import Pytester, TempPathFactory |
| 11 | + |
| 12 | +from cli.pytest_commands.fill import fill |
| 13 | + |
| 14 | + |
| 15 | +@pytest.fixture(scope="module") |
| 16 | +def test_paths() -> list[Path]: |
| 17 | + """Specify the test paths to be filled.""" |
| 18 | + return [ |
| 19 | + Path("tests/istanbul/eip1344_chainid/test_chainid.py"), |
| 20 | + ] |
| 21 | + |
| 22 | + |
| 23 | +@pytest.fixture(scope="module") |
| 24 | +def consume_test_case_ids() -> list[str]: |
| 25 | + """Hard-coded expected output of `consume direct --collectonly -q`.""" |
| 26 | + return [ |
| 27 | + "src/pytest_plugins/consume/direct/test_via_direct.py::test_fixture[CollectOnlyFixtureConsumer-tests/istanbul/eip1344_chainid/test_chainid.py::test_chainid[fork_Cancun-blockchain_test_from_state_test]]", |
| 28 | + "src/pytest_plugins/consume/direct/test_via_direct.py::test_fixture[CollectOnlyFixtureConsumer-tests/istanbul/eip1344_chainid/test_chainid.py::test_chainid[fork_Paris-blockchain_test_from_state_test]]", |
| 29 | + "src/pytest_plugins/consume/direct/test_via_direct.py::test_fixture[CollectOnlyFixtureConsumer-tests/istanbul/eip1344_chainid/test_chainid.py::test_chainid[fork_Shanghai-blockchain_test_from_state_test]]", |
| 30 | + "src/pytest_plugins/consume/direct/test_via_direct.py::test_fixture[CollectOnlyFixtureConsumer-tests/istanbul/eip1344_chainid/test_chainid.py::test_chainid[fork_Cancun-state_test]]", |
| 31 | + "src/pytest_plugins/consume/direct/test_via_direct.py::test_fixture[CollectOnlyFixtureConsumer-tests/istanbul/eip1344_chainid/test_chainid.py::test_chainid[fork_Paris-state_test]]", |
| 32 | + "src/pytest_plugins/consume/direct/test_via_direct.py::test_fixture[CollectOnlyFixtureConsumer-tests/istanbul/eip1344_chainid/test_chainid.py::test_chainid[fork_Shanghai-state_test]]", |
| 33 | + ] |
| 34 | + |
| 35 | + |
| 36 | +@pytest.fixture(scope="module") |
| 37 | +def fill_fork_from() -> str: |
| 38 | + """Specify the value for `fill`'s `--from` argument.""" |
| 39 | + return "Paris" |
| 40 | + |
| 41 | + |
| 42 | +@pytest.fixture(scope="module") |
| 43 | +def fill_fork_until() -> str: |
| 44 | + """Specify the value for `fill`'s `--until` argument.""" |
| 45 | + return "Cancun" |
| 46 | + |
| 47 | + |
| 48 | +@pytest.fixture(scope="module") |
| 49 | +def fixtures_dir(tmp_path_factory: TempPathFactory) -> Path: |
| 50 | + """Define the temporary test fixture directory for fill output.""" |
| 51 | + return tmp_path_factory.mktemp("fixtures") |
| 52 | + |
| 53 | + |
| 54 | +@pytest.fixture(autouse=True, scope="module") |
| 55 | +def fill_tests( |
| 56 | + fixtures_dir: Path, fill_fork_from: str, fill_fork_until: str, test_paths: List[Path] |
| 57 | +) -> None: |
| 58 | + """Run fill to generate test fixtures for use with testing consume.""" |
| 59 | + fill_result = CliRunner().invoke( |
| 60 | + fill, |
| 61 | + [ |
| 62 | + "-c", |
| 63 | + "pytest.ini", |
| 64 | + "--skip-evm-dump", |
| 65 | + "-m", |
| 66 | + "(not blockchain_test_engine) and (not eip_version_check)", |
| 67 | + f"--from={fill_fork_from}", |
| 68 | + f"--until={fill_fork_until}", |
| 69 | + f"--output={str(fixtures_dir)}", |
| 70 | + *[str(p) for p in test_paths], |
| 71 | + # if we fill many tests, it might help to add -n 8/auto |
| 72 | + ], |
| 73 | + ) |
| 74 | + assert fill_result.exit_code == 0, f"Fill command failed:\n{fill_result.output}" |
| 75 | + |
| 76 | + |
| 77 | +@pytest.fixture(autouse=True, scope="function") |
| 78 | +def test_fixtures(pytester: Pytester, fixtures_dir: Path, fill_tests: None) -> List[Path]: |
| 79 | + """ |
| 80 | + Copy test fixtures from the regular temp path to the pytester temporary dir. |
| 81 | +
|
| 82 | + We intentionally copy the `.meta/index.json` file to test its compatibility with consume. |
| 83 | + """ |
| 84 | + test_fixtures = [] |
| 85 | + for json_file in fixtures_dir.rglob("*.json"): |
| 86 | + target_dir = Path(pytester.path) / json_file.parent |
| 87 | + if not target_dir.exists(): |
| 88 | + target_dir.mkdir(parents=True) |
| 89 | + pytester.copy_example(name=json_file.as_posix()) |
| 90 | + shutil.move(json_file.name, target_dir / json_file.name) |
| 91 | + if ".meta" not in str(json_file): |
| 92 | + test_fixtures.append(json_file) |
| 93 | + return test_fixtures |
| 94 | + |
| 95 | + |
| 96 | +@pytest.fixture(autouse=True) |
| 97 | +def copy_consume_test_paths(pytester: Pytester): |
| 98 | + """Specify and copy the consume test paths to the testdir.""" |
| 99 | + local_test_paths = [Path("src/pytest_plugins/consume/direct/test_via_direct.py")] |
| 100 | + for test_path in local_test_paths: |
| 101 | + target_dir = Path(pytester.path) / test_path.parent |
| 102 | + target_dir.mkdir(parents=True, exist_ok=True) |
| 103 | + pytester.copy_example(name=str(test_path)) |
| 104 | + pytester.copy_example(name=str(test_path.parent / "conftest.py")) |
| 105 | + shutil.move(test_path.name, target_dir / test_path.name) |
| 106 | + shutil.move("conftest.py", target_dir / "conftest.py") |
| 107 | + |
| 108 | + |
| 109 | +single_test_id = "src/pytest_plugins/consume/direct/test_via_direct.py::test_fixture[CollectOnlyFixtureConsumer-tests/istanbul/eip1344_chainid/test_chainid.py::test_chainid[fork_Shanghai-state_test]]" # noqa: E501 |
| 110 | + |
| 111 | + |
| 112 | +@pytest.mark.parametrize( |
| 113 | + "extra_args, expected_filter_pattern", |
| 114 | + [ |
| 115 | + pytest.param( |
| 116 | + ["--collect-only", "-q"], |
| 117 | + re.compile(r".*"), |
| 118 | + id="no_extra_args", |
| 119 | + ), |
| 120 | + pytest.param( |
| 121 | + ["--collect-only", "-q", "--sim.limit", ".*fork_Cancun.*"], |
| 122 | + re.compile(".*Cancun.*"), |
| 123 | + id="sim_limit_regex", |
| 124 | + ), |
| 125 | + pytest.param( |
| 126 | + ["--sim.limit", "collectonly:.*fork_Cancun.*"], |
| 127 | + re.compile(".*Cancun.*"), |
| 128 | + id="sim_limit_collect_only_regex", |
| 129 | + ), |
| 130 | + pytest.param( |
| 131 | + [ |
| 132 | + "--collect-only", |
| 133 | + "-q", |
| 134 | + "--sim.limit", |
| 135 | + f"id:{single_test_id}", |
| 136 | + ], |
| 137 | + re.compile(re.escape(f"{single_test_id}")), |
| 138 | + id="sim_limit_id", |
| 139 | + ), |
| 140 | + pytest.param( |
| 141 | + [ |
| 142 | + "--sim.limit", |
| 143 | + f"collectonly:id:{single_test_id}", |
| 144 | + ], |
| 145 | + re.compile( |
| 146 | + re.compile(re.escape(f"{single_test_id}")), |
| 147 | + ), |
| 148 | + id="sim_limit_collect_only_id", |
| 149 | + ), |
| 150 | + ], |
| 151 | +) |
| 152 | +def test_consume_simlimit_collectonly( |
| 153 | + pytester: Pytester, |
| 154 | + fixtures_dir: Path, |
| 155 | + consume_test_case_ids: List[str], |
| 156 | + extra_args: List[str], |
| 157 | + expected_filter_pattern: re.Pattern, |
| 158 | +) -> None: |
| 159 | + """Test consume's --sim.limit argument in collect-only mode.""" |
| 160 | + ini_file = "pytest-consume.ini" |
| 161 | + pytester.copy_example(name=ini_file) |
| 162 | + consume_test_path = "src/pytest_plugins/consume/direct/test_via_direct.py" |
| 163 | + args = [ |
| 164 | + "-c", |
| 165 | + ini_file, |
| 166 | + "--input", |
| 167 | + str(fixtures_dir), |
| 168 | + consume_test_path, |
| 169 | + *extra_args, |
| 170 | + ] |
| 171 | + result = pytester.runpytest(*args) |
| 172 | + assert result.ret == 0 |
| 173 | + stdout_lines = str(result.stdout).splitlines() |
| 174 | + collected_test_ids = [ |
| 175 | + line |
| 176 | + for line in stdout_lines |
| 177 | + if line.strip() |
| 178 | + and "tests collected in" not in line |
| 179 | + and "pytest-regex selected" not in line |
| 180 | + ] |
| 181 | + expected_collected_test_ids = [ |
| 182 | + line for line in consume_test_case_ids if expected_filter_pattern.search(line) |
| 183 | + ] |
| 184 | + assert set(collected_test_ids) == set(expected_collected_test_ids) |
0 commit comments