• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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 android.appsecurity.cts;
18 
19 import com.android.tradefed.util.RunUtil;
20 import com.android.ddmlib.AdbCommandRejectedException;
21 import com.android.ddmlib.CollectingOutputReceiver;
22 import com.android.ddmlib.Log;
23 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
24 import com.android.ddmlib.testrunner.TestResult.TestStatus;
25 import com.android.tradefed.device.DeviceNotAvailableException;
26 import com.android.tradefed.device.ITestDevice;
27 import com.android.tradefed.result.CollectingTestListener;
28 import com.android.tradefed.result.TestDescription;
29 import com.android.tradefed.result.TestResult;
30 import com.android.tradefed.result.TestRunResult;
31 
32 import java.util.Arrays;
33 import java.util.Map;
34 import java.util.Objects;
35 import java.util.concurrent.TimeUnit;
36 
37 public class Utils {
38     private static final String LOG_TAG = Utils.class.getSimpleName();
39 
40     public static final int USER_SYSTEM = 0;
41 
runDeviceTestsAsCurrentUser(ITestDevice device, String packageName, String testClassName, String testMethodName)42     public static void runDeviceTestsAsCurrentUser(ITestDevice device, String packageName,
43             String testClassName, String testMethodName) throws DeviceNotAvailableException {
44         runDeviceTests(device, packageName, testClassName, testMethodName, device.getCurrentUser(),
45                 null);
46     }
47 
runDeviceTestsAsCurrentUser(ITestDevice device, String packageName, String testClassName, String testMethodName, Map<String, String> testArgs)48     public static void runDeviceTestsAsCurrentUser(ITestDevice device, String packageName,
49             String testClassName, String testMethodName, Map<String, String> testArgs)
50                     throws DeviceNotAvailableException {
51         runDeviceTests(device, packageName, testClassName, testMethodName, device.getCurrentUser(),
52                 testArgs);
53     }
54 
runDeviceTests(ITestDevice device, String packageName, String testClassName, String testMethodName)55     public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
56             String testMethodName) throws DeviceNotAvailableException {
57         runDeviceTests(device, packageName, testClassName, testMethodName, USER_SYSTEM, null);
58     }
59 
runDeviceTests(ITestDevice device, String packageName, String testClassName, String testMethodName, Map<String, String> testArgs)60     public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
61             String testMethodName, Map<String, String> testArgs)
62                     throws DeviceNotAvailableException {
63         runDeviceTests(device, packageName, testClassName, testMethodName, USER_SYSTEM, testArgs);
64     }
65 
runDeviceTests(ITestDevice device, String packageName, String testClassName, String testMethodName, int userId)66     public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
67             String testMethodName, int userId) throws DeviceNotAvailableException {
68         runDeviceTests(device, packageName, testClassName, testMethodName, userId, null);
69     }
70 
runDeviceTests(ITestDevice device, String packageName, String testClassName, String testMethodName, int userId, Map<String, String> testArgs)71     public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
72             String testMethodName, int userId, Map<String, String> testArgs)
73                     throws DeviceNotAvailableException {
74         // 60 min timeout per test by default
75         runDeviceTests(device, packageName, testClassName, testMethodName, userId, testArgs,
76                 60L, TimeUnit.MINUTES);
77     }
78 
runDeviceTests(ITestDevice device, String packageName, String testClassName, String testMethodName, int userId, Map<String, String> testArgs, long timeout, TimeUnit unit)79     public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
80             String testMethodName, int userId, Map<String, String> testArgs, long timeout,
81             TimeUnit unit)
82                     throws DeviceNotAvailableException {
83         if (testClassName != null && testClassName.startsWith(".")) {
84             testClassName = packageName + testClassName;
85         }
86         RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(packageName,
87                 "androidx.test.runner.AndroidJUnitRunner", device.getIDevice());
88         // timeout_msec is the timeout per test for instrumentation
89         long testTimeoutMs = unit.toMillis(timeout);
90         testRunner.addInstrumentationArg("timeout_msec", Long.toString(testTimeoutMs));
91         // Similar logic as InstrumentationTest to ensure on host-side level that no-hanging can happen
92         long maxTimeToOutputMs = testTimeoutMs + testTimeoutMs / 10;
93         testRunner.setMaxTimeToOutputResponse(maxTimeToOutputMs, TimeUnit.MILLISECONDS);
94 
95         if (testClassName != null && testMethodName != null) {
96             testRunner.setMethodName(testClassName, testMethodName);
97         } else if (testClassName != null) {
98             testRunner.setClassName(testClassName);
99         }
100 
101         if (testArgs != null && testArgs.size() > 0) {
102             for (String name : testArgs.keySet()) {
103                 final String value = testArgs.get(name);
104                 testRunner.addInstrumentationArg(name, value);
105             }
106         }
107         final CollectingTestListener listener = new CollectingTestListener();
108         device.runInstrumentationTestsAsUser(testRunner, userId, listener);
109 
110         final TestRunResult result = listener.getCurrentRunResults();
111         if (result.isRunFailure()) {
112             throw new AssertionError("Failed to successfully run device tests for "
113                     + result.getName() + ": " + result.getRunFailureMessage());
114         }
115         if (result.getNumTests() == 0) {
116             throw new AssertionError("No tests were run on the device");
117         }
118         if (result.hasFailedTests()) {
119             // build a meaningful error message
120             StringBuilder errorBuilder = new StringBuilder("on-device tests failed:\n");
121             for (Map.Entry<TestDescription, TestResult> resultEntry :
122                 result.getTestResults().entrySet()) {
123                 if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
124                     errorBuilder.append(resultEntry.getKey().toString());
125                     errorBuilder.append(":\n");
126                     errorBuilder.append(resultEntry.getValue().getStackTrace());
127                 }
128             }
129             throw new AssertionError(errorBuilder.toString());
130         }
131     }
132 
133     /**
134      * Prepare and return a single user relevant for testing.
135      */
prepareSingleUser(ITestDevice device)136     public static int[] prepareSingleUser(ITestDevice device)
137             throws DeviceNotAvailableException {
138         return prepareMultipleUsers(device, 1);
139     }
140 
141     /**
142      * Prepare and return two users relevant for testing.
143      */
prepareMultipleUsers(ITestDevice device)144     public static int[] prepareMultipleUsers(ITestDevice device)
145             throws DeviceNotAvailableException {
146         return prepareMultipleUsers(device, 2);
147     }
148 
149     /**
150      * Prepare and return multiple users relevant for testing.
151      */
prepareMultipleUsers(ITestDevice device, int maxUsers)152     public static int[] prepareMultipleUsers(ITestDevice device, int maxUsers)
153             throws DeviceNotAvailableException {
154         final int[] userIds = getAllUsers(device);
155         int currentUserId = device.getCurrentUser();
156         for (int i = 1; i < userIds.length; i++) {
157             if (i < maxUsers) {
158                 device.startUser(userIds[i], true);
159             } else if (userIds[i] != currentUserId) {
160                 device.stopUser(userIds[i], true, true);
161             }
162         }
163         if (userIds.length > maxUsers) {
164             return Arrays.copyOf(userIds, maxUsers);
165         } else {
166             return userIds;
167         }
168     }
169 
getAllUsers(ITestDevice device)170     public static int[] getAllUsers(ITestDevice device)
171             throws DeviceNotAvailableException {
172         Integer primary = device.getPrimaryUserId();
173         if (primary == null) {
174             primary = USER_SYSTEM;
175         }
176         int[] users = new int[] { primary };
177         for (Integer user : device.listUsers()) {
178             if ((user != USER_SYSTEM) && !Objects.equals(user, primary)) {
179                 users = Arrays.copyOf(users, users.length + 1);
180                 users[users.length - 1] = user;
181             }
182         }
183         return users;
184     }
185 
waitForBootCompleted(ITestDevice device)186     public static void waitForBootCompleted(ITestDevice device) throws Exception {
187         for (int i = 0; i < 45; i++) {
188             if (isBootCompleted(device)) {
189                 Log.d(LOG_TAG, "Yay, system is ready!");
190                 // or is it really ready?
191                 // guard against potential USB mode switch weirdness at boot
192                 RunUtil.getDefault().sleep(10 * 1000);
193                 return;
194             }
195             Log.d(LOG_TAG, "Waiting for system ready...");
196             RunUtil.getDefault().sleep(1000);
197         }
198         throw new AssertionError("System failed to become ready!");
199     }
200 
isBootCompleted(ITestDevice device)201     private static boolean isBootCompleted(ITestDevice device) throws Exception {
202         CollectingOutputReceiver receiver = new CollectingOutputReceiver();
203         try {
204             device.getIDevice().executeShellCommand("getprop sys.boot_completed", receiver);
205         } catch (AdbCommandRejectedException e) {
206             // do nothing: device might be temporarily disconnected
207             Log.d(LOG_TAG, "Ignored AdbCommandRejectedException while `getprop sys.boot_completed`");
208         }
209         String output = receiver.getOutput();
210         if (output != null) {
211             output = output.trim();
212         }
213         return "1".equals(output);
214     }
215 
216 }
217