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