blob: 3fc74aa1a468010910468cab42679ad623f68e42 [file] [log] [blame]
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.testutils
import com.android.ddmlib.testrunner.TestResult
import com.android.tradefed.config.Option
import com.android.tradefed.invoker.TestInformation
import com.android.tradefed.result.CollectingTestListener
import com.android.tradefed.result.ddmlib.DefaultRemoteAndroidTestRunner
import com.android.tradefed.targetprep.BaseTargetPreparer
import com.android.tradefed.targetprep.TargetSetupError
import com.android.tradefed.targetprep.suite.SuiteApkInstaller
private const val CONNECTIVITY_CHECKER_APK = "ConnectivityTestPreparer.apk"
private const val CONNECTIVITY_PKG_NAME = "com.android.testutils.connectivitypreparer"
private const val CONNECTIVITY_CHECK_CLASS = "$CONNECTIVITY_PKG_NAME.ConnectivityCheckTest"
// As per the <instrumentation> defined in the checker manifest
private const val CONNECTIVITY_CHECK_RUNNER_NAME = "androidx.test.runner.AndroidJUnitRunner"
private const val IGNORE_CONN_CHECK_OPTION = "ignore-connectivity-check"
/**
* A target preparer that sets up and verifies a device for connectivity tests.
*
* For quick and dirty local testing, the connectivity check can be disabled by running tests with
* "atest -- \
* --test-arg com.android.testutils.ConnectivityTestTargetPreparer:ignore-connectivity-check:true".
*/
open class ConnectivityTestTargetPreparer : BaseTargetPreparer() {
private val installer = SuiteApkInstaller()
@Option(name = IGNORE_CONN_CHECK_OPTION,
description = "Disables the check for mobile data and wifi")
private var ignoreConnectivityCheck = false
override fun setUp(testInformation: TestInformation) {
if (isDisabled) return
disableGmsUpdate(testInformation)
runPreparerApk(testInformation)
}
private fun runPreparerApk(testInformation: TestInformation) {
installer.setCleanApk(true)
installer.addTestFileName(CONNECTIVITY_CHECKER_APK)
installer.setShouldGrantPermission(true)
installer.setUp(testInformation)
val runner = DefaultRemoteAndroidTestRunner(
CONNECTIVITY_PKG_NAME,
CONNECTIVITY_CHECK_RUNNER_NAME,
testInformation.device.iDevice)
runner.runOptions = "--no-hidden-api-checks"
val receiver = CollectingTestListener()
if (!testInformation.device.runInstrumentationTests(runner, receiver)) {
throw TargetSetupError("Device state check failed to complete",
testInformation.device.deviceDescriptor)
}
val runResult = receiver.currentRunResults
if (runResult.isRunFailure) {
throw TargetSetupError("Failed to check device state before the test: " +
runResult.runFailureMessage, testInformation.device.deviceDescriptor)
}
val ignoredTestClasses = mutableSetOf<String>()
if (ignoreConnectivityCheck) {
ignoredTestClasses.add(CONNECTIVITY_CHECK_CLASS)
}
val errorMsg = runResult.testResults.mapNotNull { (testDescription, testResult) ->
if (TestResult.TestStatus.FAILURE != testResult.status ||
ignoredTestClasses.contains(testDescription.className)) {
null
} else {
"$testDescription: ${testResult.stackTrace}"
}
}.joinToString("\n")
if (errorMsg.isBlank()) return
throw TargetSetupError("Device setup checks failed. Check the test bench: \n$errorMsg",
testInformation.device.deviceDescriptor)
}
private fun disableGmsUpdate(testInformation: TestInformation) {
// This will be a no-op on devices without root (su) or not using gservices, but that's OK.
testInformation.device.executeShellCommand("su 0 am broadcast " +
"-a com.google.gservices.intent.action.GSERVICES_OVERRIDE " +
"-e finsky.play_services_auto_update_enabled false")
}
private fun clearGmsUpdateOverride(testInformation: TestInformation) {
testInformation.device.executeShellCommand("su 0 am broadcast " +
"-a com.google.gservices.intent.action.GSERVICES_OVERRIDE " +
"--esn finsky.play_services_auto_update_enabled")
}
override fun tearDown(testInformation: TestInformation, e: Throwable?) {
if (isTearDownDisabled) return
installer.tearDown(testInformation, e)
clearGmsUpdateOverride(testInformation)
}
}