2023-12-21 14:13:31 +03:00
|
|
|
from __future__ import annotations
|
2024-01-20 14:23:03 +03:00
|
|
|
|
2023-06-27 07:43:58 +03:00
|
|
|
import sys
|
|
|
|
|
2020-02-03 12:11:32 +03:00
|
|
|
import pytest
|
2020-08-07 13:28:33 +03:00
|
|
|
|
2017-09-18 02:37:47 +03:00
|
|
|
from PIL import Image
|
|
|
|
|
2020-03-02 17:02:19 +03:00
|
|
|
from .helper import is_pypy
|
2017-09-18 03:17:45 +03:00
|
|
|
|
|
|
|
|
2024-01-31 12:12:58 +03:00
|
|
|
def test_get_stats() -> None:
|
2019-11-04 01:18:55 +03:00
|
|
|
# Create at least one image
|
|
|
|
Image.new("RGB", (10, 10))
|
|
|
|
|
|
|
|
stats = Image.core.get_stats()
|
|
|
|
assert "new_count" in stats
|
|
|
|
assert "reused_blocks" in stats
|
|
|
|
assert "freed_blocks" in stats
|
|
|
|
assert "allocated_blocks" in stats
|
|
|
|
assert "reallocated_blocks" in stats
|
|
|
|
assert "blocks_cached" in stats
|
|
|
|
|
|
|
|
|
2024-01-31 12:12:58 +03:00
|
|
|
def test_reset_stats() -> None:
|
2019-11-04 01:18:55 +03:00
|
|
|
Image.core.reset_stats()
|
|
|
|
|
|
|
|
stats = Image.core.get_stats()
|
|
|
|
assert stats["new_count"] == 0
|
|
|
|
assert stats["reused_blocks"] == 0
|
|
|
|
assert stats["freed_blocks"] == 0
|
|
|
|
assert stats["allocated_blocks"] == 0
|
|
|
|
assert stats["reallocated_blocks"] == 0
|
|
|
|
assert stats["blocks_cached"] == 0
|
2017-09-18 02:37:47 +03:00
|
|
|
|
|
|
|
|
2020-03-02 17:02:19 +03:00
|
|
|
class TestCoreMemory:
|
2024-01-31 12:12:58 +03:00
|
|
|
def teardown_method(self) -> None:
|
2017-09-18 02:37:47 +03:00
|
|
|
# Restore default values
|
|
|
|
Image.core.set_alignment(1)
|
2019-06-13 18:53:42 +03:00
|
|
|
Image.core.set_block_size(1024 * 1024)
|
2017-09-18 02:37:47 +03:00
|
|
|
Image.core.set_blocks_max(0)
|
|
|
|
Image.core.clear_cache()
|
|
|
|
|
2024-01-31 12:12:58 +03:00
|
|
|
def test_get_alignment(self) -> None:
|
2017-09-18 02:37:47 +03:00
|
|
|
alignment = Image.core.get_alignment()
|
|
|
|
|
2020-02-22 16:06:21 +03:00
|
|
|
assert alignment > 0
|
2017-09-18 02:37:47 +03:00
|
|
|
|
2024-01-31 12:12:58 +03:00
|
|
|
def test_set_alignment(self) -> None:
|
2017-09-18 02:37:47 +03:00
|
|
|
for i in [1, 2, 4, 8, 16, 32]:
|
|
|
|
Image.core.set_alignment(i)
|
|
|
|
alignment = Image.core.get_alignment()
|
2020-02-22 16:06:21 +03:00
|
|
|
assert alignment == i
|
2017-09-18 02:37:47 +03:00
|
|
|
|
|
|
|
# Try to construct new image
|
2019-06-13 18:53:42 +03:00
|
|
|
Image.new("RGB", (10, 10))
|
2017-09-18 02:37:47 +03:00
|
|
|
|
2020-02-22 16:06:21 +03:00
|
|
|
with pytest.raises(ValueError):
|
|
|
|
Image.core.set_alignment(0)
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
Image.core.set_alignment(-1)
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
Image.core.set_alignment(3)
|
2017-09-18 02:37:47 +03:00
|
|
|
|
2024-01-31 12:12:58 +03:00
|
|
|
def test_get_block_size(self) -> None:
|
2017-09-18 02:37:47 +03:00
|
|
|
block_size = Image.core.get_block_size()
|
|
|
|
|
2020-02-22 16:06:21 +03:00
|
|
|
assert block_size >= 4096
|
2017-09-18 02:37:47 +03:00
|
|
|
|
2024-01-31 12:12:58 +03:00
|
|
|
def test_set_block_size(self) -> None:
|
2019-06-13 18:53:42 +03:00
|
|
|
for i in [4096, 2 * 4096, 3 * 4096]:
|
2017-09-18 02:37:47 +03:00
|
|
|
Image.core.set_block_size(i)
|
|
|
|
block_size = Image.core.get_block_size()
|
2020-02-22 16:06:21 +03:00
|
|
|
assert block_size == i
|
2017-09-18 02:37:47 +03:00
|
|
|
|
|
|
|
# Try to construct new image
|
2019-06-13 18:53:42 +03:00
|
|
|
Image.new("RGB", (10, 10))
|
2017-09-18 02:37:47 +03:00
|
|
|
|
2020-02-22 16:06:21 +03:00
|
|
|
with pytest.raises(ValueError):
|
|
|
|
Image.core.set_block_size(0)
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
Image.core.set_block_size(-1)
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
Image.core.set_block_size(4000)
|
2017-09-18 02:37:47 +03:00
|
|
|
|
2024-01-31 12:12:58 +03:00
|
|
|
def test_set_block_size_stats(self) -> None:
|
2017-09-18 02:37:47 +03:00
|
|
|
Image.core.reset_stats()
|
|
|
|
Image.core.set_blocks_max(0)
|
|
|
|
Image.core.set_block_size(4096)
|
2019-06-13 18:53:42 +03:00
|
|
|
Image.new("RGB", (256, 256))
|
2017-09-18 02:37:47 +03:00
|
|
|
|
|
|
|
stats = Image.core.get_stats()
|
2020-02-22 16:06:21 +03:00
|
|
|
assert stats["new_count"] >= 1
|
|
|
|
assert stats["allocated_blocks"] >= 64
|
2019-09-25 12:46:54 +03:00
|
|
|
if not is_pypy():
|
2020-02-22 16:06:21 +03:00
|
|
|
assert stats["freed_blocks"] >= 64
|
2017-09-18 02:37:47 +03:00
|
|
|
|
2024-01-31 12:12:58 +03:00
|
|
|
def test_get_blocks_max(self) -> None:
|
2017-09-18 02:37:47 +03:00
|
|
|
blocks_max = Image.core.get_blocks_max()
|
|
|
|
|
2020-02-22 16:06:21 +03:00
|
|
|
assert blocks_max >= 0
|
2017-09-18 02:37:47 +03:00
|
|
|
|
2024-01-31 12:12:58 +03:00
|
|
|
def test_set_blocks_max(self) -> None:
|
2017-09-18 02:37:47 +03:00
|
|
|
for i in [0, 1, 10]:
|
|
|
|
Image.core.set_blocks_max(i)
|
|
|
|
blocks_max = Image.core.get_blocks_max()
|
2020-02-22 16:06:21 +03:00
|
|
|
assert blocks_max == i
|
2017-09-18 02:37:47 +03:00
|
|
|
|
|
|
|
# Try to construct new image
|
2019-06-13 18:53:42 +03:00
|
|
|
Image.new("RGB", (10, 10))
|
2017-09-18 02:37:47 +03:00
|
|
|
|
2020-02-22 16:06:21 +03:00
|
|
|
with pytest.raises(ValueError):
|
|
|
|
Image.core.set_blocks_max(-1)
|
2023-06-27 07:43:58 +03:00
|
|
|
if sys.maxsize < 2**32:
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
Image.core.set_blocks_max(2**29)
|
2017-09-18 02:37:47 +03:00
|
|
|
|
2020-03-02 17:02:19 +03:00
|
|
|
@pytest.mark.skipif(is_pypy(), reason="Images not collected")
|
2024-01-31 12:12:58 +03:00
|
|
|
def test_set_blocks_max_stats(self) -> None:
|
2017-09-18 02:37:47 +03:00
|
|
|
Image.core.reset_stats()
|
|
|
|
Image.core.set_blocks_max(128)
|
|
|
|
Image.core.set_block_size(4096)
|
2019-06-13 18:53:42 +03:00
|
|
|
Image.new("RGB", (256, 256))
|
|
|
|
Image.new("RGB", (256, 256))
|
2017-09-18 02:37:47 +03:00
|
|
|
|
|
|
|
stats = Image.core.get_stats()
|
2020-02-22 16:06:21 +03:00
|
|
|
assert stats["new_count"] >= 2
|
|
|
|
assert stats["allocated_blocks"] >= 64
|
|
|
|
assert stats["reused_blocks"] >= 64
|
|
|
|
assert stats["freed_blocks"] == 0
|
|
|
|
assert stats["blocks_cached"] == 64
|
2017-09-18 02:37:47 +03:00
|
|
|
|
2020-03-02 17:02:19 +03:00
|
|
|
@pytest.mark.skipif(is_pypy(), reason="Images not collected")
|
2024-01-31 12:12:58 +03:00
|
|
|
def test_clear_cache_stats(self) -> None:
|
2017-09-18 02:37:47 +03:00
|
|
|
Image.core.reset_stats()
|
2017-09-18 22:41:28 +03:00
|
|
|
Image.core.clear_cache()
|
2017-09-18 02:37:47 +03:00
|
|
|
Image.core.set_blocks_max(128)
|
|
|
|
Image.core.set_block_size(4096)
|
2019-06-13 18:53:42 +03:00
|
|
|
Image.new("RGB", (256, 256))
|
|
|
|
Image.new("RGB", (256, 256))
|
2017-09-23 04:20:53 +03:00
|
|
|
# Keep 16 blocks in cache
|
|
|
|
Image.core.clear_cache(16)
|
2017-09-18 02:37:47 +03:00
|
|
|
|
|
|
|
stats = Image.core.get_stats()
|
2020-02-22 16:06:21 +03:00
|
|
|
assert stats["new_count"] >= 2
|
|
|
|
assert stats["allocated_blocks"] >= 64
|
|
|
|
assert stats["reused_blocks"] >= 64
|
|
|
|
assert stats["freed_blocks"] >= 48
|
|
|
|
assert stats["blocks_cached"] == 16
|
2017-09-18 02:57:14 +03:00
|
|
|
|
2024-01-31 12:12:58 +03:00
|
|
|
def test_large_images(self) -> None:
|
2017-09-18 02:57:14 +03:00
|
|
|
Image.core.reset_stats()
|
|
|
|
Image.core.set_blocks_max(0)
|
|
|
|
Image.core.set_block_size(4096)
|
2019-06-13 18:53:42 +03:00
|
|
|
Image.new("RGB", (2048, 16))
|
2017-09-18 02:57:14 +03:00
|
|
|
Image.core.clear_cache()
|
|
|
|
|
|
|
|
stats = Image.core.get_stats()
|
2020-02-22 16:06:21 +03:00
|
|
|
assert stats["new_count"] >= 1
|
|
|
|
assert stats["allocated_blocks"] >= 16
|
|
|
|
assert stats["reused_blocks"] >= 0
|
|
|
|
assert stats["blocks_cached"] == 0
|
2019-09-25 12:46:54 +03:00
|
|
|
if not is_pypy():
|
2020-02-22 16:06:21 +03:00
|
|
|
assert stats["freed_blocks"] >= 16
|
2017-09-19 01:00:18 +03:00
|
|
|
|
|
|
|
|
2020-03-02 17:02:19 +03:00
|
|
|
class TestEnvVars:
|
2024-01-31 12:12:58 +03:00
|
|
|
def teardown_method(self) -> None:
|
2017-09-19 01:00:18 +03:00
|
|
|
# Restore default values
|
|
|
|
Image.core.set_alignment(1)
|
2019-06-13 18:53:42 +03:00
|
|
|
Image.core.set_block_size(1024 * 1024)
|
2017-09-19 01:00:18 +03:00
|
|
|
Image.core.set_blocks_max(0)
|
|
|
|
Image.core.clear_cache()
|
|
|
|
|
2024-01-31 12:12:58 +03:00
|
|
|
def test_units(self) -> None:
|
2019-06-13 18:53:42 +03:00
|
|
|
Image._apply_env_variables({"PILLOW_BLOCKS_MAX": "2K"})
|
2020-02-22 16:06:21 +03:00
|
|
|
assert Image.core.get_blocks_max() == 2 * 1024
|
2019-06-13 18:53:42 +03:00
|
|
|
Image._apply_env_variables({"PILLOW_BLOCK_SIZE": "2m"})
|
2020-02-22 16:06:21 +03:00
|
|
|
assert Image.core.get_block_size() == 2 * 1024 * 1024
|
2017-09-19 01:00:18 +03:00
|
|
|
|
2023-02-23 16:30:38 +03:00
|
|
|
@pytest.mark.parametrize(
|
2023-02-24 10:26:18 +03:00
|
|
|
"var",
|
2023-03-03 17:00:56 +03:00
|
|
|
(
|
2023-02-23 16:30:38 +03:00
|
|
|
{"PILLOW_ALIGNMENT": "15"},
|
|
|
|
{"PILLOW_BLOCK_SIZE": "1024"},
|
|
|
|
{"PILLOW_BLOCKS_MAX": "wat"},
|
2023-03-03 17:00:56 +03:00
|
|
|
),
|
2023-02-23 16:30:38 +03:00
|
|
|
)
|
2024-01-31 12:12:58 +03:00
|
|
|
def test_warnings(self, var) -> None:
|
2023-02-23 16:30:38 +03:00
|
|
|
with pytest.warns(UserWarning):
|
2023-02-24 10:26:18 +03:00
|
|
|
Image._apply_env_variables(var)
|