• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.car.storagemonitoring;
18 
19 import android.car.storagemonitoring.IoStatsEntry;
20 import android.car.storagemonitoring.UidIoRecord;
21 import android.test.suitebuilder.annotation.MediumTest;
22 import android.util.SparseArray;
23 
24 import com.android.car.procfsinspector.ProcessInfo;
25 import com.android.car.systeminterface.SystemStateInterface;
26 
27 import junit.framework.TestCase;
28 
29 import java.time.Duration;
30 import java.util.ArrayList;
31 import java.util.Collections;
32 import java.util.List;
33 import java.util.stream.Collectors;
34 
35 /**
36  * Tests IoStatsTracker functionality.
37  */
38 @MediumTest
39 public class IoStatsTrackerTest extends TestCase {
40     private static final int SAMPLE_WINDOW_MS = 1000;
41     private static final List<IoStatsEntry> EMPTY = Collections.emptyList();
42     private static final String TAG = IoStatsTrackerTest.class.getSimpleName();
43 
testNewUsersAppear()44     public void testNewUsersAppear() throws Exception {
45         final MockSystemStateInterface mockSystemStateInterface = new MockSystemStateInterface();
46         IoStatsTracker ioStatsTracker = new IoStatsTracker(EMPTY,
47             SAMPLE_WINDOW_MS, mockSystemStateInterface);
48 
49         assertEquals(0, ioStatsTracker.getCurrentSample().size());
50         assertEquals(0, ioStatsTracker.getTotal().size());
51 
52         UserActivity user0 = new UserActivity(0);
53         user0.foreground_rchar = 50;
54         user0.background_wchar = 10;
55 
56         UserActivity user1 = new UserActivity(1);
57         user1.foreground_rchar = 30;
58         user1.background_wchar = 50;
59 
60         UidIoRecord process0 = user0.updateSystemState(mockSystemStateInterface);
61         UidIoRecord process1 = user1.updateSystemState(mockSystemStateInterface);
62 
63         ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
64 
65         assertEquals(2, ioStatsTracker.getCurrentSample().size());
66         assertEquals(2, ioStatsTracker.getTotal().size());
67 
68         assertTrue(ioStatsTracker.getCurrentSample().get(0).representsSameMetrics(process0));
69         assertTrue(ioStatsTracker.getCurrentSample().get(1).representsSameMetrics(process1));
70 
71         assertTrue(ioStatsTracker.getTotal().get(0).representsSameMetrics(process0));
72         assertTrue(ioStatsTracker.getTotal().get(1).representsSameMetrics(process1));
73     }
74 
testUserMetricsChange()75     public void testUserMetricsChange() throws Exception {
76         final MockSystemStateInterface mockSystemStateInterface = new MockSystemStateInterface();
77         IoStatsTracker ioStatsTracker = new IoStatsTracker(EMPTY,
78             SAMPLE_WINDOW_MS, mockSystemStateInterface);
79 
80         UserActivity user0 = new UserActivity(0);
81         user0.foreground_rchar = 50;
82         user0.background_wchar = 10;
83 
84         user0.updateSystemState(mockSystemStateInterface);
85         ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
86 
87         user0.foreground_rchar = 60;
88         user0.foreground_wchar = 10;
89         UidIoRecord process0 = user0.updateSystemState(mockSystemStateInterface);
90         ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
91 
92         assertEquals(1, ioStatsTracker.getCurrentSample().size());
93         assertEquals(1, ioStatsTracker.getTotal().size());
94 
95         IoStatsEntry sample0 = ioStatsTracker.getCurrentSample().get(0);
96         IoStatsEntry total0 = ioStatsTracker.getTotal().get(0);
97 
98         assertNotNull(sample0);
99         assertNotNull(total0);
100 
101         assertTrue(total0.representsSameMetrics(process0));
102 
103         assertEquals(10, sample0.foreground.bytesRead);
104         assertEquals(10, sample0.foreground.bytesWritten);
105         assertEquals(0, sample0.background.bytesWritten);
106     }
107 
testUpdateNoIoProcessActive()108     public void testUpdateNoIoProcessActive() throws Exception {
109         final MockSystemStateInterface mockSystemStateInterface = new MockSystemStateInterface();
110         IoStatsTracker ioStatsTracker = new IoStatsTracker(EMPTY,
111             SAMPLE_WINDOW_MS, mockSystemStateInterface);
112 
113         UserActivity user0 = new UserActivity(0);
114         user0.foreground_rchar = 50;
115         user0.background_wchar = 10;
116 
117         user0.updateSystemState(mockSystemStateInterface);
118         ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
119 
120         user0.spawnProcess();
121         user0.updateSystemState(mockSystemStateInterface);
122         ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
123 
124         assertEquals(1, ioStatsTracker.getCurrentSample().size());
125         assertEquals(1, ioStatsTracker.getTotal().size());
126 
127         IoStatsEntry sample0 = ioStatsTracker.getCurrentSample().get(0);
128         IoStatsEntry total0 = ioStatsTracker.getTotal().get(0);
129 
130         assertEquals(2 * SAMPLE_WINDOW_MS, sample0.runtimeMillis);
131         assertEquals(2 * SAMPLE_WINDOW_MS, total0.runtimeMillis);
132 
133         assertEquals(0, sample0.foreground.bytesRead);
134         assertEquals(0, sample0.background.bytesWritten);
135     }
136 
testUpdateNoIoProcessInactive()137     public void testUpdateNoIoProcessInactive() throws Exception {
138         final MockSystemStateInterface mockSystemStateInterface = new MockSystemStateInterface();
139         IoStatsTracker ioStatsTracker = new IoStatsTracker(EMPTY,
140             SAMPLE_WINDOW_MS, mockSystemStateInterface);
141 
142         UserActivity user0 = new UserActivity(0);
143         user0.foreground_rchar = 50;
144         user0.background_wchar = 10;
145 
146         user0.updateSystemState(mockSystemStateInterface);
147         ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
148 
149         user0.killProcess();
150         UidIoRecord record0 = user0.updateSystemState(mockSystemStateInterface);
151         ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
152 
153         assertEquals(0, ioStatsTracker.getCurrentSample().size());
154         assertEquals(1, ioStatsTracker.getTotal().size());
155 
156         IoStatsEntry total0 = ioStatsTracker.getTotal().get(0);
157         assertEquals(SAMPLE_WINDOW_MS, total0.runtimeMillis);
158         assertTrue(total0.representsSameMetrics(record0));
159     }
160 
testUpdateIoHappens()161     public void testUpdateIoHappens() throws Exception {
162         final MockSystemStateInterface mockSystemStateInterface = new MockSystemStateInterface();
163         IoStatsTracker ioStatsTracker = new IoStatsTracker(EMPTY,
164             SAMPLE_WINDOW_MS, mockSystemStateInterface);
165 
166         UserActivity user0 = new UserActivity(0);
167         user0.foreground_rchar = 50;
168         user0.background_wchar = 10;
169 
170         user0.updateSystemState(mockSystemStateInterface);
171         ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
172 
173         user0.foreground_rchar = 60;
174         UidIoRecord record0 = user0.updateSystemState(mockSystemStateInterface);
175         ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
176 
177         assertEquals(1, ioStatsTracker.getCurrentSample().size());
178         assertEquals(1, ioStatsTracker.getTotal().size());
179 
180         IoStatsEntry sample0 = ioStatsTracker.getCurrentSample().get(0);
181         IoStatsEntry total0 = ioStatsTracker.getTotal().get(0);
182 
183         assertTrue(total0.representsSameMetrics(record0));
184         assertEquals(2 * SAMPLE_WINDOW_MS, total0.runtimeMillis);
185         assertEquals(2 * SAMPLE_WINDOW_MS, sample0.runtimeMillis);
186         assertEquals(10, sample0.foreground.bytesRead);
187         assertEquals(0, sample0.background.bytesWritten);
188     }
189 
testUpdateGoAwayComeBackProcess()190     public void testUpdateGoAwayComeBackProcess() throws Exception {
191         final MockSystemStateInterface mockSystemStateInterface = new MockSystemStateInterface();
192         IoStatsTracker ioStatsTracker = new IoStatsTracker(EMPTY,
193             SAMPLE_WINDOW_MS, mockSystemStateInterface);
194 
195         UserActivity user0 = new UserActivity(0);
196         user0.foreground_rchar = 50;
197         user0.background_wchar = 10;
198 
199         user0.updateSystemState(mockSystemStateInterface);
200         ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
201 
202         ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
203 
204         assertEquals(0, ioStatsTracker.getCurrentSample().size());
205         assertEquals(1, ioStatsTracker.getTotal().size());
206 
207         user0.spawnProcess();
208         user0.updateSystemState(mockSystemStateInterface);
209         ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
210 
211         assertEquals(1, ioStatsTracker.getCurrentSample().size());
212         IoStatsEntry sample0 = ioStatsTracker.getCurrentSample().get(0);
213         assertEquals(2 * SAMPLE_WINDOW_MS, sample0.runtimeMillis);
214     }
215 
testUpdateGoAwayComeBackIo()216     public void testUpdateGoAwayComeBackIo() throws Exception {
217         final MockSystemStateInterface mockSystemStateInterface = new MockSystemStateInterface();
218         IoStatsTracker ioStatsTracker = new IoStatsTracker(EMPTY,
219             SAMPLE_WINDOW_MS, mockSystemStateInterface);
220 
221         UserActivity user0 = new UserActivity(0);
222         user0.foreground_rchar = 50;
223         user0.background_wchar = 10;
224 
225         user0.updateSystemState(mockSystemStateInterface);
226         ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
227 
228         ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
229 
230         assertEquals(0, ioStatsTracker.getCurrentSample().size());
231         assertEquals(1, ioStatsTracker.getTotal().size());
232 
233         user0.foreground_fsync = 1;
234 
235         user0.updateSystemState(mockSystemStateInterface);
236         ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
237 
238         assertEquals(1, ioStatsTracker.getCurrentSample().size());
239 
240         IoStatsEntry sample0 = ioStatsTracker.getCurrentSample().get(0);
241         assertEquals(2 * SAMPLE_WINDOW_MS, sample0.runtimeMillis);
242         assertEquals(1, sample0.foreground.fsyncCalls);
243     }
244 
245     private static final class UserActivity {
246         private final int mUid;
247         private boolean mHasProcess;
248 
249         private long foreground_rchar;
250         private long foreground_wchar;
251         private long foreground_read_bytes;
252         private long foreground_write_bytes;
253         private long foreground_fsync;
254 
255         private long background_rchar;
256         private long background_wchar;
257         private long background_read_bytes;
258         private long background_write_bytes;
259         private long background_fsync;
260 
UserActivity(int uid)261         UserActivity(int uid) {
262             mUid = uid;
263         }
264 
spawnProcess()265         void spawnProcess() {
266             mHasProcess = true;
267         }
killProcess()268         void killProcess() {
269             mHasProcess = false;
270         }
271 
updateSystemState(MockSystemStateInterface systemState)272         UidIoRecord updateSystemState(MockSystemStateInterface systemState) {
273             UidIoRecord uidIoRecord = new UidIoRecord(mUid,
274                 foreground_rchar,
275                 foreground_wchar,
276                 foreground_read_bytes,
277                 foreground_write_bytes,
278                 foreground_fsync,
279                 background_rchar,
280                 background_wchar,
281                 background_read_bytes,
282                 background_write_bytes,
283                 background_fsync);
284 
285             systemState.addIoRecord(uidIoRecord);
286             if (mHasProcess) {
287                 systemState.addProcess(new ProcessInfo(1, mUid));
288             } else {
289                 systemState.removeUserProcesses(mUid);
290             }
291 
292             return uidIoRecord;
293         }
294     }
295 
296     private final class MockSystemStateInterface implements SystemStateInterface {
297         private final List<ProcessInfo> mProcesses = new ArrayList<>();
298         private final SparseArray<UidIoRecord> mIoRecords = new SparseArray<>();
299 
300         @Override
shutdown()301         public void shutdown() {
302         }
303 
304         @Override
enterDeepSleep()305         public boolean enterDeepSleep() {
306             return true;
307         }
308 
309         @Override
scheduleActionForBootCompleted(Runnable action, Duration delay)310         public void scheduleActionForBootCompleted(Runnable action, Duration delay) {
311         }
312 
313         @Override
isWakeupCausedByTimer()314         public boolean isWakeupCausedByTimer() {
315             return false;
316         }
317 
318         @Override
isSystemSupportingDeepSleep()319         public boolean isSystemSupportingDeepSleep() {
320             return false;
321         }
322 
323         @Override
getRunningProcesses()324         public synchronized List<ProcessInfo> getRunningProcesses() {
325             return mProcesses;
326         }
327 
addProcess(ProcessInfo processInfo)328         synchronized void addProcess(ProcessInfo processInfo) {
329             mProcesses.add(processInfo);
330         }
331 
removeUserProcesses(int uid)332         synchronized void removeUserProcesses(int uid) {
333             mProcesses.removeAll(
334                     mProcesses.stream().filter(pi -> pi.uid == uid).collect(Collectors.toList()));
335         }
336 
addIoRecord(UidIoRecord record)337         synchronized void addIoRecord(UidIoRecord record) {
338             mIoRecords.put(record.uid, record);
339         }
340 
clear()341         synchronized void clear() {
342             mProcesses.clear();
343             mIoRecords.clear();
344         }
345     }
346 }
347