diff --git a/.editorconfig b/.editorconfig index 97c1b8453..f36ddfdde 100755 --- a/.editorconfig +++ b/.editorconfig @@ -7,9 +7,6 @@ indent_style = space insert_final_newline = true trim_trailing_whitespace = true -[*.{groovy,java}] -indent_size = 4 - [*.{kt,kts}] ij_kotlin_imports_layout = * ij_kotlin_allow_trailing_comma = true diff --git a/build.gradle.kts b/build.gradle.kts index 82be39fcb..58b4ff7d4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -76,6 +76,7 @@ dependencies { testImplementation(platform(libs.junit.bom)) testImplementation(libs.junit.jupiter) + testImplementation(libs.assertk) testImplementation(libs.xmlunit) testImplementation(libs.apache.commonsLang) testRuntimeOnly(libs.junit.platformLauncher) @@ -87,6 +88,7 @@ dependencies { funcTestImplementation(sourceSets.main.get().output) lintChecks(libs.androidx.gradlePluginLints) + lintChecks(libs.assertk.lint) } val integrationTest by tasks.registering(Test::class) { @@ -130,6 +132,14 @@ tasks.withType().configureEach { ) } +tasks.whenTaskAdded { + if (name == "lintAnalyzeJvmTest") { + // This task often fails on Windows CI devices. + enabled = !providers.systemProperty("os.name").get().startsWith("Windows") && + !providers.environmentVariable("CI").isPresent + } +} + tasks.register("release") { dependsOn( tasks.publish, diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7d3d1d228..406bfe1d4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,6 +11,7 @@ plexus-xml = "org.codehaus.plexus:plexus-xml:4.0.4" xmlunit = "org.xmlunit:xmlunit-legacy:2.10.0" androidx-gradlePluginLints = "androidx.lint:lint-gradle:1.0.0-alpha02" +assertk-lint = "com.jzbrooks:assertk-lint:1.3.0" # Dummy to get renovate updates, the version is used in rootProject build.gradle with spotless. ktlint = "com.pinterest.ktlint:ktlint-cli:1.4.1" @@ -18,6 +19,7 @@ spock = "org.spockframework:spock-core:2.3-groovy-3.0" junit-bom = "org.junit:junit-bom:5.11.3" junit-jupiter = { module = "org.junit.jupiter:junit-jupiter" } junit-platformLauncher = { module = "org.junit.platform:junit-platform-launcher" } +assertk = "com.willowtreeapps.assertk:assertk:0.28.1" [plugins] kotlin = "org.jetbrains.kotlin.jvm:2.1.0" diff --git a/src/funcTest/.editorconfig b/src/funcTest/.editorconfig new file mode 100755 index 000000000..3c75e2d26 --- /dev/null +++ b/src/funcTest/.editorconfig @@ -0,0 +1,2 @@ +[*.{groovy,java}] +indent_size = 4 diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformer.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformer.kt index 345cfaa44..8c273e6e7 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformer.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformer.kt @@ -13,6 +13,7 @@ import org.codehaus.plexus.util.xml.Xpp3Dom import org.codehaus.plexus.util.xml.Xpp3DomBuilder import org.codehaus.plexus.util.xml.Xpp3DomWriter import org.gradle.api.file.FileTreeElement +import org.gradle.api.tasks.Internal /** * A resource processor that aggregates plexus `components.xml` files. @@ -89,8 +90,8 @@ public open class ComponentsXmlResourceTransformer : Transformer { override fun hasTransformedResource(): Boolean = components.isNotEmpty() - @get:Throws(IOException::class) - private val transformedResource: ByteArray + @get:Internal + internal val transformedResource: ByteArray get() { val os = ByteArrayOutputStream(1024 * 4) XmlStreamWriter(os).use { writer -> diff --git a/src/test/.editorconfig b/src/test/.editorconfig deleted file mode 100755 index a54a0eb0d..000000000 --- a/src/test/.editorconfig +++ /dev/null @@ -1,4 +0,0 @@ -root = true - -[*.{groovy,java}] -indent_size = 2 diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocatorParameterTest.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocatorParameterTest.groovy deleted file mode 100644 index 28bd0a412..000000000 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocatorParameterTest.groovy +++ /dev/null @@ -1,30 +0,0 @@ -package com.github.jengelman.gradle.plugins.shadow.relocation - -import org.junit.jupiter.api.Test - -import static org.junit.jupiter.api.Assertions.fail - -/** - * Modified from org.apache.maven.plugins.shade.relocation.SimpleRelocatorParameterTest.java - */ -class SimpleRelocatorParameterTest { - - @Test - void testThatNullPatternInConstructorShouldNotThrowNullPointerException() { - constructThenFailOnNullPointerException(null, "") - } - - @Test - void testThatNullShadedPatternInConstructorShouldNotThrowNullPointerException() { - constructThenFailOnNullPointerException("", null) - } - - private static void constructThenFailOnNullPointerException(String pattern, String shadedPattern) { - try { - new SimpleRelocator(pattern, shadedPattern) - } - catch (NullPointerException ignored) { - fail("Constructor should not throw null pointer exceptions") - } - } -} diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocatorTest.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocatorTest.groovy deleted file mode 100644 index 1373c9ed5..000000000 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocatorTest.groovy +++ /dev/null @@ -1,190 +0,0 @@ -package com.github.jengelman.gradle.plugins.shadow.relocation - -import com.github.jengelman.gradle.plugins.shadow.ShadowStats -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test - -import static org.junit.jupiter.api.Assertions.assertEquals - -/** - * Modified from org.apache.maven.plugins.shade.relocation.SimpleRelocatorTest.java - */ -class SimpleRelocatorTest { - - @Test - void testCanRelocatePath() { - SimpleRelocator relocator - - relocator = new SimpleRelocator("org.foo") - assertEquals(true, relocator.canRelocatePath("org/foo/Class")) - assertEquals(true, relocator.canRelocatePath("org/foo/Class.class")) - assertEquals(true, relocator.canRelocatePath("org/foo/bar/Class")) - assertEquals(true, relocator.canRelocatePath("org/foo/bar/Class.class")) - assertEquals(false, relocator.canRelocatePath("com/foo/bar/Class")) - assertEquals(false, relocator.canRelocatePath("com/foo/bar/Class.class")) - assertEquals(false, relocator.canRelocatePath("org/Foo/Class")) - assertEquals(false, relocator.canRelocatePath("org/Foo/Class.class")) - - // Verify paths starting with '/' - assertEquals(false, relocator.canRelocatePath("/org/Foo/Class")) - assertEquals(false, relocator.canRelocatePath("/org/Foo/Class.class")) - - relocator = new SimpleRelocator("org.foo", null, null, - List.of("org.foo.Excluded", "org.foo.public.*", "org.foo.recurse.**", "org.foo.Public*Stuff")) - assertEquals(true, relocator.canRelocatePath("org/foo/Class")) - assertEquals(true, relocator.canRelocatePath("org/foo/Class.class")) - assertEquals(true, relocator.canRelocatePath("org/foo/excluded")) - assertEquals(false, relocator.canRelocatePath("org/foo/Excluded")) - assertEquals(false, relocator.canRelocatePath("org/foo/Excluded.class")) - assertEquals(false, relocator.canRelocatePath("org/foo/public")) - assertEquals(false, relocator.canRelocatePath("org/foo/public/Class")) - assertEquals(false, relocator.canRelocatePath("org/foo/public/Class.class")) - assertEquals(false, relocator.canRelocatePath("org/foo/public/sub")) - assertEquals(true, relocator.canRelocatePath("org/foo/public/sub/Class")) - assertEquals(true, relocator.canRelocatePath("org/foo/publicRELOC/Class")) - assertEquals(true, relocator.canRelocatePath("org/foo/PrivateStuff")) - assertEquals(true, relocator.canRelocatePath("org/foo/PrivateStuff.class")) - assertEquals(false, relocator.canRelocatePath("org/foo/PublicStuff")) - assertEquals(false, relocator.canRelocatePath("org/foo/PublicStuff.class")) - assertEquals(false, relocator.canRelocatePath("org/foo/PublicUtilStuff")) - assertEquals(false, relocator.canRelocatePath("org/foo/PublicUtilStuff.class")) - assertEquals(false, relocator.canRelocatePath("org/foo/recurse")) - assertEquals(false, relocator.canRelocatePath("org/foo/recurse/Class")) - assertEquals(false, relocator.canRelocatePath("org/foo/recurse/Class.class")) - assertEquals(false, relocator.canRelocatePath("org/foo/recurse/sub")) - assertEquals(false, relocator.canRelocatePath("org/foo/recurse/sub/Class")) - assertEquals(false, relocator.canRelocatePath("org/foo/recurse/sub/Class.class")) - - // Verify edge cases - relocator = new SimpleRelocator("org.f") - assertEquals(false, relocator.canRelocatePath("")) // Empty path - assertEquals(false, relocator.canRelocatePath(".class")) // only .class - assertEquals(false, relocator.canRelocatePath("te")) // shorter than path pattern - assertEquals(false, relocator.canRelocatePath("test")) // shorter than path pattern with / - assertEquals(true, relocator.canRelocatePath("org/f")) // equal to path pattern - assertEquals(true, relocator.canRelocatePath("/org/f")) // equal to path pattern with / - } - - @Test - void testCanRelocatePathWithRegex() { - SimpleRelocator relocator - - // Include with Regex - relocator = new SimpleRelocator("org.foo", null, Collections.singletonList("%regex[org/foo/R(\\\$.*)?\$]"), null) - assertEquals(true, relocator.canRelocatePath("org/foo/R.class")) - assertEquals(true, relocator.canRelocatePath("org/foo/R\$string.class")) - assertEquals(true, relocator.canRelocatePath("org/foo/R\$layout.class")) - assertEquals(false, relocator.canRelocatePath("org/foo/Recording/R.class")) - assertEquals(false, relocator.canRelocatePath("org/foo/Recording.class")) - assertEquals(false, relocator.canRelocatePath("org/foo/bar/R\$string.class")) - assertEquals(false, relocator.canRelocatePath("org/R.class")) - assertEquals(false, relocator.canRelocatePath("org/R\$string.class")) - - // Exclude with Regex - relocator = new SimpleRelocator("org.foo") - relocator.exclude("%regex[org/foo/.*Factory[0-9].*]") - assertEquals(true, relocator.canRelocatePath("org/foo/Factory.class")) - assertEquals(true, relocator.canRelocatePath("org/foo/FooFactoryMain.class")) - assertEquals(true, relocator.canRelocatePath("org/foo/BarFactory.class")) - assertEquals(false, relocator.canRelocatePath("org/foo/Factory0.class")) - assertEquals(false, relocator.canRelocatePath("org/foo/FooFactory1Main.class")) - assertEquals(false, relocator.canRelocatePath("org/foo/BarFactory2.class")) - - // Include with Regex and normal pattern - relocator = new SimpleRelocator("org.foo", null, - List.of("%regex[org/foo/.*Factory[0-9].*]", "org.foo.public.*")) - assertEquals(true, relocator.canRelocatePath("org/foo/Factory1.class")) - assertEquals(true, relocator.canRelocatePath("org/foo/public/Bar.class")) - assertEquals(false, relocator.canRelocatePath("org/foo/Factory.class")) - assertEquals(false, relocator.canRelocatePath("org/foo/R.class")) - } - - @Test - void testCanRelocateClass() { - SimpleRelocator relocator - - relocator = new SimpleRelocator("org.foo") - assertEquals(true, relocator.canRelocateClass("org.foo.Class")) - assertEquals(true, relocator.canRelocateClass("org.foo.bar.Class")) - assertEquals(false, relocator.canRelocateClass("com.foo.bar.Class")) - assertEquals(false, relocator.canRelocateClass("org.Foo.Class")) - - relocator = new SimpleRelocator("org.foo", null, null, - List.of("org.foo.Excluded", "org.foo.public.*", "org.foo.recurse.**", "org.foo.Public*Stuff")) - assertEquals(true, relocator.canRelocateClass("org.foo.Class")) - assertEquals(true, relocator.canRelocateClass("org.foo.excluded")) - assertEquals(false, relocator.canRelocateClass("org.foo.Excluded")) - assertEquals(false, relocator.canRelocateClass("org.foo.public")) - assertEquals(false, relocator.canRelocateClass("org.foo.public.Class")) - assertEquals(false, relocator.canRelocateClass("org.foo.public.sub")) - assertEquals(true, relocator.canRelocateClass("org.foo.public.sub.Class")) - assertEquals(true, relocator.canRelocateClass("org.foo.publicRELOC.Class")) - assertEquals(true, relocator.canRelocateClass("org.foo.PrivateStuff")) - assertEquals(false, relocator.canRelocateClass("org.foo.PublicStuff")) - assertEquals(false, relocator.canRelocateClass("org.foo.PublicUtilStuff")) - assertEquals(false, relocator.canRelocateClass("org.foo.recurse")) - assertEquals(false, relocator.canRelocateClass("org.foo.recurse.Class")) - assertEquals(false, relocator.canRelocateClass("org.foo.recurse.sub")) - assertEquals(false, relocator.canRelocateClass("org.foo.recurse.sub.Class")) - } - - @Test - void testCanRelocateRawString() { - SimpleRelocator relocator - - relocator = new SimpleRelocator("org/foo", null, null, null, true) - assertEquals(true, relocator.canRelocatePath("(I)org/foo/bar/Class")) - - relocator = new SimpleRelocator("^META-INF/org.foo.xml\$", null, null, null, true) - assertEquals(true, relocator.canRelocatePath("META-INF/org.foo.xml")) - } - - //MSHADE-119, make sure that the easy part of this works. - @Test - void testCanRelocateAbsClassPath() { - SimpleRelocator relocator = new SimpleRelocator("org.apache.velocity", "org.apache.momentum") - assertEquals("/org/apache/momentum/mass.properties", relocator.relocatePath(pathContext("/org/apache/velocity/mass.properties"))) - - } - - @Test - void testRelocatePath() { - SimpleRelocator relocator - - relocator = new SimpleRelocator("org.foo") - assertEquals("hidden/org/foo/bar/Class.class", relocator.relocatePath(pathContext("org/foo/bar/Class.class"))) - - relocator = new SimpleRelocator("org.foo", "private.stuff") - assertEquals("private/stuff/bar/Class.class", relocator.relocatePath(pathContext("org/foo/bar/Class.class"))) - } - - @Test - void testRelocateClass() { - SimpleRelocator relocator - - relocator = new SimpleRelocator("org.foo") - assertEquals("hidden.org.foo.bar.Class", relocator.relocateClass(classContext("org.foo.bar.Class"))) - - relocator = new SimpleRelocator("org.foo", "private.stuff") - assertEquals("private.stuff.bar.Class", relocator.relocateClass(classContext("org.foo.bar.Class"))) - } - - @Test - void testRelocateRawString() { - SimpleRelocator relocator - - relocator = new SimpleRelocator("Lorg/foo", "Lhidden/org/foo", null, null, true) - assertEquals("(I)Lhidden/org/foo/bar/Class", relocator.relocatePath(pathContext("(I)Lorg/foo/bar/Class"))) - - relocator = new SimpleRelocator("^META-INF/org.foo.xml\$", "META-INF/hidden.org.foo.xml", null, null, true) - assertEquals("META-INF/hidden.org.foo.xml", relocator.relocatePath(pathContext("META-INF/org.foo.xml"))) - } - - protected static RelocatePathContext pathContext(String path) { - return RelocatePathContext.builder().path(path).build() - } - - protected static RelocateClassContext classContext(String className) { - return RelocateClassContext.builder().className(className).build() - } -} diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformerTest.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformerTest.groovy deleted file mode 100644 index 27117c51c..000000000 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformerTest.groovy +++ /dev/null @@ -1,32 +0,0 @@ -package com.github.jengelman.gradle.plugins.shadow.transformers - -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test - -import static org.junit.jupiter.api.Assertions.assertFalse -import static org.junit.jupiter.api.Assertions.assertTrue - -/** - * Modified from org.apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformerTest.java - */ -class ApacheLicenseResourceTransformerTest extends TransformerTestSupport { - - static { - setupTurkishLocale() - } - - @BeforeEach - void setUp() { - transformer = new ApacheLicenseResourceTransformer() - } - - @Test - void testCanTransformResource() { - assertTrue(transformer.canTransformResource(getFileElement("META-INF/LICENSE"))) - assertTrue(transformer.canTransformResource(getFileElement("META-INF/LICENSE.TXT"))) - assertTrue(transformer.canTransformResource(getFileElement("META-INF/License.txt"))) - assertTrue(transformer.canTransformResource(getFileElement("META-INF/LICENSE.md"))) - assertTrue(transformer.canTransformResource(getFileElement("META-INF/License.md"))) - assertFalse(transformer.canTransformResource(getFileElement("META-INF/MANIFEST.MF"))) - } -} diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformerTest.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformerTest.groovy deleted file mode 100644 index 9a4b2b42b..000000000 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformerTest.groovy +++ /dev/null @@ -1,84 +0,0 @@ -package com.github.jengelman.gradle.plugins.shadow.transformers - -import com.github.jengelman.gradle.plugins.shadow.ShadowStats -import com.github.jengelman.gradle.plugins.shadow.relocation.Relocator -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test - -import static org.junit.jupiter.api.Assertions.* - -/** - * Modified from org.apache.maven.plugins.shade.resource.ApacheNoticeResourceTransformerParameterTests.java - */ -class ApacheNoticeResourceTransformerTest extends TransformerTestSupport { - - private static final String NOTICE_RESOURCE = "META-INF/NOTICE" - - static { - setupTurkishLocale() - } - - @BeforeEach - void setUp() { - transformer = new ApacheNoticeResourceTransformer(objectFactory) - } - - @Test - void testCanTransformResource() { - assertTrue(transformer.canTransformResource(getFileElement("META-INF/NOTICE"))) - assertTrue(transformer.canTransformResource(getFileElement("META-INF/NOTICE.TXT"))) - assertTrue(transformer.canTransformResource(getFileElement("META-INF/Notice.txt"))) - assertTrue(transformer.canTransformResource(getFileElement("META-INF/NOTICE.md"))) - assertTrue(transformer.canTransformResource(getFileElement("META-INF/Notice.md"))) - assertFalse(transformer.canTransformResource(getFileElement("META-INF/MANIFEST.MF"))) - } - - @Test - void testNoParametersShouldNotThrowNullPointerWhenNoInput() { - processAndFailOnNullPointer("") - } - - @Test - void testNoParametersShouldNotThrowNullPointerWhenNoLinesOfInput() { - processAndFailOnNullPointer("Some notice text") - } - - @Test - void testNoParametersShouldNotThrowNullPointerWhenOneLineOfInput() { - processAndFailOnNullPointer("Some notice text\n") - } - - @Test - void testNoParametersShouldNotThrowNullPointerWhenTwoLinesOfInput() { - processAndFailOnNullPointer("Some notice text\nSome notice text\n") - } - - @Test - void testNoParametersShouldNotThrowNullPointerWhenLineStartsWithSlashSlash() { - processAndFailOnNullPointer("Some notice text\n//Some notice text\n") - } - - @Test - void testNoParametersShouldNotThrowNullPointerWhenLineIsSlashSlash() { - processAndFailOnNullPointer("//\n") - } - - @Test - void testNoParametersShouldNotThrowNullPointerWhenLineIsEmpty() { - processAndFailOnNullPointer("\n") - } - - private static void processAndFailOnNullPointer(final String noticeText) { - try { - final ByteArrayInputStream noticeInputStream = new ByteArrayInputStream(noticeText.getBytes()) - def transformerContext = TransformerContext.builder() - .path(NOTICE_RESOURCE) - .inputStream(noticeInputStream) - .build() - transformer.transform(transformerContext) - } - catch (NullPointerException ignored) { - fail("Null pointer should not be thrown when no parameters are set.") - } - } -} diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformerTest.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformerTest.groovy deleted file mode 100644 index f9d4b8f59..000000000 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformerTest.groovy +++ /dev/null @@ -1,32 +0,0 @@ -package com.github.jengelman.gradle.plugins.shadow.transformers - -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test - -import static org.junit.jupiter.api.Assertions.assertFalse -import static org.junit.jupiter.api.Assertions.assertTrue - -/** - * Modified from org.apache.maven.plugins.shade.resource.AppendingTransformerTest.java - */ -class AppendingTransformerTest extends TransformerTestSupport { - - static { - setupTurkishLocale() - } - - @BeforeEach - void setUp() { - transformer = new AppendingTransformer(objectFactory) - } - - @Test - void testCanTransformResource() { - transformer.resource.set("abcdefghijklmnopqrstuvwxyz") - - assertTrue(transformer.canTransformResource(getFileElement("abcdefghijklmnopqrstuvwxyz"))) - assertTrue(transformer.canTransformResource(getFileElement("ABCDEFGHIJKLMNOPQRSTUVWXYZ"))) - assertFalse(transformer.canTransformResource(getFileElement("META-INF/MANIFEST.MF"))) - } - -} diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformerTest.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformerTest.groovy deleted file mode 100644 index 840969b36..000000000 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformerTest.groovy +++ /dev/null @@ -1,41 +0,0 @@ -package com.github.jengelman.gradle.plugins.shadow.transformers - -import org.codehaus.plexus.util.IOUtil -import org.custommonkey.xmlunit.Diff -import org.custommonkey.xmlunit.XMLAssert -import org.custommonkey.xmlunit.XMLUnit -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test - -/** - * Modified from org.apache.maven.plugins.shade.resource.ComponentsXmlResourceTransformerTest.java - */ -class ComponentsXmlResourceTransformerTest extends TransformerTestSupport { - @BeforeEach - void setUp() { - transformer = new ComponentsXmlResourceTransformer() - } - - @Test - void testConfigurationMerging() { - - XMLUnit.setNormalizeWhitespace(true) - - transformer.transform( - TransformerContext.builder() - .path("components-1.xml") - .inputStream(requireResourceAsStream("components-1.xml")) - .build() - ) - transformer.transform( - TransformerContext.builder() - .path("components-1.xml") - .inputStream(requireResourceAsStream("components-2.xml")) - .build() - ) - Diff diff = XMLUnit.compareXML( - IOUtil.toString(requireResourceAsStream("components-expected.xml"), "UTF-8"), - IOUtil.toString(transformer.transformedResource, "UTF-8")) - XMLAssert.assertXMLIdentical(diff, true) - } -} diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestAppenderTransformerTest.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestAppenderTransformerTest.groovy deleted file mode 100644 index 6db9336f5..000000000 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestAppenderTransformerTest.groovy +++ /dev/null @@ -1,116 +0,0 @@ -package com.github.jengelman.gradle.plugins.shadow.transformers - -import com.github.jengelman.gradle.plugins.shadow.ShadowStats -import com.github.jengelman.gradle.plugins.shadow.relocation.Relocator -import org.apache.tools.zip.ZipOutputStream -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test - -import java.util.zip.ZipFile - -import static java.util.Arrays.asList -import static org.junit.jupiter.api.Assertions.* - -/** - * Test for {@link ManifestAppenderTransformer}. - */ -class ManifestAppenderTransformerTest extends TransformerTestSupport { - - @BeforeEach - void setUp() { - transformer = new ManifestAppenderTransformer(objectFactory) - } - - @Test - void testCanTransformResource() { - transformer.with { - append('Name', 'org/foo/bar/') - append('Sealed', true) - } - - assertTrue(transformer.canTransformResource(getFileElement(MANIFEST_NAME))) - assertTrue(transformer.canTransformResource(getFileElement(MANIFEST_NAME.toLowerCase()))) - } - - @Test - void testHasTransformedResource() { - transformer.append('Tag', 'Something') - - assertTrue(transformer.hasTransformedResource()) - } - - @Test - void testHasNotTransformedResource() { - assertFalse(transformer.hasTransformedResource()) - } - - @Test - void testTransformation() { - transformer.with { - append('Name', 'org/foo/bar/') - append('Sealed', true) - append('Name', 'com/example/') - append('Sealed', false) - - transform(new TransformerContext(MANIFEST_NAME, requireResourceAsStream(MANIFEST_NAME))) - } - - def testableZipFile = File.createTempFile("testable-zip-file-", ".jar") - def fileOutputStream = new FileOutputStream(testableZipFile) - def bufferedOutputStream = new BufferedOutputStream(fileOutputStream) - def zipOutputStream = new ZipOutputStream(bufferedOutputStream) - - try { - transformer.modifyOutputStream(zipOutputStream, true) - } finally { - zipOutputStream.close() - } - - def targetLines = readFrom(testableZipFile, MANIFEST_NAME) - assertFalse(targetLines.isEmpty()) - assertTrue(targetLines.size() > 4) - - def trailer = targetLines.with { subList(size() - 5, size()) } - assertEquals(asList( - "Name: org/foo/bar/", - "Sealed: true", - "Name: com/example/", - "Sealed: false", - ""), trailer - ) - } - - @Test - void testNoTransformation() { - def sourceLines = requireResourceAsStream(MANIFEST_NAME).readLines() - - transformer.transform(new TransformerContext(MANIFEST_NAME, requireResourceAsStream(MANIFEST_NAME))) - - def testableZipFile = File.createTempFile("testable-zip-file-", ".jar") - def fileOutputStream = new FileOutputStream(testableZipFile) - def bufferedOutputStream = new BufferedOutputStream(fileOutputStream) - def zipOutputStream = new ZipOutputStream(bufferedOutputStream) - - try { - transformer.modifyOutputStream(zipOutputStream, true) - } finally { - zipOutputStream.close() - } - def targetLines = readFrom(testableZipFile, MANIFEST_NAME) - - assertEquals(sourceLines, targetLines) - } - - static List readFrom(File jarFile, String resourceName) { - def zip = new ZipFile(jarFile) - try { - def entry = zip.getEntry(resourceName) - if (!entry) { - return Collections.emptyList() - } - return zip.getInputStream(entry).readLines() - } finally { - zip.close() - } - } -} diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.groovy deleted file mode 100644 index c69ce09f2..000000000 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.groovy +++ /dev/null @@ -1,87 +0,0 @@ -package com.github.jengelman.gradle.plugins.shadow.transformers - -import org.apache.tools.zip.ZipOutputStream -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test - -import java.util.zip.ZipFile - -import static org.junit.jupiter.api.Assertions.* - -/** - * Test for {@link PropertiesFileTransformer}. - */ -final class PropertiesFileTransformerTest extends TransformerTestSupport { - - @BeforeEach - void setUp() { - transformer = new PropertiesFileTransformer(objectFactory) - } - - @Test - void testHasTransformedResource() { - transformer.transform(new TransformerContext(MANIFEST_NAME, requireResourceAsStream(MANIFEST_NAME))) - - assertTrue(transformer.hasTransformedResource()) - } - - @Test - void testHasNotTransformedResource() { - assertFalse(transformer.hasTransformedResource()) - } - - @Test - void testTransformation() { - transformer.transform(new TransformerContext(MANIFEST_NAME, requireResourceAsStream(MANIFEST_NAME))) - - def testableZipFile = doTransformAndGetTransformedFile(transformer, false) - def targetLines = readFrom(testableZipFile, MANIFEST_NAME) - - assertFalse(targetLines.isEmpty()) - - assertTrue(targetLines.contains("Manifest-Version=1.0")) - } - - @Test - void testTransformationPropertiesAreReproducible() { - transformer.transform(new TransformerContext(MANIFEST_NAME, requireResourceAsStream(MANIFEST_NAME))) - - def firstRunTransformedFile = doTransformAndGetTransformedFile(transformer, true) - def firstRunTargetLines = readFrom(firstRunTransformedFile, MANIFEST_NAME) - - Thread.sleep(1000) // wait for 1sec to ensure timestamps in properties would change - - def secondRunTransformedFile = doTransformAndGetTransformedFile(transformer, true) - def secondRunTargetLines = readFrom(secondRunTransformedFile, MANIFEST_NAME) - - assertEquals(firstRunTargetLines, secondRunTargetLines) - } - - static File doTransformAndGetTransformedFile(final PropertiesFileTransformer transformer, final boolean preserveFileTimestamps) { - def testableZipFile = File.createTempFile("testable-zip-file-", ".jar") - def fileOutputStream = new FileOutputStream(testableZipFile) - def bufferedOutputStream = new BufferedOutputStream(fileOutputStream) - def zipOutputStream = new ZipOutputStream(bufferedOutputStream) - - try { - transformer.modifyOutputStream(zipOutputStream, preserveFileTimestamps) - } finally { - zipOutputStream.close() - } - - return testableZipFile - } - - static List readFrom(File jarFile, String resourceName) { - def zip = new ZipFile(jarFile) - try { - def entry = zip.getEntry(resourceName) - if (!entry) { - return Collections.emptyList() - } - return zip.getInputStream(entry).readLines() - } finally { - zip.close() - } - } -} diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerTestSupport.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerTestSupport.groovy deleted file mode 100644 index f88d5492b..000000000 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerTestSupport.groovy +++ /dev/null @@ -1,28 +0,0 @@ -package com.github.jengelman.gradle.plugins.shadow.transformers - -import org.gradle.api.file.FileTreeElement -import org.gradle.api.file.RelativePath -import org.gradle.api.internal.file.DefaultFileTreeElement -import org.gradle.testfixtures.ProjectBuilder - -abstract class TransformerTestSupport { - protected static T transformer - protected static final def objectFactory = ProjectBuilder.builder().build().objects - protected static final String MANIFEST_NAME = "META-INF/MANIFEST.MF" - - protected static FileTreeElement getFileElement(String path) { - return new DefaultFileTreeElement(null, RelativePath.parse(true, path), null, null) - } - - /** - * NOTE: The Turkish locale has an usual case transformation for the letters "I" and "i", making it a prime - * choice to test for improper case-less string comparisons. - */ - protected static setupTurkishLocale() { - Locale.setDefault(new Locale("tr")) - } - - protected InputStream requireResourceAsStream(String resource) { - this.class.classLoader.getResourceAsStream(resource) - } -} diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformerTest.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformerTest.groovy deleted file mode 100644 index 71c02736c..000000000 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformerTest.groovy +++ /dev/null @@ -1,31 +0,0 @@ -package com.github.jengelman.gradle.plugins.shadow.transformers - -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test - -import static org.junit.jupiter.api.Assertions.assertFalse -import static org.junit.jupiter.api.Assertions.assertTrue - -/** - * Modified from org.apache.maven.plugins.shade.resource.XmlAppendingTransformerTest.java - */ -class XmlAppendingTransformerTest extends TransformerTestSupport { - - static { - setupTurkishLocale() - } - - @BeforeEach - void setUp() { - transformer = new XmlAppendingTransformer(objectFactory) - } - - @Test - void testCanTransformResource() { - transformer.resource.set("abcdefghijklmnopqrstuvwxyz") - - assertTrue(transformer.canTransformResource(getFileElement("abcdefghijklmnopqrstuvwxyz"))) - assertTrue(transformer.canTransformResource(getFileElement("ABCDEFGHIJKLMNOPQRSTUVWXYZ"))) - assertFalse(transformer.canTransformResource(getFileElement("META-INF/MANIFEST.MF"))) - } -} 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 new file mode 100644 index 000000000..ad8d042b9 --- /dev/null +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocatorTest.kt @@ -0,0 +1,189 @@ +package com.github.jengelman.gradle.plugins.shadow.relocation + +import assertk.assertThat +import assertk.assertions.isEqualTo +import assertk.assertions.isFalse +import assertk.assertions.isTrue +import org.junit.jupiter.api.Test + +/** + * 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). + * + * @author John Engelman + */ +class SimpleRelocatorTest { + + @Test + fun testCanRelocatePath() { + var relocator = SimpleRelocator("org.foo") + assertThat(relocator.canRelocatePath("org/foo/Class")).isTrue() + assertThat(relocator.canRelocatePath("org/foo/Class.class")).isTrue() + assertThat(relocator.canRelocatePath("org/foo/bar/Class")).isTrue() + assertThat(relocator.canRelocatePath("org/foo/bar/Class.class")).isTrue() + assertThat(relocator.canRelocatePath("com/foo/bar/Class")).isFalse() + assertThat(relocator.canRelocatePath("com/foo/bar/Class.class")).isFalse() + assertThat(relocator.canRelocatePath("org/Foo/Class")).isFalse() + assertThat(relocator.canRelocatePath("org/Foo/Class.class")).isFalse() + + // Verify paths starting with '/' + assertThat(relocator.canRelocatePath("/org/Foo/Class")).isFalse() + assertThat(relocator.canRelocatePath("/org/Foo/Class.class")).isFalse() + + relocator = SimpleRelocator( + "org.foo", + excludes = listOf("org.foo.Excluded", "org.foo.public.*", "org.foo.recurse.**", "org.foo.Public*Stuff"), + ) + assertThat(relocator.canRelocatePath("org/foo/Class")).isTrue() + assertThat(relocator.canRelocatePath("org/foo/Class.class")).isTrue() + assertThat(relocator.canRelocatePath("org/foo/excluded")).isTrue() + assertThat(relocator.canRelocatePath("org/foo/Excluded")).isFalse() + assertThat(relocator.canRelocatePath("org/foo/Excluded.class")).isFalse() + assertThat(relocator.canRelocatePath("org/foo/public")).isFalse() + assertThat(relocator.canRelocatePath("org/foo/public/Class")).isFalse() + assertThat(relocator.canRelocatePath("org/foo/public/Class.class")).isFalse() + assertThat(relocator.canRelocatePath("org/foo/public/sub")).isFalse() + assertThat(relocator.canRelocatePath("org/foo/public/sub/Class")).isTrue() + assertThat(relocator.canRelocatePath("org/foo/publicRELOC/Class")).isTrue() + assertThat(relocator.canRelocatePath("org/foo/PrivateStuff")).isTrue() + assertThat(relocator.canRelocatePath("org/foo/PrivateStuff.class")).isTrue() + assertThat(relocator.canRelocatePath("org/foo/PublicStuff")).isFalse() + assertThat(relocator.canRelocatePath("org/foo/PublicStuff.class")).isFalse() + assertThat(relocator.canRelocatePath("org/foo/PublicUtilStuff")).isFalse() + assertThat(relocator.canRelocatePath("org/foo/PublicUtilStuff.class")).isFalse() + assertThat(relocator.canRelocatePath("org/foo/recurse")).isFalse() + assertThat(relocator.canRelocatePath("org/foo/recurse/Class")).isFalse() + assertThat(relocator.canRelocatePath("org/foo/recurse/Class.class")).isFalse() + assertThat(relocator.canRelocatePath("org/foo/recurse/sub")).isFalse() + assertThat(relocator.canRelocatePath("org/foo/recurse/sub/Class")).isFalse() + assertThat(relocator.canRelocatePath("org/foo/recurse/sub/Class.class")).isFalse() + + // Verify edge cases + relocator = SimpleRelocator("org.f") + assertThat(relocator.canRelocatePath("")).isFalse() // Empty path + assertThat(relocator.canRelocatePath(".class")).isFalse() // only .class + assertThat(relocator.canRelocatePath("te")).isFalse() // shorter than path pattern + assertThat(relocator.canRelocatePath("test")).isFalse() // shorter than path pattern with / + assertThat(relocator.canRelocatePath("org/f")).isTrue() // equal to path pattern + assertThat(relocator.canRelocatePath("/org/f")).isTrue() // equal to path pattern with / + } + + @Test + fun testCanRelocatePathWithRegex() { + // Include with Regex + var relocator = SimpleRelocator("org.foo", includes = listOf("%regex[org/foo/R(\\\$.*)?\$]")) + assertThat(relocator.canRelocatePath("org/foo/R.class")).isTrue() + assertThat(relocator.canRelocatePath("org/foo/R\$string.class")).isTrue() + assertThat(relocator.canRelocatePath("org/foo/R\$layout.class")).isTrue() + assertThat(relocator.canRelocatePath("org/foo/Recording/R.class")).isFalse() + assertThat(relocator.canRelocatePath("org/foo/Recording.class")).isFalse() + assertThat(relocator.canRelocatePath("org/foo/bar/R\$string.class")).isFalse() + assertThat(relocator.canRelocatePath("org/R.class")).isFalse() + assertThat(relocator.canRelocatePath("org/R\$string.class")).isFalse() + + // Exclude with Regex + relocator = SimpleRelocator("org.foo") + relocator.exclude("%regex[org/foo/.*Factory[0-9].*]") + assertThat(relocator.canRelocatePath("org/foo/Factory.class")).isTrue() + assertThat(relocator.canRelocatePath("org/foo/FooFactoryMain.class")).isTrue() + assertThat(relocator.canRelocatePath("org/foo/BarFactory.class")).isTrue() + assertThat(relocator.canRelocatePath("org/foo/Factory0.class")).isFalse() + assertThat(relocator.canRelocatePath("org/foo/FooFactory1Main.class")).isFalse() + assertThat(relocator.canRelocatePath("org/foo/BarFactory2.class")).isFalse() + + // Include with Regex and normal pattern + relocator = SimpleRelocator( + "org.foo", + includes = listOf("%regex[org/foo/.*Factory[0-9].*]", "org.foo.public.*"), + ) + assertThat(relocator.canRelocatePath("org/foo/Factory1.class")).isTrue() + assertThat(relocator.canRelocatePath("org/foo/public/Bar.class")).isTrue() + assertThat(relocator.canRelocatePath("org/foo/Factory.class")).isFalse() + assertThat(relocator.canRelocatePath("org/foo/R.class")).isFalse() + } + + @Test + fun testCanRelocateClass() { + var relocator = SimpleRelocator("org.foo") + assertThat(relocator.canRelocateClass("org.foo.Class")).isTrue() + assertThat(relocator.canRelocateClass("org.foo.bar.Class")).isTrue() + assertThat(relocator.canRelocateClass("com.foo.bar.Class")).isFalse() + assertThat(relocator.canRelocateClass("org.Foo.Class")).isFalse() + + relocator = SimpleRelocator( + "org.foo", + excludes = listOf("org.foo.Excluded", "org.foo.public.*", "org.foo.recurse.**", "org.foo.Public*Stuff"), + ) + assertThat(relocator.canRelocateClass("org.foo.Class")).isTrue() + assertThat(relocator.canRelocateClass("org.foo.excluded")).isTrue() + assertThat(relocator.canRelocateClass("org.foo.Excluded")).isFalse() + assertThat(relocator.canRelocateClass("org.foo.public")).isFalse() + assertThat(relocator.canRelocateClass("org.foo.public.Class")).isFalse() + assertThat(relocator.canRelocateClass("org.foo.public.sub")).isFalse() + assertThat(relocator.canRelocateClass("org.foo.public.sub.Class")).isTrue() + assertThat(relocator.canRelocateClass("org.foo.publicRELOC.Class")).isTrue() + assertThat(relocator.canRelocateClass("org.foo.PrivateStuff")).isTrue() + assertThat(relocator.canRelocateClass("org.foo.PublicStuff")).isFalse() + assertThat(relocator.canRelocateClass("org.foo.PublicUtilStuff")).isFalse() + assertThat(relocator.canRelocateClass("org.foo.recurse")).isFalse() + assertThat(relocator.canRelocateClass("org.foo.recurse.Class")).isFalse() + assertThat(relocator.canRelocateClass("org.foo.recurse.sub")).isFalse() + assertThat(relocator.canRelocateClass("org.foo.recurse.sub.Class")).isFalse() + } + + @Test + fun testCanRelocateRawString() { + var relocator = SimpleRelocator("org/foo", _rawString = true) + assertThat(relocator.canRelocatePath("(I)org/foo/bar/Class")).isTrue() + + relocator = SimpleRelocator("^META-INF/org.foo.xml\$", _rawString = true) + assertThat(relocator.canRelocatePath("META-INF/org.foo.xml")).isTrue() + } + + @Test + fun testCanRelocateAbsClassPath() { + val relocator = SimpleRelocator("org.apache.velocity", "org.apache.momentum") + assertThat(relocator.relocatePath(pathContext("/org/apache/velocity/mass.properties"))) + .isEqualTo("/org/apache/momentum/mass.properties") + } + + @Test + fun testRelocatePath() { + var relocator = SimpleRelocator("org.foo") + assertThat(relocator.relocatePath(pathContext("org/foo/bar/Class.class"))) + .isEqualTo("hidden/org/foo/bar/Class.class") + + relocator = SimpleRelocator("org.foo", "private.stuff") + assertThat(relocator.relocatePath(pathContext("org/foo/bar/Class.class"))) + .isEqualTo("private/stuff/bar/Class.class") + } + + @Test + fun testRelocateClass() { + var relocator = SimpleRelocator("org.foo") + assertThat(relocator.relocateClass(classContext())) + .isEqualTo("hidden.org.foo.bar.Class") + + relocator = SimpleRelocator("org.foo", "private.stuff") + assertThat(relocator.relocateClass(classContext())) + .isEqualTo("private.stuff.bar.Class") + } + + @Test + fun testRelocateRawString() { + var relocator = SimpleRelocator("Lorg/foo", "Lhidden/org/foo", _rawString = true) + assertThat(relocator.relocatePath(pathContext("(I)Lorg/foo/bar/Class"))) + .isEqualTo("(I)Lhidden/org/foo/bar/Class") + + relocator = SimpleRelocator("^META-INF/org.foo.xml\$", "META-INF/hidden.org.foo.xml", _rawString = true) + assertThat(relocator.relocatePath(pathContext("META-INF/org.foo.xml"))) + .isEqualTo("META-INF/hidden.org.foo.xml") + } + + private fun pathContext(path: String): RelocatePathContext { + return RelocatePathContext.builder().path(path).build() + } + + private fun classContext(className: String = "org.foo.bar.Class"): RelocateClassContext { + return RelocateClassContext.builder().className(className).build() + } +} 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 new file mode 100644 index 000000000..407721fed --- /dev/null +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformerTest.kt @@ -0,0 +1,32 @@ +package com.github.jengelman.gradle.plugins.shadow.transformers + +import assertk.assertThat +import assertk.assertions.isFalse +import assertk.assertions.isTrue +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +/** + * 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 : TransformerTestSupport() { + + init { + setupTurkishLocale() + } + + @BeforeEach + fun setup() { + transformer = ApacheLicenseResourceTransformer() + } + + @Test + fun testCanTransformResource() { + assertThat(transformer.canTransformResource(getFileElement("META-INF/LICENSE"))).isTrue() + assertThat(transformer.canTransformResource(getFileElement("META-INF/LICENSE.TXT"))).isTrue() + assertThat(transformer.canTransformResource(getFileElement("META-INF/License.txt"))).isTrue() + assertThat(transformer.canTransformResource(getFileElement("META-INF/LICENSE.md"))).isTrue() + assertThat(transformer.canTransformResource(getFileElement("META-INF/License.md"))).isTrue() + assertThat(transformer.canTransformResource(getFileElement("META-INF/MANIFEST.MF"))).isFalse() + } +} 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 new file mode 100644 index 000000000..b7da3fbb9 --- /dev/null +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformerTest.kt @@ -0,0 +1,85 @@ +package com.github.jengelman.gradle.plugins.shadow.transformers + +import assertk.assertThat +import assertk.assertions.isFalse +import assertk.assertions.isTrue +import assertk.fail +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +/** + * Modified from [org.apache.maven.plugins.shade.resource.ApacheNoticeResourceTransformerParameterTests.java](https://github.com/apache/maven-shade-plugin/blob/master/src/test/java/org/apache/maven/plugins/shade/resource/ApacheNoticeResourceTransformerParameterTests.java). + */ +class ApacheNoticeResourceTransformerTest : TransformerTestSupport() { + + init { + setupTurkishLocale() + } + + @BeforeEach + fun setup() { + transformer = ApacheNoticeResourceTransformer(objectFactory) + } + + @Test + fun testCanTransformResource() { + assertThat(transformer.canTransformResource(getFileElement("META-INF/NOTICE"))).isTrue() + assertThat(transformer.canTransformResource(getFileElement("META-INF/NOTICE.TXT"))).isTrue() + assertThat(transformer.canTransformResource(getFileElement("META-INF/Notice.txt"))).isTrue() + assertThat(transformer.canTransformResource(getFileElement("META-INF/NOTICE.md"))).isTrue() + assertThat(transformer.canTransformResource(getFileElement("META-INF/Notice.md"))).isTrue() + assertThat(transformer.canTransformResource(getFileElement("META-INF/MANIFEST.MF"))).isFalse() + } + + @Test + fun testNoParametersShouldNotThrowNullPointerWhenNoInput() { + processAndFailOnNullPointer("") + } + + @Test + fun testNoParametersShouldNotThrowNullPointerWhenNoLinesOfInput() { + processAndFailOnNullPointer("Some notice text") + } + + @Test + fun testNoParametersShouldNotThrowNullPointerWhenOneLineOfInput() { + processAndFailOnNullPointer("Some notice text\n") + } + + @Test + fun testNoParametersShouldNotThrowNullPointerWhenTwoLinesOfInput() { + processAndFailOnNullPointer("Some notice text\nSome notice text\n") + } + + @Test + fun testNoParametersShouldNotThrowNullPointerWhenLineStartsWithSlashSlash() { + processAndFailOnNullPointer("Some notice text\n//Some notice text\n") + } + + @Test + fun testNoParametersShouldNotThrowNullPointerWhenLineIsSlashSlash() { + processAndFailOnNullPointer("//\n") + } + + @Test + fun testNoParametersShouldNotThrowNullPointerWhenLineIsEmpty() { + processAndFailOnNullPointer("\n") + } + + private fun processAndFailOnNullPointer(noticeText: String) { + try { + transformer.transform( + TransformerContext.builder() + .path(NOTICE_RESOURCE) + .inputStream(noticeText.toByteArray().inputStream()) + .build(), + ) + } catch (ignored: NullPointerException) { + fail("Null pointer should not be thrown when no parameters are set.") + } + } + + companion object { + private const val NOTICE_RESOURCE = "META-INF/NOTICE" + } +} diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformerTest.kt new file mode 100644 index 000000000..997717220 --- /dev/null +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformerTest.kt @@ -0,0 +1,31 @@ +package com.github.jengelman.gradle.plugins.shadow.transformers + +import assertk.assertThat +import assertk.assertions.isFalse +import assertk.assertions.isTrue +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +/** + * Modified from [org.apache.maven.plugins.shade.resource.AppendingTransformerTest.java](https://github.com/apache/maven-shade-plugin/blob/master/src/test/java/org/apache/maven/plugins/shade/resource/AppendingTransformerTest.java). + */ +class AppendingTransformerTest : TransformerTestSupport() { + + init { + setupTurkishLocale() + } + + @BeforeEach + fun setup() { + transformer = AppendingTransformer(objectFactory) + } + + @Test + fun testCanTransformResource() { + transformer.resource.set("abcdefghijklmnopqrstuvwxyz") + + assertThat(transformer.canTransformResource(getFileElement("abcdefghijklmnopqrstuvwxyz"))).isTrue() + assertThat(transformer.canTransformResource(getFileElement("ABCDEFGHIJKLMNOPQRSTUVWXYZ"))).isTrue() + assertThat(transformer.canTransformResource(getFileElement("META-INF/MANIFEST.MF"))).isFalse() + } +} 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 new file mode 100644 index 000000000..9045a89b2 --- /dev/null +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformerTest.kt @@ -0,0 +1,41 @@ +package com.github.jengelman.gradle.plugins.shadow.transformers + +import assertk.assertThat +import assertk.assertions.isTrue +import org.custommonkey.xmlunit.XMLUnit +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +/** + * 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 : TransformerTestSupport() { + + @BeforeEach + fun setup() { + transformer = ComponentsXmlResourceTransformer() + } + + @Test + fun testConfigurationMerging() { + XMLUnit.setNormalizeWhitespace(true) + + transformer.transform( + TransformerContext.builder() + .path("components-1.xml") + .inputStream(requireResourceAsStream("components-1.xml")) + .build(), + ) + transformer.transform( + TransformerContext.builder() + .path("components-1.xml") + .inputStream(requireResourceAsStream("components-2.xml")) + .build(), + ) + val diff = XMLUnit.compareXML( + requireResourceAsStream("components-expected.xml").bufferedReader().readText(), + transformer.transformedResource.decodeToString(), + ) + assertThat(diff.identical()).isTrue() + } +} 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 new file mode 100644 index 000000000..4c5c21714 --- /dev/null +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestAppenderTransformerTest.kt @@ -0,0 +1,79 @@ +package com.github.jengelman.gradle.plugins.shadow.transformers + +import assertk.assertThat +import assertk.assertions.isEqualTo +import assertk.assertions.isFalse +import assertk.assertions.isGreaterThan +import assertk.assertions.isNotEmpty +import assertk.assertions.isTrue +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +class ManifestAppenderTransformerTest : TransformerTestSupport() { + @BeforeEach + fun setup() { + transformer = ManifestAppenderTransformer(objectFactory) + } + + @Test + fun testCanTransformResource() { + with(transformer) { + append("Name", "org/foo/bar/") + append("Sealed", true) + } + + assertThat(transformer.canTransformResource(getFileElement(MANIFEST_NAME))).isTrue() + assertThat(transformer.canTransformResource(getFileElement(MANIFEST_NAME.lowercase()))).isTrue() + } + + @Test + fun testHasTransformedResource() { + transformer.append("Tag", "Something") + + assertThat(transformer.hasTransformedResource()).isTrue() + } + + @Test + fun testHasNotTransformedResource() { + assertThat(transformer.hasTransformedResource()).isFalse() + } + + @Test + fun testTransformation() { + with(transformer) { + append("Name", "org/foo/bar/") + append("Sealed", true) + append("Name", "com/example/") + append("Sealed", false) + + transform(manifestTransformerContext) + } + + val testableZipPath = doTransformAndGetTransformedPath(transformer, true) + + val targetLines = readFrom(testableZipPath) + assertThat(targetLines).isNotEmpty() + assertThat(targetLines.size).isGreaterThan(4) + + val trailer = targetLines.subList(targetLines.size - 5, targetLines.size) + assertThat(trailer).isEqualTo( + listOf( + "Name: org/foo/bar/", + "Sealed: true", + "Name: com/example/", + "Sealed: false", + "", + ), + ) + } + + @Test + fun testNoTransformation() { + val sourceLines = requireResourceAsStream(MANIFEST_NAME).bufferedReader().readLines() + transformer.transform(manifestTransformerContext) + val testableZipPath = doTransformAndGetTransformedPath(transformer, true) + val targetLines = readFrom(testableZipPath) + + assertThat(targetLines).isEqualTo(sourceLines) + } +} 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 new file mode 100644 index 000000000..0b8af0815 --- /dev/null +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt @@ -0,0 +1,56 @@ +package com.github.jengelman.gradle.plugins.shadow.transformers + +import assertk.assertThat +import assertk.assertions.contains +import assertk.assertions.isEqualTo +import assertk.assertions.isFalse +import assertk.assertions.isNotEmpty +import assertk.assertions.isTrue +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +class PropertiesFileTransformerTest : TransformerTestSupport() { + + @BeforeEach + fun setup() { + transformer = PropertiesFileTransformer(objectFactory) + } + + @Test + fun testHasTransformedResource() { + transformer.transform(manifestTransformerContext) + + assertThat(transformer.hasTransformedResource()).isTrue() + } + + @Test + fun testHasNotTransformedResource() { + assertThat(transformer.hasTransformedResource()).isFalse() + } + + @Test + fun testTransformation() { + transformer.transform(manifestTransformerContext) + + val testableZipPath = doTransformAndGetTransformedPath(transformer, false) + val targetLines = readFrom(testableZipPath) + + assertThat(targetLines).isNotEmpty() + assertThat(targetLines).contains("Manifest-Version=1.0") + } + + @Test + fun testTransformationPropertiesAreReproducible() { + transformer.transform(manifestTransformerContext) + + val firstRunTransformedPath = doTransformAndGetTransformedPath(transformer, true) + val firstRunTargetLines = readFrom(firstRunTransformedPath) + + Thread.sleep(1000) // wait for 1sec to ensure timestamps in properties would change + + val secondRunTransformedPath = doTransformAndGetTransformedPath(transformer, true) + val secondRunTargetLines = readFrom(secondRunTransformedPath) + + assertThat(firstRunTargetLines).isEqualTo(secondRunTargetLines) + } +} diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerTestSupport.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerTestSupport.kt new file mode 100644 index 000000000..8fcd2d84d --- /dev/null +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerTestSupport.kt @@ -0,0 +1,59 @@ +package com.github.jengelman.gradle.plugins.shadow.transformers + +import java.io.InputStream +import java.nio.file.Path +import java.util.Locale +import java.util.zip.ZipFile +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.gradle.api.internal.file.DefaultFileTreeElement +import org.gradle.testfixtures.ProjectBuilder + +abstract class TransformerTestSupport { + protected lateinit var transformer: T + + protected val manifestTransformerContext: TransformerContext + get() = TransformerContext(MANIFEST_NAME, requireResourceAsStream(MANIFEST_NAME)) + + protected fun requireResourceAsStream(name: String): InputStream { + return this::class.java.classLoader.getResourceAsStream(name) ?: error("Resource $name not found.") + } + + protected companion object { + const val MANIFEST_NAME: String = "META-INF/MANIFEST.MF" + val objectFactory = ProjectBuilder.builder().build().objects + + fun getFileElement(path: String): FileTreeElement { + return DefaultFileTreeElement(null, RelativePath.parse(true, path), null, null) + } + + fun readFrom(jarPath: Path, resourceName: String = MANIFEST_NAME): List { + return ZipFile(jarPath.toFile()).use { zip -> + val entry = zip.getEntry(resourceName) ?: return emptyList() + zip.getInputStream(entry).bufferedReader().readLines() + } + } + + fun doTransformAndGetTransformedPath( + transformer: Transformer, + preserveFileTimestamps: Boolean, + ): Path { + val testableZipPath = createTempFile("testable-zip-file-", ".jar") + ZipOutputStream(testableZipPath.outputStream().buffered()).use { zipOutputStream -> + transformer.modifyOutputStream(zipOutputStream, preserveFileTimestamps) + } + return testableZipPath + } + + /** + * NOTE: The Turkish locale has an usual case transformation for the letters "I" and "i", making it a prime + * choice to test for improper case-less string comparisons. + */ + fun setupTurkishLocale() { + Locale.setDefault(Locale("tr")) + } + } +} 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 new file mode 100644 index 000000000..5bb4b85f4 --- /dev/null +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformerTest.kt @@ -0,0 +1,28 @@ +package com.github.jengelman.gradle.plugins.shadow.transformers + +import assertk.assertThat +import assertk.assertions.isFalse +import assertk.assertions.isTrue +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +class XmlAppendingTransformerTest : TransformerTestSupport() { + + init { + setupTurkishLocale() + } + + @BeforeEach + fun setup() { + transformer = XmlAppendingTransformer(objectFactory) + } + + @Test + fun testCanTransformResource() { + transformer.resource.set("abcdefghijklmnopqrstuvwxyz") + + assertThat(transformer.canTransformResource(getFileElement("abcdefghijklmnopqrstuvwxyz"))).isTrue() + assertThat(transformer.canTransformResource(getFileElement("ABCDEFGHIJKLMNOPQRSTUVWXYZ"))).isTrue() + assertThat(transformer.canTransformResource(getFileElement("META-INF/MANIFEST.MF"))).isFalse() + } +}