1 /* 2 * Copyright (C) 2018 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.internal.os; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.mockito.Mockito.mockitoSession; 22 import static org.mockito.Mockito.when; 23 import static org.testng.Assert.assertThrows; 24 25 import static java.util.stream.Collectors.toList; 26 27 import android.platform.test.annotations.Presubmit; 28 29 import androidx.test.filters.SmallTest; 30 import androidx.test.runner.AndroidJUnit4; 31 32 import org.junit.After; 33 import org.junit.Before; 34 import org.junit.Test; 35 import org.junit.runner.RunWith; 36 import org.mockito.Mock; 37 import org.mockito.MockitoSession; 38 39 import java.util.ArrayList; 40 import java.util.Arrays; 41 import java.util.Collection; 42 import java.util.Collections; 43 44 @Presubmit 45 @SmallTest 46 @RunWith(AndroidJUnit4.class) 47 public class KernelCpuThreadReaderDiffTest { 48 49 private MockitoSession mMockingSessions; 50 @Mock KernelCpuThreadReader mMockReader; 51 52 @Before setUp()53 public void setUp() { 54 mMockingSessions = mockitoSession().initMocks(this).startMocking(); 55 } 56 57 @After tearDown()58 public void tearDown() { 59 if (mMockingSessions != null) { 60 mMockingSessions.finishMocking(); 61 } 62 } 63 64 @Test test_empty()65 public void test_empty() { 66 KernelCpuThreadReaderDiff kernelCpuThreadReaderDiff = 67 new KernelCpuThreadReaderDiff(mMockReader, 0); 68 assertThat(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed()).isNull(); 69 assertThat(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed()).isEmpty(); 70 } 71 72 @Test test_simple()73 public void test_simple() { 74 when(mMockReader.getProcessCpuUsage()) 75 .thenReturn(createProcess(new int[] {100, 100, 100})) 76 .thenReturn(createProcess(new int[] {150, 160, 170})); 77 KernelCpuThreadReaderDiff kernelCpuThreadReaderDiff = 78 new KernelCpuThreadReaderDiff(mMockReader, 0); 79 assertThat(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed()).isNull(); 80 assertThat(cpuUsages(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed())) 81 .containsExactly(Arrays.asList(50, 60, 70)); 82 } 83 84 @Test test_failure()85 public void test_failure() { 86 when(mMockReader.getProcessCpuUsage()) 87 .thenReturn(createProcess(new int[] {1})) 88 .thenReturn(createProcess(new int[] {2})) 89 .thenThrow(new RuntimeException()) 90 .thenReturn(createProcess(new int[] {4})) 91 .thenReturn(createProcess(new int[] {6})); 92 KernelCpuThreadReaderDiff kernelCpuThreadReaderDiff = 93 new KernelCpuThreadReaderDiff(mMockReader, 0); 94 assertThat(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed()).isNull(); 95 assertThat(cpuUsages(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed())) 96 .containsExactly(Collections.singletonList(1)); 97 assertThrows( 98 RuntimeException.class, 99 () -> cpuUsages(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed())); 100 assertThat(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed()).isNull(); 101 assertThat(cpuUsages(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed())) 102 .containsExactly(Collections.singletonList(2)); 103 } 104 105 @Test test_twoFailures()106 public void test_twoFailures() { 107 when(mMockReader.getProcessCpuUsage()) 108 .thenReturn(createProcess(new int[] {1})) 109 .thenReturn(createProcess(new int[] {2})) 110 .thenThrow(new RuntimeException()) 111 .thenThrow(new RuntimeException()) 112 .thenReturn(createProcess(new int[] {4})) 113 .thenReturn(createProcess(new int[] {6})); 114 KernelCpuThreadReaderDiff kernelCpuThreadReaderDiff = 115 new KernelCpuThreadReaderDiff(mMockReader, 0); 116 assertThat(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed()).isNull(); 117 assertThat(cpuUsages(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed())) 118 .containsExactly(Collections.singletonList(1)); 119 assertThrows( 120 RuntimeException.class, 121 () -> cpuUsages(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed())); 122 assertThrows( 123 RuntimeException.class, 124 () -> cpuUsages(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed())); 125 assertThat(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed()).isNull(); 126 assertThat(cpuUsages(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed())) 127 .containsExactly(Collections.singletonList(2)); 128 } 129 130 @Test test_negativeDiff()131 public void test_negativeDiff() { 132 when(mMockReader.getProcessCpuUsage()) 133 .thenReturn(createProcess(new int[] {2})) 134 .thenReturn(createProcess(new int[] {1})); 135 KernelCpuThreadReaderDiff kernelCpuThreadReaderDiff = 136 new KernelCpuThreadReaderDiff(mMockReader, 0); 137 assertThat(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed()).isNull(); 138 assertThat(cpuUsages(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed())) 139 .containsExactly(Collections.singletonList(-1)); 140 } 141 142 @Test test_threshold()143 public void test_threshold() { 144 when(mMockReader.getProcessCpuUsage()) 145 .thenReturn(createProcess(new int[] {1})) 146 .thenReturn(createProcess(new int[] {10})) 147 .thenReturn(createProcess(new int[] {12})) 148 .thenReturn(createProcess(new int[] {20})); 149 KernelCpuThreadReaderDiff kernelCpuThreadReaderDiff = 150 new KernelCpuThreadReaderDiff(mMockReader, 5); 151 assertThat(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed()).isNull(); 152 153 ArrayList<KernelCpuThreadReader.ProcessCpuUsage> processes1 = 154 kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed(); 155 assertThat(cpuUsages(processes1)).containsExactly(Collections.singletonList(9)); 156 assertThat(threadNames(processes1)).containsExactly("thread0"); 157 158 ArrayList<KernelCpuThreadReader.ProcessCpuUsage> processes2 = 159 kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed(); 160 assertThat(cpuUsages(processes2)).containsExactly(Collections.singletonList(2)); 161 assertThat(threadNames(processes2)).containsExactly("__OTHER_THREADS"); 162 163 ArrayList<KernelCpuThreadReader.ProcessCpuUsage> processes3 = 164 kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed(); 165 assertThat(cpuUsages(processes3)).containsExactly(Collections.singletonList(8)); 166 assertThat(threadNames(processes3)).containsExactly("thread0"); 167 } 168 169 @Test test_newThread()170 public void test_newThread() { 171 when(mMockReader.getProcessCpuUsage()) 172 .thenReturn(createProcess(new int[] {1})) 173 .thenReturn(createProcess(new int[] {2})) 174 .thenReturn(createProcess(new int[] {4}, new int[] {5})); 175 KernelCpuThreadReaderDiff kernelCpuThreadReaderDiff = 176 new KernelCpuThreadReaderDiff(mMockReader, 0); 177 assertThat(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed()).isNull(); 178 179 ArrayList<KernelCpuThreadReader.ProcessCpuUsage> processes1 = 180 kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed(); 181 assertThat(cpuUsages(processes1)).containsExactly(Collections.singletonList(1)); 182 assertThat(threadNames(processes1)).containsExactly("thread0"); 183 184 ArrayList<KernelCpuThreadReader.ProcessCpuUsage> processes2 = 185 kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed(); 186 assertThat(cpuUsages(processes2)) 187 .containsExactly(Collections.singletonList(2), Collections.singletonList(5)); 188 assertThat(threadNames(processes2)).containsExactly("thread0", "thread1"); 189 } 190 191 @Test test_stoppedThread()192 public void test_stoppedThread() { 193 when(mMockReader.getProcessCpuUsage()) 194 .thenReturn(createProcess(new int[] {1}, new int[] {1})) 195 .thenReturn(createProcess(new int[] {2}, new int[] {3})) 196 .thenReturn(createProcess(new int[] {4})); 197 KernelCpuThreadReaderDiff kernelCpuThreadReaderDiff = 198 new KernelCpuThreadReaderDiff(mMockReader, 0); 199 assertThat(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed()).isNull(); 200 201 ArrayList<KernelCpuThreadReader.ProcessCpuUsage> processes1 = 202 kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed(); 203 assertThat(cpuUsages(processes1)) 204 .containsExactly(Collections.singletonList(1), Collections.singletonList(2)); 205 assertThat(threadNames(processes1)).containsExactly("thread0", "thread1"); 206 207 ArrayList<KernelCpuThreadReader.ProcessCpuUsage> processes2 = 208 kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed(); 209 assertThat(cpuUsages(processes2)).containsExactly(Collections.singletonList(2)); 210 assertThat(threadNames(processes2)).containsExactly("thread0"); 211 } 212 213 @Test test_nonNegativeOtherThreads()214 public void test_nonNegativeOtherThreads() { 215 when(mMockReader.getProcessCpuUsage()) 216 .thenReturn(createProcess(new int[] {0}, new int[] {0})) 217 .thenReturn(createProcess(new int[] {4}, new int[] {4})) 218 .thenReturn(createProcess(new int[] {10}, new int[] {7})) 219 .thenReturn(createProcess(new int[] {20}, new int[] {15})); 220 KernelCpuThreadReaderDiff kernelCpuThreadReaderDiff = 221 new KernelCpuThreadReaderDiff(mMockReader, 5); 222 assertThat(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed()).isNull(); 223 224 ArrayList<KernelCpuThreadReader.ProcessCpuUsage> processes1 = 225 kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed(); 226 assertThat(cpuUsages(processes1)).containsExactly(Collections.singletonList(8)); 227 assertThat(threadNames(processes1)).containsExactly("__OTHER_THREADS"); 228 229 ArrayList<KernelCpuThreadReader.ProcessCpuUsage> processes2 = 230 kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed(); 231 assertThat(cpuUsages(processes2)) 232 .containsExactly(Collections.singletonList(6), Collections.singletonList(3)); 233 assertThat(threadNames(processes2)).containsExactly("thread0", "__OTHER_THREADS"); 234 235 ArrayList<KernelCpuThreadReader.ProcessCpuUsage> processes3 = 236 kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed(); 237 assertThat(cpuUsages(processes3)) 238 .containsExactly(Collections.singletonList(10), Collections.singletonList(8)); 239 assertThat(threadNames(processes3)).containsExactly("thread0", "thread1"); 240 } 241 242 @Test test_otherThreadsOnZeroDiff()243 public void test_otherThreadsOnZeroDiff() { 244 when(mMockReader.getProcessCpuUsage()) 245 .thenReturn(createProcess(new int[] {0})) 246 .thenReturn(createProcess(new int[] {0})); 247 KernelCpuThreadReaderDiff kernelCpuThreadReaderDiff = 248 new KernelCpuThreadReaderDiff(mMockReader, 5); 249 assertThat(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed()).isNull(); 250 251 ArrayList<KernelCpuThreadReader.ProcessCpuUsage> processes1 = 252 kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed(); 253 assertThat(cpuUsages(processes1)).containsExactly(Collections.singletonList(0)); 254 assertThat(threadNames(processes1)).containsExactly("__OTHER_THREADS"); 255 } 256 257 @Test test_failureAndNewThread()258 public void test_failureAndNewThread() { 259 when(mMockReader.getProcessCpuUsage()) 260 .thenReturn(createProcess(new int[] {0})) 261 .thenThrow(new RuntimeException()) 262 .thenReturn(createProcess(new int[] {1}, new int[] {10})) 263 .thenReturn(createProcess(new int[] {2}, new int[] {12})); 264 KernelCpuThreadReaderDiff kernelCpuThreadReaderDiff = 265 new KernelCpuThreadReaderDiff(mMockReader, 0); 266 assertThat(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed()).isNull(); 267 268 assertThrows( 269 RuntimeException.class, 270 () -> cpuUsages(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed())); 271 assertThat(kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed()).isNull(); 272 273 ArrayList<KernelCpuThreadReader.ProcessCpuUsage> processes1 = 274 kernelCpuThreadReaderDiff.getProcessCpuUsageDiffed(); 275 assertThat(cpuUsages(processes1)) 276 .containsExactly(Collections.singletonList(1), Collections.singletonList(2)); 277 assertThat(threadNames(processes1)).containsExactly("thread0", "thread1"); 278 } 279 createProcess( int[]... cpuUsageMillis)280 private ArrayList<KernelCpuThreadReader.ProcessCpuUsage> createProcess( 281 int[]... cpuUsageMillis) { 282 ArrayList<KernelCpuThreadReader.ThreadCpuUsage> threadCpuUsages = new ArrayList<>(); 283 for (int i = 0; i < cpuUsageMillis.length; i++) { 284 int[] cpuUsage = cpuUsageMillis[i]; 285 threadCpuUsages.add( 286 new KernelCpuThreadReader.ThreadCpuUsage(0, "thread" + i, cpuUsage)); 287 } 288 return new ArrayList<>( 289 Collections.singletonList( 290 new KernelCpuThreadReader.ProcessCpuUsage( 291 0, "process", 0, threadCpuUsages))); 292 } 293 cpuUsages( Collection<KernelCpuThreadReader.ProcessCpuUsage> processCpuUsages)294 private Collection<Collection<Integer>> cpuUsages( 295 Collection<KernelCpuThreadReader.ProcessCpuUsage> processCpuUsages) { 296 return processCpuUsages.stream() 297 .flatMap(p -> p.threadCpuUsages.stream()) 298 .map(t -> Arrays.stream(t.usageTimesMillis).boxed().collect(toList())) 299 .collect(toList()); 300 } 301 threadNames( Collection<KernelCpuThreadReader.ProcessCpuUsage> processCpuUsages)302 private Collection<String> threadNames( 303 Collection<KernelCpuThreadReader.ProcessCpuUsage> processCpuUsages) { 304 return processCpuUsages.stream() 305 .flatMap(p -> p.threadCpuUsages.stream()) 306 .map(t -> t.threadName) 307 .collect(toList()); 308 } 309 } 310