DefaultPluginXmlFactoryTest.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.impl;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import com.ctc.wstx.exc.WstxEOFException;
import org.apache.maven.api.plugin.descriptor.PluginDescriptor;
import org.apache.maven.api.services.xml.ModelXmlFactory;
import org.apache.maven.api.services.xml.XmlReaderException;
import org.apache.maven.api.services.xml.XmlReaderRequest;
import org.apache.maven.api.services.xml.XmlWriterException;
import org.apache.maven.api.services.xml.XmlWriterRequest;
import org.apache.maven.impl.model.DefaultModelProcessor;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import static java.util.UUID.randomUUID;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
class DefaultPluginXmlFactoryTest {
private static final String NAME = "sample-plugin-" + randomUUID();
private static final String SAMPLE_PLUGIN_XML =
"""
<?xml version="1.0" encoding="UTF-8"?>
<plugin>
<name>%s</name>
<groupId>org.example</groupId>
<artifactId>sample-plugin</artifactId>
<version>1.0.0</version>
</plugin>
"""
.formatted(NAME);
private final DefaultPluginXmlFactory defaultPluginXmlFactory = new DefaultPluginXmlFactory();
@TempDir
Path tempDir;
@Test
void readFromInputStreamParsesPluginDescriptorCorrectly() {
PluginDescriptor descriptor = defaultPluginXmlFactory.read(XmlReaderRequest.builder()
.inputStream(new ByteArrayInputStream(SAMPLE_PLUGIN_XML.getBytes()))
.build());
assertEquals(NAME, descriptor.getName());
assertEquals("org.example", descriptor.getGroupId());
assertEquals("sample-plugin", descriptor.getArtifactId());
assertEquals("1.0.0", descriptor.getVersion());
}
@Test
void parsePlugin() {
String actualName = defaultPluginXmlFactory
.read(XmlReaderRequest.builder()
.reader(new StringReader(SAMPLE_PLUGIN_XML))
.build())
.getName();
assertEquals(NAME, actualName, "Expected plugin name to be " + NAME + " but was " + actualName);
}
@Test
void readFromPathParsesPluginDescriptorCorrectly() throws Exception {
Path xmlFile = tempDir.resolve("plugin.xml");
Files.write(xmlFile, SAMPLE_PLUGIN_XML.getBytes());
String actualName = defaultPluginXmlFactory
.read(XmlReaderRequest.builder().path(xmlFile).build())
.getName();
assertEquals(NAME, actualName, "Expected plugin name to be " + NAME + " but was " + actualName);
}
@Test
void readWithNoInputThrowsIllegalArgumentException() {
assertThrows(
IllegalArgumentException.class,
() -> defaultPluginXmlFactory.read(XmlReaderRequest.builder().build()));
}
@Test
void writeToWriterGeneratesValidXml() {
StringWriter writer = new StringWriter();
defaultPluginXmlFactory.write(XmlWriterRequest.<PluginDescriptor>builder()
.writer(writer)
.content(PluginDescriptor.newBuilder()
.name(NAME)
.groupId("org.example")
.artifactId("sample-plugin")
.version("1.0.0")
.build())
.build());
String output = writer.toString();
assertTrue(
output.contains("<name>" + NAME + "</name>"),
"Expected " + output + " to contain " + "<name>" + NAME + "</name>");
assertTrue(
output.contains("<groupId>org.example</groupId>"),
"Expected " + output + " to contain " + "<groupId>org.example</groupId>");
}
@Test
void writeToOutputStreamGeneratesValidXml() {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
defaultPluginXmlFactory.write(XmlWriterRequest.<PluginDescriptor>builder()
.outputStream(outputStream)
.content(PluginDescriptor.newBuilder().name(NAME).build())
.build());
String output = outputStream.toString();
assertTrue(
output.contains("<name>" + NAME + "</name>"),
"Expected output to contain <name>" + NAME + "</name> but was: " + output);
}
@Test
void writeToPathGeneratesValidXmlFile() throws Exception {
Path xmlFile = tempDir.resolve("output-plugin.xml");
defaultPluginXmlFactory.write(XmlWriterRequest.<PluginDescriptor>builder()
.path(xmlFile)
.content(PluginDescriptor.newBuilder().name(NAME).build())
.build());
String fileContent = Files.readString(xmlFile);
assertTrue(
fileContent.contains("<name>" + NAME + "</name>"),
"Expected file content to contain <name>" + NAME + "</name> but was: " + fileContent);
}
@Test
void fromXmlStringParsesValidXml() {
PluginDescriptor descriptor = defaultPluginXmlFactory.fromXmlString(SAMPLE_PLUGIN_XML);
assertEquals(
NAME,
descriptor.getName(),
"Expected descriptor name to be " + NAME + " but was " + descriptor.getName());
assertEquals(
"org.example",
descriptor.getGroupId(),
"Expected descriptor groupId to be org.example but was " + descriptor.getGroupId());
assertEquals(
"sample-plugin",
descriptor.getArtifactId(),
"Expected descriptor artifactId to be sample-plugin but was " + descriptor.getArtifactId());
assertEquals(
"1.0.0",
descriptor.getVersion(),
"Expected descriptor version to be 1.0.0 but was " + descriptor.getVersion());
}
@Test
void toXmlStringGeneratesValidXml() {
String xml = defaultPluginXmlFactory.toXmlString(PluginDescriptor.newBuilder()
.name(NAME)
.groupId("org.example")
.artifactId("sample-plugin")
.version("1.0.0")
.build());
assertTrue(
xml.contains("<name>" + NAME + "</name>"),
"Expected " + xml + " to contain " + "<name>" + NAME + "</name>");
assertTrue(
xml.contains("<groupId>org.example</groupId>"),
"Expected " + xml + " to contain " + "<groupId>org.example</groupId>");
assertTrue(
xml.contains("<artifactId>sample-plugin</artifactId>"),
"Expected " + xml + " to contain " + "<artifactId>sample-plugin</artifactId>");
assertTrue(
xml.contains("<version>1.0.0</version>"),
"Expected " + xml + " to contain " + "<version>1.0.0</version>");
}
@Test
void staticFromXmlParsesValidXml() {
PluginDescriptor descriptor = DefaultPluginXmlFactory.fromXml(SAMPLE_PLUGIN_XML);
assertEquals(
NAME,
descriptor.getName(),
"Expected descriptor name to be " + NAME + " but was " + descriptor.getName());
assertEquals(
"org.example",
descriptor.getGroupId(),
"Expected descriptor groupId to be org.example but was " + descriptor.getGroupId());
assertEquals(
"sample-plugin",
descriptor.getArtifactId(),
"Expected descriptor artifactId to be sample-plugin but was " + descriptor.getArtifactId());
assertEquals(
"1.0.0",
descriptor.getVersion(),
"Expected descriptor version to be 1.0.0 but was " + descriptor.getVersion());
}
@Test
void staticToXmlGeneratesValidXml() {
String xml = DefaultPluginXmlFactory.toXml(PluginDescriptor.newBuilder()
.name(NAME)
.groupId("org.example")
.artifactId("sample-plugin")
.version("1.0.0")
.build());
assertTrue(
xml.contains("<name>" + NAME + "</name>"),
"Expected " + xml + " to contain " + "<name>" + NAME + "</name>");
assertTrue(
xml.contains("<name>" + NAME + "</name>"),
"Expected " + xml + " to contain " + "<name>" + NAME + "</name>");
assertTrue(
xml.contains("<groupId>org.example</groupId>"),
"Expected " + xml + " to contain " + "<groupId>org.example</groupId>");
assertTrue(
xml.contains("<artifactId>sample-plugin</artifactId>"),
"Expected " + xml + " to contain " + "<artifactId>sample-plugin</artifactId>");
assertTrue(
xml.contains("<version>1.0.0</version>"),
"Expected " + xml + " to contain " + "<version>1.0.0</version>");
}
@Test
void writeWithFailingWriterThrowsXmlWriterException() {
String unableToWritePlugin = "Unable to write plugin" + randomUUID();
String ioEx = "ioEx" + randomUUID();
XmlWriterException exception = assertThrows(
XmlWriterException.class,
() -> defaultPluginXmlFactory.write(XmlWriterRequest.<PluginDescriptor>builder()
.writer(new Writer() {
@Override
public void write(char[] cbuf, int off, int len) {
throw new XmlWriterException(unableToWritePlugin, null, new IOException(ioEx));
}
@Override
public void flush() {}
@Override
public void close() {}
})
.content(PluginDescriptor.newBuilder()
.name("Failing Plugin")
.build())
.build()));
assertTrue(exception.getMessage().contains(unableToWritePlugin));
assertInstanceOf(XmlWriterException.class, exception.getCause());
assertEquals(ioEx, exception.getCause().getCause().getMessage());
assertEquals(unableToWritePlugin, exception.getCause().getMessage());
}
@Test
void writeWithNoTargetThrowsIllegalArgumentException() {
IllegalArgumentException exception = assertThrows(
IllegalArgumentException.class,
() -> defaultPluginXmlFactory.write(XmlWriterRequest.<PluginDescriptor>builder()
.content(PluginDescriptor.newBuilder()
.name("No Output Plugin")
.build())
.build()));
assertEquals(
"writer, outputStream or path must be non null",
exception.getMessage(),
"Expected specific error message but was: " + exception.getMessage());
}
@Test
void readMalformedXmlThrowsXmlReaderException() {
XmlReaderException exception = assertThrows(
XmlReaderException.class,
() -> defaultPluginXmlFactory.read(XmlReaderRequest.builder()
.inputStream(new ByteArrayInputStream("<plugin><name>Broken Plugin".getBytes()))
.build()));
assertTrue(exception.getMessage().contains("Unable to read plugin"));
assertInstanceOf(WstxEOFException.class, exception.getCause());
}
@Test
void locateExistingPomWithFilePathShouldReturnSameFileIfRegularFile() throws IOException {
Path pomFile = Files.createTempFile(tempDir, "pom", ".xml");
DefaultModelProcessor processor = new DefaultModelProcessor(mock(ModelXmlFactory.class), List.of());
assertEquals(
pomFile, processor.locateExistingPom(pomFile), "Expected locateExistingPom to return the same file");
}
@Test
void readFromUrlParsesPluginDescriptorCorrectly() throws Exception {
Path xmlFile = tempDir.resolve("plugin.xml");
Files.write(xmlFile, SAMPLE_PLUGIN_XML.getBytes());
PluginDescriptor descriptor;
try (InputStream inputStream = xmlFile.toUri().toURL().openStream()) {
descriptor = defaultPluginXmlFactory.read(
XmlReaderRequest.builder().inputStream(inputStream).build());
}
assertEquals(
NAME,
descriptor.getName(),
"Expected descriptor name to be " + NAME + " but was " + descriptor.getName());
assertEquals(
"org.example",
descriptor.getGroupId(),
"Expected descriptor groupId to be org.example but was " + descriptor.getGroupId());
assertEquals(
"sample-plugin",
descriptor.getArtifactId(),
"Expected descriptor artifactId to be sample-plugin but was " + descriptor.getArtifactId());
assertEquals(
"1.0.0",
descriptor.getVersion(),
"Expected descriptor version to be 1.0.0 but was " + descriptor.getVersion());
}
@Test
void testReadWithPath() throws Exception {
Path tempPath = Files.createTempFile("plugin", ".xml");
Files.writeString(tempPath, "<plugin/>");
XmlReaderRequest request = mock(XmlReaderRequest.class);
when(request.getPath()).thenReturn(tempPath);
when(request.getInputStream()).thenReturn(null);
when(request.getReader()).thenReturn(null);
when(request.getURL()).thenReturn(null);
when(request.isAddDefaultEntities()).thenReturn(false);
when(request.isStrict()).thenReturn(false);
assertNotNull(new DefaultPluginXmlFactory().read(request));
Files.deleteIfExists(tempPath);
}
@Test
void testReadWithPathUrlDefault() throws Exception {
Path tempPath = Files.createTempFile("plugin", ".xml");
Files.writeString(tempPath, "<plugin/>");
XmlReaderRequest request = mock(XmlReaderRequest.class);
when(request.getPath()).thenReturn(null);
when(request.getInputStream()).thenReturn(null);
when(request.getReader()).thenReturn(null);
when(request.getURL()).thenReturn(tempPath.toUri().toURL());
when(request.isAddDefaultEntities()).thenReturn(false);
when(request.isStrict()).thenReturn(false);
assertNotNull(new DefaultPluginXmlFactory().read(request));
Files.deleteIfExists(tempPath);
}
}