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

Pr/98 #102

Merged
merged 4 commits into from Oct 20, 2022
Merged

Pr/98 #102

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions build.gradle.kts
Expand Up @@ -13,6 +13,7 @@ plugins {
repositories {
mavenCentral()
gradlePluginPortal()
google()
}

sourceSets {
Expand Down Expand Up @@ -63,6 +64,7 @@ val createClasspathManifest = tasks.register("createClasspathManifest") {
}

val kotlinVersion: String by project
val androidGradlePluginVersion: String = "7.2.2"

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

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

testImplementation(kotlin("test-junit"))
"functionalTestImplementation"(files(createClasspathManifest))
Expand Down
12 changes: 12 additions & 0 deletions src/functionalTest/kotlin/kotlinx/validation/api/TestDsl.kt
Expand Up @@ -47,6 +47,18 @@ internal fun FileContainer.kotlin(classFileName: String, sourceSet:String = "mai
file(fileName, fn)
}

/**
* same as [file][FileContainer.file], but prepends "src/${sourceSet}/java" before given `classFileName`
*/
internal fun FileContainer.java(classFileName: String, sourceSet:String = "main", fn: AppendableScope.() -> Unit) {
require(classFileName.endsWith(".java")) {
"ClassFileName must end with '.java'"
}

val fileName = "src/${sourceSet}/java/$classFileName"
file(fileName, fn)
}

/**
* Shortcut for creating a `build.gradle.kts` by using [file][FileContainer.file]
*/
Expand Down
@@ -0,0 +1,130 @@
/*
* Copyright 2016-2022 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
*/

package kotlinx.validation.test

import kotlinx.validation.api.*
import org.junit.Assume
import org.junit.Test
import java.io.File

internal class AndroidLibraryTest : BaseKotlinGradleTest() {

// region Kotlin Android Library

@Test
fun `Given a Kotlin Android Library, when api is dumped, then task should be successful`() {
assumeHasAndroid()
val runner = test {
createProjectWithSubModules()
runner {
arguments.add(":kotlin-library:apiDump")
arguments.add("--full-stacktrace")
}
}

runner.build().apply {
assertTaskSuccess(":kotlin-library:apiDump")
}
}

@Test
fun `Given a Kotlin Android Library, when api is checked, then it should match the expected`() {
assumeHasAndroid()
test {
createProjectWithSubModules()
runner {
arguments.add(":kotlin-library:apiCheck")
}
}.build().apply {
assertTaskSuccess(":kotlin-library:apiCheck")
}
}

//endregion

//region Java Android Library

@Test
fun `Given a Java Android Library, when api is dumped, then task should be successful`() {
assumeHasAndroid()
val runner = test {
createProjectWithSubModules()
runner {
arguments.add(":java-library:apiDump")
arguments.add("--full-stacktrace")
}
}

runner.build().apply {
assertTaskSuccess(":java-library:apiDump")
}
}

@Test
fun `Given a Java Android Library, when api is checked, then it should match the expected`() {
assumeHasAndroid()
test {
createProjectWithSubModules()
runner {
arguments.add(":java-library:apiCheck")
}
}.build().apply {
assertTaskSuccess(":java-library:apiCheck")
}
}

//endregion

/**
* Creates a single project with 2 (Kotlin and Java Android Library) modules, applies
* the plugin on the root project.
*/
private fun BaseKotlinScope.createProjectWithSubModules() {
settingsGradleKts {
resolve("examples/gradle/settings/settings-android-project.gradle.kts")
}
buildGradleKts {
resolve("examples/gradle/base/androidProjectRoot.gradle.kts")
}
initLocalProperties()

dir("kotlin-library") {
buildGradleKts {
resolve("examples/gradle/base/androidKotlinLibrary.gradle.kts")
}
kotlin("KotlinLib.kt") {
resolve("examples/classes/KotlinLib.kt")
}
apiFile(projectName = "kotlin-library") {
resolve("examples/classes/KotlinLib.dump")
}
}
dir("java-library") {
buildGradleKts {
resolve("examples/gradle/base/androidJavaLibrary.gradle.kts")
}
java("JavaLib.java") {
resolve("examples/classes/JavaLib.java")
}
apiFile(projectName = "java-library") {
resolve("examples/classes/JavaLib.dump")
}
}
}

private fun initLocalProperties() {
val home = System.getenv("ANDROID_HOME") ?: System.getenv("HOME")
File(rootProjectDir, "local.properties").apply {
writeText("sdk.dir=$home/Android/Sdk")
}
}

// We do not have ANDROID_HOME on CI, and this functionality is not critical, so we are disabling these
// tests on CI
private fun assumeHasAndroid() {
Assume.assumeFalse(System.getenv("ANDROID_HOME").isNullOrEmpty())
}
}
12 changes: 12 additions & 0 deletions src/functionalTest/resources/examples/classes/JavaLib.dump
@@ -0,0 +1,12 @@
public final class examples/classes/JavaLib {
public fun <init> ()V
public fun foo ()Ljava/lang/String;
}

public final class org/jetbrains/kotlinx/android/java/library/BuildConfig {
public static final field BUILD_TYPE Ljava/lang/String;
public static final field DEBUG Z
public static final field LIBRARY_PACKAGE_NAME Ljava/lang/String;
public fun <init> ()V
}

18 changes: 18 additions & 0 deletions src/functionalTest/resources/examples/classes/JavaLib.java
@@ -0,0 +1,18 @@
/*
* Copyright 2016-2022 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
*/

package examples.classes;

public final class JavaLib {

public String foo() {
return "foo";
}

private String bar() {
return "bar";
}

}
12 changes: 12 additions & 0 deletions src/functionalTest/resources/examples/classes/KotlinLib.dump
@@ -0,0 +1,12 @@
public final class examples/classes/KotlinLib {
public fun <init> ()V
public final fun foo ()Ljava/lang/String;
}

public final class org/jetbrains/kotlinx/android/kotlin/library/BuildConfig {
public static final field BUILD_TYPE Ljava/lang/String;
public static final field DEBUG Z
public static final field LIBRARY_PACKAGE_NAME Ljava/lang/String;
public fun <init> ()V
}

13 changes: 13 additions & 0 deletions src/functionalTest/resources/examples/classes/KotlinLib.kt
@@ -0,0 +1,13 @@
/*
* Copyright 2016-2022 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
*/

package examples.classes

class KotlinLib {

fun foo(): String = "foo"
internal fun bar(): String = "bar"

}
@@ -0,0 +1,39 @@
/*
* Copyright 2016-2022 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
*/

plugins {
id("com.android.library")
id("org.jetbrains.kotlinx.binary-compatibility-validator")
}

android {

namespace = "org.jetbrains.kotlinx.android.java.library"

compileSdk = 32

defaultConfig {
minSdk = 31
targetSdk = 32

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}

buildTypes {
release {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}

}

dependencies {
// no dependencies required
}
@@ -0,0 +1,40 @@
/*
* Copyright 2016-2022 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
*/

plugins {
id("com.android.library")
id("kotlin-android")
id("org.jetbrains.kotlinx.binary-compatibility-validator")
}

android {

namespace = "org.jetbrains.kotlinx.android.kotlin.library"

compileSdk = 32

defaultConfig {
minSdk = 31
targetSdk = 32

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}

buildTypes {
release {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}

}

dependencies {
// no dependencies required
}
@@ -0,0 +1,10 @@
plugins {
id("com.android.application").version("7.2.2").apply(false)
id("com.android.library").version("7.2.2").apply(false)
id("org.jetbrains.kotlin.android").version("1.7.10").apply(false)
id("org.jetbrains.kotlinx.binary-compatibility-validator").apply(false)
}

tasks.register("clean", Delete::class) {
delete(rootProject.buildDir)
}
@@ -0,0 +1,20 @@
pluginManagement {
repositories {
mavenLocal()
gradlePluginPortal()
google()
mavenCentral()
}
}

dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}

rootProject.name = "android-project"
include(":kotlin-library")
include(":java-library")