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