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.apache.maven.model.PluginManagement;
30  import org.codehaus.plexus.util.dag.CycleDetectedException;
31  
32  import java.util.ArrayList;
33  import java.util.Arrays;
34  import java.util.Collections;
35  import java.util.List;
36  
37  /**
38   * Test sorting projects by dependencies.
39   * 
40   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
41   * @version $Id: ProjectSorterTest.java 767940 2009-04-23 15:11:18Z jdcasey $
42   */
43  public class ProjectSorterTest
44      extends TestCase
45  {
46  
47      public void testBasicSingleProject()
48          throws CycleDetectedException, DuplicateProjectException, MissingProjectException
49      {
50          MavenProject project = createProject( "group", "artifactA", "1.0" );
51  
52          List projects = new ProjectSorter( Collections.singletonList( project ) ).getSortedProjects();
53  
54          assertEquals( "Wrong number of projects: " + projects, 1, projects.size() );
55          assertEquals( "Didn't match project", project, projects.get( 0 ) );
56      }
57  
58      public void testBasicMultiProject()
59          throws CycleDetectedException, DuplicateProjectException, MissingProjectException
60      {
61          MavenProject projectA = createProject( "group", "artifactA", "1.0" );
62          MavenProject projectB = createProject( "group", "artifactB", "1.0" );
63          MavenProject projectC = createProject( "group", "artifactC", "1.0" );
64  
65          projectA.getDependencies().add( createDependency( projectB ) );
66          projectB.getDependencies().add( createDependency( projectC ) );
67  
68          List projects = Arrays.asList( new Object[] { projectA, projectB, projectC } );
69  
70          projects = new ProjectSorter( projects ).getSortedProjects();
71  
72          assertEquals( "Wrong number of projects: " + projects, 3, projects.size() );
73          assertEquals( "Didn't match project", projectC, projects.get( 0 ) );
74          assertEquals( "Didn't match project", projectB, projects.get( 1 ) );
75          assertEquals( "Didn't match project", projectA, projects.get( 2 ) );
76      }
77  
78      public void testResumeFrom()
79          throws CycleDetectedException, DuplicateProjectException, MissingProjectException
80      {
81          MavenProject projectA = createProject( "group", "artifactA", "1.0" );
82          MavenProject projectB = createProject( "group", "artifactB", "1.0" );
83          MavenProject projectC = createProject( "group", "artifactC", "1.0" );
84  
85          projectA.getDependencies().add( createDependency( projectB ) );
86          projectB.getDependencies().add( createDependency( projectC ) );
87  
88          List projects = Arrays.asList( new Object[] { projectA, projectB, projectC } );
89  
90          projects = new ProjectSorter( projects, null, "group:artifactB", false, false ).getSortedProjects();
91  
92          assertEquals( "Wrong number of projects: " + projects, 2, projects.size() );
93          assertEquals( "Didn't match project", projectB, projects.get( 0 ) );
94          assertEquals( "Didn't match project", projectA, projects.get( 1 ) );
95      }
96  
97      public void testSelectedProjects()
98          throws CycleDetectedException, DuplicateProjectException, MissingProjectException
99      {
100         MavenProject projectA = createProject( "group", "artifactA", "1.0" );
101         MavenProject projectB = createProject( "group", "artifactB", "1.0" );
102         MavenProject projectC = createProject( "group", "artifactC", "1.0" );
103 
104         projectA.getDependencies().add( createDependency( projectB ) );
105         projectB.getDependencies().add( createDependency( projectC ) );
106 
107         List projects = Arrays.asList( new Object[] { projectA, projectB, projectC } );
108         List selectedProjects = Arrays.asList( new Object[] { "group:artifactB" } );
109 
110         projects = new ProjectSorter( projects, selectedProjects, null, false, false ).getSortedProjects();
111 
112         assertEquals( "Wrong number of projects: " + projects, 1, projects.size() );
113         assertEquals( "Didn't match project", projectB, projects.get( 0 ) );
114     }
115 
116     public void testMake()
117         throws CycleDetectedException, DuplicateProjectException, MissingProjectException
118     {
119         MavenProject projectA = createProject( "group", "artifactA", "1.0" );
120         MavenProject projectB = createProject( "group", "artifactB", "1.0" );
121         MavenProject projectC = createProject( "group", "artifactC", "1.0" );
122 
123         projectA.getDependencies().add( createDependency( projectB ) );
124         projectB.getDependencies().add( createDependency( projectC ) );
125 
126         List projects = Arrays.asList( new Object[] { projectA, projectB, projectC } );
127         List selectedProjects = Arrays.asList( new Object[] { "group:artifactB" } );
128 
129         projects = new ProjectSorter( projects, selectedProjects, null, true/* make */, false ).getSortedProjects();
130 
131         assertEquals( "Wrong number of projects: " + projects, 2, projects.size() );
132         assertEquals( "Didn't match project", projectC, projects.get( 0 ) );
133         assertEquals( "Didn't match project", projectB, projects.get( 1 ) );
134     }
135 
136     public void testMakeDependents()
137         throws CycleDetectedException, DuplicateProjectException, MissingProjectException
138     {
139         MavenProject projectA = createProject( "group", "artifactA", "1.0" );
140         MavenProject projectB = createProject( "group", "artifactB", "1.0" );
141         MavenProject projectC = createProject( "group", "artifactC", "1.0" );
142 
143         projectA.getDependencies().add( createDependency( projectB ) );
144         projectB.getDependencies().add( createDependency( projectC ) );
145 
146         List projects = Arrays.asList( new Object[] { projectA, projectB, projectC } );
147         List selectedProjects = Arrays.asList( new Object[] { "group:artifactB" } );
148 
149         projects =
150             new ProjectSorter( projects, selectedProjects, null, false/* make */, true/* makeDependents */).getSortedProjects();
151 
152         assertEquals( "Wrong number of projects: " + projects, 2, projects.size() );
153         assertEquals( "Didn't match project", projectB, projects.get( 0 ) );
154         assertEquals( "Didn't match project", projectA, projects.get( 1 ) );
155     }
156 
157     public void testMakeBoth()
158         throws CycleDetectedException, DuplicateProjectException, MissingProjectException
159     {
160         MavenProject projectA = createProject( "group", "artifactA", "1.0" );
161         MavenProject projectB = createProject( "group", "artifactB", "1.0" );
162         MavenProject projectC = createProject( "group", "artifactC", "1.0" );
163         MavenProject projectD = createProject( "group", "artifactD", "1.0" );
164         MavenProject projectE = createProject( "group", "artifactE", "1.0" );
165 
166         projectA.getDependencies().add( createDependency( projectB ) );
167         projectB.getDependencies().add( createDependency( projectC ) );
168         projectD.getDependencies().add( createDependency( projectE ) );
169         projectE.getDependencies().add( createDependency( projectB ) );
170 
171         List projects = Arrays.asList( new Object[] { projectA, projectB, projectC, projectD, projectE } );
172         List selectedProjects = Arrays.asList( new Object[] { "group:artifactE" } );
173 
174         projects =
175             new ProjectSorter( projects, selectedProjects, null, true/* make */, true/* makeDependents */).getSortedProjects();
176 
177         assertEquals( "Wrong number of projects: " + projects, 4, projects.size() );
178         assertEquals( "Didn't match project", projectC, projects.get( 0 ) );
179         assertEquals( "Didn't match project", projectB, projects.get( 1 ) );
180         assertEquals( "Didn't match project", projectE, projects.get( 2 ) );
181         assertEquals( "Didn't match project", projectD, projects.get( 3 ) );
182     }
183 
184     public void testShouldNotFailWhenPluginDepReferencesCurrentProject()
185         throws CycleDetectedException, DuplicateProjectException, MissingProjectException
186     {
187         MavenProject project = createProject( "group", "artifact", "1.0" );
188         Model model = project.getModel();
189 
190         Build build = model.getBuild();
191 
192         if ( build == null )
193         {
194             build = new Build();
195             model.setBuild( build );
196         }
197 
198         Plugin plugin = new Plugin();
199 
200         plugin.setArtifactId( "other-artifact" );
201         plugin.setGroupId( "other.group" );
202         plugin.setVersion( "1.0" );
203 
204         Dependency dep = new Dependency();
205         dep.setGroupId( "group" );
206         dep.setArtifactId( "artifact" );
207         dep.setVersion( "1.0" );
208 
209         plugin.addDependency( dep );
210 
211         build.addPlugin( plugin );
212 
213         new ProjectSorter( Collections.singletonList( project ) );
214     }
215 
216     public void testShouldNotFailWhenManagedPluginDepReferencesCurrentProject()
217         throws CycleDetectedException, DuplicateProjectException, MissingProjectException
218     {
219         MavenProject project = createProject( "group", "artifact", "1.0" );
220         Model model = project.getModel();
221 
222         Build build = model.getBuild();
223 
224         if ( build == null )
225         {
226             build = new Build();
227             model.setBuild( build );
228         }
229         
230         PluginManagement pMgmt = new PluginManagement();
231 
232         Plugin plugin = new Plugin();
233 
234         plugin.setArtifactId( "other-artifact" );
235         plugin.setGroupId( "other.group" );
236         plugin.setVersion( "1.0" );
237 
238         Dependency dep = new Dependency();
239         dep.setGroupId( "group" );
240         dep.setArtifactId( "artifact" );
241         dep.setVersion( "1.0" );
242 
243         plugin.addDependency( dep );
244 
245         pMgmt.addPlugin( plugin );
246         
247         build.setPluginManagement( pMgmt );
248 
249         new ProjectSorter( Collections.singletonList( project ) );
250     }
251 
252     public void testShouldNotFailWhenProjectReferencesNonExistentProject()
253         throws CycleDetectedException, DuplicateProjectException, MissingProjectException
254     {
255         MavenProject project = createProject( "group", "artifact", "1.0" );
256         Model model = project.getModel();
257 
258         Build build = model.getBuild();
259 
260         if ( build == null )
261         {
262             build = new Build();
263             model.setBuild( build );
264         }
265 
266         Extension extension = new Extension();
267 
268         extension.setArtifactId( "other-artifact" );
269         extension.setGroupId( "other.group" );
270         extension.setVersion( "1.0" );
271 
272         build.addExtension( extension );
273 
274         new ProjectSorter( Collections.singletonList( project ) );
275     }
276 
277     public void testMatchingArtifactIdsDifferentGroupIds()
278         throws CycleDetectedException, DuplicateProjectException, MissingProjectException
279     {
280         List projects = new ArrayList();
281         MavenProject project1 = createProject( "groupId1", "artifactId", "1.0" );
282         projects.add( project1 );
283         MavenProject project2 = createProject( "groupId2", "artifactId", "1.0" );
284         projects.add( project2 );
285         project1.getDependencies().add( createDependency( project2 ) );
286 
287         projects = new ProjectSorter( projects ).getSortedProjects();
288 
289         assertEquals( project2, projects.get( 0 ) );
290         assertEquals( project1, projects.get( 1 ) );
291     }
292 
293     public void testMatchingGroupIdsDifferentArtifactIds()
294         throws CycleDetectedException, DuplicateProjectException, MissingProjectException
295     {
296         List projects = new ArrayList();
297         MavenProject project1 = createProject( "groupId", "artifactId1", "1.0" );
298         projects.add( project1 );
299         MavenProject project2 = createProject( "groupId", "artifactId2", "1.0" );
300         projects.add( project2 );
301         project1.getDependencies().add( createDependency( project2 ) );
302 
303         projects = new ProjectSorter( projects ).getSortedProjects();
304 
305         assertEquals( project2, projects.get( 0 ) );
306         assertEquals( project1, projects.get( 1 ) );
307     }
308 
309     public void testMatchingIdsAndVersions()
310         throws CycleDetectedException, MissingProjectException
311     {
312         List projects = new ArrayList();
313         MavenProject project1 = createProject( "groupId", "artifactId", "1.0" );
314         projects.add( project1 );
315         MavenProject project2 = createProject( "groupId", "artifactId", "1.0" );
316         projects.add( project2 );
317 
318         try
319         {
320             projects = new ProjectSorter( projects ).getSortedProjects();
321             fail( "Duplicate projects should fail" );
322         }
323         catch ( DuplicateProjectException e )
324         {
325             // expected
326             assertTrue( true );
327         }
328     }
329 
330     public void testMatchingIdsAndDifferentVersions()
331         throws CycleDetectedException, MissingProjectException
332     {
333         List projects = new ArrayList();
334         MavenProject project1 = createProject( "groupId", "artifactId", "1.0" );
335         projects.add( project1 );
336         MavenProject project2 = createProject( "groupId", "artifactId", "2.0" );
337         projects.add( project2 );
338 
339         try
340         {
341             projects = new ProjectSorter( projects ).getSortedProjects();
342             fail( "Duplicate projects should fail" );
343         }
344         catch ( DuplicateProjectException e )
345         {
346             // expected
347             assertTrue( true );
348         }
349     }
350 
351     public void testPluginDependenciesInfluenceSorting()
352         throws Exception
353     {
354         List projects = new ArrayList();
355 
356         MavenProject parentProject = createProject( "groupId", "parent", "1.0" );
357         projects.add( parentProject );
358 
359         MavenProject declaringProject = createProject( "groupId", "declarer", "1.0" );
360         declaringProject.setParent( parentProject );
361         projects.add( declaringProject );
362 
363         MavenProject pluginLevelDepProject = createProject( "groupId", "plugin-level-dep", "1.0" );
364         pluginLevelDepProject.setParent( parentProject );
365         projects.add( pluginLevelDepProject );
366 
367         MavenProject pluginProject = createProject( "groupId", "plugin", "1.0" );
368         pluginProject.setParent( parentProject );
369         projects.add( pluginProject );
370 
371         Plugin plugin = new Plugin();
372         plugin.setGroupId( pluginProject.getGroupId() );
373         plugin.setArtifactId( pluginProject.getArtifactId() );
374         plugin.setVersion( pluginProject.getVersion() );
375 
376         plugin.addDependency( createDependency( pluginLevelDepProject ) );
377 
378         Model model = declaringProject.getModel();
379         Build build = model.getBuild();
380 
381         if ( build == null )
382         {
383             build = new Build();
384             model.setBuild( build );
385         }
386 
387         build.addPlugin( plugin );
388 
389         projects = new ProjectSorter( projects ).getSortedProjects();
390 
391         assertEquals( parentProject, projects.get( 0 ) );
392 
393         // the order of these two is non-deterministic, based on when they're added to the reactor.
394         assertTrue( projects.contains( pluginProject ) );
395         assertTrue( projects.contains( pluginLevelDepProject ) );
396 
397         // the declaring project MUST be listed after the plugin and its plugin-level dep, though.
398         assertEquals( declaringProject, projects.get( 3 ) );
399     }
400 
401     public void testPluginDependenciesInfluenceSorting_DeclarationInParent()
402         throws Exception
403     {
404         List projects = new ArrayList();
405 
406         MavenProject parentProject = createProject( "groupId", "parent-declarer", "1.0" );
407         projects.add( parentProject );
408 
409         MavenProject pluginProject = createProject( "groupId", "plugin", "1.0" );
410         pluginProject.setParent( parentProject );
411         projects.add( pluginProject );
412 
413         MavenProject pluginLevelDepProject = createProject( "groupId", "plugin-level-dep", "1.0" );
414         pluginLevelDepProject.setParent( parentProject );
415         projects.add( pluginLevelDepProject );
416 
417         Plugin plugin = new Plugin();
418         plugin.setGroupId( pluginProject.getGroupId() );
419         plugin.setArtifactId( pluginProject.getArtifactId() );
420         plugin.setVersion( pluginProject.getVersion() );
421 
422         plugin.addDependency( createDependency( pluginLevelDepProject ) );
423 
424         Model model = parentProject.getModel();
425         Build build = model.getBuild();
426 
427         if ( build == null )
428         {
429             build = new Build();
430             model.setBuild( build );
431         }
432 
433         build.addPlugin( plugin );
434 
435         projects = new ProjectSorter( projects ).getSortedProjects();
436 
437         System.out.println( projects );
438 
439         assertEquals( parentProject, projects.get( 0 ) );
440 
441         // the order of these two is non-deterministic, based on when they're added to the reactor.
442         assertTrue( projects.contains( pluginProject ) );
443         assertTrue( projects.contains( pluginLevelDepProject ) );
444     }
445 
446     private Dependency createDependency( MavenProject project )
447     {
448         Dependency depdendency = new Dependency();
449         depdendency.setArtifactId( project.getArtifactId() );
450         depdendency.setGroupId( project.getGroupId() );
451         depdendency.setVersion( project.getVersion() );
452         return depdendency;
453     }
454 
455     private static MavenProject createProject( String groupId, String artifactId, String version )
456     {
457         Model model = new Model();
458         model.setGroupId( groupId );
459         model.setArtifactId( artifactId );
460         model.setVersion( version );
461         return new MavenProject( model );
462     }
463 }