1 // This Source Code Form is subject to the terms of the Mozilla Public
2 // License, v. 2.0. If a copy of the MPL was not distributed with this
3 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5 mod common;
6 use crate::common::*;
7
8 use chrono::prelude::*;
9 use serde_json::json;
10
11 use glean_core::metrics::*;
12 use glean_core::storage::StorageManager;
13 use glean_core::{CommonMetricData, Lifetime};
14
15 // SKIPPED from glean-ac: datetime deserializer should correctly parse integers
16 // This test doesn't really apply to rkv
17
18 #[test]
datetime_serializer_should_correctly_serialize_datetime()19 fn datetime_serializer_should_correctly_serialize_datetime() {
20 let expected_value = "1983-04-13T12:09+00:00";
21 let (mut tempdir, _) = tempdir();
22
23 {
24 // We give tempdir to the `new_glean` function...
25 let (glean, dir) = new_glean(Some(tempdir));
26 // And then we get it back once that function returns.
27 tempdir = dir;
28
29 let metric = DatetimeMetric::new(
30 CommonMetricData {
31 name: "datetime_metric".into(),
32 category: "telemetry".into(),
33 send_in_pings: vec!["store1".into()],
34 disabled: false,
35 lifetime: Lifetime::User,
36 ..Default::default()
37 },
38 TimeUnit::Minute,
39 );
40
41 // `1983-04-13T12:09:14.274+00:00` will be truncated to Minute resolution.
42 let dt = FixedOffset::east(0)
43 .ymd(1983, 4, 13)
44 .and_hms_milli(12, 9, 14, 274);
45 metric.set(&glean, Some(dt));
46
47 let snapshot = StorageManager
48 .snapshot_as_json(glean.storage(), "store1", true)
49 .unwrap();
50 assert_eq!(
51 json!({"datetime": {"telemetry.datetime_metric": expected_value}}),
52 snapshot
53 );
54 }
55
56 // Make a new Glean instance here, which should force reloading of the data from disk
57 // so we can ensure it persisted, because it has User lifetime
58 {
59 let (glean, _) = new_glean(Some(tempdir));
60 let snapshot = StorageManager
61 .snapshot_as_json(glean.storage(), "store1", true)
62 .unwrap();
63 assert_eq!(
64 json!({"datetime": {"telemetry.datetime_metric": expected_value}}),
65 snapshot
66 );
67 }
68 }
69
70 #[test]
set_value_properly_sets_the_value_in_all_stores()71 fn set_value_properly_sets_the_value_in_all_stores() {
72 let (glean, _t) = new_glean(None);
73 let store_names: Vec<String> = vec!["store1".into(), "store2".into()];
74
75 let metric = DatetimeMetric::new(
76 CommonMetricData {
77 name: "datetime_metric".into(),
78 category: "telemetry".into(),
79 send_in_pings: store_names.clone(),
80 disabled: false,
81 lifetime: Lifetime::Ping,
82 ..Default::default()
83 },
84 TimeUnit::Nanosecond,
85 );
86
87 // `1983-04-13T12:09:14.274+00:00` will be truncated to Minute resolution.
88 let dt = FixedOffset::east(0)
89 .ymd(1983, 4, 13)
90 .and_hms_nano(12, 9, 14, 1_560_274);
91 metric.set(&glean, Some(dt));
92
93 for store_name in store_names {
94 assert_eq!(
95 "1983-04-13T12:09:14.001560274+00:00",
96 metric
97 .test_get_value_as_string(&glean, &store_name)
98 .unwrap()
99 );
100 }
101 }
102
103 // SKIPPED from glean-ac: getSnapshot() returns null if nothing is recorded in the store
104 // This test doesn't really apply to rkv
105
106 // SKIPPED from glean-ac: getSnapshot() correctly clears the stores
107 // This test doesn't really apply to rkv
108
109 #[test]
test_that_truncation_works()110 fn test_that_truncation_works() {
111 let (glean, _t) = new_glean(None);
112
113 // `1985-07-03T12:09:14.000560274+01:00`
114 let high_res_datetime = FixedOffset::east(3600)
115 .ymd(1985, 7, 3)
116 .and_hms_nano(12, 9, 14, 1_560_274);
117 let store_name = "store1";
118
119 // Create an helper struct for defining the truncation cases.
120 struct TestCase {
121 case_name: &'static str,
122 desired_resolution: TimeUnit,
123 expected_result: &'static str,
124 }
125
126 // Define the single test cases.
127 let test_cases = vec![
128 TestCase {
129 case_name: "nano",
130 desired_resolution: TimeUnit::Nanosecond,
131 expected_result: "1985-07-03T12:09:14.001560274+01:00",
132 },
133 TestCase {
134 case_name: "micro",
135 desired_resolution: TimeUnit::Microsecond,
136 expected_result: "1985-07-03T12:09:14.001560+01:00",
137 },
138 TestCase {
139 case_name: "milli",
140 desired_resolution: TimeUnit::Millisecond,
141 expected_result: "1985-07-03T12:09:14.001+01:00",
142 },
143 TestCase {
144 case_name: "second",
145 desired_resolution: TimeUnit::Second,
146 expected_result: "1985-07-03T12:09:14+01:00",
147 },
148 TestCase {
149 case_name: "minute",
150 desired_resolution: TimeUnit::Minute,
151 expected_result: "1985-07-03T12:09+01:00",
152 },
153 TestCase {
154 case_name: "hour",
155 desired_resolution: TimeUnit::Hour,
156 expected_result: "1985-07-03T12+01:00",
157 },
158 TestCase {
159 case_name: "day",
160 desired_resolution: TimeUnit::Day,
161 expected_result: "1985-07-03+01:00",
162 },
163 ];
164
165 // Execute them all.
166 for t in test_cases {
167 let metric = DatetimeMetric::new(
168 CommonMetricData {
169 name: format!("datetime_metric_{}", t.case_name),
170 category: "telemetry".into(),
171 send_in_pings: vec![store_name.into()],
172 disabled: false,
173 lifetime: Lifetime::User,
174 ..Default::default()
175 },
176 t.desired_resolution,
177 );
178 metric.set(&glean, Some(high_res_datetime));
179
180 assert_eq!(
181 t.expected_result,
182 metric
183 .test_get_value_as_string(&glean, &store_name)
184 .unwrap()
185 );
186 }
187 }
188