From 7ccc0f5e9d6539cbbe2b38c2b7c85007762927ac Mon Sep 17 00:00:00 2001 From: Goooler Date: Sun, 16 Aug 2026 13:03:53 +0800 Subject: [PATCH 1/7] Combine testSuite + class --- CONTRIBUTING.md | 12 +- build.gradle.kts | 12 +- gradle/libs.versions.toml | 6 +- .../plugins/shadow/DocCodeSnippetTest.kt | 53 +++-- .../plugins/shadow/ApplicationPluginTest.kt | 21 +- .../gradle/plugins/shadow/BasePluginTest.kt | 144 ++++++-------- .../gradle/plugins/shadow/CachingTest.kt | 26 +-- .../gradle/plugins/shadow/FilteringTest.kt | 40 ++-- .../shadow/FindResourceInClasspathTest.kt | 10 +- .../gradle/plugins/shadow/JavaPluginsTest.kt | 145 +++++++------- .../plugins/shadow/KotlinPluginsTest.kt | 51 +++-- .../gradle/plugins/shadow/MinimizeTest.kt | 41 ++-- .../gradle/plugins/shadow/PublishingTest.kt | 47 +++-- .../gradle/plugins/shadow/RelocationTest.kt | 116 +++++++---- .../transformers/AppendingTransformerTest.kt | 10 +- .../transformers/BaseTransformerTest.kt | 6 +- .../GroovyExtensionModuleTransformerTest.kt | 12 +- .../PropertiesFileTransformerTest.kt | 10 +- .../ServiceFileTransformerTest.kt | 93 ++++----- .../shadow/transformers/TransformersTest.kt | 17 +- .../plugins/shadow/ShadowPropertiesTest.kt | 31 ++- .../shadow/internal/BytecodeRemappingTest.kt | 39 +--- .../internal/DefaultDependencyFilterTest.kt | 89 +++++---- .../internal/DuplicatesStrategyCheckerTest.kt | 14 +- .../shadow/internal/MinimizeSpecsTest.kt | 15 +- .../shadow/internal/R8MinimizerTest.kt | 16 +- .../internal/ReproduciblePropertiesTest.kt | 38 ++-- .../shadow/internal/ZipEntryValidationTest.kt | 20 +- .../shadow/relocation/RelocatorsTest.kt | 70 +++---- .../shadow/relocation/SimpleRelocatorTest.kt | 28 +-- .../ApacheLicenseResourceTransformerTest.kt | 11 +- .../ApacheNoticeResourceTransformerTest.kt | 16 +- .../transformers/AppendingTransformerTest.kt | 12 +- .../transformers/BaseTransformerTest.kt | 21 +- .../ComponentsXmlResourceTransformerTest.kt | 10 +- .../DeduplicatingResourceTransformerTest.kt | 27 ++- .../GroovyExtensionModuleTransformerTest.kt | 29 ++- .../KotlinModuleMetadataTransformerTest.kt | 14 +- .../Log4j2PluginsCacheFileTransformerTest.kt | 43 +++-- .../ManifestAppenderTransformerTest.kt | 13 +- .../MergeLicenseResourceTransformerTest.kt | 17 +- ...eserveFirstFoundResourceTransformerTest.kt | 12 +- .../PropertiesFileTransformerTest.kt | 182 ++++++++++++------ .../ServiceFileTransformerTest.kt | 97 +++------- .../XmlAppendingTransformerTest.kt | 16 +- .../plugins/shadow/testkit/TestSuiteScope.kt | 111 +++++++++++ 46 files changed, 986 insertions(+), 877 deletions(-) create mode 100644 src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/TestSuiteScope.kt diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 30b5f19a8..61d015c9a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -29,12 +29,18 @@ Shadow has multiple test suites to ensure code quality: #### Running Specific Tests -To speed up local development, you can run specific test classes or methods: +To speed up local development, you can run specific test suites or individual tests: -- Run a specific unit test: `./gradlew test --tests "com.example.YourTestClass"` -- Run functional tests against a specific Gradle version: `./gradlew functionalTest -PtestGradleVersion=9.1.0` (useful +- **Run a specific test suite**: `./gradlew test --tests "*ShadowPropertiesTest*"` +- **Run an individual test within a suite**: TestBalloon uses the `↘` hierarchical separator instead of the standard `Class.method` format: + - `./gradlew functionalTest --tests "*CachingTest*↘disableCacheIfAnyTransformerIsNotCacheable"` + - `./gradlew documentTest --tests "*DocCodeSnippetTest*↘*groovy*"` +- **Run functional tests against a specific Gradle version**: `./gradlew functionalTest -PtestGradleVersion=9.1.0` (useful to verify compatibility locally with the minimum or a custom Gradle version) +> [!NOTE] +> When running individual tests via IntelliJ IDEA run configurations, if `--tests` filtering encounters issues, you can set the `TESTBALLOON_INCLUDE_PATTERNS` environment variable instead (e.g. `TESTBALLOON_INCLUDE_PATTERNS="*CachingTest*↘disableCacheIfAnyTransformerIsNotCacheable"`). + Make sure all tests pass before submitting your changes. ### API Compatibility diff --git a/build.gradle.kts b/build.gradle.kts index c34ad4623..9295d3fa3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -21,6 +21,7 @@ plugins { alias(libs.plugins.pluginPublish) alias(libs.plugins.spotless) alias(libs.plugins.buildConfig) + alias(libs.plugins.testBalloon) } version = providers.gradleProperty("VERSION_NAME").get() @@ -137,6 +138,7 @@ dependencies { testKitImplementation(gradleTestKit()) testKitImplementation(libs.assertk) + testKitImplementation(libs.testBalloon.framework.core) testPluginClasspath(libs.foojayResolver) testPluginClasspath(libs.pluginPublish) @@ -153,14 +155,6 @@ testing.suites { register("documentTest") { targets.configureEach { testTask { - systemProperty("junit.jupiter.execution.parallel.enabled", "true") - systemProperty("junit.jupiter.execution.parallel.mode.default", "concurrent") - systemProperty("junit.jupiter.execution.parallel.config.strategy", "fixed") - // Each snippet runs a nested Gradle build. Two-way parallelism performed better than - // four-way by avoiding excessive CPU, memory, and disk contention. - systemProperty("junit.jupiter.execution.parallel.config.fixed.parallelism", "2") - systemProperty("junit.jupiter.execution.parallel.config.fixed.max-pool-size", "2") - inputs.files( fileTree(docsDir) { // Changelog file doesn't contain code snippet to run. @@ -201,10 +195,10 @@ testing.suites { } withType().configureEach { - useJUnitJupiter(libs.junit.bom.map { checkNotNull(it.version) }) dependencies { implementation(testKit.get().output) implementation(libs.assertk) + implementation(libs.testBalloon.framework.core) } targets.configureEach { testTask { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index aedbd8ab6..ab380970b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,6 +3,8 @@ minGradle = "9.4.0" kotlin = "2.4.10" moshi = "1.15.2" pluginPublish = "2.1.1" +testBalloon = "1.1.0-RC" + [libraries] apache-ant = "org.apache.ant:ant:1.10.17" @@ -28,8 +30,9 @@ androidx-gradlePluginLints = "androidx.lint:lint-gradle:1.0.0" ktfmt = "com.facebook:ktfmt:0.64" r8 = "com.android.tools:r8:9.4.14" -junit-bom = "org.junit:junit-bom:6.1.3" assertk = "com.willowtreeapps.assertk:assertk:0.28.1" +testBalloon-framework-core = { module = "de.infix.testBalloon:testBalloon-framework-core", version.ref = "testBalloon" } + [plugins] kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } @@ -39,3 +42,4 @@ mavenPublish = "com.vanniktech.maven.publish:0.37.0" pluginPublish = { id = "com.gradle.plugin-publish", version.ref = "pluginPublish" } spotless = "com.diffplug.spotless:8.9.0" buildConfig = "com.github.gmazzo.buildconfig:6.0.10" +testBalloon = { id = "de.infix.testBalloon", version.ref = "testBalloon" } diff --git a/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/DocCodeSnippetTest.kt b/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/DocCodeSnippetTest.kt index 08a9c6ae3..556bcdd99 100644 --- a/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/DocCodeSnippetTest.kt +++ b/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/DocCodeSnippetTest.kt @@ -1,34 +1,33 @@ package com.github.jengelman.gradle.plugins.shadow -import java.nio.file.Path -import org.junit.jupiter.api.Named.named -import org.junit.jupiter.api.io.TempDir -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.Arguments -import org.junit.jupiter.params.provider.Arguments.arguments -import org.junit.jupiter.params.provider.MethodSource +import com.github.jengelman.gradle.plugins.shadow.testkit.tempDirFixture +import de.infix.testBalloon.framework.core.TestConfig +import de.infix.testBalloon.framework.core.coroutineContext +import de.infix.testBalloon.framework.core.invocation +import de.infix.testBalloon.framework.core.testScope +import de.infix.testBalloon.framework.core.testSuite +import kotlinx.coroutines.Dispatchers -class DocCodeSnippetTest { +val DocCodeSnippetTest by + testSuite( + testConfig = + TestConfig.invocation(TestConfig.Invocation.Concurrent) + // Each snippet runs a nested Gradle build. Two-way parallelism performed better than + // four-way by avoiding excessive CPU, memory, and disk contention. + .coroutineContext(Dispatchers.Default.limitedParallelism(2)) + .testScope(isEnabled = false) + ) { + val langExecutables = DslLang.entries.map(DslLang::extractCodeSnippets) - @ParameterizedTest(name = "{0}") - @MethodSource("snippets") - fun test(executable: SnippetExecutable, @TempDir tempDir: Path) { - executable.execute(tempDir) - } - - private companion object { - @JvmStatic - fun snippets(): List { - val langExecutables = DslLang.entries.map(DslLang::extractCodeSnippets) - - check(langExecutables.sumOf { it.size } > 0) { "No code snippets found." } - check(langExecutables.map { it.size }.distinct().size == 1) { - "All languages must have the same number of code snippets." - } + check(langExecutables.sumOf { it.size } > 0) { "No code snippets found." } + check(langExecutables.map { it.size }.distinct().size == 1) { + "All languages must have the same number of code snippets." + } - return langExecutables.flatten().map { executable -> - arguments(named(executable.displayName, executable)) + tempDirFixture() asParameterForEach + { + for (executable in langExecutables.flatten()) { + test(executable.displayName) { testDir -> executable.execute(testDir) } + } } - } } -} diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/ApplicationPluginTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/ApplicationPluginTest.kt index f1716cb88..f64e016ac 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/ApplicationPluginTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/ApplicationPluginTest.kt @@ -13,8 +13,10 @@ import com.github.jengelman.gradle.plugins.shadow.testkit.JarPath import com.github.jengelman.gradle.plugins.shadow.testkit.containsAtLeast import com.github.jengelman.gradle.plugins.shadow.testkit.getContent import com.github.jengelman.gradle.plugins.shadow.testkit.getMainAttr +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.util.isWindows import com.github.jengelman.gradle.plugins.shadow.util.runProcess +import de.infix.testBalloon.framework.core.testSuite import java.nio.file.Path import java.util.zip.ZipFile import kotlin.io.path.appendText @@ -24,12 +26,14 @@ import kotlin.io.path.readText import kotlin.io.path.relativeTo import kotlin.io.path.walk import kotlin.io.path.writeText -import org.junit.jupiter.api.Test -class ApplicationPluginTest : BasePluginTest() { +val ApplicationPluginTests by testSuite { + runTests(::ApplicationPluginTest) +} + +private class ApplicationPluginTest : BasePluginTest() { private lateinit var mainClass: String - @Test fun integrationWithApplicationPluginAndJavaToolchains() { prepare( mainClassWithImports = true, @@ -67,7 +71,6 @@ class ApplicationPluginTest : BasePluginTest() { ) } - @Test fun installShadowOutputs() { prepare( mainClassWithImports = true, @@ -116,7 +119,6 @@ class ApplicationPluginTest : BasePluginTest() { .contains("Hello, World! (bar) from Main", "Refs: junit.framework.Test") } - @Test fun installShadowDoesNotExecuteDependentShadowTask() { prepare() @@ -125,7 +127,7 @@ class ApplicationPluginTest : BasePluginTest() { commonAssertions(jarPath("build/install/myapp-shadow/lib/myapp-1.0-all.jar")) } - @Test // #613 + // #613 fun overrideMainClassAttrInManifestBlock() { val main2ClassEntry = writeClass(className = "Main2") prepare( @@ -170,7 +172,6 @@ class ApplicationPluginTest : BasePluginTest() { assertions(result.output, "bar") } - @Test fun overrideMainClassFromApplicationPlugin() { prepare() projectScript.appendText( @@ -189,7 +190,6 @@ class ApplicationPluginTest : BasePluginTest() { } } - @Test fun errorWhenMainClassNotSet() { prepare(mainClassBlock = "") @@ -198,7 +198,6 @@ class ApplicationPluginTest : BasePluginTest() { assertThat(result.output).contains("no main manifest attribute, in") } - @Test fun addExtraFilesIntoDistribution() { path("extra/echo.sh").writeText("echo 'Hello, World!'") path("some/dir/hello.txt").writeText("'Hello, World!'") @@ -239,7 +238,6 @@ class ApplicationPluginTest : BasePluginTest() { } } - @Test fun includeSrcDistByDefault() { path("src/dist/echo.sh").writeText("echo 'Hello, World!'") prepare() @@ -260,7 +258,6 @@ class ApplicationPluginTest : BasePluginTest() { } } - @Test fun honorApplicationExtensionProperties() { val applicationNames = "new" to "new" val executableDirs = "sbin" to "sbin" @@ -344,7 +341,7 @@ class ApplicationPluginTest : BasePluginTest() { } } - private companion object { + companion object { fun Path.walkEntries(includeDirs: Boolean = false): Sequence = walk() .filter { includeDirs || it.isRegularFile() } diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/BasePluginTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/BasePluginTest.kt index 0e11c26f4..40aee9183 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/BasePluginTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/BasePluginTest.kt @@ -36,29 +36,66 @@ import kotlin.io.path.writeText import org.gradle.testkit.runner.BuildResult import org.gradle.testkit.runner.GradleRunner import org.gradle.testkit.runner.TaskOutcome -import org.junit.jupiter.api.AfterAll -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.BeforeAll -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.TestInstance -import org.junit.jupiter.api.io.TempDir import org.vafer.jdeb.shaded.objectweb.asm.ClassWriter import org.vafer.jdeb.shaded.objectweb.asm.Opcodes -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -abstract class BasePluginTest { - @TempDir - lateinit var projectRoot: Path - private set - - lateinit var localRepo: AppendableMavenRepository - private set - - lateinit var artifactAJar: Path - private set +val sharedLocalRepo: AppendableMavenRepository by lazy { + val repoTempDir = createTempDirectory() + val repoRoot = repoTempDir.resolve("local-maven-repo").createDirectories() + Runtime.getRuntime() + .addShutdownHook( + Thread { + @OptIn(ExperimentalPathApi::class) repoTempDir.deleteRecursively() + } + ) + AppendableMavenRepository(root = repoRoot) + .apply { + jarModule("junit", "junit", "3.8.2") { useJar(BasePluginTest.junitJar) } + val a = + jarModule("my", "a", "1.0") { + buildJar { + insert("a.properties", "a") + insert("a2.properties", "a2") + } + } + val b = jarModule("my", "b", "1.0") { buildJar { insert("b.properties", "b") } } + val c = jarModule("my", "c", "1.0") { buildJar { insert("c.properties", "c") } } + val d = + jarModule("my", "d", "1.0") { + buildJar { insert("d.properties", "d") } + // Depends on c but c does not depend on d. + addDependency(c) + } + val e = + jarModule("my", "e", "1.0") { + buildJar { insert("e.properties", "e") } + // Circular dependency with f. + addDependency("my:f:1.0") + } + val f = + jarModule("my", "f", "1.0") { + buildJar { insert("f.properties", "f") } + // Circular dependency with e. + addDependency(e) + } + bomModule("my", "bom", "1.0") { + addDependency(a) + addDependency(b) + addDependency(c) + addDependency(d) + addDependency(e) + addDependency(f) + } + } + .also { it.publish() } +} - lateinit var artifactBJar: Path - private set +abstract class BasePluginTest( + val projectRoot: Path = createTempDirectory(), + val localRepo: AppendableMavenRepository = sharedLocalRepo, +) { + val artifactAJar: Path = localRepo.root.resolve("my/a/1.0/a-1.0.jar") + val artifactBJar: Path = localRepo.root.resolve("my/b/1.0/b-1.0.jar") val projectScript: Path get() = path("build.gradle") @@ -75,72 +112,11 @@ abstract class BasePluginTest { val outputServerShadowedJar: JarPath get() = jarPath("server/build/libs/server-1.0-all.jar") - @BeforeAll - fun beforeAll() { - localRepo = - AppendableMavenRepository( - root = createTempDirectory().resolve("local-maven-repo").createDirectories() - ) - .apply { - jarModule("junit", "junit", "3.8.2") { useJar(junitJar) } - val a = - jarModule("my", "a", "1.0") { - buildJar { - insert("a.properties", "a") - insert("a2.properties", "a2") - } - } - val b = jarModule("my", "b", "1.0") { buildJar { insert("b.properties", "b") } } - val c = jarModule("my", "c", "1.0") { buildJar { insert("c.properties", "c") } } - val d = - jarModule("my", "d", "1.0") { - buildJar { insert("d.properties", "d") } - // Depends on c but c does not depend on d. - addDependency(c) - } - val e = - jarModule("my", "e", "1.0") { - buildJar { insert("e.properties", "e") } - // Circular dependency with f. - addDependency("my:f:1.0") - } - val f = - jarModule("my", "f", "1.0") { - buildJar { insert("f.properties", "f") } - // Circular dependency with e. - addDependency(e) - } - bomModule("my", "bom", "1.0") { - addDependency(a) - addDependency(b) - addDependency(c) - addDependency(d) - addDependency(e) - addDependency(f) - } - } - localRepo.publish() - - artifactAJar = path("my/a/1.0/a-1.0.jar", parent = localRepo.root) - artifactBJar = path("my/b/1.0/b-1.0.jar", parent = localRepo.root) - } - - @BeforeEach - open fun beforeEach() { + init { projectScript.writeText(getDefaultProjectBuildScript()) settingsScript.writeText(getDefaultSettingsBuildScript()) } - @AfterEach - fun afterEach() { - println(projectScript.readText()) - } - - @AfterAll - fun afterAll() { - @OptIn(ExperimentalPathApi::class) localRepo.root.deleteRecursively() - } - fun getDefaultProjectBuildScript( plugin: String = "java", withGroup: Boolean = true, @@ -164,9 +140,9 @@ abstract class BasePluginTest { fun getDefaultSettingsBuildScript( startBlock: String = "", // Use a test-specific build cache directory. This ensures that we'll only use cached outputs - // generated during - // this test, and we won't accidentally use cached outputs from a different test or a different - // build. + // generated during this test, and we won't accidentally use cached outputs from a different + // test + // or a different build. // https://docs.gradle.org/current/userguide/build_cache.html#sec:build_cache_configure_local buildCacheBlock: String = "local { directory = file('build-cache') }", endBlock: String = "rootProject.name = 'my'", diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/CachingTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/CachingTest.kt index 08a5bfc61..db13d9a2d 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/CachingTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/CachingTest.kt @@ -8,8 +8,10 @@ import com.github.jengelman.gradle.plugins.shadow.internal.mainClassAttributeKey import com.github.jengelman.gradle.plugins.shadow.testkit.JarPath import com.github.jengelman.gradle.plugins.shadow.testkit.containsOnly import com.github.jengelman.gradle.plugins.shadow.testkit.getMainAttr +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.transformers.ResourceTransformer import com.github.jengelman.gradle.plugins.shadow.transformers.ServiceFileTransformer +import de.infix.testBalloon.framework.core.testSuite import kotlin.io.path.appendText import kotlin.io.path.isDirectory import kotlin.io.path.name @@ -18,12 +20,14 @@ import kotlin.io.path.walk import kotlin.io.path.writeText import org.gradle.api.file.DuplicatesStrategy import org.gradle.testkit.runner.TaskOutcome -import org.junit.jupiter.api.Test -class CachingTest : BasePluginTest() { +val CachingTests by testSuite { + runTests(::CachingTest) +} + +private class CachingTest : BasePluginTest() { private var taskPath: String = shadowJarPath - @Test fun dependenciesChanged() { projectScript.appendText( """ @@ -43,7 +47,6 @@ class CachingTest : BasePluginTest() { assertCompositeExecutions { containsOnly(*entriesInA, *manifestEntries) } } - @Test fun outputFileChanged() { projectScript.appendText( """ @@ -72,7 +75,6 @@ class CachingTest : BasePluginTest() { } } - @Test fun duplicatesStrategyChanged() { listOf(DuplicatesStrategy.EXCLUDE, DuplicatesStrategy.INCLUDE, DuplicatesStrategy.WARN) .forEach { strategy -> @@ -90,7 +92,6 @@ class CachingTest : BasePluginTest() { } } - @Test fun manifestAttrsChanged() { projectScript.appendText( """ @@ -133,7 +134,6 @@ class CachingTest : BasePluginTest() { assertions("Foo3", "Bar3") } - @Test fun kotlinMainRunChanged() { val mainClassName = "my.Main" val main2ClassName = "my.Main2" @@ -158,7 +158,6 @@ class CachingTest : BasePluginTest() { assertCompositeExecutions { getMainAttr(mainClassAttributeKey).isEqualTo(main2ClassName) } } - @Test fun applicationChanged() { val mainClassName = "my.Main" val main2ClassName = "my.Main2" @@ -181,7 +180,7 @@ class CachingTest : BasePluginTest() { assertCompositeExecutions { getMainAttr(mainClassAttributeKey).isEqualTo(main2ClassName) } } - @Test // #717 + // #717 fun jarIncludesExcludesChanged() { val mainClassEntry = writeClass(className = "Main") val main2ClassEntry = writeClass(className = "Main2") @@ -240,7 +239,6 @@ class CachingTest : BasePluginTest() { } } - @Test fun dependenciesIncludesExcludesChanged() { val mainClassEntry = writeClass(withImports = true) projectScript.appendText( @@ -270,7 +268,6 @@ class CachingTest : BasePluginTest() { assertCompositeExecutions { containsOnly("my/", mainClassEntry, *manifestEntries) } } - @Test fun minimizeChanged() { taskPath = serverShadowJarPath @@ -312,7 +309,6 @@ class CachingTest : BasePluginTest() { } } - @Test fun r8KeepRuleFileChanged() { val previousTaskPath = taskPath taskPath = serverShadowJarPath @@ -352,7 +348,6 @@ class CachingTest : BasePluginTest() { } } - @Test fun r8ClasspathRuleChanged() { val previousTaskPath = taskPath taskPath = serverShadowJarPath @@ -394,7 +389,6 @@ class CachingTest : BasePluginTest() { } } - @Test fun relocatorChanged() { projectScript.appendText( """ @@ -426,7 +420,7 @@ class CachingTest : BasePluginTest() { } } - @Test // #1932 + // #1932 fun relocatorPatternChanged() { projectScript.appendText( """ @@ -458,7 +452,6 @@ class CachingTest : BasePluginTest() { } } - @Test fun serviceFileTransformerPropsChanged() { val mainClassEntry = writeClass() val assertions = { @@ -485,7 +478,6 @@ class CachingTest : BasePluginTest() { assertions() } - @Test fun disableCacheIfAnyTransformerIsNotCacheable() { projectScript.appendText( """ diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/FilteringTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/FilteringTest.kt index ccb6fbad8..72f82d789 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/FilteringTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/FilteringTest.kt @@ -2,17 +2,27 @@ package com.github.jengelman.gradle.plugins.shadow import assertk.assertThat import com.github.jengelman.gradle.plugins.shadow.testkit.containsOnly +import com.github.jengelman.gradle.plugins.shadow.testkit.runTest +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests +import de.infix.testBalloon.framework.core.testSuite import kotlin.io.path.appendText import kotlin.io.path.writeText -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.ValueSource - -class FilteringTest : BasePluginTest() { - @BeforeEach - override fun beforeEach() { - super.beforeEach() + +val FilteringTests by testSuite { + runTests(::FilteringTest) + + for (useAccessor in listOf(false, true)) { + runTest("excludeDependency_useAccessor_$useAccessor", ::FilteringTest) { + excludeDependency(useAccessor) + } + runTest("filterProjectDependencies_useAccessor_$useAccessor", ::FilteringTest) { + filterProjectDependencies(useAccessor) + } + } +} + +private class FilteringTest : BasePluginTest() { + init { projectScript.appendText( """ |dependencies { @@ -24,14 +34,12 @@ class FilteringTest : BasePluginTest() { ) } - @Test fun includeAllDependencies() { runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { containsOnly(*entriesInAB, *manifestEntries) } } - @Test fun excludeFiles() { projectScript.appendText( """ @@ -49,8 +57,6 @@ class FilteringTest : BasePluginTest() { } } - @ParameterizedTest - @ValueSource(booleans = [false, true]) fun excludeDependency(useAccessor: Boolean) { settingsScript.appendText( """ @@ -82,7 +88,6 @@ class FilteringTest : BasePluginTest() { commonAssertions() } - @Test fun includeDependencyAndExcludeOthers() { projectScript.appendText( """ @@ -113,8 +118,6 @@ class FilteringTest : BasePluginTest() { } } - @ParameterizedTest - @ValueSource(booleans = [false, true]) fun filterProjectDependencies(useAccessor: Boolean) { val clientProject = if (useAccessor) "project(projects.client)" else "project(':client')" writeClientAndServerModules( @@ -134,7 +137,7 @@ class FilteringTest : BasePluginTest() { } } - @Test // #671 + // #671 fun filterProjectThatVersionContainsPlus() { writeClientAndServerModules( serverShadowBlock = @@ -154,7 +157,6 @@ class FilteringTest : BasePluginTest() { } } - @Test fun excludeTransitiveProjectDependency() { writeClientAndServerModules( serverShadowBlock = @@ -179,7 +181,6 @@ class FilteringTest : BasePluginTest() { } } - @Test fun verifyExcludePrecedenceOverInclude() { projectScript.appendText( """ @@ -199,7 +200,6 @@ class FilteringTest : BasePluginTest() { } } - @Test fun handleExcludeWithCircularDependency() { val dependency = "'my:e:1.0'" projectScript.appendText( diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/FindResourceInClasspathTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/FindResourceInClasspathTest.kt index 23533615f..23d251048 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/FindResourceInClasspathTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/FindResourceInClasspathTest.kt @@ -5,12 +5,16 @@ import assertk.assertThat import assertk.assertions.contains import assertk.assertions.doesNotContain import com.github.jengelman.gradle.plugins.shadow.tasks.FindResourceInClasspath +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.testkit.variantSeparatorsPathString +import de.infix.testBalloon.framework.core.testSuite import kotlin.io.path.appendText -import org.junit.jupiter.api.Test -class FindResourceInClasspathTest : BasePluginTest() { - @Test +val FindResourceInClasspathTests by testSuite { + runTests(::FindResourceInClasspathTest) +} + +private class FindResourceInClasspathTest : BasePluginTest() { fun findResourceInClasspath() { val taskClassName = FindResourceInClasspath::class.java.name projectScript.appendText( diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt index cd32e258c..aa8fe1d11 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt @@ -23,8 +23,11 @@ import com.github.jengelman.gradle.plugins.shadow.testkit.containsOnly import com.github.jengelman.gradle.plugins.shadow.testkit.getContent import com.github.jengelman.gradle.plugins.shadow.testkit.getMainAttr import com.github.jengelman.gradle.plugins.shadow.testkit.getStream +import com.github.jengelman.gradle.plugins.shadow.testkit.runTest +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.util.prependText import com.github.jengelman.gradle.plugins.shadow.util.runProcess +import de.infix.testBalloon.framework.core.testSuite import kotlin.io.path.appendText import kotlin.io.path.deleteExisting import kotlin.io.path.invariantSeparatorsPathString @@ -34,22 +37,55 @@ import kotlin.io.path.writeText import kotlin.reflect.full.declaredFunctions import kotlin.reflect.jvm.javaMethod import org.gradle.api.JavaVersion -import org.gradle.api.plugins.JavaPlugin.API_CONFIGURATION_NAME import org.gradle.api.plugins.JavaPlugin.COMPILE_ONLY_API_CONFIGURATION_NAME -import org.gradle.api.plugins.JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME import org.gradle.api.plugins.JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME import org.gradle.api.tasks.bundling.ZipEntryCompression import org.gradle.language.base.plugins.LifecycleBasePlugin.ASSEMBLE_TASK_NAME import org.gradle.testkit.runner.TaskOutcome.SUCCESS -import org.junit.jupiter.api.Test -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.Arguments -import org.junit.jupiter.params.provider.EnumSource -import org.junit.jupiter.params.provider.MethodSource -import org.junit.jupiter.params.provider.ValueSource - -class JavaPluginsTest : BasePluginTest() { - @Test // #1766 + +val JavaPluginsTests by testSuite { + runTests(::JavaPluginsTest) + + for (enable in listOf(false, true)) { + runTest( + "containsMultiReleaseAttrIfAnyDependencyContainsIt_addAttribute_$enable", + ::JavaPluginsTest, + ) { + containsMultiReleaseAttrIfAnyDependencyContainsIt(enable) + } + runTest("containsMultiReleaseAttrByCliOption_enable_$enable", ::JavaPluginsTest) { + containsMultiReleaseAttrByCliOption(enable) + } + runTest("failBuildIfDuplicateEntries_enable_$enable", ::JavaPluginsTest) { + failBuildIfDuplicateEntries(enable) + } + } + + for (configuration in + listOf(ShadowBasePlugin.CONFIGURATION_NAME, IMPLEMENTATION_CONFIGURATION_NAME)) { + runTest( + "addShadowConfigurationToClassPathInManifest_configuration_$configuration", + ::JavaPluginsTest, + ) { + addShadowConfigurationToClassPathInManifest(configuration) + } + } + + for (method in ZipEntryCompression.entries) { + runTest("supportZipCompressions_method_$method", ::JavaPluginsTest) { + supportZipCompressions(method) + } + } + + for (configuration in listOf("implementation", "api")) { + runTest("doNotReAddSuppressedGradleApi_configuration_$configuration", ::JavaPluginsTest) { + doNotReAddSuppressedGradleApi(configuration) + } + } +} + +private class JavaPluginsTest : BasePluginTest() { + // #1766 fun makeAssembleDependOnShadowJarEvenIfAddedLater() { val kFunction = ShadowJar.Companion::class.declaredFunctions.single { it.name == "registerShadowJarCommon" } @@ -90,7 +126,7 @@ class JavaPluginsTest : BasePluginTest() { assertThat(result.output).contains("task dependencies: $SHADOW_JAR_TASK_NAME") } - @Test // #1908 + // #1908 fun shadowJarNotAddedToAssembleWhenDisabled() { projectScript.appendText( """ @@ -110,7 +146,6 @@ class JavaPluginsTest : BasePluginTest() { assertThat(result.task(shadowJarPath)).isNull() } - @Test fun shadowJarCliOptions() { val result = runWithSuccess("help", "--task", shadowJarPath) @@ -131,7 +166,6 @@ class JavaPluginsTest : BasePluginTest() { ) } - @Test fun includeProjectDependencies() { writeClientAndServerModules() @@ -149,7 +183,6 @@ class JavaPluginsTest : BasePluginTest() { } } - @Test fun dependOnProjectShadowJar() { writeClientAndServerModules(clientShadowed = true) @@ -164,7 +197,6 @@ class JavaPluginsTest : BasePluginTest() { } } - @Test fun shadowProjectShadowJar() { writeClientAndServerModules(clientShadowed = true) val relocatedEntries = @@ -189,7 +221,7 @@ class JavaPluginsTest : BasePluginTest() { } } - @Test // #1893 + // #1893 fun consumeShadowedProjectViaApiElementsAndRuntimeElements() { settingsScript.appendText( """ @@ -267,7 +299,7 @@ class JavaPluginsTest : BasePluginTest() { } } - @Test // #1893 + // #1893 fun excludeRulesPreventBundledDepsOnConsumerClasspath() { settingsScript.appendText("include 'foo', 'consumer'\n") projectScript.writeText("") @@ -323,7 +355,7 @@ class JavaPluginsTest : BasePluginTest() { } } - @Test // #1606 + // #1606 fun shadowExposedCustomSourceSetOutput() { writeClientAndServerModules() path("client/build.gradle") @@ -373,8 +405,7 @@ class JavaPluginsTest : BasePluginTest() { } } - @ParameterizedTest // #449 - @ValueSource(booleans = [false, true]) + // #449 fun containsMultiReleaseAttrIfAnyDependencyContainsIt(addAttribute: Boolean) { writeClientAndServerModules() path("client/build.gradle") @@ -413,8 +444,6 @@ class JavaPluginsTest : BasePluginTest() { .isEqualTo(if (addAttribute) "true" else null) } - @ParameterizedTest - @ValueSource(booleans = [false, true]) fun containsMultiReleaseAttrByCliOption(enable: Boolean) { writeClientAndServerModules() path("client/build.gradle") @@ -445,7 +474,7 @@ class JavaPluginsTest : BasePluginTest() { .isEqualTo(if (enable) "true" else null) } - @Test // #352, #729 + // #352, #729 fun excludeSomeResourcesByDefault() { val resJar = buildJar("meta-inf.jar") { @@ -473,7 +502,6 @@ class JavaPluginsTest : BasePluginTest() { assertThat(outputShadowedJar).useAll { containsOnly("META-INF/a.properties", *manifestEntries) } } - @Test fun includeRuntimeConfigurationByDefault() { projectScript.appendText( """ @@ -491,7 +519,6 @@ class JavaPluginsTest : BasePluginTest() { assertThat(outputShadowedJar).useAll { containsOnly(*entriesInA, *manifestEntries) } } - @Test fun includeJavaLibraryConfigurationsByDefault() { localRepo .apply { @@ -531,7 +558,6 @@ class JavaPluginsTest : BasePluginTest() { } } - @Test fun classPathInManifestNotAddedIfEmpty() { projectScript.appendText( """ @@ -550,8 +576,7 @@ class JavaPluginsTest : BasePluginTest() { } } - @ParameterizedTest // #65 - @ValueSource(strings = [ShadowBasePlugin.CONFIGURATION_NAME, IMPLEMENTATION_CONFIGURATION_NAME]) + // #65 fun addShadowConfigurationToClassPathInManifest(configuration: String) { projectScript.appendText( """ @@ -578,7 +603,7 @@ class JavaPluginsTest : BasePluginTest() { assertThat(actual).isEqualTo(expected) } - @Test // #92 + // #92 fun doNotIncludeNullValueInClassPathWhenJarFileDoesNotContainClassPath() { projectScript.appendText( """ @@ -595,8 +620,7 @@ class JavaPluginsTest : BasePluginTest() { assertThat(value).isEqualTo("junit-3.8.2.jar") } - @ParameterizedTest // #203 - @EnumSource(ZipEntryCompression::class) + // #203 fun supportZipCompressions(method: ZipEntryCompression) { projectScript.appendText( """ @@ -616,7 +640,7 @@ class JavaPluginsTest : BasePluginTest() { assertThat(outputShadowedJar).useAll { containsOnly(*junitEntries, *manifestEntries) } } - @Test // #459, #852 + // #459, #852 fun excludeGradleApiByDefault() { writeGradlePluginModule() projectScript.appendText( @@ -653,7 +677,7 @@ class JavaPluginsTest : BasePluginTest() { } } - @Test // #1422 + // #1422 fun moveLocalGradleApiToCompileOnly() { projectScript.writeText(getDefaultProjectBuildScript("java-gradle-plugin")) @@ -663,8 +687,7 @@ class JavaPluginsTest : BasePluginTest() { assertThat(outputCompileOnlyApi).contains("unspecified") } - @ParameterizedTest // #1422 - @ValueSource(strings = [COMPILE_ONLY_CONFIGURATION_NAME, API_CONFIGURATION_NAME]) + // #1422 fun doNotReAddSuppressedGradleApi(configuration: String) { projectScript.writeText(getDefaultProjectBuildScript("java-gradle-plugin")) @@ -679,7 +702,7 @@ class JavaPluginsTest : BasePluginTest() { assertThat(output).doesNotContain("unspecified") } - @Test // #1070 + // #1070 fun registerCustomShadowJarTask() { val mainClassEntry = writeClass(sourceSet = "test", withImports = true) val testShadowJarTask = "testShadowJar" @@ -714,7 +737,7 @@ class JavaPluginsTest : BasePluginTest() { .contains("Hello, World! (foo) from Main", "Refs: junit.framework.Test") } - @Test // #1784 + // #1784 fun registerShadowJarTaskWithoutShadowPluginApplied() { val mainClassEntry = writeClass(sourceSet = "test", withImports = true) val testShadowJarTask = "testShadowJar" @@ -758,7 +781,7 @@ class JavaPluginsTest : BasePluginTest() { .contains("Hello, World! (foo) from Main", "Refs: junit.framework.Test") } - @Test // #443 + // #443 fun registerCustomShadowJarThatContainsDependenciesOnly() { val mainClassEntry = writeClass() val dependencyShadowJar = "dependencyShadowJar" @@ -789,7 +812,6 @@ class JavaPluginsTest : BasePluginTest() { } } - @Test fun registerCustomShadowJarWithoutShadowR8Configuration() { val customShadowJar = "customShadowJar" projectScript.writeText( @@ -812,7 +834,7 @@ class JavaPluginsTest : BasePluginTest() { ) } - @Test // #1975 + // #1975 fun skipNonExistentDependencyDirectory() { val nonExistentDir = projectRoot.resolve("non-existent-dir") @@ -830,7 +852,7 @@ class JavaPluginsTest : BasePluginTest() { assertThat(result.task(shadowJarPath)).isNotNull().transform { it.outcome }.isEqualTo(SUCCESS) } - @Test // #915 + // #915 fun failBuildIfProcessingBadJar() { val badJarPath = path("bad.jar").apply { writeText("A bad jar.") } @@ -848,7 +870,6 @@ class JavaPluginsTest : BasePluginTest() { assertThat(result.output).containsMatch("Cannot expand ZIP '.*bad\\.jar'".toRegex()) } - @Test fun failBuildIfProcessingAar() { val fooAarPath = buildJar("foo.aar") { insert("AndroidManifest.xml", "") } @@ -867,7 +888,6 @@ class JavaPluginsTest : BasePluginTest() { .contains("Shadowing AAR file is not supported.", "Please exclude dependency artifact:") } - @Test fun addExtraFilesViaFrom() { val mainClassEntry = writeClass() path("Foo").writeText("Foo") @@ -912,7 +932,6 @@ class JavaPluginsTest : BasePluginTest() { assertThat(jarPath(unzipped.name)).useAll { containsOnly(*entriesInA) } } - @Test fun addDependenciesViaCustomConfigurationWithoutUnzipping() { projectScript.appendText( """ @@ -935,7 +954,7 @@ class JavaPluginsTest : BasePluginTest() { } } - @Test // #520 + // #520 fun onlyKeepFilesFromProjectWhenDuplicatesStrategyIsExclude() { val fooJar = buildJar("foo.jar") { insert("module-info.class", "module myModuleName {}") } val mainClassEntry = writeClass() @@ -966,7 +985,7 @@ class JavaPluginsTest : BasePluginTest() { } } - @Test // #1441 + // #1441 fun includeFilesInTaskOutputDirectory() { // Create a build that has a task with jars in the output directory projectScript.appendText( @@ -1002,7 +1021,6 @@ class JavaPluginsTest : BasePluginTest() { assertThat(outputShadowedJar).useAll { containsOnly(*entriesInAB, *manifestEntries) } } - @Test fun integrateWithDevelocityBuildScan() { writeClientAndServerModules() settingsScript.prependText( @@ -1029,8 +1047,6 @@ class JavaPluginsTest : BasePluginTest() { } } - @ParameterizedTest - @ValueSource(booleans = [false, true]) fun failBuildIfDuplicateEntries(enable: Boolean) { path("src/main/resources/a.properties").writeText("invalid a") projectScript.appendText( @@ -1057,8 +1073,6 @@ class JavaPluginsTest : BasePluginTest() { .contains("Duplicate entries found in the shadowed JAR:", "a.properties (2 times)") } - @ParameterizedTest - @ValueSource(booleans = [false, true]) fun failBuildIfDuplicateEntriesByCliOption(enable: Boolean) { path("src/main/resources/a.properties").writeText("project a") projectScript.appendText( @@ -1084,8 +1098,6 @@ class JavaPluginsTest : BasePluginTest() { .contains("Duplicate entries found in the shadowed JAR:", "a.properties (2 times)") } - @ParameterizedTest - @MethodSource("fallbackMainClassProvider") fun fallbackMainClassByProperty(input: String, expected: String?, message: String) { projectScript.appendText( """ @@ -1102,8 +1114,6 @@ class JavaPluginsTest : BasePluginTest() { assertThat(outputShadowedJar).useAll { getMainAttr(mainClassAttributeKey).isEqualTo(expected) } } - @ParameterizedTest - @MethodSource("fallbackMainClassProvider") fun fallbackMainClassByCliOption(input: String, expected: String?) { if (input.isEmpty()) { runWithSuccess(shadowJarPath) @@ -1114,7 +1124,7 @@ class JavaPluginsTest : BasePluginTest() { assertThat(outputShadowedJar).useAll { getMainAttr(mainClassAttributeKey).isEqualTo(expected) } } - @Test // #882 + // #882 fun compatGradleArtifactTransform() { settingsScript.writeText("include('app', 'lib')\n") path("lib/build.gradle") @@ -1218,7 +1228,7 @@ class JavaPluginsTest : BasePluginTest() { } } - @Test // #2086 + // #2086 fun useToolchainWithoutTargetCompatibilityInKts() { projectScript.deleteExisting() path("build.gradle.kts") @@ -1240,7 +1250,7 @@ class JavaPluginsTest : BasePluginTest() { assertThat(result.task(shadowJarPath)).isNotNull().transform { it.outcome }.isEqualTo(SUCCESS) } - @Test // #2099 + // #2099 fun doNotResolveR8WhenLockingAllConfigurations() { projectScript.appendText( """ @@ -1276,21 +1286,4 @@ class JavaPluginsTest : BasePluginTest() { private fun dependencies(configuration: String, vararg flags: String): String { return runWithSuccess("dependencies", "--configuration", configuration, *flags).output } - - private companion object { - @JvmStatic - fun fallbackMainClassProvider() = - listOf( - Arguments.of( - "my.Main", - "my.Main", - "Adding $mainClassAttributeKey attribute to the manifest with value", - ), - Arguments.of( - "", - null, - "Skipping adding $mainClassAttributeKey attribute to the manifest as it is empty.", - ), - ) - } } diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/KotlinPluginsTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/KotlinPluginsTest.kt index c9dbb7ebd..88105fed9 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/KotlinPluginsTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/KotlinPluginsTest.kt @@ -8,25 +8,45 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.SHAD import com.github.jengelman.gradle.plugins.shadow.testkit.containsAtLeast import com.github.jengelman.gradle.plugins.shadow.testkit.containsOnly import com.github.jengelman.gradle.plugins.shadow.testkit.getMainAttr +import com.github.jengelman.gradle.plugins.shadow.testkit.runTest +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.util.JvmLang +import de.infix.testBalloon.framework.core.testSuite import kotlin.io.path.appendText import kotlin.io.path.writeText -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.ValueSource -class KotlinPluginsTest : BasePluginTest() { - @BeforeEach - override fun beforeEach() { - super.beforeEach() +val KotlinPluginsTests by testSuite { + runTests(::KotlinPluginsTest) + + for (excludeStdlib in listOf(false, true)) { + runTest("compatKotlinJvmPlugin_excludeStdlib_$excludeStdlib", ::KotlinPluginsTest) { + compatKotlinJvmPlugin(excludeStdlib) + } + runTest("compatKmpJvmTarget_excludeStdlib_$excludeStdlib", ::KotlinPluginsTest) { + compatKmpJvmTarget(excludeStdlib) + } + } + + for (useShadowAttr in listOf(false, true)) { + runTest("setMainClassAttributeFromMainRun_useShadowAttr_$useShadowAttr", ::KotlinPluginsTest) { + setMainClassAttributeFromMainRun(useShadowAttr) + } + runTest( + "setManifestAttrsFromJvmTargetJar_useShadowAttr_$useShadowAttr", + ::KotlinPluginsTest, + ) { + setManifestAttrsFromJvmTargetJar(useShadowAttr) + } + } +} + +private class KotlinPluginsTest : BasePluginTest() { + init { projectScript.writeText( getDefaultProjectBuildScript(plugin = "org.jetbrains.kotlin.multiplatform") ) } - @ParameterizedTest - @ValueSource(booleans = [false, true]) fun compatKotlinJvmPlugin(excludeStdlib: Boolean) { val stdlib = compileOnlyStdlib(excludeStdlib) @@ -61,8 +81,6 @@ class KotlinPluginsTest : BasePluginTest() { } } - @ParameterizedTest - @ValueSource(booleans = [false, true]) fun compatKmpJvmTarget(excludeStdlib: Boolean) { val stdlib = compileOnlyStdlib(excludeStdlib) @@ -108,7 +126,7 @@ class KotlinPluginsTest : BasePluginTest() { } } - @Test // #1377 + // #1377 fun compatKmpForOtherNamedJvmTarget() { val jvmTargetName = "newJvm" val jvmTargetMain = "${jvmTargetName}Main" @@ -144,7 +162,7 @@ class KotlinPluginsTest : BasePluginTest() { } } - @Test // #1377 + // #1377 fun doNotCreateJvmTargetEagerly() { projectScript.appendText( """ @@ -163,8 +181,6 @@ class KotlinPluginsTest : BasePluginTest() { ) } - @ParameterizedTest - @ValueSource(booleans = [false, true]) fun setMainClassAttributeFromMainRun(useShadowAttr: Boolean) { val mainClassName = "my.Main" val main2ClassName = "my.Main2" @@ -194,8 +210,6 @@ class KotlinPluginsTest : BasePluginTest() { } } - @ParameterizedTest - @ValueSource(booleans = [false, true]) fun setManifestAttrsFromJvmTargetJar(useShadowAttr: Boolean) { val mainClassName = "my.Main" val main2ClassName = "my.Main2" @@ -228,7 +242,6 @@ class KotlinPluginsTest : BasePluginTest() { } } - @Test fun registerShadowJarForFirstJvmTarget() { val jvmTargetName = "newJvm" projectScript.appendText( diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/MinimizeTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/MinimizeTest.kt index 772c8184b..0c6510986 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/MinimizeTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/MinimizeTest.kt @@ -11,17 +11,27 @@ import com.github.jengelman.gradle.plugins.shadow.testkit.containsNone import com.github.jengelman.gradle.plugins.shadow.testkit.containsOnly import com.github.jengelman.gradle.plugins.shadow.testkit.getContent import com.github.jengelman.gradle.plugins.shadow.testkit.invariantEolString +import com.github.jengelman.gradle.plugins.shadow.testkit.runTest +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests +import de.infix.testBalloon.framework.core.testSuite import java.net.URLClassLoader import java.util.ServiceLoader import kotlin.io.path.appendText import kotlin.io.path.readText import kotlin.io.path.writeText import org.gradle.api.JavaVersion -import org.junit.jupiter.api.Test -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.ValueSource -class MinimizeTest : BasePluginTest() { +val MinimizeTests by testSuite { + runTests(::MinimizeTest) + + for (enable in listOf(false, true)) { + runTest("enableMinimizationByCliOption_enable_$enable", ::MinimizeTest) { + enableMinimizationByCliOption(enable) + } + } +} + +private class MinimizeTest : BasePluginTest() { private val outputImplShadowedJar: JarPath get() = jarPath("impl/build/libs/impl-1.0-all.jar") @@ -30,7 +40,6 @@ class MinimizeTest : BasePluginTest() { * shall remove 'junit', but not 'api'. Unused classes of 'api' and theirs dependencies also * shouldn't be removed. */ - @Test fun useMinimizeWithDependenciesWithApiScope() { writeApiLibAndImplModules() @@ -54,7 +63,6 @@ class MinimizeTest : BasePluginTest() { * 'api' used as api for 'impl', and 'lib' used as api for 'api'. Unused classes of 'api' and * 'lib' shouldn't be removed. */ - @Test fun useMinimizeWithTransitiveDependenciesWithApiScope() { writeApiLibAndImplModules() path("api/build.gradle") @@ -88,7 +96,6 @@ class MinimizeTest : BasePluginTest() { } /** 'Server' depends on 'Client'. 'junit' is independent. The minimize shall remove 'junit'. */ - @Test fun minimizeByKeepingOnlyTransitiveDependencies() { writeClientAndServerModules( serverShadowBlock = @@ -122,7 +129,6 @@ class MinimizeTest : BasePluginTest() { * 'Client', 'Server' and 'junit' are independent. 'junit' is excluded from the minimize step. The * minimize step shall remove 'Client' but not 'junit'. */ - @Test fun excludeDependencyFromMinimize() { writeClientAndServerModules( serverShadowBlock = @@ -146,7 +152,7 @@ class MinimizeTest : BasePluginTest() { * 'Client', 'Server' and 'junit' are independent. Unused classes of 'client' and theirs * dependencies shouldn't be removed. */ - @Test // #744 + // #744 fun excludeProjectFromMinimize() { writeClientAndServerModules( serverShadowBlock = @@ -176,7 +182,6 @@ class MinimizeTest : BasePluginTest() { * 'Client', 'Server' and 'junit' are independent. Unused classes of 'client' and theirs * dependencies shouldn't be removed. */ - @Test fun excludeProjectFromMinimizeShallNotExcludeTransitiveDependenciesThatAreUsedInSubproject() { writeClientAndServerModules( serverShadowBlock = @@ -220,7 +225,7 @@ class MinimizeTest : BasePluginTest() { } } - @Test // #1610 + // #1610 fun excludeCircularDependencies() { val dependency = "'my:e:1.0'" projectScript.appendText( @@ -244,8 +249,6 @@ class MinimizeTest : BasePluginTest() { } } - @ParameterizedTest - @ValueSource(booleans = [false, true]) fun enableMinimizationByCliOption(enable: Boolean) { writeClientAndServerModules() @@ -272,7 +275,7 @@ class MinimizeTest : BasePluginTest() { } } - @Test // #1636 + // #1636 fun minimizeBomDependency() { writeApiLibAndImplModules() path("impl/build.gradle") @@ -301,7 +304,6 @@ class MinimizeTest : BasePluginTest() { } } - @Test fun minimizeWithR8ShrinksUnusedDependencyClasses() { writeR8Repository() writeR8ClientAndServerModules( @@ -340,7 +342,6 @@ class MinimizeTest : BasePluginTest() { ) } - @Test fun minimizeWithR8KeepsServiceProviders() { writeR8Repository() writeR8ServiceModules() @@ -367,7 +368,6 @@ class MinimizeTest : BasePluginTest() { } } - @Test fun minimizeWithR8HonorsCustomProguardRules() { writeR8Repository() writeR8ClientAndServerModules( @@ -411,7 +411,6 @@ class MinimizeTest : BasePluginTest() { ) } - @Test fun minimizeWithR8GeneratesReportsRelativeToConfigurationFile() { writeR8Repository() writeR8ClientAndServerModules( @@ -456,7 +455,6 @@ class MinimizeTest : BasePluginTest() { .contains("client.Reflective", "client.Unused") } - @Test fun minimizeWithR8UsesClasspathRules() { writeR8Repository() writeR8ClientAndServerModules( @@ -505,7 +503,6 @@ class MinimizeTest : BasePluginTest() { ) } - @Test fun minimizeWithR8PreservesRepeatedLinesInClasspathRules() { writeR8Repository() writeR8ClientAndServerModules( @@ -547,7 +544,6 @@ class MinimizeTest : BasePluginTest() { } } - @Test fun minimizeWithR8CanEnableObfuscation() { writeR8Repository() writeR8ClientAndServerModules( @@ -575,7 +571,6 @@ class MinimizeTest : BasePluginTest() { } } - @Test fun minimizeWithR8CanEnableOptimization() { writeR8Repository() writeR8ClientAndServerModules( @@ -601,7 +596,6 @@ class MinimizeTest : BasePluginTest() { } } - @Test fun minimizeWithR8HonorsDependencyExcludes() { writeR8Repository() writeR8ClientAndServerModules( @@ -630,7 +624,6 @@ class MinimizeTest : BasePluginTest() { } } - @Test fun minimizeWithR8UsesJavaToolchain() { writeR8Repository() writeR8ClientAndServerModules( diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/PublishingTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/PublishingTest.kt index 2f8aa4b6c..274d3a01c 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/PublishingTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/PublishingTest.kt @@ -16,14 +16,18 @@ import com.github.jengelman.gradle.plugins.shadow.testkit.containsAtLeast import com.github.jengelman.gradle.plugins.shadow.testkit.containsNone import com.github.jengelman.gradle.plugins.shadow.testkit.containsOnly import com.github.jengelman.gradle.plugins.shadow.testkit.getMainAttr +import com.github.jengelman.gradle.plugins.shadow.testkit.runTest +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.util.GradleModuleMetadata import com.github.jengelman.gradle.plugins.shadow.util.coordinate import com.github.jengelman.gradle.plugins.shadow.util.prependText import com.squareup.moshi.JsonAdapter import com.squareup.moshi.Moshi import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory +import de.infix.testBalloon.framework.core.testSuite import java.nio.file.Path import kotlin.io.path.appendText +import kotlin.io.path.createTempDirectory import kotlin.io.path.exists import kotlin.io.path.inputStream import kotlin.io.path.listDirectoryEntries @@ -41,22 +45,24 @@ import org.gradle.api.attributes.java.TargetJvmVersion import org.gradle.api.plugins.JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME import org.gradle.api.plugins.JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME import org.gradle.testkit.runner.BuildResult -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.io.TempDir -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.ValueSource - -class PublishingTest : BasePluginTest() { - @TempDir lateinit var remoteRepoPath: Path - - @BeforeEach - override fun beforeEach() { - super.beforeEach() + +val PublishingTests by testSuite { + runTests(::PublishingTest) + + for (addShadowVariant in listOf(false, true)) { + runTest("publishShadowVariantJar_addShadowVariant_$addShadowVariant", ::PublishingTest) { + publishShadowVariantJar(addShadowVariant) + } + } +} + +private class PublishingTest : BasePluginTest() { + val remoteRepoPath: Path = createTempDirectory() + + init { settingsScript.appendText("rootProject.name = 'maven'\n") } - @Test fun publishShadowJarWithCorrectTargetJvm() { projectScript.appendText( publishConfiguration( @@ -137,7 +143,7 @@ class PublishingTest : BasePluginTest() { assertions(attrsWithoutTargetJvm + targetJvmAttr8) } - @Test // #1665 + // #1665 fun dontInjectTargetJvmVersionWhenAutoTargetJvmDisabled() { projectScript.appendText( publishConfiguration( @@ -172,7 +178,6 @@ class PublishingTest : BasePluginTest() { ) } - @Test fun dontInjectTargetJvmVersionWhenOptingOut() { projectScript.appendText( publishConfiguration( @@ -207,7 +212,6 @@ class PublishingTest : BasePluginTest() { ) } - @Test fun overrideBundlingAttrInGradleMetadata() { projectScript.appendText( publishConfiguration( @@ -240,7 +244,6 @@ class PublishingTest : BasePluginTest() { ) } - @Test fun publishShadowJarInsteadOfJar() { projectScript.appendText( publishConfiguration( @@ -285,7 +288,6 @@ class PublishingTest : BasePluginTest() { assertShadowVariantCommon(gmmAdapter.fromJson(repoPath("$artifactRoot/maven-1.0.module"))) } - @Test fun publishCustomShadowJar() { projectScript.appendText( publishConfiguration( @@ -321,7 +323,6 @@ class PublishingTest : BasePluginTest() { } } - @Test fun publishShadowedGradlePlugin() { writeGradlePluginModule() projectScript.appendText( @@ -365,7 +366,7 @@ class PublishingTest : BasePluginTest() { ) } - @Test // #614, #860, #945 + // #614, #860, #945 fun publishShadowJarWithCustomArtifactName() { projectScript.appendText( publishConfiguration( @@ -420,7 +421,6 @@ class PublishingTest : BasePluginTest() { assertShadowVariantCommon(gmmAdapter.fromJson(repoPath("$artifactRoot/my-artifact-2.0.module"))) } - @Test fun publishJarAndShadowJarWithGradleMetadata() { projectScript.appendText( publishConfiguration( @@ -533,8 +533,7 @@ class PublishingTest : BasePluginTest() { } } - @ParameterizedTest // #651 - @ValueSource(booleans = [false, true]) + // #651 fun publishShadowVariantJar(addShadowVariant: Boolean) { projectScript.appendText( publishingBlock( @@ -730,7 +729,7 @@ class PublishingTest : BasePluginTest() { } } - private companion object { + companion object { val gmmAdapter: JsonAdapter = Moshi.Builder() .add(KotlinJsonAdapterFactory()) diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt index ddaa6fc1d..a2cb5becc 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt @@ -13,22 +13,71 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.CONS import com.github.jengelman.gradle.plugins.shadow.testkit.containsOnly import com.github.jengelman.gradle.plugins.shadow.testkit.getBytes import com.github.jengelman.gradle.plugins.shadow.testkit.requireResourceAsPath +import com.github.jengelman.gradle.plugins.shadow.testkit.runTest +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.util.runProcess +import de.infix.testBalloon.framework.core.testSuite import java.net.URLClassLoader import kotlin.io.path.appendText import kotlin.io.path.readBytes import kotlin.io.path.writeText import kotlin.time.Duration.Companion.seconds -import org.junit.jupiter.api.Test -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.Arguments -import org.junit.jupiter.params.provider.MethodSource -import org.junit.jupiter.params.provider.ValueSource import org.opentest4j.AssertionFailedError -class RelocationTest : BasePluginTest() { - @ParameterizedTest - @ValueSource(strings = ["foo", "new.pkg", "new/path"]) +val RelocationTests by testSuite { + runTests(::RelocationTest) + + for (relocationPrefix in listOf("foo", "new.pkg", "new/path")) { + runTest("autoRelocation_$relocationPrefix", ::RelocationTest) { + autoRelocation(relocationPrefix) + } + } + + for ((enable, relocationPrefix) in RelocationTest.relocationCliOptionProvider) { + runTest( + "enableAutoRelocationByCliOption_${enable}_${relocationPrefix}", + ::RelocationTest, + ) { + enableAutoRelocationByCliOption(enable, relocationPrefix) + } + } + + for ((preserveFileTimestamps, enableAutoRelocation) in + RelocationTest.preserveLastModifiedProvider) { + runTest( + "preserveLastModifiedCorrectly_${preserveFileTimestamps}_${enableAutoRelocation}", + ::RelocationTest, + ) { + preserveLastModifiedCorrectly(preserveFileTimestamps, enableAutoRelocation) + } + } + + for (exclude in listOf(false, true)) { + runTest("relocateAllPackagesButCertainOne_exclude_$exclude", ::RelocationTest) { + relocateAllPackagesButCertainOne(exclude) + } + } + + for (skipStringConstants in listOf(false, true)) { + runTest( + "disableStringConstantsRelocation_skipStringConstants_$skipStringConstants", + ::RelocationTest, + ) { + disableStringConstantsRelocation(skipStringConstants) + } + } + + for (enableKotlinModuleRemapping in listOf(false, true)) { + runTest( + "relocateKotlinModuleFiles_enableKotlinModuleRemapping_$enableKotlinModuleRemapping", + ::RelocationTest, + ) { + relocateKotlinModuleFiles(enableKotlinModuleRemapping) + } + } +} + +private class RelocationTest : BasePluginTest() { fun autoRelocation(relocationPrefix: String) { val mainClassEntry = writeClass() projectScript.appendText( @@ -67,8 +116,6 @@ class RelocationTest : BasePluginTest() { assertThat(result.output).contains("Relocator count: 6.") } - @ParameterizedTest - @MethodSource("relocationCliOptionProvider") fun enableAutoRelocationByCliOption(enable: Boolean, relocationPrefix: String) { val mainClassEntry = writeClass() projectScript.appendText( @@ -109,7 +156,7 @@ class RelocationTest : BasePluginTest() { } } - @Test // #58 + // #58 fun relocateDependencyFiles() { val mainClassEntry = writeClass() projectScript.appendText( @@ -150,7 +197,6 @@ class RelocationTest : BasePluginTest() { } } - @Test fun relocateDependencyFilesWithFiltering() { val mainClassEntry = writeClass() projectScript.appendText( @@ -199,7 +245,7 @@ class RelocationTest : BasePluginTest() { } } - @Test // #53, #55 + // #53, #55 fun remapClassNamesForRelocatedFilesInProjectSource() { projectScript.appendText( """ @@ -249,7 +295,7 @@ class RelocationTest : BasePluginTest() { } } - @Test // #93, #114 + // #93, #114 fun relocateResourceFiles() { val depJar = buildJar("foo.jar") { insert("foo/dep.properties", "c") } writeClass(packageName = "foo", className = "Foo") @@ -280,8 +326,6 @@ class RelocationTest : BasePluginTest() { } } - @ParameterizedTest - @MethodSource("preserveLastModifiedProvider") fun preserveLastModifiedCorrectly( enableAutoRelocation: Boolean, preserveFileTimestamps: Boolean, @@ -372,7 +416,7 @@ class RelocationTest : BasePluginTest() { } } - @Test // #295, #562, #884 + // #295, #562, #884 fun excludeKotlinBuiltinsFromRelocation() { val kotlinJar = buildJar("kotlin.jar") { @@ -399,8 +443,6 @@ class RelocationTest : BasePluginTest() { } } - @ParameterizedTest - @ValueSource(booleans = [false, true]) fun relocateAllPackagesButCertainOne(exclude: Boolean) { val relocateConfig = if (exclude) { @@ -437,7 +479,6 @@ class RelocationTest : BasePluginTest() { } } - @Test fun relocateProjectResourcesOnly() { val mainClassEntry = writeClass() projectScript.appendText( @@ -460,7 +501,6 @@ class RelocationTest : BasePluginTest() { } } - @Test fun relocateStringConstantsByDefault() { writeClassWithStringRef() projectScript.appendText( @@ -481,8 +521,7 @@ class RelocationTest : BasePluginTest() { assertThat(result).contains("shadow.foo.Foo", "shadow.foo.Bar") } - @ParameterizedTest // #232, #606 - @ValueSource(booleans = [false, true]) + // #232, #606 fun disableStringConstantsRelocation(skipStringConstants: Boolean) { writeClassWithStringRef() projectScript.appendText( @@ -509,7 +548,7 @@ class RelocationTest : BasePluginTest() { } } - @Test // #1403 + // #1403 fun relocateMultiClassSignatureStringConstants() { writeClass { """ @@ -548,7 +587,6 @@ class RelocationTest : BasePluginTest() { ) } - @Test fun classBytesUnchangedIfPossible() { val mainClassEntry = writeClass() projectScript.appendText( @@ -570,8 +608,7 @@ class RelocationTest : BasePluginTest() { assertThat(relocatedBytes).isEqualTo(originalBytes) } - @ParameterizedTest // #843 - @ValueSource(booleans = [false, true]) + // #843 fun relocateKotlinModuleFiles(enableKotlinModuleRemapping: Boolean) { val originalModuleFilePath = "META-INF/kotlin-stdlib.kotlin_module" val originalModuleFileBytes = requireResourceAsPath(originalModuleFilePath).readBytes() @@ -627,7 +664,6 @@ class RelocationTest : BasePluginTest() { } } - @Test fun relocateWithR8() { writeClass(packageName = "my", withImports = false) { """ @@ -679,23 +715,21 @@ class RelocationTest : BasePluginTest() { } } - private companion object { - @JvmStatic - fun preserveLastModifiedProvider() = + companion object { + val preserveLastModifiedProvider = listOf( - Arguments.of(false, false), - Arguments.of(true, false), - Arguments.of(false, true), - Arguments.of(true, true), + Pair(false, false), + Pair(true, false), + Pair(false, true), + Pair(true, true), ) - @JvmStatic - fun relocationCliOptionProvider() = + val relocationCliOptionProvider = listOf( - Arguments.of(false, "foo"), - Arguments.of(false, "bar"), - Arguments.of(true, "foo"), - Arguments.of(true, "bar"), + Pair(false, "foo"), + Pair(false, "bar"), + Pair(true, "foo"), + Pair(true, "bar"), ) } } diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformerTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformerTest.kt index 979efcc2f..6e0393db1 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformerTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformerTest.kt @@ -3,11 +3,15 @@ package com.github.jengelman.gradle.plugins.shadow.transformers import assertk.assertThat import assertk.assertions.isEqualTo import com.github.jengelman.gradle.plugins.shadow.testkit.getContent +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests +import de.infix.testBalloon.framework.core.testSuite import kotlin.io.path.appendText -import org.junit.jupiter.api.Test -class AppendingTransformerTest : BaseTransformerTest() { - @Test +val AppendingTransformerTests by testSuite { + runTests(::AppendingTransformerTest) +} + +private class AppendingTransformerTest : BaseTransformerTest() { fun appendTestProperties() { val one = buildJarOne { insert(ENTRY_TEST_PROPERTIES, CONTENT_ONE) } val two = buildJarTwo { insert(ENTRY_TEST_PROPERTIES, CONTENT_TWO) } diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/BaseTransformerTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/BaseTransformerTest.kt index 2d173523c..32a4c9216 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/BaseTransformerTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/BaseTransformerTest.kt @@ -4,12 +4,9 @@ import com.github.jengelman.gradle.plugins.shadow.BasePluginTest import com.github.jengelman.gradle.plugins.shadow.util.JarBuilder import java.nio.file.Path import kotlin.io.path.appendText -import org.junit.jupiter.api.BeforeEach abstract class BaseTransformerTest : BasePluginTest() { - @BeforeEach - override fun beforeEach() { - super.beforeEach() + init { projectScript.appendText( """ |$shadowJarTask { @@ -49,6 +46,5 @@ abstract class BaseTransformerTest : BasePluginTest() { const val ENTRY_TEST_PROPERTIES = "test.properties" const val ENTRY_SERVICES_SHADE = "META-INF/services/org.apache.maven.Shade" const val ENTRY_SERVICES_FOO = "META-INF/services/com.acme.Foo" - const val ENTRY_FOO_SHADE = "META-INF/foo/org.apache.maven.Shade" } } diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformerTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformerTest.kt index 365963ebb..d34296147 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformerTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformerTest.kt @@ -4,6 +4,7 @@ import assertk.assertThat import assertk.assertions.isEqualTo import com.github.jengelman.gradle.plugins.shadow.testkit.JarPath import com.github.jengelman.gradle.plugins.shadow.testkit.getContent +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.transformers.GroovyExtensionModuleTransformer.Companion.KEY_EXTENSION_CLASSES import com.github.jengelman.gradle.plugins.shadow.transformers.GroovyExtensionModuleTransformer.Companion.KEY_MODULE_NAME import com.github.jengelman.gradle.plugins.shadow.transformers.GroovyExtensionModuleTransformer.Companion.KEY_MODULE_VERSION @@ -11,12 +12,15 @@ import com.github.jengelman.gradle.plugins.shadow.transformers.GroovyExtensionMo import com.github.jengelman.gradle.plugins.shadow.transformers.GroovyExtensionModuleTransformer.Companion.MERGED_MODULE_NAME import com.github.jengelman.gradle.plugins.shadow.transformers.GroovyExtensionModuleTransformer.Companion.MERGED_MODULE_VERSION import com.github.jengelman.gradle.plugins.shadow.transformers.GroovyExtensionModuleTransformer.Companion.PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR +import de.infix.testBalloon.framework.core.testSuite import java.nio.file.Path import kotlin.io.path.appendText -import org.junit.jupiter.api.Test -class GroovyExtensionModuleTransformerTest : BaseTransformerTest() { - @Test +val GroovyExtensionModuleTransformerTests by testSuite { + runTests(::GroovyExtensionModuleTransformerTest) +} + +private class GroovyExtensionModuleTransformerTest : BaseTransformerTest() { fun groovyExtensionModuleTransformer() { projectScript.appendText( """ @@ -70,7 +74,7 @@ class GroovyExtensionModuleTransformerTest : BaseTransformerTest() { ) } - private companion object { + companion object { const val EXTENSION_CLASSES_FOO = "com.acme.foo.FooExtension,com.acme.foo.BarExtension" const val EXTENSION_CLASSES_BAR = "com.acme.bar.SomeExtension,com.acme.bar.AnotherExtension" const val STATIC_EXTENSION_CLASSES_FOO = "com.acme.foo.FooStaticExtension" diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt index 59a63382f..9eb4c1c96 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt @@ -4,14 +4,18 @@ import assertk.assertThat import assertk.assertions.contains import assertk.assertions.isEqualTo import com.github.jengelman.gradle.plugins.shadow.testkit.getContent +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests +import de.infix.testBalloon.framework.core.testSuite import kotlin.io.path.appendText import kotlin.io.path.invariantSeparatorsPathString import kotlin.io.path.writeText -import org.junit.jupiter.api.Test -class PropertiesFileTransformerTest : BaseTransformerTest() { +val PropertiesFileTransformerTests by testSuite { + runTests(::PropertiesFileTransformerTest) +} + +private class PropertiesFileTransformerTest : BaseTransformerTest() { - @Test fun configureComplexTransformerProperties() { val propertiesEntry = "META-INF/test.properties" val one = buildJarOne { diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt index 5dba0720a..efbe302fe 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt @@ -6,6 +6,9 @@ import assertk.assertions.containsMatch import assertk.assertions.isEqualTo import com.github.jengelman.gradle.plugins.shadow.testkit.containsOnly import com.github.jengelman.gradle.plugins.shadow.testkit.getContent +import com.github.jengelman.gradle.plugins.shadow.testkit.runTest +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests +import de.infix.testBalloon.framework.core.testSuite import kotlin.io.path.appendText import kotlin.io.path.writeText import org.gradle.api.file.DuplicatesStrategy @@ -14,35 +17,33 @@ import org.gradle.api.file.DuplicatesStrategy.FAIL import org.gradle.api.file.DuplicatesStrategy.INCLUDE import org.gradle.api.file.DuplicatesStrategy.INHERIT import org.gradle.api.file.DuplicatesStrategy.WARN -import org.junit.jupiter.api.Test -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.Arguments -import org.junit.jupiter.params.provider.MethodSource - -class ServiceFileTransformerTest : BaseTransformerTest() { - @Test - fun serviceResourceTransformerAlternatePath() { - val one = buildJarOne { insert(ENTRY_FOO_SHADE, CONTENT_ONE) } - val two = buildJarTwo { insert(ENTRY_FOO_SHADE, CONTENT_TWO) } - val config = - """ - |dependencies { - | ${implementationFiles(one, two)} - |} - |$shadowJarTask { - | mergeServiceFiles("META-INF/foo") - |} - """ - .trimMargin() - projectScript.appendText(config) - runWithSuccess(shadowJarPath) +val ServiceFileTransformerTests by testSuite { + runTests(::ServiceFileTransformerTest) - val content = outputShadowedJar.use { it.getContent(ENTRY_FOO_SHADE) } - assertThat(content).isEqualTo(CONTENT_ONE_TWO) + for ((strategy, outputRegex) in ServiceFileTransformerTest.withThrowingProvider) { + runTest("honorDuplicatesStrategyWithThrowing_$strategy", ::ServiceFileTransformerTest) { + honorDuplicatesStrategyWithThrowing(strategy, outputRegex) + } + } + + for ((strategy, firstValue, secondValue) in ServiceFileTransformerTest.withoutThrowingProvider) { + runTest("honorDuplicatesStrategyWithoutThrowing_$strategy", ::ServiceFileTransformerTest) { + honorDuplicatesStrategyWithoutThrowing(strategy, firstValue, secondValue) + } } - @Test + for ((default, override, matchPath) in ServiceFileTransformerTest.eachFileStrategyProvider) { + runTest( + "strategyCanBeOverriddenByEachFile_${default}_${override}", + ::ServiceFileTransformerTest, + ) { + strategyCanBeOverriddenByEachFile(default, override, matchPath) + } + } +} + +private class ServiceFileTransformerTest : BaseTransformerTest() { fun serviceResourceTransformerWithRelocation() { val one = buildJarOne { insert("com/example/Driver.class", createEmptyClassBytes("com/example/Driver")) @@ -102,7 +103,6 @@ class ServiceFileTransformerTest : BaseTransformerTest() { } } - @Test fun serviceResourceTransformerWithR8Relocation() { val one = buildJarOne { insert("com/example/Driver.class", createEmptyClassBytes("com/example/Driver")) @@ -167,7 +167,7 @@ class ServiceFileTransformerTest : BaseTransformerTest() { } } - @Test // #70, #71 + // #70, #71 fun transformProjectResources() { val servicesBarEntry = "META-INF/services/foo.Bar" val one = buildJarOne { insert(servicesBarEntry, CONTENT_ONE) } @@ -191,8 +191,6 @@ class ServiceFileTransformerTest : BaseTransformerTest() { assertThat(content).isEqualTo("$CONTENT_THREE\n$CONTENT_ONE_TWO") } - @ParameterizedTest - @MethodSource("withThrowingProvider") fun honorDuplicatesStrategyWithThrowing(strategy: DuplicatesStrategy, outputRegex: String) { writeDuplicatesStrategy(strategy) @@ -201,8 +199,6 @@ class ServiceFileTransformerTest : BaseTransformerTest() { assertThat(result.output).containsMatch(outputRegex.toRegex()) } - @ParameterizedTest - @MethodSource("withoutThrowingProvider") fun honorDuplicatesStrategyWithoutThrowing( strategy: DuplicatesStrategy, firstValue: String, @@ -226,7 +222,6 @@ class ServiceFileTransformerTest : BaseTransformerTest() { } } - @Test fun strategyCanBeOverriddenByFilesMatching() { writeDuplicatesStrategy(EXCLUDE) projectScript.appendText( @@ -248,7 +243,6 @@ class ServiceFileTransformerTest : BaseTransformerTest() { } } - @Test fun strategyCanBeOverriddenByFilesNotMatching() { writeDuplicatesStrategy(INCLUDE) projectScript.appendText( @@ -270,8 +264,6 @@ class ServiceFileTransformerTest : BaseTransformerTest() { } } - @ParameterizedTest - @MethodSource("eachFileStrategyProvider") fun strategyCanBeOverriddenByEachFile( default: DuplicatesStrategy, override: DuplicatesStrategy, @@ -315,33 +307,24 @@ class ServiceFileTransformerTest : BaseTransformerTest() { ) } - private companion object { - @JvmStatic - fun withThrowingProvider() = + companion object { + val withThrowingProvider = listOf( - Arguments.of( - FAIL, - "Cannot copy zip entry .* to .* because zip entry .* has already been copied there", - ), - Arguments.of( - INHERIT, - "Entry .* is a duplicate but no duplicate handling strategy has been set", - ), + FAIL to "Cannot copy zip entry .* to .* because zip entry .* has already been copied there", + INHERIT to "Entry .* is a duplicate but no duplicate handling strategy has been set", ) - @JvmStatic - fun withoutThrowingProvider() = + val withoutThrowingProvider = listOf( - Arguments.of(EXCLUDE, CONTENT_ONE, "one"), - Arguments.of(INCLUDE, CONTENT_ONE_TWO, "one\ntwo"), - Arguments.of(WARN, CONTENT_ONE_TWO, "one\ntwo"), + Triple(EXCLUDE, CONTENT_ONE, "one"), + Triple(INCLUDE, CONTENT_ONE_TWO, "one\ntwo"), + Triple(WARN, CONTENT_ONE_TWO, "one\ntwo"), ) - @JvmStatic - fun eachFileStrategyProvider() = + val eachFileStrategyProvider = listOf( - Arguments.of(EXCLUDE, INCLUDE, ENTRY_SERVICES_SHADE), - Arguments.of(INCLUDE, EXCLUDE, ENTRY_SERVICES_FOO), + Triple(EXCLUDE, INCLUDE, ENTRY_SERVICES_SHADE), + Triple(INCLUDE, EXCLUDE, ENTRY_SERVICES_FOO), ) } } diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformersTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformersTest.kt index 99ce25538..1b53656b1 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformersTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformersTest.kt @@ -11,16 +11,20 @@ import com.github.jengelman.gradle.plugins.shadow.testkit.containsOnly import com.github.jengelman.gradle.plugins.shadow.testkit.getContent import com.github.jengelman.gradle.plugins.shadow.testkit.getStream import com.github.jengelman.gradle.plugins.shadow.testkit.requireResourceAsPath +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests +import de.infix.testBalloon.framework.core.testSuite import java.util.jar.Attributes as JarAttribute import kotlin.io.path.appendText import kotlin.io.path.readText import kotlin.io.path.writeText import org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor.PLUGIN_CACHE_FILE -import org.junit.jupiter.api.Test -class TransformersTest : BaseTransformerTest() { +val TransformersTests by testSuite { + runTests(::TransformersTest) +} + +private class TransformersTest : BaseTransformerTest() { - @Test fun manifestRetained() { writeClass() projectScript.appendText( @@ -43,7 +47,6 @@ class TransformersTest : BaseTransformerTest() { } } - @Test fun manifestTransformed() { writeClass() @@ -54,7 +57,7 @@ class TransformersTest : BaseTransformerTest() { commonAssertions() } - @Test // #427 + // #427 fun mergeLog4j2PluginCacheFiles() { val content = requireResourceAsPath(PLUGIN_CACHE_FILE).readText() val one = buildJarOne { insert(PLUGIN_CACHE_FILE, content) } @@ -77,7 +80,6 @@ class TransformersTest : BaseTransformerTest() { } } - @Test fun preserveFirstFoundResource() { path("src/main/resources/foo/bar").writeText("bar1") path("src/main/resources/foo/baz").writeText("baz1") @@ -105,7 +107,6 @@ class TransformersTest : BaseTransformerTest() { } } - @Test fun useCustomTransformer() { projectScript.appendText( """ @@ -138,7 +139,7 @@ class TransformersTest : BaseTransformerTest() { mainAttributesBlock(mf.mainAttributes) } - private companion object { + companion object { const val NEW_ENTRY_ATTR_KEY = "New-Entry" const val TEST_ENTRY_ATTR_KEY = "Test-Entry" diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPropertiesTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPropertiesTest.kt index 91c70e5ab..92c33e265 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPropertiesTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPropertiesTest.kt @@ -23,6 +23,8 @@ import com.github.jengelman.gradle.plugins.shadow.internal.runtimeConfiguration import com.github.jengelman.gradle.plugins.shadow.legacy.LegacyShadowPlugin import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.SHADOW_JAR_TASK_NAME import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.shadowJar +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests +import de.infix.testBalloon.framework.core.testSuite import org.gradle.api.Named import org.gradle.api.Project import org.gradle.api.Task @@ -41,22 +43,18 @@ import org.gradle.language.base.plugins.LifecycleBasePlugin import org.gradle.language.base.plugins.LifecycleBasePlugin.ASSEMBLE_TASK_NAME import org.gradle.plugin.devel.plugins.JavaGradlePluginPlugin import org.gradle.testfixtures.ProjectBuilder -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -class ShadowPropertiesTest { - private lateinit var project: Project +val ShadowPropertiesTests by testSuite { + runTests(::ShadowPropertiesTest) +} - @BeforeEach - fun beforeEach() { - project = - ProjectBuilder.builder().withName(PROJECT_NAME).build().also { - it.version = VERSION - it.plugins.apply(ShadowPlugin::class.java) - } - } +private class ShadowPropertiesTest { + private val project: Project = + ProjectBuilder.builder().withName(PROJECT_NAME).build().also { + it.version = VERSION + it.plugins.apply(ShadowPlugin::class.java) + } - @Test fun misc() = with(project) { assertThat(plugins.hasPlugin(ShadowPlugin::class.java)).isTrue() @@ -71,7 +69,6 @@ class ShadowPropertiesTest { } } - @Test fun inheritManifestAttrsFromJars() = with(project) { plugins.apply(JavaPlugin::class.java) @@ -96,7 +93,6 @@ class ShadowPropertiesTest { ) } - @Test fun inheritManifestMainClassFromJar() = with(project) { plugins.apply(JavaPlugin::class.java) @@ -108,7 +104,6 @@ class ShadowPropertiesTest { .containsOnly("Manifest-Version" to "1.0", mainClassAttributeKey to "Main") } - @Test fun applyJavaPlugin() = with(project) { plugins.apply(JavaPlugin::class.java) @@ -165,7 +160,6 @@ class ShadowPropertiesTest { } } - @Test fun applyApplicationPlugin() = with(project) { plugins.apply(ApplicationPlugin::class.java) @@ -257,7 +251,6 @@ class ShadowPropertiesTest { } } - @Test fun applyJavaGradlePlugin() = with(project) { plugins.apply(JavaGradlePluginPlugin::class.java) @@ -270,7 +263,7 @@ class ShadowPropertiesTest { assertThat(compileOnlyApi.dependencies).containsOnly(gradleApi) } - private companion object { + companion object { const val PROJECT_NAME = "my-project" const val VERSION = "1.0.0" diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/BytecodeRemappingTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/BytecodeRemappingTest.kt index 9bbb3c7d6..ea75c822e 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/BytecodeRemappingTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/BytecodeRemappingTest.kt @@ -1,3 +1,5 @@ +@file:OptIn(kotlin.io.path.ExperimentalPathApi::class) + package com.github.jengelman.gradle.plugins.shadow.internal import assertk.assertFailure @@ -9,18 +11,17 @@ import assertk.assertions.isEqualTo import assertk.assertions.isInstanceOf import com.github.jengelman.gradle.plugins.shadow.relocation.SimpleRelocator import com.github.jengelman.gradle.plugins.shadow.testkit.requireResourceAsPath +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.util.noOpDelegate +import de.infix.testBalloon.framework.core.testSuite import java.io.File import java.nio.file.Path import kotlin.io.path.copyTo import kotlin.io.path.createParentDirectories +import kotlin.io.path.createTempDirectory import kotlin.reflect.KClass import org.gradle.api.GradleException import org.gradle.api.file.FileCopyDetails -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.io.TempDir -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.ValueSource import org.vafer.jdeb.shaded.objectweb.asm.AnnotationVisitor import org.vafer.jdeb.shaded.objectweb.asm.ClassReader import org.vafer.jdeb.shaded.objectweb.asm.ClassVisitor @@ -31,15 +32,17 @@ import org.vafer.jdeb.shaded.objectweb.asm.MethodVisitor import org.vafer.jdeb.shaded.objectweb.asm.ModuleVisitor import org.vafer.jdeb.shaded.objectweb.asm.Opcodes +val BytecodeRemappingTests by testSuite { + runTests(::BytecodeRemappingTest) +} + /** * The cases reflect the cases in * [com.github.jengelman.gradle.plugins.shadow.relocation.RelocatorsTest], but operate on the * bytecode level to verify that the remapper correctly transforms class names in all relevant * bytecode structures. */ -class BytecodeRemappingTest { - @TempDir lateinit var tempDir: Path - +private class BytecodeRemappingTest(val tempDir: Path = createTempDirectory()) { // Relocator used across all relocation tests: moves the test package to a distinct target. private val relocators = setOf( @@ -55,7 +58,6 @@ class BytecodeRemappingTest { private val fixtureSubjectDetails get() = FixtureSubject::class.toFileCopyDetails() - @Test fun classNotModified() { val details = fixtureSubjectDetails // Relocator pattern does not match – original bytes must be returned as-is. @@ -66,7 +68,6 @@ class BytecodeRemappingTest { assertThat(result).isEqualTo(details.file.readBytes()) } - @Test fun asmFailureIsWrappedWithClassPath() { val path = "broken/Example.class" val file = tempDir.resolve("broken.class").toFile().apply { writeText("not bytecode") } @@ -82,7 +83,6 @@ class BytecodeRemappingTest { .hasMessage("Error in ASM processing class $path") } - @Test fun classNameIsRelocated() { val result = fixtureSubjectDetails.remapClass(relocators) @@ -90,7 +90,6 @@ class BytecodeRemappingTest { .isEqualTo($$"com/example/relocated/BytecodeRemappingTest$FixtureSubject") } - @Test fun annotationIsRelocated() { val result = fixtureSubjectDetails.remapClass(relocators) @@ -98,7 +97,6 @@ class BytecodeRemappingTest { .contains($$"Lcom/example/relocated/BytecodeRemappingTest$FixtureAnnotation;") } - @Test fun baseClassNameIsRelocated() { // Verify relocation also works on a simple class (FixtureBase has no fields/methods // referencing the target package beyond its own class name). @@ -109,35 +107,30 @@ class BytecodeRemappingTest { assertThat(ClassReader(result).className).isEqualTo(relocatedFixtureBase) } - @Test fun superclassIsRelocated() { val result = fixtureSubjectDetails.remapClass(relocators) assertThat(ClassReader(result).superName).isEqualTo(relocatedFixtureBase) } - @Test fun fieldDescriptorIsRelocated() { val result = fixtureSubjectDetails.remapClass(relocators) assertThat(result.classInfo().fieldDescriptors).contains("L$relocatedFixtureBase;") } - @Test fun arrayFieldDescriptorIsRelocated() { val result = fixtureSubjectDetails.remapClass(relocators) assertThat(result.classInfo().fieldDescriptors).contains("[L$relocatedFixtureBase;") } - @Test fun array2dFieldDescriptorIsRelocated() { val result = fixtureSubjectDetails.remapClass(relocators) assertThat(result.classInfo().fieldDescriptors).contains("[[L$relocatedFixtureBase;") } - @Test fun methodDescriptorIsRelocated() { val result = fixtureSubjectDetails.remapClass(relocators) @@ -145,7 +138,6 @@ class BytecodeRemappingTest { .contains("(L$relocatedFixtureBase;)L$relocatedFixtureBase;") } - @Test fun methodMultipleArgsIsRelocated() { val result = fixtureSubjectDetails.remapClass(relocators) @@ -153,8 +145,6 @@ class BytecodeRemappingTest { .contains("(L$relocatedFixtureBase;L$relocatedFixtureBase;)L$relocatedFixtureBase;") } - @ParameterizedTest - @ValueSource(chars = ['B', 'C', 'D', 'F', 'I', 'J', 'S', 'Z']) fun primitivePlusClassMethodIsRelocated(primitiveDescriptor: Char) { val result = fixtureSubjectDetails.remapClass(relocators) @@ -162,7 +152,6 @@ class BytecodeRemappingTest { .contains("(${primitiveDescriptor}L$relocatedFixtureBase;)L$relocatedFixtureBase;") } - @Test fun stringConstantIsRelocated() { val result = fixtureSubjectDetails.remapClass(relocators) @@ -170,7 +159,6 @@ class BytecodeRemappingTest { .contains($$"com.example.relocated.BytecodeRemappingTest$FixtureBase") } - @Test fun stringConstantNotRelocatedWhenSkipEnabled() { val skipRelocators = setOf( @@ -186,7 +174,6 @@ class BytecodeRemappingTest { .doesNotContain($$"com.example.relocated.BytecodeRemappingTest$FixtureBase") } - @Test fun multiClassDescriptorStringConstantIsRelocated() { val result = fixtureSubjectDetails.remapClass(relocators) @@ -198,7 +185,6 @@ class BytecodeRemappingTest { ) } - @Test fun interfaceIsRelocated() { val result = fixtureSubjectDetails.remapClass(relocators) @@ -206,7 +192,6 @@ class BytecodeRemappingTest { .contains($$"com/example/relocated/BytecodeRemappingTest$FixtureInterface") } - @Test fun signatureIsRelocated() { val result = fixtureSubjectDetails.remapClass(relocators) @@ -214,7 +199,6 @@ class BytecodeRemappingTest { assertThat(checkNotNull(method.signature)).contains("L$relocatedFixtureBase;") } - @Test fun nestedClassSignatureIsRelocated() { val result = fixtureSubjectDetails.remapClass(relocators) @@ -225,7 +209,6 @@ class BytecodeRemappingTest { ) } - @Test fun moduleMainClassIsRelocated() { val originalMainClass = $$"com/github/jengelman/gradle/plugins/shadow/internal/BytecodeRemappingTest$FixtureBase" @@ -264,7 +247,6 @@ class BytecodeRemappingTest { assertThat(remappedMainClass).isEqualTo(relocatedFixtureBase) } - @Test fun localVariableIsRelocated() { val result = fixtureSubjectDetails.remapClass(relocators) @@ -272,7 +254,6 @@ class BytecodeRemappingTest { assertThat(method.localVarDescriptors).contains("L$relocatedFixtureBase;") } - @Test fun instructionIsRelocated() { val result = fixtureSubjectDetails.remapClass(relocators) diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultDependencyFilterTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultDependencyFilterTest.kt index 3d756a4e9..0f719f4c1 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultDependencyFilterTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultDependencyFilterTest.kt @@ -7,19 +7,36 @@ import assertk.assertions.isEqualTo import assertk.assertions.isInstanceOf import assertk.assertions.isTrue import assertk.assertions.messageContains +import com.github.jengelman.gradle.plugins.shadow.testkit.runTest +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.util.noOpDelegate +import de.infix.testBalloon.framework.core.testSuite import org.gradle.api.artifacts.ResolvedDependency import org.gradle.testfixtures.ProjectBuilder -import org.junit.jupiter.api.Test -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.Arguments -import org.junit.jupiter.params.provider.MethodSource -class DefaultDependencyFilterTest { +val DefaultDependencyFilterTests by testSuite { + runTests(::DefaultDependencyFilterTest) + + for ((notation, group, name, version, expected) in + DefaultDependencyFilterTest.dependencyNotationProvider) { + runTest( + "matchesDependencyNotation_${notation}_${group}_${name}_$version", + ::DefaultDependencyFilterTest, + ) { + matchesDependencyNotation(notation, group, name, version, expected) + } + } + + for (notation in DefaultDependencyFilterTest.projectNotationProvider) { + runTest("matchesProjectNotation_${notation}", ::DefaultDependencyFilterTest) { + matchesProjectNotation(notation) + } + } +} + +private class DefaultDependencyFilterTest { private val filter = DefaultDependencyFilter(project) - @ParameterizedTest - @MethodSource("dependencyNotationProvider") fun matchesDependencyNotation( notation: Any, group: String, @@ -33,8 +50,6 @@ class DefaultDependencyFilterTest { assertThat(spec.isSatisfiedBy(dep)).isEqualTo(expected) } - @ParameterizedTest - @MethodSource("projectNotationProvider") fun matchesProjectNotation(notation: Any) { val spec = filter.project(notation) val dep = @@ -47,66 +62,66 @@ class DefaultDependencyFilterTest { assertThat(spec.isSatisfiedBy(dep)).isTrue() } - @Test fun rejectsUnsupportedProjectNotation() { assertFailure { filter.project(42) } .isInstanceOf() .messageContains("Unsupported notation type: class java.lang.Integer") } - private companion object { + companion object { val project = ProjectBuilder.builder().build() val subproject = ProjectBuilder.builder().withName("subproject").withParent(project).build() val projectDependency = project.dependencies.project(mapOf("path" to subproject.path)) val stringNotations = listOf( - Arguments.of("foo:bar", "foo", "bar", "1.0", true), - Arguments.of("f.*:bar", "foo", "bar", "1.0", true), - Arguments.of("foo:bar:.*", "foo", "bar", "1.0", true), - Arguments.of("f.*:bar:.*", "foo", "bar", "1.0", true), - Arguments.of("f.*:bar.*:.*", "foo", "bar", "1.0", true), - Arguments.of(".*:bar:.*", "foo", "bar", "1.0", true), - Arguments.of("foo:bar:2.1.0", "foo", "bar", "2.1.0", true), - Arguments.of("foo:bar:2.1.0", "foo", "baz", "2.1.0", false), - Arguments.of("foo:bar:2.1.0", "bar", "bar", "2.1.0", false), - Arguments.of("foo:bar:1.0.0+1", "foo", "bar", "1.0.0+1", true), - Arguments.of("foo:bar:1.0.0+1", "foo", "bar", "1.0.0+2", false), - Arguments.of("foo:bar:1\\.0\\..*", "foo", "bar", "1.0.5", true), - Arguments.of("foo:bar:1\\.0\\..*", "foo", "bar", "2.0.0", false), - Arguments.of("foo:bar:1.0", "baz", "bar", "1.0", false), - Arguments.of("foo:bar:1.0", "foo", "bar", "2.0", false), - Arguments.of("f.*:bar", "zoo", "bar", "1.0", false), + Tuple5("foo:bar", "foo", "bar", "1.0", true), + Tuple5("f.*:bar", "foo", "bar", "1.0", true), + Tuple5("foo:bar:.*", "foo", "bar", "1.0", true), + Tuple5("f.*:bar:.*", "foo", "bar", "1.0", true), + Tuple5("f.*:bar.*:.*", "foo", "bar", "1.0", true), + Tuple5(".*:bar:.*", "foo", "bar", "1.0", true), + Tuple5("foo:bar:2.1.0", "foo", "bar", "2.1.0", true), + Tuple5("foo:bar:2.1.0", "foo", "baz", "2.1.0", false), + Tuple5("foo:bar:2.1.0", "bar", "bar", "2.1.0", false), + Tuple5("foo:bar:1.0.0+1", "foo", "bar", "1.0.0+1", true), + Tuple5("foo:bar:1.0.0+1", "foo", "bar", "1.0.0+2", false), + Tuple5("foo:bar:1\\.0\\..*", "foo", "bar", "1.0.5", true), + Tuple5("foo:bar:1\\.0\\..*", "foo", "bar", "2.0.0", false), + Tuple5("foo:bar:1.0", "baz", "bar", "1.0", false), + Tuple5("foo:bar:1.0", "foo", "bar", "2.0", false), + Tuple5("f.*:bar", "zoo", "bar", "1.0", false), ) val providerNotations = - listOf(Arguments.of(project.provider { "foo:bar:1.0" }, "foo", "bar", "1.0", true)) + listOf(Tuple5(project.provider { "foo:bar:1.0" }, "foo", "bar", "1.0", true)) val mapNotations = listOf( - Arguments.of( + Tuple5( mapOf("group" to "foo", "name" to "bar", "version" to "1.0"), "foo", "bar", "1.0", true, ), - Arguments.of(mapOf("name" to "bar"), "any.group", "bar", "1.0", true), + Tuple5(mapOf("name" to "bar"), "any.group", "bar", "1.0", true), ) - @JvmStatic fun dependencyNotationProvider() = stringNotations + providerNotations + mapNotations + val dependencyNotationProvider = stringNotations + providerNotations + mapNotations - @JvmStatic - fun projectNotationProvider() = + val projectNotationProvider = listOf( - Arguments.of(subproject.path), - Arguments.of(project.provider { subproject.path }), - Arguments.of(mapOf("path" to subproject.path)), - Arguments.of(projectDependency), + subproject.path, + project.provider { subproject.path }, + mapOf("path" to subproject.path), + projectDependency, ) } } +data class Tuple5(val a: A, val b: B, val c: C, val d: D, val e: E) + private class TestResolvedDependency( private val group: String, private val name: String, diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DuplicatesStrategyCheckerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DuplicatesStrategyCheckerTest.kt index c91845708..ed8c22d8e 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DuplicatesStrategyCheckerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DuplicatesStrategyCheckerTest.kt @@ -1,14 +1,19 @@ +@file:OptIn(kotlin.io.path.ExperimentalPathApi::class) + package com.github.jengelman.gradle.plugins.shadow.internal import assertk.assertThat import assertk.assertions.isEqualTo +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.transformers.BaseTransformerTest.Companion.canTransformResource import com.github.jengelman.gradle.plugins.shadow.transformers.ResourceTransformer import com.github.jengelman.gradle.plugins.shadow.transformers.ResourceTransformer.Companion.create import com.github.jengelman.gradle.plugins.shadow.util.testObjectFactory +import de.infix.testBalloon.framework.core.testSuite import java.io.File import java.net.JarURLConnection import java.nio.file.Path +import kotlin.io.path.createTempDirectory import kotlin.io.path.createTempFile import kotlin.io.path.exists import kotlin.io.path.extension @@ -16,13 +21,12 @@ import kotlin.io.path.isRegularFile import kotlin.io.path.toPath import kotlin.io.path.walk import kotlin.reflect.full.isSubclassOf -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.io.TempDir -class DuplicatesStrategyCheckerTest { - @TempDir lateinit var tempDir: Path +val DuplicatesStrategyCheckerTests by testSuite { + runTests(::DuplicatesStrategyCheckerTest) +} - @Test +private class DuplicatesStrategyCheckerTest(val tempDir: Path = createTempDirectory()) { fun checkDupStrategyInvocationCount() { val allResourceTransformers = getTransformerClasses().map { diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/MinimizeSpecsTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/MinimizeSpecsTest.kt index 0c3b5d006..95046a1e5 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/MinimizeSpecsTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/MinimizeSpecsTest.kt @@ -9,20 +9,23 @@ import assertk.assertions.isNull import assertk.assertions.isSameInstanceAs import assertk.assertions.isTrue import com.github.jengelman.gradle.plugins.shadow.tasks.MinimizeTool +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests +import de.infix.testBalloon.framework.core.testSuite import org.gradle.testfixtures.ProjectBuilder -import org.junit.jupiter.api.Test -class MinimizeSpecsTest { +val MinimizeSpecsTests by testSuite { + runTests(::MinimizeSpecsTest) +} + +private class MinimizeSpecsTest { private val project = ProjectBuilder.builder().build() - @Test fun defaultMinimizeSpecUsesDependencyAnalyzer() = with(project.objects.newInstance(DefaultMinimizeSpec::class.java, project)) { assertThat(tool.get()).isEqualTo(MinimizeTool.DEPENDENCY_ANALYZER) assertThat(r8SpecForInputs).isNull() } - @Test fun r8ConfiguresToolAndExposesSameSpecAsInput() = with(project.objects.newInstance(DefaultMinimizeSpec::class.java, project)) { lateinit var configured: Any @@ -33,7 +36,6 @@ class MinimizeSpecsTest { assertThat(r8Spec).isSameInstanceAs(configured) } - @Test fun defaultR8SpecIsShrinkOnly() = with(project.objects.newInstance(DefaultR8Spec::class.java)) { assertThat(args.get()).containsExactly(DefaultR8Spec.NO_MINIFICATION_ARG) @@ -47,7 +49,6 @@ class MinimizeSpecsTest { ) } - @Test fun enablingObfuscationRemovesDefaultArgument() = with(project.objects.newInstance(DefaultR8Spec::class.java)) { enableObfuscation() @@ -57,7 +58,6 @@ class MinimizeSpecsTest { assertThat(optimizationEnabled.get()).isFalse() } - @Test fun enablingOptimizationOnlyChangesOptimizationFlag() = with(project.objects.newInstance(DefaultR8Spec::class.java)) { enableOptimization() @@ -67,7 +67,6 @@ class MinimizeSpecsTest { assertThat(optimizationEnabled.get()).isTrue() } - @Test fun explicitArgumentsTakePrecedenceOverChangedDefaults() = with(project.objects.newInstance(DefaultR8Spec::class.java)) { args.set(listOf("--debug")) diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/R8MinimizerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/R8MinimizerTest.kt index af5b2bd5d..c3096294e 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/R8MinimizerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/R8MinimizerTest.kt @@ -1,18 +1,24 @@ +@file:OptIn(kotlin.io.path.ExperimentalPathApi::class) + package com.github.jengelman.gradle.plugins.shadow.internal import assertk.assertThat import assertk.assertions.isEqualTo +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.util.zipOutputStream +import de.infix.testBalloon.framework.core.testSuite import java.nio.file.Path +import kotlin.io.path.createTempDirectory import org.apache.tools.zip.UnixStat import org.apache.tools.zip.ZipFile import org.gradle.api.tasks.bundling.ZipEntryCompression -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.io.TempDir -class R8MinimizerTest { - @Test - fun normalizeJarPreservesUnixPermissions(@TempDir tempDir: Path) { +val R8MinimizerTests by testSuite { + runTests(::R8MinimizerTest) +} + +private class R8MinimizerTest(val tempDir: Path = createTempDirectory()) { + fun normalizeJarPreservesUnixPermissions() { val inputJar = tempDir.resolve("input.jar") val outputJar = tempDir.resolve("output.jar") val expectedExecutableMode = UnixStat.FILE_FLAG or 493 // 0755 octal diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/ReproduciblePropertiesTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/ReproduciblePropertiesTest.kt index f9ae183ab..582ce8c6a 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/ReproduciblePropertiesTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/ReproduciblePropertiesTest.kt @@ -3,22 +3,31 @@ package com.github.jengelman.gradle.plugins.shadow.internal import assertk.assertThat import assertk.assertions.isEqualTo import com.github.jengelman.gradle.plugins.shadow.testkit.invariantEolString +import de.infix.testBalloon.framework.core.testSuite import java.io.ByteArrayOutputStream import java.nio.charset.Charset -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.MethodSource -class ReproduciblePropertiesTest { - @ParameterizedTest - @MethodSource("generalCharsetsProvider") +val ReproduciblePropertiesTests by testSuite { + val subject = ReproduciblePropertiesTest() + + for (charset in ReproduciblePropertiesTest.generalCharsetsProvider) { + test("emptyProperties_${charset.name()}") { subject.emptyProperties(charset) } + test("asciiProps_${charset.name()}") { subject.asciiProps(charset) } + test("escapesSpecialCharacters_${charset.name()}") { subject.escapesSpecialCharacters(charset) } + } + + for (charset in ReproduciblePropertiesTest.utfCharsetsProvider) { + test("utfProps_${charset.name()}") { subject.utfProps(charset) } + } +} + +private class ReproduciblePropertiesTest { fun emptyProperties(charset: Charset) { val output = ReproducibleProperties().writeToString(charset) assertThat(output).isEqualTo("") } - @ParameterizedTest - @MethodSource("generalCharsetsProvider") fun asciiProps(charset: Charset) { val output = ReproducibleProperties() @@ -50,8 +59,6 @@ class ReproduciblePropertiesTest { ) } - @ParameterizedTest - @MethodSource("utfCharsetsProvider") fun utfProps(charset: Charset) { val output = ReproducibleProperties() @@ -75,8 +82,6 @@ class ReproduciblePropertiesTest { ) } - @ParameterizedTest - @MethodSource("generalCharsetsProvider") fun escapesSpecialCharacters(charset: Charset) { val output = ReproducibleProperties() @@ -94,14 +99,13 @@ class ReproduciblePropertiesTest { ) } - private companion object Companion { - @JvmStatic - fun generalCharsetsProvider() = - listOf(Charsets.ISO_8859_1, Charsets.US_ASCII) + utfCharsetsProvider() + companion object Companion { + val utfCharsetsProvider = listOf(Charsets.UTF_8, Charsets.UTF_16) - @JvmStatic fun utfCharsetsProvider() = listOf(Charsets.UTF_8, Charsets.UTF_16) + val generalCharsetsProvider = + listOf(Charsets.ISO_8859_1, Charsets.US_ASCII) + utfCharsetsProvider - fun ReproducibleProperties.writeToString(charset: Charset): String { + internal fun ReproducibleProperties.writeToString(charset: Charset): String { return ByteArrayOutputStream() .also { writeWithoutComments(charset, it) } .toString(charset.name()) diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/ZipEntryValidationTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/ZipEntryValidationTest.kt index 6112e3734..78d0a9465 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/ZipEntryValidationTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/ZipEntryValidationTest.kt @@ -1,3 +1,5 @@ +@file:OptIn(kotlin.io.path.ExperimentalPathApi::class) + package com.github.jengelman.gradle.plugins.shadow.internal import assertk.assertFailure @@ -6,28 +8,31 @@ import assertk.assertions.hasMessage import assertk.assertions.isEqualTo import assertk.assertions.isInstanceOf import assertk.assertions.isTrue +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.util.zipOutputStream +import de.infix.testBalloon.framework.core.testSuite import java.io.ByteArrayOutputStream import java.nio.file.Path import java.util.Properties import java.util.zip.ZipInputStream +import kotlin.io.path.createTempDirectory import org.apache.tools.zip.UnixStat import org.apache.tools.zip.ZipFile import org.apache.tools.zip.ZipOutputStream import org.gradle.api.GradleException -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.io.TempDir -class ZipEntryValidationTest { +val ZipEntryValidationTests by testSuite { + runTests(::ZipEntryValidationTest) +} + +private class ZipEntryValidationTest(val tempDir: Path = createTempDirectory()) { - @Test fun parentDirectoryEntriesAreOrderedFromRootToLeaf() { assertThat("foo/bar/baz.txt".parentDirectoryEntries()).isEqualTo(listOf("foo/", "foo/bar/")) assertThat("file.txt".parentDirectoryEntries()).isEqualTo(emptyList()) } - @Test - fun writeEntryUsesRequestedOrReproducibleTimestampAndAppliesUnixMode(@TempDir tempDir: Path) { + fun writeEntryUsesRequestedOrReproducibleTimestampAndAppliesUnixMode() { val requestedTimestamp = 1_700_000_000_000 val archive = tempDir.resolve("output.jar").toFile() ZipOutputStream(archive).use { output -> @@ -57,7 +62,6 @@ class ZipEntryValidationTest { } } - @Test fun propertiesInputStreamUsesRequestedCharsetAndComments() { val properties = Properties().apply { setProperty("greeting", "你好") } @@ -70,7 +74,6 @@ class ZipEntryValidationTest { assertThat(loaded.getProperty("greeting")).isEqualTo("你好") } - @Test fun validZipEntryNamesDoNotThrow() { val validNames = listOf( @@ -101,7 +104,6 @@ class ZipEntryValidationTest { assertThat(names).isEqualTo(validNames.toSet()) } - @Test fun maliciousZipEntryNamesWithPathTraversalThrowException() { val maliciousNames = listOf( diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/RelocatorsTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/RelocatorsTest.kt index 55f8c48b7..fb3196710 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/RelocatorsTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/RelocatorsTest.kt @@ -3,14 +3,14 @@ package com.github.jengelman.gradle.plugins.shadow.relocation import assertk.assertThat import assertk.assertions.isEqualTo import com.github.jengelman.gradle.plugins.shadow.internal.mapName -import org.junit.jupiter.api.Test -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.Arguments -import org.junit.jupiter.params.provider.MethodSource +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests +import de.infix.testBalloon.framework.core.testSuite -class RelocatorsTest { - @ParameterizedTest - @MethodSource("signaturePatternsProvider") +val RelocatorsTests by testSuite { + runTests(::RelocatorsTest) +} + +private class RelocatorsTest { fun relocateSignaturePatterns(input: String, expected: String) { val actual = setOf(SimpleRelocator("org.package", "shadow.org.package")).mapName(name = input) assertThat(actual).isEqualTo(expected) @@ -20,7 +20,6 @@ class RelocatorsTest { * Verifies that a relocator with [Relocator.skipStringConstants] = true is skipped individually * when mapping literals, rather than short-circuiting the entire set of relocators. */ - @Test fun skipStringConstantsIsPerRelocator() { val skippingRelocator = SimpleRelocator("org.package", "shadow.org.package", skipStringConstants = true) @@ -40,68 +39,45 @@ class RelocatorsTest { .isEqualTo("shadow.org.package.Bar") } - private companion object { + companion object { val primitiveTypes = setOf('B', 'C', 'D', 'F', 'I', 'J', 'S', 'Z') val primitiveTypePatterns = primitiveTypes.map { // Methods like `void method(boolean arg1, org.package.ClassA arg2)` - Arguments.of("(${it}Lorg/package/ClassA;)V", "(${it}Lshadow/org/package/ClassA;)V") + "(${it}Lorg/package/ClassA;)V" to "(${it}Lshadow/org/package/ClassA;)V" } - @JvmStatic - fun signaturePatternsProvider() = + val signaturePatternsProvider = listOf( // Normal class: `org.package.ClassA` - Arguments.of("Lorg/package/ClassA;", "Lshadow/org/package/ClassA;"), + "Lorg/package/ClassA;" to "Lshadow/org/package/ClassA;", // Array class: `org.package.ClassA[]` - Arguments.of("[Lorg/package/ClassA;", "[Lshadow/org/package/ClassA;"), + "[Lorg/package/ClassA;" to "[Lshadow/org/package/ClassA;", // Multidimensional array of class: `org.package.ClassA[][]` - Arguments.of("[[Lorg/package/ClassA;", "[[Lshadow/org/package/ClassA;"), + "[[Lorg/package/ClassA;" to "[[Lshadow/org/package/ClassA;", // Multiple classes: `org.package.ClassA org.package.ClassB` - Arguments.of( - "Lorg/package/ClassA;Lorg/package/ClassB;", + "Lorg/package/ClassA;Lorg/package/ClassB;" to "Lshadow/org/package/ClassA;Lshadow/org/package/ClassB;", - ), // Multiple classes: `java.lang.Object org.package.ClassB` - Arguments.of( - "Ljava/lang/Object;Lorg/package/ClassB;", - "Ljava/lang/Object;Lshadow/org/package/ClassB;", - ), + "Ljava/lang/Object;Lorg/package/ClassB;" to "Ljava/lang/Object;Lshadow/org/package/ClassB;", // Single method argument: `void method(org.package.ClassA arg);` - Arguments.of("(Lorg/package/ClassA;)", "(Lshadow/org/package/ClassA;)"), + "(Lorg/package/ClassA;)" to "(Lshadow/org/package/ClassA;)", // Method arguments: `void method(org.package.ClassA arg1, org.package.ClassB arg2);` - Arguments.of( - "(Lorg/package/ClassA;Lorg/package/ClassB;)", + "(Lorg/package/ClassA;Lorg/package/ClassB;)" to "(Lshadow/org/package/ClassA;Lshadow/org/package/ClassB;)", - ), // Example from issue 1403. - Arguments.of( - "()Lorg/package/ClassA;Lorg/package/ClassB;", + "()Lorg/package/ClassA;Lorg/package/ClassB;" to "()Lshadow/org/package/ClassA;Lshadow/org/package/ClassB;", - ), // Class name in slashy format (used in capturing class, impl class, and functional // interface class of SerializedLambda) - Arguments.of( - "org/package/ClassA", - "shadow/org/package/ClassA", - ), + "org/package/ClassA" to "shadow/org/package/ClassA", // Method descriptor formats found in lambda deserialization metadata - Arguments.of( - "(Lorg/package/ClassA;)Ljava/lang/String;", + "(Lorg/package/ClassA;)Ljava/lang/String;" to "(Lshadow/org/package/ClassA;)Ljava/lang/String;", - ), - Arguments.of( - "(Lorg/package/ClassA;I)V", - "(Lshadow/org/package/ClassA;I)V", - ), - Arguments.of( - "(ILorg/package/ClassA;)V", - "(ILshadow/org/package/ClassA;)V", - ), - Arguments.of( - "(Lorg/package/ClassA;Lorg/package/ClassB;)Lorg/package/ClassA;", + "(Lorg/package/ClassA;I)V" to "(Lshadow/org/package/ClassA;I)V", + "(ILorg/package/ClassA;)V" to "(ILshadow/org/package/ClassA;)V", + "(Lorg/package/ClassA;Lorg/package/ClassB;)Lorg/package/ClassA;" to "(Lshadow/org/package/ClassA;Lshadow/org/package/ClassB;)Lshadow/org/package/ClassA;", - ), ) + primitiveTypePatterns } } diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocatorTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocatorTest.kt index 4a88226aa..c509c843e 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocatorTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocatorTest.kt @@ -4,15 +4,19 @@ import assertk.assertThat import assertk.assertions.isEqualTo import assertk.assertions.isFalse import assertk.assertions.isTrue -import org.junit.jupiter.api.Test +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests +import de.infix.testBalloon.framework.core.testSuite + +val SimpleRelocatorTests by testSuite { + runTests(::SimpleRelocatorTest) +} /** * Modified from * [org.apache.maven.plugins.shade.relocation.SimpleRelocatorTest.java](https://github.com/apache/maven-shade-plugin/blob/master/src/test/java/org/apache/maven/plugins/shade/relocation/SimpleRelocatorTest.java). */ -class SimpleRelocatorTest { +private class SimpleRelocatorTest { - @Test fun canRelocatePath() { var relocator = SimpleRelocator("org.foo") assertThat(relocator.canRelocatePath("org/foo/Class")).isTrue() @@ -82,7 +86,6 @@ class SimpleRelocatorTest { assertThat(relocator.canRelocatePath("foo/foobar")).isFalse() // File without extension. } - @Test fun canRelocatePathWithRegex() { // Include with Regex var relocator = SimpleRelocator("org.foo", includes = listOf("%regex[org/foo/R(\\$.*)?$]")) @@ -116,7 +119,6 @@ class SimpleRelocatorTest { assertThat(relocator.canRelocatePath("org/foo/R.class")).isFalse() } - @Test fun canRelocateClass() { var relocator = SimpleRelocator("org.foo") assertThat(relocator.canRelocateClass("org.foo.Class")).isTrue() @@ -152,7 +154,6 @@ class SimpleRelocatorTest { assertThat(relocator.canRelocateClass("org.foo.recurse.sub.Class")).isFalse() } - @Test fun canRelocateRawString() { var relocator = SimpleRelocator("org/foo", rawString = true) assertThat(relocator.canRelocatePath("(I)org/foo/bar/Class;")).isTrue() @@ -161,14 +162,12 @@ class SimpleRelocatorTest { assertThat(relocator.canRelocatePath("META-INF/org.foo.xml")).isTrue() } - @Test fun canRelocateAbsClassPath() { val relocator = SimpleRelocator("org.apache.velocity", "org.apache.momentum") assertThat(relocator.relocatePath("/org/apache/velocity/mass.properties")) .isEqualTo("/org/apache/momentum/mass.properties") } - @Test fun canRelocateAbsClassPathWithExcludes() { val relocator = SimpleRelocator( @@ -182,7 +181,6 @@ class SimpleRelocatorTest { assertThat(relocator.canRelocatePath("org/apache/velocity/excluded/mass.properties")).isFalse() } - @Test fun canRelocateAbsClassPathWithIncludes() { val relocator = SimpleRelocator( @@ -196,7 +194,6 @@ class SimpleRelocatorTest { assertThat(relocator.canRelocatePath("org/apache/velocity/included/mass.properties")).isTrue() } - @Test fun relocatePath() { var relocator = SimpleRelocator("org.foo") assertThat(relocator.relocatePath("org/foo/bar/Class.class")) @@ -210,7 +207,6 @@ class SimpleRelocatorTest { .isEqualTo("private/stuff/bar/Class.class") } - @Test fun relocateClass() { var relocator = SimpleRelocator("org.foo") assertThat(relocator.relocateClass("org.foo.bar.Class")).isEqualTo("hidden.org.foo.bar.Class") @@ -219,7 +215,6 @@ class SimpleRelocatorTest { assertThat(relocator.relocateClass("org.foo.bar.Class")).isEqualTo("private.stuff.bar.Class") } - @Test fun relocateRawString() { var relocator = SimpleRelocator("Lorg/foo", "Lhidden/org/foo", rawString = true) assertThat(relocator.relocatePath("(I)Lorg/foo/bar/Class;")) @@ -231,7 +226,6 @@ class SimpleRelocatorTest { .isEqualTo("META-INF/hidden.org.foo.xml") } - @Test fun relocateMavenFiles() { val relocator = SimpleRelocator( @@ -250,7 +244,6 @@ class SimpleRelocatorTest { assertThat(relocator.canRelocatePath("META-INF/maven/com-foo-bar/artifactId/pom.xml")).isTrue() } - @Test fun canRelocateExcludedSourceFile() { val relocator = SimpleRelocator( @@ -276,7 +269,6 @@ class SimpleRelocatorTest { assertThat(relocator.canRelocatePath("org/foo/Class.class")).isTrue() } - @Test fun canRelocateExcludedSourceFileWithRegex() { val relocator = SimpleRelocator( @@ -298,7 +290,6 @@ class SimpleRelocatorTest { assertThat(relocator.canRelocatePath("org/foo/Class.class")).isTrue() } - @Test fun canRelocateIncludedSourceFile() { val relocator = SimpleRelocator( @@ -323,7 +314,6 @@ class SimpleRelocatorTest { assertThat(relocator.canRelocatePath("org/foo/Class.class")).isFalse() } - @Test fun canRelocateIncludedSourceFileWithRegex() { val relocator = SimpleRelocator( @@ -344,7 +334,6 @@ class SimpleRelocatorTest { assertThat(relocator.canRelocatePath("org/foo/Class.class")).isFalse() } - @Test fun relocateSourceWithExcludesRaw() { val relocator = SimpleRelocator( @@ -357,7 +346,6 @@ class SimpleRelocatorTest { assertThat(relocator.applyToSourceContent(sourceFile)).isEqualTo(sourceFile) } - @Test fun relocateSourceWithExcludes() { // Main relocator with in-/excludes val relocator = @@ -383,7 +371,7 @@ class SimpleRelocatorTest { .isEqualTo(relocatedFile) } - private companion object { + companion object { val sourceFile = """ |package org.apache.maven.hello; diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformerTest.kt index f48c65a8a..da0d5825a 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformerTest.kt @@ -3,20 +3,24 @@ package com.github.jengelman.gradle.plugins.shadow.transformers import assertk.assertThat import assertk.assertions.isFalse import assertk.assertions.isTrue -import org.junit.jupiter.api.Test +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests +import de.infix.testBalloon.framework.core.testSuite + +val ApacheLicenseResourceTransformerTests by testSuite { + runTests(::ApacheLicenseResourceTransformerTest) +} /** * Modified from * [org.apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformerTest.java](https://github.com/apache/maven-shade-plugin/blob/master/src/test/java/org/apache/maven/plugins/shade/resource/ApacheLicenseResourceTransformerTest.java). */ -class ApacheLicenseResourceTransformerTest : +private class ApacheLicenseResourceTransformerTest : BaseTransformerTest() { init { setupTurkishLocale() } - @Test fun canTransformResource() = with(transformer) { assertThat(canTransformResource("META-INF/LICENSE")).isTrue() @@ -27,7 +31,6 @@ class ApacheLicenseResourceTransformerTest : assertThat(canTransformResource("META-INF/MANIFEST.MF")).isFalse() } - @Test fun canTransformByPattern() = with(transformer) { exclude("META-INF/LICENSE.txt") diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformerTest.kt index e694649b7..33435f580 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformerTest.kt @@ -6,23 +6,28 @@ import assertk.assertions.isEqualTo import assertk.assertions.isFalse import assertk.assertions.isTrue import com.github.jengelman.gradle.plugins.shadow.testkit.getContent +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests +import de.infix.testBalloon.framework.core.testSuite import java.io.ByteArrayOutputStream import java.nio.charset.Charset import java.util.zip.ZipInputStream import org.apache.tools.zip.ZipOutputStream -import org.junit.jupiter.api.Test + +val ApacheNoticeResourceTransformerTests by testSuite { + runTests(::ApacheNoticeResourceTransformerTest) +} /** * Modified from * [org.apache.maven.plugins.shade.resource.ApacheNoticeResourceTransformerTest.java](https://github.com/apache/maven-shade-plugin/blob/master/src/test/java/org/apache/maven/plugins/shade/resource/ApacheNoticeResourceTransformerTest.java). */ -class ApacheNoticeResourceTransformerTest : BaseTransformerTest() { +private class ApacheNoticeResourceTransformerTest : + BaseTransformerTest() { init { setupTurkishLocale() } - @Test fun canTransformResource() = with(transformer) { assertThat(canTransformResource("META-INF/NOTICE")).isTrue() @@ -33,7 +38,6 @@ class ApacheNoticeResourceTransformerTest : BaseTransformerTest() { +private class AppendingTransformerTest : BaseTransformerTest() { init { setupTurkishLocale() } - @Test fun canTransformResource() = with(transformer) { resource.set("abcdefghijklmnopqrstuvwxyz") @@ -30,7 +34,6 @@ class AppendingTransformerTest : BaseTransformerTest() { assertThat(canTransformResource("META-INF/MANIFEST.MF")).isFalse() } - @Test fun appendResources() = with(transformer) { resource.set("test.properties") @@ -44,7 +47,6 @@ class AppendingTransformerTest : BaseTransformerTest() { assertThat(content).isEqualTo("foo=bar\nbaz=qux") } - @Test fun appendResourcesWithCustomSeparator() = with(transformer) { resource.set("application.yml") diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/BaseTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/BaseTransformerTest.kt index 1073f1310..36fcb161b 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/BaseTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/BaseTransformerTest.kt @@ -11,36 +11,29 @@ import java.lang.reflect.ParameterizedType import java.nio.file.Path import java.util.Locale import java.util.jar.JarFile.MANIFEST_NAME +import kotlin.io.path.createTempDirectory import kotlin.io.path.createTempFile import kotlin.io.path.outputStream import org.apache.tools.zip.ZipOutputStream import org.gradle.api.file.FileTreeElement import org.gradle.api.file.RelativePath -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.io.TempDir -abstract class BaseTransformerTest { - lateinit var transformer: T - private set +abstract class BaseTransformerTest( + val tempDir: Path = createTempDirectory() +) { + val transformer: T val manifestTransformerContext: TransformerContext get() = TransformerContext(MANIFEST_NAME, requireResourceAsStream(MANIFEST_NAME)) - @TempDir - lateinit var tempDir: Path - private set + val tempJar: Path = createTempFile(directory = tempDir, suffix = ".jar") - lateinit var tempJar: Path - private set - - @BeforeEach - open fun beforeEach() { + init { @Suppress("UNCHECKED_CAST") val clazz = (this::class.java.genericSuperclass as ParameterizedType).actualTypeArguments.single() as Class transformer = clazz.create(testObjectFactory) - tempJar = createTempFile(directory = tempDir, suffix = ".jar") } companion object { diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformerTest.kt index ee999d03b..b88f43a3e 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformerTest.kt @@ -3,17 +3,21 @@ package com.github.jengelman.gradle.plugins.shadow.transformers import assertk.assertThat import assertk.assertions.isTrue import com.github.jengelman.gradle.plugins.shadow.testkit.requireResourceAsPath +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests +import de.infix.testBalloon.framework.core.testSuite import kotlin.io.path.readText import org.custommonkey.xmlunit.XMLUnit -import org.junit.jupiter.api.Test + +val ComponentsXmlResourceTransformerTests by testSuite { + runTests(::ComponentsXmlResourceTransformerTest) +} /** * Modified from * [org.apache.maven.plugins.shade.resource.ComponentsXmlResourceTransformerTest.java](https://github.com/apache/maven-shade-plugin/blob/master/src/test/java/org/apache/maven/plugins/shade/resource/ComponentsXmlResourceTransformerTest.java). */ -class ComponentsXmlResourceTransformerTest : +private class ComponentsXmlResourceTransformerTest : BaseTransformerTest() { - @Test fun configurationMerging() = with(transformer) { XMLUnit.setNormalizeWhitespace(true) diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/DeduplicatingResourceTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/DeduplicatingResourceTransformerTest.kt index d129e5efe..a16734d26 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/DeduplicatingResourceTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/DeduplicatingResourceTransformerTest.kt @@ -9,30 +9,29 @@ import assertk.assertions.isEqualTo import assertk.assertions.isFalse import assertk.assertions.isInstanceOf import assertk.assertions.isTrue +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.transformers.DeduplicatingResourceTransformer.Companion.sha256Hex import com.github.jengelman.gradle.plugins.shadow.util.zipOutputStream +import de.infix.testBalloon.framework.core.testSuite import java.io.File import kotlin.io.path.writeText import org.gradle.api.GradleException -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.ValueSource -class DeduplicatingResourceTransformerTest : +val DeduplicatingResourceTransformerTests by testSuite { + runTests(::DeduplicatingResourceTransformerTest) +} + +private class DeduplicatingResourceTransformerTest : BaseTransformerTest() { - private lateinit var file1: File - private lateinit var file2: File - private lateinit var file3: File + private var file1: File + private var file2: File + private var file3: File private var hash1 = "" private var hash3 = "" - @BeforeEach - override fun beforeEach() { - super.beforeEach() - + init { val content1 = "content1" val content2 = "content2" file1 = tempDir.resolve("file1").apply { writeText(content1) }.toFile() @@ -42,7 +41,6 @@ class DeduplicatingResourceTransformerTest : hash3 = file3.sha256Hex() } - @Test fun sha256Hex() { val file = tempDir.resolve("sha256").apply { writeText("content") } @@ -50,8 +48,6 @@ class DeduplicatingResourceTransformerTest : .isEqualTo("ed7002b439e9ac845f22357d822bac1444730fbdb6016d3ec9432297b9ec9f73") } - @ParameterizedTest - @ValueSource(booleans = [false, true]) fun duplicateContent(exclusionCheck: Boolean) = with(transformer) { if (!exclusionCheck) { @@ -115,7 +111,6 @@ class DeduplicatingResourceTransformerTest : } } - @Test fun modifyOutputStreamReportsDuplicateContent() = with(transformer) { canTransformResource("differing-content", file1) diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformerTest.kt index 58d517b40..78661cdd8 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformerTest.kt @@ -7,6 +7,7 @@ import assertk.assertions.isTrue import com.github.jengelman.gradle.plugins.shadow.relocation.SimpleRelocator import com.github.jengelman.gradle.plugins.shadow.testkit.JarPath import com.github.jengelman.gradle.plugins.shadow.testkit.getContent +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.transformers.GroovyExtensionModuleTransformer.Companion.KEY_EXTENSION_CLASSES import com.github.jengelman.gradle.plugins.shadow.transformers.GroovyExtensionModuleTransformer.Companion.KEY_MODULE_NAME import com.github.jengelman.gradle.plugins.shadow.transformers.GroovyExtensionModuleTransformer.Companion.KEY_MODULE_VERSION @@ -16,17 +17,17 @@ import com.github.jengelman.gradle.plugins.shadow.transformers.GroovyExtensionMo import com.github.jengelman.gradle.plugins.shadow.transformers.GroovyExtensionModuleTransformer.Companion.PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR import com.github.jengelman.gradle.plugins.shadow.transformers.GroovyExtensionModuleTransformer.Companion.PATH_LEGACY_GROOVY_EXTENSION_MODULE_DESCRIPTOR import com.github.jengelman.gradle.plugins.shadow.util.zipOutputStream +import de.infix.testBalloon.framework.core.testSuite import java.io.StringReader import java.util.Properties -import org.junit.jupiter.api.Test -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.Arguments -import org.junit.jupiter.params.provider.MethodSource -class GroovyExtensionModuleTransformerTest : +val GroovyExtensionModuleTransformerTests by testSuite { + runTests(::GroovyExtensionModuleTransformerTest) +} + +private class GroovyExtensionModuleTransformerTest : BaseTransformerTest() { - @Test fun canTransformResource() = with(transformer) { assertThat(canTransformResource(PATH_LEGACY_GROOVY_EXTENSION_MODULE_DESCRIPTOR)).isTrue() @@ -34,8 +35,6 @@ class GroovyExtensionModuleTransformerTest : assertThat(canTransformResource("META-INF/MANIFEST.MF")).isFalse() } - @ParameterizedTest - @MethodSource("resourcePathProvider") fun mergeDescriptors(fooEntry: String, barEntry: String) = with(GroovyExtensionModuleTransformer()) { transform(textContext(fooEntry, FOO_DESCRIPTOR)) @@ -56,7 +55,6 @@ class GroovyExtensionModuleTransformerTest : .isEqualTo("$STATIC_EXTENSION_CLASSES_FOO,$STATIC_EXTENSION_CLASSES_BAR") } - @Test fun groovyExtensionModuleTransformerWithRelocation() = with(GroovyExtensionModuleTransformer()) { val relocator = SimpleRelocator("com.acme", "com.example.shaded.acme") @@ -83,7 +81,7 @@ class GroovyExtensionModuleTransformerTest : ) } - private companion object { + companion object { const val EXTENSION_CLASSES_FOO = "com.acme.foo.FooExtension,com.acme.foo.BarExtension" const val EXTENSION_CLASSES_BAR = "com.acme.bar.SomeExtension,com.acme.bar.AnotherExtension" const val STATIC_EXTENSION_CLASSES_FOO = "com.acme.foo.FooStaticExtension" @@ -109,22 +107,21 @@ class GroovyExtensionModuleTransformerTest : fun String.toProperties() = Properties().apply { load(StringReader(this@toProperties)) } - @JvmStatic - fun resourcePathProvider() = + val resourcePathProvider = listOf( - Arguments.of( + Pair( PATH_LEGACY_GROOVY_EXTENSION_MODULE_DESCRIPTOR, PATH_LEGACY_GROOVY_EXTENSION_MODULE_DESCRIPTOR, ), - Arguments.of( + Pair( PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR, PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR, ), - Arguments.of( + Pair( PATH_LEGACY_GROOVY_EXTENSION_MODULE_DESCRIPTOR, PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR, ), - Arguments.of( + Pair( PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR, PATH_LEGACY_GROOVY_EXTENSION_MODULE_DESCRIPTOR, ), diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/KotlinModuleMetadataTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/KotlinModuleMetadataTransformerTest.kt index 08e44d04f..db15da4b1 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/KotlinModuleMetadataTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/KotlinModuleMetadataTransformerTest.kt @@ -12,15 +12,20 @@ import com.github.jengelman.gradle.plugins.shadow.relocation.SimpleRelocator import com.github.jengelman.gradle.plugins.shadow.testkit.JarPath import com.github.jengelman.gradle.plugins.shadow.testkit.getBytes import com.github.jengelman.gradle.plugins.shadow.testkit.requireResourceAsStream +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.util.zipOutputStream +import de.infix.testBalloon.framework.core.testSuite import kotlin.metadata.jvm.KotlinModuleMetadata import kotlin.metadata.jvm.UnstableMetadataApi -import org.junit.jupiter.api.Test + +val KotlinModuleMetadataTransformerTests by testSuite { + runTests(::KotlinModuleMetadataTransformerTest) +} @OptIn(UnstableMetadataApi::class) -class KotlinModuleMetadataTransformerTest : BaseTransformerTest() { +private class KotlinModuleMetadataTransformerTest : + BaseTransformerTest() { - @Test fun canTransformResource() = with(transformer) { assertThat(canTransformResource("META-INF/kotlin-stdlib.kotlin_module")).isTrue() @@ -28,7 +33,6 @@ class KotlinModuleMetadataTransformerTest : BaseTransformerTest() { - @Test fun canTransformResource() = with(transformer) { assertThat(canTransformResource("")).isFalse() @@ -45,7 +57,6 @@ class Log4j2PluginsCacheFileTransformerTest : assertThat(canTransformResource(PLUGIN_CACHE_FILE)).isTrue() } - @Test fun relocateClassesInsideDatFile() = with(transformer) { val relocator = SimpleRelocator("org.apache.logging", "new.location.org.apache.logging") @@ -56,8 +67,6 @@ class Log4j2PluginsCacheFileTransformerTest : modifyOutputStream(zos, true) } - // Extract the .dat file bytes to a temp file to avoid JarURLConnection locking tempJar on - // Windows val tempDat = createTempFile(directory = tempDir, suffix = ".dat") tempDat.writeBytes(JarPath(tempJar).use { it.getBytes(PLUGIN_CACHE_FILE) }) @@ -68,7 +77,7 @@ class Log4j2PluginsCacheFileTransformerTest : .isEqualTo("new.location.org.apache.logging.log4j.core.lookup.DateLookup") } - @Test // #427 + // #427 fun transformAndModifyOutputStream() = with(transformer) { assertThat(hasTransformedResource()).isFalse() @@ -87,7 +96,6 @@ class Log4j2PluginsCacheFileTransformerTest : fail("No expected resource in the output jar.") } else if (jarEntry.name == PLUGIN_CACHE_FILE) { assertThat(inputStream.readAllBytes().contentHashCode()).all { - // Hash of the original plugin cache file. isNotEqualTo(-2114104185) isEqualTo(1911442937) } @@ -97,8 +105,6 @@ class Log4j2PluginsCacheFileTransformerTest : } } - @ParameterizedTest - @MethodSource("relocationProvider") fun relocations(pattern: String, shadedPattern: String, expected: String) = with(transformer) { val aggregator = @@ -113,24 +119,21 @@ class Log4j2PluginsCacheFileTransformerTest : } } - private companion object { + companion object { val pluginCacheUrl: URL = requireResourceAsPath(PLUGIN_CACHE_FILE).toUri().toURL() fun context(vararg relocators: Relocator): TransformerContext { return resourceContext(PLUGIN_CACHE_FILE, relocators = relocators) } - @JvmStatic - fun relocationProvider() = + val relocationProvider = listOf( - // test with matching relocator - Arguments.of( + Triple( "org.apache.logging", "new.location.org.apache.logging", "new.location.org.apache.logging", ), - // test without matching relocator - Arguments.of("com.apache.logging", "new.location.com.apache.logging", "org.apache.logging"), + Triple("com.apache.logging", "new.location.com.apache.logging", "org.apache.logging"), ) } } diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestAppenderTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestAppenderTransformerTest.kt index a171c6a40..efe548420 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestAppenderTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestAppenderTransformerTest.kt @@ -8,11 +8,15 @@ import assertk.assertions.isTrue import com.github.jengelman.gradle.plugins.shadow.testkit.getContent import com.github.jengelman.gradle.plugins.shadow.testkit.getStream import com.github.jengelman.gradle.plugins.shadow.testkit.requireResourceAsStream +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests +import de.infix.testBalloon.framework.core.testSuite import java.util.jar.JarFile.MANIFEST_NAME -import org.junit.jupiter.api.Test -class ManifestAppenderTransformerTest : BaseTransformerTest() { - @Test +val ManifestAppenderTransformerTests by testSuite { + runTests(::ManifestAppenderTransformerTest) +} + +private class ManifestAppenderTransformerTest : BaseTransformerTest() { fun canTransformResource() = with(transformer) { append("Name", "org/foo/bar/") @@ -22,7 +26,6 @@ class ManifestAppenderTransformerTest : BaseTransformerTest() { - @Test +val MergeLicenseResourceTransformerTests by testSuite { + runTests(::MergeLicenseResourceTransformerTest) +} + +private class MergeLicenseResourceTransformerTest : + BaseTransformerTest() { fun defaultIncludes() = with(transformer) { assertThat(canTransformResource("META-INF/LICENSE")).isTrue() @@ -22,7 +27,6 @@ class MergeLicenseResourceTransformerTest : BaseTransformerTest() { - @Test fun firstOccurrenceIsNotTransformed() = with(transformer) { include("foo/bar") @@ -17,7 +21,6 @@ class PreserveFirstFoundResourceTransformerTest : assertThat(canTransformResource("foo/bar")).isFalse() } - @Test fun subsequentOccurrencesAreTransformed() = with(transformer) { include("foo/bar") @@ -28,7 +31,6 @@ class PreserveFirstFoundResourceTransformerTest : assertThat(canTransformResource("foo/bar")).isTrue() } - @Test fun nonMatchingPathIsNotTransformed() = with(transformer) { include("foo/bar") diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt index ec63cbbac..f4f3b86a5 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt @@ -13,18 +13,80 @@ import com.github.jengelman.gradle.plugins.shadow.testkit.JarPath import com.github.jengelman.gradle.plugins.shadow.testkit.getBytes import com.github.jengelman.gradle.plugins.shadow.testkit.getContent import com.github.jengelman.gradle.plugins.shadow.testkit.invariantEolString +import com.github.jengelman.gradle.plugins.shadow.testkit.runTest +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.transformers.PropertiesFileTransformer.MergeStrategy import com.github.jengelman.gradle.plugins.shadow.util.zipOutputStream +import de.infix.testBalloon.framework.core.testSuite import java.nio.charset.Charset import java.util.Properties import org.gradle.api.GradleException -import org.junit.jupiter.api.Test -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.Arguments -import org.junit.jupiter.params.provider.MethodSource -class PropertiesFileTransformerTest : BaseTransformerTest() { - @Test +val PropertiesFileTransformerTests by testSuite { + runTests(::PropertiesFileTransformerTest) + + for ((path, expected) in PropertiesFileTransformerTest.pathProvider) { + runTest( + "canTransformResourceWithPaths_${path}_$expected", + ::PropertiesFileTransformerTest, + ) { + canTransformResourceWithPaths(path, expected) + } + } + + for ((path, mergeStrategy, mergeSeparator, input1, input2, expectedOutput, expectedConflicts) in + PropertiesFileTransformerTest.transformConfigProvider) { + runTest( + "exerciseAllTransformConfigurations_${path}_$mergeStrategy", + ::PropertiesFileTransformerTest, + ) { + exerciseAllTransformConfigurations( + path, + mergeStrategy, + mergeSeparator, + input1, + input2, + expectedOutput, + expectedConflicts, + ) + } + } + + for ((path, paths, input1, input2, expectedOutput) in + PropertiesFileTransformerTest.transformConfigWithPathsProvider) { + runTest( + "exerciseAllTransformConfigurationsWithPaths_${path}", + ::PropertiesFileTransformerTest, + ) { + exerciseAllTransformConfigurationsWithPaths(path, paths, input1, input2, expectedOutput) + } + } + + for ((path, mappings, input1, input2, expectedOutput) in + PropertiesFileTransformerTest.transformConfigWithMappingsProvider) { + runTest( + "exerciseAllTransformConfigurationsWithMappings_${path}", + ::PropertiesFileTransformerTest, + ) { + exerciseAllTransformConfigurationsWithMappings(path, mappings, input1, input2, expectedOutput) + } + } + + for ((path, keyTransformer, input1, input2, expectedOutput) in + PropertiesFileTransformerTest.keyTransformerProvider) { + runTest("appliesKeyTransformer_${path}", ::PropertiesFileTransformerTest) { + appliesKeyTransformer(path, keyTransformer, input1, input2, expectedOutput) + } + } + + for ((path, charset, input1, input2) in PropertiesFileTransformerTest.charsetProvider) { + runTest("appliesCharset_${path}", ::PropertiesFileTransformerTest) { + appliesCharset(path, charset, input1, input2) + } + } +} + +private class PropertiesFileTransformerTest : BaseTransformerTest() { fun hasTransformedResource() = with(transformer) { assertThat(hasTransformedResource()).isFalse() @@ -34,14 +96,10 @@ class PropertiesFileTransformerTest : BaseTransformerTest, @@ -105,8 +160,6 @@ class PropertiesFileTransformerTest : BaseTransformerTest>, @@ -126,8 +179,6 @@ class PropertiesFileTransformerTest : BaseTransformerTest String, @@ -147,8 +198,6 @@ class PropertiesFileTransformerTest : BaseTransformerTest, @@ -199,48 +248,45 @@ class PropertiesFileTransformerTest : BaseTransformerTest(), ), - Arguments.of( + tupleOf( "foo.properties", emptyList(), mapOf("foo" to "foo"), @@ -249,45 +295,44 @@ class PropertiesFileTransformerTest : BaseTransformerTest>(), ), - Arguments.of( + tupleOf( "f.properties", "latest", "", @@ -317,7 +361,7 @@ class PropertiesFileTransformerTest : BaseTransformerTest>(), ), - Arguments.of( + tupleOf( "f.properties", "append", ",", @@ -326,7 +370,7 @@ class PropertiesFileTransformerTest : BaseTransformerTest>(), ), - Arguments.of( + tupleOf( "f.properties", "append", ";", @@ -335,7 +379,7 @@ class PropertiesFileTransformerTest : BaseTransformerTest>(), ), - Arguments.of( + tupleOf( "f.properties", "fail", ";", @@ -346,31 +390,30 @@ class PropertiesFileTransformerTest : BaseTransformerTest key }, mapOf("foo" to "bar"), mapOf("FOO" to "baz"), mapOf("foo" to "bar", "FOO" to "baz"), ), - Arguments.of( + tupleOf( "foo.properties", { key: String -> key.uppercase() }, mapOf("foo" to "bar"), mapOf("FOO" to "baz"), mapOf("FOO" to "bar,baz"), ), - Arguments.of( + tupleOf( "foo.properties", { key: String -> "bar.${key.lowercase()}" }, mapOf("foo" to "bar"), mapOf("FOO" to "baz"), mapOf("bar.foo" to "bar,baz"), ), - Arguments.of( + tupleOf( "foo.properties", { key: String -> key.replaceFirst(Regex("^(foo)"), "bar.$1") }, mapOf("foo" to "bar"), @@ -380,3 +423,24 @@ class PropertiesFileTransformerTest : BaseTransformerTest tupleOf(a: A, b: B) = Pair(a, b) + +private fun tupleOf(a: A, b: B, c: C, d: D) = Tuple4(a, b, c, d) + +private fun tupleOf(a: A, b: B, c: C, d: D, e: E) = Tuple5(a, b, c, d, e) + +private fun tupleOf(a: A, b: B, c: C, d: D, e: E, f: F, g: G) = + Tuple7(a, b, c, d, e, f, g) + +data class Tuple5(val a: A, val b: B, val c: C, val d: D, val e: E) + +data class Tuple7( + val a: A, + val b: B, + val c: C, + val d: D, + val e: E, + val f: F, + val g: G, +) diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt index 192529ac4..db0dd8470 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt @@ -7,19 +7,19 @@ import assertk.assertions.isTrue import com.github.jengelman.gradle.plugins.shadow.relocation.SimpleRelocator import com.github.jengelman.gradle.plugins.shadow.testkit.JarPath import com.github.jengelman.gradle.plugins.shadow.testkit.getContent +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.util.zipOutputStream -import org.junit.jupiter.api.Test -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.Arguments -import org.junit.jupiter.params.provider.MethodSource +import de.infix.testBalloon.framework.core.testSuite + +val ServiceFileTransformerTests by testSuite { + runTests(::ServiceFileTransformerTest) +} /** * Modified from * [org.apache.maven.plugins.shade.resource.ServiceResourceTransformerTest.java](https://github.com/apache/maven-shade-plugin/blob/master/src/test/java/org/apache/maven/plugins/shade/resource/ServiceResourceTransformerTest.java). */ -class ServiceFileTransformerTest : BaseTransformerTest() { - @ParameterizedTest - @MethodSource("resourceProvider") +private class ServiceFileTransformerTest : BaseTransformerTest() { fun canTransformResource(path: String, exclude: Boolean, expected: Boolean) = with(transformer) { if (exclude) { @@ -28,8 +28,6 @@ class ServiceFileTransformerTest : BaseTransformerTest() assertThat(canTransformResource(path)).isEqualTo(expected) } - @ParameterizedTest - @MethodSource("serviceFileProvider") fun transformServiceFile(path: String, input1: String, input2: String, output: String) = with(transformer) { if (canTransformResource(path)) { @@ -42,13 +40,11 @@ class ServiceFileTransformerTest : BaseTransformerTest() assertThat(entry).isEqualTo(output) } - @Test fun excludesGroovyExtensionModuleDescriptorFilesByDefault() { val element = "META-INF/services/org.codehaus.groovy.runtime.ExtensionModule" assertThat(transformer.canTransformResource(element)).isFalse() } - @Test fun canTransformAlternateResource() = with(transformer) { path = "foo/bar" @@ -56,49 +52,16 @@ class ServiceFileTransformerTest : BaseTransformerTest() assertThat(canTransformResource("META-INF/services/Zoo")).isFalse() } - @Test fun relocatedClasses() = - with(ServiceFileTransformer()) { - val relocator = SimpleRelocator("org.foo", "borg.foo", excludes = listOf("org.foo.exclude.*")) - val content = "org.foo.Service\norg.foo.exclude.OtherService\n" - val contentResource = "META-INF/services/org.foo.something.another" - val contentResourceShaded = "META-INF/services/borg.foo.something.another" - - transform(textContext(contentResource, content, relocator)) - - tempJar.zipOutputStream().use { zos -> - modifyOutputStream(zos, false) - } - - val transformedContent = JarPath(tempJar).use { it.getContent(contentResourceShaded) } - assertThat(transformedContent).isEqualTo("borg.foo.Service\norg.foo.exclude.OtherService") - } - - @Test - fun mergeRelocatedFiles() = - with(ServiceFileTransformer()) { - val relocator = SimpleRelocator("org.foo", "borg.foo", excludes = listOf("org.foo.exclude.*")) - val content = "org.foo.Service\norg.foo.exclude.OtherService\n" - val contentResource = "META-INF/services/org.foo.something.another" - val contentResourceShaded = "META-INF/services/borg.foo.something.another" + with(transformer) { + val relocator = SimpleRelocator("org.foo", "borg.foo") + var content = "org.foo.Service\n" + var contentResource = "META-INF/services/org.foo.something.another" transform(textContext(contentResource, content, relocator)) - transform(textContext(contentResourceShaded, content, relocator)) - - tempJar.zipOutputStream().use { zos -> - modifyOutputStream(zos, false) - } - - val transformedContent = JarPath(tempJar).use { it.getContent(contentResourceShaded) } - assertThat(transformedContent).isEqualTo("borg.foo.Service\norg.foo.exclude.OtherService") - } - @Test - fun concatenationAppliedMultipleTimes() = - with(ServiceFileTransformer()) { - val relocator = SimpleRelocator("org.eclipse", "org.eclipse1234") - val content = "org.eclipse.osgi.launch.EquinoxFactory\n" - val contentResource = "META-INF/services/org.osgi.framework.launch.FrameworkFactory" + content = "org.blah.Service\n" + contentResource = "META-INF/services/org.something.another" transform(textContext(contentResource, content, relocator)) @@ -107,15 +70,15 @@ class ServiceFileTransformerTest : BaseTransformerTest() } val transformedContent = JarPath(tempJar).use { it.getContent(contentResource) } - assertThat(transformedContent).isEqualTo("org.eclipse1234.osgi.launch.EquinoxFactory") + assertThat(transformedContent).isEqualTo("org.blah.Service") } - @Test - fun concatenation() = - with(ServiceFileTransformer()) { + fun serviceEntriesAreAppendedAndPreservedOrder() = + with(transformer) { val relocator = SimpleRelocator("org.foo", "borg.foo") var content = "org.foo.Service\n" var contentResource = "META-INF/services/org.something.another" + transform(textContext(contentResource, content, relocator)) content = "org.blah.Service\n" @@ -131,25 +94,25 @@ class ServiceFileTransformerTest : BaseTransformerTest() assertThat(transformedContent).isEqualTo("borg.foo.Service\norg.blah.Service") } - private companion object { - @JvmStatic - fun resourceProvider() = + companion object { + val resourceProvider = listOf( // path, exclude, expected - Arguments.of("META-INF/services/java.sql.Driver", false, true), - Arguments.of("META-INF/services/io.dropwizard.logging.AppenderFactory", false, true), - Arguments.of("META-INF/services/org.apache.maven.Shade", true, false), - Arguments.of("META-INF/services/foo/bar/moo.goo.Zoo", false, true), - Arguments.of("foo/bar.properties", false, false), - Arguments.of("foo.props", false, false), + Triple("META-INF/services/java.sql.Driver", false, true), + Triple("META-INF/services/io.dropwizard.logging.AppenderFactory", false, true), + Triple("META-INF/services/org.apache.maven.Shade", true, false), + Triple("META-INF/services/foo/bar/moo.goo.Zoo", false, true), + Triple("foo/bar.properties", false, false), + Triple("foo.props", false, false), ) - @JvmStatic - fun serviceFileProvider() = + val serviceFileProvider = listOf( // path, input1, input2, output - Arguments.of("META-INF/services/com.acme.Foo", "foo", "bar", "foo\nbar"), - Arguments.of("META-INF/services/com.acme.Bar", "foo\nbar", "zoo", "foo\nbar\nzoo"), + Tuple4("META-INF/services/com.acme.Foo", "foo", "bar", "foo\nbar"), + Tuple4("META-INF/services/com.acme.Bar", "foo\nbar", "zoo", "foo\nbar\nzoo"), ) } } + +data class Tuple4(val a: A, val b: B, val c: C, val d: D) diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformerTest.kt index 5b406fa1f..94479899d 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformerTest.kt @@ -6,16 +6,20 @@ import assertk.assertions.isFalse import assertk.assertions.isTrue import com.github.jengelman.gradle.plugins.shadow.testkit.JarPath import com.github.jengelman.gradle.plugins.shadow.testkit.getContent +import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.util.zipOutputStream -import org.junit.jupiter.api.Test +import de.infix.testBalloon.framework.core.testSuite -class XmlAppendingTransformerTest : BaseTransformerTest() { +val XmlAppendingTransformerTests by testSuite { + runTests(::XmlAppendingTransformerTest) +} + +private class XmlAppendingTransformerTest : BaseTransformerTest() { init { setupTurkishLocale() } - @Test fun canTransformResource() = with(transformer) { resource.set("abcdefghijklmnopqrstuvwxyz") @@ -25,7 +29,6 @@ class XmlAppendingTransformerTest : BaseTransformerTest assertThat(canTransformResource("META-INF/MANIFEST.MF")).isFalse() } - @Test fun appendXmlFiles() = with(transformer) { val xmlEntry = "properties.xml" @@ -61,7 +64,6 @@ class XmlAppendingTransformerTest : BaseTransformerTest ) } - @Test fun appendXmlFilesWithUnreachableDtd() = with(transformer) { val xmlEntry = "properties_invalid_dtd.xml" @@ -97,7 +99,7 @@ class XmlAppendingTransformerTest : BaseTransformerTest ) } - @Test // #168 + // #168 fun mergeNestedLevels() = with(transformer) { val xmlEntry = "META-INF/nested.xml" @@ -129,7 +131,7 @@ class XmlAppendingTransformerTest : BaseTransformerTest ) } - private companion object { + companion object { /** * Normalizes line breaks in XML content produced by [XmlAppendingTransformer]. * diff --git a/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/TestSuiteScope.kt b/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/TestSuiteScope.kt new file mode 100644 index 000000000..9f6b6dfd4 --- /dev/null +++ b/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/TestSuiteScope.kt @@ -0,0 +1,111 @@ +package com.github.jengelman.gradle.plugins.shadow.testkit + +import de.infix.testBalloon.framework.core.TestFixture +import de.infix.testBalloon.framework.core.TestSuiteScope +import java.lang.reflect.InvocationTargetException +import java.nio.file.Path +import kotlin.io.path.ExperimentalPathApi +import kotlin.io.path.createTempDirectory +import kotlin.io.path.deleteRecursively +import kotlin.io.path.exists +import kotlin.io.path.readText +import kotlin.reflect.KFunction1 +import kotlin.reflect.KVisibility +import kotlin.reflect.full.declaredMemberFunctions +import kotlin.reflect.full.declaredMemberProperties +import kotlin.reflect.jvm.isAccessible + +fun TestSuiteScope.tempDirFixture(): TestFixture = + testFixture { + createTempDirectory() + } closeWith { @OptIn(ExperimentalPathApi::class) deleteRecursively() } + +inline fun TestSuiteScope.runTests( + noinline factory: () -> T, + vararg functions: KFunction1, +) { + if (functions.isNotEmpty()) { + for (function in functions) { + runTest(function.name, factory) { function.invoke(this) } + } + } else { + val discovered = + T::class.declaredMemberFunctions.filter { + it.visibility != KVisibility.PRIVATE && it.parameters.size == 1 + } + for (function in discovered) { + runTest(function.name, factory) { + function.isAccessible = true + function.call(this) + } + } + } +} + +inline fun TestSuiteScope.runTest( + name: String, + noinline factory: () -> T, + crossinline block: T.() -> Unit, +) { + test(name) { + val instance = factory() + try { + instance.block() + } catch (t: InvocationTargetException) { + logProjectScript(instance) + throw t.targetException ?: t + } catch (t: Throwable) { + logProjectScript(instance) + throw t + } finally { + cleanupInstance(instance) + } + } +} + +@PublishedApi +internal fun logProjectScript(instance: Any) { + try { + val scriptProp = + instance::class.declaredMemberProperties.firstOrNull { + it.name == "projectScript" && it.returnType.classifier == Path::class + } + if (scriptProp != null) { + scriptProp.isAccessible = true + val script = scriptProp.call(instance) as? Path + val rootProp = + instance::class.declaredMemberProperties.firstOrNull { + it.name == "projectRoot" && it.returnType.classifier == Path::class + } + rootProp?.isAccessible = true + val root = rootProp?.call(instance) as? Path + if (script != null && script.exists()) { + println("Project build script at $root:\n${script.readText()}") + } + } + } catch (_: Throwable) {} +} + +@OptIn(ExperimentalPathApi::class) +@PublishedApi +internal fun cleanupInstance(instance: Any) { + try { + if (instance is AutoCloseable) instance.close() + val rootProp = + instance::class.declaredMemberProperties.firstOrNull { + it.name == "projectRoot" && it.returnType.classifier == Path::class + } + if (rootProp != null) { + rootProp.isAccessible = true + (rootProp.call(instance) as? Path)?.deleteRecursively() + } + val tempDirProp = + instance::class.declaredMemberProperties.firstOrNull { + it.name == "tempDir" && it.returnType.classifier == Path::class + } + if (tempDirProp != null) { + tempDirProp.isAccessible = true + (tempDirProp.call(instance) as? Path)?.deleteRecursively() + } + } catch (_: Throwable) {} +} From a4e76c2722deb791ca705573bbd05e576737d19d Mon Sep 17 00:00:00 2001 From: Goooler Date: Sun, 16 Aug 2026 13:16:03 +0800 Subject: [PATCH 2/7] Auto-inject boolean parameters in runTests --- .../gradle/plugins/shadow/FilteringTest.kt | 10 ----- .../gradle/plugins/shadow/JavaPluginsTest.kt | 15 ------- .../plugins/shadow/KotlinPluginsTest.kt | 22 ---------- .../gradle/plugins/shadow/MinimizeTest.kt | 7 ---- .../gradle/plugins/shadow/PublishingTest.kt | 7 ---- .../gradle/plugins/shadow/RelocationTest.kt | 24 ----------- .../plugins/shadow/testkit/TestSuiteScope.kt | 40 ++++++++++++++----- 7 files changed, 30 insertions(+), 95 deletions(-) diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/FilteringTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/FilteringTest.kt index 72f82d789..1f93c0bbd 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/FilteringTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/FilteringTest.kt @@ -2,7 +2,6 @@ package com.github.jengelman.gradle.plugins.shadow import assertk.assertThat import com.github.jengelman.gradle.plugins.shadow.testkit.containsOnly -import com.github.jengelman.gradle.plugins.shadow.testkit.runTest import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import de.infix.testBalloon.framework.core.testSuite import kotlin.io.path.appendText @@ -10,15 +9,6 @@ import kotlin.io.path.writeText val FilteringTests by testSuite { runTests(::FilteringTest) - - for (useAccessor in listOf(false, true)) { - runTest("excludeDependency_useAccessor_$useAccessor", ::FilteringTest) { - excludeDependency(useAccessor) - } - runTest("filterProjectDependencies_useAccessor_$useAccessor", ::FilteringTest) { - filterProjectDependencies(useAccessor) - } - } } private class FilteringTest : BasePluginTest() { diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt index aa8fe1d11..c907e2e53 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt @@ -46,21 +46,6 @@ import org.gradle.testkit.runner.TaskOutcome.SUCCESS val JavaPluginsTests by testSuite { runTests(::JavaPluginsTest) - for (enable in listOf(false, true)) { - runTest( - "containsMultiReleaseAttrIfAnyDependencyContainsIt_addAttribute_$enable", - ::JavaPluginsTest, - ) { - containsMultiReleaseAttrIfAnyDependencyContainsIt(enable) - } - runTest("containsMultiReleaseAttrByCliOption_enable_$enable", ::JavaPluginsTest) { - containsMultiReleaseAttrByCliOption(enable) - } - runTest("failBuildIfDuplicateEntries_enable_$enable", ::JavaPluginsTest) { - failBuildIfDuplicateEntries(enable) - } - } - for (configuration in listOf(ShadowBasePlugin.CONFIGURATION_NAME, IMPLEMENTATION_CONFIGURATION_NAME)) { runTest( diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/KotlinPluginsTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/KotlinPluginsTest.kt index 88105fed9..184b291a1 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/KotlinPluginsTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/KotlinPluginsTest.kt @@ -8,7 +8,6 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.SHAD import com.github.jengelman.gradle.plugins.shadow.testkit.containsAtLeast import com.github.jengelman.gradle.plugins.shadow.testkit.containsOnly import com.github.jengelman.gradle.plugins.shadow.testkit.getMainAttr -import com.github.jengelman.gradle.plugins.shadow.testkit.runTest import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.util.JvmLang import de.infix.testBalloon.framework.core.testSuite @@ -17,27 +16,6 @@ import kotlin.io.path.writeText val KotlinPluginsTests by testSuite { runTests(::KotlinPluginsTest) - - for (excludeStdlib in listOf(false, true)) { - runTest("compatKotlinJvmPlugin_excludeStdlib_$excludeStdlib", ::KotlinPluginsTest) { - compatKotlinJvmPlugin(excludeStdlib) - } - runTest("compatKmpJvmTarget_excludeStdlib_$excludeStdlib", ::KotlinPluginsTest) { - compatKmpJvmTarget(excludeStdlib) - } - } - - for (useShadowAttr in listOf(false, true)) { - runTest("setMainClassAttributeFromMainRun_useShadowAttr_$useShadowAttr", ::KotlinPluginsTest) { - setMainClassAttributeFromMainRun(useShadowAttr) - } - runTest( - "setManifestAttrsFromJvmTargetJar_useShadowAttr_$useShadowAttr", - ::KotlinPluginsTest, - ) { - setManifestAttrsFromJvmTargetJar(useShadowAttr) - } - } } private class KotlinPluginsTest : BasePluginTest() { diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/MinimizeTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/MinimizeTest.kt index 0c6510986..704c76032 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/MinimizeTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/MinimizeTest.kt @@ -11,7 +11,6 @@ import com.github.jengelman.gradle.plugins.shadow.testkit.containsNone import com.github.jengelman.gradle.plugins.shadow.testkit.containsOnly import com.github.jengelman.gradle.plugins.shadow.testkit.getContent import com.github.jengelman.gradle.plugins.shadow.testkit.invariantEolString -import com.github.jengelman.gradle.plugins.shadow.testkit.runTest import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import de.infix.testBalloon.framework.core.testSuite import java.net.URLClassLoader @@ -23,12 +22,6 @@ import org.gradle.api.JavaVersion val MinimizeTests by testSuite { runTests(::MinimizeTest) - - for (enable in listOf(false, true)) { - runTest("enableMinimizationByCliOption_enable_$enable", ::MinimizeTest) { - enableMinimizationByCliOption(enable) - } - } } private class MinimizeTest : BasePluginTest() { diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/PublishingTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/PublishingTest.kt index 274d3a01c..aa9fedb47 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/PublishingTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/PublishingTest.kt @@ -16,7 +16,6 @@ import com.github.jengelman.gradle.plugins.shadow.testkit.containsAtLeast import com.github.jengelman.gradle.plugins.shadow.testkit.containsNone import com.github.jengelman.gradle.plugins.shadow.testkit.containsOnly import com.github.jengelman.gradle.plugins.shadow.testkit.getMainAttr -import com.github.jengelman.gradle.plugins.shadow.testkit.runTest import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.util.GradleModuleMetadata import com.github.jengelman.gradle.plugins.shadow.util.coordinate @@ -48,12 +47,6 @@ import org.gradle.testkit.runner.BuildResult val PublishingTests by testSuite { runTests(::PublishingTest) - - for (addShadowVariant in listOf(false, true)) { - runTest("publishShadowVariantJar_addShadowVariant_$addShadowVariant", ::PublishingTest) { - publishShadowVariantJar(addShadowVariant) - } - } } private class PublishingTest : BasePluginTest() { diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt index a2cb5becc..80968075b 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt @@ -51,30 +51,6 @@ val RelocationTests by testSuite { preserveLastModifiedCorrectly(preserveFileTimestamps, enableAutoRelocation) } } - - for (exclude in listOf(false, true)) { - runTest("relocateAllPackagesButCertainOne_exclude_$exclude", ::RelocationTest) { - relocateAllPackagesButCertainOne(exclude) - } - } - - for (skipStringConstants in listOf(false, true)) { - runTest( - "disableStringConstantsRelocation_skipStringConstants_$skipStringConstants", - ::RelocationTest, - ) { - disableStringConstantsRelocation(skipStringConstants) - } - } - - for (enableKotlinModuleRemapping in listOf(false, true)) { - runTest( - "relocateKotlinModuleFiles_enableKotlinModuleRemapping_$enableKotlinModuleRemapping", - ::RelocationTest, - ) { - relocateKotlinModuleFiles(enableKotlinModuleRemapping) - } - } } private class RelocationTest : BasePluginTest() { diff --git a/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/TestSuiteScope.kt b/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/TestSuiteScope.kt index 9f6b6dfd4..6bfecb53a 100644 --- a/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/TestSuiteScope.kt +++ b/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/TestSuiteScope.kt @@ -26,26 +26,46 @@ inline fun TestSuiteScope.runTests( ) { if (functions.isNotEmpty()) { for (function in functions) { - runTest(function.name, factory) { function.invoke(this) } + runTest(function.name, factory, function) } } else { val discovered = - T::class.declaredMemberFunctions.filter { - it.visibility != KVisibility.PRIVATE && it.parameters.size == 1 - } + T::class.declaredMemberFunctions.filter { it.visibility != KVisibility.PRIVATE } for (function in discovered) { - runTest(function.name, factory) { - function.isAccessible = true - function.call(this) + function.isAccessible = true + val valueParams = function.parameters.drop(1) + when { + valueParams.isEmpty() -> { + runTest(function.name, factory) { + function.call(this) + } + } + + valueParams.all { it.type.classifier == Boolean::class } -> { + val combinations = + valueParams.fold(listOf(emptyList())) { acc, _ -> + acc.flatMap { list -> listOf(list + false, list + true) } + } + for (combo in combinations) { + val name = + "${function.name}_" + + valueParams.zip(combo).joinToString("_") { (param, value) -> + "${param.name}_$value" + } + runTest(name, factory) { + function.call(this, *combo.toTypedArray()) + } + } + } } } } } -inline fun TestSuiteScope.runTest( +fun TestSuiteScope.runTest( name: String, - noinline factory: () -> T, - crossinline block: T.() -> Unit, + factory: () -> T, + block: T.() -> Unit, ) { test(name) { val instance = factory() From 0738b2f55f1d33eecc37e614880ed6a08d31780b Mon Sep 17 00:00:00 2001 From: Goooler Date: Sun, 16 Aug 2026 13:55:57 +0800 Subject: [PATCH 3/7] Introduce Arguments class to replace ad-hoc Tuple types --- .../gradle/plugins/shadow/RelocationTest.kt | 29 +---- .../ServiceFileTransformerTest.kt | 17 +-- .../internal/DefaultDependencyFilterTest.kt | 43 ++++--- .../Log4j2PluginsCacheFileTransformerTest.kt | 7 +- .../PropertiesFileTransformerTest.kt | 110 +++++++++--------- .../ServiceFileTransformerTest.kt | 34 ++++-- .../plugins/shadow/testkit/Arguments.kt | 32 +++++ 7 files changed, 153 insertions(+), 119 deletions(-) create mode 100644 src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/Arguments.kt diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt index 80968075b..9d83db6af 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt @@ -10,6 +10,7 @@ import assertk.assertions.isNotEqualTo import assertk.fail import com.github.jengelman.gradle.plugins.shadow.internal.mainClassAttributeKey import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.CONSTANT_TIME_FOR_ZIP_ENTRIES +import com.github.jengelman.gradle.plugins.shadow.testkit.Arguments import com.github.jengelman.gradle.plugins.shadow.testkit.containsOnly import com.github.jengelman.gradle.plugins.shadow.testkit.getBytes import com.github.jengelman.gradle.plugins.shadow.testkit.requireResourceAsPath @@ -33,7 +34,7 @@ val RelocationTests by testSuite { } } - for ((enable, relocationPrefix) in RelocationTest.relocationCliOptionProvider) { + for ((enable: Boolean, relocationPrefix: String) in RelocationTest.relocationCliOptionProvider) { runTest( "enableAutoRelocationByCliOption_${enable}_${relocationPrefix}", ::RelocationTest, @@ -41,16 +42,6 @@ val RelocationTests by testSuite { enableAutoRelocationByCliOption(enable, relocationPrefix) } } - - for ((preserveFileTimestamps, enableAutoRelocation) in - RelocationTest.preserveLastModifiedProvider) { - runTest( - "preserveLastModifiedCorrectly_${preserveFileTimestamps}_${enableAutoRelocation}", - ::RelocationTest, - ) { - preserveLastModifiedCorrectly(preserveFileTimestamps, enableAutoRelocation) - } - } } private class RelocationTest : BasePluginTest() { @@ -692,20 +683,12 @@ private class RelocationTest : BasePluginTest() { } companion object { - val preserveLastModifiedProvider = - listOf( - Pair(false, false), - Pair(true, false), - Pair(false, true), - Pair(true, true), - ) - val relocationCliOptionProvider = listOf( - Pair(false, "foo"), - Pair(false, "bar"), - Pair(true, "foo"), - Pair(true, "bar"), + Arguments.of(false, "foo"), + Arguments.of(false, "bar"), + Arguments.of(true, "foo"), + Arguments.of(true, "bar"), ) } } diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt index efbe302fe..e7236e3fa 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt @@ -4,6 +4,7 @@ import assertk.assertThat import assertk.assertions.contains import assertk.assertions.containsMatch import assertk.assertions.isEqualTo +import com.github.jengelman.gradle.plugins.shadow.testkit.Arguments import com.github.jengelman.gradle.plugins.shadow.testkit.containsOnly import com.github.jengelman.gradle.plugins.shadow.testkit.getContent import com.github.jengelman.gradle.plugins.shadow.testkit.runTest @@ -27,13 +28,15 @@ val ServiceFileTransformerTests by testSuite { } } - for ((strategy, firstValue, secondValue) in ServiceFileTransformerTest.withoutThrowingProvider) { + for ((strategy: DuplicatesStrategy, firstValue: String, secondValue: String) in + ServiceFileTransformerTest.withoutThrowingProvider) { runTest("honorDuplicatesStrategyWithoutThrowing_$strategy", ::ServiceFileTransformerTest) { honorDuplicatesStrategyWithoutThrowing(strategy, firstValue, secondValue) } } - for ((default, override, matchPath) in ServiceFileTransformerTest.eachFileStrategyProvider) { + for ((default: DuplicatesStrategy, override: DuplicatesStrategy, matchPath: String) in + ServiceFileTransformerTest.eachFileStrategyProvider) { runTest( "strategyCanBeOverriddenByEachFile_${default}_${override}", ::ServiceFileTransformerTest, @@ -316,15 +319,15 @@ private class ServiceFileTransformerTest : BaseTransformerTest() { val withoutThrowingProvider = listOf( - Triple(EXCLUDE, CONTENT_ONE, "one"), - Triple(INCLUDE, CONTENT_ONE_TWO, "one\ntwo"), - Triple(WARN, CONTENT_ONE_TWO, "one\ntwo"), + Arguments.of(EXCLUDE, CONTENT_ONE, "one"), + Arguments.of(INCLUDE, CONTENT_ONE_TWO, "one\ntwo"), + Arguments.of(WARN, CONTENT_ONE_TWO, "one\ntwo"), ) val eachFileStrategyProvider = listOf( - Triple(EXCLUDE, INCLUDE, ENTRY_SERVICES_SHADE), - Triple(INCLUDE, EXCLUDE, ENTRY_SERVICES_FOO), + Arguments.of(EXCLUDE, INCLUDE, ENTRY_SERVICES_SHADE), + Arguments.of(INCLUDE, EXCLUDE, ENTRY_SERVICES_FOO), ) } } diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultDependencyFilterTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultDependencyFilterTest.kt index 0f719f4c1..7c10c7485 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultDependencyFilterTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultDependencyFilterTest.kt @@ -7,6 +7,7 @@ import assertk.assertions.isEqualTo import assertk.assertions.isInstanceOf import assertk.assertions.isTrue import assertk.assertions.messageContains +import com.github.jengelman.gradle.plugins.shadow.testkit.Arguments import com.github.jengelman.gradle.plugins.shadow.testkit.runTest import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.util.noOpDelegate @@ -17,7 +18,7 @@ import org.gradle.testfixtures.ProjectBuilder val DefaultDependencyFilterTests by testSuite { runTests(::DefaultDependencyFilterTest) - for ((notation, group, name, version, expected) in + for ((notation: Any, group: String, name: String, version: String, expected: Boolean) in DefaultDependencyFilterTest.dependencyNotationProvider) { runTest( "matchesDependencyNotation_${notation}_${group}_${name}_$version", @@ -75,37 +76,37 @@ private class DefaultDependencyFilterTest { val stringNotations = listOf( - Tuple5("foo:bar", "foo", "bar", "1.0", true), - Tuple5("f.*:bar", "foo", "bar", "1.0", true), - Tuple5("foo:bar:.*", "foo", "bar", "1.0", true), - Tuple5("f.*:bar:.*", "foo", "bar", "1.0", true), - Tuple5("f.*:bar.*:.*", "foo", "bar", "1.0", true), - Tuple5(".*:bar:.*", "foo", "bar", "1.0", true), - Tuple5("foo:bar:2.1.0", "foo", "bar", "2.1.0", true), - Tuple5("foo:bar:2.1.0", "foo", "baz", "2.1.0", false), - Tuple5("foo:bar:2.1.0", "bar", "bar", "2.1.0", false), - Tuple5("foo:bar:1.0.0+1", "foo", "bar", "1.0.0+1", true), - Tuple5("foo:bar:1.0.0+1", "foo", "bar", "1.0.0+2", false), - Tuple5("foo:bar:1\\.0\\..*", "foo", "bar", "1.0.5", true), - Tuple5("foo:bar:1\\.0\\..*", "foo", "bar", "2.0.0", false), - Tuple5("foo:bar:1.0", "baz", "bar", "1.0", false), - Tuple5("foo:bar:1.0", "foo", "bar", "2.0", false), - Tuple5("f.*:bar", "zoo", "bar", "1.0", false), + Arguments.of("foo:bar", "foo", "bar", "1.0", true), + Arguments.of("f.*:bar", "foo", "bar", "1.0", true), + Arguments.of("foo:bar:.*", "foo", "bar", "1.0", true), + Arguments.of("f.*:bar:.*", "foo", "bar", "1.0", true), + Arguments.of("f.*:bar.*:.*", "foo", "bar", "1.0", true), + Arguments.of(".*:bar:.*", "foo", "bar", "1.0", true), + Arguments.of("foo:bar:2.1.0", "foo", "bar", "2.1.0", true), + Arguments.of("foo:bar:2.1.0", "foo", "baz", "2.1.0", false), + Arguments.of("foo:bar:2.1.0", "bar", "bar", "2.1.0", false), + Arguments.of("foo:bar:1.0.0+1", "foo", "bar", "1.0.0+1", true), + Arguments.of("foo:bar:1.0.0+1", "foo", "bar", "1.0.0+2", false), + Arguments.of("foo:bar:1\\.0\\..*", "foo", "bar", "1.0.5", true), + Arguments.of("foo:bar:1\\.0\\..*", "foo", "bar", "2.0.0", false), + Arguments.of("foo:bar:1.0", "baz", "bar", "1.0", false), + Arguments.of("foo:bar:1.0", "foo", "bar", "2.0", false), + Arguments.of("f.*:bar", "zoo", "bar", "1.0", false), ) val providerNotations = - listOf(Tuple5(project.provider { "foo:bar:1.0" }, "foo", "bar", "1.0", true)) + listOf(Arguments.of(project.provider { "foo:bar:1.0" }, "foo", "bar", "1.0", true)) val mapNotations = listOf( - Tuple5( + Arguments.of( mapOf("group" to "foo", "name" to "bar", "version" to "1.0"), "foo", "bar", "1.0", true, ), - Tuple5(mapOf("name" to "bar"), "any.group", "bar", "1.0", true), + Arguments.of(mapOf("name" to "bar"), "any.group", "bar", "1.0", true), ) val dependencyNotationProvider = stringNotations + providerNotations + mapNotations @@ -120,8 +121,6 @@ private class DefaultDependencyFilterTest { } } -data class Tuple5(val a: A, val b: B, val c: C, val d: D, val e: E) - private class TestResolvedDependency( private val group: String, private val name: String, diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformerTest.kt index 9959f1259..7deb963ab 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformerTest.kt @@ -10,6 +10,7 @@ import assertk.assertions.startsWith import assertk.fail import com.github.jengelman.gradle.plugins.shadow.relocation.Relocator import com.github.jengelman.gradle.plugins.shadow.relocation.SimpleRelocator +import com.github.jengelman.gradle.plugins.shadow.testkit.Arguments import com.github.jengelman.gradle.plugins.shadow.testkit.JarPath import com.github.jengelman.gradle.plugins.shadow.testkit.getBytes import com.github.jengelman.gradle.plugins.shadow.testkit.requireResourceAsPath @@ -30,7 +31,7 @@ import org.apache.tools.zip.ZipOutputStream val Log4j2PluginsCacheFileTransformerTests by testSuite { runTests(::Log4j2PluginsCacheFileTransformerTest) - for ((pattern, shadedPattern, expected) in + for ((pattern: String, shadedPattern: String, expected: String) in Log4j2PluginsCacheFileTransformerTest.relocationProvider) { runTest( "relocations_${pattern}_${shadedPattern}", @@ -128,12 +129,12 @@ private class Log4j2PluginsCacheFileTransformerTest : val relocationProvider = listOf( - Triple( + Arguments.of( "org.apache.logging", "new.location.org.apache.logging", "new.location.org.apache.logging", ), - Triple("com.apache.logging", "new.location.com.apache.logging", "org.apache.logging"), + Arguments.of("com.apache.logging", "new.location.com.apache.logging", "org.apache.logging"), ) } } diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt index f4f3b86a5..8360730f2 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt @@ -9,6 +9,7 @@ import assertk.assertions.isFalse import assertk.assertions.isInstanceOf import assertk.assertions.isTrue import com.github.jengelman.gradle.plugins.shadow.internal.inputStream +import com.github.jengelman.gradle.plugins.shadow.testkit.Arguments import com.github.jengelman.gradle.plugins.shadow.testkit.JarPath import com.github.jengelman.gradle.plugins.shadow.testkit.getBytes import com.github.jengelman.gradle.plugins.shadow.testkit.getContent @@ -25,7 +26,7 @@ import org.gradle.api.GradleException val PropertiesFileTransformerTests by testSuite { runTests(::PropertiesFileTransformerTest) - for ((path, expected) in PropertiesFileTransformerTest.pathProvider) { + for ((path: String, expected: Boolean) in PropertiesFileTransformerTest.pathProvider) { runTest( "canTransformResourceWithPaths_${path}_$expected", ::PropertiesFileTransformerTest, @@ -34,7 +35,14 @@ val PropertiesFileTransformerTests by testSuite { } } - for ((path, mergeStrategy, mergeSeparator, input1, input2, expectedOutput, expectedConflicts) in + for (( + path: String, + mergeStrategy: String, + mergeSeparator: String, + input1: Map, + input2: Map, + expectedOutput: Map, + expectedConflicts: Map>) in PropertiesFileTransformerTest.transformConfigProvider) { runTest( "exerciseAllTransformConfigurations_${path}_$mergeStrategy", @@ -52,7 +60,12 @@ val PropertiesFileTransformerTests by testSuite { } } - for ((path, paths, input1, input2, expectedOutput) in + for (( + path: String, + paths: List, + input1: Map, + input2: Map, + expectedOutput: Map) in PropertiesFileTransformerTest.transformConfigWithPathsProvider) { runTest( "exerciseAllTransformConfigurationsWithPaths_${path}", @@ -62,7 +75,12 @@ val PropertiesFileTransformerTests by testSuite { } } - for ((path, mappings, input1, input2, expectedOutput) in + for (( + path: String, + mappings: Map>, + input1: Map, + input2: Map, + expectedOutput: Map) in PropertiesFileTransformerTest.transformConfigWithMappingsProvider) { runTest( "exerciseAllTransformConfigurationsWithMappings_${path}", @@ -72,14 +90,19 @@ val PropertiesFileTransformerTests by testSuite { } } - for ((path, keyTransformer, input1, input2, expectedOutput) in - PropertiesFileTransformerTest.keyTransformerProvider) { + for (( + path: String, + keyTransformer: (String) -> String, + input1: Map, + input2: Map, + expectedOutput: Map) in PropertiesFileTransformerTest.keyTransformerProvider) { runTest("appliesKeyTransformer_${path}", ::PropertiesFileTransformerTest) { appliesKeyTransformer(path, keyTransformer, input1, input2, expectedOutput) } } - for ((path, charset, input1, input2) in PropertiesFileTransformerTest.charsetProvider) { + for ((path: String, charset: String, input1: Map, input2: Map) in + PropertiesFileTransformerTest.charsetProvider) { runTest("appliesCharset_${path}", ::PropertiesFileTransformerTest) { appliesCharset(path, charset, input1, input2) } @@ -250,43 +273,43 @@ private class PropertiesFileTransformerTest : BaseTransformerTest(), ), - tupleOf( + Arguments.of( "foo.properties", emptyList(), mapOf("foo" to "foo"), @@ -297,42 +320,42 @@ private class PropertiesFileTransformerTest : BaseTransformerTest>(), ), - tupleOf( + Arguments.of( "f.properties", "latest", "", @@ -361,7 +384,7 @@ private class PropertiesFileTransformerTest : BaseTransformerTest>(), ), - tupleOf( + Arguments.of( "f.properties", "append", ",", @@ -370,7 +393,7 @@ private class PropertiesFileTransformerTest : BaseTransformerTest>(), ), - tupleOf( + Arguments.of( "f.properties", "append", ";", @@ -379,7 +402,7 @@ private class PropertiesFileTransformerTest : BaseTransformerTest>(), ), - tupleOf( + Arguments.of( "f.properties", "fail", ";", @@ -392,28 +415,28 @@ private class PropertiesFileTransformerTest : BaseTransformerTest key }, mapOf("foo" to "bar"), mapOf("FOO" to "baz"), mapOf("foo" to "bar", "FOO" to "baz"), ), - tupleOf( + Arguments.of( "foo.properties", { key: String -> key.uppercase() }, mapOf("foo" to "bar"), mapOf("FOO" to "baz"), mapOf("FOO" to "bar,baz"), ), - tupleOf( + Arguments.of( "foo.properties", { key: String -> "bar.${key.lowercase()}" }, mapOf("foo" to "bar"), mapOf("FOO" to "baz"), mapOf("bar.foo" to "bar,baz"), ), - tupleOf( + Arguments.of( "foo.properties", { key: String -> key.replaceFirst(Regex("^(foo)"), "bar.$1") }, mapOf("foo" to "bar"), @@ -423,24 +446,3 @@ private class PropertiesFileTransformerTest : BaseTransformerTest tupleOf(a: A, b: B) = Pair(a, b) - -private fun tupleOf(a: A, b: B, c: C, d: D) = Tuple4(a, b, c, d) - -private fun tupleOf(a: A, b: B, c: C, d: D, e: E) = Tuple5(a, b, c, d, e) - -private fun tupleOf(a: A, b: B, c: C, d: D, e: E, f: F, g: G) = - Tuple7(a, b, c, d, e, f, g) - -data class Tuple5(val a: A, val b: B, val c: C, val d: D, val e: E) - -data class Tuple7( - val a: A, - val b: B, - val c: C, - val d: D, - val e: E, - val f: F, - val g: G, -) diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt index db0dd8470..ff616e7dd 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt @@ -5,14 +5,30 @@ import assertk.assertions.isEqualTo import assertk.assertions.isFalse import assertk.assertions.isTrue import com.github.jengelman.gradle.plugins.shadow.relocation.SimpleRelocator +import com.github.jengelman.gradle.plugins.shadow.testkit.Arguments import com.github.jengelman.gradle.plugins.shadow.testkit.JarPath import com.github.jengelman.gradle.plugins.shadow.testkit.getContent +import com.github.jengelman.gradle.plugins.shadow.testkit.runTest import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.util.zipOutputStream import de.infix.testBalloon.framework.core.testSuite val ServiceFileTransformerTests by testSuite { runTests(::ServiceFileTransformerTest) + + for ((path: String, exclude: Boolean, expected: Boolean) in + ServiceFileTransformerTest.resourceProvider) { + runTest("canTransformResource_${path}", ::ServiceFileTransformerTest) { + canTransformResource(path, exclude, expected) + } + } + + for ((path: String, input1: String, input2: String, output: String) in + ServiceFileTransformerTest.serviceFileProvider) { + runTest("transformServiceFile_${path}", ::ServiceFileTransformerTest) { + transformServiceFile(path, input1, input2, output) + } + } } /** @@ -98,21 +114,19 @@ private class ServiceFileTransformerTest : BaseTransformerTest(val a: A, val b: B, val c: C, val d: D) diff --git a/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/Arguments.kt b/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/Arguments.kt new file mode 100644 index 000000000..e813ccdce --- /dev/null +++ b/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/Arguments.kt @@ -0,0 +1,32 @@ +package com.github.jengelman.gradle.plugins.shadow.testkit + +@Suppress("UNCHECKED_CAST") +class Arguments private constructor(val list: List) { + operator fun get(index: Int): Any? = list[index] + + operator fun component1(): T = list[0] as T + + operator fun component2(): T = list[1] as T + + operator fun component3(): T = list[2] as T + + operator fun component4(): T = list[3] as T + + operator fun component5(): T = list[4] as T + + operator fun component6(): T = list[5] as T + + operator fun component7(): T = list[6] as T + + operator fun component8(): T = list[7] as T + + operator fun component9(): T = list[8] as T + + operator fun component10(): T = list[9] as T + + override fun toString(): String = list.joinToString(", ", prefix = "Arguments[", postfix = "]") + + companion object { + fun of(vararg arguments: Any?): Arguments = Arguments(arguments.toList()) + } +} From da32d5877e395f509ecd2b7fba963430abf8dcdb Mon Sep 17 00:00:00 2001 From: Zongle Wang Date: Sun, 16 Aug 2026 14:31:03 +0800 Subject: [PATCH 4/7] Update TestSuiteScope.kt Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../gradle/plugins/shadow/testkit/TestSuiteScope.kt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/TestSuiteScope.kt b/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/TestSuiteScope.kt index 6bfecb53a..70fd988eb 100644 --- a/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/TestSuiteScope.kt +++ b/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/TestSuiteScope.kt @@ -57,6 +57,17 @@ inline fun TestSuiteScope.runTests( } } } + + else -> { + runTest(function.name, factory) { + error( + "runTests() can only auto-run no-arg tests or tests whose parameters are all Boolean. " + + "'${function.name}' has unsupported parameters: " + + valueParams.joinToString(", ") { "${it.name}:${it.type}" } + + ". Use explicit runTest(...) registrations in the suite." + ) + } + } } } } From 3fdd070ee197731a686ad704de98fd6283e3843d Mon Sep 17 00:00:00 2001 From: Zongle Wang Date: Sun, 16 Aug 2026 14:31:24 +0800 Subject: [PATCH 5/7] Update JavaPluginsTest.kt Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../gradle/plugins/shadow/JavaPluginsTest.kt | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt index c907e2e53..96f3d9ef4 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt @@ -67,6 +67,34 @@ val JavaPluginsTests by testSuite { doNotReAddSuppressedGradleApi(configuration) } } + + val fallbackByPropertyCases = + listOf( + Triple( + "my.Main", + "my.Main", + "Adding $mainClassAttributeKey attribute to the manifest with value", + ), + Triple( + "", + null, + "Skipping adding $mainClassAttributeKey attribute to the manifest as it is empty.", + ), + ) + for ((index, case) in fallbackByPropertyCases.withIndex()) { + val (input, expected, message) = case + runTest("fallbackMainClassByProperty_$index", ::JavaPluginsTest) { + fallbackMainClassByProperty(input, expected, message) + } + } + + val fallbackByCliCases = listOf("my.Main" to "my.Main", "" to null) + for ((index, case) in fallbackByCliCases.withIndex()) { + val (input, expected) = case + runTest("fallbackMainClassByCliOption_$index", ::JavaPluginsTest) { + fallbackMainClassByCliOption(input, expected) + } + } } private class JavaPluginsTest : BasePluginTest() { From ea663d800376a6c0c340b5266b4217f28227317c Mon Sep 17 00:00:00 2001 From: Goooler Date: Sun, 16 Aug 2026 14:34:13 +0800 Subject: [PATCH 6/7] Revert "Update TestSuiteScope.kt" This reverts commit da32d5877e395f509ecd2b7fba963430abf8dcdb. --- .../gradle/plugins/shadow/testkit/TestSuiteScope.kt | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/TestSuiteScope.kt b/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/TestSuiteScope.kt index 70fd988eb..6bfecb53a 100644 --- a/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/TestSuiteScope.kt +++ b/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/TestSuiteScope.kt @@ -57,17 +57,6 @@ inline fun TestSuiteScope.runTests( } } } - - else -> { - runTest(function.name, factory) { - error( - "runTests() can only auto-run no-arg tests or tests whose parameters are all Boolean. " + - "'${function.name}' has unsupported parameters: " + - valueParams.joinToString(", ") { "${it.name}:${it.type}" } + - ". Use explicit runTest(...) registrations in the suite." - ) - } - } } } } From 3b825629a742c4da69c94159b7aab72185795c4a Mon Sep 17 00:00:00 2001 From: Goooler Date: Sun, 16 Aug 2026 14:44:37 +0800 Subject: [PATCH 7/7] Address review findings: restore missing tests and isolate localRepo --- .../gradle/plugins/shadow/JavaPluginsTest.kt | 17 ++++++++++++--- .../transformers/BaseTransformerTest.kt | 1 + .../ServiceFileTransformerTest.kt | 21 +++++++++++++++++++ .../shadow/internal/BytecodeRemappingTest.kt | 7 +++++++ .../GroovyExtensionModuleTransformerTest.kt | 17 +++++++++++---- 5 files changed, 56 insertions(+), 7 deletions(-) diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt index 96f3d9ef4..be7a326d5 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt @@ -25,6 +25,7 @@ import com.github.jengelman.gradle.plugins.shadow.testkit.getMainAttr import com.github.jengelman.gradle.plugins.shadow.testkit.getStream import com.github.jengelman.gradle.plugins.shadow.testkit.runTest import com.github.jengelman.gradle.plugins.shadow.testkit.runTests +import com.github.jengelman.gradle.plugins.shadow.util.AppendableMavenRepository import com.github.jengelman.gradle.plugins.shadow.util.prependText import com.github.jengelman.gradle.plugins.shadow.util.runProcess import de.infix.testBalloon.framework.core.testSuite @@ -33,6 +34,7 @@ import kotlin.io.path.deleteExisting import kotlin.io.path.invariantSeparatorsPathString import kotlin.io.path.name import kotlin.io.path.outputStream +import kotlin.io.path.readText import kotlin.io.path.writeText import kotlin.reflect.full.declaredFunctions import kotlin.reflect.jvm.javaMethod @@ -533,8 +535,8 @@ private class JavaPluginsTest : BasePluginTest() { } fun includeJavaLibraryConfigurationsByDefault() { - localRepo - .apply { + val customRepo = + AppendableMavenRepository(root = path("custom-local-maven-repo/")).apply { jarModule("my", "api", "1.0") { buildJar { insert("api.properties", "api") } } jarModule("my", "implementation", "1.0") { buildJar { insert("implementation.properties", "implementation") } @@ -544,7 +546,16 @@ private class JavaPluginsTest : BasePluginTest() { buildJar { insert("runtime-only.properties", "runtime-only") } } } - .publish() + customRepo.publish() + + settingsScript.writeText( + settingsScript + .readText() + .replace( + "repositories {", + "repositories {\n maven { url = '${customRepo.root.toUri()}' }", + ) + ) projectScript.writeText( """ diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/BaseTransformerTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/BaseTransformerTest.kt index 32a4c9216..77a512044 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/BaseTransformerTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/BaseTransformerTest.kt @@ -46,5 +46,6 @@ abstract class BaseTransformerTest : BasePluginTest() { const val ENTRY_TEST_PROPERTIES = "test.properties" const val ENTRY_SERVICES_SHADE = "META-INF/services/org.apache.maven.Shade" const val ENTRY_SERVICES_FOO = "META-INF/services/com.acme.Foo" + const val ENTRY_FOO_SHADE = "META-INF/foo/org.apache.maven.Shade" } } diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt index e7236e3fa..91839ba77 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt @@ -47,6 +47,27 @@ val ServiceFileTransformerTests by testSuite { } private class ServiceFileTransformerTest : BaseTransformerTest() { + fun serviceResourceTransformerAlternatePath() { + val one = buildJarOne { insert(ENTRY_FOO_SHADE, CONTENT_ONE) } + val two = buildJarTwo { insert(ENTRY_FOO_SHADE, CONTENT_TWO) } + val config = + """ + |dependencies { + | ${implementationFiles(one, two)} + |} + |$shadowJarTask { + | mergeServiceFiles("META-INF/foo") + |} + """ + .trimMargin() + projectScript.appendText(config) + + runWithSuccess(shadowJarPath) + + val content = outputShadowedJar.use { it.getContent(ENTRY_FOO_SHADE) } + assertThat(content).isEqualTo(CONTENT_ONE_TWO) + } + fun serviceResourceTransformerWithRelocation() { val one = buildJarOne { insert("com/example/Driver.class", createEmptyClassBytes("com/example/Driver")) diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/BytecodeRemappingTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/BytecodeRemappingTest.kt index ea75c822e..133623086 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/BytecodeRemappingTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/BytecodeRemappingTest.kt @@ -11,6 +11,7 @@ import assertk.assertions.isEqualTo import assertk.assertions.isInstanceOf import com.github.jengelman.gradle.plugins.shadow.relocation.SimpleRelocator import com.github.jengelman.gradle.plugins.shadow.testkit.requireResourceAsPath +import com.github.jengelman.gradle.plugins.shadow.testkit.runTest import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.util.noOpDelegate import de.infix.testBalloon.framework.core.testSuite @@ -34,6 +35,12 @@ import org.vafer.jdeb.shaded.objectweb.asm.Opcodes val BytecodeRemappingTests by testSuite { runTests(::BytecodeRemappingTest) + + for (primitiveDescriptor in listOf('B', 'C', 'D', 'F', 'I', 'J', 'S', 'Z')) { + runTest("primitivePlusClassMethodIsRelocated_$primitiveDescriptor", ::BytecodeRemappingTest) { + primitivePlusClassMethodIsRelocated(primitiveDescriptor) + } + } } /** diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformerTest.kt index 78661cdd8..ce540efaa 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformerTest.kt @@ -5,8 +5,10 @@ import assertk.assertions.isEqualTo import assertk.assertions.isFalse import assertk.assertions.isTrue import com.github.jengelman.gradle.plugins.shadow.relocation.SimpleRelocator +import com.github.jengelman.gradle.plugins.shadow.testkit.Arguments import com.github.jengelman.gradle.plugins.shadow.testkit.JarPath import com.github.jengelman.gradle.plugins.shadow.testkit.getContent +import com.github.jengelman.gradle.plugins.shadow.testkit.runTest import com.github.jengelman.gradle.plugins.shadow.testkit.runTests import com.github.jengelman.gradle.plugins.shadow.transformers.GroovyExtensionModuleTransformer.Companion.KEY_EXTENSION_CLASSES import com.github.jengelman.gradle.plugins.shadow.transformers.GroovyExtensionModuleTransformer.Companion.KEY_MODULE_NAME @@ -23,6 +25,13 @@ import java.util.Properties val GroovyExtensionModuleTransformerTests by testSuite { runTests(::GroovyExtensionModuleTransformerTest) + + for ((fooEntry: String, barEntry: String) in + GroovyExtensionModuleTransformerTest.resourcePathProvider) { + runTest("mergeDescriptors_${fooEntry}_${barEntry}", ::GroovyExtensionModuleTransformerTest) { + mergeDescriptors(fooEntry, barEntry) + } + } } private class GroovyExtensionModuleTransformerTest : @@ -109,19 +118,19 @@ private class GroovyExtensionModuleTransformerTest : val resourcePathProvider = listOf( - Pair( + Arguments.of( PATH_LEGACY_GROOVY_EXTENSION_MODULE_DESCRIPTOR, PATH_LEGACY_GROOVY_EXTENSION_MODULE_DESCRIPTOR, ), - Pair( + Arguments.of( PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR, PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR, ), - Pair( + Arguments.of( PATH_LEGACY_GROOVY_EXTENSION_MODULE_DESCRIPTOR, PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR, ), - Pair( + Arguments.of( PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR, PATH_LEGACY_GROOVY_EXTENSION_MODULE_DESCRIPTOR, ),