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