speccoder_runtime/collection/
junit_map.rs1use std::collections::BTreeMap;
5
6use speccoder_core::collection::{go_id_matches, python_id_matches, rust_tests_by_file};
7
8#[derive(Debug, Clone)]
10pub enum Place {
11 Rust(BTreeMap<String, Vec<(String, String)>>),
13 Python,
15 Js(String),
17 Go(String, Vec<String>),
19}
20
21#[must_use]
23pub fn tests_of(place: &Place, path: &str, ids: &[String]) -> Vec<String> {
24 match place {
25 Place::Rust(reach) => rust_tests_by_file(reach, ids)
26 .remove(path)
27 .unwrap_or_default(),
28 Place::Python => ids
29 .iter()
30 .filter(|id| python_id_matches(path, id))
31 .cloned()
32 .collect(),
33 Place::Js(rel) => ids
34 .iter()
35 .filter(|id| {
36 [path, rel.as_str()].iter().any(|p| {
37 *id == p
38 || id.starts_with(&format!("{p}::"))
39 || id.starts_with(&format!("{p} "))
40 })
41 })
42 .cloned()
43 .collect(),
44 Place::Go(import, names) => ids
45 .iter()
46 .filter(|id| go_id_matches(import, names, id))
47 .cloned()
48 .collect(),
49 }
50}
51
52#[must_use]
55pub fn listed(place: &Place, path: &str, lines: &[String]) -> Vec<String> {
56 let mut out: Vec<String> = lines
57 .iter()
58 .filter(|l| *l == path || l.starts_with(&format!("{path}::")))
59 .cloned()
60 .collect();
61 if out.is_empty() {
62 out = tests_of(place, path, lines);
63 }
64 out
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 #[test]
72 fn ids_map_per_toolchain() {
73 let ids = |v: &[&str]| v.iter().map(|s| (*s).to_owned()).collect::<Vec<_>>();
74 assert_eq!(
75 tests_of(
76 &Place::Js("src/a.test.ts".into()),
77 "web/src/a.test.ts",
78 &ids(&["src/a.test.ts::greets", "src/b.test.ts::x"])
79 ),
80 ["src/a.test.ts::greets"]
81 );
82 assert_eq!(
83 tests_of(
84 &Place::Go("ex.com/m/g".into(), vec!["TestA".into()]),
85 "g/a_test.go",
86 &ids(&["ex.com/m/g::TestA", "ex.com/m/g::TestB"])
87 ),
88 ["ex.com/m/g::TestA"]
89 );
90 assert_eq!(
91 listed(
92 &Place::Python,
93 "tests/test_a.py",
94 &ids(&["tests/test_a.py", "tests/test_b.py"])
95 ),
96 ["tests/test_a.py"]
97 );
98 }
99}