git_perf/
data.rs

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