1 /* 2 * Copyright (C) 2023 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.helpers.tests; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertThrows; 22 import static org.junit.Assert.assertTrue; 23 import static org.mockito.Mockito.doReturn; 24 import static org.mockito.Mockito.doThrow; 25 26 import androidx.test.runner.AndroidJUnit4; 27 28 import com.android.helpers.GenericExecutableCollectorHelper; 29 30 import org.junit.Before; 31 import org.junit.BeforeClass; 32 import org.junit.Test; 33 import org.junit.runner.RunWith; 34 import org.mockito.MockitoAnnotations; 35 import org.mockito.Spy; 36 37 import java.io.File; 38 import java.io.IOException; 39 import java.nio.file.Files; 40 import java.util.Map; 41 42 /** 43 * Android unit tests for {@link GenericExecutableCollectorHelper}. 44 * 45 * <p>To run: atest CollectorsHelperAospTest:GenericExecutableCollectorHelperTest 46 */ 47 @RunWith(AndroidJUnit4.class) 48 public class GenericExecutableCollectorHelperTest { 49 private static final String TAG = GenericExecutableCollectorHelperTest.class.getSimpleName(); 50 private static final String VALID_EMPTY_DIR = "/data"; 51 private static final String INVALID_INPUT_DIR = "0"; 52 private static final String TEST_FILE_NAME = "test_file_"; 53 private static File sTestFile1; 54 private static File sTestFile2; 55 private static String sTestFile1NamePrefix; 56 private static String sTestFile2NamePrefix; 57 private @Spy GenericExecutableCollectorHelper mGenericExecutableCollectorHelper; 58 59 @BeforeClass setUpFiles()60 public static void setUpFiles() throws IOException { 61 sTestFile1 = Files.createTempFile(TEST_FILE_NAME, "1").toFile(); 62 sTestFile2 = Files.createTempFile(TEST_FILE_NAME, "2").toFile(); 63 sTestFile1NamePrefix = sTestFile1.getName() + "_"; 64 sTestFile2NamePrefix = sTestFile2.getName() + "_"; 65 } 66 67 @Before setUp()68 public void setUp() { 69 MockitoAnnotations.initMocks(this); 70 } 71 72 /** Test invalid input directory and throw an IllegalArgumentException */ 73 @Test testBadInputDir()74 public void testBadInputDir() { 75 assertThrows( 76 "Executable directory was not a directory or was not specified.", 77 IllegalArgumentException.class, 78 () -> mGenericExecutableCollectorHelper.setUp(INVALID_INPUT_DIR)); 79 } 80 81 /** Test valid input directory but empty folder and throw an IllegalArgumentException */ 82 @Test testEmptyDir()83 public void testEmptyDir() { 84 assertThrows( 85 String.format("No test file found in the directory %s", VALID_EMPTY_DIR), 86 IllegalArgumentException.class, 87 () -> mGenericExecutableCollectorHelper.setUp(VALID_EMPTY_DIR)); 88 } 89 90 /** Test valid input directory */ 91 @Test testGoodDir()92 public void testGoodDir() throws IOException { 93 mGenericExecutableCollectorHelper.setUp(sTestFile1.getParent()); 94 assertTrue(mGenericExecutableCollectorHelper.startCollecting()); 95 } 96 97 /** Test valid input directory with multiple files */ 98 @Test testMultipleGoodFiles()99 public void testMultipleGoodFiles() throws IOException { 100 String testOutput1 = 101 "name,binder_threads_in_use,binder_threads_started,client_count\n" 102 + "DockObserver,0,32,2\n" 103 + "SurfaceFlinger,0,5,8\n" 104 + "SurfaceFlingerAIDL,0,5,8\n"; 105 String testOutput2 = 106 "name,binder_threads_in_use,binder_threads_started,client_count\n" 107 + "camera.provider/internal/0,0,3,3\n" 108 + "cas.IMediaCasService/default,1,1,2\n" 109 + "confirmationui.IConfirmationUI/default,0,1,2\n"; 110 doReturn(testOutput1) 111 .when(mGenericExecutableCollectorHelper) 112 .executeShellCommand(sTestFile1.getPath()); 113 doReturn(testOutput2) 114 .when(mGenericExecutableCollectorHelper) 115 .executeShellCommand(sTestFile2.getPath()); 116 117 mGenericExecutableCollectorHelper.setUp(sTestFile1.getParent()); 118 assertTrue(mGenericExecutableCollectorHelper.startCollecting()); 119 Map<String, String> metrics = mGenericExecutableCollectorHelper.getMetrics(); 120 121 assertFalse(metrics.isEmpty()); 122 assertTrue( 123 metrics.containsKey(sTestFile1NamePrefix + "DockObserver_binder_threads_in_use")); 124 assertTrue( 125 metrics.containsKey(sTestFile1NamePrefix + "DockObserver_binder_threads_started")); 126 assertTrue(metrics.containsKey(sTestFile1NamePrefix + "DockObserver_client_count")); 127 assertEquals( 128 metrics.get(sTestFile1NamePrefix + "SurfaceFlinger_binder_threads_in_use"), "0"); 129 assertEquals( 130 metrics.get(sTestFile1NamePrefix + "SurfaceFlinger_binder_threads_started"), "5"); 131 assertEquals(metrics.get(sTestFile1NamePrefix + "SurfaceFlinger_client_count"), "8"); 132 133 assertTrue( 134 metrics.containsKey( 135 sTestFile2NamePrefix 136 + "confirmationui.IConfirmationUI/default_binder_threads_in_use")); 137 assertTrue( 138 metrics.containsKey( 139 sTestFile2NamePrefix 140 + "confirmationui.IConfirmationUI/default_binder_threads_started")); 141 assertTrue( 142 metrics.containsKey( 143 sTestFile2NamePrefix 144 + "confirmationui.IConfirmationUI/default_client_count")); 145 assertEquals( 146 metrics.get( 147 sTestFile2NamePrefix + "camera.provider/internal/0_binder_threads_in_use"), 148 "0"); 149 assertEquals( 150 metrics.get( 151 sTestFile2NamePrefix + "camera.provider/internal/0_binder_threads_started"), 152 "3"); 153 assertEquals( 154 metrics.get(sTestFile2NamePrefix + "camera.provider/internal/0_client_count"), "3"); 155 } 156 157 /** 158 * Test valid input directory with multiple files. If there is a bad file, the metrics are still 159 * collected from other good files. 160 */ 161 @Test testBadExectuable_goodExecutableStillCollects()162 public void testBadExectuable_goodExecutableStillCollects() throws IOException { 163 String testOutput2 = 164 "name,binder_threads_in_use,binder_threads_started,client_count\n" 165 + "camera.provider/internal/0,0,3,3\n" 166 + "cas.IMediaCasService/default,1,1,2\n" 167 + "confirmationui.IConfirmationUI/default,0,1,2\n"; 168 doThrow(IOException.class) 169 .when(mGenericExecutableCollectorHelper) 170 .executeShellCommand(sTestFile1.getPath()); 171 doReturn(testOutput2) 172 .when(mGenericExecutableCollectorHelper) 173 .executeShellCommand(sTestFile2.getPath()); 174 175 mGenericExecutableCollectorHelper.setUp(sTestFile1.getParent()); 176 assertTrue(mGenericExecutableCollectorHelper.startCollecting()); 177 Map<String, String> metrics = mGenericExecutableCollectorHelper.getMetrics(); 178 179 assertFalse(metrics.isEmpty()); 180 assertTrue( 181 metrics.containsKey( 182 sTestFile2NamePrefix 183 + "confirmationui.IConfirmationUI/default_binder_threads_in_use")); 184 assertTrue( 185 metrics.containsKey( 186 sTestFile2NamePrefix 187 + "confirmationui.IConfirmationUI/default_binder_threads_started")); 188 assertTrue( 189 metrics.containsKey( 190 sTestFile2NamePrefix 191 + "confirmationui.IConfirmationUI/default_client_count")); 192 assertEquals( 193 metrics.get( 194 sTestFile2NamePrefix + "camera.provider/internal/0_binder_threads_in_use"), 195 "0"); 196 assertEquals( 197 metrics.get( 198 sTestFile2NamePrefix + "camera.provider/internal/0_binder_threads_started"), 199 "3"); 200 assertEquals( 201 metrics.get(sTestFile2NamePrefix + "camera.provider/internal/0_client_count"), "3"); 202 } 203 } 204