diff --git a/docs/changelog.rst b/docs/changelog.rst index a7f7ef4da1..4fca65b2a4 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -6,6 +6,11 @@ Changelog `Unreleased`_ ------------- +Fixed +~~~~~ + +- Crash on invalid regular expressions in ``method``, ``endpoint`` and ``tag`` CLI options. `#403`_ + `0.24.1`_ - 2020-02-08 ---------------------- @@ -687,6 +692,7 @@ Fixed .. _0.3.0: https://github.com/kiwicom/schemathesis/compare/v0.2.0...v0.3.0 .. _0.2.0: https://github.com/kiwicom/schemathesis/compare/v0.1.0...v0.2.0 +.. _#403: https://github.com/kiwicom/schemathesis/issues/403 .. _#400: https://github.com/kiwicom/schemathesis/issues/400 .. _#394: https://github.com/kiwicom/schemathesis/issues/394 .. _#391: https://github.com/kiwicom/schemathesis/issues/391 diff --git a/src/schemathesis/cli/__init__.py b/src/schemathesis/cli/__init__.py index 34bf80b6e8..0bb351d233 100644 --- a/src/schemathesis/cli/__init__.py +++ b/src/schemathesis/cli/__init__.py @@ -77,9 +77,26 @@ def schemathesis(pre_run: Optional[str] = None) -> None: type=str, multiple=True, help=r"Filter schemathesis test by endpoint pattern. Example: users/\d+", + callback=callbacks.validate_regex, +) +@click.option( + "--method", + "-M", + "methods", + type=str, + multiple=True, + help="Filter schemathesis test by HTTP method.", + callback=callbacks.validate_regex, +) +@click.option( + "--tag", + "-T", + "tags", + type=str, + multiple=True, + help="Filter schemathesis test by schema tag pattern.", + callback=callbacks.validate_regex, ) -@click.option("--method", "-M", "methods", type=str, multiple=True, help="Filter schemathesis test by HTTP method.") -@click.option("--tag", "-T", "tags", type=str, multiple=True, help="Filter schemathesis test by schema tag pattern.") @click.option( "--workers", "-w", diff --git a/src/schemathesis/cli/callbacks.py b/src/schemathesis/cli/callbacks.py index 3353c90d0b..a5f7facd69 100644 --- a/src/schemathesis/cli/callbacks.py +++ b/src/schemathesis/cli/callbacks.py @@ -71,6 +71,17 @@ def validate_headers( return headers +def validate_regex(ctx: click.core.Context, param: click.core.Parameter, raw_value: Tuple[str, ...]) -> Tuple[str, ...]: + if not raw_value: + return raw_value + for value in raw_value: + try: + re.compile(value) + except re.error as exc: + raise click.BadParameter(f"Invalid regex: {exc.args[0]}") + return raw_value + + def convert_verbosity( ctx: click.core.Context, param: click.core.Parameter, value: Optional[str] ) -> Optional[hypothesis.Verbosity]: diff --git a/test/cli/test_callbacks.py b/test/cli/test_callbacks.py index cd8c6d344c..09a5799af5 100644 --- a/test/cli/test_callbacks.py +++ b/test/cli/test_callbacks.py @@ -46,3 +46,9 @@ def test_reraise_format_error(): with pytest.raises(click.BadParameter, match="Should be in KEY:VALUE format. Got: bla"): with callbacks.reraise_format_error("bla"): raise ValueError + + +@pytest.mark.parametrize("value", ("+", "\\", "[",)) +def test_validate_regex(value): + with pytest.raises(click.BadParameter, match="Invalid regex: "): + callbacks.validate_regex(None, None, (value,))