Skip to content

Commit 291088b

Browse files
committed
Move fuzzing tests into separate files
These tests will only run with the --run-slow option. Replicates graphql/graphql-js@8a0346f
1 parent 794e733 commit 291088b

10 files changed

+140
-69
lines changed

.coveragerc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
branch = True
33
source = src
44
omit =
5+
*/conftest.py
56
*/cached_property.py
67
*/is_collection.py
8+
*/test_*_fuzz.py
79

810
[report]
911
exclude_lines =

poetry.lock

Lines changed: 16 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ pytest-asyncio = ">=0.14,<1"
3737
pytest-benchmark = "^3.2"
3838
pytest-cov = "^2.10"
3939
pytest-describe = "^1.0"
40+
pytest-timeout = "^1.4"
4041
black = "19.10b0"
4142
flake8 = "^3.8"
4243
mypy = "0.782"

setup.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ test = pytest
77
[tool:pytest]
88
# Only run benchmarks as tests.
99
# To actually run the benchmarks, use --benchmark-enable on the command line.
10+
# To run the slow tests (fuzzing), add --run-slow on the command line.
1011
addopts = --benchmark-disable
12+
timeout = 100

tests/conftest.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# pytest configuration
2+
3+
import pytest # type: ignore
4+
5+
6+
def pytest_addoption(parser):
7+
parser.addoption(
8+
"--run-slow", action="store_true", default=False, help="run slow tests"
9+
)
10+
11+
12+
def pytest_configure(config):
13+
config.addinivalue_line("markers", "slow: mark test as slow to run")
14+
15+
16+
def pytest_collection_modifyitems(config, items):
17+
if not config.getoption("--run-slow"):
18+
# without --run-slow option: skip all slow tests
19+
skip_slow = pytest.mark.skip(reason="need --run-slow option to run")
20+
for item in items:
21+
if "slow" in item.keywords:
22+
item.add_marker(skip_slow)

tests/language/test_block_string.py

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,9 @@
1-
from typing import Optional
2-
3-
from graphql.error import GraphQLSyntaxError
4-
from graphql.language import Source, Lexer, TokenKind
51
from graphql.language.block_string import (
62
dedent_block_string_value,
73
print_block_string,
84
get_block_string_indentation,
95
)
106

11-
from ..utils import dedent, gen_fuzz_strings
12-
137

148
def join_lines(*args):
159
return "\n".join(args)
@@ -138,43 +132,3 @@ def correctly_prints_string_with_a_first_line_indentation():
138132
assert print_block_string(s) == join_lines(
139133
'"""', " first ", " line ", "indentation", " string", '"""'
140134
)
141-
142-
def correctly_print_random_strings():
143-
def lex_value(s: str) -> Optional[str]:
144-
lexer = Lexer(Source(s))
145-
value = lexer.advance().value
146-
assert lexer.advance().kind == TokenKind.EOF, "Expected EOF"
147-
return value
148-
149-
# Testing with length >5 is taking exponentially more time. However it is
150-
# highly recommended to test with increased limit if you make any change.
151-
for fuzz_str in gen_fuzz_strings(allowed_chars='\n\t "a\\', max_length=5):
152-
test_str = f'"""{fuzz_str}"""'
153-
154-
try:
155-
test_value = lex_value(test_str)
156-
except (AssertionError, GraphQLSyntaxError):
157-
continue # skip invalid values
158-
assert isinstance(test_value, str)
159-
160-
printed_value = lex_value(print_block_string(test_value))
161-
162-
assert test_value == printed_value, dedent(
163-
f"""
164-
Expected lex_value(print_block_string({test_value!r})
165-
to equal {test_value!r}
166-
but got {printed_value!r}
167-
"""
168-
)
169-
170-
printed_multiline_string = lex_value(
171-
print_block_string(test_value, " ", True)
172-
)
173-
174-
assert test_value == printed_multiline_string, dedent(
175-
f"""
176-
Expected lex_value(print_block_string({test_value!r}, ' ', True)
177-
to equal {test_value!r}
178-
but got {printed_multiline_string!r}
179-
"""
180-
)
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from typing import Optional
2+
3+
from pytest import mark # type: ignore
4+
5+
from graphql.error import GraphQLSyntaxError
6+
from graphql.language import Source, Lexer, TokenKind
7+
from graphql.language.block_string import print_block_string
8+
9+
from ..utils import dedent, gen_fuzz_strings
10+
11+
12+
def lex_value(s: str) -> Optional[str]:
13+
lexer = Lexer(Source(s))
14+
value = lexer.advance().value
15+
assert lexer.advance().kind == TokenKind.EOF, "Expected EOF"
16+
return value
17+
18+
19+
def describe_print_block_string():
20+
@mark.slow
21+
@mark.timeout(20)
22+
def correctly_print_random_strings():
23+
# Testing with length >7 is taking exponentially more time. However it is
24+
# highly recommended to test with increased limit if you make any change.
25+
for fuzz_str in gen_fuzz_strings(allowed_chars='\n\t "a\\', max_length=7):
26+
test_str = f'"""{fuzz_str}"""'
27+
28+
try:
29+
test_value = lex_value(test_str)
30+
except (AssertionError, GraphQLSyntaxError):
31+
continue # skip invalid values
32+
assert isinstance(test_value, str)
33+
34+
printed_value = lex_value(print_block_string(test_value))
35+
36+
assert test_value == printed_value, dedent(
37+
f"""
38+
Expected lex_value(print_block_string({test_value!r})
39+
to equal {test_value!r}
40+
but got {printed_value!r}
41+
"""
42+
)
43+
44+
printed_multiline_string = lex_value(
45+
print_block_string(test_value, " ", True)
46+
)
47+
48+
assert test_value == printed_multiline_string, dedent(
49+
f"""
50+
Expected lex_value(print_block_string({test_value!r}, ' ', True)
51+
to equal {test_value!r}
52+
but got {printed_multiline_string!r}
53+
"""
54+
)

tests/utilities/test_strip_ignored_characters.py

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from graphql.utilities import strip_ignored_characters
99

1010
from ..fixtures import kitchen_sink_query, kitchen_sink_sdl # noqa: F401
11-
from ..utils import dedent, gen_fuzz_strings
11+
from ..utils import dedent
1212

1313
ignored_tokens = [
1414
# UnicodeBOM
@@ -374,27 +374,6 @@ def expect_stripped_string(block_str: str):
374374
expect_stripped_string('"""\n a\n b"""').to_equal('"""a\nb"""')
375375
expect_stripped_string('"""\na\n b\nc"""').to_equal('"""a\n b\nc"""')
376376

377-
def strips_ignored_characters_inside_random_block_strings():
378-
# Testing with length >5 is taking exponentially more time. However it is
379-
# highly recommended to test with increased limit if you make any change.
380-
for fuzz_str in gen_fuzz_strings(allowed_chars='\n\t "a\\', max_length=5):
381-
test_str = f'"""{fuzz_str}"""'
382-
383-
try:
384-
test_value = lex_value(test_str)
385-
except (AssertionError, GraphQLSyntaxError):
386-
continue # skip invalid values
387-
388-
stripped_value = lex_value(strip_ignored_characters(test_str))
389-
390-
assert test_value == stripped_value, dedent(
391-
f"""
392-
Expected lexValue(stripIgnoredCharacters({test_str!r})
393-
to equal {test_value!r}
394-
but got {stripped_value!r}
395-
"""
396-
)
397-
398377
# noinspection PyShadowingNames
399378
def strips_kitchen_sink_query_but_maintains_the_exact_same_ast(
400379
kitchen_sink_query, # noqa: F811
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from typing import Optional
2+
3+
from pytest import mark # type: ignore
4+
5+
from graphql.error import GraphQLSyntaxError
6+
from graphql.language import Lexer, Source, TokenKind
7+
from graphql.utilities import strip_ignored_characters
8+
9+
from ..utils import dedent, gen_fuzz_strings
10+
11+
12+
def lex_value(s: str) -> Optional[str]:
13+
lexer = Lexer(Source(s))
14+
value = lexer.advance().value
15+
assert lexer.advance().kind == TokenKind.EOF, "Expected EOF"
16+
return value
17+
18+
19+
def describe_strip_ignored_characters():
20+
@mark.slow
21+
@mark.timeout(20)
22+
def strips_ignored_characters_inside_random_block_strings():
23+
# Testing with length >7 is taking exponentially more time. However it is
24+
# highly recommended to test with increased limit if you make any change.
25+
for fuzz_str in gen_fuzz_strings(allowed_chars='\n\t "a\\', max_length=7):
26+
test_str = f'"""{fuzz_str}"""'
27+
28+
try:
29+
test_value = lex_value(test_str)
30+
except (AssertionError, GraphQLSyntaxError):
31+
continue # skip invalid values
32+
33+
stripped_value = lex_value(strip_ignored_characters(test_str))
34+
35+
assert test_value == stripped_value, dedent(
36+
f"""
37+
Expected lexValue(stripIgnoredCharacters({test_str!r})
38+
to equal {test_value!r}
39+
but got {stripped_value!r}
40+
"""
41+
)

tox.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ deps =
4444
pytest-benchmark>=3.2,<4
4545
pytest-cov>=2.10,<3
4646
pytest-describe>=1,<2
47+
pytest-timeout>=1.4,<2
4748
commands =
4849
poetry install
4950
poetry run pytest tests {posargs: --cov-report=term-missing --cov=graphql --cov=tests --cov-fail-under=100}

0 commit comments

Comments
 (0)