| package org.apache.maven.shared.release.phase; |
| |
| |
| /* |
| * 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. |
| */ |
| |
| import static org.junit.Assert.assertFalse; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.nio.file.FileVisitResult; |
| import java.nio.file.Files; |
| import java.nio.file.LinkOption; |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| import java.nio.file.SimpleFileVisitor; |
| import java.nio.file.StandardCopyOption; |
| import java.nio.file.attribute.BasicFileAttributes; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Objects; |
| |
| import org.apache.commons.lang.SystemUtils; |
| import org.apache.maven.artifact.ArtifactUtils; |
| import org.apache.maven.artifact.repository.ArtifactRepository; |
| import org.apache.maven.artifact.repository.DefaultArtifactRepository; |
| import org.apache.maven.artifact.repository.MavenArtifactRepository; |
| import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout; |
| import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout; |
| import org.apache.maven.model.Profile; |
| import org.apache.maven.model.Repository; |
| import org.apache.maven.project.DefaultProjectBuildingRequest; |
| import org.apache.maven.project.MavenProject; |
| import org.apache.maven.project.ProjectBuilder; |
| import org.apache.maven.project.ProjectBuildingRequest; |
| import org.apache.maven.project.ProjectBuildingRequest.RepositoryMerging; |
| import org.apache.maven.project.ProjectBuildingResult; |
| import org.apache.maven.project.ProjectSorter; |
| import org.apache.maven.repository.internal.MavenRepositorySystemSession; |
| import org.apache.maven.shared.release.PlexusJUnit4TestCase; |
| import org.apache.maven.shared.release.config.ReleaseDescriptorBuilder; |
| import org.sonatype.aether.impl.internal.SimpleLocalRepositoryManager; |
| import org.sonatype.aether.repository.WorkspaceReader; |
| import org.sonatype.aether.repository.WorkspaceRepository; |
| import org.xmlunit.builder.DiffBuilder; |
| import org.xmlunit.diff.Comparison; |
| import org.xmlunit.diff.ComparisonResult; |
| import org.xmlunit.diff.ComparisonType; |
| import org.xmlunit.diff.DefaultNodeMatcher; |
| import org.xmlunit.diff.Diff; |
| import org.xmlunit.diff.DifferenceEvaluator; |
| import org.xmlunit.diff.ElementSelectors; |
| |
| /** |
| * Base class for some release tests. |
| * |
| * @author <a href="mailto:brett@apache.org">Brett Porter</a> |
| */ |
| public abstract class AbstractReleaseTestCase |
| extends PlexusJUnit4TestCase |
| { |
| protected ProjectBuilder projectBuilder; |
| |
| protected ArtifactRepository localRepository; |
| |
| protected ReleasePhase phase; |
| |
| @Override |
| public void setUp() |
| throws Exception |
| { |
| super.setUp(); |
| |
| projectBuilder = lookup( ProjectBuilder.class ); |
| |
| ArtifactRepositoryLayout layout = lookup( ArtifactRepositoryLayout.class, "default" ); |
| String localRepoPath = getTestFile( "target/local-repository" ).getAbsolutePath().replace( '\\', '/' ); |
| localRepository = new MavenArtifactRepository( "local", "file://" + localRepoPath, layout, null, null ); |
| } |
| |
| protected Path getWorkingDirectory( String workingDir ) |
| { |
| return Paths.get( getBasedir(), "target/test-classes" ).resolve( Paths.get( "projects", workingDir ) ) ; |
| } |
| |
| protected List<MavenProject> createReactorProjects( String path, String subpath ) |
| throws Exception |
| { |
| return createReactorProjects( path, path, subpath ); |
| } |
| |
| protected ReleaseDescriptorBuilder createReleaseDescriptorBuilder( List<MavenProject> reactorProjects ) |
| { |
| ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder(); |
| for ( MavenProject project : reactorProjects ) |
| { |
| String projectKey = ArtifactUtils.versionlessKey( project.getGroupId(), project.getArtifactId() ); |
| builder.putOriginalVersion( projectKey, project.getVersion() ); |
| builder.addProjectPomFile( projectKey, project.getFile().getPath() ); |
| } |
| return builder; |
| } |
| |
| /** |
| * |
| * @param sourcePath sourceDirectory to copy from |
| * @param targetPath targetDirectory to copy to |
| * @param executionRoot sub directory of targetPath in case the root pom.xml is not used (e.g. flat projects) |
| * @return all Maven projects |
| * @throws Exception if any occurs |
| */ |
| protected List<MavenProject> createReactorProjects( String sourcePath, String targetPath, String executionRoot ) |
| throws Exception |
| { |
| final Path testCaseRootFrom = Paths.get( getBasedir(), "src/test/resources" ).resolve( Paths.get( "projects", sourcePath ) ) ; |
| |
| final Path testCaseRootTo = getWorkingDirectory( targetPath ); |
| |
| // Recopy the test resources since they are modified in some tests |
| Files.walkFileTree( testCaseRootFrom, new SimpleFileVisitor<Path>() { |
| |
| @Override |
| public FileVisitResult visitFile( Path file, BasicFileAttributes attrs ) |
| throws IOException |
| { |
| Path relPath = testCaseRootFrom.relativize( file ); |
| |
| if ( !relPath.toFile().getName().startsWith( "expected-" ) ) |
| { |
| Files.createDirectories( testCaseRootTo.resolve( relPath ).getParent() ); |
| |
| Files.copy( file, testCaseRootTo.resolve( relPath ), StandardCopyOption.REPLACE_EXISTING ); |
| } |
| |
| return FileVisitResult.CONTINUE; |
| } |
| }); |
| |
| Path projectFile; |
| if ( executionRoot == null ) |
| { |
| projectFile = testCaseRootTo.resolve( "pom.xml" ); |
| } |
| else |
| { |
| projectFile = testCaseRootTo.resolve( Paths.get( executionRoot, "pom.xml" ) ); |
| } |
| |
| List<ArtifactRepository> repos = |
| Collections.<ArtifactRepository>singletonList( new DefaultArtifactRepository( "central", |
| getRemoteRepositoryURL(), |
| new DefaultRepositoryLayout() ) ); |
| |
| Repository repository = new Repository(); |
| repository.setId( "central" ); |
| repository.setUrl( getRemoteRepositoryURL() ); |
| |
| Profile profile = new Profile(); |
| profile.setId( "profile" ); |
| profile.addRepository( repository ); |
| |
| ProjectBuildingRequest buildingRequest = new DefaultProjectBuildingRequest(); |
| buildingRequest.setLocalRepository( localRepository ); |
| buildingRequest.setRemoteRepositories( repos ); |
| buildingRequest.setPluginArtifactRepositories( repos ); |
| buildingRequest.setRepositoryMerging( RepositoryMerging.REQUEST_DOMINANT ); |
| MavenRepositorySystemSession repositorySession = new MavenRepositorySystemSession(); |
| repositorySession.setLocalRepositoryManager( new SimpleLocalRepositoryManager( localRepository.getBasedir() ) ); |
| buildingRequest.setRepositorySession( repositorySession ); |
| buildingRequest.addProfile( profile ); |
| buildingRequest.setActiveProfileIds( Arrays.asList( profile.getId() ) ); |
| buildingRequest.setResolveDependencies( true ); |
| |
| List<ProjectBuildingResult> buildingResults = |
| projectBuilder.build( Collections.singletonList( projectFile.toFile() ), true, buildingRequest ); |
| |
| List<MavenProject> reactorProjects = new ArrayList<>(); |
| for ( ProjectBuildingResult buildingResult : buildingResults ) |
| { |
| reactorProjects.add( buildingResult.getProject() ) ; |
| } |
| |
| WorkspaceReader simpleReactorReader = new SimpleReactorWorkspaceReader( reactorProjects ); |
| repositorySession.setWorkspaceReader( simpleReactorReader ); |
| |
| ProjectSorter sorter = new ProjectSorter( reactorProjects ); |
| reactorProjects = sorter.getSortedProjects(); |
| |
| List<MavenProject> resolvedProjects = new ArrayList<>( reactorProjects.size() ); |
| for ( MavenProject project : reactorProjects ) |
| { |
| resolvedProjects.add( projectBuilder.build( project.getFile(), buildingRequest ).getProject() ); |
| } |
| return resolvedProjects; |
| } |
| |
| protected static Map<String,MavenProject> getProjectsAsMap( List<MavenProject> reactorProjects ) |
| { |
| Map<String,MavenProject> map = new HashMap<>(); |
| for ( MavenProject project : reactorProjects ) |
| { |
| map.put( ArtifactUtils.versionlessKey( project.getGroupId(), project.getArtifactId() ), project ); |
| } |
| return map; |
| } |
| |
| protected boolean comparePomFiles( List<MavenProject> reactorProjects ) |
| throws IOException |
| { |
| return comparePomFiles( reactorProjects, true ); |
| } |
| |
| protected boolean comparePomFiles( List<MavenProject> reactorProjects, boolean normalizeLineEndings ) |
| throws IOException |
| { |
| comparePomFiles( reactorProjects, "", normalizeLineEndings ); |
| |
| // TODO: return void since this is redundant |
| return true; |
| } |
| |
| protected void comparePomFiles( List<MavenProject> reactorProjects, String expectedFileSuffix ) |
| throws IOException |
| { |
| comparePomFiles( reactorProjects, expectedFileSuffix, true ); |
| } |
| |
| protected void comparePomFiles( List<MavenProject> reactorProjects, String expectedFileSuffix, boolean normalizeLineEndings ) |
| throws IOException |
| { |
| for ( MavenProject project : reactorProjects ) |
| { |
| comparePomFiles( project, expectedFileSuffix, normalizeLineEndings ); |
| } |
| } |
| |
| protected void comparePomFiles( MavenProject project, String expectedFileSuffix ) |
| throws IOException |
| { |
| comparePomFiles( project, expectedFileSuffix, true ); |
| } |
| |
| protected void comparePomFiles( MavenProject project, String expectedFileSuffix, boolean normalizeLineEndings ) |
| throws IOException |
| { |
| File actualFile = project.getFile(); |
| File expectedFile = new File( actualFile.getParentFile(), "expected-pom" + expectedFileSuffix + ".xml" ); |
| |
| comparePomFiles( expectedFile, actualFile, normalizeLineEndings, false ); |
| } |
| |
| protected void comparePomFiles( File expectedFile, File actualFile ) |
| throws IOException |
| { |
| comparePomFiles( expectedFile, actualFile, true, false ); |
| } |
| |
| protected void comparePomFiles( File expectedFile, File actualFile, boolean normalizeLineEndings, boolean ignoreComments ) |
| throws IOException |
| { |
| StringBuffer sb = new StringBuffer( "Check the transformed POM " + actualFile ); |
| sb.append( SystemUtils.LINE_SEPARATOR ); |
| |
| final String remoteRepositoryURL = getRemoteRepositoryURL(); |
| |
| DiffBuilder diffBuilder = DiffBuilder.compare( expectedFile ).withTest( actualFile ); |
| if ( normalizeLineEndings ) |
| { |
| diffBuilder = diffBuilder.normalizeWhitespace(); |
| } |
| if ( ignoreComments ) |
| { |
| diffBuilder.ignoreComments(); |
| } |
| // Order of elements has changed between M2 and M3, so match by name |
| diffBuilder.withNodeMatcher( new DefaultNodeMatcher( ElementSelectors.byName ) ).checkForSimilar(); |
| |
| diffBuilder.withDifferenceEvaluator( new DifferenceEvaluator() |
| { |
| @Override |
| public ComparisonResult evaluate( Comparison comparison, ComparisonResult outcome ) |
| { |
| if ( "${remoterepo}".equals( comparison.getControlDetails().getValue() ) && |
| remoteRepositoryURL.equals( comparison.getTestDetails().getValue() ) ) |
| { |
| return ComparisonResult.EQUAL; |
| } |
| else if ( outcome == ComparisonResult.DIFFERENT |
| && comparison.getType() == ComparisonType.CHILD_NODELIST_SEQUENCE ) |
| { |
| // Order of elements has changed between M2 and M3 |
| return ComparisonResult.EQUAL; |
| } |
| else if ( outcome == ComparisonResult.DIFFERENT |
| && comparison.getType() == ComparisonType.TEXT_VALUE |
| && "${project.build.directory}/site".equals( comparison.getTestDetails().getValue() ) ) |
| { |
| // M2 was target/site, M3 is ${project.build.directory}/site |
| return ComparisonResult.EQUAL; |
| } |
| else |
| { |
| return outcome; |
| } |
| } |
| } ); |
| |
| Diff diff = diffBuilder.build(); |
| |
| sb.append( diff.toString() ); |
| |
| assertFalse( sb.toString(), diff.hasDifferences() ); |
| } |
| |
| private String getRemoteRepositoryURL() |
| throws IOException |
| { |
| File testFile = getTestFile( "src/test/remote-repository" ); |
| if (testFile.getAbsolutePath().equals( testFile.getCanonicalPath() ) ) |
| { |
| return "file://" + getTestFile( "src/test/remote-repository" ).getAbsolutePath().replace( '\\', '/' ); |
| } |
| return "file://" + getTestFile( "src/test/remote-repository" ).getCanonicalPath().replace( '\\', '/' ); |
| } |
| |
| public static String getPath( File file ) |
| throws IOException |
| { |
| return file.toPath().toRealPath( LinkOption.NOFOLLOW_LINKS ).toString(); |
| } |
| |
| /** |
| * WorkspaceReader to find versions and artifacts from reactor |
| */ |
| private static final class SimpleReactorWorkspaceReader |
| implements WorkspaceReader |
| { |
| private final List<MavenProject> reactorProjects; |
| |
| private SimpleReactorWorkspaceReader( List<MavenProject> reactorProjects ) |
| { |
| this.reactorProjects = reactorProjects; |
| } |
| |
| @Override |
| public WorkspaceRepository getRepository() |
| { |
| return null; |
| } |
| |
| @Override |
| public List<String> findVersions( org.sonatype.aether.artifact.Artifact artifact ) |
| { |
| for ( MavenProject mavenProject : reactorProjects ) |
| { |
| if ( Objects.equals( artifact.toString(), mavenProject.getArtifact().toString() ) ) |
| { |
| return Collections.singletonList( mavenProject.getArtifact().getVersion() ); |
| } |
| } |
| return Collections.emptyList(); |
| } |
| |
| @Override |
| public File findArtifact( org.sonatype.aether.artifact.Artifact artifact ) |
| { |
| for ( MavenProject mavenProject : reactorProjects ) |
| { |
| String pom = mavenProject.getGroupId() + ':' + mavenProject.getArtifactId() + ":pom:" |
| + mavenProject.getVersion(); |
| if ( Objects.equals( artifact.toString(), pom ) ) |
| { |
| return mavenProject.getFile(); |
| } |
| else if ( Objects.equals( artifact.toString(), mavenProject.getArtifact().toString() ) ) |
| { |
| // just an existing, content doesn't matter |
| return mavenProject.getFile(); |
| } |
| } |
| return null; |
| } |
| } |
| } |