diff --git a/datamodel/odata-v4/odata-v4-generator-maven-plugin/pom.xml b/datamodel/odata-v4/odata-v4-generator-maven-plugin/pom.xml index c390df027..e99499334 100644 --- a/datamodel/odata-v4/odata-v4-generator-maven-plugin/pom.xml +++ b/datamodel/odata-v4/odata-v4-generator-maven-plugin/pom.xml @@ -50,6 +50,11 @@ com.sap.cloud.sdk.datamodel odata-generator-utility + + com.google.guava + guava + + org.apache.maven maven-core @@ -60,7 +65,6 @@ maven-plugin-api provided - org.apache.maven.plugin-tools maven-plugin-annotations @@ -68,8 +72,8 @@ - junit - junit + org.junit.jupiter + junit-jupiter-api test @@ -78,19 +82,11 @@ test - org.apache.maven.plugin-testing - maven-plugin-testing-harness - test - - - org.apache.maven - maven-compat + com.sap.cloud.sdk.testutil + testutil-maven-plugin + 5.0.0-alpha-SNAPSHOT test - - com.google.guava - guava - @@ -115,16 +111,6 @@ odata-v4-generator - - org.apache.maven.plugins - maven-dependency-plugin - - - - org.apache.maven:maven-compat - - - diff --git a/datamodel/odata-v4/odata-v4-generator-maven-plugin/src/test/java/com/sap/cloud/sdk/datamodel/odatav4/generator/DataModelGeneratorMojoTest.java b/datamodel/odata-v4/odata-v4-generator-maven-plugin/src/test/java/com/sap/cloud/sdk/datamodel/odatav4/generator/DataModelGeneratorMojoTest.java index 32616d4df..e6757b6fe 100644 --- a/datamodel/odata-v4/odata-v4-generator-maven-plugin/src/test/java/com/sap/cloud/sdk/datamodel/odatav4/generator/DataModelGeneratorMojoTest.java +++ b/datamodel/odata-v4/odata-v4-generator-maven-plugin/src/test/java/com/sap/cloud/sdk/datamodel/odatav4/generator/DataModelGeneratorMojoTest.java @@ -4,35 +4,27 @@ package com.sap.cloud.sdk.datamodel.odatav4.generator; -import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.SoftAssertions.assertSoftly; -import java.io.File; -import java.net.URL; - -import org.apache.maven.plugin.testing.MojoRule; -import org.junit.Rule; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import com.sap.cloud.sdk.datamodel.odata.utility.NameSource; import com.sap.cloud.sdk.datamodel.odata.utility.S4HanaNamingStrategy; import com.sap.cloud.sdk.datamodel.odatav4.generator.annotation.DefaultAnnotationStrategy; +import com.sap.cloud.sdk.testutil.MavenPluginExtension; public class DataModelGeneratorMojoTest { - @Rule - public MojoRule rule = new MojoRule(); + @RegisterExtension + static MavenPluginExtension extension = + new MavenPluginExtension().withClass(DataModelGeneratorMojoTest.class).withGoal("generate"); + //void testMe( @MojoForGoal("generate") final DataModelGeneratorMojo mojo ) @Test - public void test() - throws Exception + void testMe() { - final URL resource = getClass().getClassLoader().getResource(getClass().getSimpleName()); - assertThat(resource).isNotNull(); - - final File pomFile = new File(resource.getFile()); - - final DataModelGeneratorMojo mojo = (DataModelGeneratorMojo) rule.lookupConfiguredMojo(pomFile, "generate"); + final DataModelGeneratorMojo mojo = extension.getMojo(); final DataModelGenerator generator = mojo.getDataModelGenerator(); assertSoftly(softly -> { diff --git a/testutil/pom.xml b/testutil/pom.xml index c7e3eae84..cc69c1a49 100644 --- a/testutil/pom.xml +++ b/testutil/pom.xml @@ -32,6 +32,7 @@ testutil-core + testutil-maven-plugin diff --git a/testutil/testutil-maven-plugin/.gitignore b/testutil/testutil-maven-plugin/.gitignore new file mode 100644 index 000000000..ba3989521 --- /dev/null +++ b/testutil/testutil-maven-plugin/.gitignore @@ -0,0 +1,5 @@ +/target/ +/.settings/ +/.project +/src/main/generated +/.classpath diff --git a/testutil/testutil-maven-plugin/pom.xml b/testutil/testutil-maven-plugin/pom.xml new file mode 100644 index 000000000..a2a74a0c9 --- /dev/null +++ b/testutil/testutil-maven-plugin/pom.xml @@ -0,0 +1,141 @@ + + + 4.0.0 + + com.sap.cloud.sdk.testutil + testutil-parent + 5.0.0-alpha-SNAPSHOT + + testutil-maven-plugin + Test Utilities - Maven Plugin + Convenience utilities for testing. + https://sap.github.io/cloud-sdk/docs/java/getting-started + + SAP SE + https://www.sap.com + + + + The Apache Software License, Version 2.0 + https://www.apache.org/licenses/LICENSE-2.0.txt + + + + + SAP + cloudsdk@sap.com + SAP SE + https://www.sap.com + + + + + + + + None + Stable + true + true + false + + true + + + + org.codehaus.plexus + plexus-utils + 3.2.1 + compile + + + org.codehaus.plexus + plexus-classworlds + 2.6.0 + compile + + + org.eclipse.sisu + org.eclipse.sisu.plexus + 0.3.4 + compile + + + plexus-classworlds + org.codehaus.plexus + + + plexus-utils + org.codehaus.plexus + + + + + org.apache.maven.resolver + maven-resolver-api + 1.6.2 + compile + + + org.junit.jupiter + junit-jupiter-api + ${junit.jupiter.version} + compile + + + org.apache.maven + maven-plugin-api + ${maven-plugin.version} + compile + + + org.apache.maven + maven-artifact + ${maven-plugin.version} + compile + + + org.apache.maven + maven-core + ${maven-plugin.version} + compile + + + plexus-utils + org.codehaus.plexus + + + + + org.apache.maven + maven-resolver-provider + ${maven-plugin.version} + compile + + + org.apache.maven + maven-model + ${maven-plugin.version} + compile + + + commons-io + commons-io + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + -Xlint:-cast + + + + + + diff --git a/testutil/testutil-maven-plugin/src/main/java/com/sap/cloud/sdk/testutil/MavenPluginExtension.java b/testutil/testutil-maven-plugin/src/main/java/com/sap/cloud/sdk/testutil/MavenPluginExtension.java new file mode 100644 index 000000000..22cbaf68a --- /dev/null +++ b/testutil/testutil-maven-plugin/src/main/java/com/sap/cloud/sdk/testutil/MavenPluginExtension.java @@ -0,0 +1,210 @@ +package com.sap.cloud.sdk.testutil; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.Collections; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.apache.commons.io.input.XmlStreamReader; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.execution.DefaultMavenExecutionRequest; +import org.apache.maven.execution.DefaultMavenExecutionResult; +import org.apache.maven.execution.MavenExecutionRequest; +import org.apache.maven.execution.MavenExecutionResult; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.lifecycle.internal.MojoDescriptorCreator; +import org.apache.maven.model.Plugin; +import org.apache.maven.plugin.Mojo; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.PluginParameterExpressionEvaluator; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.ProjectBuilder; +import org.apache.maven.project.ProjectBuildingRequest; +import org.apache.maven.repository.RepositorySystem; +import org.apache.maven.repository.internal.MavenRepositorySystemUtils; +import org.codehaus.plexus.ContainerConfiguration; +import org.codehaus.plexus.DefaultContainerConfiguration; +import org.codehaus.plexus.DefaultPlexusContainer; +import org.codehaus.plexus.PlexusConstants; +import org.codehaus.plexus.classworlds.ClassWorld; +import org.codehaus.plexus.component.configurator.ComponentConfigurator; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; +import org.codehaus.plexus.component.repository.exception.ComponentLookupException; +import org.codehaus.plexus.configuration.PlexusConfiguration; +import org.codehaus.plexus.configuration.PlexusConfigurationException; +import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration; +import org.codehaus.plexus.util.InterpolationFilterReader; +import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.eclipse.aether.DefaultRepositorySystemSession; +import org.junit.jupiter.api.extension.AfterAllCallback; +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.BeforeAllCallback; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; + +public class MavenPluginExtension implements BeforeAllCallback, AfterEachCallback, BeforeEachCallback, AfterAllCallback +{ + private ComponentConfigurator configurator; + private DefaultPlexusContainer container; + private Map goals; + private String goal; + private File baseDir; + private Mojo mojo; + private Class baseClass; + + public MavenPluginExtension withGoal( final String goal ) + { + this.goal = goal; + return this; + } + + public MavenPluginExtension withBasePath( final File basePath ) + { + this.baseDir = basePath; + return this; + } + + public MavenPluginExtension withClass( final Class baseClass ) + { + this.baseClass = baseClass; + this.baseDir = new File(baseClass.getClassLoader().getResource(baseClass.getSimpleName()).getFile()); + return this; + } + + private Map loadGoals() + throws ComponentLookupException, + IOException, + PlexusConfigurationException + { + final String pluginDescriptorLocation = "/META-INF/maven/plugin.xml"; + final URL resource = baseClass.getResource(pluginDescriptorLocation); + final String path = Objects.requireNonNull(resource, "plugin.xml file not found.").getPath(); + final File artifactFile = new File(path.substring(0, path.length() - pluginDescriptorLocation.length())); + + final XmlStreamReader reader = XmlStreamReader.builder().setInputStream(resource.openStream()).get(); + + final Map contextData = + container + .getContext() + .getContextData() + .entrySet() + .stream() + .collect(Collectors.toMap(Object::toString, Function.identity())); + try( + final InterpolationFilterReader interpolationFilterReader = + new InterpolationFilterReader(new BufferedReader(reader), contextData) ) { + + final PluginDescriptor pluginDescriptor = new PluginDescriptorBuilder().build(interpolationFilterReader); + + final Artifact artifact = + container + .lookup(RepositorySystem.class) + .createArtifact( + pluginDescriptor.getGroupId(), + pluginDescriptor.getArtifactId(), + pluginDescriptor.getVersion(), + ".jar"); + artifact.setFile(artifactFile); + pluginDescriptor.setPluginArtifact(artifact); + pluginDescriptor.setArtifacts(Collections.singletonList(artifact)); + pluginDescriptor.getComponents().forEach(container::addComponentDescriptor); + return pluginDescriptor + .getMojos() + .stream() + .collect(Collectors.toMap(MojoDescriptor::getGoal, Function.identity())); + } + } + + private ContainerConfiguration getContainerConfiguration() + { + return new DefaultContainerConfiguration() + .setClassWorld(new ClassWorld("plexus.core", Thread.currentThread().getContextClassLoader())) + .setClassPathScanning(PlexusConstants.SCANNING_INDEX) + .setAutoWiring(true) + .setName("maven"); + } + + @Override + public void afterEach( final ExtensionContext extensionContext ) + { + mojo = null; + } + + @SuppressWarnings( "deprecation" ) + @Override + public void beforeEach( final ExtensionContext extensionContext ) + throws Exception + { + final String role = "org.apache.maven.plugin.Mojo"; + final MojoDescriptor descriptor = goals.get(goal); + this.mojo = (Mojo) container.lookup(role, descriptor.getRoleHint()); + + // project + final File pom = new File(baseDir, "pom.xml"); + final MavenExecutionRequest request = new DefaultMavenExecutionRequest().setBaseDirectory(baseDir); + final DefaultRepositorySystemSession repoSession = new DefaultRepositorySystemSession(); + final ProjectBuildingRequest conf = request.getProjectBuildingRequest().setRepositorySession(repoSession); + final MavenProject project = container.lookup(ProjectBuilder.class).build(pom, conf).getProject(); + + // session + final MavenExecutionResult res = new DefaultMavenExecutionResult(); + final MavenSession session = new MavenSession(container, MavenRepositorySystemUtils.newSession(), request, res); + session.setCurrentProject(project); + session.setProjects(Collections.singletonList(project)); + + // execution + final MojoExecution execution = new MojoExecution(descriptor); + final Xpp3Dom executionConfiguration = new Xpp3Dom("configuration"); + final Xpp3Dom defaultConfiguration = MojoDescriptorCreator.convert(descriptor); + final Xpp3Dom finalConfiguration = new Xpp3Dom("configuration"); + if( descriptor.getParameters() != null ) { + for( final Parameter parameter : descriptor.getParameters() ) { + Xpp3Dom parameterConfiguration = executionConfiguration.getChild(parameter.getAlias()); + final Xpp3Dom parameterDefaults = defaultConfiguration.getChild(parameter.getName()); + parameterConfiguration = Xpp3Dom.mergeXpp3Dom(parameterConfiguration, parameterDefaults, Boolean.TRUE); + finalConfiguration.addChild(new Xpp3Dom(parameterConfiguration, parameter.getName())); + } + } + execution.setConfiguration(finalConfiguration); + + // evaluation + final ExpressionEvaluator evaluator = new PluginParameterExpressionEvaluator(session, execution); + final Plugin pl = session.getCurrentProject().getPlugin(descriptor.getPluginDescriptor().getPluginLookupKey()); + final Xpp3Dom confXml = Xpp3Dom.mergeXpp3Dom((Xpp3Dom) pl.getConfiguration(), execution.getConfiguration()); + final PlexusConfiguration pluginConfiguration = new XmlPlexusConfiguration(confXml); + configurator.configureComponent(mojo, pluginConfiguration, evaluator, container.getContainerRealm()); + } + + @SuppressWarnings( "unchecked" ) + public T getMojo() + { + return (T) mojo; + } + + @Override + public void afterAll( final ExtensionContext extensionContext ) + { + container.dispose(); + container = null; + configurator = null; + goals = null; + } + + @Override + public void beforeAll( final ExtensionContext extensionContext ) + throws Exception + { + container = new DefaultPlexusContainer(getContainerConfiguration()); + configurator = container.lookup(ComponentConfigurator.class, "basic"); + goals = loadGoals(); + } +}