• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 package android.media.cts;
17 
18 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
19 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
20 import com.android.tradefed.build.IBuildInfo;
21 import com.android.tradefed.device.DeviceNotAvailableException;
22 import com.android.tradefed.log.LogUtil;
23 import com.android.tradefed.result.CollectingTestListener;
24 import com.android.tradefed.result.TestDescription;
25 import com.android.tradefed.result.TestResult;
26 import com.android.tradefed.result.TestRunResult;
27 import com.android.tradefed.testtype.DeviceTestCase;
28 import com.android.tradefed.testtype.IBuildReceiver;
29 
30 import java.io.FileNotFoundException;
31 import java.util.Map;
32 import java.util.concurrent.TimeUnit;
33 
34 import javax.annotation.Nonnull;
35 import javax.annotation.Nullable;
36 
37 /** Base class for host-side tests for media APIs. */
38 public class BaseMediaHostSideTest extends DeviceTestCase implements IBuildReceiver {
39     private static final String RUNNER = "androidx.test.runner.AndroidJUnitRunner";
40 
41     /**
42      * The defined timeout (in milliseconds) is used as a maximum waiting time when expecting the
43      * command output from the device. At any time, if the shell command does not output anything
44      * for a period longer than the defined timeout the Tradefed run terminates.
45      */
46     private static final long DEFAULT_SHELL_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(5);
47 
48     /** Instrumentation test runner argument key used for individual test timeout. */
49     protected static final String TEST_TIMEOUT_INST_ARGS_KEY = "timeout_msec";
50 
51     /**
52      * Sets timeout (in milliseconds) that will be applied to each test. In the event of a test
53      * timeout it will log the results and proceed with executing the next test.
54      */
55     private static final long DEFAULT_TEST_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(5);
56 
57     protected IBuildInfo mCtsBuild;
58 
59     @Override
setBuild(IBuildInfo buildInfo)60     public void setBuild(IBuildInfo buildInfo) {
61         mCtsBuild = buildInfo;
62     }
63 
64     /**
65      * Runs tests on the device.
66      *
67      * @param pkgName The test package file name that contains the test.
68      * @param testClassName The class name to test within the test package. If {@code null}, runs
69      *     all test classes in the package.
70      * @param testMethodName Method name to test within the test class. Ignored if {@code
71      *     testClassName} is {@code null}. If {@code null}, runs all test classes in the class.
72      */
runDeviceTests( String pkgName, @Nullable String testClassName, @Nullable String testMethodName)73     protected void runDeviceTests(
74             String pkgName, @Nullable String testClassName, @Nullable String testMethodName)
75             throws DeviceNotAvailableException {
76         RemoteAndroidTestRunner testRunner = getTestRunner(pkgName, testClassName, testMethodName);
77         CollectingTestListener listener = new CollectingTestListener();
78         assertTrue(getDevice().runInstrumentationTests(testRunner, listener));
79         assertTestsPassed(listener.getCurrentRunResults());
80     }
81 
82     /**
83      * Excutes shell command and returns the result.
84      *
85      * @param command The command to run.
86      * @return The result from the command. If the result was {@code null}, empty string ("") will
87      *     be returned instead. Otherwise, trimmed result will be returned.
88      */
executeShellCommand(String command)89     protected @Nonnull String executeShellCommand(String command) throws Exception {
90         LogUtil.CLog.d("Starting command " + command);
91         String commandOutput = getDevice().executeShellCommand(command);
92         LogUtil.CLog.d("Output for command " + command + ": " + commandOutput);
93         return commandOutput != null ? commandOutput.trim() : "";
94     }
95 
96     /** Installs the app with the given {@code appFileName}. */
installApp(String appFileName)97     protected void installApp(String appFileName)
98             throws FileNotFoundException, DeviceNotAvailableException {
99         LogUtil.CLog.d("Installing app " + appFileName);
100         CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
101         String result =
102                 getDevice()
103                         .installPackage(
104                                 buildHelper.getTestFile(appFileName),
105                                 /* reinstall= */ true,
106                                 /* grantPermissions= */ true,
107                                 "-t"); // Signals that this is a test APK.
108         assertNull("Failed to install " + appFileName + ": " + result, result);
109     }
110 
111     /** Returns a {@link RemoteAndroidTestRunner} for the given test parameters. */
getTestRunner( String pkgName, String testClassName, String testMethodName)112     protected RemoteAndroidTestRunner getTestRunner(
113             String pkgName, String testClassName, String testMethodName) {
114         if (testClassName != null && testClassName.startsWith(".")) {
115             testClassName = pkgName + testClassName;
116         }
117 
118         RemoteAndroidTestRunner testRunner =
119                 new RemoteAndroidTestRunner(pkgName, RUNNER, getDevice().getIDevice());
120         testRunner.setMaxTimeToOutputResponse(DEFAULT_SHELL_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
121         testRunner.addInstrumentationArg(
122                 TEST_TIMEOUT_INST_ARGS_KEY, Long.toString(DEFAULT_TEST_TIMEOUT_MILLIS));
123         if (testClassName != null && testMethodName != null) {
124             testRunner.setMethodName(testClassName, testMethodName);
125         } else if (testClassName != null) {
126             testRunner.setClassName(testClassName);
127         }
128         return testRunner;
129     }
130 
131     /**
132      * Asserts that {@code testRunResult} contains at least one test, and that all tests passed.
133      *
134      * <p>If the assertion fails, an {@link AssertionError} with a descriptive message is thrown.
135      */
assertTestsPassed(TestRunResult testRunResult)136     protected void assertTestsPassed(TestRunResult testRunResult) {
137         if (testRunResult.isRunFailure()) {
138             throw new AssertionError(
139                     "Failed to successfully run device tests for "
140                             + testRunResult.getName()
141                             + ": "
142                             + testRunResult.getRunFailureMessage());
143         }
144         if (testRunResult.getNumTests() == 0) {
145             throw new AssertionError("No tests were run on the device");
146         }
147 
148         if (testRunResult.hasFailedTests()) {
149             // Build a meaningful error message
150             StringBuilder errorBuilder = new StringBuilder("On-device tests failed:\n");
151             for (Map.Entry<TestDescription, TestResult> resultEntry :
152                     testRunResult.getTestResults().entrySet()) {
153                 if (!resultEntry
154                         .getValue()
155                         .getStatus()
156                         .equals(com.android.ddmlib.testrunner.TestResult.TestStatus.PASSED)) {
157                     errorBuilder.append(resultEntry.getKey().toString());
158                     errorBuilder.append(":\n");
159                     errorBuilder.append(resultEntry.getValue().getStackTrace());
160                 }
161             }
162             throw new AssertionError(errorBuilder.toString());
163         }
164     }
165 }
166