Skip to content

Commit

Permalink
[Student][MBL-12337] Fix patch for PSPDFKit crash, add assertion (#49) (
Browse files Browse the repository at this point in the history
  • Loading branch information
JordanMarshall authored May 8, 2019
1 parent 566a392 commit 7f39bd5
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ abstract class ClassTransformer {
/** The name of this transformer */
abstract val transformName: String

/**
* Counts the number successful transforms performed by this Transformer and provides an assertion
* that this count matches a given condition.
*/
open val counter: TransformCounter = TransformCounter.Any

/**
* Called once the [ClassPool] has been populated. At this point all source files have been scanned and it should be
* safe to obtain [CtClass]es, add package imports, append the classpath, or otherwise interact with the [ClassPool].
Expand All @@ -47,6 +53,13 @@ abstract class ClassTransformer {
*/
abstract fun transform(cc: CtClass, classPool: ClassPool): Boolean

/** Invokes [transform] and updates the [counter] if the transform was successful */
fun performTransform(cc: CtClass, classPool: ClassPool): Boolean {
val transformed = transform(cc, classPool)
if (transformed) counter.increment()
return transformed
}

val filter by lazy { createFilter() }

open val includeExternalLibs: List<String> = emptyList()
Expand Down Expand Up @@ -75,3 +88,41 @@ abstract class ClassTransformer {

}

sealed class TransformCounter {
internal var transformCount: Int = 0

abstract fun assertCount()

fun increment() {
transformCount++
}

object Any : TransformCounter() {
override fun assertCount() = Unit
}

class AtLest(private val atLeast: Int) : TransformCounter() {
override fun assertCount() {
if (transformCount < atLeast) {
throw IllegalStateException("Transformer ran $transformCount time(s) but was required to run at least $atLeast time(s)")
}
}
}

class AtMost(private val atMost: Int) : TransformCounter() {
override fun assertCount() {
if (transformCount > atMost) {
throw IllegalStateException("Transformer ran $transformCount time(s) but was required to run at most $atMost time(s)")
}
}
}

class Exactly(private val exactly: Int) : TransformCounter() {
override fun assertCount() {
if (transformCount != exactly) {
throw IllegalStateException("Transformer ran $transformCount time(s) but was required to run exactly $exactly time(s)")
}
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ class PDFKitCrashFixTransformer : ClassTransformer() {

override val transformName = "PSPDFKitYUDoDis"

override val includeExternalLibs = listOf("pspdfkit-4.8.1.aar")
override val counter = TransformCounter.Exactly(1)

override val includeExternalLibs = listOf("pspdfkit:4.8.1")

private val problemClassName = "com.pspdfkit.ui.PdfThumbnailGrid"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,19 @@ class ProjectTransformer(
)

override fun transform(transformInvocation: TransformInvocation) = with(transformInvocation) {
val start = System.currentTimeMillis()

// Don't transform anything if this is a test APK; just copy inputs and return
if (context.variantName.endsWith("AndroidTest")) {
inputs.forEach {
it.jarInputs.forEach {
inputs.forEach { input ->
input.jarInputs.forEach {
val dest = outputProvider.getContentLocation(it.name, it.contentTypes, it.scopes, Format.JAR)
when (it.status) {
Status.REMOVED -> dest.delete()
else -> it.file.copyTo(dest, true)
}
}
it.directoryInputs.forEach {
input.directoryInputs.forEach {
val dest = outputProvider.getContentLocation(it.name, it.contentTypes, it.scopes, Format.DIRECTORY)
it.file.copyRecursively(dest, overwrite = true)
}
Expand Down Expand Up @@ -88,7 +89,7 @@ class ProjectTransformer(
jarInput.file.copyTo(dest, true)
classPool.insertClassPath(jarInput.file.absolutePath)
if (jarInput.scopes.contains(QualifiedContent.Scope.SUB_PROJECTS)
|| includedExternalLibs.any { it in jarInput.file.absolutePath }) {
|| includedExternalLibs.any { it in jarInput.name }) {
candidateJars += jarInput.file to dest
}
}
Expand All @@ -112,7 +113,7 @@ class ProjectTransformer(
// Transform files
candidateFiles.forEach { (cc, src) ->
try {
val modCount = transformers.count { it.filter.matches(cc) && it.transform(cc, classPool) }
val modCount = transformers.count { it.filter.matches(cc) && it.performTransform(cc, classPool) }
if (modCount > 0) src.writeBytes(cc.toBytecode())
} catch (e: Throwable) {
println("Error transforming file ${src.nameWithoutExtension}")
Expand All @@ -130,7 +131,7 @@ class ProjectTransformer(
if (entry.name.endsWith(".class")) {
val cc = classPool[entry.name.substringBeforeLast(".class").replace("/", ".")]
if (cc.isFrozen) cc.defrost()
if (transformers.count { it.filter.matches(cc) && it.transform(cc, classPool) } > 0) {
if (transformers.count { it.filter.matches(cc) && it.performTransform(cc, classPool) } > 0) {
output.putNextEntry(JarEntry(entry.name))
output.write(cc.toBytecode())
} else {
Expand All @@ -148,6 +149,12 @@ class ProjectTransformer(
output.close()
input.close()
}

// Assert the transform counts match their expected conditions
transformers.forEach { it.counter.assertCount() }

val end = System.currentTimeMillis()
println(" :Transform took ${(end - start) / 1000.0} seconds")
}

/** Copies [entry] from the [input] jar to the [output] jar without modification */
Expand Down

0 comments on commit 7f39bd5

Please sign in to comment.