Skip to content

Commit

Permalink
fix: Generation of invalid headers in some cases
Browse files Browse the repository at this point in the history
Ref: #1142
  • Loading branch information
Stranger6667 committed Oct 26, 2021
1 parent 5684c82 commit 05ef0ea
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 9 deletions.
2 changes: 2 additions & 0 deletions docs/changelog.rst
Expand Up @@ -13,6 +13,7 @@ Changelog
**Fixed**

- Pass ``data_generation_method`` to ``Case`` for GraphQL schemas.
- Generation of invalid headers in some cases. `#1142`_

`3.10.1`_ - 2021-10-04
----------------------
Expand Down Expand Up @@ -2183,6 +2184,7 @@ Deprecated
.. _#1160: https://github.com/schemathesis/schemathesis/issues/1160
.. _#1153: https://github.com/schemathesis/schemathesis/issues/1153
.. _#1152: https://github.com/schemathesis/schemathesis/issues/1152
.. _#1142: https://github.com/schemathesis/schemathesis/issues/1142
.. _#1134: https://github.com/schemathesis/schemathesis/issues/1134
.. _#1121: https://github.com/schemathesis/schemathesis/issues/1121
.. _#1100: https://github.com/schemathesis/schemathesis/issues/1100
Expand Down
10 changes: 4 additions & 6 deletions src/schemathesis/specs/openapi/_hypothesis.py
Expand Up @@ -279,7 +279,7 @@ def get_parameters_strategy(
"query": is_valid_query,
}[location]
# Headers with special format do not need filtration
if not (is_header_location(location) and _has_header_format(schema)):
if not (is_header_location(location) and _can_skip_header_filter(schema)):
strategy = strategy.filter(filter_func)
# Path & query parameters will be cast to string anyway, but having their JSON equivalents for
# `True` / `False` / `None` improves chances of them passing validation in apps that expect boolean / null types
Expand Down Expand Up @@ -328,11 +328,9 @@ def make_positive_strategy(
return from_schema(schema, custom_formats=STRING_FORMATS)


def _has_header_format(schema: Dict[str, Any]) -> bool:
for sub_schema in schema.get("properties", {}).values():
if sub_schema.get("format") == HEADER_FORMAT:
return True
return False
def _can_skip_header_filter(schema: Dict[str, Any]) -> bool:
# All headers should contain HEADER_FORMAT in order to avoid header filter
return all(sub_schema.get("format") == HEADER_FORMAT for sub_schema in schema.get("properties", {}).values())


def make_negative_strategy(
Expand Down
44 changes: 41 additions & 3 deletions test/specs/openapi/test_hypothesis.py
Expand Up @@ -284,9 +284,8 @@ def test_header_filtration_not_needed(empty_open_api_3_schema, mocker):
schema = schemathesis.from_dict(empty_open_api_3_schema)

@given(schema["/data"]["GET"].as_strategy())
@settings(max_examples=1)
def test(_):
pass
def test(case):
assert is_valid_header(case.headers)

test()

Expand All @@ -312,6 +311,45 @@ def test(_):
mocked.assert_called()


def test_missing_header_filter(empty_open_api_3_schema, mocker):
# Regression. See GH-1142
mocked = mocker.spy(_hypothesis, "is_valid_header")
# When some header parameters have the `format` keyword
# And some don't
empty_open_api_3_schema["paths"] = {
"/data": {
"get": {
"parameters": [
{
"name": "key1",
"in": "header",
"required": True,
"schema": {"type": "string", "format": "uuid"},
},
{
"name": "key2",
"in": "header",
"required": True,
"schema": {"type": "string"},
},
],
"responses": {"200": {"description": "OK"}},
}
}
}

schema = schemathesis.from_dict(empty_open_api_3_schema)

@given(schema["/data"]["GET"].as_strategy())
def test(case):
assert is_valid_header(case.headers)

test()

# Then header filter should be used
mocked.assert_called()


@pytest.mark.parametrize(
"value, expected",
(
Expand Down

0 comments on commit 05ef0ea

Please sign in to comment.