blob: 95b0b294f1b3f5d09df4252994d28a831695674c [file] [log] [blame]
Sudheer Shanka9b735c52017-05-09 18:26:18 -07001/*
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
17package com.android.internal.os;
18
Sudheer Shankab8ad5942017-08-08 12:16:09 -070019import static org.junit.Assert.assertArrayEquals;
20import static org.junit.Assert.assertEquals;
21import static org.junit.Assert.assertFalse;
22import static org.junit.Assert.assertNull;
23import static org.junit.Assert.assertTrue;
Sudheer Shanka9b735c52017-05-09 18:26:18 -070024import static org.mockito.Mockito.verify;
25import static org.mockito.Mockito.verifyNoMoreInteractions;
Sudheer Shanka59f5c002017-05-15 10:57:15 -070026import static org.mockito.Mockito.verifyZeroInteractions;
Sudheer Shanka9b735c52017-05-09 18:26:18 -070027import static org.mockito.Mockito.when;
28
29import android.support.test.filters.SmallTest;
30import android.support.test.runner.AndroidJUnit4;
31
32import org.junit.Before;
33import org.junit.Test;
34import org.junit.runner.RunWith;
35import org.mockito.Mock;
Sudheer Shanka59f5c002017-05-15 10:57:15 -070036import org.mockito.Mockito;
Sudheer Shanka9b735c52017-05-09 18:26:18 -070037import org.mockito.MockitoAnnotations;
38
39import java.io.BufferedReader;
Sudheer Shankab8ad5942017-08-08 12:16:09 -070040import java.util.Arrays;
Sudheer Shanka9b735c52017-05-09 18:26:18 -070041
42/**
43 * Test class for {@link KernelUidCpuFreqTimeReader}.
44 *
45 * To run the tests, use
46 *
47 * runtest -c com.android.internal.os.KernelUidCpuFreqTimeReaderTest frameworks-core
48 *
49 * or the following steps:
50 *
51 * Build: m FrameworksCoreTests
52 * Install: adb install -r \
53 * ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
54 * Run: adb shell am instrument -e class com.android.internal.os.KernelUidCpuFreqTimeReaderTest -w \
55 * com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
Sudheer Shankab8ad5942017-08-08 12:16:09 -070056 *
57 * or
58 *
59 * bit FrameworksCoreTests:com.android.internal.os.KernelUidCpuFreqTimeReaderTest
Sudheer Shanka9b735c52017-05-09 18:26:18 -070060 */
61@SmallTest
62@RunWith(AndroidJUnit4.class)
63public class KernelUidCpuFreqTimeReaderTest {
64 @Mock private BufferedReader mBufferedReader;
65 @Mock private KernelUidCpuFreqTimeReader.Callback mCallback;
Sudheer Shankab8ad5942017-08-08 12:16:09 -070066 @Mock private PowerProfile mPowerProfile;
Sudheer Shanka9b735c52017-05-09 18:26:18 -070067
68 private KernelUidCpuFreqTimeReader mKernelUidCpuFreqTimeReader;
69
70 @Before
71 public void setUp() {
72 MockitoAnnotations.initMocks(this);
73 mKernelUidCpuFreqTimeReader = new KernelUidCpuFreqTimeReader();
74 }
75
76 @Test
Sudheer Shankab8ad5942017-08-08 12:16:09 -070077 public void testReadFreqs_perClusterTimesNotAvailable() throws Exception {
78 final long[][] freqs = {
79 {1, 12, 123, 1234},
80 {1, 12, 123, 23, 123, 1234, 12345, 123456},
81 {1, 12, 123, 23, 123, 1234, 12345, 123456, 12, 123, 12345},
82 {1, 12, 123, 23, 2345, 234567}
83 };
84 final int[] numClusters = {2, 2, 3, 1};
85 final int[][] numFreqs = {{3, 6}, {4, 5}, {3, 5, 4}, {3}};
86 for (int i = 0; i < freqs.length; ++i) {
87 setCpuClusterFreqs(numClusters[i], numFreqs[i]);
88 when(mBufferedReader.readLine()).thenReturn(getFreqsLine(freqs[i]));
89 long[] actualFreqs = mKernelUidCpuFreqTimeReader.readFreqs(
90 mBufferedReader, mPowerProfile);
91 assertArrayEquals(freqs[i], actualFreqs);
92 verifyZeroInteractions(mCallback);
93 final String errMsg = String.format("Freqs=%s, nClusters=%d, nFreqs=%s",
94 Arrays.toString(freqs[i]), numClusters[i], Arrays.toString(numFreqs[i]));
95 assertFalse(errMsg, mKernelUidCpuFreqTimeReader.perClusterTimesAvailable());
96
97 // Verify that a second call won't read the proc file again
98 Mockito.reset(mBufferedReader);
99 actualFreqs = mKernelUidCpuFreqTimeReader.readFreqs(mPowerProfile);
100 assertArrayEquals(freqs[i], actualFreqs);
101 assertFalse(errMsg, mKernelUidCpuFreqTimeReader.perClusterTimesAvailable());
102
103 // Prepare for next iteration
104 Mockito.reset(mBufferedReader, mPowerProfile);
105 }
106 }
107
108 @Test
109 public void testReadFreqs_perClusterTimesAvailable() throws Exception {
110 final long[][] freqs = {
111 {1, 12, 123, 1234},
112 {1, 12, 123, 23, 123, 1234, 12345, 123456},
113 {1, 12, 123, 23, 123, 1234, 12345, 123456, 12, 123, 12345, 1234567}
114 };
115 final int[] numClusters = {1, 2, 3};
116 final int[][] numFreqs = {{4}, {3, 5}, {3, 5, 4}};
117 for (int i = 0; i < freqs.length; ++i) {
118 setCpuClusterFreqs(numClusters[i], numFreqs[i]);
119 when(mBufferedReader.readLine()).thenReturn(getFreqsLine(freqs[i]));
120 long[] actualFreqs = mKernelUidCpuFreqTimeReader.readFreqs(
121 mBufferedReader, mPowerProfile);
122 assertArrayEquals(freqs[i], actualFreqs);
123 verifyZeroInteractions(mCallback);
124 final String errMsg = String.format("Freqs=%s, nClusters=%d, nFreqs=%s",
125 Arrays.toString(freqs[i]), numClusters[i], Arrays.toString(numFreqs[i]));
126 assertTrue(errMsg, mKernelUidCpuFreqTimeReader.perClusterTimesAvailable());
127
128 // Verify that a second call won't read the proc file again
129 Mockito.reset(mBufferedReader);
130 actualFreqs = mKernelUidCpuFreqTimeReader.readFreqs(mPowerProfile);
131 assertArrayEquals(freqs[i], actualFreqs);
132 assertTrue(errMsg, mKernelUidCpuFreqTimeReader.perClusterTimesAvailable());
133
134 // Prepare for next iteration
135 Mockito.reset(mBufferedReader, mPowerProfile);
136 }
137 }
138
139 @Test
Sudheer Shanka9b735c52017-05-09 18:26:18 -0700140 public void testReadDelta() throws Exception {
141 final long[] freqs = {1, 12, 123, 1234, 12345, 123456};
142 final int[] uids = {1, 22, 333, 4444, 5555};
143 final long[][] times = new long[uids.length][freqs.length];
144 for (int i = 0; i < uids.length; ++i) {
145 for (int j = 0; j < freqs.length; ++j) {
146 times[i][j] = uids[i] * freqs[j] * 10;
147 }
148 }
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700149 when(mBufferedReader.readLine()).thenReturn(getFreqsLine(freqs));
150 long[] actualFreqs = mKernelUidCpuFreqTimeReader.readFreqs(mBufferedReader, mPowerProfile);
151
152 assertArrayEquals(freqs, actualFreqs);
Sudheer Shanka9b735c52017-05-09 18:26:18 -0700153 when(mBufferedReader.readLine())
Sudheer Shanka59f5c002017-05-15 10:57:15 -0700154 .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, times));
Sudheer Shanka9b735c52017-05-09 18:26:18 -0700155 mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
Sudheer Shanka9b735c52017-05-09 18:26:18 -0700156 for (int i = 0; i < uids.length; ++i) {
157 verify(mCallback).onUidCpuFreqTime(uids[i], times[i]);
158 }
159 verifyNoMoreInteractions(mCallback);
Sudheer Shanka59f5c002017-05-15 10:57:15 -0700160
161 // Verify that a second call will only return deltas.
162 Mockito.reset(mCallback, mBufferedReader);
163 final long[][] newTimes1 = new long[uids.length][freqs.length];
164 for (int i = 0; i < uids.length; ++i) {
165 for (int j = 0; j < freqs.length; ++j) {
166 newTimes1[i][j] = (times[i][j] + uids[i] + freqs[j]) * 10;
167 }
168 }
169 when(mBufferedReader.readLine())
170 .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes1));
171 mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
Sudheer Shanka59f5c002017-05-15 10:57:15 -0700172 for (int i = 0; i < uids.length; ++i) {
173 verify(mCallback).onUidCpuFreqTime(uids[i], subtract(newTimes1[i], times[i]));
174 }
175 verifyNoMoreInteractions(mCallback);
176
Sudheer Shanka00857522017-07-06 18:28:14 -0700177 // Verify that there won't be a callback if the proc file values didn't change.
178 Mockito.reset(mCallback, mBufferedReader);
179 when(mBufferedReader.readLine())
180 .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes1));
181 mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
Sudheer Shanka00857522017-07-06 18:28:14 -0700182 verifyNoMoreInteractions(mCallback);
183
Sudheer Shanka59f5c002017-05-15 10:57:15 -0700184 // Verify that calling with a null callback doesn't result in any crashes
185 Mockito.reset(mCallback, mBufferedReader);
186 final long[][] newTimes2 = new long[uids.length][freqs.length];
187 for (int i = 0; i < uids.length; ++i) {
188 for (int j = 0; j < freqs.length; ++j) {
189 newTimes2[i][j] = (newTimes1[i][j] + uids[i] * freqs[j]) * 10;
190 }
191 }
192 when(mBufferedReader.readLine())
193 .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes2));
194 mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, null);
Sudheer Shanka59f5c002017-05-15 10:57:15 -0700195
196 // Verify that the readDelta call will only return deltas when
197 // the previous call had null callback.
198 Mockito.reset(mCallback, mBufferedReader);
199 final long[][] newTimes3 = new long[uids.length][freqs.length];
200 for (int i = 0; i < uids.length; ++i) {
201 for (int j = 0; j < freqs.length; ++j) {
202 newTimes3[i][j] = (newTimes2[i][j] * (uids[i] + freqs[j])) * 10;
203 }
204 }
205 when(mBufferedReader.readLine())
206 .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes3));
207 mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
Sudheer Shanka59f5c002017-05-15 10:57:15 -0700208 for (int i = 0; i < uids.length; ++i) {
209 verify(mCallback).onUidCpuFreqTime(uids[i], subtract(newTimes3[i], newTimes2[i]));
210 }
211 verifyNoMoreInteractions(mCallback);
212 }
213
Sudheer Shanka00857522017-07-06 18:28:14 -0700214 @Test
215 public void testReadDelta_malformedData() throws Exception {
216 final long[] freqs = {1, 12, 123, 1234, 12345, 123456};
217 final int[] uids = {1, 22, 333, 4444, 5555};
218 final long[][] times = new long[uids.length][freqs.length];
219 for (int i = 0; i < uids.length; ++i) {
220 for (int j = 0; j < freqs.length; ++j) {
221 times[i][j] = uids[i] * freqs[j] * 10;
222 }
223 }
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700224 when(mBufferedReader.readLine()).thenReturn(getFreqsLine(freqs));
225 long[] actualFreqs = mKernelUidCpuFreqTimeReader.readFreqs(mBufferedReader, mPowerProfile);
226
227 assertArrayEquals(freqs, actualFreqs);
Sudheer Shanka00857522017-07-06 18:28:14 -0700228 when(mBufferedReader.readLine())
229 .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, times));
230 mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
Sudheer Shanka00857522017-07-06 18:28:14 -0700231 for (int i = 0; i < uids.length; ++i) {
232 verify(mCallback).onUidCpuFreqTime(uids[i], times[i]);
233 }
234 verifyNoMoreInteractions(mCallback);
235
236 // Verify that there is no callback if any value in the proc file is -ve.
237 Mockito.reset(mCallback, mBufferedReader);
238 final long[][] newTimes1 = new long[uids.length][freqs.length];
239 for (int i = 0; i < uids.length; ++i) {
240 for (int j = 0; j < freqs.length; ++j) {
241 newTimes1[i][j] = (times[i][j] + uids[i] + freqs[j]) * 10;
242 }
243 }
244 newTimes1[uids.length - 1][freqs.length - 1] *= -1;
245 when(mBufferedReader.readLine())
246 .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes1));
247 mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
Sudheer Shanka00857522017-07-06 18:28:14 -0700248 for (int i = 0; i < uids.length; ++i) {
249 if (i == uids.length - 1) {
250 continue;
251 }
252 verify(mCallback).onUidCpuFreqTime(uids[i], subtract(newTimes1[i], times[i]));
253 }
254 verifyNoMoreInteractions(mCallback);
255
256 // Verify that the internal state was not modified when the proc file had -ve value.
257 Mockito.reset(mCallback, mBufferedReader);
258 for (int i = 0; i < freqs.length; ++i) {
259 newTimes1[uids.length - 1][i] = times[uids.length - 1][i];
260 }
261 when(mBufferedReader.readLine())
262 .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes1));
263 mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
Sudheer Shanka00857522017-07-06 18:28:14 -0700264 verifyNoMoreInteractions(mCallback);
265
266 // Verify that there is no callback if the values in the proc file are decreased.
267 Mockito.reset(mCallback, mBufferedReader);
268 final long[][] newTimes2 = new long[uids.length][freqs.length];
269 for (int i = 0; i < uids.length; ++i) {
270 for (int j = 0; j < freqs.length; ++j) {
271 newTimes2[i][j] = (newTimes1[i][j] + uids[i] * freqs[j]) * 10;
272 }
273 }
274 newTimes2[uids.length - 1][freqs.length - 1] =
275 newTimes1[uids.length - 1][freqs.length - 1] - 222;
276 when(mBufferedReader.readLine())
277 .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes2));
278 mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
Sudheer Shanka00857522017-07-06 18:28:14 -0700279 for (int i = 0; i < uids.length; ++i) {
280 if (i == uids.length - 1) {
281 continue;
282 }
283 verify(mCallback).onUidCpuFreqTime(uids[i], subtract(newTimes2[i], newTimes1[i]));
284 }
285 verifyNoMoreInteractions(mCallback);
286
287 // Verify that the internal state was not modified when the proc file had decreasing values.
288 Mockito.reset(mCallback, mBufferedReader);
289 for (int i = 0; i < freqs.length; ++i) {
290 newTimes2[uids.length - 1][i] = newTimes1[uids.length - 1][i];
291 }
292 when(mBufferedReader.readLine())
293 .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes2));
294 mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
Sudheer Shanka00857522017-07-06 18:28:14 -0700295 verifyNoMoreInteractions(mCallback);
296 }
297
Sudheer Shanka59f5c002017-05-15 10:57:15 -0700298 private long[] subtract(long[] a1, long[] a2) {
299 long[] val = new long[a1.length];
300 for (int i = 0; i < val.length; ++i) {
301 val[i] = a1[i] - a2[i];
302 }
303 return val;
Sudheer Shanka9b735c52017-05-09 18:26:18 -0700304 }
305
306 private String getFreqsLine(long[] freqs) {
307 final StringBuilder sb = new StringBuilder();
308 sb.append("uid:");
309 for (int i = 0; i < freqs.length; ++i) {
310 sb.append(" " + freqs[i]);
311 }
312 return sb.toString();
313 }
314
315 private String[] getUidTimesLines(int[] uids, long[][] times) {
Sudheer Shanka59f5c002017-05-15 10:57:15 -0700316 final String[] lines = new String[uids.length + 1];
Sudheer Shanka9b735c52017-05-09 18:26:18 -0700317 final StringBuilder sb = new StringBuilder();
318 for (int i = 0; i < uids.length; ++i) {
319 sb.setLength(0);
320 sb.append(uids[i] + ":");
321 for (int j = 0; j < times[i].length; ++j) {
322 sb.append(" " + times[i][j] / 10);
323 }
324 lines[i] = sb.toString();
325 }
Sudheer Shanka59f5c002017-05-15 10:57:15 -0700326 lines[uids.length] = null;
Sudheer Shanka9b735c52017-05-09 18:26:18 -0700327 return lines;
328 }
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700329
330 private void setCpuClusterFreqs(int numClusters, int... clusterFreqs) {
331 assertEquals(numClusters, clusterFreqs.length);
332 when(mPowerProfile.getNumCpuClusters()).thenReturn(numClusters);
333 for (int i = 0; i < numClusters; ++i) {
334 when(mPowerProfile.getNumSpeedStepsInCpuCluster(i)).thenReturn(clusterFreqs[i]);
335 }
336 }
Sudheer Shanka9b735c52017-05-09 18:26:18 -0700337}