diff options
Diffstat (limited to 'third_party/rust/glean-core/tests/ping_maker.rs')
-rw-r--r-- | third_party/rust/glean-core/tests/ping_maker.rs | 301 |
1 files changed, 301 insertions, 0 deletions
diff --git a/third_party/rust/glean-core/tests/ping_maker.rs b/third_party/rust/glean-core/tests/ping_maker.rs new file mode 100644 index 0000000000..29b6bccaca --- /dev/null +++ b/third_party/rust/glean-core/tests/ping_maker.rs @@ -0,0 +1,301 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +mod common; +use crate::common::*; + +use glean_core::metrics::*; +use glean_core::ping::PingMaker; +use glean_core::{CommonMetricData, Glean, Lifetime}; + +fn set_up_basic_ping() -> (Glean, PingMaker, PingType, tempfile::TempDir) { + let (tempdir, _) = tempdir(); + let (mut glean, t) = new_glean(Some(tempdir)); + let ping_maker = PingMaker::new(); + let ping_type = PingType::new("store1", true, false, true, vec![]); + glean.register_ping_type(&ping_type); + + // Record something, so the ping will have data + let metric = BooleanMetric::new(CommonMetricData { + name: "boolean_metric".into(), + category: "telemetry".into(), + send_in_pings: vec!["store1".into()], + disabled: false, + lifetime: Lifetime::User, + ..Default::default() + }); + metric.set_sync(&glean, true); + + (glean, ping_maker, ping_type, t) +} + +#[test] +fn ping_info_must_contain_a_nonempty_start_and_end_time() { + let (glean, ping_maker, ping_type, _t) = set_up_basic_ping(); + + let ping = ping_maker + .collect(&glean, &ping_type, None, "", "") + .unwrap(); + let ping_info = ping.content["ping_info"].as_object().unwrap(); + + let start_time_str = ping_info["start_time"].as_str().unwrap(); + let start_time_date = iso8601_to_chrono(&iso8601::datetime(start_time_str).unwrap()); + + let end_time_str = ping_info["end_time"].as_str().unwrap(); + let end_time_date = iso8601_to_chrono(&iso8601::datetime(end_time_str).unwrap()); + + assert!(start_time_date <= end_time_date); +} + +#[test] +fn get_ping_info_must_report_all_the_required_fields() { + let (glean, ping_maker, ping_type, _t) = set_up_basic_ping(); + + let ping = ping_maker + .collect(&glean, &ping_type, None, "", "") + .unwrap(); + let ping_info = ping.content["ping_info"].as_object().unwrap(); + + assert!(ping_info.get("start_time").is_some()); + assert!(ping_info.get("end_time").is_some()); + assert!(ping_info.get("seq").is_some()); +} + +#[test] +fn get_client_info_must_report_all_the_available_data() { + let (glean, ping_maker, ping_type, _t) = set_up_basic_ping(); + + let ping = ping_maker + .collect(&glean, &ping_type, None, "", "") + .unwrap(); + let client_info = ping.content["client_info"].as_object().unwrap(); + + client_info["telemetry_sdk_build"].as_str().unwrap(); +} + +#[test] +fn test_metrics_must_report_experimentation_id() { + let (tempdir, _) = tempdir(); + let mut glean = Glean::new(glean_core::InternalConfiguration { + data_path: tempdir.path().display().to_string(), + application_id: GLOBAL_APPLICATION_ID.into(), + language_binding_name: "Rust".into(), + upload_enabled: true, + max_events: None, + delay_ping_lifetime_io: false, + app_build: "Unknown".into(), + use_core_mps: false, + trim_data_to_registered_pings: false, + log_level: None, + rate_limit: None, + enable_event_timestamps: false, + experimentation_id: Some("test-experimentation-id".to_string()), + }) + .unwrap(); + let ping_maker = PingMaker::new(); + let ping_type = PingType::new("store1", true, false, true, vec![]); + glean.register_ping_type(&ping_type); + + // Record something, so the ping will have data + let metric = BooleanMetric::new(CommonMetricData { + name: "boolean_metric".into(), + category: "telemetry".into(), + send_in_pings: vec!["store1".into()], + disabled: false, + lifetime: Lifetime::User, + ..Default::default() + }); + metric.set_sync(&glean, true); + + let ping = ping_maker + .collect(&glean, &ping_type, None, "", "") + .unwrap(); + let metrics = ping.content["metrics"].as_object().unwrap(); + println!("TLDEBUG Metrics:\n{:?}", metrics); + + let strings = metrics["string"].as_object().unwrap(); + assert_eq!( + strings["glean.client.annotation.experimentation_id"] + .as_str() + .unwrap(), + "test-experimentation-id", + "experimentation ids must match" + ); +} + +#[test] +fn experimentation_id_is_removed_if_send_if_empty_is_false() { + // Initialize Glean with an experimentation id, it should be removed if the ping is empty + // and send_if_empty is false. + let (tempdir, _) = tempdir(); + let mut glean = Glean::new(glean_core::InternalConfiguration { + data_path: tempdir.path().display().to_string(), + application_id: GLOBAL_APPLICATION_ID.into(), + language_binding_name: "Rust".into(), + upload_enabled: true, + max_events: None, + delay_ping_lifetime_io: false, + app_build: "Unknown".into(), + use_core_mps: false, + trim_data_to_registered_pings: false, + log_level: None, + rate_limit: None, + enable_event_timestamps: false, + experimentation_id: Some("test-experimentation-id".to_string()), + }) + .unwrap(); + let ping_maker = PingMaker::new(); + + let unknown_ping_type = PingType::new("unknown", true, false, true, vec![]); + glean.register_ping_type(&unknown_ping_type); + + assert!(ping_maker + .collect(&glean, &unknown_ping_type, None, "", "") + .is_none()); +} + +#[test] +fn collect_must_report_none_when_no_data_is_stored() { + // NOTE: This is a behavior change from glean-ac which returned an empty + // string in this case. As this is an implementation detail and not part of + // the public API, it's safe to change this. + + let (mut glean, ping_maker, ping_type, _t) = set_up_basic_ping(); + + let unknown_ping_type = PingType::new("unknown", true, false, true, vec![]); + glean.register_ping_type(&ping_type); + + assert!(ping_maker + .collect(&glean, &unknown_ping_type, None, "", "") + .is_none()); +} + +#[test] +fn seq_number_must_be_sequential() { + let (glean, ping_maker, _ping_type, _t) = set_up_basic_ping(); + + let metric = BooleanMetric::new(CommonMetricData { + name: "boolean_metric".into(), + category: "telemetry".into(), + send_in_pings: vec!["store2".into()], + disabled: false, + lifetime: Lifetime::User, + ..Default::default() + }); + metric.set_sync(&glean, true); + + for i in 0..=1 { + for ping_name in ["store1", "store2"].iter() { + let ping_type = PingType::new(*ping_name, true, false, true, vec![]); + let ping = ping_maker + .collect(&glean, &ping_type, None, "", "") + .unwrap(); + let seq_num = ping.content["ping_info"]["seq"].as_i64().unwrap(); + // Ensure sequence numbers in different stores are independent of + // each other + assert_eq!(i, seq_num); + } + } + + // Test that ping sequence numbers increase independently. + { + let ping_type = PingType::new("store1", true, false, true, vec![]); + + // 3rd ping of store1 + let ping = ping_maker + .collect(&glean, &ping_type, None, "", "") + .unwrap(); + let seq_num = ping.content["ping_info"]["seq"].as_i64().unwrap(); + assert_eq!(2, seq_num); + + // 4th ping of store1 + let ping = ping_maker + .collect(&glean, &ping_type, None, "", "") + .unwrap(); + let seq_num = ping.content["ping_info"]["seq"].as_i64().unwrap(); + assert_eq!(3, seq_num); + } + + { + let ping_type = PingType::new("store2", true, false, true, vec![]); + + // 3rd ping of store2 + let ping = ping_maker + .collect(&glean, &ping_type, None, "", "") + .unwrap(); + let seq_num = ping.content["ping_info"]["seq"].as_i64().unwrap(); + assert_eq!(2, seq_num); + } + + { + let ping_type = PingType::new("store1", true, false, true, vec![]); + + // 5th ping of store1 + let ping = ping_maker + .collect(&glean, &ping_type, None, "", "") + .unwrap(); + let seq_num = ping.content["ping_info"]["seq"].as_i64().unwrap(); + assert_eq!(4, seq_num); + } +} + +#[test] +fn clear_pending_pings() { + let (mut glean, _t) = new_glean(None); + let ping_maker = PingMaker::new(); + let ping_type = PingType::new("store1", true, false, true, vec![]); + glean.register_ping_type(&ping_type); + + // Record something, so the ping will have data + let metric = BooleanMetric::new(CommonMetricData { + name: "boolean_metric".into(), + category: "telemetry".into(), + send_in_pings: vec!["store1".into()], + disabled: false, + lifetime: Lifetime::User, + ..Default::default() + }); + metric.set_sync(&glean, true); + + assert!(ping_type.submit_sync(&glean, None)); + assert_eq!(1, get_queued_pings(glean.get_data_path()).unwrap().len()); + + assert!(ping_maker + .clear_pending_pings(glean.get_data_path()) + .is_ok()); + assert_eq!(0, get_queued_pings(glean.get_data_path()).unwrap().len()); +} + +#[test] +fn no_pings_submitted_if_upload_disabled() { + // Regression test, bug 1603571 + + let (mut glean, _t) = new_glean(None); + let ping_type = PingType::new("store1", true, true, true, vec![]); + glean.register_ping_type(&ping_type); + + assert!(ping_type.submit_sync(&glean, None)); + assert_eq!(1, get_queued_pings(glean.get_data_path()).unwrap().len()); + + // Disable upload, then try to sumbit + glean.set_upload_enabled(false); + + // Test again through the direct call + assert!(!ping_type.submit_sync(&glean, None)); + assert_eq!(0, get_queued_pings(glean.get_data_path()).unwrap().len()); +} + +#[test] +fn metadata_is_correctly_added_when_necessary() { + let (mut glean, _t) = new_glean(None); + glean.set_debug_view_tag("valid-tag"); + let ping_type = PingType::new("store1", true, true, true, vec![]); + glean.register_ping_type(&ping_type); + + assert!(ping_type.submit_sync(&glean, None)); + + let (_, _, metadata) = &get_queued_pings(glean.get_data_path()).unwrap()[0]; + let headers = metadata.as_ref().unwrap().get("headers").unwrap(); + assert_eq!(headers.get("X-Debug-ID").unwrap(), "valid-tag"); +} |