Skip to content

Commit 07b864f

Browse files
committed
Add a new current_thread_only to all markers
Add a new "current_thread_only" keyword to the "limit_memory" and "limit_leaks" markers to ignore all allocations made in threads other than the one running the test.
1 parent bdcfd2c commit 07b864f

File tree

5 files changed

+89
-8
lines changed

5 files changed

+89
-8
lines changed

docs/news/117.feature.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Add a new ``current_thread_only`` keyword argument to the ``limit_memory`` and
2+
``limit_leaks`` markers to ignore all allocations made in threads other than
3+
the one running the test.

docs/usage.rst

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ This plugin provides `markers <https://docs.pytest.org/en/latest/example/markers
3535
that can be used to enforce additional checks and validations on tests.
3636

3737

38-
.. py:function:: pytest.mark.limit_memory(memory_limit: str)
38+
.. py:function:: pytest.mark.limit_memory(memory_limit: str, current_thread_only: bool = False)
3939
4040
Fail the execution of the test if the test allocates more peak memory than allowed.
4141

@@ -47,6 +47,10 @@ that can be used to enforce additional checks and validations on tests.
4747
The format for the string is ``<NUMBER> ([KMGTP]B|B)``. The marker will raise
4848
``ValueError`` if the string format cannot be parsed correctly.
4949

50+
If the optional keyword-only argument ``current_thread_only`` is set to *True*, the
51+
plugin will only track memory allocations made by the current thread and all other
52+
allocations will be ignored.
53+
5054
.. warning::
5155

5256
As the Python interpreter has its own
@@ -96,6 +100,10 @@ that can be used to enforce additional checks and validations on tests.
96100
ignored, the test will not fail. This can be used to discard any known false
97101
positives.
98102

103+
If the optional keyword-only argument ``current_thread_only`` is set to *True*, the
104+
plugin will only track memory allocations made by the current thread and all other
105+
allocations will be ignored.
106+
99107
.. tip::
100108

101109
You can pass the ``--memray-bin-path`` argument to ``pytest`` to specify

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ maintainers = [
2020
requires-python = ">=3.8"
2121
dependencies = [
2222
"pytest>=7.2",
23-
"memray>=1.5",
23+
"memray>=1.12",
2424
]
2525
optional-dependencies.docs = [
2626
"furo>=2022.12.7",

src/pytest_memray/marks.py

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -186,15 +186,27 @@ def _passes_filter(
186186
def limit_memory(
187187
limit: str,
188188
*,
189+
current_thread_only: bool = False,
189190
_result_file: Path,
190191
_config: Config,
191192
_test_id: str,
192193
) -> _MemoryInfo | _MoreMemoryInfo | None:
193194
"""Limit memory used by the test."""
194195
reader = FileReader(_result_file)
195-
allocations: list[AllocationRecord] = list(
196-
reader.get_high_watermark_allocation_records(merge_threads=True)
197-
)
196+
allocations: list[AllocationRecord] = []
197+
if current_thread_only:
198+
main_thread = reader.metadata.main_thread_id
199+
allocations.extend(
200+
record
201+
for record in reader.get_high_watermark_allocation_records(
202+
merge_threads=False
203+
)
204+
if record.tid == main_thread
205+
)
206+
else:
207+
allocations.extend(
208+
reader.get_high_watermark_allocation_records(merge_threads=True)
209+
)
198210
max_memory = parse_memory_string(limit)
199211
total_allocated_memory = sum(record.size for record in allocations)
200212

@@ -225,14 +237,22 @@ def limit_leaks(
225237
location_limit: str,
226238
*,
227239
filter_fn: Optional[LeaksFilterFunction] = None,
240+
current_thread_only: bool = False,
228241
_result_file: Path,
229242
_config: Config,
230243
_test_id: str,
231244
) -> _LeakedInfo | None:
232245
reader = FileReader(_result_file)
233-
allocations: list[AllocationRecord] = list(
234-
reader.get_leaked_allocation_records(merge_threads=True)
235-
)
246+
allocations: list[AllocationRecord] = []
247+
if current_thread_only:
248+
main_thread_id = reader.metadata.main_thread_id
249+
allocations.extend(
250+
record
251+
for record in reader.get_leaked_allocation_records(merge_threads=False)
252+
if record.tid == main_thread_id
253+
)
254+
else:
255+
allocations.extend(reader.get_leaked_allocation_records(merge_threads=True))
236256

237257
memory_limit = parse_memory_string(location_limit)
238258

tests/test_pytest_memray.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -868,3 +868,53 @@ def test_memory_alloc_fails():
868868
)
869869
result = pytester.runpytest("--memray")
870870
assert result.ret == ExitCode.OK
871+
872+
873+
def test_limit_memory_in_current_thread(pytester: Pytester) -> None:
874+
pytester.makepyfile(
875+
"""
876+
import pytest
877+
from memray._test import MemoryAllocator
878+
allocator = MemoryAllocator()
879+
import threading
880+
def allocating_func():
881+
for _ in range(10):
882+
allocator.valloc(1024*5)
883+
# No free call here
884+
885+
@pytest.mark.limit_memory("5KB", current_thread_only=True)
886+
def test_memory_alloc_fails():
887+
t = threading.Thread(target=allocating_func)
888+
t.start()
889+
t.join()
890+
"""
891+
)
892+
893+
result = pytester.runpytest("--memray")
894+
895+
assert result.ret == ExitCode.OK
896+
897+
898+
def test_leaks_in_current_thread(pytester: Pytester) -> None:
899+
pytester.makepyfile(
900+
"""
901+
import pytest
902+
from memray._test import MemoryAllocator
903+
allocator = MemoryAllocator()
904+
import threading
905+
def allocating_func():
906+
for _ in range(10):
907+
allocator.valloc(1024*5)
908+
# No free call here
909+
910+
@pytest.mark.limit_leaks("5KB", current_thread_only=True)
911+
def test_memory_alloc_fails():
912+
t = threading.Thread(target=allocating_func)
913+
t.start()
914+
t.join()
915+
"""
916+
)
917+
918+
result = pytester.runpytest("--memray")
919+
920+
assert result.ret == ExitCode.OK

0 commit comments

Comments
 (0)