103 lines
2.9 KiB
Python
103 lines
2.9 KiB
Python
import pytest
|
|
from tblib import pickling_support
|
|
|
|
import ray
|
|
from ray import cloudpickle
|
|
from ray.air._internal.util import StartTraceback, exception_cause, skip_exceptions
|
|
from ray.tune import Tuner
|
|
|
|
|
|
@pytest.fixture
|
|
def ray_start_2_cpus():
|
|
address_info = ray.init(num_cpus=2)
|
|
yield address_info
|
|
# The code after the yield will run as teardown code.
|
|
ray.shutdown()
|
|
|
|
|
|
def _failing_recursive(levels: int = 0, start_traceback: int = -1):
|
|
if levels > 0:
|
|
if start_traceback == 0:
|
|
try:
|
|
_failing_recursive(
|
|
levels=levels - 1, start_traceback=start_traceback - 1
|
|
)
|
|
except Exception as e:
|
|
raise StartTraceback from e
|
|
else:
|
|
_failing_recursive(levels=levels - 1, start_traceback=start_traceback - 1)
|
|
else:
|
|
raise RuntimeError("Failing")
|
|
|
|
|
|
@pytest.mark.parametrize("levels", [4, 5, 6, 7, 8, 9, 10])
|
|
def test_short_traceback(levels):
|
|
start_traceback = 3
|
|
with pytest.raises(StartTraceback) as exc_info:
|
|
_failing_recursive(levels=levels, start_traceback=start_traceback)
|
|
|
|
exc = skip_exceptions(exc_info.value)
|
|
tb = exc.__traceback__
|
|
i = 0
|
|
while tb:
|
|
i += 1
|
|
tb = tb.tb_next
|
|
|
|
assert i == levels - start_traceback + 1
|
|
|
|
|
|
def test_recursion():
|
|
"""Test that the skipped exception does not point to the original exception."""
|
|
root_exception = None
|
|
|
|
with pytest.raises(StartTraceback) as exc_info:
|
|
try:
|
|
raise Exception("Root Exception")
|
|
except Exception as e:
|
|
root_exception = e
|
|
raise StartTraceback from root_exception
|
|
|
|
assert root_exception, "Root exception was not captured."
|
|
|
|
start_traceback = exc_info.value
|
|
skipped_exception = skip_exceptions(start_traceback)
|
|
|
|
assert (
|
|
root_exception != skipped_exception
|
|
), "Skipped exception points to the original exception."
|
|
|
|
|
|
def test_tblib():
|
|
"""Test that tblib does not cause a maximum recursion error."""
|
|
|
|
with pytest.raises(Exception) as exc_info:
|
|
try:
|
|
try:
|
|
raise Exception("Root Exception")
|
|
except Exception as root_exception:
|
|
raise StartTraceback from root_exception
|
|
except Exception as start_traceback:
|
|
raise skip_exceptions(start_traceback) from exception_cause(start_traceback)
|
|
|
|
pickling_support.install()
|
|
reraised_exception = exc_info.value
|
|
# This should not raise a RecursionError/PicklingError.
|
|
cloudpickle.dumps(reraised_exception)
|
|
|
|
|
|
def test_traceback_tuner(ray_start_2_cpus):
|
|
"""Ensure that the Tuner's stack trace is not too long."""
|
|
|
|
def failing(config):
|
|
raise RuntimeError("Error")
|
|
|
|
tuner = Tuner(failing)
|
|
results = tuner.fit()
|
|
assert len(str(results[0].error).split("\n")) <= 20
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import sys
|
|
|
|
sys.exit(pytest.main(["-v", "-x", __file__]))
|