Skip to content

Commit

Permalink
Add integration tests for ksp library modules.
Browse files Browse the repository at this point in the history
I've added a new module ksp:integrationtest so that we can keep the
pollution from the dependent module out of the normal library glide
module tests. There's more detail in the documentation for the
build.gradle file in ksp:integrationtests.

This does at least make sure that if a dependent module is added, it is
succesfully included by ksp. Previously the tests only tested either
library modules compiled with the app glide module or library modules
compiled by ksp. This new set of tests now tests library modules
compiled by java. If we ever compile a module with ksp, we should add
that module to these tests as well so that we have integration tests for
both types of modules. For now all modules are compiled only with the
java processor.

In an ideal world we'd be able to just run the Java annotation processor
using kotlin compile testing the same way we are with ksp. The library
seems to support it. However I can't figure out a way to get the javax
annotations and kotlin and android all available in a single gradle
module. For now using a separate module is reasonable (if somewhat
clunky) compromise.
  • Loading branch information
sjudd committed Mar 8, 2023
1 parent 902bbd4 commit 9fd7a84
Show file tree
Hide file tree
Showing 10 changed files with 405 additions and 12 deletions.
38 changes: 38 additions & 0 deletions annotation/ksp/integrationtest/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* This package verifies that our ksp processor is able to successfully import
* and include LibraryGlideModules compiled in other modules. ksp:test is a more
* comprehensive set of unit tests for other scenarios for library tests.
*
* <p>Technically we could include these integration tests in ksp:test. However
* doing so would cause the dependent library to pollute every individual test
* because it's pulled in from the classpath. Using a separate module allows us
* to keep unit tests that are not concerned with dependent library modules
* separate.
*/
plugins {
id 'org.jetbrains.kotlin.android'
id 'com.android.library'
}

android {
compileSdkVersion COMPILE_SDK_VERSION as int

defaultConfig {
minSdkVersion MIN_SDK_VERSION as int
targetSdkVersion TARGET_SDK_VERSION as int
versionName VERSION_NAME as String
}
}

dependencies {
implementation "junit:junit:$JUNIT_VERSION"
testImplementation project(":annotation:ksp:test")
testImplementation project(":annotation:ksp")
testImplementation project(":annotation")
testImplementation project(":glide")
testImplementation project(":integration:okhttp3")
testImplementation "com.github.tschuchortdev:kotlin-compile-testing-ksp:${KOTLIN_COMPILE_TESTING_VERSION}"
testImplementation "com.google.truth:truth:${TRUTH_VERSION}"
testImplementation "org.jetbrains.kotlin:kotlin-test:${JETBRAINS_KOTLIN_TEST_VERSION}"
testImplementation project(path: ':annotation:ksp:test')
}
5 changes: 5 additions & 0 deletions annotation/ksp/integrationtest/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.bumptech.glide.annotation.ksp.integrationtest">

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,344 @@
package com.bumptech.glide.annotation.ksp.integrationtest

import com.google.common.truth.Truth.assertThat
import com.tschuchort.compiletesting.KotlinCompilation.ExitCode
import com.bumptech.glide.annotation.ksp.test.JavaSourceFile
import com.bumptech.glide.annotation.ksp.test.KotlinSourceFile
import com.bumptech.glide.annotation.ksp.test.SourceType
import com.bumptech.glide.annotation.ksp.test.PerSourceTypeTest
import com.bumptech.glide.annotation.ksp.test.hasSourceEqualTo
import org.intellij.lang.annotations.Language
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import org.junit.runners.Parameterized.Parameters

@RunWith(Parameterized::class)
class LibraryGlideModuleTests(override val sourceType: SourceType) : PerSourceTypeTest {

companion object {
@Parameters(name = "sourceType = {0}")
@JvmStatic
fun data() = SourceType.values()
}

@Test
fun compile_withOnlyAppGlideModule_generatesGeneratedAppGlideModule_thatCallsDependencyLibraryGlideModules() {
val kotlinAppModule =
KotlinSourceFile(
"AppModule.kt",
"""
import com.bumptech.glide.annotation.GlideModule
import com.bumptech.glide.module.AppGlideModule
@GlideModule class AppModule : AppGlideModule()
"""
)
val javaAppModule =
JavaSourceFile(
"AppModule.java",
"""
import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.module.AppGlideModule;
@GlideModule public class AppModule extends AppGlideModule {
public AppModule() {}
}
"""
)


compileCurrentSourceType(
kotlinAppModule,
javaAppModule,
) {
assertThat(it.exitCode).isEqualTo(ExitCode.OK)
assertThat(it.generatedAppGlideModuleContents())
.hasSourceEqualTo(appGlideModuleWithOnlyDependencyLibraryModules)
}
}

@Test
fun compile_withValidLibraryGlideModule_andAppGlideModule_generatesGeneratedAppGlideModule_thatCallsAllLibraryAndDependencyAndAppGlideModules() {
val kotlinLibraryModule =
KotlinSourceFile(
"LibraryModule.kt",
"""
import com.bumptech.glide.annotation.GlideModule
import com.bumptech.glide.module.LibraryGlideModule
@GlideModule class LibraryModule : LibraryGlideModule()
"""
)
val kotlinAppModule =
KotlinSourceFile(
"AppModule.kt",
"""
import com.bumptech.glide.annotation.GlideModule
import com.bumptech.glide.module.AppGlideModule
@GlideModule class AppModule : AppGlideModule()
"""
)
val javaLibraryModule =
JavaSourceFile(
"LibraryModule.java",
"""
import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.module.LibraryGlideModule;
@GlideModule public class LibraryModule extends LibraryGlideModule {}
"""
)
val javaAppModule =
JavaSourceFile(
"AppModule.java",
"""
import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.module.AppGlideModule;
@GlideModule public class AppModule extends AppGlideModule {
public AppModule() {}
}
"""
)

compileCurrentSourceType(
kotlinAppModule,
kotlinLibraryModule,
javaAppModule,
javaLibraryModule
) {
assertThat(it.exitCode).isEqualTo(ExitCode.OK)
assertThat(it.generatedAppGlideModuleContents())
.hasSourceEqualTo(appGlideModuleWithLibraryModuleAndDependencyLibraryModules)
}
}

@Test
fun compile_withDependencyModuleInExcludes_generatesGeneratedAppGlideModule_thatDoesNotCallDependencyLibraryGlideModules() {
val kotlinAppModule =
KotlinSourceFile(
"AppModule.kt",
"""
import com.bumptech.glide.annotation.Excludes
import com.bumptech.glide.annotation.GlideModule
import com.bumptech.glide.module.AppGlideModule
import com.bumptech.glide.integration.okhttp3.OkHttpLibraryGlideModule
@Excludes(OkHttpLibraryGlideModule::class)
@GlideModule class AppModule : AppGlideModule()
"""
)
val javaAppModule =
JavaSourceFile(
"AppModule.java",
"""
import com.bumptech.glide.annotation.Excludes;
import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.module.AppGlideModule;
import com.bumptech.glide.integration.okhttp3.OkHttpLibraryGlideModule;
@Excludes(OkHttpLibraryGlideModule.class)
@GlideModule
public class AppModule extends AppGlideModule {
public AppModule() {}
}
"""
)

compileCurrentSourceType(
kotlinAppModule,
javaAppModule,
) {
assertThat(it.exitCode).isEqualTo(ExitCode.OK)
assertThat(it.generatedAppGlideModuleContents())
.hasSourceEqualTo(simpleAppGlideModule)
}
}

@Test
fun compile_withLibraryModuleInExcludes_producesGeneratedAppGlideModuleThatDoesNotCallExcludedLibraryModule() {
val kotlinExcludedLibraryModule =
KotlinSourceFile(
"ExcludedLibraryModule.kt",
"""
import com.bumptech.glide.annotation.GlideModule
import com.bumptech.glide.module.LibraryGlideModule
@GlideModule class ExcludedLibraryModule : LibraryGlideModule()
"""
)
val kotlinAppModule =
KotlinSourceFile(
"AppModule.kt",
"""
import com.bumptech.glide.annotation.Excludes
import com.bumptech.glide.annotation.GlideModule
import com.bumptech.glide.module.AppGlideModule
@GlideModule
@Excludes(ExcludedLibraryModule::class)
class AppModule : AppGlideModule()
"""
)

val javaExcludedLibraryModule =
JavaSourceFile(
"ExcludedLibraryModule.java",
"""
import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.module.LibraryGlideModule;
@GlideModule
public class ExcludedLibraryModule extends LibraryGlideModule {}
"""
)
val javaAppModule =
JavaSourceFile(
"AppModule.java",
"""
import com.bumptech.glide.annotation.Excludes;
import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.module.AppGlideModule;
@GlideModule
@Excludes(ExcludedLibraryModule.class)
public class AppModule extends AppGlideModule {
public AppModule() {}
}
"""
)
compileCurrentSourceType(
kotlinAppModule,
kotlinExcludedLibraryModule,
javaAppModule,
javaExcludedLibraryModule
) {
assertThat(it.generatedAppGlideModuleContents())
.hasSourceEqualTo(appGlideModuleWithOnlyDependencyLibraryModules)
assertThat(it.exitCode).isEqualTo(ExitCode.OK)
}
}
}

// generated code always includes public and Unit
@Suppress("RedundantVisibilityModifier", "RedundantUnitReturnType")
@Language("kotlin")
const val simpleAppGlideModule =
"""
package com.bumptech.glide
import AppModule
import android.content.Context
import kotlin.Boolean
import kotlin.Suppress
import kotlin.Unit
internal class GeneratedAppGlideModuleImpl(
@Suppress("UNUSED_PARAMETER")
context: Context,
) : GeneratedAppGlideModule() {
private val appGlideModule: AppModule
init {
appGlideModule = AppModule()
}
public override fun registerComponents(
context: Context,
glide: Glide,
registry: Registry,
): Unit {
appGlideModule.registerComponents(context, glide, registry)
}
public override fun applyOptions(context: Context, builder: GlideBuilder): Unit {
appGlideModule.applyOptions(context, builder)
}
public override fun isManifestParsingEnabled(): Boolean = false
}
"""

// generated code always includes public and Unit
@Suppress("RedundantVisibilityModifier", "RedundantUnitReturnType")
@Language("kotlin")
const val appGlideModuleWithLibraryModuleAndDependencyLibraryModules =
"""
package com.bumptech.glide
import AppModule
import LibraryModule
import android.content.Context
import com.bumptech.glide.integration.okhttp3.OkHttpLibraryGlideModule
import kotlin.Boolean
import kotlin.Suppress
import kotlin.Unit
internal class GeneratedAppGlideModuleImpl(
@Suppress("UNUSED_PARAMETER")
context: Context,
) : GeneratedAppGlideModule() {
private val appGlideModule: AppModule
init {
appGlideModule = AppModule()
}
public override fun registerComponents(
context: Context,
glide: Glide,
registry: Registry,
): Unit {
OkHttpLibraryGlideModule().registerComponents(context, glide, registry)
LibraryModule().registerComponents(context, glide, registry)
appGlideModule.registerComponents(context, glide, registry)
}
public override fun applyOptions(context: Context, builder: GlideBuilder): Unit {
appGlideModule.applyOptions(context, builder)
}
public override fun isManifestParsingEnabled(): Boolean = false
}
"""

// generated code always includes public and Unit
@Suppress("RedundantVisibilityModifier", "RedundantUnitReturnType")
@Language("kotlin")
const val appGlideModuleWithOnlyDependencyLibraryModules =
"""
package com.bumptech.glide
import AppModule
import android.content.Context
import com.bumptech.glide.integration.okhttp3.OkHttpLibraryGlideModule
import kotlin.Boolean
import kotlin.Suppress
import kotlin.Unit
internal class GeneratedAppGlideModuleImpl(
@Suppress("UNUSED_PARAMETER")
context: Context,
) : GeneratedAppGlideModule() {
private val appGlideModule: AppModule
init {
appGlideModule = AppModule()
}
public override fun registerComponents(
context: Context,
glide: Glide,
registry: Registry,
): Unit {
OkHttpLibraryGlideModule().registerComponents(context, glide, registry)
appGlideModule.registerComponents(context, glide, registry)
}
public override fun applyOptions(context: Context, builder: GlideBuilder): Unit {
appGlideModule.applyOptions(context, builder)
}
public override fun isManifestParsingEnabled(): Boolean = false
}
"""

Loading

0 comments on commit 9fd7a84

Please sign in to comment.