001package org.eclipse.aether.transport.wagon; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import static org.junit.Assert.assertEquals; 023import static org.junit.Assert.assertTrue; 024import static org.junit.Assert.fail; 025 026import java.io.File; 027import java.net.URI; 028import java.nio.charset.StandardCharsets; 029import java.util.Map; 030import java.util.UUID; 031 032import org.apache.maven.wagon.ResourceDoesNotExistException; 033import org.apache.maven.wagon.TransferFailedException; 034import org.apache.maven.wagon.Wagon; 035import org.eclipse.aether.ConfigurationProperties; 036import org.eclipse.aether.DefaultRepositorySystemSession; 037import org.eclipse.aether.internal.test.util.TestFileUtils; 038import org.eclipse.aether.internal.test.util.TestLoggerFactory; 039import org.eclipse.aether.internal.test.util.TestUtils; 040import org.eclipse.aether.repository.Authentication; 041import org.eclipse.aether.repository.Proxy; 042import org.eclipse.aether.repository.RemoteRepository; 043import org.eclipse.aether.spi.connector.transport.GetTask; 044import org.eclipse.aether.spi.connector.transport.PeekTask; 045import org.eclipse.aether.spi.connector.transport.PutTask; 046import org.eclipse.aether.spi.connector.transport.Transporter; 047import org.eclipse.aether.spi.connector.transport.TransporterFactory; 048import org.eclipse.aether.transfer.NoTransporterException; 049import org.eclipse.aether.transfer.TransferCancelledException; 050import org.eclipse.aether.util.repository.AuthenticationBuilder; 051import org.junit.After; 052import org.junit.Before; 053import org.junit.Test; 054 055/** 056 */ 057public abstract class AbstractWagonTransporterTest 058{ 059 060 private DefaultRepositorySystemSession session; 061 062 private TransporterFactory factory; 063 064 private Transporter transporter; 065 066 private String id; 067 068 private Map<String, String> fs; 069 070 protected abstract Wagon newWagon(); 071 072 private RemoteRepository newRepo( String url ) 073 { 074 return new RemoteRepository.Builder( "test", "default", url ).build(); 075 } 076 077 private void newTransporter( String url ) 078 throws Exception 079 { 080 newTransporter( newRepo( url ) ); 081 } 082 083 private void newTransporter( RemoteRepository repo ) 084 throws Exception 085 { 086 if ( transporter != null ) 087 { 088 transporter.close(); 089 transporter = null; 090 } 091 transporter = factory.newInstance( session, repo ); 092 } 093 094 @Before 095 public void setUp() 096 throws Exception 097 { 098 session = TestUtils.newSession(); 099 factory = new WagonTransporterFactory( new WagonProvider() 100 { 101 public Wagon lookup( String roleHint ) 102 throws Exception 103 { 104 if ( "mem".equalsIgnoreCase( roleHint ) ) 105 { 106 return newWagon(); 107 } 108 throw new IllegalArgumentException( "unknown wagon role: " + roleHint ); 109 } 110 111 public void release( Wagon wagon ) 112 { 113 } 114 }, new WagonConfigurator() 115 { 116 public void configure( Wagon wagon, Object configuration ) 117 throws Exception 118 { 119 ( (Configurable) wagon ).setConfiguration( configuration ); 120 } 121 }, new TestLoggerFactory() ); 122 id = UUID.randomUUID().toString().replace( "-", "" ); 123 fs = MemWagonUtils.getFilesystem( id ); 124 fs.put( "file.txt", "test" ); 125 fs.put( "empty.txt", "" ); 126 fs.put( "some space.txt", "space" ); 127 newTransporter( "mem://" + id ); 128 } 129 130 @After 131 public void tearDown() 132 { 133 if ( transporter != null ) 134 { 135 transporter.close(); 136 transporter = null; 137 } 138 factory = null; 139 session = null; 140 } 141 142 @Test 143 public void testClassify() 144 { 145 assertEquals( Transporter.ERROR_OTHER, transporter.classify( new TransferFailedException( "test" ) ) ); 146 assertEquals( Transporter.ERROR_NOT_FOUND, transporter.classify( new ResourceDoesNotExistException( "test" ) ) ); 147 } 148 149 @Test 150 public void testPeek() 151 throws Exception 152 { 153 transporter.peek( new PeekTask( URI.create( "file.txt" ) ) ); 154 } 155 156 @Test 157 public void testPeek_NotFound() 158 throws Exception 159 { 160 try 161 { 162 transporter.peek( new PeekTask( URI.create( "missing.txt" ) ) ); 163 fail( "Expected error" ); 164 } 165 catch ( ResourceDoesNotExistException e ) 166 { 167 assertEquals( Transporter.ERROR_NOT_FOUND, transporter.classify( e ) ); 168 } 169 } 170 171 @Test 172 public void testPeek_Closed() 173 throws Exception 174 { 175 transporter.close(); 176 try 177 { 178 transporter.peek( new PeekTask( URI.create( "missing.txt" ) ) ); 179 fail( "Expected error" ); 180 } 181 catch ( IllegalStateException e ) 182 { 183 assertEquals( Transporter.ERROR_OTHER, transporter.classify( e ) ); 184 } 185 } 186 187 @Test 188 public void testGet_ToMemory() 189 throws Exception 190 { 191 RecordingTransportListener listener = new RecordingTransportListener(); 192 GetTask task = new GetTask( URI.create( "file.txt" ) ).setListener( listener ); 193 transporter.get( task ); 194 assertEquals( "test", task.getDataString() ); 195 assertEquals( 0L, listener.dataOffset ); 196 assertEquals( 4L, listener.dataLength ); 197 assertEquals( 1, listener.startedCount ); 198 assertTrue( "Count: " + listener.progressedCount, listener.progressedCount > 0 ); 199 assertEquals( task.getDataString(), new String( listener.baos.toByteArray(), StandardCharsets.UTF_8 ) ); 200 } 201 202 @Test 203 public void testGet_ToFile() 204 throws Exception 205 { 206 File file = TestFileUtils.createTempFile( "failure" ); 207 RecordingTransportListener listener = new RecordingTransportListener(); 208 GetTask task = new GetTask( URI.create( "file.txt" ) ).setDataFile( file ).setListener( listener ); 209 transporter.get( task ); 210 assertEquals( "test", TestFileUtils.readString( file ) ); 211 assertEquals( 0L, listener.dataOffset ); 212 assertEquals( 4L, listener.dataLength ); 213 assertEquals( 1, listener.startedCount ); 214 assertTrue( "Count: " + listener.progressedCount, listener.progressedCount > 0 ); 215 assertEquals( "test", new String( listener.baos.toByteArray(), StandardCharsets.UTF_8 ) ); 216 } 217 218 @Test 219 public void testGet_EmptyResource() 220 throws Exception 221 { 222 File file = TestFileUtils.createTempFile( "failure" ); 223 assertTrue( file.delete() && !file.exists() ); 224 RecordingTransportListener listener = new RecordingTransportListener(); 225 GetTask task = new GetTask( URI.create( "empty.txt" ) ).setDataFile( file ).setListener( listener ); 226 transporter.get( task ); 227 assertEquals( "", TestFileUtils.readString( file ) ); 228 assertEquals( 0L, listener.dataOffset ); 229 assertEquals( 0L, listener.dataLength ); 230 assertEquals( 1, listener.startedCount ); 231 assertEquals( 0, listener.progressedCount ); 232 assertEquals( "", new String( listener.baos.toByteArray(), StandardCharsets.UTF_8 ) ); 233 } 234 235 @Test 236 public void testGet_EncodedResourcePath() 237 throws Exception 238 { 239 GetTask task = new GetTask( URI.create( "some%20space.txt" ) ); 240 transporter.get( task ); 241 assertEquals( "space", task.getDataString() ); 242 } 243 244 @Test 245 public void testGet_FileHandleLeak() 246 throws Exception 247 { 248 for ( int i = 0; i < 100; i++ ) 249 { 250 File file = TestFileUtils.createTempFile( "failure" ); 251 transporter.get( new GetTask( URI.create( "file.txt" ) ).setDataFile( file ) ); 252 assertTrue( i + ", " + file.getAbsolutePath(), file.delete() ); 253 } 254 } 255 256 @Test 257 public void testGet_NotFound() 258 throws Exception 259 { 260 try 261 { 262 transporter.get( new GetTask( URI.create( "missing.txt" ) ) ); 263 fail( "Expected error" ); 264 } 265 catch ( ResourceDoesNotExistException e ) 266 { 267 assertEquals( Transporter.ERROR_NOT_FOUND, transporter.classify( e ) ); 268 } 269 } 270 271 @Test 272 public void testGet_Closed() 273 throws Exception 274 { 275 transporter.close(); 276 try 277 { 278 transporter.get( new GetTask( URI.create( "file.txt" ) ) ); 279 fail( "Expected error" ); 280 } 281 catch ( IllegalStateException e ) 282 { 283 assertEquals( Transporter.ERROR_OTHER, transporter.classify( e ) ); 284 } 285 } 286 287 @Test 288 public void testGet_StartCancelled() 289 throws Exception 290 { 291 RecordingTransportListener listener = new RecordingTransportListener(); 292 listener.cancelStart = true; 293 GetTask task = new GetTask( URI.create( "file.txt" ) ).setListener( listener ); 294 transporter.get( task ); 295 assertEquals( 1, listener.startedCount ); 296 } 297 298 @Test 299 public void testGet_ProgressCancelled() 300 throws Exception 301 { 302 RecordingTransportListener listener = new RecordingTransportListener(); 303 listener.cancelProgress = true; 304 GetTask task = new GetTask( URI.create( "file.txt" ) ).setListener( listener ); 305 try 306 { 307 transporter.get( task ); 308 fail( "Expected error" ); 309 } 310 catch ( TransferCancelledException e ) 311 { 312 assertEquals( Transporter.ERROR_OTHER, transporter.classify( e ) ); 313 } 314 assertEquals( 0L, listener.dataOffset ); 315 assertEquals( 4L, listener.dataLength ); 316 assertEquals( 1, listener.startedCount ); 317 assertEquals( 1, listener.progressedCount ); 318 } 319 320 @Test 321 public void testPut_FromMemory() 322 throws Exception 323 { 324 RecordingTransportListener listener = new RecordingTransportListener(); 325 PutTask task = new PutTask( URI.create( "file.txt" ) ).setListener( listener ).setDataString( "upload" ); 326 transporter.put( task ); 327 assertEquals( 0L, listener.dataOffset ); 328 assertEquals( 6L, listener.dataLength ); 329 assertEquals( 1, listener.startedCount ); 330 assertTrue( "Count: " + listener.progressedCount, listener.progressedCount > 0 ); 331 assertEquals( "upload", fs.get( "file.txt" ) ); 332 } 333 334 @Test 335 public void testPut_FromFile() 336 throws Exception 337 { 338 File file = TestFileUtils.createTempFile( "upload" ); 339 RecordingTransportListener listener = new RecordingTransportListener(); 340 PutTask task = new PutTask( URI.create( "file.txt" ) ).setListener( listener ).setDataFile( file ); 341 transporter.put( task ); 342 assertEquals( 0L, listener.dataOffset ); 343 assertEquals( 6L, listener.dataLength ); 344 assertEquals( 1, listener.startedCount ); 345 assertTrue( "Count: " + listener.progressedCount, listener.progressedCount > 0 ); 346 assertEquals( "upload", fs.get( "file.txt" ) ); 347 } 348 349 @Test 350 public void testPut_EmptyResource() 351 throws Exception 352 { 353 RecordingTransportListener listener = new RecordingTransportListener(); 354 PutTask task = new PutTask( URI.create( "file.txt" ) ).setListener( listener ); 355 transporter.put( task ); 356 assertEquals( 0L, listener.dataOffset ); 357 assertEquals( 0L, listener.dataLength ); 358 assertEquals( 1, listener.startedCount ); 359 assertEquals( 0, listener.progressedCount ); 360 assertEquals( "", fs.get( "file.txt" ) ); 361 } 362 363 @Test 364 public void testPut_NonExistentParentDir() 365 throws Exception 366 { 367 RecordingTransportListener listener = new RecordingTransportListener(); 368 PutTask task = 369 new PutTask( URI.create( "dir/sub/dir/file.txt" ) ).setListener( listener ).setDataString( "upload" ); 370 transporter.put( task ); 371 assertEquals( 0L, listener.dataOffset ); 372 assertEquals( 6L, listener.dataLength ); 373 assertEquals( 1, listener.startedCount ); 374 assertTrue( "Count: " + listener.progressedCount, listener.progressedCount > 0 ); 375 assertEquals( "upload", fs.get( "dir/sub/dir/file.txt" ) ); 376 } 377 378 @Test 379 public void testPut_EncodedResourcePath() 380 throws Exception 381 { 382 RecordingTransportListener listener = new RecordingTransportListener(); 383 PutTask task = new PutTask( URI.create( "some%20space.txt" ) ).setListener( listener ).setDataString( "OK" ); 384 transporter.put( task ); 385 assertEquals( 0L, listener.dataOffset ); 386 assertEquals( 2L, listener.dataLength ); 387 assertEquals( 1, listener.startedCount ); 388 assertTrue( "Count: " + listener.progressedCount, listener.progressedCount > 0 ); 389 assertEquals( "OK", fs.get( "some space.txt" ) ); 390 } 391 392 @Test 393 public void testPut_FileHandleLeak() 394 throws Exception 395 { 396 for ( int i = 0; i < 100; i++ ) 397 { 398 File src = TestFileUtils.createTempFile( "upload" ); 399 transporter.put( new PutTask( URI.create( "file.txt" ) ).setDataFile( src ) ); 400 assertTrue( i + ", " + src.getAbsolutePath(), src.delete() ); 401 } 402 } 403 404 @Test 405 public void testPut_Closed() 406 throws Exception 407 { 408 transporter.close(); 409 try 410 { 411 transporter.put( new PutTask( URI.create( "missing.txt" ) ) ); 412 fail( "Expected error" ); 413 } 414 catch ( IllegalStateException e ) 415 { 416 assertEquals( Transporter.ERROR_OTHER, transporter.classify( e ) ); 417 } 418 } 419 420 @Test 421 public void testPut_StartCancelled() 422 throws Exception 423 { 424 RecordingTransportListener listener = new RecordingTransportListener(); 425 listener.cancelStart = true; 426 PutTask task = new PutTask( URI.create( "file.txt" ) ).setListener( listener ).setDataString( "upload" ); 427 transporter.put( task ); 428 assertEquals( 1, listener.startedCount ); 429 } 430 431 @Test 432 public void testPut_ProgressCancelled() 433 throws Exception 434 { 435 RecordingTransportListener listener = new RecordingTransportListener(); 436 listener.cancelProgress = true; 437 PutTask task = new PutTask( URI.create( "file.txt" ) ).setListener( listener ).setDataString( "upload" ); 438 try 439 { 440 transporter.put( task ); 441 fail( "Expected error" ); 442 } 443 catch ( TransferCancelledException e ) 444 { 445 assertEquals( Transporter.ERROR_OTHER, transporter.classify( e ) ); 446 } 447 assertEquals( 0L, listener.dataOffset ); 448 assertEquals( 6L, listener.dataLength ); 449 assertEquals( 1, listener.startedCount ); 450 assertEquals( 1, listener.progressedCount ); 451 } 452 453 @Test( expected = NoTransporterException.class ) 454 public void testInit_BadProtocol() 455 throws Exception 456 { 457 newTransporter( "bad:/void" ); 458 } 459 460 @Test 461 public void testInit_CaseInsensitiveProtocol() 462 throws Exception 463 { 464 newTransporter( "mem:/void" ); 465 newTransporter( "MEM:/void" ); 466 newTransporter( "mEm:/void" ); 467 } 468 469 @Test 470 public void testInit_Configuration() 471 throws Exception 472 { 473 session.setConfigProperty( "aether.connector.wagon.config.test", "passed" ); 474 newTransporter( "mem://" + id + "?config=passed" ); 475 transporter.peek( new PeekTask( URI.create( "file.txt" ) ) ); 476 } 477 478 @Test 479 public void testInit_UserAgent() 480 throws Exception 481 { 482 session.setConfigProperty( ConfigurationProperties.USER_AGENT, "Test/1.0" ); 483 newTransporter( "mem://" + id + "?userAgent=Test/1.0" ); 484 transporter.peek( new PeekTask( URI.create( "file.txt" ) ) ); 485 } 486 487 @Test 488 public void testInit_Timeout() 489 throws Exception 490 { 491 session.setConfigProperty( ConfigurationProperties.REQUEST_TIMEOUT, "12345678" ); 492 newTransporter( "mem://" + id + "?requestTimeout=12345678" ); 493 transporter.peek( new PeekTask( URI.create( "file.txt" ) ) ); 494 } 495 496 @Test 497 public void testInit_ServerAuth() 498 throws Exception 499 { 500 String url = 501 "mem://" + id + "?serverUsername=testuser&serverPassword=testpass" 502 + "&serverPrivateKey=testkey&serverPassphrase=testphrase"; 503 Authentication auth = 504 new AuthenticationBuilder().addUsername( "testuser" ).addPassword( "testpass" ).addPrivateKey( "testkey", 505 "testphrase" ).build(); 506 RemoteRepository repo = 507 new RemoteRepository.Builder( "test", "default", url ).setAuthentication( auth ).build(); 508 newTransporter( repo ); 509 transporter.peek( new PeekTask( URI.create( "file.txt" ) ) ); 510 } 511 512 @Test 513 public void testInit_Proxy() 514 throws Exception 515 { 516 String url = "mem://" + id + "?proxyHost=testhost&proxyPort=8888"; 517 RemoteRepository repo = 518 new RemoteRepository.Builder( "test", "default", url ).setProxy( new Proxy( "http", "testhost", 8888 ) ).build(); 519 newTransporter( repo ); 520 transporter.peek( new PeekTask( URI.create( "file.txt" ) ) ); 521 } 522 523 @Test 524 public void testInit_ProxyAuth() 525 throws Exception 526 { 527 String url = "mem://" + id + "?proxyUsername=testuser&proxyPassword=testpass"; 528 Authentication auth = new AuthenticationBuilder().addUsername( "testuser" ).addPassword( "testpass" ).build(); 529 RemoteRepository repo = 530 new RemoteRepository.Builder( "test", "default", url ).setProxy( new Proxy( "http", "testhost", 8888, auth ) ).build(); 531 newTransporter( repo ); 532 transporter.peek( new PeekTask( URI.create( "file.txt" ) ) ); 533 } 534 535}