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