@@ -305,13 +305,75 @@ def check_longrepr(longrepr):
305
305
306
306
data = report ._to_json ()
307
307
loaded_report = report_class ._from_json (data )
308
+
309
+ assert loaded_report .failed
308
310
check_longrepr (loaded_report .longrepr )
309
311
310
312
# make sure we don't blow up on ``toterminal`` call; we don't test the actual output because it is very
311
313
# brittle and hard to maintain, but we can assume it is correct because ``toterminal`` is already tested
312
314
# elsewhere and we do check the contents of the longrepr object after loading it.
313
315
loaded_report .longrepr .toterminal (tw_mock )
314
316
317
+ def test_chained_exceptions_no_reprcrash (
318
+ self , testdir , tw_mock ,
319
+ ):
320
+ """Regression test for tracebacks without a reprcrash (#5971)
321
+
322
+ This happens notably on exceptions raised by multiprocess.pool: the exception transfer
323
+ from subprocess to main process creates an artificial exception which, ExceptionInfo
324
+ can't obtain the ReprFileLocation from.
325
+ """
326
+ testdir .makepyfile (
327
+ """
328
+ # equivalent of multiprocessing.pool.RemoteTraceback
329
+ class RemoteTraceback(Exception):
330
+ def __init__(self, tb):
331
+ self.tb = tb
332
+ def __str__(self):
333
+ return self.tb
334
+
335
+ def test_a():
336
+ try:
337
+ raise ValueError('value error')
338
+ except ValueError as e:
339
+ # equivalent to how multiprocessing.pool.rebuild_exc does it
340
+ e.__cause__ = RemoteTraceback('runtime error')
341
+ raise e
342
+ """
343
+ )
344
+ reprec = testdir .inline_run ()
345
+
346
+ reports = reprec .getreports ("pytest_runtest_logreport" )
347
+
348
+ def check_longrepr (longrepr ):
349
+ assert isinstance (longrepr , ExceptionChainRepr )
350
+ assert len (longrepr .chain ) == 2
351
+ entry1 , entry2 = longrepr .chain
352
+ tb1 , fileloc1 , desc1 = entry1
353
+ tb2 , fileloc2 , desc2 = entry2
354
+
355
+ assert "RemoteTraceback: runtime error" in str (tb1 )
356
+ assert "ValueError('value error')" in str (tb2 )
357
+
358
+ assert fileloc1 is None
359
+ assert fileloc2 .message == "ValueError: value error"
360
+
361
+ # 3 reports: setup/call/teardown: get the call report
362
+ assert len (reports ) == 3
363
+ report = reports [1 ]
364
+
365
+ assert report .failed
366
+ check_longrepr (report .longrepr )
367
+
368
+ data = report ._to_json ()
369
+ loaded_report = TestReport ._from_json (data )
370
+
371
+ assert loaded_report .failed
372
+ check_longrepr (loaded_report .longrepr )
373
+
374
+ # for same reasons as previous test, ensure we don't blow up here
375
+ loaded_report .longrepr .toterminal (tw_mock )
376
+
315
377
316
378
class TestHooks :
317
379
"""Test that the hooks are working correctly for plugins"""
0 commit comments