1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package com.jcabi.aether;
31
32 import com.jcabi.log.Logger;
33 import com.jcabi.log.VerboseRunnable;
34 import com.jcabi.log.VerboseThreads;
35 import java.io.File;
36 import java.util.Arrays;
37 import java.util.Collection;
38 import java.util.LinkedList;
39 import java.util.List;
40 import java.util.concurrent.Callable;
41 import java.util.concurrent.CountDownLatch;
42 import java.util.concurrent.ExecutorService;
43 import java.util.concurrent.Executors;
44 import java.util.concurrent.TimeUnit;
45 import org.apache.maven.project.MavenProject;
46 import org.hamcrest.CustomMatcher;
47 import org.hamcrest.Matcher;
48 import org.hamcrest.MatcherAssert;
49 import org.hamcrest.Matchers;
50 import org.junit.Assert;
51 import org.junit.Rule;
52 import org.junit.Test;
53 import org.junit.rules.TemporaryFolder;
54 import org.mockito.Mockito;
55 import org.sonatype.aether.artifact.Artifact;
56 import org.sonatype.aether.repository.Authentication;
57 import org.sonatype.aether.repository.RemoteRepository;
58 import org.sonatype.aether.resolution.DependencyResolutionException;
59 import org.sonatype.aether.util.artifact.DefaultArtifact;
60 import org.sonatype.aether.util.artifact.JavaScopes;
61
62
63
64
65
66
67
68 @SuppressWarnings({ "PMD.DoNotUseThreads", "PMD.TooManyMethods" })
69 public final class AetherTest {
70
71
72
73
74 private static final String AWS_KEY = System.getProperty("aws.key");
75
76
77
78
79 private static final String AWS_SECRET = System.getProperty("aws.secret");
80
81
82
83
84
85 @Rule
86 public final transient TemporaryFolder temp = new TemporaryFolder();
87
88
89
90
91
92 @Test
93 public void findsAndLoadsArtifacts() throws Exception {
94 final File local = this.temp.newFolder();
95 final Aether aether = new Aether(this.project(), local);
96 final Collection<DefaultArtifact> artifacts =
97 new LinkedList<DefaultArtifact>(
98 Arrays.asList(
99 new DefaultArtifact("com.jcabi:jcabi-log:pom:1.0-SNAPSHOT"),
100 new DefaultArtifact("log4j:log4j:jar:1.2.16")
101 )
102 );
103 if (AetherTest.AWS_KEY != null) {
104 artifacts.add(
105 new DefaultArtifact(
106 "com.jcabi.aether-test:parent:pom:1.0"
107 )
108 );
109 }
110 final Matcher<?> matcher = new CustomMatcher<String>("file exists") {
111 @Override
112 public boolean matches(final Object file) {
113 return File.class.cast(file).exists();
114 }
115 };
116 for (final Artifact artifact : artifacts) {
117 MatcherAssert.assertThat(
118 aether.resolve(artifact, JavaScopes.RUNTIME),
119 Matchers.<Artifact>everyItem(
120 Matchers.<Artifact>hasProperty("file", matcher)
121 )
122 );
123 }
124 }
125
126
127
128
129
130 @Test
131 public void resolvesArtifactsInParallelThreads() throws Exception {
132 final File local = this.temp.newFolder();
133 final Aether aether = new Aether(this.project(), local);
134 final int threads = Runtime.getRuntime().availableProcessors() * 5;
135 final Artifact artifact = new DefaultArtifact(
136 "com.jcabi:jcabi-assembly:pom:0.1.10"
137 );
138 final CountDownLatch start = new CountDownLatch(1);
139 final CountDownLatch latch = new CountDownLatch(threads);
140 final Runnable task = new VerboseRunnable(
141 new Callable<Void>() {
142 @Override
143 public Void call() throws Exception {
144 start.await();
145 MatcherAssert.assertThat(
146 aether.resolve(artifact, JavaScopes.RUNTIME),
147 Matchers.not(Matchers.<Artifact>empty())
148 );
149 latch.countDown();
150 return null;
151 }
152 },
153 true
154 );
155 final ExecutorService svc =
156 Executors.newFixedThreadPool(threads, new VerboseThreads());
157 for (int thread = 0; thread < threads; ++thread) {
158 svc.submit(task);
159 }
160 start.countDown();
161 MatcherAssert.assertThat(
162 latch.await(2, TimeUnit.MINUTES),
163 Matchers.is(true)
164 );
165 svc.shutdown();
166 }
167
168
169
170
171
172 @Test(expected = javax.validation.ConstraintViolationException.class)
173 public void rejectsNullMavenProject() throws Exception {
174 final MavenProject project = null;
175 new Aether(project, this.temp.newFolder());
176 }
177
178
179
180
181
182 @Test(expected = javax.validation.ConstraintViolationException.class)
183 public void rejectsNullRepoPath() throws Exception {
184 new Aether(this.project(), null);
185 }
186
187
188
189
190
191 @Test(expected = javax.validation.ConstraintViolationException.class)
192 public void rejectsNullArtifact() throws Exception {
193 new Aether(this.project(), this.temp.newFolder())
194 .resolve(null, JavaScopes.RUNTIME);
195 }
196
197
198
199
200
201 @Test(expected = javax.validation.ConstraintViolationException.class)
202 public void rejectsNullScope() throws Exception {
203 new Aether(this.project(), this.temp.newFolder())
204 .resolve(new DefaultArtifact("junit:junit:4.10"), null);
205 }
206
207
208
209
210
211 @Test(expected = DependencyResolutionException.class)
212 public void throwsWhenArtifactNotFound() throws Exception {
213 new Aether(this.project(), this.temp.newFolder()).resolve(
214 new DefaultArtifact("com.jcabi:jcabi-log:jar:0.0.0"),
215 JavaScopes.COMPILE
216 );
217 }
218
219
220
221
222
223 @Test
224 public void recoversAfterFailure() throws Exception {
225 final Aether aether = new Aether(
226 this.project(),
227 this.temp.newFolder()
228 );
229 try {
230 aether.resolve(
231 new DefaultArtifact("com.jcabi:jcabi-x:jar:0.0.0"),
232 JavaScopes.TEST
233 );
234 Assert.fail("expection expected here");
235 } catch (final DependencyResolutionException ex) {
236 MatcherAssert.assertThat(
237 Logger.format("%[exception]s", ex),
238 Matchers.allOf(
239 Matchers.containsString("oss.sonatype.org"),
240 Matchers.containsString("repo1.maven.org"),
241 Matchers.containsString("without authentication")
242 )
243 );
244 if (AetherTest.AWS_KEY != null) {
245 MatcherAssert.assertThat(
246 Logger.format("%[exception]s ", ex),
247 Matchers.allOf(
248 Matchers.containsString("aether-test.jcabi.com"),
249 Matchers.containsString(AetherTest.AWS_KEY),
250 Matchers.not(
251 Matchers.containsString(AetherTest.AWS_SECRET)
252 )
253 )
254 );
255 }
256 }
257 MatcherAssert.assertThat(
258 aether.resolve(
259 new DefaultArtifact("com.jcabi:jcabi-log:jar:0.1.8"),
260 JavaScopes.RUNTIME
261 ),
262 Matchers.not(Matchers.<Artifact>empty())
263 );
264 }
265
266
267
268
269
270
271 private MavenProject project() throws Exception {
272 final MavenProject project = Mockito.mock(MavenProject.class);
273 final String type = "default";
274 final List<RemoteRepository> repos = new LinkedList<RemoteRepository>(
275 Arrays.asList(
276 new RemoteRepository(
277 "sonatype",
278 type,
279 "https://oss.sonatype.org/content/groups/public"
280 ),
281 new RemoteRepository(
282 "maven-central",
283 type,
284 "http://repo1.maven.org/maven2/"
285 ),
286 new RemoteRepository(
287 "invalid-http-repository",
288 type,
289 "http://repo1.maven.org/invalid-maven-repo/"
290 ),
291 new RemoteRepository(
292 "invalid-s3-repository",
293 type,
294 "s3://invalid-s3-repository/"
295 )
296 )
297 );
298 if (AetherTest.AWS_KEY != null) {
299 final RemoteRepository aws = new RemoteRepository(
300 "aether-test",
301 type,
302 "s3://aether-test.jcabi.com/release"
303 );
304 aws.setAuthentication(
305 new Authentication(
306 AetherTest.AWS_KEY,
307 AetherTest.AWS_SECRET
308 )
309 );
310 repos.add(aws);
311 }
312 Mockito.doReturn(repos).when(project).getRemoteProjectRepositories();
313 return project;
314 }
315
316 }