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