Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Tests/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,12 @@ def assert_tuple_approx_equal(
pytest.fail(msg + ": " + repr(actuals) + " != " + repr(targets))


def timeout_unless_slower_valgrind(timeout: float) -> pytest.MarkDecorator:
if "PILLOW_VALGRIND_TEST" in os.environ:
return pytest.mark.pil_noop_mark()
return pytest.mark.timeout(timeout)


def skip_unless_feature(feature: str) -> pytest.MarkDecorator:
reason = f"{feature} not available"
return pytest.mark.skipif(not features.check(feature), reason=reason)
Expand Down
6 changes: 2 additions & 4 deletions Tests/test_file_jpeg.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
is_win32,
mark_if_feature_version,
skip_unless_feature,
timeout_unless_slower_valgrind,
)

ElementTree: ModuleType | None
Expand Down Expand Up @@ -1033,10 +1034,7 @@ def test_save_xmp(self, tmp_path: Path) -> None:
with pytest.raises(ValueError):
im.save(f, xmp=b"1" * 65505)

@pytest.mark.timeout(timeout=1)
@pytest.mark.xfail(
"PILLOW_VALGRIND_TEST" in os.environ, reason="Valgrind is slower"
)
@timeout_unless_slower_valgrind(1)
def test_eof(self, monkeypatch: pytest.MonkeyPatch) -> None:
# Even though this decoder never says that it is finished
# the image should still end when there is no new data
Expand Down
10 changes: 7 additions & 3 deletions Tests/test_file_pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@

from PIL import Image, PdfParser, features

from .helper import hopper, mark_if_feature_version, skip_unless_feature
from .helper import (
hopper,
mark_if_feature_version,
skip_unless_feature,
timeout_unless_slower_valgrind,
)


def helper_save_as_pdf(tmp_path: Path, mode: str, **kwargs: Any) -> str:
Expand Down Expand Up @@ -339,8 +344,7 @@ def test_pdf_append_to_bytesio() -> None:
assert len(f.getvalue()) > initial_size


@pytest.mark.timeout(1)
@pytest.mark.skipif("PILLOW_VALGRIND_TEST" in os.environ, reason="Valgrind is slower")
@timeout_unless_slower_valgrind(1)
@pytest.mark.parametrize("newline", (b"\r", b"\n"))
def test_redos(newline: bytes) -> None:
malicious = b" trailer<<>>" + newline * 3456
Expand Down
11 changes: 3 additions & 8 deletions Tests/test_file_tiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
hopper,
is_pypy,
is_win32,
timeout_unless_slower_valgrind,
)

ElementTree: ModuleType | None
Expand Down Expand Up @@ -988,11 +989,8 @@ def test_string_dimension(self) -> None:
with pytest.raises(OSError):
im.load()

@pytest.mark.timeout(6)
@timeout_unless_slower_valgrind(6)
@pytest.mark.filterwarnings("ignore:Truncated File Read")
@pytest.mark.xfail(
"PILLOW_VALGRIND_TEST" in os.environ, reason="Valgrind is slower"
)
def test_timeout(self, monkeypatch: pytest.MonkeyPatch) -> None:
with Image.open("Tests/images/timeout-6646305047838720") as im:
monkeypatch.setattr(ImageFile, "LOAD_TRUNCATED_IMAGES", True)
Expand All @@ -1004,10 +1002,7 @@ def test_timeout(self, monkeypatch: pytest.MonkeyPatch) -> None:
"Tests/images/oom-225817ca0f8c663be7ab4b9e717b02c661e66834.tif",
],
)
@pytest.mark.timeout(2)
@pytest.mark.xfail(
"PILLOW_VALGRIND_TEST" in os.environ, reason="Valgrind is slower"
)
@timeout_unless_slower_valgrind(2)
def test_oom(self, test_file: str) -> None:
with pytest.raises(UnidentifiedImageError):
with pytest.warns(UserWarning):
Expand Down
6 changes: 2 additions & 4 deletions Tests/test_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
is_win32,
mark_if_feature_version,
skip_unless_feature,
timeout_unless_slower_valgrind,
)

ElementTree: ModuleType | None
Expand Down Expand Up @@ -572,10 +573,7 @@ def test_check_size(self) -> None:
i = Image.new("RGB", [1, 1])
assert isinstance(i.size, tuple)

@pytest.mark.timeout(0.75)
@pytest.mark.skipif(
"PILLOW_VALGRIND_TEST" in os.environ, reason="Valgrind is slower"
)
@timeout_unless_slower_valgrind(0.75)
@pytest.mark.parametrize("size", ((0, 100000000), (100000000, 0)))
def test_empty_image(self, size: tuple[int, int]) -> None:
Image.new("RGB", size)
Expand Down
6 changes: 2 additions & 4 deletions Tests/test_imagefontpil.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
from __future__ import annotations

import os
import struct
from io import BytesIO

import pytest

from PIL import Image, ImageDraw, ImageFont, _util, features

from .helper import assert_image_equal_tofile
from .helper import assert_image_equal_tofile, timeout_unless_slower_valgrind

fonts = [ImageFont.load_default_imagefont()]
if not features.check_module("freetype2"):
Expand Down Expand Up @@ -73,8 +72,7 @@ def test_decompression_bomb() -> None:
font.getmask("A" * 1_000_000)


@pytest.mark.timeout(4)
@pytest.mark.xfail("PILLOW_VALGRIND_TEST" in os.environ, reason="Valgrind is slower")
@timeout_unless_slower_valgrind(4)
def test_oom() -> None:
glyph = struct.pack(
">hhhhhhhhhh", 1, 0, -32767, -32767, 32767, 32767, -32767, -32767, 32767, 32767
Expand Down
Loading