Skip to content

Commit 3f37b63

Browse files
AndroidLibrarySupport: Add functional tests for Kotlin Android libraries (#102)
Fixes: #94 Co-authored-by: Baris Basturk <realbarisbasturk@gmail.com>
1 parent 89c1b22 commit 3f37b63

File tree

12 files changed

+375
-2
lines changed

12 files changed

+375
-2
lines changed

build.gradle.kts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ plugins {
1313
repositories {
1414
mavenCentral()
1515
gradlePluginPortal()
16+
google()
1617
}
1718

1819
sourceSets {
@@ -63,6 +64,7 @@ val createClasspathManifest = tasks.register("createClasspathManifest") {
6364
}
6465

6566
val kotlinVersion: String by project
67+
val androidGradlePluginVersion: String = "7.2.2"
6668

6769
configurations.implementation {
6870
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib")
@@ -77,10 +79,12 @@ dependencies {
7779
implementation("org.ow2.asm:asm-tree:9.2")
7880
implementation("com.googlecode.java-diff-utils:diffutils:1.3.0")
7981
compileOnly("org.jetbrains.kotlin.multiplatform:org.jetbrains.kotlin.multiplatform.gradle.plugin:1.6.0")
82+
compileOnly("com.android.tools.build:gradle:${androidGradlePluginVersion}")
8083

8184
// The test needs the full kotlin multiplatform plugin loaded as it has no visibility of previously loaded plugins,
8285
// unlike the regular way gradle loads plugins.
8386
add(testPluginRuntimeConfiguration.name, "org.jetbrains.kotlin.multiplatform:org.jetbrains.kotlin.multiplatform.gradle.plugin:$kotlinVersion")
87+
add(testPluginRuntimeConfiguration.name, "com.android.tools.build:gradle:${androidGradlePluginVersion}")
8488

8589
testImplementation(kotlin("test-junit"))
8690
"functionalTestImplementation"(files(createClasspathManifest))

src/functionalTest/kotlin/kotlinx/validation/api/TestDsl.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,18 @@ internal fun FileContainer.kotlin(classFileName: String, sourceSet:String = "mai
4747
file(fileName, fn)
4848
}
4949

50+
/**
51+
* same as [file][FileContainer.file], but prepends "src/${sourceSet}/java" before given `classFileName`
52+
*/
53+
internal fun FileContainer.java(classFileName: String, sourceSet:String = "main", fn: AppendableScope.() -> Unit) {
54+
require(classFileName.endsWith(".java")) {
55+
"ClassFileName must end with '.java'"
56+
}
57+
58+
val fileName = "src/${sourceSet}/java/$classFileName"
59+
file(fileName, fn)
60+
}
61+
5062
/**
5163
* Shortcut for creating a `build.gradle.kts` by using [file][FileContainer.file]
5264
*/
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
* Copyright 2016-2022 JetBrains s.r.o.
3+
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
4+
*/
5+
6+
package kotlinx.validation.test
7+
8+
import kotlinx.validation.api.*
9+
import org.junit.Assume
10+
import org.junit.Test
11+
import java.io.File
12+
13+
internal class AndroidLibraryTest : BaseKotlinGradleTest() {
14+
15+
// region Kotlin Android Library
16+
17+
@Test
18+
fun `Given a Kotlin Android Library, when api is dumped, then task should be successful`() {
19+
assumeHasAndroid()
20+
val runner = test {
21+
createProjectWithSubModules()
22+
runner {
23+
arguments.add(":kotlin-library:apiDump")
24+
arguments.add("--full-stacktrace")
25+
}
26+
}
27+
28+
runner.build().apply {
29+
assertTaskSuccess(":kotlin-library:apiDump")
30+
}
31+
}
32+
33+
@Test
34+
fun `Given a Kotlin Android Library, when api is checked, then it should match the expected`() {
35+
assumeHasAndroid()
36+
test {
37+
createProjectWithSubModules()
38+
runner {
39+
arguments.add(":kotlin-library:apiCheck")
40+
}
41+
}.build().apply {
42+
assertTaskSuccess(":kotlin-library:apiCheck")
43+
}
44+
}
45+
46+
//endregion
47+
48+
//region Java Android Library
49+
50+
@Test
51+
fun `Given a Java Android Library, when api is dumped, then task should be successful`() {
52+
assumeHasAndroid()
53+
val runner = test {
54+
createProjectWithSubModules()
55+
runner {
56+
arguments.add(":java-library:apiDump")
57+
arguments.add("--full-stacktrace")
58+
}
59+
}
60+
61+
runner.build().apply {
62+
assertTaskSuccess(":java-library:apiDump")
63+
}
64+
}
65+
66+
@Test
67+
fun `Given a Java Android Library, when api is checked, then it should match the expected`() {
68+
assumeHasAndroid()
69+
test {
70+
createProjectWithSubModules()
71+
runner {
72+
arguments.add(":java-library:apiCheck")
73+
}
74+
}.build().apply {
75+
assertTaskSuccess(":java-library:apiCheck")
76+
}
77+
}
78+
79+
//endregion
80+
81+
/**
82+
* Creates a single project with 2 (Kotlin and Java Android Library) modules, applies
83+
* the plugin on the root project.
84+
*/
85+
private fun BaseKotlinScope.createProjectWithSubModules() {
86+
settingsGradleKts {
87+
resolve("examples/gradle/settings/settings-android-project.gradle.kts")
88+
}
89+
buildGradleKts {
90+
resolve("examples/gradle/base/androidProjectRoot.gradle.kts")
91+
}
92+
initLocalProperties()
93+
94+
dir("kotlin-library") {
95+
buildGradleKts {
96+
resolve("examples/gradle/base/androidKotlinLibrary.gradle.kts")
97+
}
98+
kotlin("KotlinLib.kt") {
99+
resolve("examples/classes/KotlinLib.kt")
100+
}
101+
apiFile(projectName = "kotlin-library") {
102+
resolve("examples/classes/KotlinLib.dump")
103+
}
104+
}
105+
dir("java-library") {
106+
buildGradleKts {
107+
resolve("examples/gradle/base/androidJavaLibrary.gradle.kts")
108+
}
109+
java("JavaLib.java") {
110+
resolve("examples/classes/JavaLib.java")
111+
}
112+
apiFile(projectName = "java-library") {
113+
resolve("examples/classes/JavaLib.dump")
114+
}
115+
}
116+
}
117+
118+
private fun initLocalProperties() {
119+
val home = System.getenv("ANDROID_HOME") ?: System.getenv("HOME")
120+
File(rootProjectDir, "local.properties").apply {
121+
writeText("sdk.dir=$home/Android/Sdk")
122+
}
123+
}
124+
125+
// We do not have ANDROID_HOME on CI, and this functionality is not critical, so we are disabling these
126+
// tests on CI
127+
private fun assumeHasAndroid() {
128+
Assume.assumeFalse(System.getenv("ANDROID_HOME").isNullOrEmpty())
129+
}
130+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
public final class examples/classes/JavaLib {
2+
public fun <init> ()V
3+
public fun foo ()Ljava/lang/String;
4+
}
5+
6+
public final class org/jetbrains/kotlinx/android/java/library/BuildConfig {
7+
public static final field BUILD_TYPE Ljava/lang/String;
8+
public static final field DEBUG Z
9+
public static final field LIBRARY_PACKAGE_NAME Ljava/lang/String;
10+
public fun <init> ()V
11+
}
12+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright 2016-2022 JetBrains s.r.o.
3+
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
4+
*/
5+
6+
package examples.classes;
7+
8+
public final class JavaLib {
9+
10+
public String foo() {
11+
return "foo";
12+
}
13+
14+
private String bar() {
15+
return "bar";
16+
}
17+
18+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
public final class examples/classes/KotlinLib {
2+
public fun <init> ()V
3+
public final fun foo ()Ljava/lang/String;
4+
}
5+
6+
public final class org/jetbrains/kotlinx/android/kotlin/library/BuildConfig {
7+
public static final field BUILD_TYPE Ljava/lang/String;
8+
public static final field DEBUG Z
9+
public static final field LIBRARY_PACKAGE_NAME Ljava/lang/String;
10+
public fun <init> ()V
11+
}
12+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
* Copyright 2016-2022 JetBrains s.r.o.
3+
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
4+
*/
5+
6+
package examples.classes
7+
8+
class KotlinLib {
9+
10+
fun foo(): String = "foo"
11+
internal fun bar(): String = "bar"
12+
13+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2016-2022 JetBrains s.r.o.
3+
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
4+
*/
5+
6+
plugins {
7+
id("com.android.library")
8+
id("org.jetbrains.kotlinx.binary-compatibility-validator")
9+
}
10+
11+
android {
12+
13+
namespace = "org.jetbrains.kotlinx.android.java.library"
14+
15+
compileSdk = 32
16+
17+
defaultConfig {
18+
minSdk = 31
19+
targetSdk = 32
20+
21+
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
22+
consumerProguardFiles("consumer-rules.pro")
23+
}
24+
25+
buildTypes {
26+
release {
27+
isMinifyEnabled = true
28+
proguardFiles(
29+
getDefaultProguardFile("proguard-android-optimize.txt"),
30+
"proguard-rules.pro"
31+
)
32+
}
33+
}
34+
35+
}
36+
37+
dependencies {
38+
// no dependencies required
39+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2016-2022 JetBrains s.r.o.
3+
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
4+
*/
5+
6+
plugins {
7+
id("com.android.library")
8+
id("kotlin-android")
9+
id("org.jetbrains.kotlinx.binary-compatibility-validator")
10+
}
11+
12+
android {
13+
14+
namespace = "org.jetbrains.kotlinx.android.kotlin.library"
15+
16+
compileSdk = 32
17+
18+
defaultConfig {
19+
minSdk = 31
20+
targetSdk = 32
21+
22+
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
23+
consumerProguardFiles("consumer-rules.pro")
24+
}
25+
26+
buildTypes {
27+
release {
28+
isMinifyEnabled = true
29+
proguardFiles(
30+
getDefaultProguardFile("proguard-android-optimize.txt"),
31+
"proguard-rules.pro"
32+
)
33+
}
34+
}
35+
36+
}
37+
38+
dependencies {
39+
// no dependencies required
40+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
plugins {
2+
id("com.android.application").version("7.2.2").apply(false)
3+
id("com.android.library").version("7.2.2").apply(false)
4+
id("org.jetbrains.kotlin.android").version("1.7.10").apply(false)
5+
id("org.jetbrains.kotlinx.binary-compatibility-validator").apply(false)
6+
}
7+
8+
tasks.register("clean", Delete::class) {
9+
delete(rootProject.buildDir)
10+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
pluginManagement {
2+
repositories {
3+
mavenLocal()
4+
gradlePluginPortal()
5+
google()
6+
mavenCentral()
7+
}
8+
}
9+
10+
dependencyResolutionManagement {
11+
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
12+
repositories {
13+
google()
14+
mavenCentral()
15+
}
16+
}
17+
18+
rootProject.name = "android-project"
19+
include(":kotlin-library")
20+
include(":java-library")

0 commit comments

Comments
 (0)