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.jupiter.api.Test;
33  
34  import static org.hamcrest.MatcherAssert.assertThat;
35  import static org.hamcrest.Matchers.hasItem;
36  import static org.junit.jupiter.api.Assertions.assertEquals;
37  import static org.junit.jupiter.api.Assertions.assertThrows;
38  
39  /**
40   * Test sorting projects by dependencies.
41   *
42   */
43  class ProjectSorterTest {
44      private Parent createParent(MavenProject project) {
45          return createParent(project.getGroupId(), project.getArtifactId(), project.getVersion());
46      }
47  
48      private Parent createParent(String groupId, String artifactId, String version) {
49          Parent plugin = new Parent();
50          plugin.setGroupId(groupId);
51          plugin.setArtifactId(artifactId);
52          plugin.setVersion(version);
53          return plugin;
54      }
55  
56      private Dependency createDependency(MavenProject project) {
57          return createDependency(project.getGroupId(), project.getArtifactId(), project.getVersion());
58      }
59  
60      private Dependency createDependency(String groupId, String artifactId, String version) {
61          Dependency dependency = new Dependency();
62          dependency.setGroupId(groupId);
63          dependency.setArtifactId(artifactId);
64          dependency.setVersion(version);
65          return dependency;
66      }
67  
68      private Plugin createPlugin(MavenProject project) {
69          return createPlugin(project.getGroupId(), project.getArtifactId(), project.getVersion());
70      }
71  
72      private Plugin createPlugin(String groupId, String artifactId, String version) {
73          Plugin plugin = new Plugin();
74          plugin.setGroupId(groupId);
75          plugin.setArtifactId(artifactId);
76          plugin.setVersion(version);
77          return plugin;
78      }
79  
80      private Extension createExtension(String groupId, String artifactId, String version) {
81          Extension extension = new Extension();
82          extension.setGroupId(groupId);
83          extension.setArtifactId(artifactId);
84          extension.setVersion(version);
85          return extension;
86      }
87  
88      private static MavenProject createProject(String groupId, String artifactId, String version) {
89          Model model = new Model();
90          model.setGroupId(groupId);
91          model.setArtifactId(artifactId);
92          model.setVersion(version);
93          model.setBuild(new Build());
94          return new MavenProject(model);
95      }
96  
97      @Test
98      void testShouldNotFailWhenPluginDepReferencesCurrentProject() throws Exception {
99          MavenProject project = createProject("group", "artifact", "1.0");
100 
101         Build build = project.getModel().getBuild();
102 
103         Plugin plugin = createPlugin("other.group", "other-artifact", "1.0");
104 
105         Dependency dep = createDependency("group", "artifact", "1.0");
106 
107         plugin.addDependency(dep);
108 
109         build.addPlugin(plugin);
110 
111         new ProjectSorter(Collections.singletonList(project));
112     }
113 
114     @Test
115     void testShouldNotFailWhenManagedPluginDepReferencesCurrentProject() throws Exception {
116         MavenProject project = createProject("group", "artifact", "1.0");
117 
118         Build build = project.getModel().getBuild();
119 
120         PluginManagement pMgmt = new PluginManagement();
121 
122         Plugin plugin = createPlugin("other.group", "other-artifact", "1.0");
123 
124         Dependency dep = createDependency("group", "artifact", "1.0");
125 
126         plugin.addDependency(dep);
127 
128         pMgmt.addPlugin(plugin);
129 
130         build.setPluginManagement(pMgmt);
131 
132         new ProjectSorter(Collections.singletonList(project));
133     }
134 
135     @Test
136     void testShouldNotFailWhenProjectReferencesNonExistentProject() throws Exception {
137         MavenProject project = createProject("group", "artifact", "1.0");
138 
139         Build build = project.getModel().getBuild();
140 
141         Extension extension = createExtension("other.group", "other-artifact", "1.0");
142 
143         build.addExtension(extension);
144 
145         new ProjectSorter(Collections.singletonList(project));
146     }
147 
148     @Test
149     void testMatchingArtifactIdsDifferentGroupIds() throws Exception {
150         List<MavenProject> projects = new ArrayList<>();
151         MavenProject project1 = createProject("groupId1", "artifactId", "1.0");
152         projects.add(project1);
153         MavenProject project2 = createProject("groupId2", "artifactId", "1.0");
154         projects.add(project2);
155         project1.getDependencies().add(createDependency(project2));
156 
157         projects = new ProjectSorter(projects).getSortedProjects();
158 
159         assertEquals(project2, projects.get(0));
160         assertEquals(project1, projects.get(1));
161     }
162 
163     @Test
164     void testMatchingGroupIdsDifferentArtifactIds() throws Exception {
165         List<MavenProject> projects = new ArrayList<>();
166         MavenProject project1 = createProject("groupId", "artifactId1", "1.0");
167         projects.add(project1);
168         MavenProject project2 = createProject("groupId", "artifactId2", "1.0");
169         projects.add(project2);
170         project1.getDependencies().add(createDependency(project2));
171 
172         projects = new ProjectSorter(projects).getSortedProjects();
173 
174         assertEquals(project2, projects.get(0));
175         assertEquals(project1, projects.get(1));
176     }
177 
178     @Test
179     void testMatchingIdsAndVersions() throws Exception {
180         List<MavenProject> projects = new ArrayList<>();
181         MavenProject project1 = createProject("groupId", "artifactId", "1.0");
182         projects.add(project1);
183         MavenProject project2 = createProject("groupId", "artifactId", "1.0");
184         projects.add(project2);
185 
186         assertThrows(
187                 DuplicateProjectException.class,
188                 () -> new ProjectSorter(projects).getSortedProjects(),
189                 "Duplicate projects should fail");
190     }
191 
192     @Test
193     void testMatchingIdsAndDifferentVersions() throws Exception {
194         List<MavenProject> projects = new ArrayList<>();
195         MavenProject project1 = createProject("groupId", "artifactId", "1.0");
196         projects.add(project1);
197         MavenProject project2 = createProject("groupId", "artifactId", "2.0");
198         projects.add(project2);
199 
200         projects = new ProjectSorter(projects).getSortedProjects();
201         assertEquals(project1, projects.get(0));
202         assertEquals(project2, projects.get(1));
203     }
204 
205     @Test
206     void testPluginDependenciesInfluenceSorting() throws Exception {
207         List<MavenProject> projects = new ArrayList<>();
208 
209         MavenProject parentProject = createProject("groupId", "parent", "1.0");
210         projects.add(parentProject);
211 
212         MavenProject declaringProject = createProject("groupId", "declarer", "1.0");
213         declaringProject.setParent(parentProject);
214         declaringProject.getModel().setParent(createParent(parentProject));
215         projects.add(declaringProject);
216 
217         MavenProject pluginLevelDepProject = createProject("groupId", "plugin-level-dep", "1.0");
218         pluginLevelDepProject.setParent(parentProject);
219         pluginLevelDepProject.getModel().setParent(createParent(parentProject));
220         projects.add(pluginLevelDepProject);
221 
222         MavenProject pluginProject = createProject("groupId", "plugin", "1.0");
223         pluginProject.setParent(parentProject);
224         pluginProject.getModel().setParent(createParent(parentProject));
225         projects.add(pluginProject);
226 
227         Plugin plugin = createPlugin(pluginProject);
228 
229         plugin.addDependency(createDependency(pluginLevelDepProject));
230 
231         Build build = declaringProject.getModel().getBuild();
232 
233         build.addPlugin(plugin);
234 
235         declaringProject.getModel().setBuild(build);
236 
237         projects = new ProjectSorter(projects).getSortedProjects();
238 
239         assertEquals(parentProject, projects.get(0));
240 
241         // the order of these two is non-deterministic, based on when they're added to the reactor.
242         assertThat(projects, hasItem(pluginProject));
243         assertThat(projects, hasItem(pluginLevelDepProject));
244 
245         // the declaring project MUST be listed after the plugin and its plugin-level dep, though.
246         assertEquals(declaringProject, projects.get(3));
247     }
248 
249     @Test
250     void testPluginDependenciesInfluenceSorting_DeclarationInParent() throws Exception {
251         List<MavenProject> projects = new ArrayList<>();
252 
253         MavenProject parentProject = createProject("groupId", "parent-declarer", "1.0");
254         projects.add(parentProject);
255 
256         MavenProject pluginProject = createProject("groupId", "plugin", "1.0");
257         pluginProject.setParent(parentProject);
258         pluginProject.getModel().setParent(createParent(parentProject));
259         projects.add(pluginProject);
260 
261         MavenProject pluginLevelDepProject = createProject("groupId", "plugin-level-dep", "1.0");
262         pluginLevelDepProject.setParent(parentProject);
263         pluginLevelDepProject.getModel().setParent(createParent(parentProject));
264         projects.add(pluginLevelDepProject);
265 
266         Plugin plugin = createPlugin(pluginProject);
267 
268         plugin.addDependency(createDependency(pluginLevelDepProject));
269 
270         Build build = parentProject.getModel().getBuild();
271 
272         build.addPlugin(plugin);
273 
274         projects = new ProjectSorter(projects).getSortedProjects();
275 
276         assertEquals(parentProject, projects.get(0));
277 
278         // the order of these two is non-deterministic, based on when they're added to the reactor.
279         assertThat(projects, hasItem(pluginProject));
280         assertThat(projects, hasItem(pluginLevelDepProject));
281     }
282 
283     @Test
284     void testPluginVersionsAreConsidered() throws Exception {
285         List<MavenProject> projects = new ArrayList<>();
286 
287         MavenProject pluginProjectA = createProject("group", "plugin-a", "2.0-SNAPSHOT");
288         projects.add(pluginProjectA);
289         pluginProjectA.getModel().getBuild().addPlugin(createPlugin("group", "plugin-b", "1.0"));
290 
291         MavenProject pluginProjectB = createProject("group", "plugin-b", "2.0-SNAPSHOT");
292         projects.add(pluginProjectB);
293         pluginProjectB.getModel().getBuild().addPlugin(createPlugin("group", "plugin-a", "1.0"));
294 
295         projects = new ProjectSorter(projects).getSortedProjects();
296 
297         assertThat(projects, hasItem(pluginProjectA));
298         assertThat(projects, hasItem(pluginProjectB));
299     }
300 
301     @Test
302     void testDependencyPrecedesProjectThatUsesSpecificDependencyVersion() throws Exception {
303         List<MavenProject> projects = new ArrayList<>();
304 
305         MavenProject usingProject = createProject("group", "project", "1.0");
306         projects.add(usingProject);
307         usingProject.getModel().addDependency(createDependency("group", "dependency", "1.0"));
308 
309         MavenProject pluginProject = createProject("group", "dependency", "1.0");
310         projects.add(pluginProject);
311 
312         projects = new ProjectSorter(projects).getSortedProjects();
313 
314         assertEquals(pluginProject, projects.get(0));
315         assertEquals(usingProject, projects.get(1));
316     }
317 
318     @Test
319     void testDependencyPrecedesProjectThatUsesUnresolvedDependencyVersion() throws Exception {
320         List<MavenProject> projects = new ArrayList<>();
321 
322         MavenProject usingProject = createProject("group", "project", "1.0");
323         projects.add(usingProject);
324         usingProject.getModel().addDependency(createDependency("group", "dependency", "[1.0,)"));
325 
326         MavenProject pluginProject = createProject("group", "dependency", "1.0");
327         projects.add(pluginProject);
328 
329         projects = new ProjectSorter(projects).getSortedProjects();
330 
331         assertEquals(pluginProject, projects.get(0));
332         assertEquals(usingProject, projects.get(1));
333     }
334 }