1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.aether.transport.wagon;
20
21 import java.io.File;
22 import java.net.URI;
23 import java.nio.charset.StandardCharsets;
24 import java.util.Map;
25 import java.util.UUID;
26
27 import org.apache.maven.wagon.ResourceDoesNotExistException;
28 import org.apache.maven.wagon.TransferFailedException;
29 import org.apache.maven.wagon.Wagon;
30 import org.eclipse.aether.ConfigurationProperties;
31 import org.eclipse.aether.DefaultRepositorySystemSession;
32 import org.eclipse.aether.internal.test.util.TestFileUtils;
33 import org.eclipse.aether.internal.test.util.TestUtils;
34 import org.eclipse.aether.repository.Authentication;
35 import org.eclipse.aether.repository.Proxy;
36 import org.eclipse.aether.repository.RemoteRepository;
37 import org.eclipse.aether.spi.connector.transport.GetTask;
38 import org.eclipse.aether.spi.connector.transport.PeekTask;
39 import org.eclipse.aether.spi.connector.transport.PutTask;
40 import org.eclipse.aether.spi.connector.transport.Transporter;
41 import org.eclipse.aether.spi.connector.transport.TransporterFactory;
42 import org.eclipse.aether.spi.io.PathProcessorSupport;
43 import org.eclipse.aether.transfer.NoTransporterException;
44 import org.eclipse.aether.transfer.TransferCancelledException;
45 import org.eclipse.aether.util.repository.AuthenticationBuilder;
46 import org.junit.jupiter.api.AfterEach;
47 import org.junit.jupiter.api.BeforeEach;
48 import org.junit.jupiter.api.Test;
49
50 import static org.eclipse.aether.transport.wagon.WagonTransporterConfigurationKeys.CONFIG_PROP_CONFIG;
51 import static org.junit.jupiter.api.Assertions.*;
52
53
54
55 public abstract class AbstractWagonTransporterTest {
56
57 private DefaultRepositorySystemSession session;
58
59 private TransporterFactory factory;
60
61 private Transporter transporter;
62
63 private String id;
64
65 private Map<String, String> fs;
66
67 protected abstract Wagon newWagon();
68
69 private RemoteRepository newRepo(String url) {
70 return new RemoteRepository.Builder("test", "default", url).build();
71 }
72
73 private void newTransporter(String url) throws Exception {
74 newTransporter(newRepo(url));
75 }
76
77 private void newTransporter(RemoteRepository repo) throws Exception {
78 if (transporter != null) {
79 transporter.close();
80 transporter = null;
81 }
82 transporter = factory.newInstance(session, repo);
83 }
84
85 @BeforeEach
86 void setUp() throws Exception {
87 session = TestUtils.newSession();
88 factory = new WagonTransporterFactory(
89 new WagonProvider() {
90 public Wagon lookup(String roleHint) {
91 if ("mem".equalsIgnoreCase(roleHint)) {
92 return newWagon();
93 }
94 throw new IllegalArgumentException("unknown wagon role: " + roleHint);
95 }
96
97 public void release(Wagon wagon) {}
98 },
99 new WagonConfigurator() {
100 public void configure(Wagon wagon, Object configuration) {
101 ((Configurable) wagon).setConfiguration(configuration);
102 }
103 },
104 new PathProcessorSupport());
105 id = UUID.randomUUID().toString().replace("-", "");
106 fs = MemWagonUtils.getFilesystem(id);
107 fs.put("file.txt", "test");
108 fs.put("empty.txt", "");
109 fs.put("some space.txt", "space");
110 newTransporter("mem://" + id);
111 }
112
113 @AfterEach
114 void tearDown() {
115 if (transporter != null) {
116 transporter.close();
117 transporter = null;
118 }
119 factory = null;
120 session = null;
121 }
122
123 @Test
124 void testClassify() {
125 assertEquals(Transporter.ERROR_OTHER, transporter.classify(new TransferFailedException("test")));
126 assertEquals(Transporter.ERROR_NOT_FOUND, transporter.classify(new ResourceDoesNotExistException("test")));
127 }
128
129 @Test
130 void testPeek() throws Exception {
131 transporter.peek(new PeekTask(URI.create("file.txt")));
132 }
133
134 @Test
135 void testPeek_NotFound() throws Exception {
136 try {
137 transporter.peek(new PeekTask(URI.create("missing.txt")));
138 fail("Expected error");
139 } catch (ResourceDoesNotExistException e) {
140 assertEquals(Transporter.ERROR_NOT_FOUND, transporter.classify(e));
141 }
142 }
143
144 @Test
145 void testPeek_Closed() throws Exception {
146 transporter.close();
147 try {
148 transporter.peek(new PeekTask(URI.create("missing.txt")));
149 fail("Expected error");
150 } catch (IllegalStateException e) {
151 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
152 }
153 }
154
155 @Test
156 void testGet_ToMemory() throws Exception {
157 RecordingTransportListener listener = new RecordingTransportListener();
158 GetTask task = new GetTask(URI.create("file.txt")).setListener(listener);
159 transporter.get(task);
160 assertEquals("test", task.getDataString());
161 assertEquals(0L, listener.dataOffset);
162 assertEquals(4L, listener.dataLength);
163 assertEquals(1, listener.startedCount);
164 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
165 assertEquals(task.getDataString(), new String(listener.baos.toByteArray(), StandardCharsets.UTF_8));
166 }
167
168 @Test
169 void testGet_ToFile() throws Exception {
170 File file = TestFileUtils.createTempFile("failure");
171 RecordingTransportListener listener = new RecordingTransportListener();
172 GetTask task = new GetTask(URI.create("file.txt")).setDataFile(file).setListener(listener);
173 transporter.get(task);
174 assertEquals("test", TestFileUtils.readString(file));
175 assertEquals(0L, listener.dataOffset);
176 assertEquals(4L, listener.dataLength);
177 assertEquals(1, listener.startedCount);
178 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
179 assertEquals("test", new String(listener.baos.toByteArray(), StandardCharsets.UTF_8));
180 }
181
182 @Test
183 void testGet_EmptyResource() throws Exception {
184 File file = TestFileUtils.createTempFile("failure");
185 assertTrue(file.delete() && !file.exists());
186 RecordingTransportListener listener = new RecordingTransportListener();
187 GetTask task = new GetTask(URI.create("empty.txt")).setDataFile(file).setListener(listener);
188 transporter.get(task);
189 assertEquals("", TestFileUtils.readString(file));
190 assertEquals(0L, listener.dataOffset);
191 assertEquals(0L, listener.dataLength);
192 assertEquals(1, listener.startedCount);
193 assertEquals(0, listener.progressedCount);
194 assertEquals("", new String(listener.baos.toByteArray(), StandardCharsets.UTF_8));
195 }
196
197 @Test
198 void testGet_EncodedResourcePath() throws Exception {
199 GetTask task = new GetTask(URI.create("some%20space.txt"));
200 transporter.get(task);
201 assertEquals("space", task.getDataString());
202 }
203
204 @Test
205 void testGet_FileHandleLeak() throws Exception {
206 for (int i = 0; i < 100; i++) {
207 File file = TestFileUtils.createTempFile("failure");
208 transporter.get(new GetTask(URI.create("file.txt")).setDataFile(file));
209 assertTrue(file.delete(), i + ", " + file.getAbsolutePath());
210 }
211 }
212
213 @Test
214 void testGet_NotFound() throws Exception {
215 try {
216 transporter.get(new GetTask(URI.create("missing.txt")));
217 fail("Expected error");
218 } catch (ResourceDoesNotExistException e) {
219 assertEquals(Transporter.ERROR_NOT_FOUND, transporter.classify(e));
220 }
221 }
222
223 @Test
224 void testGet_Closed() throws Exception {
225 transporter.close();
226 try {
227 transporter.get(new GetTask(URI.create("file.txt")));
228 fail("Expected error");
229 } catch (IllegalStateException e) {
230 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
231 }
232 }
233
234 @Test
235 void testGet_StartCancelled() throws Exception {
236 RecordingTransportListener listener = new RecordingTransportListener();
237 listener.cancelStart = true;
238 GetTask task = new GetTask(URI.create("file.txt")).setListener(listener);
239 transporter.get(task);
240 assertEquals(1, listener.startedCount);
241 }
242
243 @Test
244 void testGet_ProgressCancelled() throws Exception {
245 RecordingTransportListener listener = new RecordingTransportListener();
246 listener.cancelProgress = true;
247 GetTask task = new GetTask(URI.create("file.txt")).setListener(listener);
248 try {
249 transporter.get(task);
250 fail("Expected error");
251 } catch (TransferCancelledException e) {
252 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
253 }
254 assertEquals(0L, listener.dataOffset);
255 assertEquals(4L, listener.dataLength);
256 assertEquals(1, listener.startedCount);
257 assertEquals(1, listener.progressedCount);
258 }
259
260 @Test
261 void testPut_FromMemory() throws Exception {
262 RecordingTransportListener listener = new RecordingTransportListener();
263 PutTask task = new PutTask(URI.create("file.txt")).setListener(listener).setDataString("upload");
264 transporter.put(task);
265 assertEquals(0L, listener.dataOffset);
266 assertEquals(6L, listener.dataLength);
267 assertEquals(1, listener.startedCount);
268 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
269 assertEquals("upload", fs.get("file.txt"));
270 }
271
272 @Test
273 void testPut_FromFile() throws Exception {
274 File file = TestFileUtils.createTempFile("upload");
275 RecordingTransportListener listener = new RecordingTransportListener();
276 PutTask task = new PutTask(URI.create("file.txt")).setListener(listener).setDataFile(file);
277 transporter.put(task);
278 assertEquals(0L, listener.dataOffset);
279 assertEquals(6L, listener.dataLength);
280 assertEquals(1, listener.startedCount);
281 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
282 assertEquals("upload", fs.get("file.txt"));
283 }
284
285 @Test
286 void testPut_EmptyResource() throws Exception {
287 RecordingTransportListener listener = new RecordingTransportListener();
288 PutTask task = new PutTask(URI.create("file.txt")).setListener(listener);
289 transporter.put(task);
290 assertEquals(0L, listener.dataOffset);
291 assertEquals(0L, listener.dataLength);
292 assertEquals(1, listener.startedCount);
293 assertEquals(0, listener.progressedCount);
294 assertEquals("", fs.get("file.txt"));
295 }
296
297 @Test
298 void testPut_NonExistentParentDir() throws Exception {
299 RecordingTransportListener listener = new RecordingTransportListener();
300 PutTask task = new PutTask(URI.create("dir/sub/dir/file.txt"))
301 .setListener(listener)
302 .setDataString("upload");
303 transporter.put(task);
304 assertEquals(0L, listener.dataOffset);
305 assertEquals(6L, listener.dataLength);
306 assertEquals(1, listener.startedCount);
307 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
308 assertEquals("upload", fs.get("dir/sub/dir/file.txt"));
309 }
310
311 @Test
312 void testPut_EncodedResourcePath() throws Exception {
313 RecordingTransportListener listener = new RecordingTransportListener();
314 PutTask task = new PutTask(URI.create("some%20space.txt"))
315 .setListener(listener)
316 .setDataString("OK");
317 transporter.put(task);
318 assertEquals(0L, listener.dataOffset);
319 assertEquals(2L, listener.dataLength);
320 assertEquals(1, listener.startedCount);
321 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
322 assertEquals("OK", fs.get("some space.txt"));
323 }
324
325 @Test
326 void testPut_FileHandleLeak() throws Exception {
327 for (int i = 0; i < 100; i++) {
328 File src = TestFileUtils.createTempFile("upload");
329 transporter.put(new PutTask(URI.create("file.txt")).setDataFile(src));
330 assertTrue(src.delete(), i + ", " + src.getAbsolutePath());
331 }
332 }
333
334 @Test
335 void testPut_Closed() throws Exception {
336 transporter.close();
337 try {
338 transporter.put(new PutTask(URI.create("missing.txt")));
339 fail("Expected error");
340 } catch (IllegalStateException e) {
341 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
342 }
343 }
344
345 @Test
346 void testPut_StartCancelled() throws Exception {
347 RecordingTransportListener listener = new RecordingTransportListener();
348 listener.cancelStart = true;
349 PutTask task = new PutTask(URI.create("file.txt")).setListener(listener).setDataString("upload");
350 transporter.put(task);
351 assertEquals(1, listener.startedCount);
352 }
353
354 @Test
355 void testPut_ProgressCancelled() throws Exception {
356 RecordingTransportListener listener = new RecordingTransportListener();
357 listener.cancelProgress = true;
358 PutTask task = new PutTask(URI.create("file.txt")).setListener(listener).setDataString("upload");
359 try {
360 transporter.put(task);
361 fail("Expected error");
362 } catch (TransferCancelledException e) {
363 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
364 }
365 assertEquals(0L, listener.dataOffset);
366 assertEquals(6L, listener.dataLength);
367 assertEquals(1, listener.startedCount);
368 assertEquals(1, listener.progressedCount);
369 }
370
371 @Test
372 void testInit_BadProtocol() {
373 assertThrows(NoTransporterException.class, () -> newTransporter("bad:/void"));
374 }
375
376 @Test
377 void testInit_CaseInsensitiveProtocol() throws Exception {
378 newTransporter("mem:/void");
379 newTransporter("MEM:/void");
380 newTransporter("mEm:/void");
381 }
382
383 @Test
384 void testInit_Configuration() throws Exception {
385 session.setConfigProperty(CONFIG_PROP_CONFIG + ".test", "passed");
386 newTransporter("mem://" + id + "?config=passed");
387 transporter.peek(new PeekTask(URI.create("file.txt")));
388 }
389
390 @Test
391 void testInit_UserAgent() throws Exception {
392 session.setConfigProperty(ConfigurationProperties.USER_AGENT, "Test/1.0");
393 newTransporter("mem://" + id + "?userAgent=Test/1.0");
394 transporter.peek(new PeekTask(URI.create("file.txt")));
395 }
396
397 @Test
398 void testInit_Timeout() throws Exception {
399 session.setConfigProperty(ConfigurationProperties.REQUEST_TIMEOUT, "12345678");
400 newTransporter("mem://" + id + "?requestTimeout=12345678");
401 transporter.peek(new PeekTask(URI.create("file.txt")));
402 }
403
404 @Test
405 void testInit_ServerAuth() throws Exception {
406 String url = "mem://" + id + "?serverUsername=testuser&serverPassword=testpass"
407 + "&serverPrivateKey=testkey&serverPassphrase=testphrase";
408 Authentication auth = new AuthenticationBuilder()
409 .addUsername("testuser")
410 .addPassword("testpass")
411 .addPrivateKey("testkey", "testphrase")
412 .build();
413 RemoteRepository repo = new RemoteRepository.Builder("test", "default", url)
414 .setAuthentication(auth)
415 .build();
416 newTransporter(repo);
417 transporter.peek(new PeekTask(URI.create("file.txt")));
418 }
419
420 @Test
421 void testInit_Proxy() throws Exception {
422 String url = "mem://" + id + "?proxyHost=testhost&proxyPort=8888";
423 RemoteRepository repo = new RemoteRepository.Builder("test", "default", url)
424 .setProxy(new Proxy("http", "testhost", 8888))
425 .build();
426 newTransporter(repo);
427 transporter.peek(new PeekTask(URI.create("file.txt")));
428 }
429
430 @Test
431 void testInit_ProxyAuth() throws Exception {
432 String url = "mem://" + id + "?proxyUsername=testuser&proxyPassword=testpass";
433 Authentication auth = new AuthenticationBuilder()
434 .addUsername("testuser")
435 .addPassword("testpass")
436 .build();
437 RemoteRepository repo = new RemoteRepository.Builder("test", "default", url)
438 .setProxy(new Proxy("http", "testhost", 8888, auth))
439 .build();
440 newTransporter(repo);
441 transporter.peek(new PeekTask(URI.create("file.txt")));
442 }
443 }