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