@@ -305,13 +305,69 @@ 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
+ from concurrent.futures import ProcessPoolExecutor
329
+
330
+ def func():
331
+ raise ValueError('value error')
332
+
333
+ def test_a():
334
+ with ProcessPoolExecutor() as p:
335
+ p.submit(func).result()
336
+ """
337
+ )
338
+ reprec = testdir .inline_run ()
339
+
340
+ reports = reprec .getreports ("pytest_runtest_logreport" )
341
+
342
+ def check_longrepr (longrepr ):
343
+ assert isinstance (longrepr , ExceptionChainRepr )
344
+ assert len (longrepr .chain ) == 2
345
+ entry1 , entry2 = longrepr .chain
346
+ tb1 , fileloc1 , desc1 = entry1
347
+ tb2 , fileloc2 , desc2 = entry2
348
+
349
+ assert "RemoteTraceback" in str (tb1 )
350
+ assert "ValueError: value error" in str (tb2 )
351
+
352
+ assert fileloc1 is None
353
+ assert fileloc2 .message == "ValueError: value error"
354
+
355
+ # 3 reports: setup/call/teardown: get the call report
356
+ assert len (reports ) == 3
357
+ report = reports [1 ]
358
+
359
+ assert report .failed
360
+ check_longrepr (report .longrepr )
361
+
362
+ data = report ._to_json ()
363
+ loaded_report = TestReport ._from_json (data )
364
+
365
+ assert loaded_report .failed
366
+ check_longrepr (loaded_report .longrepr )
367
+
368
+ # for same reasons as previous test, ensure we don't blow up here
369
+ loaded_report .longrepr .toterminal (tw_mock )
370
+
315
371
316
372
class TestHooks :
317
373
"""Test that the hooks are working correctly for plugins"""
0 commit comments