View Javadoc

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