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