@@ -409,59 +409,58 @@ def build_coverage_cache( # pylint: disable=unused-argument,too-many-locals,too
409409 cons .print ()
410410
411411 gcda_dir = tempfile .mkdtemp (prefix = "mfc_gcov_" )
412-
413- # Phase 1: Run all tests in parallel via direct binary invocation.
414- cons .print ("[bold]Phase 1/2: Running tests...[/bold]" )
415- test_results : dict = {}
416- all_failures : dict = {}
417- with ThreadPoolExecutor (max_workers = n_jobs ) as pool :
418- futures = {
419- pool .submit (_run_single_test_direct , info , gcda_dir , strip ): info
420- for info in test_infos
421- }
422- for i , future in enumerate (as_completed (futures )):
423- uuid , test_gcda , failures = future .result ()
424- test_results [uuid ] = test_gcda
425- if failures :
426- all_failures [uuid ] = failures
412+ try :
413+ # Phase 1: Run all tests in parallel via direct binary invocation.
414+ cons .print ("[bold]Phase 1/2: Running tests...[/bold]" )
415+ test_results : dict = {}
416+ all_failures : dict = {}
417+ with ThreadPoolExecutor (max_workers = n_jobs ) as pool :
418+ futures = {
419+ pool .submit (_run_single_test_direct , info , gcda_dir , strip ): info
420+ for info in test_infos
421+ }
422+ for i , future in enumerate (as_completed (futures )):
423+ uuid , test_gcda , failures = future .result ()
424+ test_results [uuid ] = test_gcda
425+ if failures :
426+ all_failures [uuid ] = failures
427+ if (i + 1 ) % 50 == 0 or (i + 1 ) == len (cases ):
428+ cons .print (f" [{ i + 1 :3d} /{ len (cases ):3d} ] tests completed" )
429+
430+ if all_failures :
431+ cons .print ()
432+ cons .print (f"[bold yellow]Warning: { len (all_failures )} tests had target failures:[/bold yellow]" )
433+ for uuid , fails in sorted (all_failures .items ()):
434+ fail_str = ", " .join (f"{ t } ={ rc } " for t , rc in fails )
435+ cons .print (f" [yellow]{ uuid } [/yellow]: { fail_str } " )
436+
437+ # Phase 2: Collect gcov coverage from each test's isolated .gcda directory.
438+ # For each test, copy its .gcda files into the build tree, run gcov only
439+ # on matching .gcno files (not all 414), then clean up. Targeting matching
440+ # .gcno files gives ~8x speedup over the full scan.
441+ cons .print ()
442+ cons .print ("[bold]Phase 2/2: Collecting coverage...[/bold]" )
443+ cache : dict = {}
444+ for i , (uuid , test_gcda ) in enumerate (sorted (test_results .items ())):
445+ zero_gcda_files (root_dir )
446+ n_copied = _install_gcda_files (test_gcda , root_dir )
447+
448+ if n_copied == 0 :
449+ coverage = set ()
450+ else :
451+ # Only run gcov on .gcno files that have a matching .gcda installed.
452+ matching = _find_matching_gcno (root_dir )
453+ coverage = collect_coverage_for_test (
454+ matching or gcno_files , root_dir , gcov_bin
455+ )
456+
457+ cache [uuid ] = sorted (coverage )
427458 if (i + 1 ) % 50 == 0 or (i + 1 ) == len (cases ):
428- cons .print (f" [{ i + 1 :3d} /{ len (cases ):3d} ] tests completed " )
459+ cons .print (f" [{ i + 1 :3d} /{ len (cases ):3d} ] tests processed " )
429460
430- if all_failures :
431- cons .print ()
432- cons .print (f"[bold yellow]Warning: { len (all_failures )} tests had target failures:[/bold yellow]" )
433- for uuid , fails in sorted (all_failures .items ()):
434- fail_str = ", " .join (f"{ t } ={ rc } " for t , rc in fails )
435- cons .print (f" [yellow]{ uuid } [/yellow]: { fail_str } " )
436-
437- # Phase 2: Collect gcov coverage from each test's isolated .gcda directory.
438- # For each test, copy its .gcda files into the build tree, run gcov only
439- # on matching .gcno files (not all 414), then clean up. Targeting matching
440- # .gcno files gives ~8x speedup over the full scan.
441- cons .print ()
442- cons .print ("[bold]Phase 2/2: Collecting coverage...[/bold]" )
443- cache : dict = {}
444- for i , (uuid , test_gcda ) in enumerate (sorted (test_results .items ())):
445461 zero_gcda_files (root_dir )
446- n_copied = _install_gcda_files (test_gcda , root_dir )
447-
448- if n_copied == 0 :
449- coverage = set ()
450- else :
451- # Only run gcov on .gcno files that have a matching .gcda installed.
452- matching = _find_matching_gcno (root_dir )
453- coverage = collect_coverage_for_test (
454- matching or gcno_files , root_dir , gcov_bin
455- )
456-
457- cache [uuid ] = sorted (coverage )
458- if (i + 1 ) % 50 == 0 or (i + 1 ) == len (cases ):
459- cons .print (f" [{ i + 1 :3d} /{ len (cases ):3d} ] tests processed" )
460-
461- zero_gcda_files (root_dir )
462-
463- # Clean up temp directory.
464- shutil .rmtree (gcda_dir , ignore_errors = True )
462+ finally :
463+ shutil .rmtree (gcda_dir , ignore_errors = True )
465464
466465 # Sanity check: at least some tests should have non-empty coverage.
467466 tests_with_coverage = sum (1 for v in cache .values () if v )
0 commit comments