diff options
Diffstat (limited to 'toolkit/components/glean/tests')
25 files changed, 645 insertions, 128 deletions
diff --git a/toolkit/components/glean/tests/gtest/TestFog.cpp b/toolkit/components/glean/tests/gtest/TestFog.cpp index 2de8f9ba4d..0c1621911e 100644 --- a/toolkit/components/glean/tests/gtest/TestFog.cpp +++ b/toolkit/components/glean/tests/gtest/TestFog.cpp @@ -181,6 +181,7 @@ TEST_F(FOGFixture, TestCppMemoryDistWorks) { // Sum is in bytes, test_only::do_you_remember is in megabytes. So // multiplication ahoy! ASSERT_EQ(data.sum, 24UL * 1024 * 1024); + ASSERT_EQ(data.count, 2UL); for (const auto& entry : data.values) { const uint64_t bucket = entry.GetKey(); const uint64_t count = entry.GetData(); @@ -196,6 +197,7 @@ TEST_F(FOGFixture, TestCppCustomDistWorks) { DistributionData data = test_only_ipc::a_custom_dist.TestGetValue("store1"_ns).unwrap().ref(); ASSERT_EQ(data.sum, 7UL + 268435458); + ASSERT_EQ(data.count, 2UL); for (const auto& entry : data.values) { const uint64_t bucket = entry.GetKey(); const uint64_t count = entry.GetData(); @@ -253,6 +255,10 @@ TEST_F(FOGFixture, TestCppTimingDistWorks) { DistributionData data = test_only::what_time_is_it.TestGetValue().unwrap().ref(); + + // Cancelled timers should not increase count. + ASSERT_EQ(data.count, 2UL); + const uint64_t NANOS_IN_MILLIS = 1e6; // bug 1701847 - Sleeps don't necessarily round up as you'd expect. diff --git a/toolkit/components/glean/tests/pytest/gifft_output_Event b/toolkit/components/glean/tests/pytest/gifft_output_Event index ba80e3300b..203dc19a62 100644 --- a/toolkit/components/glean/tests/pytest/gifft_output_Event +++ b/toolkit/components/glean/tests/pytest/gifft_output_Event @@ -26,10 +26,10 @@ using Telemetry::EventID; static inline Maybe<EventID> EventIdForMetric(uint32_t aId) { switch(aId) { - case 17: { // test.nested.event_metric + case 18: { // test.nested.event_metric return Some(EventID::EventMetric_EnumNames_AreStrange); } - case 18: { // test.nested.event_metric_with_extra + case 19: { // test.nested.event_metric_with_extra return Some(EventID::EventMetric_EnumName_WithExtra); } default: { diff --git a/toolkit/components/glean/tests/pytest/gifft_output_Scalar b/toolkit/components/glean/tests/pytest/gifft_output_Scalar index 854455b584..9e1db3e84d 100644 --- a/toolkit/components/glean/tests/pytest/gifft_output_Scalar +++ b/toolkit/components/glean/tests/pytest/gifft_output_Scalar @@ -58,13 +58,13 @@ static inline Maybe<ScalarID> ScalarIdForMetric(uint32_t aId) { case 14: { // test.timespan_metric return Some(ScalarID::SOME_OTHER_UINT_SCALAR); } - case 16: { // test.nested.datetime_metric + case 17: { // test.nested.datetime_metric return Some(ScalarID::SOME_STILL_OTHER_STRING_SCALAR); } - case 21: { // test.nested.quantity_metric + case 22: { // test.nested.quantity_metric return Some(ScalarID::TELEMETRY_TEST_MIRROR_FOR_QUANTITY); } - case 24: { // test.nested.uuid_metric + case 25: { // test.nested.uuid_metric return Some(ScalarID::SOME_OTHER_STRING_SCALAR); } default: { diff --git a/toolkit/components/glean/tests/pytest/jogfile_output b/toolkit/components/glean/tests/pytest/jogfile_output index d75c08c8ba..510b4995c5 100644 --- a/toolkit/components/glean/tests/pytest/jogfile_output +++ b/toolkit/components/glean/tests/pytest/jogfile_output @@ -189,6 +189,15 @@ ], "test.nested": [ [ + "object", + "an_object", + [ + "metrics" + ], + "ping", + false + ], + [ "datetime", "datetime_metric", [ @@ -303,6 +312,7 @@ true, false, true, + true, [ "background", "dirty_startup", @@ -314,6 +324,7 @@ true, true, true, + true, [] ], [ @@ -321,6 +332,7 @@ true, false, true, + true, [ "background", "max_capacity", @@ -332,6 +344,7 @@ true, false, true, + true, [ "overdue", "reschedule", @@ -339,6 +352,14 @@ "tomorrow", "upgrade" ] + ], + [ + "not-ohttp", + false, + true, + true, + false, + [] ] ] }
\ No newline at end of file diff --git a/toolkit/components/glean/tests/pytest/metrics_test.yaml b/toolkit/components/glean/tests/pytest/metrics_test.yaml index cbbb0220b5..6d9a4f8c0e 100644 --- a/toolkit/components/glean/tests/pytest/metrics_test.yaml +++ b/toolkit/components/glean/tests/pytest/metrics_test.yaml @@ -396,3 +396,23 @@ test.nested: - https://bugzilla.mozilla.org/1635260/ data_reviews: - https://example.com + + an_object: + type: object + description: An example object + bugs: + - https://bugzilla.mozilla.org/1839640 + data_reviews: + - http://example.com/reviews + notification_emails: + - CHANGE-ME@example.com + expires: never + structure: + type: array + items: + type: object + properties: + colour: + type: string + diameter: + type: number diff --git a/toolkit/components/glean/tests/pytest/metrics_test_output b/toolkit/components/glean/tests/pytest/metrics_test_output index 76808cc984..0f93eb032d 100644 --- a/toolkit/components/glean/tests/pytest/metrics_test_output +++ b/toolkit/components/glean/tests/pytest/metrics_test_output @@ -6,6 +6,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + pub enum DynamicLabel { } pub mod test { @@ -16,6 +17,9 @@ pub mod test { use glean::HistogramType; use once_cell::sync::Lazy; + #[allow(unused_imports)] + use std::convert::TryFrom; + #[allow(non_upper_case_globals)] /// generated from test.boolean_metric /// @@ -361,13 +365,40 @@ pub mod test_nested { use glean::HistogramType; use once_cell::sync::Lazy; + #[allow(unused_imports)] + use std::convert::TryFrom; + + pub type AnObjectObject = Vec<AnObjectObjectItem>; + + #[derive(Debug, Hash, Eq, PartialEq, ::glean::traits::__serde::Serialize, ::glean::traits::__serde::Deserialize)] + #[serde(deny_unknown_fields)] + pub struct AnObjectObjectItem { + pub colour: Option<String>, + pub diameter: Option<i64>, + } + + #[allow(non_upper_case_globals)] + /// generated from test.nested.an_object + /// + /// An example object + pub static an_object: Lazy<ObjectMetric<AnObjectObject>> = Lazy::new(|| { + ObjectMetric::new(16.into(), CommonMetricData { + name: "an_object".into(), + category: "test.nested".into(), + send_in_pings: vec!["metrics".into()], + lifetime: Lifetime::Ping, + disabled: false, + ..Default::default() + }) + }); + #[allow(non_upper_case_globals)] /// generated from test.nested.datetime_metric /// /// A multi-line /// description pub static datetime_metric: Lazy<DatetimeMetric> = Lazy::new(|| { - DatetimeMetric::new(16.into(), CommonMetricData { + DatetimeMetric::new(17.into(), CommonMetricData { name: "datetime_metric".into(), category: "test.nested".into(), send_in_pings: vec!["metrics".into()], @@ -383,7 +414,7 @@ pub mod test_nested { /// A multi-line /// description pub static event_metric: Lazy<EventMetric<NoExtraKeys>> = Lazy::new(|| { - EventMetric::new(17.into(), CommonMetricData { + EventMetric::new(18.into(), CommonMetricData { name: "event_metric".into(), category: "test.nested".into(), send_in_pings: vec!["events".into()], @@ -415,7 +446,7 @@ pub mod test_nested { /// A multi-line /// description pub static event_metric_with_extra: Lazy<EventMetric<EventMetricWithExtraExtra>> = Lazy::new(|| { - EventMetric::new(18.into(), CommonMetricData { + EventMetric::new(19.into(), CommonMetricData { name: "event_metric_with_extra".into(), category: "test.nested".into(), send_in_pings: vec!["events".into()], @@ -431,7 +462,7 @@ pub mod test_nested { /// A multi-line /// description pub static external_denominator: Lazy<DenominatorMetric> = Lazy::new(|| { - DenominatorMetric::new(19.into(), CommonMetricData { + DenominatorMetric::new(20.into(), CommonMetricData { name: "external_denominator".into(), category: "test.nested".into(), send_in_pings: vec!["metrics".into()], @@ -448,7 +479,7 @@ pub mod test_nested { /// description pub static optimizable_counter_metric: Lazy<CounterMetric> = Lazy::new(|| { CounterMetric::codegen_new( - 20, + 21, "test.nested", "optimizable_counter_metric", "metrics" @@ -461,7 +492,7 @@ pub mod test_nested { /// A multi-line /// description pub static quantity_metric: Lazy<QuantityMetric> = Lazy::new(|| { - QuantityMetric::new(21.into(), CommonMetricData { + QuantityMetric::new(22.into(), CommonMetricData { name: "quantity_metric".into(), category: "test.nested".into(), send_in_pings: vec!["metrics".into()], @@ -477,7 +508,7 @@ pub mod test_nested { /// A multi-line /// description pub static rate_metric: Lazy<RateMetric> = Lazy::new(|| { - RateMetric::new(22.into(), CommonMetricData { + RateMetric::new(23.into(), CommonMetricData { name: "rate_metric".into(), category: "test.nested".into(), send_in_pings: vec!["metrics".into()], @@ -493,7 +524,7 @@ pub mod test_nested { /// A multi-line /// description pub static rate_with_external_denominator: Lazy<NumeratorMetric> = Lazy::new(|| { - NumeratorMetric::new(23.into(), CommonMetricData { + NumeratorMetric::new(24.into(), CommonMetricData { name: "rate_with_external_denominator".into(), category: "test.nested".into(), send_in_pings: vec!["metrics".into()], @@ -509,7 +540,7 @@ pub mod test_nested { /// A multi-line /// description pub static uuid_metric: Lazy<UuidMetric> = Lazy::new(|| { - UuidMetric::new(24.into(), CommonMetricData { + UuidMetric::new(25.into(), CommonMetricData { name: "uuid_metric".into(), category: "test.nested".into(), send_in_pings: vec!["metrics".into()], @@ -538,7 +569,7 @@ pub(crate) mod __glean_metric_maps { pub static COUNTER_MAP: Lazy<HashMap<MetricId, &Lazy<CounterMetric>>> = Lazy::new(|| { let mut map = HashMap::with_capacity(2); map.insert(2.into(), &super::test::counter_metric); - map.insert(20.into(), &super::test_nested::optimizable_counter_metric); + map.insert(21.into(), &super::test_nested::optimizable_counter_metric); map }); @@ -586,41 +617,100 @@ pub(crate) mod __glean_metric_maps { pub static DATETIME_MAP: Lazy<HashMap<MetricId, &Lazy<DatetimeMetric>>> = Lazy::new(|| { let mut map = HashMap::with_capacity(1); - map.insert(16.into(), &super::test_nested::datetime_metric); + map.insert(17.into(), &super::test_nested::datetime_metric); map }); pub static DENOMINATOR_MAP: Lazy<HashMap<MetricId, &Lazy<DenominatorMetric>>> = Lazy::new(|| { let mut map = HashMap::with_capacity(1); - map.insert(19.into(), &super::test_nested::external_denominator); + map.insert(20.into(), &super::test_nested::external_denominator); map }); pub static QUANTITY_MAP: Lazy<HashMap<MetricId, &Lazy<QuantityMetric>>> = Lazy::new(|| { let mut map = HashMap::with_capacity(1); - map.insert(21.into(), &super::test_nested::quantity_metric); + map.insert(22.into(), &super::test_nested::quantity_metric); map }); pub static RATE_MAP: Lazy<HashMap<MetricId, &Lazy<RateMetric>>> = Lazy::new(|| { let mut map = HashMap::with_capacity(1); - map.insert(22.into(), &super::test_nested::rate_metric); + map.insert(23.into(), &super::test_nested::rate_metric); map }); pub static NUMERATOR_MAP: Lazy<HashMap<MetricId, &Lazy<NumeratorMetric>>> = Lazy::new(|| { let mut map = HashMap::with_capacity(1); - map.insert(23.into(), &super::test_nested::rate_with_external_denominator); + map.insert(24.into(), &super::test_nested::rate_with_external_denominator); map }); pub static UUID_MAP: Lazy<HashMap<MetricId, &Lazy<UuidMetric>>> = Lazy::new(|| { let mut map = HashMap::with_capacity(1); - map.insert(24.into(), &super::test_nested::uuid_metric); + map.insert(25.into(), &super::test_nested::uuid_metric); map }); + pub(crate) fn set_object_by_id(metric_id: u32, value: String) -> Result<(), ()> { + match metric_id { + 16 => { + super::test_nested::an_object.set_string(value); + Ok(()) + } + _ => Err(()), + } + } + + /// Wrapper to get the currently stored object for object metric as a string. + /// + /// # Arguments + /// + /// * `metric_id` - The metric's ID to look up + /// * `ping_name` - (Optional) The ping name to look into. + /// Defaults to the first value in `send_in_pings`. + /// + /// # Returns + /// + /// Returns the recorded object serialized as a JSON string or `None` if nothing stored. + /// + /// # Panics + /// + /// Panics if no object by the given metric ID could be found. + pub(crate) fn object_test_get_value(metric_id: u32, ping_name: Option<String>) -> Option<String> { + match metric_id { + 16 => super::test_nested::an_object.test_get_value_as_str(ping_name.as_deref()), + _ => panic!("No object for metric id {}", metric_id), + } + } + + /// Check the provided object for errors. + /// + /// # Arguments + /// + /// * `metric_id` - The metric's ID to look up + /// + /// # Returns + /// + /// Returns a string for the recorded error or `None`. + /// + /// # Panics + /// + /// Panics if no object by the given metric ID could be found. + #[allow(unused_variables)] + pub(crate) fn object_test_get_error(metric_id: u32) -> Option<String> { + #[cfg(feature = "with_gecko")] + match metric_id { + 16 => test_get_errors!(super::test_nested::an_object), + _ => panic!("No object for metric id {}", metric_id), + } + + #[cfg(not(feature = "with_gecko"))] + { + return None; + } + } + /// Wrapper to record an event based on its metric ID. /// /// # Arguments @@ -635,7 +725,7 @@ pub(crate) mod __glean_metric_maps { /// or an `EventRecordingError::InvalidExtraKey` if the `extra` map could not be deserialized. pub(crate) fn record_event_by_id(metric_id: u32, extra: HashMap<String, String>) -> Result<(), EventRecordingError> { match metric_id { - 17 => { + 18 => { assert!( extra_keys_len(&super::test_nested::event_metric) != 0 || extra.is_empty(), "No extra keys allowed, but some were passed" @@ -644,7 +734,7 @@ pub(crate) mod __glean_metric_maps { super::test_nested::event_metric.record_raw(extra); Ok(()) } - 18 => { + 19 => { assert!( extra_keys_len(&super::test_nested::event_metric_with_extra) != 0 || extra.is_empty(), "No extra keys allowed, but some were passed" @@ -673,7 +763,7 @@ pub(crate) mod __glean_metric_maps { /// but some are passed in. pub(crate) fn record_event_by_id_with_time(metric_id: MetricId, timestamp: u64, extra: HashMap<String, String>) -> Result<(), EventRecordingError> { match metric_id { - MetricId(17) => { + MetricId(18) => { if extra_keys_len(&super::test_nested::event_metric) == 0 && !extra.is_empty() { return Err(EventRecordingError::InvalidExtraKey); } @@ -681,7 +771,7 @@ pub(crate) mod __glean_metric_maps { super::test_nested::event_metric.record_with_time(timestamp, extra); Ok(()) } - MetricId(18) => { + MetricId(19) => { if extra_keys_len(&super::test_nested::event_metric_with_extra) == 0 && !extra.is_empty() { return Err(EventRecordingError::InvalidExtraKey); } @@ -710,8 +800,8 @@ pub(crate) mod __glean_metric_maps { /// Panics if no event by the given metric ID could be found. pub(crate) fn event_test_get_value_wrapper(metric_id: u32, ping_name: Option<String>) -> Option<Vec<RecordedEvent>> { match metric_id { - 17 => super::test_nested::event_metric.test_get_value(ping_name.as_deref()), - 18 => super::test_nested::event_metric_with_extra.test_get_value(ping_name.as_deref()), + 18 => super::test_nested::event_metric.test_get_value(ping_name.as_deref()), + 19 => super::test_nested::event_metric_with_extra.test_get_value(ping_name.as_deref()), _ => panic!("No event for metric id {}", metric_id), } } @@ -735,8 +825,8 @@ pub(crate) mod __glean_metric_maps { pub(crate) fn event_test_get_error(metric_id: u32) -> Option<String> { #[cfg(feature = "with_gecko")] match metric_id { - 17 => test_get_errors!(super::test_nested::event_metric), - 18 => test_get_errors!(super::test_nested::event_metric_with_extra), + 18 => test_get_errors!(super::test_nested::event_metric), + 19 => test_get_errors!(super::test_nested::event_metric_with_extra), _ => panic!("No event for metric id {}", metric_id), } diff --git a/toolkit/components/glean/tests/pytest/metrics_test_output_cpp b/toolkit/components/glean/tests/pytest/metrics_test_output_cpp index 5b9c7bfae4..615e1c857d 100644 --- a/toolkit/components/glean/tests/pytest/metrics_test_output_cpp +++ b/toolkit/components/glean/tests/pytest/metrics_test_output_cpp @@ -181,6 +181,7 @@ namespace test { } namespace test_nested { + /** * generated from test.nested.datetime_metric */ @@ -188,7 +189,7 @@ namespace test_nested { * A multi-line * description */ - constexpr impl::DatetimeMetric datetime_metric(16); + constexpr impl::DatetimeMetric datetime_metric(17); /** * generated from test.nested.event_metric @@ -197,7 +198,7 @@ namespace test_nested { * A multi-line * description */ - constexpr impl::EventMetric<NoExtraKeys> event_metric(17); + constexpr impl::EventMetric<NoExtraKeys> event_metric(18); /** * generated from test.nested.event_metric_with_extra @@ -224,7 +225,7 @@ namespace test_nested { * A multi-line * description */ - constexpr impl::EventMetric<EventMetricWithExtraExtra> event_metric_with_extra(18); + constexpr impl::EventMetric<EventMetricWithExtraExtra> event_metric_with_extra(19); /** * generated from test.nested.external_denominator @@ -233,7 +234,7 @@ namespace test_nested { * A multi-line * description */ - constexpr impl::DenominatorMetric external_denominator(19); + constexpr impl::DenominatorMetric external_denominator(20); /** * generated from test.nested.optimizable_counter_metric @@ -242,7 +243,7 @@ namespace test_nested { * A multi-line * description */ - constexpr impl::CounterMetric optimizable_counter_metric(20); + constexpr impl::CounterMetric optimizable_counter_metric(21); /** * generated from test.nested.quantity_metric @@ -251,7 +252,7 @@ namespace test_nested { * A multi-line * description */ - constexpr impl::QuantityMetric quantity_metric(21); + constexpr impl::QuantityMetric quantity_metric(22); /** * generated from test.nested.rate_metric @@ -260,7 +261,7 @@ namespace test_nested { * A multi-line * description */ - constexpr impl::RateMetric rate_metric(22); + constexpr impl::RateMetric rate_metric(23); /** * generated from test.nested.rate_with_external_denominator @@ -269,7 +270,7 @@ namespace test_nested { * A multi-line * description */ - constexpr impl::NumeratorMetric rate_with_external_denominator(23); + constexpr impl::NumeratorMetric rate_with_external_denominator(24); /** * generated from test.nested.uuid_metric @@ -278,7 +279,7 @@ namespace test_nested { * A multi-line * description */ - constexpr impl::UuidMetric uuid_metric(24); + constexpr impl::UuidMetric uuid_metric(25); } diff --git a/toolkit/components/glean/tests/pytest/metrics_test_output_js_cpp b/toolkit/components/glean/tests/pytest/metrics_test_output_js_cpp index ba4619bb57..7cb5ce7d12 100644 --- a/toolkit/components/glean/tests/pytest/metrics_test_output_js_cpp +++ b/toolkit/components/glean/tests/pytest/metrics_test_output_js_cpp @@ -39,8 +39,8 @@ using metric_entry_t = uint64_t; static_assert(GLEAN_INDEX_BITS + GLEAN_TYPE_BITS + GLEAN_ID_BITS == sizeof(metric_entry_t) * 8, "Index, Type, and ID bits need to fit into a metric_entry_t"); static_assert(GLEAN_TYPE_BITS + GLEAN_ID_BITS <= sizeof(uint32_t) * 8, "Metric Types and IDs need to fit into at most 32 bits"); static_assert(2 < UINT32_MAX, "Too many metric categories generated."); -static_assert(24 < 33554432, "Too many metrics generated. Need room for 2 signal bits."); -static_assert(19 < 32, "Too many different metric types."); +static_assert(25 < 33554432, "Too many metrics generated. Need room for 2 signal bits."); +static_assert(20 < 32, "Too many different metric types."); already_AddRefed<GleanMetric> NewMetricFromId(uint32_t id, nsISupports* aParent) { uint32_t typeId = GLEAN_TYPE_ID(id); @@ -95,31 +95,35 @@ already_AddRefed<GleanMetric> NewMetricFromId(uint32_t id, nsISupports* aParent) { return MakeAndAddRef<GleanTimingDistribution>(metricId, aParent); } - case 13: /* datetime */ + case 13: /* object */ + { + return MakeAndAddRef<GleanObject>(metricId, aParent); + } + case 14: /* datetime */ { return MakeAndAddRef<GleanDatetime>(metricId, aParent); } - case 14: /* event */ + case 15: /* event */ { return MakeAndAddRef<GleanEvent>(metricId, aParent); } - case 15: /* denominator */ + case 16: /* denominator */ { return MakeAndAddRef<GleanDenominator>(metricId, aParent); } - case 16: /* quantity */ + case 17: /* quantity */ { return MakeAndAddRef<GleanQuantity>(metricId, aParent); } - case 17: /* rate */ + case 18: /* rate */ { return MakeAndAddRef<GleanRate>(metricId, aParent); } - case 18: /* numerator */ + case 19: /* numerator */ { return MakeAndAddRef<GleanNumerator>(metricId, aParent); } - case 19: /* uuid */ + case 20: /* uuid */ { return MakeAndAddRef<GleanUuid>(metricId, aParent); } @@ -289,45 +293,47 @@ constexpr char gMetricStringTable[] = { /* 310 - "test.textMetric" */ 't', 'e', 's', 't', '.', 't', 'e', 'x', 't', 'M', 'e', 't', 'r', 'i', 'c', '\0', /* 326 - "test.timespanMetric" */ 't', 'e', 's', 't', '.', 't', 'i', 'm', 'e', 's', 'p', 'a', 'n', 'M', 'e', 't', 'r', 'i', 'c', '\0', /* 346 - "test.timingDistributionMetric" */ 't', 'e', 's', 't', '.', 't', 'i', 'm', 'i', 'n', 'g', 'D', 'i', 's', 't', 'r', 'i', 'b', 'u', 't', 'i', 'o', 'n', 'M', 'e', 't', 'r', 'i', 'c', '\0', - /* 376 - "testNested.datetimeMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'd', 'a', 't', 'e', 't', 'i', 'm', 'e', 'M', 'e', 't', 'r', 'i', 'c', '\0', - /* 402 - "testNested.eventMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'e', 'v', 'e', 'n', 't', 'M', 'e', 't', 'r', 'i', 'c', '\0', - /* 425 - "testNested.eventMetricWithExtra" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'e', 'v', 'e', 'n', 't', 'M', 'e', 't', 'r', 'i', 'c', 'W', 'i', 't', 'h', 'E', 'x', 't', 'r', 'a', '\0', - /* 457 - "testNested.externalDenominator" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'e', 'x', 't', 'e', 'r', 'n', 'a', 'l', 'D', 'e', 'n', 'o', 'm', 'i', 'n', 'a', 't', 'o', 'r', '\0', - /* 488 - "testNested.optimizableCounterMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'o', 'p', 't', 'i', 'm', 'i', 'z', 'a', 'b', 'l', 'e', 'C', 'o', 'u', 'n', 't', 'e', 'r', 'M', 'e', 't', 'r', 'i', 'c', '\0', - /* 524 - "testNested.quantityMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'q', 'u', 'a', 'n', 't', 'i', 't', 'y', 'M', 'e', 't', 'r', 'i', 'c', '\0', - /* 550 - "testNested.rateMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'r', 'a', 't', 'e', 'M', 'e', 't', 'r', 'i', 'c', '\0', - /* 572 - "testNested.rateWithExternalDenominator" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'r', 'a', 't', 'e', 'W', 'i', 't', 'h', 'E', 'x', 't', 'e', 'r', 'n', 'a', 'l', 'D', 'e', 'n', 'o', 'm', 'i', 'n', 'a', 't', 'o', 'r', '\0', - /* 611 - "testNested.uuidMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'u', 'u', 'i', 'd', 'M', 'e', 't', 'r', 'i', 'c', '\0', + /* 376 - "testNested.anObject" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'a', 'n', 'O', 'b', 'j', 'e', 'c', 't', '\0', + /* 396 - "testNested.datetimeMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'd', 'a', 't', 'e', 't', 'i', 'm', 'e', 'M', 'e', 't', 'r', 'i', 'c', '\0', + /* 422 - "testNested.eventMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'e', 'v', 'e', 'n', 't', 'M', 'e', 't', 'r', 'i', 'c', '\0', + /* 445 - "testNested.eventMetricWithExtra" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'e', 'v', 'e', 'n', 't', 'M', 'e', 't', 'r', 'i', 'c', 'W', 'i', 't', 'h', 'E', 'x', 't', 'r', 'a', '\0', + /* 477 - "testNested.externalDenominator" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'e', 'x', 't', 'e', 'r', 'n', 'a', 'l', 'D', 'e', 'n', 'o', 'm', 'i', 'n', 'a', 't', 'o', 'r', '\0', + /* 508 - "testNested.optimizableCounterMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'o', 'p', 't', 'i', 'm', 'i', 'z', 'a', 'b', 'l', 'e', 'C', 'o', 'u', 'n', 't', 'e', 'r', 'M', 'e', 't', 'r', 'i', 'c', '\0', + /* 544 - "testNested.quantityMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'q', 'u', 'a', 'n', 't', 'i', 't', 'y', 'M', 'e', 't', 'r', 'i', 'c', '\0', + /* 570 - "testNested.rateMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'r', 'a', 't', 'e', 'M', 'e', 't', 'r', 'i', 'c', '\0', + /* 592 - "testNested.rateWithExternalDenominator" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'r', 'a', 't', 'e', 'W', 'i', 't', 'h', 'E', 'x', 't', 'e', 'r', 'n', 'a', 'l', 'D', 'e', 'n', 'o', 'm', 'i', 'n', 'a', 't', 'o', 'r', '\0', + /* 631 - "testNested.uuidMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'u', 'u', 'i', 'd', 'M', 'e', 't', 'r', 'i', 'c', '\0', }; static_assert(sizeof(gMetricStringTable) < 4294967296, "Metric string table is too large."); const metric_entry_t sMetricByNameLookupEntries[] = { - 6341068335467200838ull, - 3458764548180279480ull, - 1152921590506193384ull, - 576460756598390784ull, - 2882303787286921342ull, - 6917529092065591642ull, - 9799832883647480358ull, - 2305843026393563204ull, - 7493989848663982456ull, + 5764607578868810038ull, 1152921513196781587ull, - 8070450609557340585ull, - 2305843030688530526ull, - 5188146822270419236ull, - 8646911366155731401ull, 1729382269795172390ull, - 10952754396844261987ull, + 3458764552475246801ull, + 10952754396844261968ull, + 4611686065672028430ull, + 2305843026393563204ull, + 1152921594801160700ull, + 5188146822270419236ull, + 3458764548180279480ull, + 8646911361860764070ull, + 8646911366155731389ull, + 8070450605262373260ull, + 9799832883647480352ull, + 11529215153442652791ull, + 2305843030688530526ull, + 6917529092065591642ull, + 9223372122754122205ull, + 10376293640245871162ull, 4035225309073637616ull, - 10376293640245871164ull, - 9223372127049089548ull, - 5764607578868810038ull, - 8070450605262373266ull, + 2882303787286921342ull, + 576460756598390784ull, + 7493989848663982456ull, 2882303791581888664ull, - 4611686065672028430ull, - 3458764552475246801ull + 6341068335467200838ull }; @@ -365,39 +371,39 @@ MetricByNameLookup(const nsACString& aKey) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, - 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 6, 0, 12, 0, 0, 0, 0, 0, 0, 0, - 11, 0, 0, 0, 3, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 6, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; diff --git a/toolkit/components/glean/tests/pytest/metrics_test_output_js_h b/toolkit/components/glean/tests/pytest/metrics_test_output_js_h index 6ce9833732..99887c5a74 100644 --- a/toolkit/components/glean/tests/pytest/metrics_test_output_js_h +++ b/toolkit/components/glean/tests/pytest/metrics_test_output_js_h @@ -69,7 +69,7 @@ Maybe<uint32_t> MetricByNameLookup(const nsACString&); Maybe<uint32_t> CategoryByNameLookup(const nsACString&); extern const category_entry_t sCategoryByNameLookupEntries[2]; -extern const metric_entry_t sMetricByNameLookupEntries[24]; +extern const metric_entry_t sMetricByNameLookupEntries[25]; } // namespace mozilla::glean #endif // mozilla_GleanJSMetricsLookup_h diff --git a/toolkit/components/glean/tests/pytest/pings_test.yaml b/toolkit/components/glean/tests/pytest/pings_test.yaml index efa6ba9e0a..558cbb1022 100644 --- a/toolkit/components/glean/tests/pytest/pings_test.yaml +++ b/toolkit/components/glean/tests/pytest/pings_test.yaml @@ -7,7 +7,7 @@ # `glean_parser` PyPI package. --- -$schema: moz://mozilla.org/schemas/glean/pings/1-0-0 +$schema: moz://mozilla.org/schemas/glean/pings/2-0-0 not-baseline: description: > @@ -114,3 +114,19 @@ not-deletion-request: - https://bugzilla.mozilla.org/show_bug.cgi?id=1587095#c6 notification_emails: - glean-team@mozilla.com + +not-ohttp: + description: > + A fake OHTTP-using ping + include_client_id: false + metadata: + include_info_sections: false + use_ohttp: true + send_if_empty: true + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1862002 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1862002 + notification_emails: + - chutten@mozilla.com + - glean-team@mozilla.com diff --git a/toolkit/components/glean/tests/pytest/pings_test_output b/toolkit/components/glean/tests/pytest/pings_test_output index 9e037eb22a..97c0793b1f 100644 --- a/toolkit/components/glean/tests/pytest/pings_test_output +++ b/toolkit/components/glean/tests/pytest/pings_test_output @@ -20,6 +20,7 @@ pub static not_baseline: Lazy<Ping> = Lazy::new(|| { true, false, true, + true, vec!["background".into(), "dirty_startup".into(), "foreground".into()], ) }); @@ -36,6 +37,7 @@ pub static not_deletion_request: Lazy<Ping> = Lazy::new(|| { true, true, true, + true, vec![], ) }); @@ -50,6 +52,7 @@ pub static not_events: Lazy<Ping> = Lazy::new(|| { true, false, true, + true, vec!["background".into(), "max_capacity".into(), "startup".into()], ) }); @@ -68,10 +71,24 @@ pub static not_metrics: Lazy<Ping> = Lazy::new(|| { true, false, true, + true, vec!["overdue".into(), "reschedule".into(), "today".into(), "tomorrow".into(), "upgrade".into()], ) }); +#[allow(non_upper_case_globals)] +/// A fake OHTTP-using ping +pub static not_ohttp: Lazy<Ping> = Lazy::new(|| { + Ping::new( + "not-ohttp", + false, + true, + true, + false, + vec![], + ) +}); + /// Instantiate custom pings once to trigger registration. /// @@ -87,6 +104,7 @@ pub fn register_pings(application_id: Option<&str>) { let _ = &*not_deletion_request; let _ = &*not_events; let _ = &*not_metrics; + let _ = &*not_ohttp; } } } @@ -110,6 +128,7 @@ pub(crate) fn submit_ping_by_id(id: u32, reason: Option<&str>) { 2 => not_deletion_request.submit(reason), 3 => not_events.submit(reason), 4 => not_metrics.submit(reason), + 5 => not_ohttp.submit(reason), _ => { // TODO: instrument this error. log::error!("Cannot submit unknown ping {} by id.", id); diff --git a/toolkit/components/glean/tests/pytest/pings_test_output_cpp b/toolkit/components/glean/tests/pytest/pings_test_output_cpp index 289529b118..8994204634 100644 --- a/toolkit/components/glean/tests/pytest/pings_test_output_cpp +++ b/toolkit/components/glean/tests/pytest/pings_test_output_cpp @@ -56,6 +56,13 @@ constexpr glean::impl::Ping NotEvents(3); */ constexpr glean::impl::Ping NotMetrics(4); +/* + * Generated from not-ohttp. + * + * A fake OHTTP-using ping + */ +constexpr glean::impl::Ping NotOhttp(5); + } // namespace mozilla::glean_pings diff --git a/toolkit/components/glean/tests/pytest/pings_test_output_js_cpp b/toolkit/components/glean/tests/pytest/pings_test_output_js_cpp index 139eb29148..bc4f235d1e 100644 --- a/toolkit/components/glean/tests/pytest/pings_test_output_js_cpp +++ b/toolkit/components/glean/tests/pytest/pings_test_output_js_cpp @@ -33,15 +33,17 @@ constexpr char gPingStringTable[] = { /* 12 - "notDeletionRequest" */ 'n', 'o', 't', 'D', 'e', 'l', 'e', 't', 'i', 'o', 'n', 'R', 'e', 'q', 'u', 'e', 's', 't', '\0', /* 31 - "notEvents" */ 'n', 'o', 't', 'E', 'v', 'e', 'n', 't', 's', '\0', /* 41 - "notMetrics" */ 'n', 'o', 't', 'M', 'e', 't', 'r', 'i', 'c', 's', '\0', + /* 52 - "notOhttp" */ 'n', 'o', 't', 'O', 'h', 't', 't', 'p', '\0', }; const ping_entry_t sPingByNameLookupEntries[] = { 65536, + 327732, + 262185, 131084, - 196639, - 262185 + 196639 }; @@ -88,7 +90,7 @@ PingByNameLookup(const nsACString& aKey) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -108,7 +110,7 @@ PingByNameLookup(const nsACString& aKey) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/toolkit/components/glean/tests/pytest/pings_test_output_js_h b/toolkit/components/glean/tests/pytest/pings_test_output_js_h index 0c89de93ae..af21515ccc 100644 --- a/toolkit/components/glean/tests/pytest/pings_test_output_js_h +++ b/toolkit/components/glean/tests/pytest/pings_test_output_js_h @@ -28,6 +28,6 @@ const char* GetPingName(ping_entry_t aEntry); */ Maybe<uint32_t> PingByNameLookup(const nsACString&); -extern const ping_entry_t sPingByNameLookupEntries[4]; +extern const ping_entry_t sPingByNameLookupEntries[5]; } // namespace mozilla::glean #endif // mozilla_GleanJSPingsLookup_h diff --git a/toolkit/components/glean/tests/test_metrics.yaml b/toolkit/components/glean/tests/test_metrics.yaml index bc290d470f..47587241b1 100644 --- a/toolkit/components/glean/tests/test_metrics.yaml +++ b/toolkit/components/glean/tests/test_metrics.yaml @@ -403,6 +403,25 @@ test_only: - test-ping telemetry_mirror: TELEMETRY_TEST_MIRROR_FOR_QUANTITY + balloons: + type: object + description: A collection of balloons + bugs: + - https://bugzilla.mozilla.org/1839640 + data_reviews: + - http://example.com/reviews + notification_emails: + - CHANGE-ME@example.com + expires: never + structure: + type: array + items: + type: object + properties: + colour: + type: string + diameter: + type: number test_only.ipc: a_counter: diff --git a/toolkit/components/glean/tests/test_pings.yaml b/toolkit/components/glean/tests/test_pings.yaml index d62f682109..8bae13215e 100644 --- a/toolkit/components/glean/tests/test_pings.yaml +++ b/toolkit/components/glean/tests/test_pings.yaml @@ -40,3 +40,22 @@ test-ping: - glean-team@mozilla.com no_lint: - REDUNDANT_PING + +test-ohttp-ping: + description: | + This ping is for tests only. + Resembles how OHTTP pings are defined. + include_client_id: false + metadata: + include_info_sections: false + use_ohttp: true + send_if_empty: true + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1862002 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1862002 + notification_emails: + - chutten@mozilla.com + - glean-team@mozilla.com + no_lint: + - REDUNDANT_PING diff --git a/toolkit/components/glean/tests/xpcshell/head.js b/toolkit/components/glean/tests/xpcshell/head.js index f42bd02822..eaf8fa9c61 100644 --- a/toolkit/components/glean/tests/xpcshell/head.js +++ b/toolkit/components/glean/tests/xpcshell/head.js @@ -4,3 +4,155 @@ const { XPCOMUtils } = ChromeUtils.importESModule( "resource://gre/modules/XPCOMUtils.sys.mjs" ); + +ChromeUtils.defineESModuleGetters(this, { + HttpServer: "resource://testing-common/httpd.sys.mjs", + NetUtil: "resource://gre/modules/NetUtil.sys.mjs", +}); + +const PingServer = { + _httpServer: null, + _started: false, + _defers: [Promise.withResolvers()], + _currentDeferred: 0, + + get port() { + return this._httpServer.identity.primaryPort; + }, + + get host() { + return this._httpServer.identity.primaryHost; + }, + + get started() { + return this._started; + }, + + registerPingHandler(handler) { + this._httpServer.registerPrefixHandler("/submit/", handler); + }, + + resetPingHandler() { + this.registerPingHandler(request => { + let r = request; + console.trace( + `defaultPingHandler() - ${r.method} ${r.scheme}://${r.host}:${r.port}${r.path}` + ); + let deferred = this._defers[this._defers.length - 1]; + this._defers.push(Promise.withResolvers()); + deferred.resolve(request); + }); + }, + + start() { + this._httpServer = new HttpServer(); + this._httpServer.start(-1); + this._started = true; + this.clearRequests(); + this.resetPingHandler(); + }, + + stop() { + return new Promise(resolve => { + this._httpServer.stop(resolve); + this._started = false; + }); + }, + + clearRequests() { + this._defers = [Promise.withResolvers()]; + this._currentDeferred = 0; + }, + + promiseNextRequest() { + const deferred = this._defers[this._currentDeferred++]; + // Send the ping to the consumer on the next tick, so that the completion gets + // signaled to Telemetry. + return new Promise(r => + Services.tm.dispatchToMainThread(() => r(deferred.promise)) + ); + }, + + promiseNextPing() { + return this.promiseNextRequest().then(request => + decodeRequestPayload(request) + ); + }, + + async promiseNextRequests(count) { + let results = []; + for (let i = 0; i < count; ++i) { + results.push(await this.promiseNextRequest()); + } + + return results; + }, + + promiseNextPings(count) { + return this.promiseNextRequests(count).then(requests => { + return Array.from(requests, decodeRequestPayload); + }); + }, +}; + +/** + * Decode the payload of an HTTP request into a ping. + * + * @param {object} request The data representing an HTTP request (nsIHttpRequest). + * @returns {object} The decoded ping payload. + */ +function decodeRequestPayload(request) { + let s = request.bodyInputStream; + let payload = null; + + if ( + request.hasHeader("content-encoding") && + request.getHeader("content-encoding") == "gzip" + ) { + let observer = { + buffer: "", + onStreamComplete(loader, context, status, length, result) { + // String.fromCharCode can only deal with 500,000 characters + // at a time, so chunk the result into parts of that size. + const chunkSize = 500000; + for (let offset = 0; offset < result.length; offset += chunkSize) { + this.buffer += String.fromCharCode.apply( + String, + result.slice(offset, offset + chunkSize) + ); + } + }, + }; + + let scs = Cc["@mozilla.org/streamConverters;1"].getService( + Ci.nsIStreamConverterService + ); + let listener = Cc["@mozilla.org/network/stream-loader;1"].createInstance( + Ci.nsIStreamLoader + ); + listener.init(observer); + let converter = scs.asyncConvertData( + "gzip", + "uncompressed", + listener, + null + ); + converter.onStartRequest(null, null); + converter.onDataAvailable(null, s, 0, s.available()); + converter.onStopRequest(null, null, null); + // TODO: nsIScriptableUnicodeConverter is deprecated + // But I can't figure out how else to ungzip bodyInputStream. + let unicodeConverter = Cc[ + "@mozilla.org/intl/scriptableunicodeconverter" + ].createInstance(Ci.nsIScriptableUnicodeConverter); + unicodeConverter.charset = "UTF-8"; + let utf8string = unicodeConverter.ConvertToUnicode(observer.buffer); + utf8string += unicodeConverter.Finish(); + payload = JSON.parse(utf8string); + } else { + let bytes = NetUtil.readInputStream(s, s.available()); + payload = JSON.parse(new TextDecoder().decode(bytes)); + } + + return payload; +} diff --git a/toolkit/components/glean/tests/xpcshell/test_GIFFT.js b/toolkit/components/glean/tests/xpcshell/test_GIFFT.js index 015b4d4e38..8fcf755d3a 100644 --- a/toolkit/components/glean/tests/xpcshell/test_GIFFT.js +++ b/toolkit/components/glean/tests/xpcshell/test_GIFFT.js @@ -176,10 +176,7 @@ add_task(async function test_gifft_timing_dist() { // But we can guarantee it's only two samples. Assert.equal( 2, - Object.entries(data.values).reduce( - (acc, [bucket, count]) => acc + count, - 0 - ), + Object.entries(data.values).reduce((acc, [, count]) => acc + count, 0), "Only two buckets with samples" ); @@ -188,10 +185,7 @@ add_task(async function test_gifft_timing_dist() { Assert.greaterOrEqual(data.sum, 13, "Histogram's in milliseconds"); Assert.equal( 2, - Object.entries(data.values).reduce( - (acc, [bucket, count]) => acc + count, - 0 - ), + Object.entries(data.values).reduce((acc, [, count]) => acc + count, 0), "Only two samples" ); }); diff --git a/toolkit/components/glean/tests/xpcshell/test_GIFFTIPC.js b/toolkit/components/glean/tests/xpcshell/test_GIFFTIPC.js index a318d57b9c..ae4c48b6e8 100644 --- a/toolkit/components/glean/tests/xpcshell/test_GIFFTIPC.js +++ b/toolkit/components/glean/tests/xpcshell/test_GIFFTIPC.js @@ -291,10 +291,7 @@ add_task( // but we can assert there are only two samples. Assert.equal( 2, - Object.entries(times.values).reduce( - (acc, [bucket, count]) => acc + count, - 0 - ) + Object.entries(times.values).reduce((acc, [, count]) => acc + count, 0) ); const timingHist = histSnapshot.content.TELEMETRY_TEST_EXPONENTIAL; Assert.greaterOrEqual(timingHist.sum, 13, "Histogram's in milliseconds."); @@ -303,7 +300,7 @@ add_task( Assert.equal( 2, Object.entries(timingHist.values).reduce( - (acc, [bucket, count]) => acc + count, + (acc, [, count]) => acc + count, 0 ), "Only two samples" diff --git a/toolkit/components/glean/tests/xpcshell/test_Glean.js b/toolkit/components/glean/tests/xpcshell/test_Glean.js index 8375c22a3e..18b450a69b 100644 --- a/toolkit/components/glean/tests/xpcshell/test_Glean.js +++ b/toolkit/components/glean/tests/xpcshell/test_Glean.js @@ -182,6 +182,7 @@ add_task(async function test_fog_memory_distribution_works() { Glean.testOnly.doYouRemember.accumulate(17); let data = Glean.testOnly.doYouRemember.testGetValue("test-ping"); + Assert.equal(2, data.count, "Count of entries is correct"); // `data.sum` is in bytes, but the metric is in MB. Assert.equal(24 * 1024 * 1024, data.sum, "Sum's correct"); for (let [bucket, count] of Object.entries(data.values)) { @@ -196,6 +197,7 @@ add_task(async function test_fog_custom_distribution_works() { Glean.testOnlyIpc.aCustomDist.accumulateSamples([7, 268435458]); let data = Glean.testOnlyIpc.aCustomDist.testGetValue("store1"); + Assert.equal(2, data.count, "Count of entries is correct"); Assert.equal(7 + 268435458, data.sum, "Sum's correct"); for (let [bucket, count] of Object.entries(data.values)) { Assert.ok( @@ -216,7 +218,7 @@ add_task(function test_fog_custom_pings() { Assert.ok("onePingOnly" in GleanPings); let submitted = false; Glean.testOnly.onePingOneBool.set(false); - GleanPings.onePingOnly.testBeforeNextSubmit(reason => { + GleanPings.onePingOnly.testBeforeNextSubmit(() => { submitted = true; Assert.equal(false, Glean.testOnly.onePingOneBool.testGetValue()); }); @@ -227,7 +229,7 @@ add_task(function test_fog_custom_pings() { add_task(function test_recursive_testBeforeNextSubmit() { Assert.ok("onePingOnly" in GleanPings); let submitted = 0; - let rec = reason => { + let rec = () => { submitted++; GleanPings.onePingOnly.testBeforeNextSubmit(rec); }; @@ -255,6 +257,10 @@ add_task(async function test_fog_timing_distribution_works() { Glean.testOnly.whatTimeIsIt.stopAndAccumulate(t3); // 5ms let data = Glean.testOnly.whatTimeIsIt.testGetValue(); + + // Cancelled timers should not be counted. + Assert.equal(2, data.count, "Count of entries is correct"); + const NANOS_IN_MILLIS = 1e6; // bug 1701949 - Sleep gets close, but sometimes doesn't wait long enough. const EPSILON = 40000; @@ -266,10 +272,7 @@ add_task(async function test_fog_timing_distribution_works() { // But we can guarantee it's only two samples. Assert.equal( 2, - Object.entries(data.values).reduce( - (acc, [bucket, count]) => acc + count, - 0 - ), + Object.entries(data.values).reduce((acc, [, count]) => acc + count, 0), "Only two buckets with samples" ); }); @@ -456,3 +459,106 @@ add_task(async function test_fog_text_works_unusual_character() { Assert.greater(rslt.length, 100); }); + +add_task(async function test_fog_object_works() { + if (!Glean.testOnly.balloons) { + // FIXME(bug 1883857): object metric type not available, e.g. in artifact builds. + // Skipping this test. + return; + } + + Assert.equal( + undefined, + Glean.testOnly.balloons.testGetValue(), + "No object stored" + ); + + // Can't store not-objects. + let invalidValues = [1, "str", false, undefined, null, NaN, Infinity]; + for (let value of invalidValues) { + Assert.throws( + () => Glean.testOnly.balloons.set(value), + /is not an object/, + "Should throw a type error" + ); + } + + // No invalid value will be stored. + Assert.equal( + undefined, + Glean.testOnly.balloons.testGetValue(), + "No object stored" + ); + + // `JS_Stringify` internally throws + // an `TypeError: cyclic object value` exception. + // That's cleared and `set` should not throw on it. + // This eventually should log a proper error in Glean. + let selfref = {}; + selfref.a = selfref; + Glean.testOnly.balloons.set(selfref); + Assert.equal( + undefined, + Glean.testOnly.balloons.testGetValue(), + "No object stored" + ); + + let balloons = [ + { colour: "red", diameter: 5 }, + { colour: "blue", diameter: 7 }, + { colour: "orange" }, + ]; + Glean.testOnly.balloons.set(balloons); + + let result = Glean.testOnly.balloons.testGetValue(); + let expected = [ + { colour: "red", diameter: 5 }, + { colour: "blue", diameter: 7 }, + { colour: "orange", diameter: null }, + ]; + Assert.deepEqual(expected, result); + + // These values are coerced to null or removed. + balloons = [ + { colour: "inf", diameter: Infinity }, + { colour: "negative-inf", diameter: -1 / 0 }, + { colour: "nan", diameter: NaN }, + { colour: "undef", diameter: undefined }, + ]; + Glean.testOnly.balloons.set(balloons); + result = Glean.testOnly.balloons.testGetValue(); + expected = [ + { colour: "inf", diameter: null }, + { colour: "negative-inf", diameter: null }, + { colour: "nan", diameter: null }, + { colour: "undef", diameter: null }, + ]; + Assert.deepEqual(expected, result); + + // colour != color. + let invalid = [{ color: "orange" }, { color: "red", diameter: "small" }]; + Glean.testOnly.balloons.set(invalid); + Assert.throws( + () => Glean.testOnly.balloons.testGetValue(), + /invalid_value/, + "Should throw because last object was invalid." + ); + + Services.fog.testResetFOG(); + // set again to ensure it's stored + balloons = [ + { colour: "red", diameter: 5 }, + { colour: "blue", diameter: 7 }, + ]; + Glean.testOnly.balloons.set(balloons); + result = Glean.testOnly.balloons.testGetValue(); + Assert.deepEqual(balloons, result); + + invalid = [{ colour: "red", diameter: 5, extra: "field" }]; + Glean.testOnly.balloons.set(invalid); + Assert.throws( + () => Glean.testOnly.balloons.testGetValue(), + /invalid_value/, + "Should throw because last object was invalid." + ); +}); diff --git a/toolkit/components/glean/tests/xpcshell/test_GleanIPC.js b/toolkit/components/glean/tests/xpcshell/test_GleanIPC.js index 3d665c23b9..2db1c53218 100644 --- a/toolkit/components/glean/tests/xpcshell/test_GleanIPC.js +++ b/toolkit/components/glean/tests/xpcshell/test_GleanIPC.js @@ -127,10 +127,7 @@ add_task( // but we can assert there are only two samples. Assert.equal( 2, - Object.entries(times.values).reduce( - (acc, [bucket, count]) => acc + count, - 0 - ) + Object.entries(times.values).reduce((acc, [, count]) => acc + count, 0) ); const mabelsCounters = Glean.testOnly.mabelsKitchenCounters; diff --git a/toolkit/components/glean/tests/xpcshell/test_JOG.js b/toolkit/components/glean/tests/xpcshell/test_JOG.js index 53b1d25962..00f3ded135 100644 --- a/toolkit/components/glean/tests/xpcshell/test_JOG.js +++ b/toolkit/components/glean/tests/xpcshell/test_JOG.js @@ -289,11 +289,11 @@ add_task(async function test_jog_custom_pings() { `"ping"`, false ); - Services.fog.testRegisterRuntimePing("jog-ping", true, true, true, []); + Services.fog.testRegisterRuntimePing("jog-ping", true, true, true, true, []); Assert.ok("jogPing" in GleanPings); let submitted = false; Glean.jogCat.jogPingBool.set(false); - GleanPings.jogPing.testBeforeNextSubmit(reason => { + GleanPings.jogPing.testBeforeNextSubmit(() => { submitted = true; Assert.equal(false, Glean.jogCat.jogPingBool.testGetValue()); }); @@ -338,10 +338,7 @@ add_task(async function test_jog_timing_distribution_works() { // But we can guarantee it's only two samples. Assert.equal( 2, - Object.entries(data.values).reduce( - (acc, [bucket, count]) => acc + count, - 0 - ), + Object.entries(data.values).reduce((acc, [, count]) => acc + count, 0), "Only two buckets with samples" ); }); @@ -642,7 +639,9 @@ add_task(function test_jog_dotted_categories_work() { add_task(async function test_jog_ping_works() { const kReason = "reason-1"; - Services.fog.testRegisterRuntimePing("my-ping", true, true, true, [kReason]); + Services.fog.testRegisterRuntimePing("my-ping", true, true, true, true, [ + kReason, + ]); let submitted = false; GleanPings.myPing.testBeforeNextSubmit(reason => { submitted = true; @@ -652,6 +651,20 @@ add_task(async function test_jog_ping_works() { Assert.ok(submitted, "Ping must have been submitted"); }); +add_task(async function test_jog_noinfo_ping_works() { + const kReason = "reason-1"; + Services.fog.testRegisterRuntimePing("noinfo-ping", true, true, true, false, [ + kReason, + ]); + let submitted = false; + GleanPings.noinfoPing.testBeforeNextSubmit(reason => { + submitted = true; + Assert.equal(kReason, reason); + }); + GleanPings.noinfoPing.submit("reason-1"); + Assert.ok(submitted, "Ping must have been submitted"); +}); + add_task(function test_jog_name_collision() { Assert.ok("aCounter" in Glean.testOnlyJog); Assert.equal(undefined, Glean.testOnlyJog.aCounter.testGetValue()); diff --git a/toolkit/components/glean/tests/xpcshell/test_JOGIPC.js b/toolkit/components/glean/tests/xpcshell/test_JOGIPC.js index 505dba6825..b43a448c53 100644 --- a/toolkit/components/glean/tests/xpcshell/test_JOGIPC.js +++ b/toolkit/components/glean/tests/xpcshell/test_JOGIPC.js @@ -226,10 +226,7 @@ add_task( // but we can assert there are only two samples. Assert.equal( 2, - Object.entries(times.values).reduce( - (acc, [bucket, count]) => acc + count, - 0 - ) + Object.entries(times.values).reduce((acc, [, count]) => acc + count, 0) ); const labeledCounter = Glean.jogIpc.jogLabeledCounter; diff --git a/toolkit/components/glean/tests/xpcshell/test_OHTTP.js b/toolkit/components/glean/tests/xpcshell/test_OHTTP.js new file mode 100644 index 0000000000..76d1d2a67b --- /dev/null +++ b/toolkit/components/glean/tests/xpcshell/test_OHTTP.js @@ -0,0 +1,32 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_setup(async () => { + // FOG needs a profile dir to put its data in. + do_get_profile(); + + PingServer.start(); + + registerCleanupFunction(async () => { + await PingServer.stop(); + }); + + Services.prefs.setIntPref( + "telemetry.fog.test.localhost_port", + PingServer.port + ); + // Port pref needs to be set before init, so let's reset to reinit. + Services.fog.testResetFOG(); +}); + +add_task(async () => { + PingServer.clearRequests(); + GleanPings.testOhttpPing.submit(); + + let ping = await PingServer.promiseNextPing(); + + ok(!("client_info" in ping), "No client_info allowed."); + ok(!("ping_info" in ping), "No ping_info allowed."); +}); diff --git a/toolkit/components/glean/tests/xpcshell/xpcshell.toml b/toolkit/components/glean/tests/xpcshell/xpcshell.toml index 40b1a22bf4..22806a32e6 100644 --- a/toolkit/components/glean/tests/xpcshell/xpcshell.toml +++ b/toolkit/components/glean/tests/xpcshell/xpcshell.toml @@ -30,3 +30,6 @@ skip-if = ["os == 'android'"] # Server Knobs on mobile will be handled by the sp ["test_MillionQ.js"] skip-if = ["os == 'android'"] # Android inits its own FOG, so the test won't work. + +["test_OHTTP.js"] +skip-if = ["os == 'android'"] # FOG isn't responsible for monitoring prefs and controlling upload on Android |