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.plugin.surefire;
20  
21  import java.io.File;
22  import java.util.Collections;
23  import java.util.Iterator;
24  import java.util.LinkedHashSet;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.Set;
28  import java.util.stream.Collectors;
29  
30  import org.apache.maven.RepositoryUtils;
31  import org.apache.maven.artifact.Artifact;
32  import org.apache.maven.artifact.DefaultArtifact;
33  import org.apache.maven.artifact.handler.DefaultArtifactHandler;
34  import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
35  import org.apache.maven.artifact.versioning.VersionRange;
36  import org.apache.maven.model.Dependency;
37  import org.apache.maven.model.Plugin;
38  import org.apache.maven.plugin.MojoExecutionException;
39  import org.eclipse.aether.RepositorySystem;
40  import org.eclipse.aether.RepositorySystemSession;
41  import org.eclipse.aether.artifact.ArtifactTypeRegistry;
42  import org.eclipse.aether.resolution.ArtifactRequest;
43  import org.eclipse.aether.resolution.ArtifactResult;
44  import org.eclipse.aether.resolution.DependencyRequest;
45  import org.eclipse.aether.resolution.DependencyResolutionException;
46  import org.eclipse.aether.resolution.DependencyResult;
47  import org.junit.Rule;
48  import org.junit.Test;
49  import org.junit.rules.ExpectedException;
50  import org.mockito.ArgumentCaptor;
51  
52  import static java.util.Collections.singletonList;
53  import static java.util.Collections.singletonMap;
54  import static org.apache.maven.artifact.versioning.VersionRange.createFromVersionSpec;
55  import static org.apache.maven.plugin.surefire.SurefireDependencyResolver.PROVIDER_GROUP_ID;
56  import static org.assertj.core.api.Assertions.assertThat;
57  import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
58  import static org.mockito.ArgumentMatchers.any;
59  import static org.mockito.ArgumentMatchers.eq;
60  import static org.mockito.Mockito.mock;
61  import static org.mockito.Mockito.verify;
62  import static org.mockito.Mockito.verifyNoMoreInteractions;
63  import static org.mockito.Mockito.when;
64  
65  /**
66   *
67   */
68  public class SurefireDependencyResolverTest {
69      @Rule
70      public final ExpectedException expectedException = ExpectedException.none();
71  
72      @Test
73      public void shouldNotBeWithinRangeNullArtifact() {
74          boolean result = SurefireDependencyResolver.isWithinVersionSpec(null, "[4.7,)");
75          assertThat(result).isFalse();
76      }
77  
78      @Test
79      public void shouldNotBeWithinRange() throws InvalidVersionSpecificationException {
80          Artifact api = createArtifact("junit", "junit", "4.6");
81          boolean result = SurefireDependencyResolver.isWithinVersionSpec(api, "[4.7,)");
82          assertThat(result).isFalse();
83      }
84  
85      @Test
86      public void shouldBeWithinRange() throws InvalidVersionSpecificationException {
87          Artifact api = createArtifact("junit", "junit", "4.7");
88          boolean result = SurefireDependencyResolver.isWithinVersionSpec(api, "[4.7,)");
89          assertThat(result).isTrue();
90      }
91  
92      @Test
93      public void shouldBeFarWithinRange() throws InvalidVersionSpecificationException {
94          Artifact api = createArtifact("junit", "junit", "4.13");
95          boolean result = SurefireDependencyResolver.isWithinVersionSpec(api, "[4.7,)");
96          assertThat(result).isTrue();
97      }
98  
99      @Test
100     public void shouldBeFailWithinRange() throws InvalidVersionSpecificationException {
101         Artifact api = createArtifact("junit", "junit", "");
102         expectedException.expect(RuntimeException.class);
103         expectedException.expectMessage("Bug in plugin. Please report with stacktrace");
104         SurefireDependencyResolver.isWithinVersionSpec(api, "[4.7,)");
105     }
106 
107     @Test
108     public void testResolveArtifact()
109             throws InvalidVersionSpecificationException, MojoExecutionException, DependencyResolutionException {
110 
111         Artifact provider = createArtifact("surefire-junit-platform");
112         RepositorySystem repositorySystem = mock(RepositorySystem.class);
113         RepositorySystemSession session = mock(RepositorySystemSession.class);
114         ArgumentCaptor<DependencyRequest> requestCaptor = ArgumentCaptor.forClass(DependencyRequest.class);
115 
116         DependencyResult result = new DependencyResult(new DependencyRequest());
117         when(repositorySystem.resolveDependencies(eq(session), requestCaptor.capture()))
118                 .thenReturn(result);
119 
120         SurefireDependencyResolver surefireDependencyResolver = new SurefireDependencyResolver(repositorySystem);
121         surefireDependencyResolver.resolveArtifacts(session, Collections.emptyList(), provider);
122 
123         DependencyRequest value = requestCaptor.getValue();
124         assertThat(value).isNotNull();
125         org.eclipse.aether.graph.Dependency requestDependency =
126                 value.getCollectRequest().getRoot();
127         assertThat(requestDependency.getArtifact().getGroupId()).isEqualTo(provider.getGroupId());
128         assertThat(requestDependency.getArtifact().getArtifactId()).isEqualTo(provider.getArtifactId());
129         assertThat(requestDependency.getArtifact().getVersion()).isEqualTo(provider.getVersion());
130         assertThat(requestDependency.getArtifact().getExtension()).isEqualTo(provider.getType());
131     }
132 
133     @Test
134     public void testGetProviderClasspath() throws Exception {
135 
136         Artifact commonJunit4 = createArtifact("common-junit4");
137         Artifact api = createArtifact("surefire-api");
138         Artifact provider = createArtifact("surefire-junit-platform");
139         Artifact ext = createArtifact("org.apiguardian", "apiguardian-api");
140         Artifact logger = createArtifact("surefire-logger-api");
141 
142         Set<Artifact> providerArtifacts = new LinkedHashSet<>();
143         providerArtifacts.add(commonJunit4);
144         providerArtifacts.add(api);
145         providerArtifacts.add(provider);
146         providerArtifacts.add(ext);
147         providerArtifacts.add(logger);
148 
149         List<ArtifactResult> artifactResults = providerArtifacts.stream()
150                 .map(RepositoryUtils::toArtifact)
151                 .map(a -> new ArtifactResult(new ArtifactRequest()).setArtifact(a))
152                 .collect(Collectors.toList());
153 
154         DependencyResult result = new DependencyResult(new DependencyRequest());
155         result.setArtifactResults(artifactResults);
156 
157         RepositorySystem repositorySystem = mock(RepositorySystem.class);
158         RepositorySystemSession session = mock(RepositorySystemSession.class);
159 
160         when(session.getArtifactTypeRegistry()).thenReturn(mock(ArtifactTypeRegistry.class));
161         when(repositorySystem.resolveDependencies(eq(session), any())).thenReturn(result);
162 
163         SurefireDependencyResolver surefireDependencyResolver = new SurefireDependencyResolver(repositorySystem);
164         Set<Artifact> classpath = surefireDependencyResolver.getProviderClasspath(
165                 session, Collections.emptyList(), "surefire-junit-platform", "1");
166 
167         assertThat(classpath).hasSize(5);
168 
169         Iterator<Artifact> it = classpath.iterator();
170 
171         // result should be ordered
172         assertThat(it.next()).isEqualTo(provider);
173         assertThat(it.next()).isEqualTo(api);
174         assertThat(it.next()).isEqualTo(logger);
175         assertThat(it.next()).isEqualTo(commonJunit4);
176         assertThat(it.next()).isEqualTo(ext);
177     }
178 
179     @Test
180     public void testGetProviderClasspathShouldPropagateTheResolutionException() throws Exception {
181 
182         RepositorySystem repositorySystem = mock(RepositorySystem.class);
183         RepositorySystemSession session = mock(RepositorySystemSession.class);
184         when(session.getArtifactTypeRegistry()).thenReturn(mock(ArtifactTypeRegistry.class));
185 
186         DependencyResolutionException dependencyResolutionException =
187                 new DependencyResolutionException(new DependencyResult(new DependencyRequest()), new Exception());
188         when(repositorySystem.resolveDependencies(eq(session), any())).thenThrow(dependencyResolutionException);
189 
190         SurefireDependencyResolver surefireDependencyResolver = new SurefireDependencyResolver(repositorySystem);
191 
192         assertThatThrownBy(() -> surefireDependencyResolver.getProviderClasspath(
193                         session, Collections.emptyList(), "surefire-junit-platform", "1"))
194                 .isInstanceOf(MojoExecutionException.class)
195                 .hasCause(dependencyResolutionException);
196     }
197 
198     @Test
199     public void testResolvePluginDependencies() throws Exception {
200         Dependency providerAsDependency = new Dependency();
201         providerAsDependency.setGroupId(PROVIDER_GROUP_ID);
202         providerAsDependency.setArtifactId("surefire-shadefire");
203         providerAsDependency.setVersion("1");
204 
205         Artifact providerAsArtifact = createArtifact("surefire-shadefire");
206 
207         Plugin plugin = mock(Plugin.class);
208         when(plugin.getDependencies()).thenReturn(singletonList(providerAsDependency));
209 
210         RepositorySystem repositorySystem = mock(RepositorySystem.class);
211         RepositorySystemSession session = mock(RepositorySystemSession.class);
212         when(session.getArtifactTypeRegistry()).thenReturn(mock(ArtifactTypeRegistry.class));
213 
214         ArtifactResult artifactResult =
215                 new ArtifactResult(new ArtifactRequest().setArtifact(RepositoryUtils.toArtifact(providerAsArtifact)));
216         artifactResult.setArtifact(RepositoryUtils.toArtifact(providerAsArtifact));
217         DependencyResult result = new DependencyResult(new DependencyRequest());
218         result.setArtifactResults(Collections.singletonList(artifactResult));
219 
220         when(repositorySystem.resolveDependencies(eq(session), any())).thenReturn(result);
221 
222         Map<String, Artifact> pluginResolvedDependencies =
223                 singletonMap(PROVIDER_GROUP_ID + ":surefire-shadefire", providerAsArtifact);
224 
225         SurefireDependencyResolver surefireDependencyResolver = new SurefireDependencyResolver(repositorySystem);
226 
227         Map<String, Artifact> providers = surefireDependencyResolver.resolvePluginDependencies(
228                 session, Collections.emptyList(), plugin, pluginResolvedDependencies);
229 
230         assertThat(providers.values()).hasSize(1).containsOnly(providerAsArtifact);
231 
232         verify(repositorySystem).resolveDependencies(eq(session), any());
233         verifyNoMoreInteractions(repositorySystem);
234     }
235 
236     private static Artifact createArtifact(String artifactId) throws InvalidVersionSpecificationException {
237         return createArtifact(PROVIDER_GROUP_ID, artifactId);
238     }
239 
240     private static Artifact createArtifact(String groupId, String artifactId)
241             throws InvalidVersionSpecificationException {
242         return createArtifact(groupId, artifactId, "1");
243     }
244 
245     private static Artifact createArtifact(String groupId, String artifactId, String version)
246             throws InvalidVersionSpecificationException {
247         VersionRange versionSpec = createFromVersionSpec(version);
248         DefaultArtifact defaultArtifact = new DefaultArtifact(
249                 groupId, artifactId, versionSpec, null, "jar", null, new DefaultArtifactHandler("jar"));
250         defaultArtifact.setFile(new File(""));
251         return defaultArtifact;
252     }
253 }