ModuleNameFixStrategyTest.java
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.cling.invoker.mvnup.goals;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import eu.maveniverse.domtrip.Document;
import org.apache.maven.cling.invoker.mvnup.UpgradeContext;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Unit tests for the {@link ModuleNameFixStrategy} class.
*/
@DisplayName("ModuleNameFixStrategy")
class ModuleNameFixStrategyTest {
private static final Path POM_PATH = Paths.get("/project/pom.xml");
@Nested
@DisplayName("sanitizeModuleName")
class SanitizeTests {
@Test
@DisplayName("should replace dashes with dots")
void replacesDashes() {
assertEquals(
"org.apache.geronimo.arthur.integration.test",
ModuleNameFixStrategy.sanitizeModuleName("org.apache.geronimo.arthur.integration-test"));
}
@Test
@DisplayName("should replace multiple dashes")
void replacesMultipleDashes() {
assertEquals(
"org.apache.winegrower.cepages.winegrower.cepage.osgi.cdi",
ModuleNameFixStrategy.sanitizeModuleName(
"org.apache.winegrower.cepages.winegrower-cepage-osgi-cdi"));
}
@Test
@DisplayName("should collapse consecutive dots")
void collapsesConsecutiveDots() {
assertEquals("foo.bar", ModuleNameFixStrategy.sanitizeModuleName("foo--bar"));
}
@Test
@DisplayName("should leave valid names unchanged")
void leavesValidUnchanged() {
assertEquals("org.example.valid.name", ModuleNameFixStrategy.sanitizeModuleName("org.example.valid.name"));
}
@Test
@DisplayName("should handle leading dash")
void handlesLeadingDash() {
assertEquals("foo.bar", ModuleNameFixStrategy.sanitizeModuleName("-foo.bar"));
}
@Test
@DisplayName("should handle trailing dash")
void handlesTrailingDash() {
assertEquals("foo.bar", ModuleNameFixStrategy.sanitizeModuleName("foo.bar-"));
}
}
@Nested
@DisplayName("Apply")
class ApplyTests {
@Test
@DisplayName("should fix Automatic-Module-Name with dashes in jar plugin config")
void fixesDashInJarPlugin() {
ModuleNameFixStrategy strategy = new ModuleNameFixStrategy();
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>integration-test</artifactId>
<version>1.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Automatic-Module-Name>org.example.integration-test</Automatic-Module-Name>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
""";
Document doc = Document.of(pomXml);
UpgradeContext context = TestUtils.createMockContext();
UpgradeResult result = strategy.doApply(context, Map.of(POM_PATH, doc));
assertEquals(1, result.modifiedPoms().size());
// Verify the fix was applied
String xml = doc.toXml();
assertTrue(xml.contains("org.example.integration.test"));
assertFalse(xml.contains("org.example.integration-test"));
}
@Test
@DisplayName("should not modify valid Automatic-Module-Name")
void noChangeForValid() {
ModuleNameFixStrategy strategy = new ModuleNameFixStrategy();
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>my-module</artifactId>
<version>1.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Automatic-Module-Name>org.example.mymodule</Automatic-Module-Name>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
""";
Document doc = Document.of(pomXml);
UpgradeContext context = TestUtils.createMockContext();
UpgradeResult result = strategy.doApply(context, Map.of(POM_PATH, doc));
assertEquals(0, result.modifiedPoms().size());
}
@Test
@DisplayName("should fix in pluginManagement section")
void fixesInPluginManagement() {
ModuleNameFixStrategy strategy = new ModuleNameFixStrategy();
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>test</artifactId>
<version>1.0</version>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Automatic-Module-Name>org.example.my-lib</Automatic-Module-Name>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
""";
Document doc = Document.of(pomXml);
UpgradeContext context = TestUtils.createMockContext();
UpgradeResult result = strategy.doApply(context, Map.of(POM_PATH, doc));
assertEquals(1, result.modifiedPoms().size());
assertTrue(doc.toXml().contains("org.example.my.lib"));
}
@Test
@DisplayName("should handle POM without any plugins")
void noPlugins() {
ModuleNameFixStrategy strategy = new ModuleNameFixStrategy();
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>test</artifactId>
<version>1.0</version>
</project>
""";
Document doc = Document.of(pomXml);
UpgradeContext context = TestUtils.createMockContext();
UpgradeResult result = strategy.doApply(context, Map.of(POM_PATH, doc));
assertEquals(0, result.modifiedPoms().size());
}
@Test
@DisplayName("should fix in shade plugin configuration")
void fixesInShadePlugin() {
ModuleNameFixStrategy strategy = new ModuleNameFixStrategy();
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>test</artifactId>
<version>1.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Automatic-Module-Name>org.example.shaded-lib</Automatic-Module-Name>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
""";
Document doc = Document.of(pomXml);
UpgradeContext context = TestUtils.createMockContext();
UpgradeResult result = strategy.doApply(context, Map.of(POM_PATH, doc));
assertEquals(1, result.modifiedPoms().size());
assertTrue(doc.toXml().contains("org.example.shaded.lib"));
}
@Test
@DisplayName("should ignore non-packaging plugins")
void ignoresNonPackagingPlugins() {
ModuleNameFixStrategy strategy = new ModuleNameFixStrategy();
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>test</artifactId>
<version>1.0</version>
<build>
<plugins>
<plugin>
<groupId>com.example</groupId>
<artifactId>custom-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Automatic-Module-Name>org.example.my-lib</Automatic-Module-Name>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
""";
Document doc = Document.of(pomXml);
UpgradeContext context = TestUtils.createMockContext();
UpgradeResult result = strategy.doApply(context, Map.of(POM_PATH, doc));
assertEquals(0, result.modifiedPoms().size());
}
@Test
@DisplayName("should fix in profile plugin configuration")
void fixesInProfile() {
ModuleNameFixStrategy strategy = new ModuleNameFixStrategy();
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>test</artifactId>
<version>1.0</version>
<profiles>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Automatic-Module-Name>org.example.my-release</Automatic-Module-Name>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
""";
Document doc = Document.of(pomXml);
UpgradeContext context = TestUtils.createMockContext();
UpgradeResult result = strategy.doApply(context, Map.of(POM_PATH, doc));
assertEquals(1, result.modifiedPoms().size());
assertTrue(doc.toXml().contains("org.example.my.release"));
}
@Test
@DisplayName("should skip property references")
void skipsPropertyReferences() {
ModuleNameFixStrategy strategy = new ModuleNameFixStrategy();
// geronimo-arthur uses ${project.groupId}.${geronimo-arthur.shortname}
// which resolves to a hyphenated name ��� but we can't fix property references
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>test</artifactId>
<version>1.0</version>
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Automatic-Module-Name>${project.groupId}.${project.artifactId}</Automatic-Module-Name>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
""";
Document doc = Document.of(pomXml);
UpgradeContext context = TestUtils.createMockContext();
UpgradeResult result = strategy.doApply(context, Map.of(POM_PATH, doc));
// Should not modify ��� cannot resolve property expressions
assertEquals(0, result.modifiedPoms().size());
}
@Test
@DisplayName("should fix multiple dashes like winegrower-cepage-osgi-cdi")
void fixesMultipleDashes() {
ModuleNameFixStrategy strategy = new ModuleNameFixStrategy();
String pomXml = """
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.winegrower.cepages</groupId>
<artifactId>test</artifactId>
<version>1.0</version>
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Automatic-Module-Name>org.apache.winegrower.cepages.winegrower-cepage-osgi-cdi</Automatic-Module-Name>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
""";
Document doc = Document.of(pomXml);
UpgradeContext context = TestUtils.createMockContext();
UpgradeResult result = strategy.doApply(context, Map.of(POM_PATH, doc));
assertEquals(1, result.modifiedPoms().size());
String xml = doc.toXml();
assertTrue(xml.contains("org.apache.winegrower.cepages.winegrower.cepage.osgi.cdi"));
}
}
}