001package org.apache.maven.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 org.apache.maven.wagon.authentication.AuthenticationException; 023import org.apache.maven.wagon.authentication.AuthenticationInfo; 024import org.apache.maven.wagon.authorization.AuthorizationException; 025import org.apache.maven.wagon.events.TransferEvent; 026import org.apache.maven.wagon.events.TransferListener; 027import org.apache.maven.wagon.observers.ChecksumObserver; 028import org.apache.maven.wagon.observers.Debug; 029import org.apache.maven.wagon.repository.Repository; 030import org.apache.maven.wagon.repository.RepositoryPermissions; 031import org.apache.maven.wagon.resource.Resource; 032import org.codehaus.plexus.PlexusTestCase; 033import org.codehaus.plexus.util.FileUtils; 034import org.easymock.IAnswer; 035 036// CHECKSTYLE_OFF: AvoidStarImport 037import static org.easymock.EasyMock.*; 038//CHECKSTYLE_ON: AvoidStarImport 039 040import org.slf4j.Logger; 041import org.slf4j.LoggerFactory; 042 043import java.io.File; 044import java.io.IOException; 045import java.nio.charset.StandardCharsets; 046import java.security.NoSuchAlgorithmException; 047import java.text.SimpleDateFormat; 048import java.util.ArrayList; 049import java.util.Collections; 050import java.util.List; 051 052/** 053 * @author <a href="mailto:jason@maven.org">Jason van Zyl</a> 054 */ 055public abstract class WagonTestCase 056 extends PlexusTestCase 057{ 058 protected static Logger logger = LoggerFactory.getLogger( WagonTestCase.class ); 059 060 061 static final class ProgressAnswer implements IAnswer 062 { 063 private int size; 064 065 public Object answer() throws Throwable 066 { 067 int length = (Integer) getCurrentArguments()[2]; 068 size += length; 069 return null; 070 } 071 072 public int getSize() 073 { 074 return size; 075 } 076 } 077 078 protected static final String TEST_CONTENT = "test-resource.txt\n"; 079 080 protected static final String TEST_CKSUM = cksum( TEST_CONTENT ); 081 082 protected static final String POM = "pom.xml"; 083 084 protected Repository localRepository; 085 086 protected Repository testRepository; 087 088 protected String localRepositoryPath; 089 090 protected File sourceFile; 091 092 protected File destFile; 093 094 protected String resource; 095 096 protected boolean testSkipped; 097 098 protected File artifactSourceFile; 099 100 protected File artifactDestFile; 101 102 protected ChecksumObserver checksumObserver; 103 104 protected TransferListener mockTransferListener; 105 106 // ---------------------------------------------------------------------- 107 // Constructors 108 // ---------------------------------------------------------------------- 109 110 protected void setUp() 111 throws Exception 112 { 113 checksumObserver = new ChecksumObserver(); 114 115 mockTransferListener = createMock( TransferListener.class ); 116 117 super.setUp(); 118 } 119 120 // ---------------------------------------------------------------------- 121 // Methods that should be provided by subclasses for proper testing 122 // ---------------------------------------------------------------------- 123 124 /** 125 * URL of the repository. For a complete test it should point to a non existing folder so we also check for the 126 * creation of new folders in the remote site. <p/> return the URL of the repository as specified by Wagon syntax 127 */ 128 protected abstract String getTestRepositoryUrl() 129 throws IOException; 130 131 /** 132 * Protocol id of the Wagon to use, eg. <code>scp</code>, <code>ftp</code> 133 * 134 * @return the protocol id 135 */ 136 protected abstract String getProtocol(); 137 138 // ---------------------------------------------------------------------- 139 // 1. Create a local file repository which mimic a users local file 140 // Repository. 141 // 142 // 2. Create a test repository for the type of wagon we are testing. So, 143 // for example, for testing the file wagon we might have a test 144 // repository url of file://${basedir}/target/file-repository. 145 // ---------------------------------------------------------------------- 146 147 protected void setupRepositories() 148 throws Exception 149 { 150 resource = "test-resource"; 151 152 // ---------------------------------------------------------------------- 153 // Create the test repository for the wagon we are testing. 154 // ---------------------------------------------------------------------- 155 156 testRepository = new Repository(); 157 158 testRepository.setUrl( getTestRepositoryUrl() ); 159 160 testRepository.setPermissions( getPermissions() ); 161 162 // ---------------------------------------------------------------------- 163 // Create a test local repository. 164 // ---------------------------------------------------------------------- 165 166 File file = FileTestUtils.createDir( "local-repository" ); 167 localRepositoryPath = file.getPath(); 168 169 localRepository = createFileRepository( file.toPath().toUri().toASCIIString() ); 170 171 message( "Local repository: " + localRepository ); 172 173 File f = new File( localRepositoryPath ); 174 175 if ( !f.exists() ) 176 { 177 f.mkdirs(); 178 } 179 } 180 181 protected void customizeContext() 182 throws Exception 183 { 184 getContainer().addContextValue( "test.repository", localRepositoryPath ); 185 } 186 187 protected void setupWagonTestingFixtures() 188 throws Exception 189 { 190 } 191 192 protected void tearDownWagonTestingFixtures() 193 throws Exception 194 { 195 } 196 197 // ---------------------------------------------------------------------- 198 // 199 // ---------------------------------------------------------------------- 200 201 protected AuthenticationInfo getAuthInfo() 202 { 203 return new AuthenticationInfo(); 204 } 205 206 protected RepositoryPermissions getPermissions() 207 { 208 return new RepositoryPermissions(); 209 } 210 211 protected Wagon getWagon() 212 throws Exception 213 { 214 Wagon wagon = (Wagon) lookup( Wagon.ROLE, getProtocol() ); 215 216 Debug debug = new Debug(); 217 218 wagon.addSessionListener( debug ); 219 220 wagon.addTransferListener( debug ); 221 222 return wagon; 223 } 224 225 /** 226 * @param cmd the executable to run, not null. 227 * @return <code>true</code> 228 */ 229 public static boolean isSystemCmd( String cmd ) 230 { 231 try 232 { 233 Runtime.getRuntime().exec( cmd ); 234 235 return true; 236 } 237 catch ( IOException e ) 238 { 239 return false; 240 } 241 } 242 243 protected void message( String message ) 244 { 245 logger.info( message ); 246 } 247 248 // ---------------------------------------------------------------------- 249 // 250 // ---------------------------------------------------------------------- 251 252 public void testWagon() 253 throws Exception 254 { 255 setupWagonTestingFixtures(); 256 257 setupRepositories(); 258 259 fileRoundTripTesting(); 260 261 tearDownWagonTestingFixtures(); 262 } 263 264 public void testWagonGetIfNewerIsNewer() 265 throws Exception 266 { 267 if ( supportsGetIfNewer() ) 268 { 269 setupWagonTestingFixtures(); 270 setupRepositories(); 271 int expectedSize = putFile(); 272 // CHECKSTYLE_OFF: MagicNumber 273 getIfNewer( getExpectedLastModifiedOnGet( testRepository, new Resource( resource ) ) + 30000, false, 274 expectedSize ); 275 // CHECKSTYLE_ON: MagicNumber 276 } 277 } 278 279 @Override 280 protected void runTest() 281 throws Throwable 282 { 283 if ( !testSkipped ) 284 { 285 super.runTest(); 286 } 287 } 288 289 protected boolean supportsGetIfNewer() 290 { 291 return true; 292 } 293 294 295 public void testWagonGetIfNewerIsSame() 296 throws Exception 297 { 298 if ( supportsGetIfNewer() ) 299 { 300 setupWagonTestingFixtures(); 301 setupRepositories(); 302 int expectedSize = putFile(); 303 getIfNewer( getExpectedLastModifiedOnGet( testRepository, new Resource( resource ) ), false, expectedSize ); 304 } 305 } 306 307 public void testWagonGetIfNewerIsOlder() 308 throws Exception 309 { 310 if ( supportsGetIfNewer() ) 311 { 312 setupWagonTestingFixtures(); 313 setupRepositories(); 314 int expectedSize = putFile(); 315 getIfNewer( new SimpleDateFormat( "yyyy-MM-dd" ).parse( "2006-01-01" ).getTime(), true, expectedSize ); 316 } 317 } 318 319 private void getIfNewer( long timestamp, boolean expectedResult, int expectedSize ) 320 throws Exception 321 { 322 Wagon wagon = getWagon(); 323 324 ProgressAnswer progressAnswer = setupGetIfNewerTest( wagon, expectedResult, expectedSize ); 325 326 connectWagon( wagon ); 327 328 boolean result = wagon.getIfNewer( this.resource, destFile, timestamp ); 329 assertEquals( expectedResult, result ); 330 331 disconnectWagon( wagon ); 332 333 assertGetIfNewerTest( progressAnswer, expectedResult, expectedSize ); 334 335 tearDownWagonTestingFixtures(); 336 } 337 338 protected ProgressAnswer setupGetIfNewerTest( Wagon wagon, boolean expectedResult, int expectedSize ) 339 throws NoSuchAlgorithmException, IOException 340 { 341 checksumObserver = new ChecksumObserver(); 342 343 destFile = FileTestUtils.createUniqueFile( getName(), getName() ); 344 destFile.delete(); 345 assertFalse( destFile.exists() ); 346 destFile.deleteOnExit(); 347 348 ProgressAnswer progressAnswer = null; 349 if ( expectedResult ) 350 { 351 progressAnswer = replaceMockForGet( wagon, expectedSize ); 352 } 353 else 354 { 355 replaceMockForSkippedGetIfNewer( wagon, expectedSize ); 356 } 357 return progressAnswer; 358 } 359 360 protected void assertGetIfNewerTest( ProgressAnswer progressAnswer, boolean expectedResult, 361 int expectedSize ) 362 throws IOException 363 { 364 if ( expectedResult ) 365 { 366 verifyMock( progressAnswer, expectedSize ); 367 368 assertNotNull( "check checksum is not null", checksumObserver.getActualChecksum() ); 369 370 assertEquals( "compare checksums", TEST_CKSUM, 371 checksumObserver.getActualChecksum() ); 372 373 // Now compare the contents of the artifact that was placed in 374 // the repository with the contents of the artifact that was 375 // retrieved from the repository. 376 377 String sourceContent = FileUtils.fileRead( sourceFile ); 378 String destContent = FileUtils.fileRead( destFile ); 379 assertEquals( sourceContent, destContent ); 380 } 381 else 382 { 383 verify( mockTransferListener ); 384 385 reset( mockTransferListener ); 386 387 assertNull( "check checksum is null", checksumObserver.getActualChecksum() ); 388 389 assertFalse( destFile.exists() ); 390 } 391 } 392 393 394 private void replaceMockForSkippedGetIfNewer( Wagon wagon, int expectedSize ) 395 { 396 Resource resource = new Resource( this.resource ); 397 mockTransferListener.transferInitiated( 398 createTransferEvent( wagon, resource, TransferEvent.TRANSFER_INITIATED, TransferEvent.REQUEST_GET, 399 destFile ) ); 400 resource = new Resource( this.resource ); 401 resource.setContentLength( getExpectedContentLengthOnGet( expectedSize ) ); 402 resource.setLastModified( getExpectedLastModifiedOnGet( testRepository, resource ) ); 403 // TODO: transfer skipped event? 404 // mockTransferListener.transferSkipped( createTransferEvent( wagon, resource, TransferEvent.TRANSFER_STARTED, 405 // TransferEvent.REQUEST_GET, destFile ) ); 406 407 mockTransferListener.debug( anyString() ); 408 expectLastCall().anyTimes(); 409 410 replay( mockTransferListener ); 411 } 412 413 public void testWagonPutDirectory() 414 throws Exception 415 { 416 setupWagonTestingFixtures(); 417 418 setupRepositories(); 419 420 Wagon wagon = getWagon(); 421 422 if ( wagon.supportsDirectoryCopy() ) 423 { 424 sourceFile = new File( FileTestUtils.getTestOutputDir(), "directory-copy" ); 425 426 FileUtils.deleteDirectory( sourceFile ); 427 428 writeTestFile( "test-resource-1.txt" ); 429 writeTestFile( "a/test-resource-2.txt" ); 430 writeTestFile( "a/b/test-resource-3.txt" ); 431 writeTestFile( "c/test-resource-4.txt" ); 432 writeTestFile( "d/e/f/test-resource-5.txt" ); 433 434 wagon.connect( testRepository, getAuthInfo() ); 435 436 wagon.putDirectory( sourceFile, "directory-copy" ); 437 438 destFile = FileTestUtils.createUniqueFile( getName(), getName() ); 439 440 destFile.deleteOnExit(); 441 442 wagon.get( "directory-copy/test-resource-1.txt", destFile ); 443 wagon.get( "directory-copy/a/test-resource-2.txt", destFile ); 444 wagon.get( "directory-copy/a/b/test-resource-3.txt", destFile ); 445 wagon.get( "directory-copy/c/test-resource-4.txt", destFile ); 446 wagon.get( "directory-copy/d/e/f/test-resource-5.txt", destFile ); 447 448 wagon.disconnect(); 449 } 450 451 tearDownWagonTestingFixtures(); 452 } 453 454 /** 455 * Test for putting a directory with a destination that multiple directories deep, all of which haven't been 456 * created. 457 * 458 * @throws Exception 459 * @since 1.0-beta-2 460 */ 461 public void testWagonPutDirectoryDeepDestination() 462 throws Exception 463 { 464 setupWagonTestingFixtures(); 465 466 setupRepositories(); 467 468 Wagon wagon = getWagon(); 469 470 if ( wagon.supportsDirectoryCopy() ) 471 { 472 sourceFile = new File( FileTestUtils.getTestOutputDir(), "deep0/deep1/deep2" ); 473 474 FileUtils.deleteDirectory( sourceFile ); 475 476 writeTestFile( "test-resource-1.txt" ); 477 writeTestFile( "a/test-resource-2.txt" ); 478 writeTestFile( "a/b/test-resource-3.txt" ); 479 writeTestFile( "c/test-resource-4.txt" ); 480 writeTestFile( "d/e/f/test-resource-5.txt" ); 481 482 wagon.connect( testRepository, getAuthInfo() ); 483 484 wagon.putDirectory( sourceFile, "deep0/deep1/deep2" ); 485 486 destFile = FileTestUtils.createUniqueFile( getName(), getName() ); 487 488 destFile.deleteOnExit(); 489 490 wagon.get( "deep0/deep1/deep2/test-resource-1.txt", destFile ); 491 wagon.get( "deep0/deep1/deep2/a/test-resource-2.txt", destFile ); 492 wagon.get( "deep0/deep1/deep2/a/b/test-resource-3.txt", destFile ); 493 wagon.get( "deep0/deep1/deep2/c/test-resource-4.txt", destFile ); 494 wagon.get( "deep0/deep1/deep2/d/e/f/test-resource-5.txt", destFile ); 495 496 wagon.disconnect(); 497 } 498 499 tearDownWagonTestingFixtures(); 500 } 501 502 /** 503 * Test that when putting a directory that already exists new files get also copied 504 * 505 * @throws Exception 506 * @since 1.0-beta-1 507 */ 508 public void testWagonPutDirectoryWhenDirectoryAlreadyExists() 509 throws Exception 510 { 511 512 final String dirName = "directory-copy-existing"; 513 514 final String resourceToCreate = "test-resource-1.txt"; 515 516 final String[] resources = { "a/test-resource-2.txt", "a/b/test-resource-3.txt", "c/test-resource-4.txt" }; 517 518 setupWagonTestingFixtures(); 519 520 setupRepositories(); 521 522 Wagon wagon = getWagon(); 523 524 if ( wagon.supportsDirectoryCopy() ) 525 { 526 sourceFile = new File( FileTestUtils.getTestOutputDir(), dirName ); 527 528 FileUtils.deleteDirectory( sourceFile ); 529 530 createDirectory( wagon, resourceToCreate, dirName ); 531 532 for ( String resource : resources ) 533 { 534 writeTestFile( resource ); 535 } 536 537 wagon.connect( testRepository, getAuthInfo() ); 538 539 wagon.putDirectory( sourceFile, dirName ); 540 541 List<String> resourceNames = new ArrayList<String>( resources.length + 1 ); 542 543 resourceNames.add( dirName + "/" + resourceToCreate ); 544 for ( String resource : resources ) 545 { 546 resourceNames.add( dirName + "/" + resource ); 547 } 548 549 assertResourcesAreInRemoteSide( wagon, resourceNames ); 550 551 wagon.disconnect(); 552 } 553 554 tearDownWagonTestingFixtures(); 555 } 556 557 /** 558 * Test that when putting a directory that already exists new files get also copied and destination is "." 559 * 560 * @throws Exception 561 * @since 1.0-beta-1 562 */ 563 public void testWagonPutDirectoryForDot() 564 throws Exception 565 { 566 final String resourceToCreate = "test-resource-1.txt"; 567 568 final String[] resources = { "a/test-resource-2.txt", "a/b/test-resource-3.txt", "c/test-resource-4.txt" }; 569 570 setupWagonTestingFixtures(); 571 572 setupRepositories(); 573 574 Wagon wagon = getWagon(); 575 576 if ( wagon.supportsDirectoryCopy() ) 577 { 578 sourceFile = new File( FileTestUtils.getTestOutputDir(), "dot-repo" ); 579 580 FileUtils.deleteDirectory( sourceFile ); 581 582 createDirectory( wagon, resourceToCreate, "." ); 583 584 for ( String resource : resources ) 585 { 586 writeTestFile( resource ); 587 } 588 589 wagon.connect( testRepository, getAuthInfo() ); 590 591 wagon.putDirectory( sourceFile, "." ); 592 593 List<String> resourceNames = new ArrayList<String>( resources.length + 1 ); 594 595 resourceNames.add( resourceToCreate ); 596 Collections.addAll( resourceNames, resources ); 597 598 assertResourcesAreInRemoteSide( wagon, resourceNames ); 599 600 wagon.disconnect(); 601 } 602 603 tearDownWagonTestingFixtures(); 604 } 605 606 /** 607 * Create a directory with a resource and check that the other ones don't exist 608 * 609 * @param wagon 610 * @param resourceToCreate name of the resource to be created 611 * @param dirName directory name to create 612 * @throws Exception 613 */ 614 protected void createDirectory( Wagon wagon, String resourceToCreate, String dirName ) 615 throws Exception 616 { 617 writeTestFile( resourceToCreate ); 618 } 619 620 protected void assertResourcesAreInRemoteSide( Wagon wagon, List<String> resourceNames ) 621 throws IOException, TransferFailedException, ResourceDoesNotExistException, AuthorizationException 622 { 623 for ( String resourceName : resourceNames ) 624 { 625 File destFile = FileTestUtils.createUniqueFile( getName(), resourceName ); 626 627 destFile.deleteOnExit(); 628 629 wagon.get( resourceName, destFile ); 630 } 631 } 632 633 /** 634 * Assert that a resource does not exist in the remote wagon system 635 * 636 * @param wagon wagon to get the resource from 637 * @param resourceName name of the resource 638 * @throws IOException if a temp file can't be created 639 * @throws AuthorizationException 640 * @throws TransferFailedException 641 * @since 1.0-beta-1 642 */ 643 protected void assertNotExists( Wagon wagon, String resourceName ) 644 throws IOException, TransferFailedException, AuthorizationException 645 { 646 File tmpFile = File.createTempFile( "wagon", null ); 647 try 648 { 649 wagon.get( resourceName, tmpFile ); 650 fail( "Resource exists: " + resourceName ); 651 } 652 catch ( ResourceDoesNotExistException e ) 653 { 654 // ok 655 } 656 finally 657 { 658 tmpFile.delete(); 659 } 660 } 661 662 private void writeTestFile( String child ) 663 throws IOException 664 { 665 File dir = new File( sourceFile, child ); 666 dir.getParentFile().mkdirs(); 667 FileUtils.fileWrite( dir.getAbsolutePath(), child ); 668 } 669 670 public void testFailedGet() 671 throws Exception 672 { 673 setupWagonTestingFixtures(); 674 675 setupRepositories(); 676 677 message( "Getting test artifact from test repository " + testRepository ); 678 679 Wagon wagon = getWagon(); 680 681 wagon.addTransferListener( checksumObserver ); 682 683 wagon.connect( testRepository, getAuthInfo() ); 684 685 destFile = FileTestUtils.createUniqueFile( getName(), getName() ); 686 687 destFile.deleteOnExit(); 688 689 try 690 { 691 wagon.get( "fubar.txt", destFile ); 692 fail( "File was found when it shouldn't have been" ); 693 } 694 catch ( ResourceDoesNotExistException e ) 695 { 696 // expected 697 assertTrue( true ); 698 } 699 finally 700 { 701 wagon.removeTransferListener( checksumObserver ); 702 703 wagon.disconnect(); 704 705 tearDownWagonTestingFixtures(); 706 } 707 } 708 709 public void testFailedGetIfNewer() 710 throws Exception 711 { 712 if ( supportsGetIfNewer() ) 713 { 714 setupWagonTestingFixtures(); 715 setupRepositories(); 716 message( "Getting test artifact from test repository " + testRepository ); 717 Wagon wagon = getWagon(); 718 wagon.addTransferListener( checksumObserver ); 719 wagon.connect( testRepository, getAuthInfo() ); 720 destFile = FileTestUtils.createUniqueFile( getName(), getName() ); 721 destFile.deleteOnExit(); 722 try 723 { 724 wagon.getIfNewer( "fubar.txt", destFile, 0 ); 725 fail( "File was found when it shouldn't have been" ); 726 } 727 catch ( ResourceDoesNotExistException e ) 728 { 729 // expected 730 assertTrue( true ); 731 } 732 finally 733 { 734 wagon.removeTransferListener( checksumObserver ); 735 736 wagon.disconnect(); 737 738 tearDownWagonTestingFixtures(); 739 } 740 } 741 } 742 743 /** 744 * Test {@link Wagon#getFileList(String)}. 745 * 746 * @throws Exception 747 * @since 1.0-beta-2 748 */ 749 public void testWagonGetFileList() 750 throws Exception 751 { 752 setupWagonTestingFixtures(); 753 754 setupRepositories(); 755 756 String dirName = "file-list"; 757 758 String filenames[] = 759 new String[]{ "test-resource.txt", "test-resource.pom", "test-resource b.txt", "more-resources.dat", 760 ".index.txt" }; 761 762 for ( String filename : filenames ) 763 { 764 putFile( dirName + "/" + filename, dirName + "/" + filename, filename + "\n" ); 765 } 766 767 Wagon wagon = getWagon(); 768 769 wagon.connect( testRepository, getAuthInfo() ); 770 771 List<String> list = wagon.getFileList( dirName ); 772 assertNotNull( "file list should not be null.", list ); 773 assertTrue( "file list should contain more items (actually contains '" + list + "').", 774 list.size() >= filenames.length ); 775 776 for ( String filename : filenames ) 777 { 778 assertTrue( "Filename '" + filename + "' should be in list.", list.contains( filename ) ); 779 } 780 781 // WAGON-250 782 list = wagon.getFileList( "" ); 783 assertNotNull( "file list should not be null.", list ); 784 assertTrue( "file list should contain items (actually contains '" + list + "').", !list.isEmpty() ); 785 assertTrue( list.contains( "file-list/" ) ); 786 assertFalse( list.contains( "file-list" ) ); 787 assertFalse( list.contains( "." ) ); 788 assertFalse( list.contains( ".." ) ); 789 assertFalse( list.contains( "./" ) ); 790 assertFalse( list.contains( "../" ) ); 791 792 wagon.disconnect(); 793 794 tearDownWagonTestingFixtures(); 795 } 796 797 /** 798 * Test {@link Wagon#getFileList(String)} when the directory does not exist. 799 * 800 * @throws Exception 801 * @since 1.0-beta-2 802 */ 803 public void testWagonGetFileListWhenDirectoryDoesNotExist() 804 throws Exception 805 { 806 setupWagonTestingFixtures(); 807 808 setupRepositories(); 809 810 String dirName = "file-list-unexisting"; 811 812 Wagon wagon = getWagon(); 813 814 wagon.connect( testRepository, getAuthInfo() ); 815 816 try 817 { 818 wagon.getFileList( dirName ); 819 fail( "getFileList on unexisting directory must throw ResourceDoesNotExistException" ); 820 } 821 catch ( ResourceDoesNotExistException e ) 822 { 823 // expected 824 } 825 finally 826 { 827 wagon.disconnect(); 828 829 tearDownWagonTestingFixtures(); 830 } 831 } 832 833 /** 834 * Test for an existing resource. 835 * 836 * @throws Exception 837 * @since 1.0-beta-2 838 */ 839 public void testWagonResourceExists() 840 throws Exception 841 { 842 setupWagonTestingFixtures(); 843 844 setupRepositories(); 845 846 Wagon wagon = getWagon(); 847 848 putFile(); 849 850 wagon.connect( testRepository, getAuthInfo() ); 851 852 assertTrue( sourceFile.getName() + " does not exist", wagon.resourceExists( sourceFile.getName() ) ); 853 854 wagon.disconnect(); 855 856 tearDownWagonTestingFixtures(); 857 } 858 859 /** 860 * Test for an invalid resource. 861 * 862 * @throws Exception 863 * @since 1.0-beta-2 864 */ 865 public void testWagonResourceNotExists() 866 throws Exception 867 { 868 setupWagonTestingFixtures(); 869 870 setupRepositories(); 871 872 Wagon wagon = getWagon(); 873 874 wagon.connect( testRepository, getAuthInfo() ); 875 876 assertFalse( wagon.resourceExists( "a/bad/resource/name/that/should/not/exist.txt" ) ); 877 878 wagon.disconnect(); 879 880 tearDownWagonTestingFixtures(); 881 } 882 883 // ---------------------------------------------------------------------- 884 // File <--> File round trip testing 885 // ---------------------------------------------------------------------- 886 // We are testing taking a file, our sourcefile, and placing it into the 887 // test repository that we have setup. 888 // ---------------------------------------------------------------------- 889 890 protected void putFile( String resourceName, String testFileName, String content ) 891 throws Exception 892 { 893 sourceFile = new File( FileTestUtils.getTestOutputDir(), testFileName ); 894 sourceFile.getParentFile().mkdirs(); 895 FileUtils.fileWrite( sourceFile.getAbsolutePath(), content ); 896 897 Wagon wagon = getWagon(); 898 899 ProgressAnswer progressAnswer = replayMockForPut( resourceName, content, wagon ); 900 901 message( "Putting test artifact: " + resourceName + " into test repository " + testRepository ); 902 903 connectWagon( wagon ); 904 905 wagon.put( sourceFile, resourceName ); 906 907 disconnectWagon( wagon ); 908 909 verifyMock( progressAnswer, content.length() ); 910 } 911 912 protected ProgressAnswer replayMockForPut( String resourceName, String content, Wagon wagon ) 913 { 914 Resource resource = new Resource( resourceName ); 915 mockTransferListener.transferInitiated( 916 createTransferEvent( wagon, resource, TransferEvent.TRANSFER_INITIATED, TransferEvent.REQUEST_PUT, 917 sourceFile ) ); 918 resource = new Resource( resourceName ); 919 resource.setContentLength( content.length() ); 920 resource.setLastModified( sourceFile.lastModified() ); 921 mockTransferListener.transferStarted( 922 createTransferEvent( wagon, resource, TransferEvent.TRANSFER_STARTED, TransferEvent.REQUEST_PUT, 923 sourceFile ) ); 924 mockTransferListener.transferProgress( 925 eq( createTransferEvent( wagon, resource, TransferEvent.TRANSFER_PROGRESS, TransferEvent.REQUEST_PUT, 926 sourceFile ) ), anyObject( byte[].class ), anyInt() ); 927 ProgressAnswer progressAnswer = new ProgressAnswer(); 928 expectLastCall().andStubAnswer( progressAnswer ); 929 930 mockTransferListener.debug( anyString() ); 931 expectLastCall().anyTimes(); 932 933 mockTransferListener.transferCompleted( 934 createTransferEvent( wagon, resource, TransferEvent.TRANSFER_COMPLETED, TransferEvent.REQUEST_PUT, 935 sourceFile ) ); 936 937 replay( mockTransferListener ); 938 return progressAnswer; 939 } 940 941 protected TransferEvent createTransferEvent( Wagon wagon, Resource resource, int eventType, int requestType, 942 File file ) 943 { 944 TransferEvent transferEvent = new TransferEvent( wagon, resource, eventType, requestType ); 945 transferEvent.setLocalFile( file ); 946 return transferEvent; 947 } 948 949 protected int putFile() 950 throws Exception 951 { 952 String content = TEST_CONTENT; 953 putFile( resource, "test-resource", content ); 954 return content.length(); 955 } 956 957 protected void getFile( int expectedSize ) 958 throws Exception 959 { 960 destFile = FileTestUtils.createUniqueFile( getName(), getName() ); 961 destFile.deleteOnExit(); 962 963 Wagon wagon = getWagon(); 964 965 ProgressAnswer progressAnswer = replaceMockForGet( wagon, expectedSize ); 966 967 message( "Getting test artifact from test repository " + testRepository ); 968 969 connectWagon( wagon ); 970 971 wagon.get( this.resource, destFile ); 972 973 disconnectWagon( wagon ); 974 975 verifyMock( progressAnswer, expectedSize ); 976 } 977 978 979 protected void verifyMock( ProgressAnswer progressAnswer, int length ) 980 { 981 verify( mockTransferListener ); 982 983 assertEquals( length, progressAnswer.getSize() ); 984 985 reset( mockTransferListener ); 986 } 987 988 protected void disconnectWagon( Wagon wagon ) 989 throws ConnectionException 990 { 991 wagon.removeTransferListener( mockTransferListener ); 992 993 wagon.removeTransferListener( checksumObserver ); 994 995 wagon.disconnect(); 996 } 997 998 protected void connectWagon( Wagon wagon ) 999 throws ConnectionException, AuthenticationException 1000 { 1001 wagon.addTransferListener( checksumObserver ); 1002 1003 wagon.addTransferListener( mockTransferListener ); 1004 1005 wagon.connect( testRepository, getAuthInfo() ); 1006 } 1007 1008 /** 1009 * 1010 * some test (mock on transfertprogress call) relies on the fact that InputStream #read(byte[] b, int off, int len) 1011 * read all bytes. But javadoc says: "" 1012 */ 1013 protected boolean assertOnTransferProgress() 1014 { 1015 return false; 1016 } 1017 1018 protected ProgressAnswer replaceMockForGet( Wagon wagon, int expectedSize ) 1019 { 1020 Resource resource = new Resource( this.resource ); 1021 mockTransferListener.transferInitiated( 1022 createTransferEvent( wagon, resource, TransferEvent.TRANSFER_INITIATED, TransferEvent.REQUEST_GET, 1023 destFile ) ); 1024 resource = new Resource( this.resource ); 1025 resource.setContentLength( getExpectedContentLengthOnGet( expectedSize ) ); 1026 resource.setLastModified( getExpectedLastModifiedOnGet( testRepository, resource ) ); 1027 TransferEvent te = 1028 createTransferEvent( wagon, resource, TransferEvent.TRANSFER_STARTED, TransferEvent.REQUEST_GET, null ); 1029 mockTransferListener.transferStarted( te ); 1030 mockTransferListener.transferProgress( 1031 eq( new TransferEvent( wagon, resource, TransferEvent.TRANSFER_PROGRESS, TransferEvent.REQUEST_GET ) ), 1032 anyObject( byte[].class ), anyInt() ); 1033 1034 ProgressAnswer progressAnswer = new ProgressAnswer(); 1035 1036 if ( assertOnTransferProgress() ) 1037 { 1038 expectLastCall().andAnswer( progressAnswer ); 1039 } 1040 else 1041 { 1042 expectLastCall().andAnswer( progressAnswer ); 1043 expectLastCall().anyTimes(); 1044 } 1045 mockTransferListener.debug( anyString() ); 1046 expectLastCall().anyTimes(); 1047 1048 mockTransferListener.transferCompleted( 1049 createTransferEvent( wagon, resource, TransferEvent.TRANSFER_COMPLETED, TransferEvent.REQUEST_GET, 1050 destFile ) ); 1051 1052 replay( mockTransferListener ); 1053 return progressAnswer; 1054 } 1055 1056 protected int getExpectedContentLengthOnGet( int expectedSize ) 1057 { 1058 return expectedSize; 1059 } 1060 1061 protected long getExpectedLastModifiedOnGet( Repository repository, Resource resource ) 1062 { 1063 // default implementation - prone to failing if the time between test file creation and completion of putFile() 1064 // cross the "second" boundary, causing the "remote" and local files to have different times. 1065 1066 return sourceFile.lastModified(); 1067 } 1068 1069 protected void fileRoundTripTesting() 1070 throws Exception 1071 { 1072 message( "File round trip testing ..." ); 1073 1074 int expectedSize = putFile(); 1075 1076 assertNotNull( "check checksum is not null", checksumObserver.getActualChecksum() ); 1077 1078 assertEquals( "compare checksums", TEST_CKSUM, checksumObserver.getActualChecksum() ); 1079 1080 checksumObserver = new ChecksumObserver(); 1081 1082 getFile( expectedSize ); 1083 1084 assertNotNull( "check checksum is not null", checksumObserver.getActualChecksum() ); 1085 1086 assertEquals( "compare checksums", TEST_CKSUM, checksumObserver.getActualChecksum() ); 1087 1088 // Now compare the conents of the artifact that was placed in 1089 // the repository with the contents of the artifact that was 1090 // retrieved from the repository. 1091 1092 String sourceContent = FileUtils.fileRead( sourceFile ); 1093 1094 String destContent = FileUtils.fileRead( destFile ); 1095 1096 assertEquals( sourceContent, destContent ); 1097 } 1098 1099 // ---------------------------------------------------------------------- 1100 // 1101 // ---------------------------------------------------------------------- 1102 1103 protected Repository createFileRepository( String url ) 1104 { 1105 File path = new File( url.substring( 7 ) ); 1106 1107 path.mkdirs(); 1108 1109 Repository repository = new Repository(); 1110 1111 repository.setUrl( url ); 1112 1113 return repository; 1114 } 1115 1116 protected static String cksum( String content ) 1117 { 1118 String checkSum; 1119 try 1120 { 1121 ChecksumObserver obs = new ChecksumObserver(); 1122 byte[] buf = content.getBytes( StandardCharsets.ISO_8859_1 ); 1123 obs.transferProgress( null, buf, buf.length ); 1124 obs.transferCompleted( null ); 1125 checkSum = obs.getActualChecksum(); 1126 } 1127 catch ( Exception e ) 1128 { 1129 checkSum = null; 1130 } 1131 return checkSum; 1132 } 1133 1134}