Install and test LSPosed through test app

This commit is contained in:
topjohnwu
2024-12-24 17:11:08 -08:00
committed by John Wu
parent 32faa4ced6
commit 2baedf74d1
8 changed files with 136 additions and 49 deletions

View File

@@ -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)
}

View File

@@ -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))
)
}
}

View File

@@ -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)
)
}
}