mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-04-29 22:14:27 +02:00
Drive app migration tests through instrumentation
Make tests less flaky
This commit is contained in:
parent
08ea937f7c
commit
9e2b59060d
@ -2,13 +2,22 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission
|
||||
android:name="android.permission.QUERY_ALL_PACKAGES"
|
||||
tools:ignore="QueryAllPackagesPermission" />
|
||||
|
||||
<queries tools:node="removeAll" />
|
||||
|
||||
<application tools:node="replace">
|
||||
<uses-library android:name="android.test.runner" />
|
||||
</application>
|
||||
|
||||
<instrumentation
|
||||
android:name="com.topjohnwu.magisk.test.AppTestRunner"
|
||||
android:targetPackage="com.topjohnwu.magisk" />
|
||||
|
||||
<instrumentation
|
||||
android:name="com.topjohnwu.magisk.test.TestRunner"
|
||||
android:targetPackage="com.topjohnwu.magisk"
|
||||
android:label="Tests for Magisk" />
|
||||
android:targetPackage="com.topjohnwu.magisk.test" />
|
||||
|
||||
</manifest>
|
||||
|
@ -0,0 +1,88 @@
|
||||
package com.topjohnwu.magisk.test
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.os.ParcelFileDescriptor.AutoCloseInputStream
|
||||
import androidx.annotation.Keep
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import org.junit.After
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@Keep
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class AppMigrationTest {
|
||||
|
||||
companion object {
|
||||
private const val APP_PKG = "com.topjohnwu.magisk"
|
||||
private const val STUB_PKG = "repackaged.$APP_PKG"
|
||||
private const val RECEIVER_TIMEOUT = 20L
|
||||
}
|
||||
|
||||
private val instrumentation get() = InstrumentationRegistry.getInstrumentation()
|
||||
private val context get() = instrumentation.context
|
||||
private val uiAutomation get() = instrumentation.uiAutomation
|
||||
private val registeredReceivers = mutableListOf<BroadcastReceiver>()
|
||||
|
||||
class PackageRemoveMonitor(
|
||||
context: Context,
|
||||
private val packageName: String
|
||||
) : BroadcastReceiver() {
|
||||
|
||||
val latch = CountDownLatch(1)
|
||||
|
||||
init {
|
||||
val filter = IntentFilter(Intent.ACTION_PACKAGE_REMOVED)
|
||||
filter.addDataScheme("package")
|
||||
context.registerReceiver(this, filter)
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
if (intent.action != Intent.ACTION_PACKAGE_REMOVED)
|
||||
return
|
||||
val data = intent.data ?: return
|
||||
val pkg = data.schemeSpecificPart
|
||||
if (pkg == packageName) latch.countDown()
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
registeredReceivers.forEach(context::unregisterReceiver)
|
||||
}
|
||||
|
||||
private fun testAppMigration(pkg: String, method: String) {
|
||||
val receiver = PackageRemoveMonitor(context, pkg)
|
||||
registeredReceivers.add(receiver)
|
||||
|
||||
// Trigger the test to run migration
|
||||
val pfd = uiAutomation.executeShellCommand(
|
||||
"am instrument -w --user 0 -e class .Environment#$method " +
|
||||
"$pkg.test/${AppTestRunner::class.java.name}"
|
||||
)
|
||||
val output = AutoCloseInputStream(pfd).reader().use { it.readText() }
|
||||
assertTrue("$method failed, inst out: $output", output.contains("OK ("))
|
||||
|
||||
// Wait for migration to complete
|
||||
assertTrue(
|
||||
"$pkg uninstallation failed",
|
||||
receiver.latch.await(RECEIVER_TIMEOUT, TimeUnit.SECONDS)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAppHide() {
|
||||
testAppMigration(APP_PKG, "setupAppHide")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAppRestore() {
|
||||
testAppMigration(STUB_PKG, "setupAppRestore")
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ import android.os.Bundle
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.runner.AndroidJUnitRunner
|
||||
|
||||
class TestRunner : AndroidJUnitRunner() {
|
||||
open class TestRunner : AndroidJUnitRunner() {
|
||||
override fun onCreate(arguments: Bundle) {
|
||||
// Support short-hand ".ClassName"
|
||||
arguments.getString("class")?.let {
|
||||
@ -17,6 +17,12 @@ class TestRunner : AndroidJUnitRunner() {
|
||||
}
|
||||
arguments.putString("class", classArg)
|
||||
}
|
||||
super.onCreate(arguments)
|
||||
}
|
||||
}
|
||||
|
||||
class AppTestRunner : TestRunner() {
|
||||
override fun onCreate(arguments: Bundle) {
|
||||
// Force using the target context's classloader to run tests
|
||||
arguments.putString("classLoader", TestClassLoader::class.java.name)
|
||||
super.onCreate(arguments)
|
@ -28,16 +28,9 @@ print_error() {
|
||||
}
|
||||
|
||||
# $1 = TestClass#method
|
||||
# $2: boolean = isRepackaged
|
||||
# $2 = component
|
||||
am_instrument() {
|
||||
local test_pkg
|
||||
if [ -n "$2" -a "$2" ]; then
|
||||
test_pkg="repackaged.com.topjohnwu.magisk.test"
|
||||
else
|
||||
test_pkg=com.topjohnwu.magisk.test
|
||||
fi
|
||||
local out=$(adb shell am instrument -w --user 0 -e class "$1" \
|
||||
"$test_pkg/com.topjohnwu.magisk.test.TestRunner")
|
||||
local out=$(adb shell am instrument -w --user 0 -e class "$1" "$2")
|
||||
grep -q 'OK (' <<< "$out"
|
||||
}
|
||||
|
||||
@ -57,27 +50,31 @@ run_setup() {
|
||||
# Install the test app
|
||||
adb install -r -g out/test.apk
|
||||
|
||||
local app='com.topjohnwu.magisk.test/com.topjohnwu.magisk.test.AppTestRunner'
|
||||
|
||||
# Run setup through the test app
|
||||
am_instrument '.Environment#setupMagisk'
|
||||
am_instrument '.Environment#setupMagisk' $app
|
||||
# Install LSPosed
|
||||
am_instrument '.Environment#setupLsposed'
|
||||
am_instrument '.Environment#setupLsposed' $app
|
||||
}
|
||||
|
||||
run_tests() {
|
||||
local self='com.topjohnwu.magisk.test/com.topjohnwu.magisk.test.TestRunner'
|
||||
local app='com.topjohnwu.magisk.test/com.topjohnwu.magisk.test.AppTestRunner'
|
||||
local stub='repackaged.com.topjohnwu.magisk.test/com.topjohnwu.magisk.test.AppTestRunner'
|
||||
|
||||
# Run app tests
|
||||
am_instrument '.MagiskAppTest,.AdditionalTest'
|
||||
am_instrument '.MagiskAppTest,.AdditionalTest' $app
|
||||
|
||||
# Test app hiding
|
||||
am_instrument '.Environment#setupAppHide'
|
||||
wait_for_pm com.topjohnwu.magisk
|
||||
am_instrument '.AppMigrationTest#testAppHide' $self
|
||||
|
||||
# Make sure it still works
|
||||
am_instrument '.MagiskAppTest' true
|
||||
am_instrument '.MagiskAppTest' $stub
|
||||
|
||||
# Test app restore
|
||||
am_instrument '.Environment#setupAppRestore' true
|
||||
wait_for_pm repackaged.com.topjohnwu.magisk
|
||||
am_instrument '.AppMigrationTest#testAppRestore' $self
|
||||
|
||||
# Make sure it still works
|
||||
am_instrument '.MagiskAppTest'
|
||||
am_instrument '.MagiskAppTest' $app
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user