Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "Refactor daggertrack tests" #12

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package me.amanjeet.daggertrack

import com.android.build.api.transform.TransformInvocation
import com.android.build.gradle.BaseExtension
import javassist.ClassPool
import java.io.File

/**
* A factory which helps creating [ClassPool] for the project
Expand All @@ -15,15 +15,21 @@ internal class ClassPoolFactory(private val classPool: ClassPool) {
* Builds class pool of internal project files, external dependencies android jar from
* sdk directory.
*
* @param projectInputs Project files including both direct and referenced of module
* @param transformInvocation TransformInvocation to copy jar and directory inputs
* @param android BaseExtension for android to extract android.jar of compiledSdkVersion from
* sdk directory
*/
fun buildProjectClassPool(
projectInputs: List<File>,
android: BaseExtension
): ClassPool {
projectInputs.forEach { classPool.insertClassPath(it.absolutePath) }
fun buildProjectClassPool(transformInvocation: TransformInvocation, android: BaseExtension): ClassPool {
// External Deps
transformInvocation.referencedInputs.forEach { transformInput ->
transformInput.directoryInputs.forEach { classPool.insertClassPath(it.file.absolutePath) }
transformInput.jarInputs.forEach { classPool.insertClassPath(it.file.absolutePath) }
}
// Project files
transformInvocation.inputs.forEach { transformInput ->
transformInput.directoryInputs.forEach{ classPool.insertClassPath(it.file.absolutePath) }
transformInput.jarInputs.forEach { classPool.insertClassPath(it.file.absolutePath) }
}
// android jar from compiled sdk
val androidJar = "${android.sdkDirectory.absolutePath}/platforms" +
"/${android.compileSdkVersion}/android.jar"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import me.amanjeet.daggertrack.transform.DaggerAndroidClassTransform
import me.amanjeet.daggertrack.transform.DaggerHiltClassTransform
import org.gradle.api.GradleException
import org.gradle.api.Project
import java.io.File

internal class DaggerTrackTransform(
private val project: Project,
Expand Down Expand Up @@ -54,7 +53,12 @@ internal class DaggerTrackTransform(
Format.DIRECTORY
)
transformInvocation.outputProvider.deleteAll()
val classPool = createClassPool(transformInvocation)
val defaultClassPool = ClassPool.getDefault()
val classPoolFactory = ClassPoolFactory(defaultClassPool)
val classPool = classPoolFactory.buildProjectClassPool(
transformInvocation,
android
)
val shouldApplyTransform = daggerTrackExtension.applyFor?.find {
variantName.endsWith(it, true)
} != null
Expand All @@ -73,38 +77,6 @@ internal class DaggerTrackTransform(
copyAllJars(transformInvocation)
}

private fun createClassPool(transformInvocation: TransformInvocation): ClassPool {
val projectInputs = getProjectInput(transformInvocation)
val defaultClassPool = ClassPool.getDefault()
val classPoolFactory = ClassPoolFactory(defaultClassPool)
return classPoolFactory.buildProjectClassPool(projectInputs, android)
}

/**
* Creates a list of files from both direct inputs and referenced inputs of transform
*
* @param transformInvocation TransformInvocation object for [DaggerTrackTransform]
* @return list of file containing both direct and referenced input of transform
*/
private fun getProjectInput(transformInvocation: TransformInvocation): List<File> {
// External deps.
val referencedDirInputs = transformInvocation.referencedInputs.map { it.directoryInputs }
.flatten()
.map { it.file }
val referencedJarInputs = transformInvocation.referencedInputs.map { it.jarInputs }
.flatten()
.map { it.file }
// Project files
val projectDirInputs = transformInvocation.inputs.map { it.directoryInputs }
.flatten()
.map { it.file }
val projectJarInputs = transformInvocation.inputs.map { it.jarInputs }
.flatten()
.map { it.file }
return referencedDirInputs + referencedJarInputs +
projectDirInputs + projectJarInputs
}

private fun validateDaggerClocks(classPool: ClassPool) {
try {
classPool.get("me.amanjeet.daggertrack.DaggerTrackClocks")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package me.amanjeet.daggertrack

import com.android.SdkConstants.DOT_CLASS
import com.android.build.api.transform.DirectoryInput
import com.android.build.api.transform.JarInput
import com.android.build.api.transform.TransformInput
import com.android.build.api.transform.TransformInvocation
import com.android.build.gradle.BaseExtension
import com.google.common.truth.Truth.assertThat
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.verify
import com.nhaarman.mockitokotlin2.whenever
import javassist.ClassPool
import org.junit.Before
Expand All @@ -12,35 +15,74 @@ import java.io.File

internal class ClassPoolFactoryTest {

private val defaultClassPool = ClassPool.getDefault()
private val transformInvocation = mock<TransformInvocation>()
private val transformInput = mock<TransformInput>()
private val directoryInput = mock<DirectoryInput>()
private val jarInput = mock<JarInput>()
private val jarFile = mock<File>()
private val directoryInputFile = mock<File>()
private val sdkDirectory = mock<File>()
private val classPool = mock<ClassPool>()
private val android = mock<BaseExtension>()
private val transformInputCollection = arrayListOf(transformInput)
private val directoryInputCollection = arrayListOf(directoryInput)
private val jarInputCollection = arrayListOf(jarInput)

@Before
fun setup() {
whenever(sdkDirectory.absolutePath).thenReturn("./src/test/resources/fake-android-sdk")
whenever(sdkDirectory.absolutePath).thenReturn("/directory/androidSdk")
whenever(android.sdkDirectory).thenReturn(sdkDirectory)
whenever(android.compileSdkVersion).thenReturn("android-28")
whenever(android.compileSdkVersion).thenReturn("28")
}

@Test
fun `it builds class pool of external libraries`() {
// given
val classFileInputSequence = File("./src/test/resources/external")
.walkTopDown()
.map { it }
.filter { it.absolutePath.endsWith(DOT_CLASS) }
val externalJarPath = "/jars/myExternalJar.jar"
val externalClassDirectoryPath = "/directory/MyExternalClass"
whenever(jarFile.absolutePath).thenReturn(externalJarPath)
whenever(directoryInputFile.absolutePath).thenReturn(externalClassDirectoryPath)
whenever(directoryInput.file).thenReturn(directoryInputFile)
whenever(jarInput.file).thenReturn(jarFile)
whenever(transformInvocation.referencedInputs).thenReturn(transformInputCollection)
whenever(transformInput.directoryInputs).thenReturn(directoryInputCollection)
whenever(transformInput.jarInputs).thenReturn(jarInputCollection)
val androidJarPath = "${android.sdkDirectory.absolutePath}/platforms" +
"/${android.compileSdkVersion}/android.jar"

// when
val classPool = ClassPoolFactory(defaultClassPool).buildProjectClassPool(
classFileInputSequence.toList(),
ClassPoolFactory(classPool).buildProjectClassPool(
transformInvocation,
android
)

// then, class file from dummy android jar & external class file exist in classpool
val classFromJarFile = classPool.get("me.amanjeet.daggertrack.ClassPoolFactory")
val externalLibraryA = classPool.get("external.minimal.LibraryA")
assertThat(classFromJarFile.simpleName).isEqualTo("ClassPoolFactory")
assertThat(externalLibraryA.simpleName).isEqualTo("LibraryA")
// then
verify(classPool).insertClassPath(androidJarPath)
verify(classPool).insertClassPath(externalJarPath)
verify(classPool).insertClassPath(externalClassDirectoryPath)
}

@Test
fun `it includes project files inputs in class pool`() {
// given
val jarPath = "/jars/myInternalJar.jar"
val directoryPath = "/directory/MyApplicationClass"
whenever(jarFile.absolutePath).thenReturn(jarPath)
whenever(directoryInputFile.absolutePath).thenReturn(directoryPath)
whenever(directoryInput.file).thenReturn(directoryInputFile)
whenever(jarInput.file).thenReturn(jarFile)
whenever(transformInvocation.inputs).thenReturn(transformInputCollection)
whenever(transformInput.directoryInputs).thenReturn(directoryInputCollection)
whenever(transformInput.jarInputs).thenReturn(jarInputCollection)

// when
ClassPoolFactory(classPool).buildProjectClassPool(
transformInvocation,
android
)

// then
verify(classPool).insertClassPath(jarPath)
verify(classPool).insertClassPath(directoryPath)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,96 +7,29 @@ import com.google.common.truth.Truth.assertThat
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.whenever
import javassist.ClassPool
import me.amanjeet.daggertrack.utils.GradleTestRunner
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
import java.io.File

internal class ClassPoolTransformationsTest {

@Rule
@JvmField
val testProjectDir: TemporaryFolder = TemporaryFolder
.builder().assureDeletion().build()

private val classPool = ClassPool.getDefault()

private lateinit var gradleTestRunner: GradleTestRunner

@Before
fun setup() {
gradleTestRunner = GradleTestRunner(testProjectDir)
gradleTestRunner.addDependencies(
"implementation 'androidx.appcompat:appcompat:1.1.0'"
)
setupApplicationClass()
setupMainActivity()
}

@Test
fun `it transforms class pool to the list of CtClass`() {
fun `it transforms the class pool to list of CtClass`() {
// given
val inputs = mock<TransformInput>()
val classFilesDirectoryInput = mock<DirectoryInput>()
val transformInvocation = mock<TransformInvocation>()
val result = gradleTestRunner.build(shouldIntegrateDaggerTrack = false)
val appClassFile = result.getClassFile("minimal/MyApp.class")
val classFilesDirectory = appClassFile.parentFile.parentFile
classPool.insertClassPath(classFilesDirectory.absolutePath)
val inputs = mock<TransformInput>()
val directoryInput = mock<DirectoryInput>()
val file = File("./src/test/resources")
val classPool = ClassPool.getDefault()
classPool.makeClass("me.amanjeet.daggertrack.HomeActivity")
whenever(transformInvocation.inputs).thenReturn(arrayListOf(inputs))
whenever(inputs.directoryInputs).thenReturn(arrayListOf(classFilesDirectoryInput))
whenever(classFilesDirectoryInput.file).thenReturn(classFilesDirectory)
whenever(inputs.directoryInputs).thenReturn(arrayListOf(directoryInput))
whenever(directoryInput.file).thenReturn(file)

// when
val ctClassList = classPool.mapToCtClassList(transformInvocation)

// then
val classNameList = ctClassList.map { it.name }
assertThat(classNameList).containsExactly(
"minimal.MyApp",
"minimal.MainActivity",
"minimal.BuildConfig"
)
}

private fun setupApplicationClass() {
gradleTestRunner.addSrc(
srcPath = "minimal/MyApp.java",
srcContent =
"""
package minimal;
import android.app.Application;

public class MyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
}
}
""".trimIndent()
)
gradleTestRunner.setAppClassName(".MyApp")
}

private fun setupMainActivity() {
gradleTestRunner.addSrc(
srcPath = "minimal/MainActivity.java",
srcContent =
"""
package minimal;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
""".trimIndent()
)
gradleTestRunner.addActivities(
"<activity android:name=\".MainActivity\"/>"
)
assertThat(classNameList).contains("me.amanjeet.daggertrack.HomeActivity")
}
}
Loading