001package org.apache.maven.project;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.util.ArrayList;
023import java.util.Collections;
024import java.util.List;
025
026import junit.framework.TestCase;
027
028import org.apache.maven.model.Build;
029import org.apache.maven.model.Dependency;
030import org.apache.maven.model.Extension;
031import org.apache.maven.model.Model;
032import org.apache.maven.model.Parent;
033import org.apache.maven.model.Plugin;
034import org.apache.maven.model.PluginManagement;
035import org.codehaus.plexus.util.dag.CycleDetectedException;
036
037/**
038 * Test sorting projects by dependencies.
039 *
040 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
041 */
042public class ProjectSorterTest
043    extends TestCase
044{
045
046    private Parent createParent( MavenProject project )
047    {
048        return createParent( project.getGroupId(), project.getArtifactId(), project.getVersion() );
049    }
050
051    private Parent createParent( String groupId, String artifactId, String version )
052    {
053        Parent plugin = new Parent();
054        plugin.setGroupId( groupId );
055        plugin.setArtifactId( artifactId );
056        plugin.setVersion( version );
057        return plugin;
058    }
059
060    private Dependency createDependency( MavenProject project )
061    {
062        return createDependency( project.getGroupId(), project.getArtifactId(), project.getVersion() );
063    }
064
065    private Dependency createDependency( String groupId, String artifactId, String version )
066    {
067        Dependency depdendency = new Dependency();
068        depdendency.setGroupId( groupId );
069        depdendency.setArtifactId( artifactId );
070        depdendency.setVersion( version );
071        return depdendency;
072    }
073
074    private Plugin createPlugin( MavenProject project )
075    {
076        return createPlugin( project.getGroupId(), project.getArtifactId(), project.getVersion() );
077    }
078
079    private Plugin createPlugin( String groupId, String artifactId, String version )
080    {
081        Plugin plugin = new Plugin();
082        plugin.setGroupId( groupId );
083        plugin.setArtifactId( artifactId );
084        plugin.setVersion( version );
085        return plugin;
086    }
087
088    private Extension createExtension( String groupId, String artifactId, String version )
089    {
090        Extension extension = new Extension();
091        extension.setGroupId( groupId );
092        extension.setArtifactId( artifactId );
093        extension.setVersion( version );
094        return extension;
095    }
096
097    private static MavenProject createProject( String groupId, String artifactId, String version )
098    {
099        Model model = new Model();
100        model.setGroupId( groupId );
101        model.setArtifactId( artifactId );
102        model.setVersion( version );
103        model.setBuild( new Build() );
104        return new MavenProject( model );
105    }
106
107    public void testShouldNotFailWhenPluginDepReferencesCurrentProject()
108        throws CycleDetectedException, DuplicateProjectException
109    {
110        MavenProject project = createProject( "group", "artifact", "1.0" );
111
112        Build build = project.getModel().getBuild();
113
114        Plugin plugin = createPlugin( "other.group", "other-artifact", "1.0" );
115
116        Dependency dep = createDependency( "group", "artifact", "1.0" );
117
118        plugin.addDependency( dep );
119
120        build.addPlugin( plugin );
121
122        new ProjectSorter( Collections.singletonList( project ) );
123    }
124
125    public void testShouldNotFailWhenManagedPluginDepReferencesCurrentProject()
126        throws CycleDetectedException, DuplicateProjectException
127    {
128        MavenProject project = createProject( "group", "artifact", "1.0" );
129
130        Build build = project.getModel().getBuild();
131
132        PluginManagement pMgmt = new PluginManagement();
133
134        Plugin plugin = createPlugin( "other.group", "other-artifact", "1.0" );
135
136        Dependency dep = createDependency( "group", "artifact", "1.0" );
137
138        plugin.addDependency( dep );
139
140        pMgmt.addPlugin( plugin );
141
142        build.setPluginManagement( pMgmt );
143
144        new ProjectSorter( Collections.singletonList( project ) );
145    }
146
147    public void testShouldNotFailWhenProjectReferencesNonExistentProject()
148        throws CycleDetectedException, DuplicateProjectException
149    {
150        MavenProject project = createProject( "group", "artifact", "1.0" );
151
152        Build build = project.getModel().getBuild();
153
154        Extension extension = createExtension( "other.group", "other-artifact", "1.0" );
155
156        build.addExtension( extension );
157
158        new ProjectSorter( Collections.singletonList( project ) );
159    }
160
161    public void testMatchingArtifactIdsDifferentGroupIds()
162        throws CycleDetectedException, DuplicateProjectException
163    {
164        List<MavenProject> projects = new ArrayList<MavenProject>();
165        MavenProject project1 = createProject( "groupId1", "artifactId", "1.0" );
166        projects.add( project1 );
167        MavenProject project2 = createProject( "groupId2", "artifactId", "1.0" );
168        projects.add( project2 );
169        project1.getDependencies().add( createDependency( project2 ) );
170
171        projects = new ProjectSorter( projects ).getSortedProjects();
172
173        assertEquals( project2, projects.get( 0 ) );
174        assertEquals( project1, projects.get( 1 ) );
175    }
176
177    public void testMatchingGroupIdsDifferentArtifactIds()
178        throws CycleDetectedException, DuplicateProjectException
179    {
180        List<MavenProject> projects = new ArrayList<MavenProject>();
181        MavenProject project1 = createProject( "groupId", "artifactId1", "1.0" );
182        projects.add( project1 );
183        MavenProject project2 = createProject( "groupId", "artifactId2", "1.0" );
184        projects.add( project2 );
185        project1.getDependencies().add( createDependency( project2 ) );
186
187        projects = new ProjectSorter( projects ).getSortedProjects();
188
189        assertEquals( project2, projects.get( 0 ) );
190        assertEquals( project1, projects.get( 1 ) );
191    }
192
193    public void testMatchingIdsAndVersions()
194        throws CycleDetectedException
195    {
196        List<MavenProject> projects = new ArrayList<MavenProject>();
197        MavenProject project1 = createProject( "groupId", "artifactId", "1.0" );
198        projects.add( project1 );
199        MavenProject project2 = createProject( "groupId", "artifactId", "1.0" );
200        projects.add( project2 );
201
202        try
203        {
204            projects = new ProjectSorter( projects ).getSortedProjects();
205            fail( "Duplicate projects should fail" );
206        }
207        catch ( DuplicateProjectException e )
208        {
209            // expected
210            assertTrue( true );
211        }
212    }
213
214    public void testMatchingIdsAndDifferentVersions()
215        throws CycleDetectedException, DuplicateProjectException
216    {
217        List<MavenProject> projects = new ArrayList<MavenProject>();
218        MavenProject project1 = createProject( "groupId", "artifactId", "1.0" );
219        projects.add( project1 );
220        MavenProject project2 = createProject( "groupId", "artifactId", "2.0" );
221        projects.add( project2 );
222
223        projects = new ProjectSorter( projects ).getSortedProjects();
224        assertEquals( project1, projects.get( 0 ) );
225        assertEquals( project2, projects.get( 1 ) );
226    }
227
228    public void testPluginDependenciesInfluenceSorting()
229        throws Exception
230    {
231        List<MavenProject> projects = new ArrayList<MavenProject>();
232
233        MavenProject parentProject = createProject( "groupId", "parent", "1.0" );
234        projects.add( parentProject );
235
236        MavenProject declaringProject = createProject( "groupId", "declarer", "1.0" );
237        declaringProject.setParent( parentProject );
238        declaringProject.getModel().setParent( createParent( parentProject ) );
239        projects.add( declaringProject );
240
241        MavenProject pluginLevelDepProject = createProject( "groupId", "plugin-level-dep", "1.0" );
242        pluginLevelDepProject.setParent( parentProject );
243        pluginLevelDepProject.getModel().setParent( createParent( parentProject ) );
244        projects.add( pluginLevelDepProject );
245
246        MavenProject pluginProject = createProject( "groupId", "plugin", "1.0" );
247        pluginProject.setParent( parentProject );
248        pluginProject.getModel().setParent( createParent( parentProject ) );
249        projects.add( pluginProject );
250
251        Plugin plugin = createPlugin( pluginProject );
252
253        plugin.addDependency( createDependency( pluginLevelDepProject ) );
254
255        Build build = declaringProject.getModel().getBuild();
256
257        build.addPlugin( plugin );
258
259        projects = new ProjectSorter( projects ).getSortedProjects();
260
261        assertEquals( parentProject, projects.get( 0 ) );
262
263        // the order of these two is non-deterministic, based on when they're added to the reactor.
264        assertTrue( projects.contains( pluginProject ) );
265        assertTrue( projects.contains( pluginLevelDepProject ) );
266
267        // the declaring project MUST be listed after the plugin and its plugin-level dep, though.
268        assertEquals( declaringProject, projects.get( 3 ) );
269    }
270
271    public void testPluginDependenciesInfluenceSorting_DeclarationInParent()
272        throws Exception
273    {
274        List<MavenProject> projects = new ArrayList<MavenProject>();
275
276        MavenProject parentProject = createProject( "groupId", "parent-declarer", "1.0" );
277        projects.add( parentProject );
278
279        MavenProject pluginProject = createProject( "groupId", "plugin", "1.0" );
280        pluginProject.setParent( parentProject );
281        pluginProject.getModel().setParent( createParent( parentProject ) );
282        projects.add( pluginProject );
283
284        MavenProject pluginLevelDepProject = createProject( "groupId", "plugin-level-dep", "1.0" );
285        pluginLevelDepProject.setParent( parentProject );
286        pluginLevelDepProject.getModel().setParent( createParent( parentProject ) );
287        projects.add( pluginLevelDepProject );
288
289        Plugin plugin = createPlugin( pluginProject );
290
291        plugin.addDependency( createDependency( pluginLevelDepProject ) );
292
293        Build build = parentProject.getModel().getBuild();
294
295        build.addPlugin( plugin );
296
297        projects = new ProjectSorter( projects ).getSortedProjects();
298
299        System.out.println( projects );
300
301        assertEquals( parentProject, projects.get( 0 ) );
302
303        // the order of these two is non-deterministic, based on when they're added to the reactor.
304        assertTrue( projects.contains( pluginProject ) );
305        assertTrue( projects.contains( pluginLevelDepProject ) );
306    }
307
308    public void testPluginVersionsAreConsidered()
309        throws Exception
310    {
311        List<MavenProject> projects = new ArrayList<MavenProject>();
312
313        MavenProject pluginProjectA = createProject( "group", "plugin-a", "2.0-SNAPSHOT" );
314        projects.add( pluginProjectA );
315        pluginProjectA.getModel().getBuild().addPlugin( createPlugin( "group", "plugin-b", "1.0" ) );
316
317        MavenProject pluginProjectB = createProject( "group", "plugin-b", "2.0-SNAPSHOT" );
318        projects.add( pluginProjectB );
319        pluginProjectB.getModel().getBuild().addPlugin( createPlugin( "group", "plugin-a", "1.0" ) );
320
321        projects = new ProjectSorter( projects ).getSortedProjects();
322
323        assertTrue( projects.contains( pluginProjectA ) );
324        assertTrue( projects.contains( pluginProjectB ) );
325    }
326
327    public void testDependencyPrecedesProjectThatUsesSpecificDependencyVersion()
328        throws Exception
329    {
330        List<MavenProject> projects = new ArrayList<MavenProject>();
331
332        MavenProject usingProject = createProject( "group", "project", "1.0" );
333        projects.add( usingProject );
334        usingProject.getModel().addDependency( createDependency( "group", "dependency", "1.0" ) );
335
336        MavenProject pluginProject = createProject( "group", "dependency", "1.0" );
337        projects.add( pluginProject );
338
339        projects = new ProjectSorter( projects ).getSortedProjects();
340
341        assertEquals( pluginProject, projects.get( 0 ) );
342        assertEquals( usingProject, projects.get( 1 ) );
343    }
344
345    public void testDependencyPrecedesProjectThatUsesUnresolvedDependencyVersion()
346        throws Exception
347    {
348        List<MavenProject> projects = new ArrayList<MavenProject>();
349
350        MavenProject usingProject = createProject( "group", "project", "1.0" );
351        projects.add( usingProject );
352        usingProject.getModel().addDependency( createDependency( "group", "dependency", "[1.0,)" ) );
353
354        MavenProject pluginProject = createProject( "group", "dependency", "1.0" );
355        projects.add( pluginProject );
356
357        projects = new ProjectSorter( projects ).getSortedProjects();
358
359        assertEquals( pluginProject, projects.get( 0 ) );
360        assertEquals( usingProject, projects.get( 1 ) );
361    }
362
363}