aws_runtime/user_agent/
test_util.rs

1/*
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6//! Utilities for testing the User-Agent header
7
8use regex_lite::Regex;
9use std::sync::LazyLock;
10
11// regular expression pattern for base64 numeric values
12#[allow(dead_code)]
13static RE: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"m/([A-Za-z0-9+/=_,-]+)").unwrap());
14
15/// Asserts `user_agent` contains all metric values `values`
16///
17/// Refer to the end of the parent module file `user_agent.rs` for the complete ABNF specification
18/// of `business-metrics`.
19pub fn assert_ua_contains_metric_values(user_agent: &str, values: &[&str]) {
20    match extract_ua_values(user_agent) {
21        Some(metrics) => {
22            let mut missed = vec![];
23
24            for value in values.iter() {
25                if !metrics.contains(value) {
26                    missed.push(value);
27                }
28            }
29            assert!(
30                missed.is_empty(),
31                "{}",
32                format!("metric values {missed:?} not found in `{user_agent}`")
33            );
34        }
35        None => {
36            panic!("{}", format!("the pattern for business-metrics `m/(metric_id) *(comma metric_id)` not found in `{user_agent}`"))
37        }
38    }
39}
40
41/// Extract the metric values from the `user_agent` string
42pub fn extract_ua_values(user_agent: &str) -> Option<Vec<&str>> {
43    RE.find(user_agent).map(|matched| {
44        matched
45            .as_str()
46            .strip_prefix("m/")
47            .expect("prefix `m/` is guaranteed to exist by regex match")
48            .split(',')
49            .collect()
50    })
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    #[test]
58    fn test_assert_ua_contains_metric_values() {
59        assert_ua_contains_metric_values("m/A", &[]);
60        assert_ua_contains_metric_values("m/A", &["A"]);
61        assert_ua_contains_metric_values(" m/A", &["A"]);
62        assert_ua_contains_metric_values("m/A ", &["A"]);
63        assert_ua_contains_metric_values(" m/A ", &["A"]);
64        assert_ua_contains_metric_values("m/A,B", &["B"]);
65        assert_ua_contains_metric_values("m/A,B", &["A", "B"]);
66        assert_ua_contains_metric_values("m/A,B", &["B", "A"]);
67        assert_ua_contains_metric_values("m/A,B,C", &["B"]);
68        assert_ua_contains_metric_values("m/A,B,C", &["B", "C"]);
69        assert_ua_contains_metric_values("m/A,B,C", &["A", "B", "C"]);
70        assert_ua_contains_metric_values("m/A,B,C,AA", &["AA"]);
71        assert_ua_contains_metric_values("m/A,B,C=,AA", &["C="]);
72        assert_ua_contains_metric_values(
73            "aws-sdk-rust/0.123.test api/test-service/0.123 os/windows/XPSP3 lang/rust/1.50.0 m/A",
74            &["A"],
75        );
76        assert_ua_contains_metric_values(
77            "aws-sdk-rust/0.123.test api/test-service/0.123 os/windows/XPSP3 lang/rust/1.50.0 m/A md/http#capture-request-handler",
78            &["A"]
79        );
80    }
81
82    #[test]
83    #[should_panic(expected = "the pattern for business-metrics")]
84    fn empty_ua_fails_assert() {
85        assert_ua_contains_metric_values("", &["A"]);
86    }
87
88    #[test]
89    #[should_panic(expected = "the pattern for business-metrics")]
90    fn invalid_business_metrics_pattern_fails_assert() {
91        assert_ua_contains_metric_values("mA", &["A"]);
92    }
93
94    #[test]
95    #[should_panic(expected = "the pattern for business-metrics")]
96    fn another_invalid_business_metrics_pattern_fails_assert() {
97        assert_ua_contains_metric_values("m/", &["A"]);
98    }
99
100    #[test]
101    #[should_panic(expected = "metric values [\"\"] not found in `m/A`")]
102    fn empty_metric_value_fails_assert() {
103        assert_ua_contains_metric_values("m/A", &[""]);
104    }
105
106    #[test]
107    #[should_panic(expected = "metric values [\"A\"] not found in `m/AA`")]
108    fn business_metrics_do_not_contain_given_metric_value() {
109        assert_ua_contains_metric_values("m/AA", &["A"]);
110    }
111
112    #[test]
113    #[should_panic(expected = "the pattern for business-metrics")]
114    fn ua_containing_no_business_metrics_fails_assert() {
115        assert_ua_contains_metric_values(
116            "aws-sdk-rust/0.123.test api/test-service/0.123 os/windows/XPSP3 lang/rust/1.50.0",
117            &["A"],
118        );
119    }
120
121    #[test]
122    #[should_panic(expected = "the pattern for business-metrics")]
123    fn ua_containing_invalid_business_metrics_fails_assert() {
124        assert_ua_contains_metric_values(
125            "aws-sdk-rust/0.123.test api/test-service/0.123 os/windows/XPSP3 lang/rust/1.50.0 mA",
126            &["A"],
127        );
128    }
129}