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