Skip to content

Commit ae3871e

Browse files
new tests with different config settings
1 parent 8904877 commit ae3871e

File tree

3 files changed

+71
-31
lines changed

3 files changed

+71
-31
lines changed

ddtrace/profiling/collector/_lock.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@
2929
from ddtrace.trace import Tracer
3030

3131

32-
ACQUIRE_RELEASE_CO_NAMES: List[str] = ["_acquire", "_release"]
33-
ENTER_EXIT_CO_NAMES: List[str] = ["acquire", "release", "__enter__", "__exit__", "__aenter__", "__aexit__"]
32+
ACQUIRE_RELEASE_CO_NAMES: frozenset[str] = frozenset(["_acquire", "_release"])
33+
ENTER_EXIT_CO_NAMES: frozenset[str] = frozenset(
34+
["acquire", "release", "__enter__", "__exit__", "__aenter__", "__aexit__"]
35+
)
3436

3537

3638
def _current_thread() -> Tuple[int, str]:
@@ -238,11 +240,11 @@ def _maybe_update_self_name(self) -> None:
238240
if config.enable_asserts:
239241
frame: FrameType = sys._getframe(1)
240242
if frame.f_code.co_name not in ACQUIRE_RELEASE_CO_NAMES:
241-
raise AssertionError("Unexpected frame %s" % frame.f_code.co_name)
243+
raise AssertionError(f"Unexpected frame in stack: '{frame.f_code.co_name}'")
242244

243245
frame = sys._getframe(2)
244246
if frame.f_code.co_name not in ENTER_EXIT_CO_NAMES:
245-
raise AssertionError("Unexpected frame %s" % frame.f_code.co_name)
247+
raise AssertionError(f"Unexpected frame in stack: '{frame.f_code.co_name}'")
246248

247249
# First, look at the local variables of the caller frame, and then the global variables
248250
frame = sys._getframe(3)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
---
22
fixes:
33
- |
4-
profiling: This fix resolves an issue where AssertionError exceptions were silently suppressed in the `_acquire` method of the Lock profiler (note: this only occurs when assertions are enabled.)
4+
profiling: This fix resolves an issue where AssertionError exceptions were silently suppressed in the `_acquire` method of the Lock profiler (note: this only occurs when assertions are enabled.)

tests/profiling_v2/collector/test_threading.py

Lines changed: 64 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,70 @@ def validate_and_cleanup() -> None:
360360
validate_and_cleanup()
361361

362362

363+
@pytest.mark.subprocess(env=dict(DD_PROFILING_ENABLE_ASSERTS="true"))
364+
def test_assertion_error_raised_with_enable_asserts():
365+
"""Ensure that AssertionError is propagated when config.enable_asserts=True."""
366+
import threading
367+
368+
import mock
369+
import pytest
370+
371+
from ddtrace.internal.datadog.profiling import ddup
372+
from ddtrace.profiling.collector.threading import ThreadingLockCollector
373+
374+
# Initialize ddup (required before using collectors)
375+
assert ddup.is_available, "ddup is not available"
376+
ddup.config(env="test", service="test_asserts", version="1.0", output_filename="/tmp/test_asserts")
377+
ddup.start()
378+
379+
with ThreadingLockCollector(capture_pct=100):
380+
lock = threading.Lock()
381+
382+
# Patch _maybe_update_self_name to raise AssertionError
383+
lock._maybe_update_self_name = mock.Mock(side_effect=AssertionError("test: unexpected frame in stack"))
384+
385+
with pytest.raises(AssertionError):
386+
# AssertionError should be propagated when enable_asserts=True
387+
lock.acquire()
388+
389+
390+
@pytest.mark.subprocess(env=dict(DD_PROFILING_ENABLE_ASSERTS="false"))
391+
def test_all_exceptions_suppressed_by_default() -> None:
392+
"""
393+
Ensure that exceptions are silently suppressed in the `_acquire` method
394+
when config.enable_asserts=False (default).
395+
"""
396+
import threading
397+
398+
import mock
399+
400+
from ddtrace.internal.datadog.profiling import ddup
401+
from ddtrace.profiling.collector.threading import ThreadingLockCollector
402+
403+
# Initialize ddup (required before using collectors)
404+
assert ddup.is_available, "ddup is not available"
405+
ddup.config(env="test", service="test_exceptions", version="1.0", output_filename="/tmp/test_exceptions")
406+
ddup.start()
407+
408+
with ThreadingLockCollector(capture_pct=100):
409+
lock = threading.Lock()
410+
411+
# Patch _maybe_update_self_name to raise AssertionError
412+
lock._maybe_update_self_name = mock.Mock(side_effect=AssertionError("Unexpected frame in stack: 'fubar'"))
413+
lock.acquire()
414+
lock.release()
415+
416+
# Patch _maybe_update_self_name to raise RuntimeError
417+
lock._maybe_update_self_name = mock.Mock(side_effect=RuntimeError("Some profiling error"))
418+
lock.acquire()
419+
lock.release()
420+
421+
# Patch _maybe_update_self_name to raise Exception
422+
lock._maybe_update_self_name = mock.Mock(side_effect=Exception("Wut happened?!?!"))
423+
lock.acquire()
424+
lock.release()
425+
426+
363427
class BaseThreadingLockCollectorTest:
364428
# These should be implemented by child classes
365429
@property
@@ -979,32 +1043,6 @@ def test_upload_resets_profile(self) -> None:
9791043
with pytest.raises(AssertionError):
9801044
pprof_utils.parse_newest_profile(self.output_filename)
9811045

982-
def test_assertion_exceptions_raised_in_acquire(self) -> None:
983-
"""Ensure that AssertionError exceptions is propagated in the `_acquire` method."""
984-
985-
with self.collector_class(capture_pct=100):
986-
lock = self.lock_class()
987-
988-
# Patch _maybe_update_self_name to raise AssertionError
989-
lock._maybe_update_self_name = mock.Mock(side_effect=AssertionError("test: unexpected frame in stack"))
990-
991-
with pytest.raises(AssertionError):
992-
# acquire() will propagate AssertionError if _maybe_update_self_name raises it
993-
lock.acquire()
994-
995-
def test_non_assertion_exceptions_suppressed_in_acquire(self) -> None:
996-
"""Ensure that non - AssertionError exceptions are silently suppressed in the `_acquire` method."""
997-
998-
with self.collector_class(capture_pct=100):
999-
lock = self.lock_class()
1000-
1001-
# Patch _maybe_update_self_name to raise RuntimeError
1002-
lock._maybe_update_self_name = mock.Mock(side_effect=RuntimeError("Some profiling error"))
1003-
1004-
# RuntimeError should be caught and suppressed - lock operations should succeed
1005-
lock.acquire()
1006-
lock.release()
1007-
10081046

10091047
class TestThreadingLockCollector(BaseThreadingLockCollectorTest):
10101048
"""Test Lock profiling"""

0 commit comments

Comments
 (0)