From e9bda99dfd94565ee17810435d49070711807fa1 Mon Sep 17 00:00:00 2001 From: Peter Trifanov Date: Thu, 10 Dec 2020 16:17:21 +0300 Subject: [PATCH] Bugfix for diktat-gradle-plugin, introduced functional tests (#628) ### What's done: * Introduced functional tests for diktat-gradle-plugin * Respect skipTests in diktat-gradle-plugin build * Do not use quotes in patterns * Run gradle daemon in CI builds because gradle is invoked several times from maven * Jacoco test coverage in functionalTest * Updated gradle to 6.7.1 --- .github/workflows/build_and_test.yml | 3 - diktat-gradle-plugin/build.gradle.kts | 45 ++++++-- .../gradle/wrapper/gradle-wrapper.properties | 2 +- diktat-gradle-plugin/pom.xml | 21 +++- .../DiktatGradlePluginFunctionalTest.kt | 101 ++++++++++++++++++ .../plugin/gradle/DiktatJavaExecTaskBase.kt | 4 +- .../plugin/gradle/DiktatJavaExecTaskTest.kt | 10 +- 7 files changed, 165 insertions(+), 21 deletions(-) create mode 100644 diktat-gradle-plugin/src/functionalTest/kotlin/org/cqfn/diktat/plugin/gradle/DiktatGradlePluginFunctionalTest.kt diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 9dafb60c08..ad8a117897 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -3,9 +3,6 @@ name: Build and test on: pull_request -env: - GRADLE_OPTS: -Dorg.gradle.daemon=false - jobs: test: name: Unit Test diff --git a/diktat-gradle-plugin/build.gradle.kts b/diktat-gradle-plugin/build.gradle.kts index 6d75f03456..4c855f2e9a 100644 --- a/diktat-gradle-plugin/build.gradle.kts +++ b/diktat-gradle-plugin/build.gradle.kts @@ -1,9 +1,11 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.getCurrentOperatingSystem plugins { `java-gradle-plugin` kotlin("jvm") version "1.4.20" jacoco + id("pl.droidsonroids.jacoco.testkit") version "1.0.7" } repositories { @@ -39,7 +41,8 @@ val generateVersionsFile by tasks.registering { doFirst { versionsFile.parentFile.mkdirs() - versionsFile.writeText(""" + versionsFile.writeText( + """ package generated internal const val DIKTAT_VERSION = "$diktatVersion" @@ -75,19 +78,45 @@ java { withSourcesJar() } -// === testing & code coverage, consistent with maven +// === testing & code coverage, jacoco is run independent from maven +val functionalTestTask by tasks.register("functionalTest") +val jacocoMergeTask by tasks.register("jacocoMerge") tasks.withType { useJUnitPlatform() - extensions.configure(JacocoTaskExtension::class) { - setDestinationFile(file("target/jacoco.exec")) - } } +// === integration testing +// fixme: should probably use KotlinSourceSet instead +val functionalTest = sourceSets.create("functionalTest") { + compileClasspath += sourceSets.main.get().output + configurations.testRuntimeClasspath + runtimeClasspath += output + compileClasspath +} +tasks.getByName("functionalTest") { + dependsOn("test") + testClassesDirs = functionalTest.output.classesDirs + classpath = functionalTest.runtimeClasspath + doLast { + if (getCurrentOperatingSystem().isWindows) { + // workaround for https://github.com/koral--/jacoco-gradle-testkit-plugin/issues/9 + logger.lifecycle("Sleeping for 5 sec after functionalTest to avoid error with file locking") + Thread.sleep(5_000) + } + } + finalizedBy(jacocoMergeTask) +} +tasks.check { dependsOn(tasks.jacocoTestReport) } +jacocoTestKit { + applyTo("functionalTestRuntimeOnly", tasks.named("functionalTest")) +} +tasks.getByName("jacocoMerge", JacocoMerge::class) { + dependsOn(functionalTestTask) + executionData(tasks.test, functionalTestTask) +} tasks.jacocoTestReport { - dependsOn(tasks.test) + dependsOn(jacocoMergeTask) + executionData("$buildDir/jacoco/jacocoMerge.exec") reports { // xml report is used by codecov xml.isEnabled = true - xml.destination = file("target/site/jacoco/jacoco.xml") } -} +} \ No newline at end of file diff --git a/diktat-gradle-plugin/gradle/wrapper/gradle-wrapper.properties b/diktat-gradle-plugin/gradle/wrapper/gradle-wrapper.properties index be52383ef4..4d9ca16491 100644 --- a/diktat-gradle-plugin/gradle/wrapper/gradle-wrapper.properties +++ b/diktat-gradle-plugin/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/diktat-gradle-plugin/pom.xml b/diktat-gradle-plugin/pom.xml index bc804153c6..781a7a1312 100644 --- a/diktat-gradle-plugin/pom.xml +++ b/diktat-gradle-plugin/pom.xml @@ -18,6 +18,9 @@ build build false + false + + @@ -69,7 +72,7 @@ ${gradle.executable} clean - jacocoTestReport + test -Pgroup=${project.groupId} -Pversion=${project.version} -Pdescription=${project.description} @@ -77,7 +80,7 @@ -PjunitVersion=${junit.version} -S - ${skip.gradle.build} + ${skip.gradle.test} exec @@ -96,6 +99,7 @@ -PktlintVersion=${ktlint.version} -PjunitVersion=${junit.version} -S + ${gradle.exclude.check} ${skip.gradle.build} @@ -185,5 +189,18 @@ ${project.basedir}/gradlew.bat + + skip-gradle-tests + + + skipTests + true + + + + -xcheck + true + + \ No newline at end of file diff --git a/diktat-gradle-plugin/src/functionalTest/kotlin/org/cqfn/diktat/plugin/gradle/DiktatGradlePluginFunctionalTest.kt b/diktat-gradle-plugin/src/functionalTest/kotlin/org/cqfn/diktat/plugin/gradle/DiktatGradlePluginFunctionalTest.kt new file mode 100644 index 0000000000..595bd9720d --- /dev/null +++ b/diktat-gradle-plugin/src/functionalTest/kotlin/org/cqfn/diktat/plugin/gradle/DiktatGradlePluginFunctionalTest.kt @@ -0,0 +1,101 @@ +package org.cqfn.diktat.plugin.gradle + +import org.cqfn.diktat.plugin.gradle.DiktatGradlePlugin.Companion.DIKTAT_CHECK_TASK +import org.gradle.internal.impldep.org.junit.rules.TemporaryFolder +import org.gradle.testkit.runner.GradleRunner +import org.gradle.testkit.runner.TaskOutcome +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import java.io.File + +class DiktatGradlePluginFunctionalTest { + private val testProjectDir = TemporaryFolder() + private lateinit var buildFile: File + + @BeforeEach + fun setUp() { + testProjectDir.create() + File("../examples/gradle-kotlin-dsl").copyRecursively(testProjectDir.root) + File(testProjectDir.root, "build.gradle.kts").delete() + buildFile = testProjectDir.newFile("build.gradle.kts").apply { + writeText( + """ + plugins { + id("org.cqfn.diktat.diktat-gradle-plugin") + } + + repositories { + mavenLocal() + mavenCentral() + } + """.trimIndent() + ) + } + } + + @AfterEach + fun tearDown() { + testProjectDir.delete() + } + + @Test + fun `should execute diktatCheck on default values`() { + val result = runDiktat() + + val diktatCheckBuildResult = result.task(":$DIKTAT_CHECK_TASK") + requireNotNull(diktatCheckBuildResult) + Assertions.assertEquals(TaskOutcome.FAILED, diktatCheckBuildResult.outcome) + Assertions.assertTrue( + result.output.contains("[HEADER_MISSING_OR_WRONG_COPYRIGHT]") + ) + } + + @Test + fun `should execute diktatCheck with explicit inputs`() { + buildFile.appendText( + """${System.lineSeparator()} + diktat { + inputs = files("src/**/*.kt") + } + """.trimIndent() + ) + val result = runDiktat() + + val diktatCheckBuildResult = result.task(":$DIKTAT_CHECK_TASK") + requireNotNull(diktatCheckBuildResult) + Assertions.assertEquals(TaskOutcome.FAILED, diktatCheckBuildResult.outcome) + Assertions.assertTrue( + result.output.contains("[HEADER_MISSING_OR_WRONG_COPYRIGHT]") + ) + } + + private fun runDiktat() = GradleRunner.create() + .withProjectDir(testProjectDir.root) + .withArguments(DIKTAT_CHECK_TASK) + .withPluginClasspath() + .withJaCoCo() + .forwardOutput() + .runCatching { + buildAndFail() + } + .also { + require(it.isSuccess) { "Running gradle returned exception ${it.exceptionOrNull()}" } + } + .getOrNull()!! + + /** + * This is support for jacoco reports in tests run with gradle TestKit + */ + private fun GradleRunner.withJaCoCo() = apply { + javaClass.classLoader + .getResourceAsStream("testkit-gradle.properties") + .also { it ?: println("properties file for testkit is not available, check build configuration") } + ?.use { propertiesFileStream -> + File(projectDir, "gradle.properties").outputStream().use { + propertiesFileStream.copyTo(it) + } + } + } +} diff --git a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskBase.kt b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskBase.kt index 9eb2cc3afa..b957052117 100644 --- a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskBase.kt +++ b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskBase.kt @@ -68,10 +68,10 @@ open class DiktatJavaExecTaskBase @Inject constructor( } .files .forEach { - add("\"${it.path}\"") + add(it.path) } diktatExtension.excludes?.files?.forEach { - add("\"!${it.path}\"") + add(it.path) } } logger.debug("Setting JavaExec args to $args") diff --git a/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskTest.kt b/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskTest.kt index 6c976f80b2..2debadc173 100644 --- a/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskTest.kt +++ b/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskTest.kt @@ -19,7 +19,7 @@ class DiktatJavaExecTaskTest { @Test fun `check command line for various inputs`() { assertCommandLineEquals( - listOf(null, "\"${combinePathParts("src", "**", "*.kt")}\""), + listOf(null, combinePathParts("src", "**", "*.kt")), DiktatExtension().apply { inputs = project.files("src/**/*.kt") } @@ -29,7 +29,7 @@ class DiktatJavaExecTaskTest { @Test fun `check command line in debug mode`() { assertCommandLineEquals( - listOf(null, "--debug", "\"${combinePathParts("src", "**", "*.kt")}\""), + listOf(null, "--debug", combinePathParts("src", "**", "*.kt")), DiktatExtension().apply { inputs = project.files("src/**/*.kt") debug = true @@ -40,8 +40,8 @@ class DiktatJavaExecTaskTest { @Test fun `check command line with excludes`() { assertCommandLineEquals( - listOf(null, "\"${combinePathParts("src", "**", "*.kt")}\"", - "\"!${combinePathParts("src", "main", "kotlin", "generated")}\"" + listOf(null, combinePathParts("src", "**", "*.kt"), + combinePathParts("src", "main", "kotlin", "generated") ), DiktatExtension().apply { inputs = project.files("src/**/*.kt") @@ -70,6 +70,6 @@ class DiktatJavaExecTaskTest { Assertions.assertIterableEquals(expected, task.commandLine) } - private fun combinePathParts(vararg parts: String) = project.projectDir.absolutePath + + private fun combinePathParts(vararg parts: String) = project.rootDir.absolutePath + parts.joinToString(File.separator, prefix = File.separator) }