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