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.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 }