001package org.apache.maven.wagon;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import org.apache.log4j.Logger;
023import org.apache.maven.wagon.authentication.AuthenticationException;
024import org.apache.maven.wagon.authentication.AuthenticationInfo;
025import org.apache.maven.wagon.authorization.AuthorizationException;
026import org.apache.maven.wagon.events.TransferEvent;
027import org.apache.maven.wagon.events.TransferListener;
028import org.apache.maven.wagon.observers.ChecksumObserver;
029import org.apache.maven.wagon.observers.Debug;
030import org.apache.maven.wagon.repository.Repository;
031import org.apache.maven.wagon.repository.RepositoryPermissions;
032import org.apache.maven.wagon.resource.Resource;
033import org.codehaus.plexus.PlexusTestCase;
034import org.codehaus.plexus.util.FileUtils;
035import org.easymock.IAnswer;
036
037import static org.easymock.EasyMock.*;
038
039import java.io.File;
040import java.io.IOException;
041import java.security.NoSuchAlgorithmException;
042import java.text.SimpleDateFormat;
043import java.util.ArrayList;
044import java.util.Collections;
045import java.util.List;
046
047/**
048 * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
049 */
050public abstract class WagonTestCase
051    extends PlexusTestCase
052{
053    protected static Logger logger = Logger.getLogger( WagonTestCase.class );
054
055
056    static final class ProgressAnswer implements IAnswer
057    {
058        private int size;
059        
060        public Object answer() throws Throwable
061        {
062            int length = (Integer) getCurrentArguments()[2];
063            size += length;
064            return null;
065        }
066
067        public int getSize()
068        {
069            return size;
070        }
071    }
072
073    protected static String POM = "pom.xml";
074
075    protected Repository localRepository;
076
077    protected Repository testRepository;
078
079    protected String localRepositoryPath;
080
081    protected File sourceFile;
082
083    protected File destFile;
084
085    protected String resource;
086
087    protected File artifactSourceFile;
088
089    protected File artifactDestFile;
090
091    protected ChecksumObserver checksumObserver;
092
093    protected TransferListener mockTransferListener;
094
095    // ----------------------------------------------------------------------
096    // Constructors
097    // ----------------------------------------------------------------------
098
099    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}