1
mirror of https://github.com/revanced/revanced-patcher synced 2025-09-10 05:30:49 +02:00

Compare commits

...

21 Commits

Author SHA1 Message Date
semantic-release-bot
0a8ccba33e chore(release): 11.0.2-dev.4 [skip ci]
## [11.0.2-dev.4](https://github.com/revanced/revanced-patcher/compare/v11.0.2-dev.3...v11.0.2-dev.4) (2023-06-27)

### Bug Fixes

* do not load annotations as patches ([519359a](519359a9eb))
2023-06-27 02:11:33 +00:00
oSumAtrIX
519359a9eb fix: do not load annotations as patches 2023-06-27 04:09:03 +02:00
semantic-release-bot
b615ed6aab chore(release): 11.0.2-dev.3 [skip ci]
## [11.0.2-dev.3](https://github.com/revanced/revanced-patcher/compare/v11.0.2-dev.2...v11.0.2-dev.3) (2023-06-27)

### Performance Improvements

* resolve fingerprints using method maps ([#185](https://github.com/revanced/revanced-patcher/issues/185)) ([d718134](d718134ab2))
2023-06-27 02:08:29 +00:00
LisoUseInAIKyrios
d718134ab2 perf: resolve fingerprints using method maps (#185)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-06-27 04:06:51 +02:00
semantic-release-bot
5e681ed381 chore(release): 11.0.2-dev.2 [skip ci]
## [11.0.2-dev.2](https://github.com/revanced/revanced-patcher/compare/v11.0.2-dev.1...v11.0.2-dev.2) (2023-06-18)

### Bug Fixes

* use `versionCode` if `versionName` is unavailable ([6e1b647](6e1b6479b6))
2023-06-18 14:41:34 +00:00
oSumAtrIX
6e1b6479b6 fix: use versionCode if versionName is unavailable 2023-06-18 16:39:49 +02:00
semantic-release-bot
f3c9e28a62 chore(release): 11.0.2-dev.1 [skip ci]
## [11.0.2-dev.1](https://github.com/revanced/revanced-patcher/compare/v11.0.1...v11.0.2-dev.1) (2023-06-14)

### Bug Fixes

* catch exceptions from closing patches ([d5d6f85](d5d6f85084))
* only close succeeded patches ([b8151eb](b8151ebccb))
2023-06-14 00:16:26 +00:00
oSumAtrIX
d5d6f85084 fix: catch exceptions from closing patches 2023-06-14 02:14:37 +02:00
oSumAtrIX
b8151ebccb fix: only close succeeded patches 2023-06-14 01:43:19 +02:00
semantic-release-bot
5650e34432 chore(release): 11.0.1 [skip ci]
## [11.0.1](https://github.com/revanced/revanced-patcher/compare/v11.0.0...v11.0.1) (2023-06-12)

### Bug Fixes

* revert using `OutputStream.nullOutputStream` ([f02a426](f02a42610b))
2023-06-12 03:36:10 +00:00
oSumAtrIX
c893d16d52 chore: merge branch dev to main (#190) 2023-06-12 05:34:23 +02:00
semantic-release-bot
34f08bf206 chore(release): 11.0.1-dev.1 [skip ci]
## [11.0.1-dev.1](https://github.com/revanced/revanced-patcher/compare/v11.0.0...v11.0.1-dev.1) (2023-06-12)

### Bug Fixes

* revert using `OutputStream.nullOutputStream` ([f02a426](f02a42610b))
2023-06-12 03:33:53 +00:00
oSumAtrIX
f02a42610b fix: revert using OutputStream.nullOutputStream
Older Android versions don't support this API
2023-06-12 05:32:13 +02:00
oSumAtrIX
c95e6fa92f ci: add cache step 2023-06-12 02:55:09 +02:00
oSumAtrIX
fd738e723b ci: build before running semantic-release 2023-06-12 01:52:52 +02:00
oSumAtrIX
b1d1956323 ci: remove unnecessary steps 2023-06-12 01:47:26 +02:00
semantic-release-bot
725a8012ac chore(release): 11.0.0 [skip ci]
# [11.0.0](https://github.com/revanced/revanced-patcher/compare/v10.0.0...v11.0.0) (2023-06-10)

### Bug Fixes

* add imports to fix failing tests ([43d6868](43d6868d1f))

* refactor!: move extension functions to their corresponding classes ([a12fe7d](a12fe7dd9e))
* refactor!: use proper extension function names ([efdd01a](efdd01a988))
* fix!: implement extension functions consistently ([aacf900](aacf900764))

### BREAKING CHANGES

* This changes the import paths for extension functions.
* This changes the names of extension functions
* This changes the name of functions
2023-06-10 23:11:52 +00:00
oSumAtrIX
bb9a73e53b chore: merge branch dev to main (#187) 2023-06-11 01:10:59 +02:00
semantic-release-bot
ef2de35a74 chore(release): 11.0.0-dev.2 [skip ci]
# [11.0.0-dev.2](https://github.com/revanced/revanced-patcher/compare/v11.0.0-dev.1...v11.0.0-dev.2) (2023-06-09)

### Bug Fixes

* add imports to fix failing tests ([43d6868](43d6868d1f))
2023-06-09 23:56:16 +00:00
oSumAtrIX
2a453d51a8 refactor: rename helper methods for tests 2023-06-10 01:55:05 +02:00
oSumAtrIX
43d6868d1f fix: add imports to fix failing tests 2023-06-10 01:43:09 +02:00
8 changed files with 425 additions and 130 deletions

View File

@@ -23,17 +23,20 @@ jobs:
# https://github.com/cycjimmy/semantic-release-action#private-packages # https://github.com/cycjimmy/semantic-release-action#private-packages
persist-credentials: false persist-credentials: false
fetch-depth: 0 fetch-depth: 0
- name: Setup JDK - name: Cache
uses: actions/setup-java@v3 uses: actions/cache@v3
with: with:
java-version: '17' path: |
distribution: 'zulu' ${{ runner.home }}/.gradle/caches
cache: gradle ${{ runner.home }}/.gradle/wrapper
- name: Setup Node.js .gradle
uses: actions/setup-node@v3 build
with: node_modules
node-version: "18" key: ${{ runner.os }}-gradle-npm-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', 'package-lock.json') }}
cache: 'npm' - name: Build with Gradle
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ./gradlew clean --no-daemon
- name: Setup semantic-release - name: Setup semantic-release
run: npm install run: npm install
- name: Release - name: Release

View File

@@ -1,3 +1,72 @@
## [11.0.2-dev.4](https://github.com/revanced/revanced-patcher/compare/v11.0.2-dev.3...v11.0.2-dev.4) (2023-06-27)
### Bug Fixes
* do not load annotations as patches ([519359a](https://github.com/revanced/revanced-patcher/commit/519359a9eb0e9dfa390c5016e9fe4a7490b8ab18))
## [11.0.2-dev.3](https://github.com/revanced/revanced-patcher/compare/v11.0.2-dev.2...v11.0.2-dev.3) (2023-06-27)
### Performance Improvements
* resolve fingerprints using method maps ([#185](https://github.com/revanced/revanced-patcher/issues/185)) ([d718134](https://github.com/revanced/revanced-patcher/commit/d718134ab26423e02708e01eba711737f9260ba0))
## [11.0.2-dev.2](https://github.com/revanced/revanced-patcher/compare/v11.0.2-dev.1...v11.0.2-dev.2) (2023-06-18)
### Bug Fixes
* use `versionCode` if `versionName` is unavailable ([6e1b647](https://github.com/revanced/revanced-patcher/commit/6e1b6479b677657c226693e9cc6b63f4ef2ee060))
## [11.0.2-dev.1](https://github.com/revanced/revanced-patcher/compare/v11.0.1...v11.0.2-dev.1) (2023-06-14)
### Bug Fixes
* catch exceptions from closing patches ([d5d6f85](https://github.com/revanced/revanced-patcher/commit/d5d6f85084c03ed9c776632823ca12394a716167))
* only close succeeded patches ([b8151eb](https://github.com/revanced/revanced-patcher/commit/b8151ebccb5b27dd9e06fa63235cf9baeef1c0ee))
## [11.0.1](https://github.com/revanced/revanced-patcher/compare/v11.0.0...v11.0.1) (2023-06-12)
### Bug Fixes
* revert using `OutputStream.nullOutputStream` ([f02a426](https://github.com/revanced/revanced-patcher/commit/f02a42610b7698fc8cc6bc5183c9ccba2ed96cda))
## [11.0.1-dev.1](https://github.com/revanced/revanced-patcher/compare/v11.0.0...v11.0.1-dev.1) (2023-06-12)
### Bug Fixes
* revert using `OutputStream.nullOutputStream` ([f02a426](https://github.com/revanced/revanced-patcher/commit/f02a42610b7698fc8cc6bc5183c9ccba2ed96cda))
# [11.0.0](https://github.com/revanced/revanced-patcher/compare/v10.0.0...v11.0.0) (2023-06-10)
### Bug Fixes
* add imports to fix failing tests ([43d6868](https://github.com/revanced/revanced-patcher/commit/43d6868d1f59922f9812f3e4a2a890f3b331def6))
* refactor!: move extension functions to their corresponding classes ([a12fe7d](https://github.com/revanced/revanced-patcher/commit/a12fe7dd9e976c38a0a82fe35e6650f58f815de4))
* refactor!: use proper extension function names ([efdd01a](https://github.com/revanced/revanced-patcher/commit/efdd01a9886b6f06af213731824621964367b2a3))
* fix!: implement extension functions consistently ([aacf900](https://github.com/revanced/revanced-patcher/commit/aacf9007647b1cc11bc40053625802573efda6ef))
### BREAKING CHANGES
* This changes the import paths for extension functions.
* This changes the names of extension functions
* This changes the name of functions
# [11.0.0-dev.2](https://github.com/revanced/revanced-patcher/compare/v11.0.0-dev.1...v11.0.0-dev.2) (2023-06-09)
### Bug Fixes
* add imports to fix failing tests ([43d6868](https://github.com/revanced/revanced-patcher/commit/43d6868d1f59922f9812f3e4a2a890f3b331def6))
# [11.0.0-dev.1](https://github.com/revanced/revanced-patcher/compare/v10.0.0...v11.0.0-dev.1) (2023-06-07) # [11.0.0-dev.1](https://github.com/revanced/revanced-patcher/compare/v10.0.0...v11.0.0-dev.1) (2023-06-07)

View File

@@ -1,2 +1,2 @@
kotlin.code.style = official kotlin.code.style = official
version = 11.0.0-dev.1 version = 11.0.2-dev.4

View File

@@ -4,7 +4,8 @@ import app.revanced.patcher.data.Context
import app.revanced.patcher.extensions.PatchExtensions.dependencies import app.revanced.patcher.extensions.PatchExtensions.dependencies
import app.revanced.patcher.extensions.PatchExtensions.patchName import app.revanced.patcher.extensions.PatchExtensions.patchName
import app.revanced.patcher.extensions.PatchExtensions.requiresIntegrations import app.revanced.patcher.extensions.PatchExtensions.requiresIntegrations
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolveUsingLookupMap
import app.revanced.patcher.patch.* import app.revanced.patcher.patch.*
import app.revanced.patcher.util.VersionReader import app.revanced.patcher.util.VersionReader
import brut.androlib.Androlib import brut.androlib.Androlib
@@ -23,6 +24,7 @@ import lanchon.multidexlib2.MultiDexIO
import org.jf.dexlib2.Opcodes import org.jf.dexlib2.Opcodes
import org.jf.dexlib2.iface.DexFile import org.jf.dexlib2.iface.DexFile
import org.jf.dexlib2.writer.io.MemoryDataStore import org.jf.dexlib2.writer.io.MemoryDataStore
import java.io.Closeable
import java.io.File import java.io.File
import java.io.OutputStream import java.io.OutputStream
import java.nio.file.Files import java.nio.file.Files
@@ -247,7 +249,13 @@ class Patcher(private val options: PatcherOptions) {
XmlPullStreamDecoder( XmlPullStreamDecoder(
axmlParser, AndrolibResources().resXmlSerializer axmlParser, AndrolibResources().resXmlSerializer
).decodeManifest( ).decodeManifest(
extInputFile.directory.getFileInput("AndroidManifest.xml"), OutputStream.nullOutputStream() extInputFile.directory.getFileInput("AndroidManifest.xml"),
// Older Android versions do not support OutputStream.nullOutputStream()
object : OutputStream() {
override fun write(b: Int) {
// do nothing
}
}
) )
} }
} }
@@ -255,7 +263,7 @@ class Patcher(private val options: PatcherOptions) {
// read of the resourceTable which is created by reading the manifest file // read of the resourceTable which is created by reading the manifest file
context.packageMetadata.let { metadata -> context.packageMetadata.let { metadata ->
metadata.packageName = resourceTable.currentResPackage.name metadata.packageName = resourceTable.currentResPackage.name
metadata.packageVersion = resourceTable.versionInfo.versionName metadata.packageVersion = resourceTable.versionInfo.versionName ?: resourceTable.versionInfo.versionCode
metadata.metaInfo.versionInfo = resourceTable.versionInfo metadata.metaInfo.versionInfo = resourceTable.versionInfo
metadata.metaInfo.sdkInfo = resourceTable.sdkInfo metadata.metaInfo.sdkInfo = resourceTable.sdkInfo
} }
@@ -315,10 +323,7 @@ class Patcher(private val options: PatcherOptions) {
context.resourceContext context.resourceContext
} else { } else {
context.bytecodeContext.also { context -> context.bytecodeContext.also { context ->
(patchInstance as BytecodePatch).fingerprints?.resolve( (patchInstance as BytecodePatch).fingerprints?.resolveUsingLookupMap(context)
context,
context.classes.classes
)
} }
} }
@@ -338,31 +343,52 @@ class Patcher(private val options: PatcherOptions) {
return sequence { return sequence {
if (mergeIntegrations) context.integrations.merge(logger) if (mergeIntegrations) context.integrations.merge(logger)
logger.trace("Initialize lookup maps for method MethodFingerprint resolution")
MethodFingerprint.initializeFingerprintResolutionLookupMaps(context.bytecodeContext)
// prevent from decoding the manifest twice if it is not needed // prevent from decoding the manifest twice if it is not needed
if (resourceDecodingMode == ResourceDecodingMode.FULL) decodeResources(ResourceDecodingMode.FULL) if (resourceDecodingMode == ResourceDecodingMode.FULL) decodeResources(ResourceDecodingMode.FULL)
logger.trace("Executing all patches") logger.info("Executing patches")
val executedPatches = LinkedHashMap<String, ExecutedPatch>() // first is name val executedPatches = LinkedHashMap<String, ExecutedPatch>() // first is name
try { context.patches.forEach { patch ->
context.patches.forEach { patch -> val patchResult = executePatch(patch, executedPatches)
val patchResult = executePatch(patch, executedPatches)
val result = if (patchResult.isSuccess()) { val result = if (patchResult.isSuccess()) {
Result.success(patchResult.success()!!) Result.success(patchResult.success()!!)
} else { } else {
Result.failure(patchResult.error()!!) Result.failure(patchResult.error()!!)
} }
yield(patch.patchName to result) // TODO: This prints before the patch really finishes in case it is a Closeable
if (stopOnError && patchResult.isError()) return@sequence // because the Closeable is closed after all patches are executed.
} yield(patch.patchName to result)
} finally {
executedPatches.values.reversed().forEach { (patch, _) -> if (stopOnError && patchResult.isError()) return@sequence
patch.close()
}
} }
executedPatches.values
.filter(ExecutedPatch::success)
.map(ExecutedPatch::patchInstance)
.filterIsInstance(Closeable::class.java)
.asReversed().forEach {
try {
it.close()
} catch (exception: Exception) {
val patchName = (it as Patch<Context>).javaClass.patchName
logger.error("Failed to close '$patchName': ${exception.stackTraceToString()}")
yield(patchName to Result.failure(exception))
// This is not failsafe. If a patch throws an exception while closing,
// the other patches that depend on it may fail.
if (stopOnError) return@sequence
}
}
} }
} }

View File

@@ -12,7 +12,7 @@ import java.io.Closeable
* If it implements [Closeable], it will be closed after all patches have been executed. * If it implements [Closeable], it will be closed after all patches have been executed.
* Closing will be done in reverse execution order. * Closing will be done in reverse execution order.
*/ */
sealed interface Patch<out T : Context> : Closeable { sealed interface Patch<out T : Context> {
/** /**
* The main function of the [Patch] which the patcher will call. * The main function of the [Patch] which the patcher will call.
* *
@@ -20,13 +20,6 @@ sealed interface Patch<out T : Context> : Closeable {
* @return The result of executing the patch. * @return The result of executing the patch.
*/ */
fun execute(context: @UnsafeVariance T): PatchResult fun execute(context: @UnsafeVariance T): PatchResult
/**
* The closing function for this patch.
*
* This can be treated like popping the patch from the current patch stack.
*/
override fun close() {}
} }
/** /**

View File

@@ -3,6 +3,7 @@
package app.revanced.patcher.util.patch package app.revanced.patcher.util.patch
import app.revanced.patcher.data.Context import app.revanced.patcher.data.Context
import app.revanced.patcher.extensions.AnnotationExtensions.findAnnotationRecursively
import app.revanced.patcher.extensions.PatchExtensions.patchName import app.revanced.patcher.extensions.PatchExtensions.patchName
import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.Patch
import org.jf.dexlib2.DexFileFactory import org.jf.dexlib2.DexFileFactory
@@ -19,7 +20,13 @@ sealed class PatchBundle(path: String) : File(path) {
internal fun loadPatches(classLoader: ClassLoader, classNames: Iterator<String>) = buildList { internal fun loadPatches(classLoader: ClassLoader, classNames: Iterator<String>) = buildList {
classNames.forEach { className -> classNames.forEach { className ->
val clazz = classLoader.loadClass(className) val clazz = classLoader.loadClass(className)
if (!clazz.isAnnotationPresent(app.revanced.patcher.patch.annotations.Patch::class.java)) return@forEach
// Annotations can not Patch.
if (clazz.isAnnotation) return@forEach
clazz.findAnnotationRecursively(app.revanced.patcher.patch.annotations.Patch::class)
?: return@forEach
@Suppress("UNCHECKED_CAST") this.add(clazz as Class<out Patch<Context>>) @Suppress("UNCHECKED_CAST") this.add(clazz as Class<out Patch<Context>>)
} }
}.sortedBy { it.patchName } }.sortedBy { it.patchName }
@@ -43,11 +50,9 @@ sealed class PatchBundle(path: String) : File(path) {
), ),
JarFile(this) JarFile(this)
.stream() .stream()
.filter {it.name.endsWith(".class") && !it.name.contains("$")} .filter { it.name.endsWith(".class") && !it.name.contains("$") }
.map({it -> it.realName.replace('/', '.').replace(".class", "")}).iterator() .map { it.realName.replace('/', '.').replace(".class", "") }.iterator()
) )
} }
/** /**
@@ -63,8 +68,9 @@ sealed class PatchBundle(path: String) : File(path) {
* Patches will be loaded to the provided [dexClassLoader]. * Patches will be loaded to the provided [dexClassLoader].
*/ */
fun loadPatches() = loadPatches(dexClassLoader, fun loadPatches() = loadPatches(dexClassLoader,
DexFileFactory.loadDexFile(path, null).classes.asSequence().map({ classDef -> DexFileFactory.loadDexFile(path, null).classes.asSequence().map { classDef ->
classDef.type.substring(1, classDef.length - 1).replace('/', '.') classDef.type.substring(1, classDef.length - 1).replace('/', '.')
}).iterator()) }.iterator()
)
} }
} }

View File

@@ -1,5 +1,13 @@
package app.revanced.patcher.extensions package app.revanced.patcher.extensions
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patcher.util.smali.ExternalLabel
@@ -33,7 +41,7 @@ private object InstructionExtensionsTest {
).let { testMethod = it.toMutable() } ).let { testMethod = it.toMutable() }
@Test @Test
fun addInstructionsToImplementationIndexed() = applyOnImplementation { fun addInstructionsToImplementationIndexed() = applyToImplementation {
addInstructions(5, getTestInstructions(5..6)).also { addInstructions(5, getTestInstructions(5..6)).also {
assertRegisterIs(5, 5) assertRegisterIs(5, 5)
assertRegisterIs(6, 6) assertRegisterIs(6, 6)
@@ -43,7 +51,7 @@ private object InstructionExtensionsTest {
} }
@Test @Test
fun addInstructionsToImplementation() = applyOnImplementation { fun addInstructionsToImplementation() = applyToImplementation {
addInstructions(getTestInstructions(10..11)).also { addInstructions(getTestInstructions(10..11)).also {
assertRegisterIs(10, 10) assertRegisterIs(10, 10)
assertRegisterIs(11, 11) assertRegisterIs(11, 11)
@@ -51,19 +59,19 @@ private object InstructionExtensionsTest {
} }
@Test @Test
fun removeInstructionsFromImplementationIndexed() = applyOnImplementation { fun removeInstructionsFromImplementationIndexed() = applyToImplementation {
removeInstructions(5, 5).also { assertRegisterIs(4, 4) } removeInstructions(5, 5).also { assertRegisterIs(4, 4) }
} }
@Test @Test
fun removeInstructionsFromImplementation() = applyOnImplementation { fun removeInstructionsFromImplementation() = applyToImplementation {
removeInstructions(0).also { assertRegisterIs(9, 9) } removeInstructions(0).also { assertRegisterIs(9, 9) }
removeInstructions(1).also { assertRegisterIs(1, 0) } removeInstructions(1).also { assertRegisterIs(1, 0) }
removeInstructions(2).also { assertRegisterIs(3, 0) } removeInstructions(2).also { assertRegisterIs(3, 0) }
} }
@Test @Test
fun replaceInstructionsInImplementationIndexed() = applyOnImplementation { fun replaceInstructionsInImplementationIndexed() = applyToImplementation {
replaceInstructions(5, getTestInstructions(0..1)).also { replaceInstructions(5, getTestInstructions(0..1)).also {
assertRegisterIs(0, 5) assertRegisterIs(0, 5)
assertRegisterIs(1, 6) assertRegisterIs(1, 6)
@@ -72,27 +80,27 @@ private object InstructionExtensionsTest {
} }
@Test @Test
fun addInstructionToMethodIndexed() = applyOnMethod { fun addInstructionToMethodIndexed() = applyToMethod {
addInstruction(5, TestInstruction(0)).also { assertRegisterIs(0, 5) } addInstruction(5, TestInstruction(0)).also { assertRegisterIs(0, 5) }
} }
@Test @Test
fun addInstructionToMethod() = applyOnMethod { fun addInstructionToMethod() = applyToMethod {
addInstruction(TestInstruction(0)).also { assertRegisterIs(0, 10) } addInstruction(TestInstruction(0)).also { assertRegisterIs(0, 10) }
} }
@Test @Test
fun addSmaliInstructionToMethodIndexed() = applyOnMethod { fun addSmaliInstructionToMethodIndexed() = applyToMethod {
addInstruction(5, getTestSmaliInstruction(0)).also { assertRegisterIs(0, 5) } addInstruction(5, getTestSmaliInstruction(0)).also { assertRegisterIs(0, 5) }
} }
@Test @Test
fun addSmaliInstructionToMethod() = applyOnMethod { fun addSmaliInstructionToMethod() = applyToMethod {
addInstruction(getTestSmaliInstruction(0)).also { assertRegisterIs(0, 10) } addInstruction(getTestSmaliInstruction(0)).also { assertRegisterIs(0, 10) }
} }
@Test @Test
fun addInstructionsToMethodIndexed() = applyOnMethod { fun addInstructionsToMethodIndexed() = applyToMethod {
addInstructions(5, getTestInstructions(0..1)).also { addInstructions(5, getTestInstructions(0..1)).also {
assertRegisterIs(0, 5) assertRegisterIs(0, 5)
assertRegisterIs(1, 6) assertRegisterIs(1, 6)
@@ -102,7 +110,7 @@ private object InstructionExtensionsTest {
} }
@Test @Test
fun addInstructionsToMethod() = applyOnMethod { fun addInstructionsToMethod() = applyToMethod {
addInstructions(getTestInstructions(0..1)).also { addInstructions(getTestInstructions(0..1)).also {
assertRegisterIs(0, 10) assertRegisterIs(0, 10)
assertRegisterIs(1, 11) assertRegisterIs(1, 11)
@@ -112,7 +120,7 @@ private object InstructionExtensionsTest {
} }
@Test @Test
fun addSmaliInstructionsToMethodIndexed() = applyOnMethod { fun addSmaliInstructionsToMethodIndexed() = applyToMethod {
addInstructionsWithLabels(5, getTestSmaliInstructions(0..1)).also { addInstructionsWithLabels(5, getTestSmaliInstructions(0..1)).also {
assertRegisterIs(0, 5) assertRegisterIs(0, 5)
assertRegisterIs(1, 6) assertRegisterIs(1, 6)
@@ -122,7 +130,7 @@ private object InstructionExtensionsTest {
} }
@Test @Test
fun addSmaliInstructionsToMethod() = applyOnMethod { fun addSmaliInstructionsToMethod() = applyToMethod {
addInstructions(getTestSmaliInstructions(0..1)).also { addInstructions(getTestSmaliInstructions(0..1)).also {
assertRegisterIs(0, 10) assertRegisterIs(0, 10)
assertRegisterIs(1, 11) assertRegisterIs(1, 11)
@@ -132,8 +140,8 @@ private object InstructionExtensionsTest {
} }
@Test @Test
fun addSmaliInstructionsWithExternalLabelToMethodIndexed() = applyOnMethod { fun addSmaliInstructionsWithExternalLabelToMethodIndexed() = applyToMethod {
val label = ExternalLabel("testLabel", instruction(5)) val label = ExternalLabel("testLabel", getInstruction(5))
addInstructionsWithLabels( addInstructionsWithLabels(
5, 5,
@@ -144,7 +152,7 @@ private object InstructionExtensionsTest {
assertRegisterIs(1, 6) assertRegisterIs(1, 6)
assertRegisterIs(5, 8) assertRegisterIs(5, 8)
val gotoTarget = instruction<BuilderOffsetInstruction>(7) val gotoTarget = getInstruction<BuilderOffsetInstruction>(7)
.target.location.instruction as OneRegisterInstruction .target.location.instruction as OneRegisterInstruction
assertEquals(5, gotoTarget.registerA) assertEquals(5, gotoTarget.registerA)
@@ -152,7 +160,7 @@ private object InstructionExtensionsTest {
} }
@Test @Test
fun removeInstructionFromMethodIndexed() = applyOnMethod { fun removeInstructionFromMethodIndexed() = applyToMethod {
removeInstruction(5).also { removeInstruction(5).also {
assertRegisterIs(4, 4) assertRegisterIs(4, 4)
assertRegisterIs(6, 5) assertRegisterIs(6, 5)
@@ -160,24 +168,24 @@ private object InstructionExtensionsTest {
} }
@Test @Test
fun removeInstructionsFromMethodIndexed() = applyOnMethod { fun removeInstructionsFromMethodIndexed() = applyToMethod {
removeInstructions(5, 5).also { assertRegisterIs(4, 4) } removeInstructions(5, 5).also { assertRegisterIs(4, 4) }
} }
@Test @Test
fun removeInstructionsFromMethod() = applyOnMethod { fun removeInstructionsFromMethod() = applyToMethod {
removeInstructions(0).also { assertRegisterIs(9, 9) } removeInstructions(0).also { assertRegisterIs(9, 9) }
removeInstructions(1).also { assertRegisterIs(1, 0) } removeInstructions(1).also { assertRegisterIs(1, 0) }
removeInstructions(2).also { assertRegisterIs(3, 0) } removeInstructions(2).also { assertRegisterIs(3, 0) }
} }
@Test @Test
fun replaceInstructionInMethodIndexed() = applyOnMethod { fun replaceInstructionInMethodIndexed() = applyToMethod {
replaceInstruction(5, TestInstruction(0)).also { assertRegisterIs(0, 5) } replaceInstruction(5, TestInstruction(0)).also { assertRegisterIs(0, 5) }
} }
@Test @Test
fun replaceInstructionsInMethodIndexed() = applyOnMethod { fun replaceInstructionsInMethodIndexed() = applyToMethod {
replaceInstructions(5, getTestInstructions(0..1)).also { replaceInstructions(5, getTestInstructions(0..1)).also {
assertRegisterIs(0, 5) assertRegisterIs(0, 5)
assertRegisterIs(1, 6) assertRegisterIs(1, 6)
@@ -186,7 +194,7 @@ private object InstructionExtensionsTest {
} }
@Test @Test
fun replaceSmaliInstructionsInMethodIndexed() = applyOnMethod { fun replaceSmaliInstructionsInMethodIndexed() = applyToMethod {
replaceInstructions(5, getTestSmaliInstructions(0..1)).also { replaceInstructions(5, getTestSmaliInstructions(0..1)).also {
assertRegisterIs(0, 5) assertRegisterIs(0, 5)
assertRegisterIs(1, 6) assertRegisterIs(1, 6)
@@ -196,16 +204,16 @@ private object InstructionExtensionsTest {
// region Helper methods // region Helper methods
private fun applyOnImplementation(block: MutableMethodImplementation.() -> Unit) { private fun applyToImplementation(block: MutableMethodImplementation.() -> Unit) {
testMethodImplementation.apply(block) testMethodImplementation.apply(block)
} }
private fun applyOnMethod(block: MutableMethod.() -> Unit) { private fun applyToMethod(block: MutableMethod.() -> Unit) {
testMethod.apply(block) testMethod.apply(block)
} }
private fun MutableMethodImplementation.assertRegisterIs(register: Int, atIndex: Int) = assertEquals( private fun MutableMethodImplementation.assertRegisterIs(register: Int, atIndex: Int) = assertEquals(
register, instruction<OneRegisterInstruction>(atIndex).registerA register, getInstruction<OneRegisterInstruction>(atIndex).registerA
) )
private fun MutableMethod.assertRegisterIs(register: Int, atIndex: Int) = private fun MutableMethod.assertRegisterIs(register: Int, atIndex: Int) =