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