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