1   package org.apache.maven.project;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import junit.framework.TestCase;
23  
24  import org.apache.maven.model.Build;
25  import org.apache.maven.model.Dependency;
26  import org.apache.maven.model.Extension;
27  import org.apache.maven.model.Model;
28  import org.apache.maven.model.Plugin;
29  import org.codehaus.plexus.util.dag.CycleDetectedException;
30  
31  import java.util.ArrayList;
32  import java.util.Arrays;
33  import java.util.Collections;
34  import java.util.List;
35  
36  /**
37   * Test sorting projects by dependencies.
38   *
39   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
40   * @version $Id: ProjectSorterTest.java 752622 2009-03-11 21:15:51Z jdcasey $
41   */
42  public class ProjectSorterTest
43      extends TestCase
44  {
45  
46      public void testBasicSingleProject()
47          throws CycleDetectedException, DuplicateProjectException, MissingProjectException
48      {
49          MavenProject project = createProject( "group", "artifactA", "1.0" );
50  
51          List projects = new ProjectSorter( Collections.singletonList( project ) ).getSortedProjects();
52          
53          assertEquals( "Wrong number of projects: " + projects, 1, projects.size() );
54          assertEquals( "Didn't match project", project, projects.get( 0 ) );
55      }
56      
57      public void testBasicMultiProject()
58          throws CycleDetectedException, DuplicateProjectException, MissingProjectException
59      {
60          MavenProject projectA = createProject( "group", "artifactA", "1.0" );
61          MavenProject projectB = createProject( "group", "artifactB", "1.0" );
62          MavenProject projectC = createProject( "group", "artifactC", "1.0" );
63          
64          projectA.getDependencies().add( createDependency( projectB ) );
65          projectB.getDependencies().add( createDependency( projectC ) );
66          
67          List projects = Arrays.asList( new Object[] { projectA, projectB, projectC} );
68  
69          projects = new ProjectSorter( projects ).getSortedProjects();
70  
71          assertEquals( "Wrong number of projects: " + projects, 3, projects.size() );
72          assertEquals( "Didn't match project", projectC, projects.get( 0 ) );
73          assertEquals( "Didn't match project", projectB, projects.get( 1 ) );
74          assertEquals( "Didn't match project", projectA, projects.get( 2 ) );
75      }
76  
77      public void testResumeFrom()
78          throws CycleDetectedException, DuplicateProjectException, MissingProjectException
79      {
80          MavenProject projectA = createProject( "group", "artifactA", "1.0" );
81          MavenProject projectB = createProject( "group", "artifactB", "1.0" );
82          MavenProject projectC = createProject( "group", "artifactC", "1.0" );
83  
84          projectA.getDependencies().add( createDependency( projectB ) );
85          projectB.getDependencies().add( createDependency( projectC ) );
86  
87          List projects = Arrays.asList( new Object[] { projectA, projectB, projectC } );
88  
89          projects = new ProjectSorter( projects, null, "group:artifactB", false, false ).getSortedProjects();
90  
91          assertEquals( "Wrong number of projects: " + projects, 2, projects.size() );
92          assertEquals( "Didn't match project", projectB, projects.get( 0 ) );
93          assertEquals( "Didn't match project", projectA, projects.get( 1 ) );
94      }
95  
96      public void testSelectedProjects()
97          throws CycleDetectedException, DuplicateProjectException, MissingProjectException
98      {
99          MavenProject projectA = createProject( "group", "artifactA", "1.0" );
100         MavenProject projectB = createProject( "group", "artifactB", "1.0" );
101         MavenProject projectC = createProject( "group", "artifactC", "1.0" );
102 
103         projectA.getDependencies().add( createDependency( projectB ) );
104         projectB.getDependencies().add( createDependency( projectC ) );
105 
106         List projects = Arrays.asList( new Object[] { projectA, projectB, projectC } );
107         List selectedProjects = Arrays.asList( new Object[] { "group:artifactB" } );
108 
109         projects = new ProjectSorter( projects, selectedProjects, null, false, false ).getSortedProjects();
110 
111         assertEquals( "Wrong number of projects: " + projects, 1, projects.size() );
112         assertEquals( "Didn't match project", projectB, projects.get( 0 ) );
113     }
114 
115     public void testMake()
116         throws CycleDetectedException, DuplicateProjectException, MissingProjectException
117     {
118         MavenProject projectA = createProject( "group", "artifactA", "1.0" );
119         MavenProject projectB = createProject( "group", "artifactB", "1.0" );
120         MavenProject projectC = createProject( "group", "artifactC", "1.0" );
121 
122         projectA.getDependencies().add( createDependency( projectB ) );
123         projectB.getDependencies().add( createDependency( projectC ) );
124 
125         List projects = Arrays.asList( new Object[] { projectA, projectB, projectC } );
126         List selectedProjects = Arrays.asList( new Object[] { "group:artifactB" } );
127 
128         projects = new ProjectSorter( projects, selectedProjects, null, true/* make */, false ).getSortedProjects();
129 
130         assertEquals( "Wrong number of projects: " + projects, 2, projects.size() );
131         assertEquals( "Didn't match project", projectC, projects.get( 0 ) );
132         assertEquals( "Didn't match project", projectB, projects.get( 1 ) );
133     }
134 
135     public void testMakeDependents()
136         throws CycleDetectedException, DuplicateProjectException, MissingProjectException
137     {
138         MavenProject projectA = createProject( "group", "artifactA", "1.0" );
139         MavenProject projectB = createProject( "group", "artifactB", "1.0" );
140         MavenProject projectC = createProject( "group", "artifactC", "1.0" );
141 
142         projectA.getDependencies().add( createDependency( projectB ) );
143         projectB.getDependencies().add( createDependency( projectC ) );
144 
145         List projects = Arrays.asList( new Object[] { projectA, projectB, projectC } );
146         List selectedProjects = Arrays.asList( new Object[] { "group:artifactB" } );
147 
148         projects = new ProjectSorter( projects, selectedProjects, null, false/* make */, true/*makeDependents*/ ).getSortedProjects();
149 
150         assertEquals( "Wrong number of projects: " + projects, 2, projects.size() );
151         assertEquals( "Didn't match project", projectB, projects.get( 0 ) );
152         assertEquals( "Didn't match project", projectA, projects.get( 1 ) );
153     }
154 
155     public void testMakeBoth()
156         throws CycleDetectedException, DuplicateProjectException, MissingProjectException
157     {
158         MavenProject projectA = createProject( "group", "artifactA", "1.0" );
159         MavenProject projectB = createProject( "group", "artifactB", "1.0" );
160         MavenProject projectC = createProject( "group", "artifactC", "1.0" );
161         MavenProject projectD = createProject( "group", "artifactD", "1.0" );
162         MavenProject projectE = createProject( "group", "artifactE", "1.0" );
163 
164         projectA.getDependencies().add( createDependency( projectB ) );
165         projectB.getDependencies().add( createDependency( projectC ) );
166         projectD.getDependencies().add( createDependency( projectE ) );
167         projectE.getDependencies().add( createDependency( projectB ) );
168 
169         List projects = Arrays.asList( new Object[] { projectA, projectB, projectC, projectD, projectE } );
170         List selectedProjects = Arrays.asList( new Object[] { "group:artifactE" } );
171 
172         projects =
173             new ProjectSorter( projects, selectedProjects, null, true/* make */, true/* makeDependents */).getSortedProjects();
174 
175         assertEquals( "Wrong number of projects: " + projects, 4, projects.size() );
176         assertEquals( "Didn't match project", projectC, projects.get( 0 ) );
177         assertEquals( "Didn't match project", projectB, projects.get( 1 ) );
178         assertEquals( "Didn't match project", projectE, projects.get( 2 ) );
179         assertEquals( "Didn't match project", projectD, projects.get( 3 ) );
180     }
181     
182     public void testShouldNotFailWhenProjectReferencesNonExistentProject()
183         throws CycleDetectedException, DuplicateProjectException, MissingProjectException
184     {
185         MavenProject project = createProject( "group", "artifact", "1.0" );
186         Model model = project.getModel();
187         
188         Build build = model.getBuild();
189         
190         if ( build == null )
191         {
192             build = new Build();
193             model.setBuild( build );
194         }
195         
196         Extension extension = new Extension();
197         
198         extension.setArtifactId( "other-artifact" );
199         extension.setGroupId( "other.group" );
200         extension.setVersion( "1.0" );
201         
202         build.addExtension( extension );
203         
204         new ProjectSorter( Collections.singletonList( project ) );
205     }
206     
207     public void testMatchingArtifactIdsDifferentGroupIds()
208         throws CycleDetectedException, DuplicateProjectException, MissingProjectException
209     {
210         List projects = new ArrayList();
211         MavenProject project1 = createProject( "groupId1", "artifactId", "1.0" );
212         projects.add( project1 );
213         MavenProject project2 = createProject( "groupId2", "artifactId", "1.0" );
214         projects.add( project2 );
215         project1.getDependencies().add( createDependency( project2 ) );
216 
217         projects = new ProjectSorter( projects ).getSortedProjects();
218 
219         assertEquals( project2, projects.get( 0 ) );
220         assertEquals( project1, projects.get( 1 ) );
221     }
222 
223     public void testMatchingGroupIdsDifferentArtifactIds()
224         throws CycleDetectedException, DuplicateProjectException, MissingProjectException
225     {
226         List projects = new ArrayList();
227         MavenProject project1 = createProject( "groupId", "artifactId1", "1.0" );
228         projects.add( project1 );
229         MavenProject project2 = createProject( "groupId", "artifactId2", "1.0" );
230         projects.add( project2 );
231         project1.getDependencies().add( createDependency( project2 ) );
232 
233         projects = new ProjectSorter( projects ).getSortedProjects();
234 
235         assertEquals( project2, projects.get( 0 ) );
236         assertEquals( project1, projects.get( 1 ) );
237     }
238 
239     public void testMatchingIdsAndVersions()
240         throws CycleDetectedException, MissingProjectException
241     {
242         List projects = new ArrayList();
243         MavenProject project1 = createProject( "groupId", "artifactId", "1.0" );
244         projects.add( project1 );
245         MavenProject project2 = createProject( "groupId", "artifactId", "1.0" );
246         projects.add( project2 );
247 
248         try 
249         {
250             projects = new ProjectSorter( projects ).getSortedProjects();
251             fail( "Duplicate projects should fail" );
252         }
253         catch ( DuplicateProjectException e )
254         {
255             // expected
256             assertTrue( true );
257         }
258     }
259 
260     public void testMatchingIdsAndDifferentVersions()
261         throws CycleDetectedException, MissingProjectException
262     {
263         List projects = new ArrayList();
264         MavenProject project1 = createProject( "groupId", "artifactId", "1.0" );
265         projects.add( project1 );
266         MavenProject project2 = createProject( "groupId", "artifactId", "2.0" );
267         projects.add( project2 );
268 
269         try 
270         {
271             projects = new ProjectSorter( projects ).getSortedProjects();
272             fail( "Duplicate projects should fail" );
273         }
274         catch ( DuplicateProjectException e )
275         {
276             // expected
277             assertTrue( true );
278         }
279     }
280 
281     public void testPluginDependenciesInfluenceSorting()
282         throws Exception
283     {
284         List projects = new ArrayList();
285 
286         MavenProject parentProject = createProject( "groupId", "parent", "1.0" );
287         projects.add( parentProject );
288 
289         MavenProject declaringProject = createProject( "groupId", "declarer", "1.0" );
290         declaringProject.setParent( parentProject );
291         projects.add( declaringProject );
292 
293         MavenProject pluginLevelDepProject = createProject( "groupId", "plugin-level-dep", "1.0" );
294         pluginLevelDepProject.setParent( parentProject );
295         projects.add( pluginLevelDepProject );
296 
297         MavenProject pluginProject = createProject( "groupId", "plugin", "1.0" );
298         pluginProject.setParent( parentProject );
299         projects.add( pluginProject );
300 
301         Plugin plugin = new Plugin();
302         plugin.setGroupId( pluginProject.getGroupId() );
303         plugin.setArtifactId( pluginProject.getArtifactId() );
304         plugin.setVersion( pluginProject.getVersion() );
305 
306         plugin.addDependency( createDependency( pluginLevelDepProject ) );
307 
308         Model model = declaringProject.getModel();
309         Build build = model.getBuild();
310 
311         if ( build == null )
312         {
313             build = new Build();
314             model.setBuild( build );
315         }
316 
317         build.addPlugin( plugin );
318 
319         projects = new ProjectSorter( projects ).getSortedProjects();
320         
321         assertEquals( parentProject, projects.get( 0 ) );
322         
323         // the order of these two is non-deterministic, based on when they're added to the reactor.
324         assertTrue( projects.contains( pluginProject ) );
325         assertTrue( projects.contains( pluginLevelDepProject ) );
326         
327         // the declaring project MUST be listed after the plugin and its plugin-level dep, though.
328         assertEquals( declaringProject, projects.get( 3 ) );
329     }
330 
331     public void testPluginDependenciesInfluenceSorting_DeclarationInParent()
332         throws Exception
333     {
334         List projects = new ArrayList();
335 
336         MavenProject parentProject = createProject( "groupId", "parent-declarer", "1.0" );
337         projects.add( parentProject );
338 
339         MavenProject pluginProject = createProject( "groupId", "plugin", "1.0" );
340         pluginProject.setParent( parentProject );
341         projects.add( pluginProject );
342 
343         MavenProject pluginLevelDepProject = createProject( "groupId", "plugin-level-dep", "1.0" );
344         pluginLevelDepProject.setParent( parentProject );
345         projects.add( pluginLevelDepProject );
346 
347         Plugin plugin = new Plugin();
348         plugin.setGroupId( pluginProject.getGroupId() );
349         plugin.setArtifactId( pluginProject.getArtifactId() );
350         plugin.setVersion( pluginProject.getVersion() );
351 
352         plugin.addDependency( createDependency( pluginLevelDepProject ) );
353 
354         Model model = parentProject.getModel();
355         Build build = model.getBuild();
356 
357         if ( build == null )
358         {
359             build = new Build();
360             model.setBuild( build );
361         }
362 
363         build.addPlugin( plugin );
364 
365         projects = new ProjectSorter( projects ).getSortedProjects();
366         
367         System.out.println( projects );
368 
369         assertEquals( parentProject, projects.get( 0 ) );
370         
371         // the order of these two is non-deterministic, based on when they're added to the reactor.
372         assertTrue( projects.contains( pluginProject ) );
373         assertTrue( projects.contains( pluginLevelDepProject ) );
374     }
375 
376     private Dependency createDependency( MavenProject project )
377     {
378         Dependency depdendency = new Dependency();
379         depdendency.setArtifactId( project.getArtifactId() );
380         depdendency.setGroupId( project.getGroupId() );
381         depdendency.setVersion( project.getVersion() );
382         return depdendency;
383     }
384 
385     private static MavenProject createProject( String groupId, String artifactId, String version )
386     {
387         Model model = new Model();
388         model.setGroupId( groupId );
389         model.setArtifactId( artifactId );
390         model.setVersion( version );
391         return new MavenProject( model );
392     }
393 }