Make ConnectivityCheckTargetPreparer more generic

Rename ConnectivityCheckTargetPreparer to
ConnectivityTestTargetPreparer, and the ConnectivityChecker app to
ConnectivityTestPreparer, and remove the assumption that the app only
does connectivity checks.

This will allow overriding the app with versions that have more specific
setup steps in downstream branches.

Bug: 263665773
Bug: 267413275
Test: tests using this preparer
Merged-In: Icb9b1eb8eb1c75f89cb751e0ca696ea96359e6d0
Change-Id: Icb9b1eb8eb1c75f89cb751e0ca696ea96359e6d0
This commit is contained in:
Remi NGUYEN VAN 2023-04-25 15:49:10 +09:00
commit e2b5213774
5 changed files with 38 additions and 20 deletions

View file

@ -83,5 +83,5 @@ java_test_host {
],
libs: ["tradefed"],
test_suites: ["ats", "device-tests", "general-tests", "cts", "mts-networking"],
data: [":ConnectivityChecker"],
data: [":ConnectivityTestPreparer"],
}

View file

@ -17,7 +17,7 @@ package {
}
android_test_helper_app {
name: "ConnectivityChecker",
name: "ConnectivityTestPreparer",
srcs: ["src/**/*.kt"],
sdk_version: "system_current",
// Allow running the test on any device with SDK Q+, even when built from a branch that uses

View file

@ -15,7 +15,7 @@
~ limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.testutils.connectivitychecker">
package="com.android.testutils.connectivitypreparer">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
@ -27,6 +27,6 @@
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.testutils.connectivitychecker"
android:label="Connectivity checker target preparer" />
android:targetPackage="com.android.testutils.connectivitypreparer"
android:label="Connectivity test target preparer" />
</manifest>

View file

@ -0,0 +1,88 @@
/*
* 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.connectivitypreparer
import android.content.pm.PackageManager.FEATURE_TELEPHONY
import android.content.pm.PackageManager.FEATURE_WIFI
import android.net.ConnectivityManager
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
import android.net.NetworkRequest
import android.telephony.TelephonyManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.android.testutils.ConnectUtil
import com.android.testutils.RecorderCallback
import com.android.testutils.TestableNetworkCallback
import com.android.testutils.tryTest
import kotlin.test.assertTrue
import kotlin.test.fail
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class ConnectivityCheckTest {
val context by lazy { InstrumentationRegistry.getInstrumentation().context }
val pm by lazy { context.packageManager }
@Test
fun testCheckConnectivity() {
checkWifiSetup()
checkTelephonySetup()
}
private fun checkWifiSetup() {
if (!pm.hasSystemFeature(FEATURE_WIFI)) return
ConnectUtil(context).ensureWifiConnected()
}
private fun checkTelephonySetup() {
if (!pm.hasSystemFeature(FEATURE_TELEPHONY)) return
val tm = context.getSystemService(TelephonyManager::class.java)
?: fail("Could not get telephony service")
val commonError = "Check the test bench. To run the tests anyway for quick & dirty local " +
"testing, you can use atest X -- " +
"--test-arg com.android.testutils.ConnectivityTestTargetPreparer" +
":ignore-connectivity-check:true"
// Do not use assertEquals: it outputs "expected X, was Y", which looks like a test failure
if (tm.simState == TelephonyManager.SIM_STATE_ABSENT) {
fail("The device has no SIM card inserted. $commonError")
} else if (tm.simState != TelephonyManager.SIM_STATE_READY) {
fail("The device is not setup with a usable SIM card. Sim state was ${tm.simState}. " +
commonError)
}
assertTrue(tm.isDataConnectivityPossible,
"The device is not setup with a SIM card that supports data connectivity. " +
commonError)
val cb = TestableNetworkCallback()
val cm = context.getSystemService(ConnectivityManager::class.java)
?: fail("Could not get ConnectivityManager")
cm.registerNetworkCallback(
NetworkRequest.Builder()
.addTransportType(TRANSPORT_CELLULAR)
.addCapability(NET_CAPABILITY_INTERNET).build(), cb)
tryTest {
cb.poll { it is RecorderCallback.CallbackEntry.Available }
?: fail("The device does not have mobile data available. Check that it is " +
"setup with a SIM card that has a working data plan, and that the " +
"APN configuration is valid.")
} cleanup {
cm.unregisterNetworkCallback(cb)
}
}
}

View file

@ -0,0 +1,97 @@
/*
* 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
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)
}
override fun tearDown(testInformation: TestInformation?, e: Throwable?) {
if (isTearDownDisabled) return
installer.tearDown(testInformation, e)
}
}