git_perf/
data.rs

1use std::collections::HashMap;
2
3#[derive(Debug, Clone, Copy)]
4pub struct MeasurementSummary {
5    pub epoch: u32,
6    pub val: f64,
7}
8
9#[derive(Debug)]
10pub struct CommitSummary {
11    pub commit: String,
12    pub measurement: Option<MeasurementSummary>,
13}
14
15#[derive(Debug, PartialEq, Clone)]
16pub struct MeasurementData {
17    pub epoch: u32,
18    pub name: String,
19    pub timestamp: f64,
20    pub val: f64,
21    pub key_values: HashMap<String, String>,
22}
23
24// TODO double check CLONE addition
25#[derive(Debug, PartialEq, Clone)]
26pub struct Commit {
27    pub commit: String,
28    pub title: String,
29    pub author: String,
30    pub measurements: Vec<MeasurementData>,
31}
32
33impl MeasurementData {
34    /// Checks if this measurement matches all the specified key-value criteria.
35    /// Returns true if all key-value pairs in `criteria` exist in this measurement
36    /// with matching values.
37    #[must_use]
38    pub fn matches_key_values(&self, criteria: &[(String, String)]) -> bool {
39        self.key_values_is_superset_of(criteria)
40    }
41
42    /// Checks if this measurement's key-values form a superset of the given criteria.
43    /// In other words, verifies that criteria ⊆ measurement.key_values.
44    /// Returns true if all key-value pairs in `criteria` exist in this measurement's
45    /// key_values with matching values.
46    #[must_use]
47    pub fn key_values_is_superset_of(&self, criteria: &[(String, String)]) -> bool {
48        criteria
49            .iter()
50            .all(|(k, v)| self.key_values.get(k).map(|mv| v == mv).unwrap_or(false))
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57
58    #[test]
59    fn test_matches_key_values() {
60        let mut key_values = HashMap::new();
61        key_values.insert("env".to_string(), "production".to_string());
62        key_values.insert("branch".to_string(), "main".to_string());
63        key_values.insert("cpu".to_string(), "x64".to_string());
64
65        let measurement = MeasurementData {
66            epoch: 1,
67            name: "test_measurement".to_string(),
68            timestamp: 1234567890.0,
69            val: 42.0,
70            key_values,
71        };
72
73        // Test empty criteria (should always match)
74        assert!(measurement.matches_key_values(&[]));
75
76        // Test single matching criterion
77        assert!(measurement.matches_key_values(&[("env".to_string(), "production".to_string())]));
78
79        // Test multiple matching criteria
80        assert!(measurement.matches_key_values(&[
81            ("env".to_string(), "production".to_string()),
82            ("branch".to_string(), "main".to_string()),
83        ]));
84
85        // Test all matching criteria
86        assert!(measurement.matches_key_values(&[
87            ("env".to_string(), "production".to_string()),
88            ("branch".to_string(), "main".to_string()),
89            ("cpu".to_string(), "x64".to_string()),
90        ]));
91
92        // Test non-matching value
93        assert!(!measurement.matches_key_values(&[("env".to_string(), "staging".to_string())]));
94
95        // Test non-existing key
96        assert!(!measurement.matches_key_values(&[("os".to_string(), "linux".to_string())]));
97
98        // Test mixed (some match, some don't) - should fail
99        assert!(!measurement.matches_key_values(&[
100            ("env".to_string(), "production".to_string()), // matches
101            ("branch".to_string(), "develop".to_string()), // doesn't match
102        ]));
103    }
104}