mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-29 13:07:39 +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.
|
// However, we don't want to bundle test dependencies.
|
||||||
// That's why we make it compileOnly.
|
// That's why we make it compileOnly.
|
||||||
compileOnly(libs.test.junit)
|
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
|
package com.topjohnwu.magisk.test
|
||||||
|
|
||||||
|
import android.app.Notification
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
import androidx.annotation.Keep
|
import androidx.annotation.Keep
|
||||||
|
import androidx.core.net.toUri
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
import com.topjohnwu.magisk.core.BuildConfig.APP_PACKAGE_NAME
|
import com.topjohnwu.magisk.core.BuildConfig.APP_PACKAGE_NAME
|
||||||
import com.topjohnwu.magisk.core.Config
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.core.di.ServiceLocator
|
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.model.su.SuPolicy
|
||||||
import com.topjohnwu.magisk.core.tasks.AppMigration
|
import com.topjohnwu.magisk.core.tasks.AppMigration
|
||||||
|
import com.topjohnwu.magisk.core.tasks.FlashZip
|
||||||
import com.topjohnwu.magisk.core.tasks.MagiskInstaller
|
import com.topjohnwu.magisk.core.tasks.MagiskInstaller
|
||||||
import com.topjohnwu.superuser.CallbackList
|
import com.topjohnwu.superuser.CallbackList
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.junit.Assert.assertTrue
|
import org.junit.Assert.assertTrue
|
||||||
|
import org.junit.Assume.assumeTrue
|
||||||
|
import org.junit.Before
|
||||||
import org.junit.BeforeClass
|
import org.junit.BeforeClass
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
@ -25,19 +35,55 @@ class Environment {
|
|||||||
@BeforeClass
|
@BeforeClass
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun before() = MagiskAppTest.before()
|
fun before() = MagiskAppTest.before()
|
||||||
|
|
||||||
|
fun lsposed(): Boolean {
|
||||||
|
return Build.VERSION.SDK_INT >= 27 && Build.VERSION.SDK_INT <= 34
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
private const val LSPOSED_URL =
|
||||||
fun setupMagisk() {
|
"https://github.com/LSPosed/LSPosed/releases/download/v1.9.2/LSPosed-v1.9.2-7024-zygisk-release.zip"
|
||||||
val log = object : CallbackList<String>(Runnable::run) {
|
}
|
||||||
|
|
||||||
|
object TimberLog : CallbackList<String>(Runnable::run) {
|
||||||
override fun onAddElement(e: String) {
|
override fun onAddElement(e: String) {
|
||||||
Timber.i(e)
|
Timber.i(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private lateinit var mContext: Context
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
mContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun setupMagisk() {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
assertTrue(
|
assertTrue(
|
||||||
"Magisk setup failed",
|
"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(
|
assertTrue(
|
||||||
"App hiding failed",
|
"App hiding failed",
|
||||||
AppMigration.patchAndHide(
|
AppMigration.patchAndHide(
|
||||||
context = InstrumentationRegistry.getInstrumentation().targetContext,
|
context = mContext,
|
||||||
label = "Settings",
|
label = "Settings",
|
||||||
pkg = "repackaged.$APP_PACKAGE_NAME"
|
pkg = "repackaged.$APP_PACKAGE_NAME"
|
||||||
)
|
)
|
||||||
@ -78,9 +124,7 @@ class Environment {
|
|||||||
runBlocking {
|
runBlocking {
|
||||||
assertTrue(
|
assertTrue(
|
||||||
"App restoration failed",
|
"App restoration failed",
|
||||||
AppMigration.restoreApp(
|
AppMigration.restoreApp(mContext)
|
||||||
context = InstrumentationRegistry.getInstrumentation().targetContext
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,4 +26,5 @@ dependencies {
|
|||||||
implementation(libs.test.runner)
|
implementation(libs.test.runner)
|
||||||
implementation(libs.test.rules)
|
implementation(libs.test.rules)
|
||||||
implementation(libs.test.junit)
|
implementation(libs.test.junit)
|
||||||
|
implementation(libs.test.uiautomator)
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,17 @@ import androidx.test.runner.AndroidJUnitRunner
|
|||||||
|
|
||||||
class TestRunner : AndroidJUnitRunner() {
|
class TestRunner : AndroidJUnitRunner() {
|
||||||
override fun onCreate(arguments: Bundle) {
|
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
|
// Force using the target context's classloader to run tests
|
||||||
arguments.putString("classLoader", TestClassLoader::class.java.name)
|
arguments.putString("classLoader", TestClassLoader::class.java.name)
|
||||||
super.onCreate(arguments)
|
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-runner = { module = "androidx.test:runner", version = "1.6.2" }
|
||||||
test-rules = { module = "androidx.test:rules", version = "1.6.1" }
|
test-rules = { module = "androidx.test:rules", version = "1.6.1" }
|
||||||
test-junit = { module = "androidx.test.ext:junit", version = "1.2.1" }
|
test-junit = { module = "androidx.test.ext:junit", version = "1.2.1" }
|
||||||
|
test-uiautomator = { module = "androidx.test.uiautomator:uiautomator", version = "2.3.0" }
|
||||||
|
|
||||||
# topjohnwu
|
# topjohnwu
|
||||||
indeterminate-checkbox = { module = "com.github.topjohnwu:indeterminate-checkbox", version = "1.0.7" }
|
indeterminate-checkbox = { module = "com.github.topjohnwu:indeterminate-checkbox", version = "1.0.7" }
|
||||||
|
@ -4,13 +4,10 @@ set -xe
|
|||||||
. scripts/test_common.sh
|
. scripts/test_common.sh
|
||||||
|
|
||||||
emu_args_base="-no-window -no-audio -no-boot-anim -gpu swiftshader_indirect -read-only -no-snapshot -cores $core_count"
|
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=
|
emu_pid=
|
||||||
|
|
||||||
atd_min_api=30
|
atd_min_api=30
|
||||||
atd_max_api=35
|
atd_max_api=35
|
||||||
lsposed_min_api=27
|
|
||||||
lsposed_max_api=34
|
|
||||||
huge_ram_min_api=26
|
huge_ram_min_api=26
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
@ -81,35 +78,10 @@ test_emu() {
|
|||||||
|
|
||||||
run_setup $variant
|
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
|
adb reboot
|
||||||
wait_emu wait_for_boot
|
wait_emu wait_for_boot
|
||||||
|
|
||||||
run_tests
|
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() {
|
test_main() {
|
||||||
@ -220,7 +192,6 @@ if [ -n "$FORCE_32_BIT" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
yes | "$sdk" --licenses > /dev/null
|
yes | "$sdk" --licenses > /dev/null
|
||||||
curl -L $lsposed_url -o out/lsposed.zip
|
|
||||||
"$sdk" --channel=3 platform-tools emulator
|
"$sdk" --channel=3 platform-tools emulator
|
||||||
|
|
||||||
adb kill-server
|
adb kill-server
|
||||||
|
@ -36,8 +36,7 @@ am_instrument() {
|
|||||||
else
|
else
|
||||||
test_pkg=com.topjohnwu.magisk.test
|
test_pkg=com.topjohnwu.magisk.test
|
||||||
fi
|
fi
|
||||||
local out=$(adb shell am instrument -w --user 0 \
|
local out=$(adb shell am instrument -w --user 0 -e class "$1" \
|
||||||
-e class "com.topjohnwu.magisk.test.$1" \
|
|
||||||
"$test_pkg/com.topjohnwu.magisk.test.TestRunner")
|
"$test_pkg/com.topjohnwu.magisk.test.TestRunner")
|
||||||
grep -q 'OK (' <<< "$out"
|
grep -q 'OK (' <<< "$out"
|
||||||
}
|
}
|
||||||
@ -59,34 +58,36 @@ run_setup() {
|
|||||||
adb install -r -g out/test.apk
|
adb install -r -g out/test.apk
|
||||||
|
|
||||||
# Run setup through the test app
|
# Run setup through the test app
|
||||||
am_instrument 'Environment#setupMagisk'
|
am_instrument '.Environment#setupMagisk'
|
||||||
|
# Install LSPosed
|
||||||
|
am_instrument '.Environment#setupLsposed'
|
||||||
}
|
}
|
||||||
|
|
||||||
run_tests() {
|
run_tests() {
|
||||||
# Run app tests
|
# Run app tests
|
||||||
am_instrument 'MagiskAppTest'
|
am_instrument '.MagiskAppTest,.AdditionalTest'
|
||||||
|
|
||||||
# Test shell su request
|
# 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 /system/xbin/su 2000 su -c id | tee /dev/fd/2 | grep -q 'uid=0'
|
||||||
adb shell am force-stop com.topjohnwu.magisk
|
adb shell am force-stop com.topjohnwu.magisk
|
||||||
|
|
||||||
# Test app hiding
|
# Test app hiding
|
||||||
am_instrument 'Environment#setupAppHide'
|
am_instrument '.Environment#setupAppHide'
|
||||||
wait_for_pm com.topjohnwu.magisk
|
wait_for_pm com.topjohnwu.magisk
|
||||||
|
|
||||||
# Make sure it still works
|
# Make sure it still works
|
||||||
am_instrument 'MagiskAppTest' true
|
am_instrument '.MagiskAppTest' true
|
||||||
|
|
||||||
# Test shell su request
|
# 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 /system/xbin/su 2000 su -c id | tee /dev/fd/2 | grep -q 'uid=0'
|
||||||
adb shell am force-stop repackaged.com.topjohnwu.magisk
|
adb shell am force-stop repackaged.com.topjohnwu.magisk
|
||||||
|
|
||||||
# Test app restore
|
# Test app restore
|
||||||
am_instrument 'Environment#setupAppRestore' true
|
am_instrument '.Environment#setupAppRestore' true
|
||||||
wait_for_pm repackaged.com.topjohnwu.magisk
|
wait_for_pm repackaged.com.topjohnwu.magisk
|
||||||
|
|
||||||
# Make sure it still works
|
# Make sure it still works
|
||||||
am_instrument 'MagiskAppTest'
|
am_instrument '.MagiskAppTest'
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user