• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use super::*;
16 use crate::time::MockTimeApi;
17 use crate::time::TIME_API_MTX;
18 
19 const BASE_RAW_MONOTONIC_TIME: Duration = Duration::from_secs(12345);
20 const BASE_RAW_BOOT_TIME: Duration = Duration::from_secs(67890);
21 const HOUR_IN_SECONDS: u64 = 3600;
22 const DEFAULT_MAX_IDLE_DURATION: Duration = Duration::from_secs(25 * HOUR_IN_SECONDS);
23 
24 #[test]
test_suspend_monitor()25 fn test_suspend_monitor() {
26     let _m = TIME_API_MTX.lock();
27     let mock_monitonic = MockTimeApi::get_monotonic_time_context();
28     let mock_boot = MockTimeApi::get_boot_time_context();
29     mock_monitonic
30         .expect()
31         .times(1)
32         .return_const(MonotonicTime::from_duration(BASE_RAW_MONOTONIC_TIME));
33     mock_boot.expect().times(1).return_const(BootTime::from_duration(BASE_RAW_BOOT_TIME));
34     let mut suspend_monitor = SuspendMonitor::<MockTimeApi>::new();
35 
36     // + 100s on monotonic clock
37     mock_monitonic.expect().times(1).return_const(MonotonicTime::from_duration(
38         BASE_RAW_MONOTONIC_TIME + Duration::from_secs(100),
39     ));
40     // + 300s on boottime clock
41     let boot_now = BootTime::from_duration(BASE_RAW_BOOT_TIME + Duration::from_secs(300));
42     mock_boot.expect().times(1).return_const(boot_now);
43     assert_eq!(suspend_monitor.generate_suspend_duration(), (Duration::from_secs(200), boot_now));
44 
45     // + 900s on monotonic clock
46     mock_monitonic.expect().times(1).return_const(MonotonicTime::from_duration(
47         BASE_RAW_MONOTONIC_TIME + Duration::from_secs(1000),
48     ));
49     // + 1000s on boottime clock
50     let boot_now = BootTime::from_duration(BASE_RAW_BOOT_TIME + Duration::from_secs(1300));
51     mock_boot.expect().times(1).return_const(boot_now);
52     assert_eq!(suspend_monitor.generate_suspend_duration(), (Duration::from_secs(100), boot_now));
53 }
54 
55 #[test]
test_suspend_monitor_negative_adjustment()56 fn test_suspend_monitor_negative_adjustment() {
57     let _m = TIME_API_MTX.lock();
58     let mock_monitonic = MockTimeApi::get_monotonic_time_context();
59     let mock_boot = MockTimeApi::get_boot_time_context();
60     mock_monitonic
61         .expect()
62         .times(1)
63         .return_const(MonotonicTime::from_duration(BASE_RAW_MONOTONIC_TIME));
64     mock_boot.expect().times(1).return_const(BootTime::from_duration(BASE_RAW_BOOT_TIME));
65     let mut suspend_monitor = SuspendMonitor::<MockTimeApi>::new();
66 
67     // + 400s on monotonic clock
68     mock_monitonic.expect().times(1).return_const(MonotonicTime::from_duration(
69         BASE_RAW_MONOTONIC_TIME + Duration::from_secs(400),
70     ));
71     // + 100s on boottime clock
72     let boot_now = BootTime::from_duration(BASE_RAW_BOOT_TIME + Duration::from_secs(100));
73     mock_boot.expect().times(1).return_const(boot_now);
74     // 300s of negative adjustment is stored.
75     assert_eq!(suspend_monitor.generate_suspend_duration(), (Duration::ZERO, boot_now));
76 
77     // + 100s on monotonic clock
78     mock_monitonic.expect().times(1).return_const(MonotonicTime::from_duration(
79         BASE_RAW_MONOTONIC_TIME + Duration::from_secs(500),
80     ));
81     // + 1000s on boottime clock
82     let boot_now = BootTime::from_duration(BASE_RAW_BOOT_TIME + Duration::from_secs(1100));
83     mock_boot.expect().times(1).return_const(boot_now);
84     // suspend duration is 900s - 300s (negative adjustment from the last call)
85     assert_eq!(suspend_monitor.generate_suspend_duration(), (Duration::from_secs(600), boot_now));
86 
87     // + 100s on monotonic clock
88     mock_monitonic.expect().times(1).return_const(MonotonicTime::from_duration(
89         BASE_RAW_MONOTONIC_TIME + Duration::from_secs(600),
90     ));
91     // + 400s on boottime clock
92     let boot_now = BootTime::from_duration(BASE_RAW_BOOT_TIME + Duration::from_secs(1500));
93     mock_boot.expect().times(1).return_const(boot_now);
94     // suspend duration is 300s without negative adjustment
95     assert_eq!(suspend_monitor.generate_suspend_duration(), (Duration::from_secs(300), boot_now));
96 }
97 
98 #[test]
test_suspend_monitor_big_negative_adjustment()99 fn test_suspend_monitor_big_negative_adjustment() {
100     let _m = TIME_API_MTX.lock();
101     let mock_monitonic = MockTimeApi::get_monotonic_time_context();
102     let mock_boot = MockTimeApi::get_boot_time_context();
103     mock_monitonic
104         .expect()
105         .times(1)
106         .return_const(MonotonicTime::from_duration(BASE_RAW_MONOTONIC_TIME));
107     mock_boot.expect().times(1).return_const(BootTime::from_duration(BASE_RAW_BOOT_TIME));
108     let mut suspend_monitor = SuspendMonitor::<MockTimeApi>::new();
109 
110     // + 400s on monotonic clock
111     mock_monitonic.expect().times(1).return_const(MonotonicTime::from_duration(
112         BASE_RAW_MONOTONIC_TIME + Duration::from_secs(400),
113     ));
114     // + 100s on boottime clock
115     let boot_now = BootTime::from_duration(BASE_RAW_BOOT_TIME + Duration::from_secs(100));
116     mock_boot.expect().times(1).return_const(boot_now);
117     // 300s of negative adjustment is stored.
118     assert_eq!(suspend_monitor.generate_suspend_duration(), (Duration::ZERO, boot_now));
119 
120     // + 100s on monotonic clock
121     mock_monitonic.expect().times(1).return_const(MonotonicTime::from_duration(
122         BASE_RAW_MONOTONIC_TIME + Duration::from_secs(500),
123     ));
124     // + 300s on boottime clock
125     let boot_now = BootTime::from_duration(BASE_RAW_BOOT_TIME + Duration::from_secs(400));
126     mock_boot.expect().times(1).return_const(boot_now);
127     // suspend duration is 200s is shorter than negative adjustment. 100s of negative adjustment is
128     // left.
129     assert_eq!(suspend_monitor.generate_suspend_duration(), (Duration::ZERO, boot_now));
130 
131     // + 100s on monotonic clock
132     mock_monitonic.expect().times(1).return_const(MonotonicTime::from_duration(
133         BASE_RAW_MONOTONIC_TIME + Duration::from_secs(600),
134     ));
135     // + 400s on boottime clock
136     let boot_now = BootTime::from_duration(BASE_RAW_BOOT_TIME + Duration::from_secs(800));
137     mock_boot.expect().times(1).return_const(boot_now);
138     // suspend duration is 300s - 100s (negative adjustment).
139     assert_eq!(suspend_monitor.generate_suspend_duration(), (Duration::from_secs(200), boot_now));
140 }
141 
142 #[test]
test_calculate_total_suspend_duration()143 fn test_calculate_total_suspend_duration() {
144     let mut history = SuspendHistory::new();
145 
146     history.record_suspend_duration(
147         Duration::from_secs(2 * HOUR_IN_SECONDS),
148         BootTime::from_duration(BASE_RAW_BOOT_TIME),
149         DEFAULT_MAX_IDLE_DURATION,
150     );
151     history.record_suspend_duration(
152         Duration::from_secs(5 * HOUR_IN_SECONDS),
153         BootTime::from_duration(BASE_RAW_BOOT_TIME + Duration::from_secs(7 * HOUR_IN_SECONDS)),
154         DEFAULT_MAX_IDLE_DURATION,
155     );
156     history.record_suspend_duration(
157         Duration::from_secs(2 * HOUR_IN_SECONDS),
158         BootTime::from_duration(BASE_RAW_BOOT_TIME + Duration::from_secs(10 * HOUR_IN_SECONDS)),
159         DEFAULT_MAX_IDLE_DURATION,
160     );
161     history.record_suspend_duration(
162         Duration::from_secs(HOUR_IN_SECONDS),
163         BootTime::from_duration(BASE_RAW_BOOT_TIME + Duration::from_secs(12 * HOUR_IN_SECONDS)),
164         DEFAULT_MAX_IDLE_DURATION,
165     );
166 
167     assert_eq!(
168         history.calculate_total_suspend_duration(
169             Duration::from_secs(4 * HOUR_IN_SECONDS),
170             BootTime::from_duration(BASE_RAW_BOOT_TIME + Duration::from_secs(13 * HOUR_IN_SECONDS))
171         ),
172         Duration::from_secs(8 * HOUR_IN_SECONDS)
173     );
174 }
175 
176 #[test]
test_calculate_total_suspend_duration_empty()177 fn test_calculate_total_suspend_duration_empty() {
178     let history = SuspendHistory::new();
179 
180     assert_eq!(
181         history.calculate_total_suspend_duration(
182             Duration::from_secs(4 * HOUR_IN_SECONDS),
183             BootTime::from_duration(BASE_RAW_BOOT_TIME + Duration::from_secs(13 * HOUR_IN_SECONDS))
184         ),
185         Duration::ZERO
186     );
187 }
188 
189 #[test]
test_calculate_total_suspend_duration_negative_target()190 fn test_calculate_total_suspend_duration_negative_target() {
191     let history = SuspendHistory::new();
192 
193     // now - target_duration is negative.
194     assert_eq!(
195         history.calculate_total_suspend_duration(
196             Duration::from_secs(4 * HOUR_IN_SECONDS),
197             BootTime::from_duration(Duration::from_secs(HOUR_IN_SECONDS))
198         ),
199         Duration::ZERO
200     );
201 }
202 
203 #[test]
test_suspend_history_gc_entries()204 fn test_suspend_history_gc_entries() {
205     let max_idle_duration = Duration::from_secs(25 * HOUR_IN_SECONDS);
206     let base_raw_boot_time: Duration = Duration::ZERO;
207     let mut history = SuspendHistory::new();
208 
209     assert_eq!(history.history.len(), 1);
210 
211     // awake for 26 hours.
212     history.record_suspend_duration(
213         Duration::from_secs(HOUR_IN_SECONDS),
214         BootTime::from_duration(base_raw_boot_time + Duration::from_secs(27 * HOUR_IN_SECONDS)),
215         max_idle_duration,
216     );
217     // Does not pop entry if there was only 1 entry.
218     assert_eq!(history.history.len(), 2);
219 
220     // awake for 1 hour.
221     history.record_suspend_duration(
222         Duration::from_secs(HOUR_IN_SECONDS),
223         BootTime::from_duration(base_raw_boot_time + Duration::from_secs(29 * HOUR_IN_SECONDS)),
224         max_idle_duration,
225     );
226     // The first entry is GC-ed.
227     assert_eq!(history.history.len(), 2);
228 
229     // awake for 2 hour.
230     history.record_suspend_duration(
231         Duration::from_secs(HOUR_IN_SECONDS),
232         BootTime::from_duration(base_raw_boot_time + Duration::from_secs(32 * HOUR_IN_SECONDS)),
233         max_idle_duration,
234     );
235     assert_eq!(history.history.len(), 3);
236 
237     // awake for 10 hour.
238     history.record_suspend_duration(
239         Duration::from_secs(11 * HOUR_IN_SECONDS),
240         BootTime::from_duration(base_raw_boot_time + Duration::from_secs(53 * HOUR_IN_SECONDS)),
241         max_idle_duration,
242     );
243     assert_eq!(history.history.len(), 4);
244 
245     // awake for 20 hours.
246     history.record_suspend_duration(
247         Duration::from_secs(12 * HOUR_IN_SECONDS),
248         BootTime::from_duration(base_raw_boot_time + Duration::from_secs(85 * HOUR_IN_SECONDS)),
249         max_idle_duration,
250     );
251     // The entries except last 2 entries are GC-ed.
252     assert_eq!(history.history.len(), 2);
253 
254     assert_eq!(
255         history.calculate_total_suspend_duration(
256             Duration::from_secs(25 * HOUR_IN_SECONDS),
257             BootTime::from_duration(base_raw_boot_time + Duration::from_secs(85 * HOUR_IN_SECONDS))
258         ),
259         Duration::from_secs(23 * HOUR_IN_SECONDS)
260     );
261 }
262