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