mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-28 05:47:38 +00:00
Install and test LSPosed through test app
This commit is contained in:
parent
32faa4ced6
commit
2baedf74d1
@ -65,4 +65,5 @@ dependencies {
|
||||
// However, we don't want to bundle test dependencies.
|
||||
// That's why we make it compileOnly.
|
||||
compileOnly(libs.test.junit)
|
||||
compileOnly(libs.test.uiautomator)
|
||||
}
|
||||
|
@ -0,0 +1,57 @@
|
||||
package com.topjohnwu.magisk.test
|
||||
|
||||
import android.app.UiAutomation
|
||||
import androidx.annotation.Keep
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.uiautomator.By
|
||||
import androidx.test.uiautomator.UiDevice
|
||||
import androidx.test.uiautomator.Until
|
||||
import org.junit.After
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.Assume.assumeTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.regex.Pattern
|
||||
|
||||
@Keep
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class AdditionalTest {
|
||||
|
||||
companion object {
|
||||
private const val SHELL_PKG = "com.android.shell"
|
||||
private const val LSPOSED_CATEGORY = "org.lsposed.manager.LAUNCH_MANAGER"
|
||||
private const val LSPOSED_PKG = "org.lsposed.manager"
|
||||
}
|
||||
|
||||
private lateinit var uiAutomation: UiAutomation
|
||||
private lateinit var device: UiDevice
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
val inst = InstrumentationRegistry.getInstrumentation()
|
||||
uiAutomation = inst.uiAutomation
|
||||
device = UiDevice.getInstance(inst)
|
||||
}
|
||||
|
||||
@After
|
||||
fun teardown() {
|
||||
device.pressHome()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testLaunchLsposedManager() {
|
||||
assumeTrue(Environment.lsposed())
|
||||
|
||||
uiAutomation.executeShellCommand(
|
||||
"am start -c $LSPOSED_CATEGORY $SHELL_PKG/.BugreportWarningActivity"
|
||||
)
|
||||
val pattern = Pattern.compile("$LSPOSED_PKG:id/.*")
|
||||
assertNotNull(
|
||||
"LSPosed manager launch failed",
|
||||
device.wait(Until.hasObject(By.res(pattern)), TimeUnit.SECONDS.toMillis(10))
|
||||
)
|
||||
}
|
||||
}
|
@ -1,17 +1,27 @@
|
||||
package com.topjohnwu.magisk.test
|
||||
|
||||
import android.app.Notification
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import androidx.annotation.Keep
|
||||
import androidx.core.net.toUri
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import com.topjohnwu.magisk.core.BuildConfig.APP_PACKAGE_NAME
|
||||
import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.di.ServiceLocator
|
||||
import com.topjohnwu.magisk.core.download.DownloadNotifier
|
||||
import com.topjohnwu.magisk.core.download.DownloadProcessor
|
||||
import com.topjohnwu.magisk.core.ktx.cachedFile
|
||||
import com.topjohnwu.magisk.core.model.su.SuPolicy
|
||||
import com.topjohnwu.magisk.core.tasks.AppMigration
|
||||
import com.topjohnwu.magisk.core.tasks.FlashZip
|
||||
import com.topjohnwu.magisk.core.tasks.MagiskInstaller
|
||||
import com.topjohnwu.superuser.CallbackList
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Assume.assumeTrue
|
||||
import org.junit.Before
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@ -25,19 +35,55 @@ class Environment {
|
||||
@BeforeClass
|
||||
@JvmStatic
|
||||
fun before() = MagiskAppTest.before()
|
||||
|
||||
fun lsposed(): Boolean {
|
||||
return Build.VERSION.SDK_INT >= 27 && Build.VERSION.SDK_INT <= 34
|
||||
}
|
||||
|
||||
private const val LSPOSED_URL =
|
||||
"https://github.com/LSPosed/LSPosed/releases/download/v1.9.2/LSPosed-v1.9.2-7024-zygisk-release.zip"
|
||||
}
|
||||
|
||||
object TimberLog : CallbackList<String>(Runnable::run) {
|
||||
override fun onAddElement(e: String) {
|
||||
Timber.i(e)
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var mContext: Context
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
mContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setupMagisk() {
|
||||
val log = object : CallbackList<String>(Runnable::run) {
|
||||
override fun onAddElement(e: String) {
|
||||
Timber.i(e)
|
||||
}
|
||||
}
|
||||
runBlocking {
|
||||
assertTrue(
|
||||
"Magisk setup failed",
|
||||
MagiskInstaller.Emulator(log, log).exec()
|
||||
MagiskInstaller.Emulator(TimberLog, TimberLog).exec()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setupLsposed() {
|
||||
assumeTrue(lsposed())
|
||||
|
||||
val notify = object : DownloadNotifier {
|
||||
override val context = mContext
|
||||
override fun notifyUpdate(id: Int, editor: (Notification.Builder) -> Unit) {}
|
||||
}
|
||||
val processor = DownloadProcessor(notify)
|
||||
val zip = mContext.cachedFile("lsposed.zip")
|
||||
runBlocking {
|
||||
ServiceLocator.networkService.fetchFile(LSPOSED_URL).byteStream().use {
|
||||
processor.handleModule(it, zip.toUri())
|
||||
}
|
||||
assertTrue(
|
||||
"LSPosed installation failed",
|
||||
FlashZip(zip.toUri(), TimberLog, TimberLog).exec()
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -65,7 +111,7 @@ class Environment {
|
||||
assertTrue(
|
||||
"App hiding failed",
|
||||
AppMigration.patchAndHide(
|
||||
context = InstrumentationRegistry.getInstrumentation().targetContext,
|
||||
context = mContext,
|
||||
label = "Settings",
|
||||
pkg = "repackaged.$APP_PACKAGE_NAME"
|
||||
)
|
||||
@ -78,9 +124,7 @@ class Environment {
|
||||
runBlocking {
|
||||
assertTrue(
|
||||
"App restoration failed",
|
||||
AppMigration.restoreApp(
|
||||
context = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
)
|
||||
AppMigration.restoreApp(mContext)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -26,4 +26,5 @@ dependencies {
|
||||
implementation(libs.test.runner)
|
||||
implementation(libs.test.rules)
|
||||
implementation(libs.test.junit)
|
||||
implementation(libs.test.uiautomator)
|
||||
}
|
||||
|
@ -6,6 +6,17 @@ import androidx.test.runner.AndroidJUnitRunner
|
||||
|
||||
class TestRunner : AndroidJUnitRunner() {
|
||||
override fun onCreate(arguments: Bundle) {
|
||||
// Support short-hand ".ClassName"
|
||||
arguments.getString("class")?.let {
|
||||
val classArg = it.split(",").joinToString(separator = ",") { clz ->
|
||||
if (clz.startsWith(".")) {
|
||||
"com.topjohnwu.magisk.test$clz"
|
||||
} else {
|
||||
clz
|
||||
}
|
||||
}
|
||||
arguments.putString("class", classArg)
|
||||
}
|
||||
// Force using the target context's classloader to run tests
|
||||
arguments.putString("classLoader", TestClassLoader::class.java.name)
|
||||
super.onCreate(arguments)
|
||||
|
@ -47,6 +47,7 @@ jdk-libs = { module = "com.android.tools:desugar_jdk_libs_nio", version = "2.1.3
|
||||
test-runner = { module = "androidx.test:runner", version = "1.6.2" }
|
||||
test-rules = { module = "androidx.test:rules", version = "1.6.1" }
|
||||
test-junit = { module = "androidx.test.ext:junit", version = "1.2.1" }
|
||||
test-uiautomator = { module = "androidx.test.uiautomator:uiautomator", version = "2.3.0" }
|
||||
|
||||
# topjohnwu
|
||||
indeterminate-checkbox = { module = "com.github.topjohnwu:indeterminate-checkbox", version = "1.0.7" }
|
||||
|
@ -4,13 +4,10 @@ set -xe
|
||||
. scripts/test_common.sh
|
||||
|
||||
emu_args_base="-no-window -no-audio -no-boot-anim -gpu swiftshader_indirect -read-only -no-snapshot -cores $core_count"
|
||||
lsposed_url='https://github.com/LSPosed/LSPosed/releases/download/v1.9.2/LSPosed-v1.9.2-7024-zygisk-release.zip'
|
||||
emu_pid=
|
||||
|
||||
atd_min_api=30
|
||||
atd_max_api=35
|
||||
lsposed_min_api=27
|
||||
lsposed_max_api=34
|
||||
huge_ram_min_api=26
|
||||
|
||||
cleanup() {
|
||||
@ -81,35 +78,10 @@ test_emu() {
|
||||
|
||||
run_setup $variant
|
||||
|
||||
local lsposed
|
||||
if [ $api -ge $lsposed_min_api -a $api -le $lsposed_max_api ]; then
|
||||
lsposed=true
|
||||
else
|
||||
lsposed=false
|
||||
fi
|
||||
|
||||
# Install LSPosed
|
||||
if $lsposed; then
|
||||
adb push out/lsposed.zip /data/local/tmp/lsposed.zip
|
||||
echo 'PATH=$PATH:/debug_ramdisk magisk --install-module /data/local/tmp/lsposed.zip' | adb shell /system/xbin/su
|
||||
fi
|
||||
|
||||
adb reboot
|
||||
wait_emu wait_for_boot
|
||||
|
||||
run_tests
|
||||
|
||||
# Try to launch LSPosed
|
||||
if $lsposed; then
|
||||
adb shell rm -f /data/local/tmp/window_dump.xml
|
||||
adb shell am start -c org.lsposed.manager.LAUNCH_MANAGER com.android.shell/.BugreportWarningActivity
|
||||
while adb shell '[ ! -f /data/local/tmp/window_dump.xml ]'; do
|
||||
sleep 10
|
||||
adb shell uiautomator dump /data/local/tmp/window_dump.xml
|
||||
done
|
||||
adb shell grep -q org.lsposed.manager /data/local/tmp/window_dump.xml
|
||||
adb pull /data/local/tmp/window_dump.xml
|
||||
fi
|
||||
}
|
||||
|
||||
test_main() {
|
||||
@ -220,7 +192,6 @@ if [ -n "$FORCE_32_BIT" ]; then
|
||||
fi
|
||||
|
||||
yes | "$sdk" --licenses > /dev/null
|
||||
curl -L $lsposed_url -o out/lsposed.zip
|
||||
"$sdk" --channel=3 platform-tools emulator
|
||||
|
||||
adb kill-server
|
||||
|
@ -36,8 +36,7 @@ am_instrument() {
|
||||
else
|
||||
test_pkg=com.topjohnwu.magisk.test
|
||||
fi
|
||||
local out=$(adb shell am instrument -w --user 0 \
|
||||
-e class "com.topjohnwu.magisk.test.$1" \
|
||||
local out=$(adb shell am instrument -w --user 0 -e class "$1" \
|
||||
"$test_pkg/com.topjohnwu.magisk.test.TestRunner")
|
||||
grep -q 'OK (' <<< "$out"
|
||||
}
|
||||
@ -59,34 +58,36 @@ run_setup() {
|
||||
adb install -r -g out/test.apk
|
||||
|
||||
# Run setup through the test app
|
||||
am_instrument 'Environment#setupMagisk'
|
||||
am_instrument '.Environment#setupMagisk'
|
||||
# Install LSPosed
|
||||
am_instrument '.Environment#setupLsposed'
|
||||
}
|
||||
|
||||
run_tests() {
|
||||
# Run app tests
|
||||
am_instrument 'MagiskAppTest'
|
||||
am_instrument '.MagiskAppTest,.AdditionalTest'
|
||||
|
||||
# Test shell su request
|
||||
am_instrument 'Environment#setupShellGrantTest'
|
||||
am_instrument '.Environment#setupShellGrantTest'
|
||||
adb shell /system/xbin/su 2000 su -c id | tee /dev/fd/2 | grep -q 'uid=0'
|
||||
adb shell am force-stop com.topjohnwu.magisk
|
||||
|
||||
# Test app hiding
|
||||
am_instrument 'Environment#setupAppHide'
|
||||
am_instrument '.Environment#setupAppHide'
|
||||
wait_for_pm com.topjohnwu.magisk
|
||||
|
||||
# Make sure it still works
|
||||
am_instrument 'MagiskAppTest' true
|
||||
am_instrument '.MagiskAppTest' true
|
||||
|
||||
# Test shell su request
|
||||
am_instrument 'Environment#setupShellGrantTest' true
|
||||
am_instrument '.Environment#setupShellGrantTest' true
|
||||
adb shell /system/xbin/su 2000 su -c id | tee /dev/fd/2 | grep -q 'uid=0'
|
||||
adb shell am force-stop repackaged.com.topjohnwu.magisk
|
||||
|
||||
# Test app restore
|
||||
am_instrument 'Environment#setupAppRestore' true
|
||||
am_instrument '.Environment#setupAppRestore' true
|
||||
wait_for_pm repackaged.com.topjohnwu.magisk
|
||||
|
||||
# Make sure it still works
|
||||
am_instrument 'MagiskAppTest'
|
||||
am_instrument '.MagiskAppTest'
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user