Skip to content

Commit 21c83b6

Browse files
Merge pull request #74 from ErichDonGubler/relocate-internal-cts-paths
`process-reports`: Relocate WPT tests based on WebGPU CTS paths
2 parents 45923a8 + 57238af commit 21c83b6

1 file changed

Lines changed: 190 additions & 109 deletions

File tree

moz-webgpu-cts/src/main.rs

Lines changed: 190 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,24 @@ fn run(cli: Cli) -> ExitCode {
325325
files
326326
};
327327

328+
#[derive(Debug, Default)]
329+
struct EntryByCtsPath<'a> {
330+
metadata_path: Option<TestPath<'a>>,
331+
reported_path: Option<TestPath<'a>>,
332+
entry: TestEntry,
333+
}
334+
335+
fn cts_path(test_path: &TestPath<'_>) -> Option<String> {
336+
test_path
337+
.variant
338+
.as_ref()
339+
.filter(|v| v.starts_with("?q=webgpu:"))
340+
.map(|v| v.strip_prefix("?q=").unwrap().to_owned())
341+
.filter(|_q| test_path.path.ends_with("cts.https.html"))
342+
}
343+
328344
let mut file_props_by_file = IndexMap::<Utf8PathBuf, FileProps>::default();
345+
let mut entries_by_cts_path = IndexMap::<String, EntryByCtsPath<'_>>::default();
329346
let mut other_entries_by_test = IndexMap::<TestPath<'_>, TestEntry>::default();
330347
let old_meta_file_paths = meta_files_by_path.keys().cloned().collect::<Vec<_>>();
331348

@@ -370,9 +387,19 @@ fn run(cli: Cli) -> ExitCode {
370387
let TestEntry {
371388
entry: test_entry,
372389
subtests: subtest_entries,
373-
} = other_entries_by_test
374-
.entry(test_path.clone().into_owned())
375-
.or_default();
390+
} = if let Some(cts_path) = cts_path(&test_path) {
391+
let entry = entries_by_cts_path.entry(cts_path).or_default();
392+
if let Some(_old) =
393+
entry.metadata_path.replace(test_path.clone().into_owned())
394+
{
395+
dupe_err();
396+
}
397+
&mut entry.entry
398+
} else {
399+
other_entries_by_test
400+
.entry(test_path.clone().into_owned())
401+
.or_default()
402+
};
376403

377404
let test_path = &test_path;
378405

@@ -451,9 +478,32 @@ fn run(cli: Cli) -> ExitCode {
451478
let TestEntry {
452479
entry: test_entry,
453480
subtests: subtest_entries,
454-
} = other_entries_by_test
455-
.entry(test_path.clone().into_owned())
456-
.or_default();
481+
} = if let Some(cts_path) = cts_path(&test_path) {
482+
let entry = entries_by_cts_path.entry(cts_path).or_default();
483+
if let Some(old) =
484+
entry.reported_path.replace(test_path.clone().into_owned())
485+
{
486+
if old != test_path {
487+
log::warn!(
488+
concat!(
489+
"found test execution entry containing the same ",
490+
"CTS test path as another, ",
491+
"discarding previous entries with ",
492+
"this and further dupes; entries:\n",
493+
"older: {:#?}\n",
494+
"newer: {:#?}\n",
495+
),
496+
old,
497+
test_path
498+
)
499+
}
500+
}
501+
&mut entry.entry
502+
} else {
503+
other_entries_by_test
504+
.entry(test_path.clone().into_owned())
505+
.or_default()
506+
};
457507

458508
let (reported_outcome, reported_subtests) = match result {
459509
TestExecutionResult::Complete { outcome, subtests } => (outcome, subtests),
@@ -518,119 +568,150 @@ fn run(cli: Cli) -> ExitCode {
518568
log::info!("metadata and reports gathered, now reconciling outcomes…");
519569

520570
let mut found_reconciliation_err = false;
521-
let recombined_tests_iter =
522-
other_entries_by_test
523-
.into_iter()
524-
.filter_map(|(test_path, test_entry)| {
525-
fn reconcile<Out>(
526-
entry: Entry<Out>,
527-
preset: ReportProcessingPreset,
528-
) -> TestProps<Out>
529-
where
530-
Out: Debug + Default + EnumSetType,
531-
{
532-
let Entry {
533-
meta_props,
534-
reported,
535-
} = entry;
536-
let normalize = NormalizedExpectationPropertyValue::from_fully_expanded;
537-
538-
let mut meta_props = meta_props.unwrap_or_default();
539-
meta_props.expectations = Some('resolve: {
540-
let resolve = match preset {
541-
ReportProcessingPreset::ResetAll => {
542-
break 'resolve normalize(reported);
543-
}
544-
ReportProcessingPreset::ResetContradictory => {
545-
|meta: Expectation<_>, rep: Option<Expectation<_>>| {
546-
rep.filter(|rep| !meta.is_superset(rep)).unwrap_or(meta)
547-
}
571+
let entries_by_cts_path = entries_by_cts_path.into_iter().map(|(_name, entry)| {
572+
let EntryByCtsPath {
573+
metadata_path,
574+
reported_path,
575+
entry,
576+
} = entry;
577+
let output_path = if let Some((meta, rep)) = metadata_path
578+
.as_ref()
579+
.zip(reported_path.as_ref())
580+
.filter(|(meta, rep)| meta != rep)
581+
{
582+
log::info!(
583+
concat!(
584+
"metadata path for test is different from ",
585+
"reported execution; relocating…\n",
586+
"…metadata: {:#?}\n",
587+
"…reported: {:#?}\n"
588+
),
589+
meta,
590+
rep
591+
);
592+
reported_path
593+
} else {
594+
metadata_path.or(reported_path)
595+
};
596+
597+
(
598+
output_path.expect(concat!(
599+
"internal error: CTS path entry created without at least one ",
600+
"report or metadata path specified"
601+
)),
602+
entry,
603+
)
604+
});
605+
let recombined_tests_iter = entries_by_cts_path
606+
.chain(other_entries_by_test)
607+
.filter_map(|(test_path, test_entry)| {
608+
fn reconcile<Out>(
609+
entry: Entry<Out>,
610+
preset: ReportProcessingPreset,
611+
) -> TestProps<Out>
612+
where
613+
Out: Debug + Default + EnumSetType,
614+
{
615+
let Entry {
616+
meta_props,
617+
reported,
618+
} = entry;
619+
let normalize = NormalizedExpectationPropertyValue::from_fully_expanded;
620+
621+
let mut meta_props = meta_props.unwrap_or_default();
622+
meta_props.expectations = Some('resolve: {
623+
let resolve = match preset {
624+
ReportProcessingPreset::ResetAll => {
625+
break 'resolve normalize(reported);
626+
}
627+
ReportProcessingPreset::ResetContradictory => {
628+
|meta: Expectation<_>, rep: Option<Expectation<_>>| {
629+
rep.filter(|rep| !meta.is_superset(rep)).unwrap_or(meta)
548630
}
549-
ReportProcessingPreset::Merge => |meta, rep| match rep {
550-
Some(rep) => meta | rep,
551-
None => meta,
552-
},
553-
};
554-
555-
normalize(
556-
Platform::iter()
557-
.map(|platform| {
558-
let build_profiles = BuildProfile::iter()
559-
.map(|build_profile| {
560-
(
561-
build_profile,
562-
resolve(
563-
meta_props
564-
.expectations
565-
.as_ref()
566-
.unwrap_or(&Default::default())
567-
.get(platform, build_profile),
568-
reported
569-
.get(&platform)
570-
.and_then(|rep| {
571-
rep.get(&build_profile)
572-
})
573-
.copied(),
574-
),
575-
)
576-
})
577-
.collect();
578-
(platform, build_profiles)
579-
})
580-
.collect(),
581-
)
582-
});
583-
meta_props
584-
}
631+
}
632+
ReportProcessingPreset::Merge => |meta, rep| match rep {
633+
Some(rep) => meta | rep,
634+
None => meta,
635+
},
636+
};
585637

586-
let TestEntry {
587-
entry: test_entry,
588-
subtests: subtest_entries,
589-
} = test_entry;
638+
normalize(
639+
Platform::iter()
640+
.map(|platform| {
641+
let build_profiles = BuildProfile::iter()
642+
.map(|build_profile| {
643+
(
644+
build_profile,
645+
resolve(
646+
meta_props
647+
.expectations
648+
.as_ref()
649+
.unwrap_or(&Default::default())
650+
.get(platform, build_profile),
651+
reported
652+
.get(&platform)
653+
.and_then(|rep| rep.get(&build_profile))
654+
.copied(),
655+
),
656+
)
657+
})
658+
.collect();
659+
(platform, build_profiles)
660+
})
661+
.collect(),
662+
)
663+
});
664+
meta_props
665+
}
590666

591-
if test_entry.meta_props.is_none() {
592-
log::info!("new test entry: {test_path:?}")
593-
}
667+
let TestEntry {
668+
entry: test_entry,
669+
subtests: subtest_entries,
670+
} = test_entry;
594671

595-
if test_entry.reported.is_empty() {
596-
match preset {
597-
ReportProcessingPreset::Merge => {
598-
log::warn!("no entries found in reports for {test_path:?}")
599-
}
600-
ReportProcessingPreset::ResetAll
601-
| ReportProcessingPreset::ResetContradictory => {
602-
log::warn!(
603-
"removing entry after finding no entries in reports: {:?}",
604-
test_path
605-
);
606-
return None;
607-
}
672+
if test_entry.meta_props.is_none() {
673+
log::info!("new test entry: {test_path:?}")
674+
}
675+
676+
if test_entry.reported.is_empty() {
677+
match preset {
678+
ReportProcessingPreset::Merge => {
679+
log::warn!("no entries found in reports for {test_path:?}")
680+
}
681+
ReportProcessingPreset::ResetAll
682+
| ReportProcessingPreset::ResetContradictory => {
683+
log::warn!(
684+
"removing entry after finding no entries in reports: {:?}",
685+
test_path
686+
);
687+
return None;
608688
}
609689
}
690+
}
610691

611-
let properties = reconcile(test_entry, preset);
692+
let properties = reconcile(test_entry, preset);
612693

613-
let mut subtests = BTreeMap::new();
614-
for (subtest_name, subtest) in subtest_entries {
615-
let subtest_name = SectionHeader(subtest_name);
616-
if subtests.get(&subtest_name).is_some() {
617-
found_reconciliation_err = true;
618-
log::error!("internal error: duplicate test path {test_path:?}");
619-
}
620-
subtests.insert(
621-
subtest_name,
622-
Subtest {
623-
properties: reconcile(subtest, preset),
624-
},
625-
);
694+
let mut subtests = BTreeMap::new();
695+
for (subtest_name, subtest) in subtest_entries {
696+
let subtest_name = SectionHeader(subtest_name);
697+
if subtests.get(&subtest_name).is_some() {
698+
found_reconciliation_err = true;
699+
log::error!("internal error: duplicate test path {test_path:?}");
626700
}
701+
subtests.insert(
702+
subtest_name,
703+
Subtest {
704+
properties: reconcile(subtest, preset),
705+
},
706+
);
707+
}
627708

628-
if subtests.is_empty() && properties == Default::default() {
629-
None
630-
} else {
631-
Some((test_path, (properties, subtests)))
632-
}
633-
});
709+
if subtests.is_empty() && properties == Default::default() {
710+
None
711+
} else {
712+
Some((test_path, (properties, subtests)))
713+
}
714+
});
634715

635716
log::info!(
636717
"outcome reconciliation complete, gathering tests back into new metadata files…"

0 commit comments

Comments
 (0)