@@ -17,7 +17,7 @@ use self::{
1717
1818use std:: {
1919 collections:: { BTreeMap , BTreeSet } ,
20- fmt:: { Debug , Display } ,
20+ fmt:: { self , Debug , Display , Formatter } ,
2121 fs,
2222 hash:: Hash ,
2323 io:: { self , BufReader , BufWriter } ,
@@ -753,8 +753,55 @@ fn run(cli: Cli) -> ExitCode {
753753 "from metadata files, analyzing results…"
754754 ) ) ;
755755
756- type TestSet = BTreeSet < Arc < SectionHeader > > ;
757- type SubtestByTestSet = BTreeMap < Arc < SectionHeader > , IndexSet < Arc < SectionHeader > > > ;
756+ #[ derive( Clone , Default ) ]
757+ struct PermaAndIntermittent < T > {
758+ perma : T ,
759+ intermittent : T ,
760+ }
761+
762+ impl < T > Debug for PermaAndIntermittent < T >
763+ where
764+ T : Debug ,
765+ {
766+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
767+ let Self {
768+ perma,
769+ intermittent,
770+ } = self ;
771+ f. debug_struct ( "" ) // the name is distracting, blank it out plz
772+ . field ( "perma" , perma)
773+ . field ( "intermittent" , intermittent)
774+ . finish ( )
775+ }
776+ }
777+
778+ impl < T > PermaAndIntermittent < T > {
779+ pub fn as_ref ( & self ) -> PermaAndIntermittent < & T > {
780+ let Self {
781+ perma,
782+ intermittent,
783+ } = self ;
784+ PermaAndIntermittent {
785+ perma,
786+ intermittent,
787+ }
788+ }
789+
790+ pub fn map < U > ( self , f : impl Fn ( T ) -> U ) -> PermaAndIntermittent < U > {
791+ let Self {
792+ perma,
793+ intermittent,
794+ } = self ;
795+ PermaAndIntermittent {
796+ perma : f ( perma) ,
797+ intermittent : f ( intermittent) ,
798+ }
799+ }
800+ }
801+
802+ type TestSet = PermaAndIntermittent < BTreeSet < Arc < SectionHeader > > > ;
803+ type SubtestByTestSet =
804+ PermaAndIntermittent < BTreeMap < Arc < SectionHeader > , IndexSet < Arc < SectionHeader > > > > ;
758805
759806 #[ derive( Clone , Debug , Default ) ]
760807 struct PerPlatformAnalysis {
@@ -844,57 +891,101 @@ fn run(cli: Cli) -> ExitCode {
844891 analysis. for_each_platform_mut ( |analysis| {
845892 analysis
846893 . tests_with_disabled_or_skip
894+ . perma
847895 . insert ( test_name. clone ( ) ) ;
848896 } )
849897 }
850898
851- fn apply_expectation < Out , F > ( expectation : Expectation < Out > , f : F )
852- where
853- F : FnMut ( Out ) ,
854- Out : EnumSetType ,
899+ fn insert_in_test_set < Out > (
900+ poi : & mut TestSet ,
901+ test_name : & Arc < SectionHeader > ,
902+ expectation : Expectation < Out > ,
903+ outcome : Out ,
904+ ) where
905+ Out : Debug + Default + EnumSetType ,
906+ {
907+ if expectation. is_superset ( & Expectation :: permanent ( outcome) ) {
908+ if expectation. is_permanent ( ) {
909+ & mut poi. perma
910+ } else {
911+ & mut poi. intermittent
912+ }
913+ . insert ( test_name. clone ( ) ) ;
914+ }
915+ }
916+
917+ fn insert_in_subtest_by_test_set < Out > (
918+ poi : & mut SubtestByTestSet ,
919+ test_name : & Arc < SectionHeader > ,
920+ subtest_name : & Arc < SectionHeader > ,
921+ expectation : Expectation < Out > ,
922+ outcome : Out ,
923+ ) where
924+ Out : Debug + Default + EnumSetType ,
855925 {
856- expectation. into_iter ( ) . for_each ( f)
926+ if expectation. is_superset ( & Expectation :: permanent ( outcome) ) {
927+ if expectation. is_permanent ( ) {
928+ & mut poi. perma
929+ } else {
930+ & mut poi. intermittent
931+ }
932+ . entry ( test_name. clone ( ) )
933+ . or_default ( )
934+ . insert ( subtest_name. clone ( ) ) ;
935+ }
857936 }
937+
858938 if let Some ( expectations) = expectations {
859939 fn analyze_test_outcome < F > (
860940 test_name : & Arc < SectionHeader > ,
861- outcome : TestOutcome ,
941+ expectation : Expectation < TestOutcome > ,
862942 mut receiver : F ,
863943 ) where
864944 F : FnMut ( & mut dyn FnMut ( & mut PerPlatformAnalysis ) ) ,
865945 {
866- match outcome {
867- TestOutcome :: Ok => ( ) ,
868- // We skip this because this test _should_ contain subtests with
869- // `TIMEOUT` and `NOTRUN`, so we shouldn't actually miss anything.
870- TestOutcome :: Timeout => ( ) ,
871- TestOutcome :: Crash => receiver ( & mut |analysis| {
872- analysis. tests_with_crashes . insert ( test_name. clone ( ) ) ;
873- } ) ,
874- TestOutcome :: Error => receiver ( & mut |analysis| {
875- analysis. tests_with_runner_errors . insert ( test_name. clone ( ) ) ;
876- } ) ,
877- TestOutcome :: Skip => receiver ( & mut |analysis| {
878- analysis
879- . tests_with_disabled_or_skip
880- . insert ( test_name. clone ( ) ) ;
881- } ) ,
946+ for outcome in expectation. iter ( ) {
947+ match outcome {
948+ TestOutcome :: Ok => ( ) ,
949+ // We skip this because this test _should_ contain subtests with
950+ // `TIMEOUT` and `NOTRUN`, so we shouldn't actually miss anything.
951+ TestOutcome :: Timeout => ( ) ,
952+ TestOutcome :: Crash => receiver ( & mut |analysis| {
953+ insert_in_test_set (
954+ & mut analysis. tests_with_crashes ,
955+ test_name,
956+ expectation,
957+ outcome,
958+ )
959+ } ) ,
960+ TestOutcome :: Error => receiver ( & mut |analysis| {
961+ insert_in_test_set (
962+ & mut analysis. tests_with_runner_errors ,
963+ test_name,
964+ expectation,
965+ outcome,
966+ )
967+ } ) ,
968+ TestOutcome :: Skip => receiver ( & mut |analysis| {
969+ insert_in_test_set (
970+ & mut analysis. tests_with_disabled_or_skip ,
971+ test_name,
972+ expectation,
973+ outcome,
974+ )
975+ } ) ,
976+ }
882977 }
883978 }
884979
885980 let apply_to_all_platforms = |analysis : & mut Analysis , expectation| {
886- apply_expectation ( expectation, |outcome| {
887- analyze_test_outcome ( & test_name, outcome, |f| {
888- analysis. for_each_platform_mut ( f)
889- } )
981+ analyze_test_outcome ( & test_name, expectation, |f| {
982+ analysis. for_each_platform_mut ( f)
890983 } )
891984 } ;
892985 let apply_to_specific_platforms =
893986 |analysis : & mut Analysis , platform, expectation| {
894- apply_expectation ( expectation, |outcome| {
895- analyze_test_outcome ( & test_name, outcome, |f| {
896- analysis. for_platform_mut ( platform, f)
897- } )
987+ analyze_test_outcome ( & test_name, expectation, |f| {
988+ analysis. for_platform_mut ( platform, f)
898989 } )
899990 } ;
900991
@@ -944,59 +1035,67 @@ fn run(cli: Cli) -> ExitCode {
9441035 analysis
9451036 . windows
9461037 . tests_with_disabled_or_skip
1038+ . perma
9471039 . insert ( test_name. clone ( ) ) ;
9481040 }
9491041
9501042 if let Some ( expectations) = expectations {
9511043 fn analyze_subtest_outcome < Fo > (
9521044 test_name : & Arc < SectionHeader > ,
9531045 subtest_name : & Arc < SectionHeader > ,
954- outcome : SubtestOutcome ,
1046+ expectation : Expectation < SubtestOutcome > ,
9551047 mut receiver : Fo ,
9561048 ) where
9571049 Fo : FnMut ( & mut dyn FnMut ( & mut PerPlatformAnalysis ) ) ,
9581050 {
959- match outcome {
960- SubtestOutcome :: Pass => ( ) ,
961- SubtestOutcome :: Timeout | SubtestOutcome :: NotRun => {
962- receiver ( & mut |analysis| {
963- analysis
964- . subtests_with_timeouts_by_test
965- . entry ( test_name. clone ( ) )
966- . or_default ( )
967- . insert ( subtest_name. clone ( ) ) ;
968- } )
1051+ for outcome in expectation. iter ( ) {
1052+ match outcome {
1053+ SubtestOutcome :: Pass => ( ) ,
1054+ SubtestOutcome :: Timeout | SubtestOutcome :: NotRun => {
1055+ receiver ( & mut |analysis| {
1056+ insert_in_subtest_by_test_set (
1057+ & mut analysis. subtests_with_timeouts_by_test ,
1058+ test_name,
1059+ subtest_name,
1060+ expectation,
1061+ outcome,
1062+ )
1063+ } )
1064+ }
1065+ SubtestOutcome :: Crash => receiver ( & mut |analysis| {
1066+ insert_in_test_set (
1067+ & mut analysis. tests_with_crashes ,
1068+ test_name,
1069+ expectation,
1070+ outcome,
1071+ )
1072+ } ) ,
1073+ SubtestOutcome :: Fail => receiver ( & mut |analysis| {
1074+ insert_in_subtest_by_test_set (
1075+ & mut analysis. subtests_with_failures_by_test ,
1076+ test_name,
1077+ subtest_name,
1078+ expectation,
1079+ outcome,
1080+ )
1081+ } ) ,
9691082 }
970- SubtestOutcome :: Crash => receiver ( & mut |analysis| {
971- analysis. tests_with_crashes . insert ( test_name. clone ( ) ) ;
972- } ) ,
973- SubtestOutcome :: Fail => receiver ( & mut |analysis| {
974- analysis
975- . subtests_with_failures_by_test
976- . entry ( test_name. clone ( ) )
977- . or_default ( )
978- . insert ( subtest_name. clone ( ) ) ;
979- } ) ,
9801083 }
9811084 }
9821085
9831086 let apply_to_all_platforms = |analysis : & mut Analysis , expectation| {
984- apply_expectation ( expectation, |outcome| {
985- analyze_subtest_outcome ( & test_name, & subtest_name, outcome, |f| {
986- analysis. for_each_platform_mut ( f)
987- } )
1087+ analyze_subtest_outcome ( & test_name, & subtest_name, expectation, |f| {
1088+ analysis. for_each_platform_mut ( f)
9881089 } )
9891090 } ;
9901091 let apply_to_specific_platforms =
9911092 |analysis : & mut Analysis , platform, expectation| {
992- apply_expectation ( expectation, |outcome| {
993- analyze_subtest_outcome (
994- & test_name,
995- & subtest_name,
996- outcome,
997- |f| analysis. for_platform_mut ( platform, f) ,
998- )
999- } )
1093+ analyze_subtest_outcome (
1094+ & test_name,
1095+ & subtest_name,
1096+ expectation,
1097+ |f| analysis. for_platform_mut ( platform, f) ,
1098+ )
10001099 } ;
10011100
10021101 match expectations. into_inner ( ) {
@@ -1047,29 +1146,75 @@ fn run(cli: Cli) -> ExitCode {
10471146 subtests_with_timeouts_by_test,
10481147 } = analysis;
10491148
1050- let num_tests_with_runner_errors = tests_with_runner_errors. len ( ) ;
1051- let num_tests_with_disabled = tests_with_disabled_or_skip. len ( ) ;
1052- let num_tests_with_crashes = tests_with_crashes. len ( ) ;
1053- let num_tests_with_failures_somewhere = subtests_with_failures_by_test. len ( ) ;
1054- let num_subtests_with_failures_somewhere = subtests_with_failures_by_test
1055- . iter ( )
1056- . flat_map ( |( _name, subtests) | subtests. iter ( ) )
1057- . count ( ) ;
1058- let num_tests_with_timeouts_somewhere = subtests_with_timeouts_by_test. len ( ) ;
1059- let num_subtests_with_timeouts_somewhere = subtests_with_timeouts_by_test
1060- . iter ( )
1061- . flat_map ( |( _name, subtests) | subtests. iter ( ) )
1062- . count ( ) ;
1149+ let PermaAndIntermittent {
1150+ perma : num_tests_with_perma_runner_errors,
1151+ intermittent : num_tests_with_intermittent_runner_errors,
1152+ } = tests_with_runner_errors. as_ref ( ) . map ( |tests| tests. len ( ) ) ;
1153+
1154+ let PermaAndIntermittent {
1155+ perma : num_tests_with_disabled,
1156+ intermittent : num_tests_with_intermittent_disabled,
1157+ } = tests_with_disabled_or_skip
1158+ . as_ref ( )
1159+ . map ( |tests| tests. len ( ) ) ;
1160+ let PermaAndIntermittent {
1161+ perma : num_tests_with_perma_crashes,
1162+ intermittent : num_tests_with_intermittent_crashes,
1163+ } = tests_with_crashes. as_ref ( ) . map ( |tests| tests. len ( ) ) ;
1164+ let PermaAndIntermittent {
1165+ perma : num_tests_with_perma_failures_somewhere,
1166+ intermittent : num_tests_with_intermittent_failures_somewhere,
1167+ } = subtests_with_failures_by_test
1168+ . as_ref ( )
1169+ . map ( |tests| tests. len ( ) ) ;
1170+ let PermaAndIntermittent {
1171+ perma : num_subtests_with_perma_failures_somewhere,
1172+ intermittent : num_subtests_with_intermittent_failures_somewhere,
1173+ } = subtests_with_failures_by_test. as_ref ( ) . map ( |tests| {
1174+ tests
1175+ . iter ( )
1176+ . flat_map ( |( _name, subtests) | subtests. iter ( ) )
1177+ . count ( )
1178+ } ) ;
1179+ let PermaAndIntermittent {
1180+ perma : num_tests_with_perma_timeouts_somewhere,
1181+ intermittent : num_tests_with_intermittent_timeouts_somewhere,
1182+ } = subtests_with_timeouts_by_test
1183+ . as_ref ( )
1184+ . map ( |tests| tests. len ( ) ) ;
1185+ let PermaAndIntermittent {
1186+ perma : num_subtests_with_perma_timeouts_somewhere,
1187+ intermittent : num_subtests_with_intermittent_timeouts_somewhere,
1188+ } = subtests_with_timeouts_by_test. as_ref ( ) . map ( |tests| {
1189+ tests
1190+ . iter ( )
1191+ . flat_map ( |( _name, subtests) | subtests. iter ( ) )
1192+ . count ( )
1193+ } ) ;
1194+
1195+ if num_tests_with_intermittent_disabled > 0 {
1196+ log:: warn!(
1197+ concat!( "found {} intermittent `SKIP` outcomes, which we don't understand yet; figure it out! The tests: {:#?}" ) ,
1198+ num_tests_with_intermittent_disabled,
1199+ tests_with_disabled_or_skip,
1200+ )
1201+ }
1202+
10631203 println ! (
10641204 "\
10651205 {platform:?}:
10661206 HIGH PRIORITY:
1067- {num_tests_with_runner_errors } test(s) with execution reporting `ERROR`
1207+ {num_tests_with_perma_runner_errors } test(s) with execution reporting permanent `ERROR`
10681208 {num_tests_with_disabled} test(s) with some portion marked as `disabled`
1069- {num_tests_with_crashes } test(s) with some portion expecting `CRASH`
1209+ {num_tests_with_perma_crashes } test(s) with some portion expecting permanent `CRASH`
10701210 MEDIUM PRIORITY:
1071- {num_tests_with_failures_somewhere} test(s) with some portion `FAIL`ing, {num_subtests_with_failures_somewhere} subtests total
1072- {num_tests_with_timeouts_somewhere} test(s) with some portion returning `TIMEOUT`/`NOTRUN`, {num_subtests_with_timeouts_somewhere} subtests total
1211+ {num_tests_with_perma_failures_somewhere} test(s) with some portion perma-`FAIL`ing, {num_subtests_with_perma_failures_somewhere} subtests total
1212+ {num_tests_with_perma_timeouts_somewhere} test(s) with some portion returning permanent `TIMEOUT`/`NOTRUN`, {num_subtests_with_perma_timeouts_somewhere} subtests total
1213+ {num_tests_with_intermittent_crashes} tests(s) with some portion expecting intermittent `CRASH`
1214+ {num_tests_with_intermittent_runner_errors} test(s) with execution reporting intermittent `ERROR`
1215+ LOW PRIORITY:
1216+ {num_tests_with_intermittent_timeouts_somewhere} test(s) with some portion intermittently returning `TIMEOUT`/`NOTRUN`, {num_subtests_with_intermittent_timeouts_somewhere} subtest(s) total
1217+ {num_tests_with_intermittent_failures_somewhere} test(s) with some portion intermittently `FAIL`ing, {num_subtests_with_intermittent_failures_somewhere} subtests total
10731218"
10741219 ) ;
10751220 } ) ;
0 commit comments