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