View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.project;
20  
21  import java.util.ArrayList;
22  import java.util.Collections;
23  import java.util.List;
24  
25  import org.apache.maven.model.Build;
26  import org.apache.maven.model.Dependency;
27  import org.apache.maven.model.Extension;
28  import org.apache.maven.model.Model;
29  import org.apache.maven.model.Parent;
30  import org.apache.maven.model.Plugin;
31  import org.apache.maven.model.PluginManagement;
32  import org.junit.Rule;
33  import org.junit.Test;
34  import org.junit.rules.ExpectedException;
35  
36  import static org.hamcrest.Matchers.hasItem;
37  import static org.junit.Assert.assertEquals;
38  import static org.junit.Assert.assertThat;
39  
40  /**
41   * Test sorting projects by dependencies.
42   *
43   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
44   */
45  public class ProjectSorterTest {
46      @Rule
47      public ExpectedException expectedException = ExpectedException.none();
48  
49      private Parent createParent(MavenProject project) {
50          return createParent(project.getGroupId(), project.getArtifactId(), project.getVersion());
51      }
52  
53      private Parent createParent(String groupId, String artifactId, String version) {
54          Parent plugin = new Parent();
55          plugin.setGroupId(groupId);
56          plugin.setArtifactId(artifactId);
57          plugin.setVersion(version);
58          return plugin;
59      }
60  
61      private Dependency createDependency(MavenProject project) {
62          return createDependency(project.getGroupId(), project.getArtifactId(), project.getVersion());
63      }
64  
65      private Dependency createDependency(String groupId, String artifactId, String version) {
66          Dependency dependency = new Dependency();
67          dependency.setGroupId(groupId);
68          dependency.setArtifactId(artifactId);
69          dependency.setVersion(version);
70          return dependency;
71      }
72  
73      private Plugin createPlugin(MavenProject project) {
74          return createPlugin(project.getGroupId(), project.getArtifactId(), project.getVersion());
75      }
76  
77      private Plugin createPlugin(String groupId, String artifactId, String version) {
78          Plugin plugin = new Plugin();
79          plugin.setGroupId(groupId);
80          plugin.setArtifactId(artifactId);
81          plugin.setVersion(version);
82          return plugin;
83      }
84  
85      private Extension createExtension(String groupId, String artifactId, String version) {
86          Extension extension = new Extension();
87          extension.setGroupId(groupId);
88          extension.setArtifactId(artifactId);
89          extension.setVersion(version);
90          return extension;
91      }
92  
93      private static MavenProject createProject(String groupId, String artifactId, String version) {
94          Model model = new Model();
95          model.setGroupId(groupId);
96          model.setArtifactId(artifactId);
97          model.setVersion(version);
98          model.setBuild(new Build());
99          return new MavenProject(model);
100     }
101 
102     @Test
103     public void testShouldNotFailWhenPluginDepReferencesCurrentProject() throws Exception {
104         MavenProject project = createProject("group", "artifact", "1.0");
105 
106         Build build = project.getModel().getBuild();
107 
108         Plugin plugin = createPlugin("other.group", "other-artifact", "1.0");
109 
110         Dependency dep = createDependency("group", "artifact", "1.0");
111 
112         plugin.addDependency(dep);
113 
114         build.addPlugin(plugin);
115 
116         new ProjectSorter(Collections.singletonList(project));
117     }
118 
119     @Test
120     public void testShouldNotFailWhenManagedPluginDepReferencesCurrentProject() throws Exception {
121         MavenProject project = createProject("group", "artifact", "1.0");
122 
123         Build build = project.getModel().getBuild();
124 
125         PluginManagement pMgmt = new PluginManagement();
126 
127         Plugin plugin = createPlugin("other.group", "other-artifact", "1.0");
128 
129         Dependency dep = createDependency("group", "artifact", "1.0");
130 
131         plugin.addDependency(dep);
132 
133         pMgmt.addPlugin(plugin);
134 
135         build.setPluginManagement(pMgmt);
136 
137         new ProjectSorter(Collections.singletonList(project));
138     }
139 
140     @Test
141     public void testShouldNotFailWhenProjectReferencesNonExistentProject() throws Exception {
142         MavenProject project = createProject("group", "artifact", "1.0");
143 
144         Build build = project.getModel().getBuild();
145 
146         Extension extension = createExtension("other.group", "other-artifact", "1.0");
147 
148         build.addExtension(extension);
149 
150         new ProjectSorter(Collections.singletonList(project));
151     }
152 
153     @Test
154     public void testMatchingArtifactIdsDifferentGroupIds() throws Exception {
155         List<MavenProject> projects = new ArrayList<>();
156         MavenProject project1 = createProject("groupId1", "artifactId", "1.0");
157         projects.add(project1);
158         MavenProject project2 = createProject("groupId2", "artifactId", "1.0");
159         projects.add(project2);
160         project1.getDependencies().add(createDependency(project2));
161 
162         projects = new ProjectSorter(projects).getSortedProjects();
163 
164         assertEquals(project2, projects.get(0));
165         assertEquals(project1, projects.get(1));
166     }
167 
168     @Test
169     public void testMatchingGroupIdsDifferentArtifactIds() throws Exception {
170         List<MavenProject> projects = new ArrayList<>();
171         MavenProject project1 = createProject("groupId", "artifactId1", "1.0");
172         projects.add(project1);
173         MavenProject project2 = createProject("groupId", "artifactId2", "1.0");
174         projects.add(project2);
175         project1.getDependencies().add(createDependency(project2));
176 
177         projects = new ProjectSorter(projects).getSortedProjects();
178 
179         assertEquals(project2, projects.get(0));
180         assertEquals(project1, projects.get(1));
181     }
182 
183     @Test
184     public void testMatchingIdsAndVersions() throws Exception {
185         List<MavenProject> projects = new ArrayList<>();
186         MavenProject project1 = createProject("groupId", "artifactId", "1.0");
187         projects.add(project1);
188         MavenProject project2 = createProject("groupId", "artifactId", "1.0");
189         projects.add(project2);
190 
191         expectedException.expect(DuplicateProjectException.class);
192         expectedException.reportMissingExceptionWithMessage("Duplicate projects should fail");
193 
194         new ProjectSorter(projects).getSortedProjects();
195     }
196 
197     @Test
198     public void testMatchingIdsAndDifferentVersions() throws Exception {
199         List<MavenProject> projects = new ArrayList<>();
200         MavenProject project1 = createProject("groupId", "artifactId", "1.0");
201         projects.add(project1);
202         MavenProject project2 = createProject("groupId", "artifactId", "2.0");
203         projects.add(project2);
204 
205         projects = new ProjectSorter(projects).getSortedProjects();
206         assertEquals(project1, projects.get(0));
207         assertEquals(project2, projects.get(1));
208     }
209 
210     @Test
211     public void testPluginDependenciesInfluenceSorting() throws Exception {
212         List<MavenProject> projects = new ArrayList<>();
213 
214         MavenProject parentProject = createProject("groupId", "parent", "1.0");
215         projects.add(parentProject);
216 
217         MavenProject declaringProject = createProject("groupId", "declarer", "1.0");
218         declaringProject.setParent(parentProject);
219         declaringProject.getModel().setParent(createParent(parentProject));
220         projects.add(declaringProject);
221 
222         MavenProject pluginLevelDepProject = createProject("groupId", "plugin-level-dep", "1.0");
223         pluginLevelDepProject.setParent(parentProject);
224         pluginLevelDepProject.getModel().setParent(createParent(parentProject));
225         projects.add(pluginLevelDepProject);
226 
227         MavenProject pluginProject = createProject("groupId", "plugin", "1.0");
228         pluginProject.setParent(parentProject);
229         pluginProject.getModel().setParent(createParent(parentProject));
230         projects.add(pluginProject);
231 
232         Plugin plugin = createPlugin(pluginProject);
233 
234         plugin.addDependency(createDependency(pluginLevelDepProject));
235 
236         Build build = declaringProject.getModel().getBuild();
237 
238         build.addPlugin(plugin);
239 
240         projects = new ProjectSorter(projects).getSortedProjects();
241 
242         assertEquals(parentProject, projects.get(0));
243 
244         // the order of these two is non-deterministic, based on when they're added to the reactor.
245         assertThat(projects, hasItem(pluginProject));
246         assertThat(projects, hasItem(pluginLevelDepProject));
247 
248         // the declaring project MUST be listed after the plugin and its plugin-level dep, though.
249         assertEquals(declaringProject, projects.get(3));
250     }
251 
252     @Test
253     public void testPluginDependenciesInfluenceSorting_DeclarationInParent() throws Exception {
254         List<MavenProject> projects = new ArrayList<>();
255 
256         MavenProject parentProject = createProject("groupId", "parent-declarer", "1.0");
257         projects.add(parentProject);
258 
259         MavenProject pluginProject = createProject("groupId", "plugin", "1.0");
260         pluginProject.setParent(parentProject);
261         pluginProject.getModel().setParent(createParent(parentProject));
262         projects.add(pluginProject);
263 
264         MavenProject pluginLevelDepProject = createProject("groupId", "plugin-level-dep", "1.0");
265         pluginLevelDepProject.setParent(parentProject);
266         pluginLevelDepProject.getModel().setParent(createParent(parentProject));
267         projects.add(pluginLevelDepProject);
268 
269         Plugin plugin = createPlugin(pluginProject);
270 
271         plugin.addDependency(createDependency(pluginLevelDepProject));
272 
273         Build build = parentProject.getModel().getBuild();
274 
275         build.addPlugin(plugin);
276 
277         projects = new ProjectSorter(projects).getSortedProjects();
278 
279         assertEquals(parentProject, projects.get(0));
280 
281         // the order of these two is non-deterministic, based on when they're added to the reactor.
282         assertThat(projects, hasItem(pluginProject));
283         assertThat(projects, hasItem(pluginLevelDepProject));
284     }
285 
286     @Test
287     public void testPluginVersionsAreConsidered() throws Exception {
288         List<MavenProject> projects = new ArrayList<>();
289 
290         MavenProject pluginProjectA = createProject("group", "plugin-a", "2.0-SNAPSHOT");
291         projects.add(pluginProjectA);
292         pluginProjectA.getModel().getBuild().addPlugin(createPlugin("group", "plugin-b", "1.0"));
293 
294         MavenProject pluginProjectB = createProject("group", "plugin-b", "2.0-SNAPSHOT");
295         projects.add(pluginProjectB);
296         pluginProjectB.getModel().getBuild().addPlugin(createPlugin("group", "plugin-a", "1.0"));
297 
298         projects = new ProjectSorter(projects).getSortedProjects();
299 
300         assertThat(projects, hasItem(pluginProjectA));
301         assertThat(projects, hasItem(pluginProjectB));
302     }
303 
304     @Test
305     public void testDependencyPrecedesProjectThatUsesSpecificDependencyVersion() throws Exception {
306         List<MavenProject> projects = new ArrayList<>();
307 
308         MavenProject usingProject = createProject("group", "project", "1.0");
309         projects.add(usingProject);
310         usingProject.getModel().addDependency(createDependency("group", "dependency", "1.0"));
311 
312         MavenProject pluginProject = createProject("group", "dependency", "1.0");
313         projects.add(pluginProject);
314 
315         projects = new ProjectSorter(projects).getSortedProjects();
316 
317         assertEquals(pluginProject, projects.get(0));
318         assertEquals(usingProject, projects.get(1));
319     }
320 
321     @Test
322     public void testDependencyPrecedesProjectThatUsesUnresolvedDependencyVersion() throws Exception {
323         List<MavenProject> projects = new ArrayList<>();
324 
325         MavenProject usingProject = createProject("group", "project", "1.0");
326         projects.add(usingProject);
327         usingProject.getModel().addDependency(createDependency("group", "dependency", "[1.0,)"));
328 
329         MavenProject pluginProject = createProject("group", "dependency", "1.0");
330         projects.add(pluginProject);
331 
332         projects = new ProjectSorter(projects).getSortedProjects();
333 
334         assertEquals(pluginProject, projects.get(0));
335         assertEquals(usingProject, projects.get(1));
336     }
337 }