Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test Windows with GitHub Actions #4084

Merged
merged 22 commits into from Oct 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
360 changes: 360 additions & 0 deletions .github/workflows/test-windows.yml

Large diffs are not rendered by default.

6 changes: 2 additions & 4 deletions Tests/check_imaging_leaks.py
Expand Up @@ -2,17 +2,15 @@

from __future__ import division

import sys

from PIL import Image

from .helper import PillowTestCase, unittest
from .helper import PillowTestCase, is_win32, unittest

min_iterations = 100
max_iterations = 10000


@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS")
@unittest.skipIf(is_win32(), "requires Unix or macOS")
class TestImagingLeaks(PillowTestCase):
def _get_mem_usage(self):
from resource import getpagesize, getrusage, RUSAGE_SELF
Expand Down
5 changes: 2 additions & 3 deletions Tests/check_j2k_leaks.py
@@ -1,9 +1,8 @@
import sys
from io import BytesIO

from PIL import Image

from .helper import PillowTestCase, unittest
from .helper import PillowTestCase, is_win32, unittest

# Limits for testing the leak
mem_limit = 1024 * 1048576
Expand All @@ -13,7 +12,7 @@
test_file = "Tests/images/rgb_trns_ycbc.jp2"


@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS")
@unittest.skipIf(is_win32(), "requires Unix or macOS")
class TestJpegLeaks(PillowTestCase):
def setUp(self):
if "jpeg2k_encoder" not in codecs or "jpeg2k_decoder" not in codecs:
Expand Down
5 changes: 2 additions & 3 deletions Tests/check_jpeg_leaks.py
@@ -1,7 +1,6 @@
import sys
from io import BytesIO

from .helper import PillowTestCase, hopper, unittest
from .helper import PillowTestCase, hopper, is_win32, unittest

iterations = 5000

Expand All @@ -15,7 +14,7 @@
"""


@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS")
@unittest.skipIf(is_win32(), "requires Unix or macOS")
class TestJpegLeaks(PillowTestCase):

"""
Expand Down
17 changes: 16 additions & 1 deletion Tests/helper.py
Expand Up @@ -351,10 +351,25 @@ def on_appveyor():
return "APPVEYOR" in os.environ


def on_github_actions():
return "GITHUB_ACTIONS" in os.environ


def on_ci():
# Travis and AppVeyor have "CI"
# Azure Pipelines has "TF_BUILD"
return "CI" in os.environ or "TF_BUILD" in os.environ
# GitHub Actions has "GITHUB_ACTIONS"
return (
"CI" in os.environ or "TF_BUILD" in os.environ or "GITHUB_ACTIONS" in os.environ
)


def is_win32():
return sys.platform.startswith("win32")


def is_pypy():
return hasattr(sys, "pypy_translation_info")


if sys.platform == "win32":
Expand Down
12 changes: 5 additions & 7 deletions Tests/test_core_resources.py
Expand Up @@ -4,9 +4,7 @@

from PIL import Image

from .helper import PillowTestCase, unittest

is_pypy = hasattr(sys, "pypy_version_info")
from .helper import PillowTestCase, is_pypy, unittest


class TestCoreStats(PillowTestCase):
Expand Down Expand Up @@ -87,7 +85,7 @@ def test_set_block_size_stats(self):
stats = Image.core.get_stats()
self.assertGreaterEqual(stats["new_count"], 1)
self.assertGreaterEqual(stats["allocated_blocks"], 64)
if not is_pypy:
if not is_pypy():
self.assertGreaterEqual(stats["freed_blocks"], 64)

def test_get_blocks_max(self):
Expand All @@ -108,7 +106,7 @@ def test_set_blocks_max(self):
if sys.maxsize < 2 ** 32:
self.assertRaises(ValueError, Image.core.set_blocks_max, 2 ** 29)

@unittest.skipIf(is_pypy, "images are not collected")
@unittest.skipIf(is_pypy(), "images are not collected")
def test_set_blocks_max_stats(self):
Image.core.reset_stats()
Image.core.set_blocks_max(128)
Expand All @@ -123,7 +121,7 @@ def test_set_blocks_max_stats(self):
self.assertEqual(stats["freed_blocks"], 0)
self.assertEqual(stats["blocks_cached"], 64)

@unittest.skipIf(is_pypy, "images are not collected")
@unittest.skipIf(is_pypy(), "images are not collected")
def test_clear_cache_stats(self):
Image.core.reset_stats()
Image.core.clear_cache()
Expand Down Expand Up @@ -153,7 +151,7 @@ def test_large_images(self):
self.assertGreaterEqual(stats["allocated_blocks"], 16)
self.assertGreaterEqual(stats["reused_blocks"], 0)
self.assertEqual(stats["blocks_cached"], 0)
if not is_pypy:
if not is_pypy():
self.assertGreaterEqual(stats["freed_blocks"], 16)


Expand Down
12 changes: 9 additions & 3 deletions Tests/test_file_jpeg.py
@@ -1,10 +1,16 @@
import os
import sys
from io import BytesIO

from PIL import Image, ImageFile, JpegImagePlugin

from .helper import PillowTestCase, cjpeg_available, djpeg_available, hopper, unittest
from .helper import (
PillowTestCase,
cjpeg_available,
djpeg_available,
hopper,
is_win32,
unittest,
)

codecs = dir(Image.core)

Expand Down Expand Up @@ -654,7 +660,7 @@ def test_photoshop(self):
self.assertNotIn("photoshop", im.info)


@unittest.skipUnless(sys.platform.startswith("win32"), "Windows only")
@unittest.skipUnless(is_win32(), "Windows only")
class TestFileCloseW32(PillowTestCase):
def setUp(self):
if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs:
Expand Down
5 changes: 2 additions & 3 deletions Tests/test_file_png.py
@@ -1,11 +1,10 @@
import sys
import zlib
from io import BytesIO

from PIL import Image, ImageFile, PngImagePlugin
from PIL._util import py3

from .helper import PillowLeakTestCase, PillowTestCase, hopper, unittest
from .helper import PillowLeakTestCase, PillowTestCase, hopper, is_win32, unittest

try:
from PIL import _webp
Expand Down Expand Up @@ -650,7 +649,7 @@ def test_apng(self):
self.assert_image_similar(im, expected, 0.23)


@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS")
@unittest.skipIf(is_win32(), "requires Unix or macOS")
class TestTruncatedPngPLeaks(PillowLeakTestCase):
mem_limit = 2 * 1024 # max increase in K
iterations = 100 # Leak is 56k/iteration, this will leak 5.6megs
Expand Down
5 changes: 2 additions & 3 deletions Tests/test_file_tiff.py
@@ -1,13 +1,12 @@
import logging
import os
import sys
from io import BytesIO

from PIL import Image, TiffImagePlugin
from PIL._util import py3
from PIL.TiffImagePlugin import RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION

from .helper import PillowTestCase, hopper, unittest
from .helper import PillowTestCase, hopper, is_win32, unittest

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -582,7 +581,7 @@ def test_string_dimension(self):
Image.open("Tests/images/string_dimension.tiff")


@unittest.skipUnless(sys.platform.startswith("win32"), "Windows only")
@unittest.skipUnless(is_win32(), "Windows only")
class TestFileTiffW32(PillowTestCase):
def test_fd_leak(self):
tmpfile = self.tempfile("temp.tif")
Expand Down
6 changes: 2 additions & 4 deletions Tests/test_font_leaks.py
@@ -1,13 +1,11 @@
from __future__ import division

import sys

from PIL import Image, ImageDraw, ImageFont, features

from .helper import PillowLeakTestCase, unittest
from .helper import PillowLeakTestCase, is_win32, unittest


@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS")
@unittest.skipIf(is_win32(), "requires Unix or macOS")
class TestTTypeFontLeak(PillowLeakTestCase):
# fails at iteration 3 in master
iterations = 10
Expand Down
7 changes: 2 additions & 5 deletions Tests/test_image.py
@@ -1,12 +1,11 @@
import os
import shutil
import sys
import tempfile

from PIL import Image
from PIL._util import py3

from .helper import PillowTestCase, hopper, unittest
from .helper import PillowTestCase, hopper, is_win32, unittest


class TestImage(PillowTestCase):
Expand Down Expand Up @@ -149,9 +148,7 @@ def test_internals(self):
im.paste(0, (0, 0, 100, 100))
self.assertFalse(im.readonly)

@unittest.skipIf(
sys.platform.startswith("win32"), "Test requires opening tempfile twice"
)
@unittest.skipIf(is_win32(), "Test requires opening tempfile twice")
def test_readonly_save(self):
temp_file = self.tempfile("temp.bmp")
shutil.copy("Tests/images/rgb32bf-rgba.bmp", temp_file)
Expand Down
6 changes: 3 additions & 3 deletions Tests/test_image_access.py
Expand Up @@ -6,7 +6,7 @@

from PIL import Image

from .helper import PillowTestCase, hopper, on_appveyor, unittest
from .helper import PillowTestCase, hopper, is_win32, on_ci, unittest

# CFFI imports pycparser which doesn't support PYTHONOPTIMIZE=2
# https://github.com/eliben/pycparser/pull/198#issuecomment-317001670
Expand Down Expand Up @@ -336,8 +336,8 @@ def test_p_putpixel_rgb_rgba(self):

class TestEmbeddable(unittest.TestCase):
@unittest.skipIf(
not sys.platform.startswith("win32") or on_appveyor(),
"Failing on AppVeyor when run from subprocess, not from shell",
not is_win32() or on_ci(),
"Failing on AppVeyor / GitHub Actions when run from subprocess, not from shell",
)
def test_embeddable(self):
with open("embed_pil.c", "w") as fh:
Expand Down
11 changes: 4 additions & 7 deletions Tests/test_imagefont.py
Expand Up @@ -9,7 +9,7 @@

from PIL import Image, ImageDraw, ImageFont, features

from .helper import PillowTestCase, unittest
from .helper import PillowTestCase, is_pypy, is_win32, unittest

FONT_PATH = "Tests/fonts/FreeMono.ttf"
FONT_SIZE = 20
Expand Down Expand Up @@ -464,10 +464,7 @@ def test_unicode_pilfont(self):
with self.assertRaises(UnicodeEncodeError):
font.getsize(u"’")

@unittest.skipIf(
sys.version.startswith("2") or hasattr(sys, "pypy_translation_info"),
"requires CPython 3.3+",
)
@unittest.skipIf(sys.version.startswith("2") or is_pypy(), "requires CPython 3.3+")
def test_unicode_extended(self):
# issue #3777
text = u"A\u278A\U0001F12B"
Expand Down Expand Up @@ -504,7 +501,7 @@ def loadable_font(filepath, size, index, encoding, *args, **kwargs):
name = font.getname()
self.assertEqual(("FreeMono", "Regular"), name)

@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS")
@unittest.skipIf(is_win32(), "requires Unix or macOS")
def test_find_linux_font(self):
# A lot of mocking here - this is more for hitting code and
# catching syntax like errors
Expand Down Expand Up @@ -550,7 +547,7 @@ def fake_walker(path):
font_directory + "/Duplicate.ttf", "Duplicate"
)

@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS")
@unittest.skipIf(is_win32(), "requires Unix or macOS")
def test_find_macos_font(self):
# Like the linux test, more cover hitting code rather than testing
# correctness.
Expand Down
7 changes: 5 additions & 2 deletions Tests/test_imageshow.py
@@ -1,6 +1,6 @@
from PIL import Image, ImageShow

from .helper import PillowTestCase, hopper, on_ci, unittest
from .helper import PillowTestCase, hopper, is_win32, on_ci, on_github_actions, unittest


class TestImageShow(PillowTestCase):
Expand Down Expand Up @@ -34,7 +34,10 @@ def show_image(self, image, **options):
# Restore original state
ImageShow._viewers.pop(0)

@unittest.skipUnless(on_ci(), "Only run on CIs")
@unittest.skipUnless(
on_ci() and not (is_win32() and on_github_actions()),
"Only run on CIs; hangs on Windows on GitHub Actions",
)
def test_show(self):
for mode in ("1", "I;16", "LA", "RGB", "RGBA"):
im = hopper(mode)
Expand Down
6 changes: 2 additions & 4 deletions Tests/test_imagewin.py
@@ -1,8 +1,6 @@
import sys

from PIL import ImageWin

from .helper import PillowTestCase, hopper, unittest
from .helper import PillowTestCase, hopper, is_win32, unittest


class TestImageWin(PillowTestCase):
Expand Down Expand Up @@ -32,7 +30,7 @@ def test_hwnd(self):
self.assertEqual(wnd2, 50)


@unittest.skipUnless(sys.platform.startswith("win32"), "Windows only")
@unittest.skipUnless(is_win32(), "Windows only")
class TestImageWinDib(PillowTestCase):
def test_dib_image(self):
# Arrange
Expand Down
5 changes: 2 additions & 3 deletions Tests/test_imagewin_pointers.py
@@ -1,14 +1,13 @@
import ctypes
import sys
from io import BytesIO

from PIL import Image, ImageWin

from .helper import PillowTestCase, hopper
from .helper import PillowTestCase, hopper, is_win32

# see https://github.com/python-pillow/Pillow/pull/1431#issuecomment-144692652

if sys.platform.startswith("win32"):
if is_win32():
import ctypes.wintypes

class BITMAPFILEHEADER(ctypes.Structure):
Expand Down
6 changes: 6 additions & 0 deletions Tests/test_main.py
Expand Up @@ -5,8 +5,14 @@
import sys
from unittest import TestCase

from .helper import is_pypy, is_win32, on_github_actions, unittest


class TestMain(TestCase):
@unittest.skipIf(
is_win32() and is_pypy() and on_github_actions(),
"Failing on Windows on GitHub Actions running PyPy",
)
def test_main(self):
out = subprocess.check_output([sys.executable, "-m", "PIL"]).decode("utf-8")
lines = out.splitlines()
Expand Down
4 changes: 2 additions & 2 deletions Tests/test_map.py
Expand Up @@ -2,15 +2,15 @@

from PIL import Image

from .helper import PillowTestCase, unittest
from .helper import PillowTestCase, is_win32, unittest

try:
import numpy
except ImportError:
numpy = None


@unittest.skipIf(sys.platform.startswith("win32"), "Win32 does not call map_buffer")
@unittest.skipIf(is_win32(), "Win32 does not call map_buffer")
class TestMap(PillowTestCase):
def test_overflow(self):
# There is the potential to overflow comparisons in map.c
Expand Down