1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.aether.internal.test.util.http;
20
21 import java.io.File;
22 import java.io.FileNotFoundException;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.UncheckedIOException;
26 import java.net.ServerSocket;
27 import java.net.URI;
28 import java.net.URL;
29 import java.nio.charset.StandardCharsets;
30 import java.nio.file.Files;
31 import java.nio.file.Path;
32 import java.nio.file.Paths;
33 import java.nio.file.StandardCopyOption;
34 import java.util.HashMap;
35 import java.util.Map;
36 import java.util.concurrent.atomic.AtomicReference;
37 import java.util.function.Supplier;
38
39 import org.eclipse.aether.ConfigurationProperties;
40 import org.eclipse.aether.DefaultRepositoryCache;
41 import org.eclipse.aether.DefaultRepositorySystemSession;
42 import org.eclipse.aether.DefaultSessionData;
43 import org.eclipse.aether.internal.impl.transport.http.DefaultChecksumExtractor;
44 import org.eclipse.aether.internal.impl.transport.http.Nx2ChecksumExtractor;
45 import org.eclipse.aether.internal.impl.transport.http.XChecksumExtractor;
46 import org.eclipse.aether.internal.test.util.TestFileUtils;
47 import org.eclipse.aether.internal.test.util.TestLocalRepositoryManager;
48 import org.eclipse.aether.repository.Authentication;
49 import org.eclipse.aether.repository.Proxy;
50 import org.eclipse.aether.repository.RemoteRepository;
51 import org.eclipse.aether.spi.connector.transport.GetTask;
52 import org.eclipse.aether.spi.connector.transport.PeekTask;
53 import org.eclipse.aether.spi.connector.transport.PutTask;
54 import org.eclipse.aether.spi.connector.transport.Transporter;
55 import org.eclipse.aether.spi.connector.transport.http.ChecksumExtractor;
56 import org.eclipse.aether.spi.connector.transport.http.ChecksumExtractorStrategy;
57 import org.eclipse.aether.spi.connector.transport.http.HttpTransporter;
58 import org.eclipse.aether.spi.connector.transport.http.HttpTransporterException;
59 import org.eclipse.aether.spi.connector.transport.http.HttpTransporterFactory;
60 import org.eclipse.aether.transfer.NoTransporterException;
61 import org.eclipse.aether.transfer.TransferCancelledException;
62 import org.eclipse.aether.util.repository.AuthenticationBuilder;
63 import org.junit.jupiter.api.AfterEach;
64 import org.junit.jupiter.api.BeforeEach;
65 import org.junit.jupiter.api.Test;
66 import org.junit.jupiter.api.TestInfo;
67 import org.junit.jupiter.api.Timeout;
68
69 import static java.util.Objects.requireNonNull;
70 import static org.junit.jupiter.api.Assertions.assertEquals;
71 import static org.junit.jupiter.api.Assertions.assertNotNull;
72 import static org.junit.jupiter.api.Assertions.assertNull;
73 import static org.junit.jupiter.api.Assertions.assertThrows;
74 import static org.junit.jupiter.api.Assertions.assertTrue;
75 import static org.junit.jupiter.api.Assertions.fail;
76
77
78
79
80 @SuppressWarnings({"checkstyle:MagicNumber", "checkstyle:MethodName"})
81 public class HttpTransporterTest {
82
83 protected static final Path KEY_STORE_PATH = Paths.get("target/keystore");
84
85 protected static final Path KEY_STORE_SELF_SIGNED_PATH = Paths.get("target/keystore-self-signed");
86
87 protected static final Path TRUST_STORE_PATH = Paths.get("target/trustStore");
88
89 static {
90
91 System.setProperty(
92 "javax.net.ssl.trustStore", KEY_STORE_PATH.toAbsolutePath().toString());
93 System.setProperty("javax.net.ssl.trustStorePassword", "server-pwd");
94 System.setProperty(
95 "javax.net.ssl.keyStore", TRUST_STORE_PATH.toAbsolutePath().toString());
96 System.setProperty("javax.net.ssl.keyStorePassword", "client-pwd");
97
98 System.setProperty("javax.net.ssl.trustStoreType", "jks");
99 System.setProperty("javax.net.ssl.keyStoreType", "jks");
100
101 }
102
103 private final Supplier<HttpTransporterFactory> transporterFactorySupplier;
104
105 protected DefaultRepositorySystemSession session;
106
107 protected HttpTransporterFactory factory;
108
109 protected HttpTransporter transporter;
110
111 protected Runnable closer;
112
113 protected File repoDir;
114
115 protected HttpServer httpServer;
116
117 protected Authentication auth;
118
119 protected Proxy proxy;
120
121 protected HttpTransporterTest(Supplier<HttpTransporterFactory> transporterFactorySupplier) {
122 this.transporterFactorySupplier = requireNonNull(transporterFactorySupplier);
123
124 if (!Files.isRegularFile(KEY_STORE_PATH)) {
125 URL keyStoreUrl = HttpTransporterTest.class.getClassLoader().getResource("ssl/server-store");
126 URL keyStoreSelfSignedUrl =
127 HttpTransporterTest.class.getClassLoader().getResource("ssl/server-store-selfsigned");
128 URL trustStoreUrl = HttpTransporterTest.class.getClassLoader().getResource("ssl/client-store");
129
130 try {
131 try (InputStream keyStoreStream = keyStoreUrl.openStream();
132 InputStream keyStoreSelfSignedStream = keyStoreSelfSignedUrl.openStream();
133 InputStream trustStoreStream = trustStoreUrl.openStream()) {
134 Files.copy(keyStoreStream, KEY_STORE_PATH, StandardCopyOption.REPLACE_EXISTING);
135 Files.copy(
136 keyStoreSelfSignedStream, KEY_STORE_SELF_SIGNED_PATH, StandardCopyOption.REPLACE_EXISTING);
137 Files.copy(trustStoreStream, TRUST_STORE_PATH, StandardCopyOption.REPLACE_EXISTING);
138 }
139 } catch (IOException e) {
140 throw new UncheckedIOException(e);
141 }
142 }
143 }
144
145 protected static ChecksumExtractor standardChecksumExtractor() {
146 HashMap<String, ChecksumExtractorStrategy> strategies = new HashMap<>();
147 strategies.put("1", new Nx2ChecksumExtractor());
148 strategies.put("2", new XChecksumExtractor());
149 return new DefaultChecksumExtractor(strategies);
150 }
151
152 protected RemoteRepository newRepo(String url) {
153 return new RemoteRepository.Builder("test", "default", url)
154 .setAuthentication(auth)
155 .setProxy(proxy)
156 .build();
157 }
158
159 protected void newTransporter(String url) throws Exception {
160 if (transporter != null) {
161 transporter.close();
162 transporter = null;
163 }
164 if (closer != null) {
165 closer.run();
166 closer = null;
167 }
168 session = new DefaultRepositorySystemSession(session);
169 session.setData(new DefaultSessionData());
170 transporter = factory.newInstance(session, newRepo(url));
171 }
172
173 protected static final long OLD_FILE_TIMESTAMP = 160660800000L;
174
175 @BeforeEach
176 protected void setUp(TestInfo testInfo) throws Exception {
177 System.out.println("=== " + testInfo.getDisplayName() + " ===");
178 session = new DefaultRepositorySystemSession(h -> {
179 this.closer = h;
180 return true;
181 });
182 session.setLocalRepositoryManager(new TestLocalRepositoryManager());
183 factory = transporterFactorySupplier.get();
184 repoDir = TestFileUtils.createTempDir();
185 TestFileUtils.writeString(new File(repoDir, "file.txt"), "test");
186 TestFileUtils.writeString(new File(repoDir, "dir/file.txt"), "test");
187 TestFileUtils.writeString(new File(repoDir, "dir/oldFile.txt"), "oldTest", OLD_FILE_TIMESTAMP);
188 TestFileUtils.writeString(new File(repoDir, "empty.txt"), "");
189 TestFileUtils.writeString(new File(repoDir, "some space.txt"), "space");
190 File resumable = new File(repoDir, "resume.txt");
191 TestFileUtils.writeString(resumable, "resumable");
192 resumable.setLastModified(System.currentTimeMillis() - 90 * 1000);
193 httpServer = new HttpServer().setRepoDir(repoDir).start();
194 newTransporter(httpServer.getHttpUrl());
195 }
196
197 @AfterEach
198 protected void tearDown() throws Exception {
199 if (transporter != null) {
200 transporter.close();
201 transporter = null;
202 }
203 if (closer != null) {
204 closer.run();
205 closer = null;
206 }
207 if (httpServer != null) {
208 httpServer.stop();
209 httpServer = null;
210 }
211 factory = null;
212 session = null;
213 }
214
215 @Test
216 protected void testClassify() {
217 assertEquals(Transporter.ERROR_OTHER, transporter.classify(new FileNotFoundException()));
218 assertEquals(Transporter.ERROR_OTHER, transporter.classify(new HttpTransporterException(403)));
219 assertEquals(Transporter.ERROR_NOT_FOUND, transporter.classify(new HttpTransporterException(404)));
220 }
221
222 @Test
223 protected void testPeek() throws Exception {
224 transporter.peek(new PeekTask(URI.create("repo/file.txt")));
225 }
226
227 @Test
228 protected void testRetryHandler_defaultCount_positive() throws Exception {
229 httpServer.setConnectionsToClose(3);
230 transporter.peek(new PeekTask(URI.create("repo/file.txt")));
231 }
232
233 @Test
234 protected void testRetryHandler_defaultCount_negative() throws Exception {
235 httpServer.setConnectionsToClose(4);
236 try {
237 transporter.peek(new PeekTask(URI.create("repo/file.txt")));
238 fail("Expected error");
239 } catch (Exception expected) {
240 }
241 }
242
243 @Test
244 protected void testRetryHandler_explicitCount_positive() throws Exception {
245 session.setConfigProperty(ConfigurationProperties.HTTP_RETRY_HANDLER_COUNT, 10);
246 newTransporter(httpServer.getHttpUrl());
247 httpServer.setConnectionsToClose(10);
248 transporter.peek(new PeekTask(URI.create("repo/file.txt")));
249 }
250
251 @Test
252 protected void testRetryHandler_disabled() throws Exception {
253 session.setConfigProperty(ConfigurationProperties.HTTP_RETRY_HANDLER_COUNT, 0);
254 newTransporter(httpServer.getHttpUrl());
255 httpServer.setConnectionsToClose(1);
256 try {
257 transporter.peek(new PeekTask(URI.create("repo/file.txt")));
258 } catch (Exception expected) {
259 }
260 }
261
262 @Test
263 protected void testPeek_NotFound() throws Exception {
264 try {
265 transporter.peek(new PeekTask(URI.create("repo/missing.txt")));
266 fail("Expected error");
267 } catch (HttpTransporterException e) {
268 assertEquals(404, e.getStatusCode());
269 assertEquals(Transporter.ERROR_NOT_FOUND, transporter.classify(e));
270 }
271 }
272
273 @Test
274 protected void testPeek_Closed() throws Exception {
275 transporter.close();
276 try {
277 transporter.peek(new PeekTask(URI.create("repo/missing.txt")));
278 fail("Expected error");
279 } catch (IllegalStateException e) {
280 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
281 }
282 }
283
284 @Test
285 protected void testPeek_Authenticated() throws Exception {
286 httpServer.setAuthentication("testuser", "testpass");
287 auth = new AuthenticationBuilder()
288 .addUsername("testuser")
289 .addPassword("testpass")
290 .build();
291 newTransporter(httpServer.getHttpUrl());
292 transporter.peek(new PeekTask(URI.create("repo/file.txt")));
293 }
294
295 @Test
296 protected void testPeek_Unauthenticated() throws Exception {
297 httpServer.setAuthentication("testuser", "testpass");
298 try {
299 transporter.peek(new PeekTask(URI.create("repo/file.txt")));
300 fail("Expected error");
301 } catch (HttpTransporterException e) {
302 assertEquals(401, e.getStatusCode());
303 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
304 }
305 }
306
307 @Test
308 protected void testPeek_ProxyAuthenticated() throws Exception {
309 httpServer.setProxyAuthentication("testuser", "testpass");
310 auth = new AuthenticationBuilder()
311 .addUsername("testuser")
312 .addPassword("testpass")
313 .build();
314 proxy = new Proxy(Proxy.TYPE_HTTP, httpServer.getHost(), httpServer.getHttpPort(), auth);
315 newTransporter("http://bad.localhost:1/");
316 transporter.peek(new PeekTask(URI.create("repo/file.txt")));
317 }
318
319 @Test
320 protected void testPeek_ProxyUnauthenticated() throws Exception {
321 httpServer.setProxyAuthentication("testuser", "testpass");
322 proxy = new Proxy(Proxy.TYPE_HTTP, httpServer.getHost(), httpServer.getHttpPort());
323 newTransporter("http://bad.localhost:1/");
324 try {
325 transporter.peek(new PeekTask(URI.create("repo/file.txt")));
326 fail("Expected error");
327 } catch (HttpTransporterException e) {
328 assertEquals(407, e.getStatusCode());
329 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
330 }
331 }
332
333 @Test
334 protected void testPeek_SSL() throws Exception {
335 httpServer.addSslConnector();
336 newTransporter(httpServer.getHttpsUrl());
337 transporter.peek(new PeekTask(URI.create("repo/file.txt")));
338 }
339
340 @Test
341 protected void testPeek_Redirect() throws Exception {
342 httpServer.addSslConnector();
343 transporter.peek(new PeekTask(URI.create("redirect/file.txt")));
344 transporter.peek(new PeekTask(URI.create("redirect/file.txt?scheme=https")));
345 }
346
347 @Test
348 protected void testGet_ToMemory() throws Exception {
349 RecordingTransportListener listener = new RecordingTransportListener();
350 GetTask task = new GetTask(URI.create("repo/file.txt")).setListener(listener);
351 transporter.get(task);
352 assertEquals("test", task.getDataString());
353 assertEquals(0L, listener.getDataOffset());
354 assertEquals(4L, listener.getDataLength());
355 assertEquals(1, listener.getStartedCount());
356 assertTrue(listener.getProgressedCount() > 0, "Count: " + listener.getProgressedCount());
357 assertEquals(task.getDataString(), listener.getBaos().toString(StandardCharsets.UTF_8));
358 }
359
360 @Test
361 protected void testGet_ToFile() throws Exception {
362 File file = TestFileUtils.createTempFile("failure");
363 RecordingTransportListener listener = new RecordingTransportListener();
364 GetTask task = new GetTask(URI.create("repo/file.txt"))
365 .setDataPath(file.toPath())
366 .setListener(listener);
367 transporter.get(task);
368 assertEquals("test", TestFileUtils.readString(file));
369 assertEquals(0L, listener.getDataOffset());
370 assertEquals(4L, listener.getDataLength());
371 assertEquals(1, listener.getStartedCount());
372 assertTrue(listener.getProgressedCount() > 0, "Count: " + listener.getProgressedCount());
373 assertEquals("test", listener.getBaos().toString(StandardCharsets.UTF_8));
374 }
375
376 @Test
377 protected void testGet_ToFileTimestamp() throws Exception {
378 File file = TestFileUtils.createTempFile("failure");
379 RecordingTransportListener listener = new RecordingTransportListener();
380 GetTask task = new GetTask(URI.create("repo/dir/oldFile.txt"))
381 .setDataPath(file.toPath())
382 .setListener(listener);
383 transporter.get(task);
384 assertEquals("oldTest", TestFileUtils.readString(file));
385 assertEquals(0L, listener.getDataOffset());
386 assertEquals(7L, listener.getDataLength());
387 assertEquals(1, listener.getStartedCount());
388 assertTrue(listener.getProgressedCount() > 0, "Count: " + listener.getProgressedCount());
389 assertEquals("oldTest", listener.getBaos().toString(StandardCharsets.UTF_8));
390 assertEquals(file.lastModified(), OLD_FILE_TIMESTAMP);
391 }
392
393 @Test
394 protected void testGet_EmptyResource() throws Exception {
395 File file = TestFileUtils.createTempFile("failure");
396 RecordingTransportListener listener = new RecordingTransportListener();
397 GetTask task = new GetTask(URI.create("repo/empty.txt"))
398 .setDataPath(file.toPath())
399 .setListener(listener);
400 transporter.get(task);
401 assertEquals("", TestFileUtils.readString(file));
402 assertEquals(0L, listener.getDataOffset());
403 assertEquals(0L, listener.getDataLength());
404 assertEquals(1, listener.getStartedCount());
405 assertEquals(0, listener.getProgressedCount());
406 assertEquals("", listener.getBaos().toString(StandardCharsets.UTF_8));
407 }
408
409 @Test
410 protected void testGet_EncodedResourcePath() throws Exception {
411 GetTask task = new GetTask(URI.create("repo/some%20space.txt"));
412 transporter.get(task);
413 assertEquals("space", task.getDataString());
414 }
415
416 @Test
417 protected void testGet_Authenticated() throws Exception {
418 httpServer.setAuthentication("testuser", "testpass");
419 auth = new AuthenticationBuilder()
420 .addUsername("testuser")
421 .addPassword("testpass")
422 .build();
423 newTransporter(httpServer.getHttpUrl());
424 RecordingTransportListener listener = new RecordingTransportListener();
425 GetTask task = new GetTask(URI.create("repo/file.txt")).setListener(listener);
426 transporter.get(task);
427 assertEquals("test", task.getDataString());
428 assertEquals(0L, listener.getDataOffset());
429 assertEquals(4L, listener.getDataLength());
430 assertEquals(1, listener.getStartedCount());
431 assertTrue(listener.getProgressedCount() > 0, "Count: " + listener.getProgressedCount());
432 assertEquals(task.getDataString(), listener.getBaos().toString(StandardCharsets.UTF_8));
433 }
434
435 @Test
436 protected void testGet_Unauthenticated() throws Exception {
437 httpServer.setAuthentication("testuser", "testpass");
438 try {
439 transporter.get(new GetTask(URI.create("repo/file.txt")));
440 fail("Expected error");
441 } catch (HttpTransporterException e) {
442 assertEquals(401, e.getStatusCode());
443 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
444 }
445 }
446
447 @Test
448 protected void testGet_ProxyAuthenticated() throws Exception {
449 httpServer.setProxyAuthentication("testuser", "testpass");
450 Authentication auth = new AuthenticationBuilder()
451 .addUsername("testuser")
452 .addPassword("testpass")
453 .build();
454 proxy = new Proxy(Proxy.TYPE_HTTP, httpServer.getHost(), httpServer.getHttpPort(), auth);
455 newTransporter("http://bad.localhost:1/");
456 RecordingTransportListener listener = new RecordingTransportListener();
457 GetTask task = new GetTask(URI.create("repo/file.txt")).setListener(listener);
458 transporter.get(task);
459 assertEquals("test", task.getDataString());
460 assertEquals(0L, listener.getDataOffset());
461 assertEquals(4L, listener.getDataLength());
462 assertEquals(1, listener.getStartedCount());
463 assertTrue(listener.getProgressedCount() > 0, "Count: " + listener.getProgressedCount());
464 assertEquals(task.getDataString(), listener.getBaos().toString(StandardCharsets.UTF_8));
465 }
466
467 @Test
468 protected void testGet_ProxyUnauthenticated() throws Exception {
469 httpServer.setProxyAuthentication("testuser", "testpass");
470 proxy = new Proxy(Proxy.TYPE_HTTP, httpServer.getHost(), httpServer.getHttpPort());
471 newTransporter("http://bad.localhost:1/");
472 try {
473 transporter.get(new GetTask(URI.create("repo/file.txt")));
474 fail("Expected error");
475 } catch (HttpTransporterException e) {
476 assertEquals(407, e.getStatusCode());
477 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
478 }
479 }
480
481 @Test
482 protected void testGet_SSL() throws Exception {
483 httpServer.addSslConnector();
484 newTransporter(httpServer.getHttpsUrl());
485 RecordingTransportListener listener = new RecordingTransportListener();
486 GetTask task = new GetTask(URI.create("repo/file.txt")).setListener(listener);
487 transporter.get(task);
488 assertEquals("test", task.getDataString());
489 assertEquals(0L, listener.getDataOffset());
490 assertEquals(4L, listener.getDataLength());
491 assertEquals(1, listener.getStartedCount());
492 assertTrue(listener.getProgressedCount() > 0, "Count: " + listener.getProgressedCount());
493 assertEquals(task.getDataString(), listener.getBaos().toString(StandardCharsets.UTF_8));
494 }
495
496 @Test
497 protected void testGet_SSL_WithServerErrors() throws Exception {
498 httpServer.setServerErrorsBeforeWorks(1);
499 httpServer.addSslConnector();
500 newTransporter(httpServer.getHttpsUrl());
501 for (int i = 1; i < 3; i++) {
502 try {
503 RecordingTransportListener listener = new RecordingTransportListener();
504 GetTask task = new GetTask(URI.create("repo/file.txt")).setListener(listener);
505 transporter.get(task);
506 assertEquals("test", task.getDataString());
507 assertEquals(0L, listener.getDataOffset());
508 assertEquals(4L, listener.getDataLength());
509 assertEquals(1, listener.getStartedCount());
510 assertTrue(listener.getProgressedCount() > 0, "Count: " + listener.getProgressedCount());
511 assertEquals(task.getDataString(), listener.getBaos().toString(StandardCharsets.UTF_8));
512 } catch (HttpTransporterException e) {
513 assertEquals(500, e.getStatusCode());
514 }
515 }
516 }
517
518 @Test
519 protected void testGet_HTTPS_Unknown_SecurityMode() throws Exception {
520 session.setConfigProperty(ConfigurationProperties.HTTPS_SECURITY_MODE, "unknown");
521 httpServer.addSelfSignedSslConnector();
522 try {
523 newTransporter(httpServer.getHttpsUrl());
524 fail("Unsupported security mode");
525 } catch (IllegalArgumentException a) {
526
527 }
528 }
529
530 @Test
531 protected void testGet_HTTPS_Insecure_SecurityMode() throws Exception {
532
533
534 session.setConfigProperty(
535 ConfigurationProperties.HTTPS_SECURITY_MODE, ConfigurationProperties.HTTPS_SECURITY_MODE_INSECURE);
536 httpServer.addSelfSignedSslConnector();
537 newTransporter(httpServer.getHttpsUrl());
538 RecordingTransportListener listener = new RecordingTransportListener();
539 GetTask task = new GetTask(URI.create("repo/file.txt")).setListener(listener);
540 transporter.get(task);
541 assertEquals("test", task.getDataString());
542 assertEquals(0L, listener.getDataOffset());
543 assertEquals(4L, listener.getDataLength());
544 assertEquals(1, listener.getStartedCount());
545 assertTrue(listener.getProgressedCount() > 0, "Count: " + listener.getProgressedCount());
546 assertEquals(task.getDataString(), listener.getBaos().toString(StandardCharsets.UTF_8));
547 }
548
549 @Test
550 protected void testGet_HTTPS_HTTP2Only_Insecure_SecurityMode() throws Exception {
551
552
553 session.setConfigProperty(
554 ConfigurationProperties.HTTPS_SECURITY_MODE, ConfigurationProperties.HTTPS_SECURITY_MODE_INSECURE);
555 httpServer.addSelfSignedSslConnectorHttp2Only();
556 newTransporter(httpServer.getHttpsUrl());
557 RecordingTransportListener listener = new RecordingTransportListener();
558 GetTask task = new GetTask(URI.create("repo/file.txt")).setListener(listener);
559 transporter.get(task);
560 assertEquals("test", task.getDataString());
561 assertEquals(0L, listener.getDataOffset());
562 assertEquals(4L, listener.getDataLength());
563 assertEquals(1, listener.getStartedCount());
564 assertTrue(listener.getProgressedCount() > 0, "Count: " + listener.getProgressedCount());
565 assertEquals(task.getDataString(), listener.getBaos().toString(StandardCharsets.UTF_8));
566 }
567
568 @Test
569 protected void testGet_Redirect() throws Exception {
570 httpServer.addSslConnector();
571 RecordingTransportListener listener = new RecordingTransportListener();
572 GetTask task = new GetTask(URI.create("redirect/file.txt?scheme=https")).setListener(listener);
573 transporter.get(task);
574 assertEquals("test", task.getDataString());
575 assertEquals(0L, listener.getDataOffset());
576 assertEquals(4L, listener.getDataLength());
577 assertEquals(1, listener.getStartedCount());
578 assertTrue(listener.getProgressedCount() > 0, "Count: " + listener.getProgressedCount());
579 assertEquals(task.getDataString(), listener.getBaos().toString(StandardCharsets.UTF_8));
580 }
581
582 @Test
583 protected void testGet_Resume() throws Exception {
584 File file = TestFileUtils.createTempFile("re");
585 RecordingTransportListener listener = new RecordingTransportListener();
586 GetTask task = new GetTask(URI.create("repo/resume.txt"))
587 .setDataPath(file.toPath(), true)
588 .setListener(listener);
589 transporter.get(task);
590 assertEquals("resumable", TestFileUtils.readString(file));
591 assertEquals(1L, listener.getStartedCount());
592 assertEquals(2L, listener.getDataOffset());
593 assertEquals(9, listener.getDataLength());
594 assertTrue(listener.getProgressedCount() > 0, "Count: " + listener.getProgressedCount());
595 assertEquals("sumable", listener.getBaos().toString(StandardCharsets.UTF_8));
596 }
597
598 @Test
599 protected void testGet_ResumeLocalContentsOutdated() throws Exception {
600 File file = TestFileUtils.createTempFile("re");
601 file.setLastModified(System.currentTimeMillis() - 5 * 60 * 1000);
602 RecordingTransportListener listener = new RecordingTransportListener();
603 GetTask task = new GetTask(URI.create("repo/resume.txt"))
604 .setDataPath(file.toPath(), true)
605 .setListener(listener);
606 transporter.get(task);
607 assertEquals("resumable", TestFileUtils.readString(file));
608 assertEquals(1L, listener.getStartedCount());
609 assertEquals(0L, listener.getDataOffset());
610 assertEquals(9, listener.getDataLength());
611 assertTrue(listener.getProgressedCount() > 0, "Count: " + listener.getProgressedCount());
612 assertEquals("resumable", listener.getBaos().toString(StandardCharsets.UTF_8));
613 }
614
615 @Test
616 protected void testGet_ResumeRangesNotSupportedByServer() throws Exception {
617 httpServer.setRangeSupport(false);
618 File file = TestFileUtils.createTempFile("re");
619 RecordingTransportListener listener = new RecordingTransportListener();
620 GetTask task = new GetTask(URI.create("repo/resume.txt"))
621 .setDataPath(file.toPath(), true)
622 .setListener(listener);
623 transporter.get(task);
624 assertEquals("resumable", TestFileUtils.readString(file));
625 assertEquals(1L, listener.getStartedCount());
626 assertEquals(0L, listener.getDataOffset());
627 assertEquals(9, listener.getDataLength());
628 assertTrue(listener.getProgressedCount() > 0, "Count: " + listener.getProgressedCount());
629 assertEquals("resumable", listener.getBaos().toString(StandardCharsets.UTF_8));
630 }
631
632 @Test
633 protected void testGet_Checksums_Nexus() throws Exception {
634 httpServer.setChecksumHeader(HttpServer.ChecksumHeader.NEXUS);
635 GetTask task = new GetTask(URI.create("repo/file.txt"));
636 transporter.get(task);
637 assertEquals("test", task.getDataString());
638 assertEquals(
639 "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", task.getChecksums().get("SHA-1"));
640 }
641
642 @Test
643 protected void testGet_Checksums_XChecksum() throws Exception {
644 httpServer.setChecksumHeader(HttpServer.ChecksumHeader.XCHECKSUM);
645 GetTask task = new GetTask(URI.create("repo/file.txt"));
646 transporter.get(task);
647 assertEquals("test", task.getDataString());
648 assertEquals(
649 "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", task.getChecksums().get("SHA-1"));
650 }
651
652 @Test
653 protected void testGet_FileHandleLeak() throws Exception {
654 for (int i = 0; i < 100; i++) {
655 File file = TestFileUtils.createTempFile("failure");
656 transporter.get(new GetTask(URI.create("repo/file.txt")).setDataPath(file.toPath()));
657 assertTrue(file.delete(), i + ", " + file.getAbsolutePath());
658 }
659 }
660
661 @Test
662 protected void testGet_NotFound() throws Exception {
663 try {
664 transporter.get(new GetTask(URI.create("repo/missing.txt")));
665 fail("Expected error");
666 } catch (HttpTransporterException e) {
667 assertEquals(404, e.getStatusCode());
668 assertEquals(Transporter.ERROR_NOT_FOUND, transporter.classify(e));
669 }
670 }
671
672 @Test
673 protected void testGet_Closed() throws Exception {
674 transporter.close();
675 try {
676 transporter.get(new GetTask(URI.create("repo/file.txt")));
677 fail("Expected error");
678 } catch (IllegalStateException e) {
679 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
680 }
681 }
682
683 @Test
684 protected void testGet_StartCancelled() throws Exception {
685 RecordingTransportListener listener = new RecordingTransportListener();
686 listener.cancelStart();
687 GetTask task = new GetTask(URI.create("repo/file.txt")).setListener(listener);
688 try {
689 transporter.get(task);
690 fail("Expected error");
691 } catch (TransferCancelledException e) {
692 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
693 }
694 assertEquals(0L, listener.getDataOffset());
695 assertEquals(4L, listener.getDataLength());
696 assertEquals(1, listener.getStartedCount());
697 assertEquals(0, listener.getProgressedCount());
698 }
699
700 @Test
701 protected void testGet_ProgressCancelled() throws Exception {
702 RecordingTransportListener listener = new RecordingTransportListener();
703 listener.cancelProgress();
704 GetTask task = new GetTask(URI.create("repo/file.txt")).setListener(listener);
705 try {
706 transporter.get(task);
707 fail("Expected error");
708 } catch (TransferCancelledException e) {
709 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
710 }
711 assertEquals(0L, listener.getDataOffset());
712 assertEquals(4L, listener.getDataLength());
713 assertEquals(1, listener.getStartedCount());
714 assertEquals(1, listener.getProgressedCount());
715 }
716
717 @Test
718 protected void testPut_FromMemory() throws Exception {
719 RecordingTransportListener listener = new RecordingTransportListener();
720 PutTask task =
721 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
722 transporter.put(task);
723 assertEquals(0L, listener.getDataOffset());
724 assertEquals(6L, listener.getDataLength());
725 assertEquals(1, listener.getStartedCount());
726 assertTrue(listener.getProgressedCount() > 0, "Count: " + listener.getProgressedCount());
727 assertEquals("upload", TestFileUtils.readString(new File(repoDir, "file.txt")));
728 }
729
730 @Test
731 protected void testPut_FromFile() throws Exception {
732 File file = TestFileUtils.createTempFile("upload");
733 RecordingTransportListener listener = new RecordingTransportListener();
734 PutTask task =
735 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataPath(file.toPath());
736 transporter.put(task);
737 assertEquals(0L, listener.getDataOffset());
738 assertEquals(6L, listener.getDataLength());
739 assertEquals(1, listener.getStartedCount());
740 assertTrue(listener.getProgressedCount() > 0, "Count: " + listener.getProgressedCount());
741 assertEquals("upload", TestFileUtils.readString(new File(repoDir, "file.txt")));
742 }
743
744 @Test
745 protected void testPut_EmptyResource() throws Exception {
746 RecordingTransportListener listener = new RecordingTransportListener();
747 PutTask task = new PutTask(URI.create("repo/file.txt")).setListener(listener);
748 transporter.put(task);
749 assertEquals(0L, listener.getDataOffset());
750 assertEquals(0L, listener.getDataLength());
751 assertEquals(1, listener.getStartedCount());
752 assertEquals(0, listener.getProgressedCount());
753 assertEquals("", TestFileUtils.readString(new File(repoDir, "file.txt")));
754 }
755
756 @Test
757 protected void testPut_EncodedResourcePath() throws Exception {
758 RecordingTransportListener listener = new RecordingTransportListener();
759 PutTask task = new PutTask(URI.create("repo/some%20space.txt"))
760 .setListener(listener)
761 .setDataString("OK");
762 transporter.put(task);
763 assertEquals(0L, listener.getDataOffset());
764 assertEquals(2L, listener.getDataLength());
765 assertEquals(1, listener.getStartedCount());
766 assertTrue(listener.getProgressedCount() > 0, "Count: " + listener.getProgressedCount());
767 assertEquals("OK", TestFileUtils.readString(new File(repoDir, "some space.txt")));
768 }
769
770 @Test
771 protected void testPut_Authenticated_ExpectContinue() throws Exception {
772 httpServer.setAuthentication("testuser", "testpass");
773 auth = new AuthenticationBuilder()
774 .addUsername("testuser")
775 .addPassword("testpass")
776 .build();
777 newTransporter(httpServer.getHttpUrl());
778 RecordingTransportListener listener = new RecordingTransportListener();
779 PutTask task =
780 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
781 transporter.put(task);
782 assertEquals(0L, listener.getDataOffset());
783 assertEquals(6L, listener.getDataLength());
784 assertEquals(1, listener.getStartedCount());
785 assertTrue(listener.getProgressedCount() > 0, "Count: " + listener.getProgressedCount());
786 assertEquals("upload", TestFileUtils.readString(new File(repoDir, "file.txt")));
787 }
788
789 @Test
790 protected void testPut_Authenticated_ExpectContinueBroken() throws Exception {
791
792 session.setConfigProperty(ConfigurationProperties.HTTP_SUPPORT_WEBDAV, true);
793 httpServer.setAuthentication("testuser", "testpass");
794 httpServer.setExpectSupport(HttpServer.ExpectContinue.BROKEN);
795 auth = new AuthenticationBuilder()
796 .addUsername("testuser")
797 .addPassword("testpass")
798 .build();
799 newTransporter(httpServer.getHttpUrl());
800 RecordingTransportListener listener = new RecordingTransportListener();
801 PutTask task =
802 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
803 transporter.put(task);
804 assertEquals(0L, listener.getDataOffset());
805 assertEquals(6L, listener.getDataLength());
806 assertEquals(1, listener.getStartedCount());
807 assertTrue(listener.getProgressedCount() > 0, "Count: " + listener.getProgressedCount());
808 assertEquals("upload", TestFileUtils.readString(new File(repoDir, "file.txt")));
809 }
810
811 @Test
812 protected void testPut_Authenticated_ExpectContinueRejected() throws Exception {
813 httpServer.setAuthentication("testuser", "testpass");
814 httpServer.setExpectSupport(HttpServer.ExpectContinue.FAIL);
815 auth = new AuthenticationBuilder()
816 .addUsername("testuser")
817 .addPassword("testpass")
818 .build();
819 newTransporter(httpServer.getHttpUrl());
820 RecordingTransportListener listener = new RecordingTransportListener();
821 PutTask task =
822 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
823 transporter.put(task);
824 assertEquals(0L, listener.getDataOffset());
825 assertEquals(6L, listener.getDataLength());
826 assertEquals(1, listener.getStartedCount());
827 assertTrue(listener.getProgressedCount() > 0, "Count: " + listener.getProgressedCount());
828 assertEquals("upload", TestFileUtils.readString(new File(repoDir, "file.txt")));
829 }
830
831 @Test
832 protected void testPut_Authenticated_ExpectContinueDisabled() throws Exception {
833 session.setConfigProperty(ConfigurationProperties.HTTP_EXPECT_CONTINUE, false);
834 httpServer.setAuthentication("testuser", "testpass");
835 httpServer.setExpectSupport(HttpServer.ExpectContinue.FAIL);
836 auth = new AuthenticationBuilder()
837 .addUsername("testuser")
838 .addPassword("testpass")
839 .build();
840 newTransporter(httpServer.getHttpUrl());
841 RecordingTransportListener listener = new RecordingTransportListener();
842 PutTask task =
843 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
844 transporter.put(task);
845 assertEquals(0L, listener.getDataOffset());
846 assertEquals(6L, listener.getDataLength());
847 assertEquals(1, listener.getStartedCount());
848 assertTrue(listener.getProgressedCount() > 0, "Count: " + listener.getProgressedCount());
849 assertEquals("upload", TestFileUtils.readString(new File(repoDir, "file.txt")));
850 }
851
852 @Test
853 protected void testPut_Authenticated_ExpectContinueRejected_ExplicitlyConfiguredHeader() throws Exception {
854 Map<String, String> headers = new HashMap<>();
855 headers.put("Expect", "100-continue");
856 session.setConfigProperty(ConfigurationProperties.HTTP_HEADERS + ".test", headers);
857 httpServer.setAuthentication("testuser", "testpass");
858 httpServer.setExpectSupport(HttpServer.ExpectContinue.FAIL);
859 auth = new AuthenticationBuilder()
860 .addUsername("testuser")
861 .addPassword("testpass")
862 .build();
863 newTransporter(httpServer.getHttpUrl());
864 RecordingTransportListener listener = new RecordingTransportListener();
865 PutTask task =
866 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
867 transporter.put(task);
868 assertEquals(0L, listener.getDataOffset());
869 assertEquals(6L, listener.getDataLength());
870 assertEquals(1, listener.getStartedCount());
871 assertTrue(listener.getProgressedCount() > 0, "Count: " + listener.getProgressedCount());
872 assertEquals("upload", TestFileUtils.readString(new File(repoDir, "file.txt")));
873 }
874
875 @Test
876 protected void testPut_Unauthenticated() throws Exception {
877 httpServer.setAuthentication("testuser", "testpass");
878 RecordingTransportListener listener = new RecordingTransportListener();
879 PutTask task =
880 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
881 try {
882 transporter.put(task);
883 fail("Expected error");
884 } catch (HttpTransporterException e) {
885 assertEquals(401, e.getStatusCode());
886 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
887 }
888 assertEquals(0, listener.getStartedCount());
889 assertEquals(0, listener.getProgressedCount());
890 }
891
892 @Test
893 protected void testPut_ProxyAuthenticated() throws Exception {
894 httpServer.setProxyAuthentication("testuser", "testpass");
895 Authentication auth = new AuthenticationBuilder()
896 .addUsername("testuser")
897 .addPassword("testpass")
898 .build();
899 proxy = new Proxy(Proxy.TYPE_HTTP, httpServer.getHost(), httpServer.getHttpPort(), auth);
900 newTransporter("http://bad.localhost:1/");
901 RecordingTransportListener listener = new RecordingTransportListener();
902 PutTask task =
903 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
904 transporter.put(task);
905 assertEquals(0L, listener.getDataOffset());
906 assertEquals(6L, listener.getDataLength());
907 assertEquals(1, listener.getStartedCount());
908 assertTrue(listener.getProgressedCount() > 0, "Count: " + listener.getProgressedCount());
909 assertEquals("upload", TestFileUtils.readString(new File(repoDir, "file.txt")));
910 }
911
912 @Test
913 protected void testPut_ProxyUnauthenticated() throws Exception {
914 httpServer.setProxyAuthentication("testuser", "testpass");
915 proxy = new Proxy(Proxy.TYPE_HTTP, httpServer.getHost(), httpServer.getHttpPort());
916 newTransporter("http://bad.localhost:1/");
917 RecordingTransportListener listener = new RecordingTransportListener();
918 PutTask task =
919 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
920 try {
921 transporter.put(task);
922 fail("Expected error");
923 } catch (HttpTransporterException e) {
924 assertEquals(407, e.getStatusCode());
925 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
926 }
927 assertEquals(0, listener.getStartedCount());
928 assertEquals(0, listener.getProgressedCount());
929 }
930
931 @Test
932 protected void testPut_SSL() throws Exception {
933 httpServer.addSslConnector();
934 httpServer.setAuthentication("testuser", "testpass");
935 auth = new AuthenticationBuilder()
936 .addUsername("testuser")
937 .addPassword("testpass")
938 .build();
939 newTransporter(httpServer.getHttpsUrl());
940 RecordingTransportListener listener = new RecordingTransportListener();
941 PutTask task =
942 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
943 transporter.put(task);
944 assertEquals(0L, listener.getDataOffset());
945 assertEquals(6L, listener.getDataLength());
946 assertEquals(1, listener.getStartedCount());
947 assertTrue(listener.getProgressedCount() > 0, "Count: " + listener.getProgressedCount());
948 assertEquals("upload", TestFileUtils.readString(new File(repoDir, "file.txt")));
949 }
950
951 @Test
952 protected void testPut_FileHandleLeak() throws Exception {
953 for (int i = 0; i < 100; i++) {
954 File src = TestFileUtils.createTempFile("upload");
955 File dst = new File(repoDir, "file.txt");
956 transporter.put(new PutTask(URI.create("repo/file.txt")).setDataPath(src.toPath()));
957 assertTrue(src.delete(), i + ", " + src.getAbsolutePath());
958 assertTrue(dst.delete(), i + ", " + dst.getAbsolutePath());
959 }
960 }
961
962 @Test
963 protected void testPut_Closed() throws Exception {
964 transporter.close();
965 try {
966 transporter.put(new PutTask(URI.create("repo/missing.txt")));
967 fail("Expected error");
968 } catch (IllegalStateException e) {
969 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
970 }
971 }
972
973 @Test
974 protected void testPut_StartCancelled() throws Exception {
975 RecordingTransportListener listener = new RecordingTransportListener();
976 listener.cancelStart();
977 PutTask task =
978 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
979 try {
980 transporter.put(task);
981 fail("Expected error");
982 } catch (TransferCancelledException e) {
983 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
984 }
985 assertEquals(0L, listener.getDataOffset());
986 assertEquals(6L, listener.getDataLength());
987 assertEquals(1, listener.getStartedCount());
988 assertEquals(0, listener.getProgressedCount());
989 }
990
991 @Test
992 protected void testPut_ProgressCancelled() throws Exception {
993 RecordingTransportListener listener = new RecordingTransportListener();
994 listener.cancelProgress();
995 PutTask task =
996 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
997 try {
998 transporter.put(task);
999 fail("Expected error");
1000 } catch (TransferCancelledException e) {
1001 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
1002 }
1003 assertEquals(0L, listener.getDataOffset());
1004 assertEquals(6L, listener.getDataLength());
1005 assertEquals(1, listener.getStartedCount());
1006 assertEquals(1, listener.getProgressedCount());
1007 }
1008
1009 @Test
1010 protected void testGetPut_AuthCache() throws Exception {
1011 httpServer.setAuthentication("testuser", "testpass");
1012 auth = new AuthenticationBuilder()
1013 .addUsername("testuser")
1014 .addPassword("testpass")
1015 .build();
1016 newTransporter(httpServer.getHttpUrl());
1017 GetTask get = new GetTask(URI.create("repo/file.txt"));
1018 transporter.get(get);
1019 RecordingTransportListener listener = new RecordingTransportListener();
1020 PutTask task =
1021 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
1022 transporter.put(task);
1023 assertEquals(1, listener.getStartedCount());
1024 }
1025
1026 @Test
1027 protected void testPut_PreemptiveIsDefault() throws Exception {
1028 httpServer.setAuthentication("testuser", "testpass");
1029 auth = new AuthenticationBuilder()
1030 .addUsername("testuser")
1031 .addPassword("testpass")
1032 .build();
1033 newTransporter(httpServer.getHttpUrl());
1034 PutTask task = new PutTask(URI.create("repo/file.txt")).setDataString("upload");
1035 transporter.put(task);
1036 assertEquals(1, httpServer.getLogEntries().size());
1037 }
1038
1039 @Test
1040 protected void testPut_AuthCache() throws Exception {
1041 session.setConfigProperty(ConfigurationProperties.HTTP_PREEMPTIVE_PUT_AUTH, false);
1042 httpServer.setAuthentication("testuser", "testpass");
1043 auth = new AuthenticationBuilder()
1044 .addUsername("testuser")
1045 .addPassword("testpass")
1046 .build();
1047 newTransporter(httpServer.getHttpUrl());
1048 PutTask task = new PutTask(URI.create("repo/file.txt")).setDataString("upload");
1049 transporter.put(task);
1050 assertEquals(2, httpServer.getLogEntries().size());
1051 httpServer.getLogEntries().clear();
1052 task = new PutTask(URI.create("repo/file.txt")).setDataString("upload");
1053 transporter.put(task);
1054 assertEquals(1, httpServer.getLogEntries().size());
1055 }
1056
1057 @Test
1058 protected void testPut_AuthCache_Preemptive() throws Exception {
1059 httpServer.setAuthentication("testuser", "testpass");
1060 auth = new AuthenticationBuilder()
1061 .addUsername("testuser")
1062 .addPassword("testpass")
1063 .build();
1064 session.setConfigProperty(ConfigurationProperties.HTTP_PREEMPTIVE_AUTH, true);
1065 newTransporter(httpServer.getHttpUrl());
1066 PutTask task = new PutTask(URI.create("repo/file.txt")).setDataString("upload");
1067 transporter.put(task);
1068 assertEquals(1, httpServer.getLogEntries().size());
1069 httpServer.getLogEntries().clear();
1070 task = new PutTask(URI.create("repo/file.txt")).setDataString("upload");
1071 transporter.put(task);
1072 assertEquals(1, httpServer.getLogEntries().size());
1073 }
1074
1075 @Test
1076 @Timeout(20)
1077 protected void testConcurrency() throws Exception {
1078 httpServer.setAuthentication("testuser", "testpass");
1079 auth = new AuthenticationBuilder()
1080 .addUsername("testuser")
1081 .addPassword("testpass")
1082 .build();
1083 newTransporter(httpServer.getHttpUrl());
1084 final AtomicReference<Throwable> error = new AtomicReference<>();
1085 Thread[] threads = new Thread[20];
1086 for (int i = 0; i < threads.length; i++) {
1087 final String path = "repo/file.txt?i=" + i;
1088 threads[i] = new Thread(() -> {
1089 try {
1090 for (int j = 0; j < 100; j++) {
1091 GetTask task = new GetTask(URI.create(path));
1092 transporter.get(task);
1093 assertEquals("test", task.getDataString());
1094 }
1095 } catch (Throwable t) {
1096 error.compareAndSet(null, t);
1097 System.err.println(path);
1098 t.printStackTrace();
1099 }
1100 });
1101 threads[i].setName("Task-" + i);
1102 }
1103 for (Thread thread : threads) {
1104 thread.start();
1105 }
1106 for (Thread thread : threads) {
1107 thread.join();
1108 }
1109 assertNull(error.get(), String.valueOf(error.get()));
1110 }
1111
1112 @Test
1113 @Timeout(10)
1114 protected void testConnectTimeout() throws Exception {
1115 session.setConfigProperty(ConfigurationProperties.CONNECT_TIMEOUT, 100);
1116 int port = 1;
1117 newTransporter("http://localhost:" + port);
1118 try {
1119 transporter.get(new GetTask(URI.create("repo/file.txt")));
1120 fail("Expected error");
1121 } catch (Exception e) {
1122
1123 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
1124 }
1125 }
1126
1127 @Test
1128 @Timeout(10)
1129 protected void testRequestTimeout() throws Exception {
1130 session.setConfigProperty(ConfigurationProperties.REQUEST_TIMEOUT, 100);
1131 ServerSocket server = new ServerSocket(0);
1132 try (server) {
1133 newTransporter("http://localhost:" + server.getLocalPort());
1134 try {
1135 transporter.get(new GetTask(URI.create("repo/file.txt")));
1136 fail("Expected error");
1137 } catch (Exception e) {
1138 assertTrue(e.getClass().getSimpleName().contains("Timeout"));
1139 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
1140 }
1141 }
1142 }
1143
1144 @Test
1145 protected void testUserAgent() throws Exception {
1146 session.setConfigProperty(ConfigurationProperties.USER_AGENT, "SomeTest/1.0");
1147 newTransporter(httpServer.getHttpUrl());
1148 transporter.get(new GetTask(URI.create("repo/file.txt")));
1149 assertEquals(1, httpServer.getLogEntries().size());
1150 for (HttpServer.LogEntry log : httpServer.getLogEntries()) {
1151 assertEquals("SomeTest/1.0", log.getHeaders().get("User-Agent"));
1152 }
1153 }
1154
1155 @Test
1156 protected void testCustomHeaders() throws Exception {
1157 Map<String, String> headers = new HashMap<>();
1158 headers.put("User-Agent", "Custom/1.0");
1159 headers.put("X-CustomHeader", "Custom-Value");
1160 session.setConfigProperty(ConfigurationProperties.USER_AGENT, "SomeTest/1.0");
1161 session.setConfigProperty(ConfigurationProperties.HTTP_HEADERS + ".test", headers);
1162 newTransporter(httpServer.getHttpUrl());
1163 transporter.get(new GetTask(URI.create("repo/file.txt")));
1164 assertEquals(1, httpServer.getLogEntries().size());
1165 for (HttpServer.LogEntry log : httpServer.getLogEntries()) {
1166 for (Map.Entry<String, String> entry : headers.entrySet()) {
1167 assertEquals(entry.getValue(), log.getHeaders().get(entry.getKey()), entry.getKey());
1168 }
1169 }
1170 }
1171
1172 @Test
1173 protected void testServerAuthScope_NotUsedForProxy() throws Exception {
1174 String username = "testuser", password = "testpass";
1175 httpServer.setProxyAuthentication(username, password);
1176 auth = new AuthenticationBuilder()
1177 .addUsername(username)
1178 .addPassword(password)
1179 .build();
1180 proxy = new Proxy(Proxy.TYPE_HTTP, httpServer.getHost(), httpServer.getHttpPort());
1181 newTransporter("http://" + httpServer.getHost() + ":12/");
1182 try {
1183 transporter.get(new GetTask(URI.create("repo/file.txt")));
1184 fail("Server auth must not be used as proxy auth");
1185 } catch (HttpTransporterException e) {
1186 assertEquals(407, e.getStatusCode());
1187 } catch (IOException e) {
1188
1189 }
1190 }
1191
1192 @Test
1193 protected void testProxyAuthScope_NotUsedForServer() throws Exception {
1194 String username = "testuser", password = "testpass";
1195 httpServer.setAuthentication(username, password);
1196 Authentication auth = new AuthenticationBuilder()
1197 .addUsername(username)
1198 .addPassword(password)
1199 .build();
1200 proxy = new Proxy(Proxy.TYPE_HTTP, httpServer.getHost(), httpServer.getHttpPort(), auth);
1201 newTransporter("http://" + httpServer.getHost() + ":12/");
1202 try {
1203 transporter.get(new GetTask(URI.create("repo/file.txt")));
1204 fail("Proxy auth must not be used as server auth");
1205 } catch (HttpTransporterException e) {
1206 assertEquals(401, e.getStatusCode());
1207 } catch (IOException e) {
1208
1209 }
1210 }
1211
1212 @Test
1213 protected void testAuthSchemeReuse() throws Exception {
1214 httpServer.setAuthentication("testuser", "testpass");
1215 httpServer.setProxyAuthentication("proxyuser", "proxypass");
1216 session.setCache(new DefaultRepositoryCache());
1217 auth = new AuthenticationBuilder()
1218 .addUsername("testuser")
1219 .addPassword("testpass")
1220 .build();
1221 Authentication auth = new AuthenticationBuilder()
1222 .addUsername("proxyuser")
1223 .addPassword("proxypass")
1224 .build();
1225 proxy = new Proxy(Proxy.TYPE_HTTP, httpServer.getHost(), httpServer.getHttpPort(), auth);
1226 newTransporter("http://bad.localhost:1/");
1227 GetTask task = new GetTask(URI.create("repo/file.txt"));
1228 transporter.get(task);
1229 assertEquals("test", task.getDataString());
1230 assertEquals(3, httpServer.getLogEntries().size());
1231 httpServer.getLogEntries().clear();
1232 newTransporter("http://bad.localhost:1/");
1233 task = new GetTask(URI.create("repo/file.txt"));
1234 transporter.get(task);
1235 assertEquals("test", task.getDataString());
1236 assertEquals(1, httpServer.getLogEntries().size());
1237 assertNotNull(httpServer.getLogEntries().get(0).getHeaders().get("Authorization"));
1238 assertNotNull(httpServer.getLogEntries().get(0).getHeaders().get("Proxy-Authorization"));
1239 }
1240
1241 @Test
1242 protected void testAuthSchemePreemptive() throws Exception {
1243 httpServer.setAuthentication("testuser", "testpass");
1244 session.setCache(new DefaultRepositoryCache());
1245 auth = new AuthenticationBuilder()
1246 .addUsername("testuser")
1247 .addPassword("testpass")
1248 .build();
1249
1250 session.setConfigProperty(ConfigurationProperties.HTTP_PREEMPTIVE_AUTH, false);
1251 newTransporter(httpServer.getHttpUrl());
1252 GetTask task = new GetTask(URI.create("repo/file.txt"));
1253 transporter.get(task);
1254 assertEquals("test", task.getDataString());
1255
1256 assertEquals(2, httpServer.getLogEntries().size());
1257
1258 httpServer.getLogEntries().clear();
1259
1260 session.setConfigProperty(ConfigurationProperties.HTTP_PREEMPTIVE_AUTH, true);
1261 newTransporter(httpServer.getHttpUrl());
1262 task = new GetTask(URI.create("repo/file.txt"));
1263 transporter.get(task);
1264 assertEquals("test", task.getDataString());
1265
1266 assertEquals(1, httpServer.getLogEntries().size());
1267 }
1268
1269 @Test
1270 void testInit_BadProtocol() {
1271 assertThrows(NoTransporterException.class, () -> newTransporter("bad:/void"));
1272 }
1273
1274 @Test
1275 void testInit_BadUrl() {
1276 assertThrows(NoTransporterException.class, () -> newTransporter("http://localhost:NaN"));
1277 }
1278
1279 @Test
1280 void testInit_CaseInsensitiveProtocol() throws Exception {
1281 newTransporter("http://localhost");
1282 newTransporter("HTTP://localhost");
1283 newTransporter("Http://localhost");
1284 newTransporter("https://localhost");
1285 newTransporter("HTTPS://localhost");
1286 newTransporter("HttpS://localhost");
1287 }
1288 }