/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.maven.wagon;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.maven.wagon.authentication.AuthenticationException;
import org.apache.maven.wagon.authentication.AuthenticationInfo;
import org.apache.maven.wagon.authorization.AuthorizationException;
import org.apache.maven.wagon.events.TransferEvent;
import org.apache.maven.wagon.events.TransferListener;
import org.apache.maven.wagon.observers.ChecksumObserver;
import org.apache.maven.wagon.observers.Debug;
import org.apache.maven.wagon.repository.Repository;
import org.apache.maven.wagon.repository.RepositoryPermissions;
import org.apache.maven.wagon.resource.Resource;
import org.codehaus.plexus.PlexusTestCase;
import org.codehaus.plexus.util.FileUtils;
import org.easymock.IAnswer;
import org.junit.Assume;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.easymock.EasyMock.*;

/**
 * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
 */
public abstract class WagonTestCase extends PlexusTestCase {
    protected static Logger logger = LoggerFactory.getLogger(WagonTestCase.class);

    static final class ProgressAnswer implements IAnswer {
        private int size;

        public Object answer() throws Throwable {
            int length = (Integer) getCurrentArguments()[2];
            size += length;
            return null;
        }

        public int getSize() {
            return size;
        }
    }

    protected static final String TEST_CONTENT = "test-resource.txt\n";

    protected static final String TEST_CKSUM = cksum(TEST_CONTENT);

    protected static final String POM = "pom.xml";

    protected Repository localRepository;

    protected Repository testRepository;

    protected String localRepositoryPath;

    protected File sourceFile;

    protected File destFile;

    protected String resource;

    protected boolean testSkipped;

    protected File artifactSourceFile;

    protected File artifactDestFile;

    protected ChecksumObserver checksumObserver;

    protected TransferListener mockTransferListener;

    // ----------------------------------------------------------------------
    // Constructors
    // ----------------------------------------------------------------------

    protected void setUp() throws Exception {
        checksumObserver = new ChecksumObserver();

        mockTransferListener = createMock(TransferListener.class);

        super.setUp();
    }

    // ----------------------------------------------------------------------
    // Methods that should be provided by subclasses for proper testing
    // ----------------------------------------------------------------------

    /**
     * URL of the repository. For a complete test it should point to a non existing folder so we also check for the
     * creation of new folders in the remote site. <p/> return the URL of the repository as specified by Wagon syntax
     */
    protected abstract String getTestRepositoryUrl() throws IOException;

    /**
     * Protocol id of the Wagon to use, eg. <code>scp</code>, <code>ftp</code>
     *
     * @return the protocol id
     */
    protected abstract String getProtocol();

    // ----------------------------------------------------------------------
    // 1. Create a local file repository which mimic a users local file
    // Repository.
    //
    // 2. Create a test repository for the type of wagon we are testing. So,
    // for example, for testing the file wagon we might have a test
    // repository url of file://${basedir}/target/file-repository.
    // ----------------------------------------------------------------------

    protected void setupRepositories() throws Exception {
        resource = "test-resource";

        // ----------------------------------------------------------------------
        // Create the test repository for the wagon we are testing.
        // ----------------------------------------------------------------------

        testRepository = new Repository();

        testRepository.setUrl(getTestRepositoryUrl());

        testRepository.setPermissions(getPermissions());

        // ----------------------------------------------------------------------
        // Create a test local repository.
        // ----------------------------------------------------------------------

        File file = FileTestUtils.createDir("local-repository");
        localRepositoryPath = file.getPath();

        localRepository = createFileRepository(file.toPath().toUri().toASCIIString());

        message("Local repository: " + localRepository);

        File f = new File(localRepositoryPath);

        if (!f.exists()) {
            f.mkdirs();
        }
    }

    protected void customizeContext() throws Exception {
        getContainer().addContextValue("test.repository", localRepositoryPath);
    }

    protected void setupWagonTestingFixtures() throws Exception {}

    protected void tearDownWagonTestingFixtures() throws Exception {}

    // ----------------------------------------------------------------------
    //
    // ----------------------------------------------------------------------

    protected AuthenticationInfo getAuthInfo() {
        return new AuthenticationInfo();
    }

    protected RepositoryPermissions getPermissions() {
        return new RepositoryPermissions();
    }

    protected Wagon getWagon() throws Exception {
        Wagon wagon = (Wagon) lookup(Wagon.ROLE, getProtocol());

        Debug debug = new Debug();

        wagon.addSessionListener(debug);

        wagon.addTransferListener(debug);

        return wagon;
    }

    /**
     * @param cmd the executable to run, not null.
     * @return <code>true</code>
     */
    public static boolean isSystemCmd(String cmd) {
        try {
            Runtime.getRuntime().exec(cmd);

            return true;
        } catch (IOException e) {
            return false;
        }
    }

    protected void message(String message) {
        logger.info(message);
    }

    // ----------------------------------------------------------------------
    //
    // ----------------------------------------------------------------------

    public void testWagon() throws Exception {
        setupWagonTestingFixtures();

        setupRepositories();

        fileRoundTripTesting();

        tearDownWagonTestingFixtures();
    }

    public void testWagonGetIfNewerIsNewer() throws Exception {
        if (supportsGetIfNewer()) {
            setupWagonTestingFixtures();
            setupRepositories();
            int expectedSize = putFile();
            // CHECKSTYLE_OFF: MagicNumber
            getIfNewer(
                    getExpectedLastModifiedOnGet(testRepository, new Resource(resource)) + 30000, false, expectedSize);
            // CHECKSTYLE_ON: MagicNumber
        }
    }

    @Override
    protected void runTest() throws Throwable {
        if (!testSkipped) {
            super.runTest();
        }
    }

    protected boolean supportsGetIfNewer() {
        return true;
    }

    public void testWagonGetIfNewerIsSame() throws Exception {
        if (supportsGetIfNewer()) {
            setupWagonTestingFixtures();
            setupRepositories();
            int expectedSize = putFile();
            getIfNewer(getExpectedLastModifiedOnGet(testRepository, new Resource(resource)), false, expectedSize);
        }
    }

    public void testWagonGetIfNewerIsOlder() throws Exception {
        if (supportsGetIfNewer()) {
            setupWagonTestingFixtures();
            setupRepositories();
            int expectedSize = putFile();
            getIfNewer(new SimpleDateFormat("yyyy-MM-dd").parse("2006-01-01").getTime(), true, expectedSize);
        }
    }

    private void getIfNewer(long timestamp, boolean expectedResult, int expectedSize) throws Exception {
        Wagon wagon = getWagon();

        ProgressAnswer progressAnswer = setupGetIfNewerTest(wagon, expectedResult, expectedSize);

        connectWagon(wagon);

        boolean result = wagon.getIfNewer(this.resource, destFile, timestamp);
        assertEquals(expectedResult, result);

        disconnectWagon(wagon);

        assertGetIfNewerTest(progressAnswer, expectedResult, expectedSize);

        tearDownWagonTestingFixtures();
    }

    protected ProgressAnswer setupGetIfNewerTest(Wagon wagon, boolean expectedResult, int expectedSize)
            throws NoSuchAlgorithmException, IOException {
        checksumObserver = new ChecksumObserver();

        destFile = FileTestUtils.createUniqueFile(getName(), getName());
        destFile.delete();
        assertFalse(destFile.exists());
        destFile.deleteOnExit();

        ProgressAnswer progressAnswer = null;
        if (expectedResult) {
            progressAnswer = replaceMockForGet(wagon, expectedSize);
        } else {
            replaceMockForSkippedGetIfNewer(wagon, expectedSize);
        }
        return progressAnswer;
    }

    protected void assertGetIfNewerTest(ProgressAnswer progressAnswer, boolean expectedResult, int expectedSize)
            throws IOException {
        if (expectedResult) {
            verifyMock(progressAnswer, expectedSize);

            assertNotNull("check checksum is not null", checksumObserver.getActualChecksum());

            assertEquals("compare checksums", TEST_CKSUM, checksumObserver.getActualChecksum());

            // Now compare the contents of the artifact that was placed in
            // the repository with the contents of the artifact that was
            // retrieved from the repository.

            String sourceContent = FileUtils.fileRead(sourceFile);
            String destContent = FileUtils.fileRead(destFile);
            assertEquals(sourceContent, destContent);
        } else {
            verify(mockTransferListener);

            reset(mockTransferListener);

            assertNull("check checksum is null", checksumObserver.getActualChecksum());

            assertFalse(destFile.exists());
        }
    }

    private void replaceMockForSkippedGetIfNewer(Wagon wagon, int expectedSize) {
        Resource resource = new Resource(this.resource);
        mockTransferListener.transferInitiated(createTransferEvent(
                wagon, resource, TransferEvent.TRANSFER_INITIATED, TransferEvent.REQUEST_GET, destFile));
        resource = new Resource(this.resource);
        resource.setContentLength(getExpectedContentLengthOnGet(expectedSize));
        resource.setLastModified(getExpectedLastModifiedOnGet(testRepository, resource));
        // TODO: transfer skipped event?
        // mockTransferListener.transferSkipped( createTransferEvent( wagon, resource, TransferEvent.TRANSFER_STARTED,
        // TransferEvent.REQUEST_GET, destFile ) );

        mockTransferListener.debug(anyString());
        expectLastCall().anyTimes();

        replay(mockTransferListener);
    }

    public void testWagonPutDirectory() throws Exception {
        setupWagonTestingFixtures();

        setupRepositories();

        Wagon wagon = getWagon();

        if (wagon.supportsDirectoryCopy()) {
            sourceFile = new File(FileTestUtils.getTestOutputDir(), "directory-copy");

            FileUtils.deleteDirectory(sourceFile);

            writeTestFile("test-resource-1.txt");
            writeTestFile("a/test-resource-2.txt");
            writeTestFile("a/b/test-resource-3.txt");
            writeTestFile("c/test-resource-4.txt");
            writeTestFile("d/e/f/test-resource-5.txt");

            wagon.connect(testRepository, getAuthInfo());

            wagon.putDirectory(sourceFile, "directory-copy");

            destFile = FileTestUtils.createUniqueFile(getName(), getName());

            destFile.deleteOnExit();

            wagon.get("directory-copy/test-resource-1.txt", destFile);
            wagon.get("directory-copy/a/test-resource-2.txt", destFile);
            wagon.get("directory-copy/a/b/test-resource-3.txt", destFile);
            wagon.get("directory-copy/c/test-resource-4.txt", destFile);
            wagon.get("directory-copy/d/e/f/test-resource-5.txt", destFile);

            wagon.disconnect();
        }

        tearDownWagonTestingFixtures();
    }

    /**
     * Test for putting a directory with a destination that multiple directories deep, all of which haven't been
     * created.
     *
     * @throws Exception
     * @since 1.0-beta-2
     */
    public void testWagonPutDirectoryDeepDestination() throws Exception {
        setupWagonTestingFixtures();

        setupRepositories();

        Wagon wagon = getWagon();

        if (wagon.supportsDirectoryCopy()) {
            sourceFile = new File(FileTestUtils.getTestOutputDir(), "deep0/deep1/deep2");

            FileUtils.deleteDirectory(sourceFile);

            writeTestFile("test-resource-1.txt");
            writeTestFile("a/test-resource-2.txt");
            writeTestFile("a/b/test-resource-3.txt");
            writeTestFile("c/test-resource-4.txt");
            writeTestFile("d/e/f/test-resource-5.txt");

            wagon.connect(testRepository, getAuthInfo());

            wagon.putDirectory(sourceFile, "deep0/deep1/deep2");

            destFile = FileTestUtils.createUniqueFile(getName(), getName());

            destFile.deleteOnExit();

            wagon.get("deep0/deep1/deep2/test-resource-1.txt", destFile);
            wagon.get("deep0/deep1/deep2/a/test-resource-2.txt", destFile);
            wagon.get("deep0/deep1/deep2/a/b/test-resource-3.txt", destFile);
            wagon.get("deep0/deep1/deep2/c/test-resource-4.txt", destFile);
            wagon.get("deep0/deep1/deep2/d/e/f/test-resource-5.txt", destFile);

            wagon.disconnect();
        }

        tearDownWagonTestingFixtures();
    }

    /**
     * Test that when putting a directory that already exists new files get also copied
     *
     * @throws Exception
     * @since 1.0-beta-1
     */
    public void testWagonPutDirectoryWhenDirectoryAlreadyExists() throws Exception {

        final String dirName = "directory-copy-existing";

        final String resourceToCreate = "test-resource-1.txt";

        final String[] resources = {"a/test-resource-2.txt", "a/b/test-resource-3.txt", "c/test-resource-4.txt"};

        setupWagonTestingFixtures();

        setupRepositories();

        Wagon wagon = getWagon();

        if (wagon.supportsDirectoryCopy()) {
            sourceFile = new File(FileTestUtils.getTestOutputDir(), dirName);

            FileUtils.deleteDirectory(sourceFile);

            createDirectory(wagon, resourceToCreate, dirName);

            for (String resource : resources) {
                writeTestFile(resource);
            }

            wagon.connect(testRepository, getAuthInfo());

            wagon.putDirectory(sourceFile, dirName);

            List<String> resourceNames = new ArrayList<>(resources.length + 1);

            resourceNames.add(dirName + "/" + resourceToCreate);
            for (String resource : resources) {
                resourceNames.add(dirName + "/" + resource);
            }

            assertResourcesAreInRemoteSide(wagon, resourceNames);

            wagon.disconnect();
        }

        tearDownWagonTestingFixtures();
    }

    /**
     * Test that when putting a directory that already exists new files get also copied and destination is "."
     *
     * @throws Exception
     * @since 1.0-beta-1
     */
    public void testWagonPutDirectoryForDot() throws Exception {
        final String resourceToCreate = "test-resource-1.txt";

        final String[] resources = {"a/test-resource-2.txt", "a/b/test-resource-3.txt", "c/test-resource-4.txt"};

        setupWagonTestingFixtures();

        setupRepositories();

        Wagon wagon = getWagon();

        if (wagon.supportsDirectoryCopy()) {
            sourceFile = new File(FileTestUtils.getTestOutputDir(), "dot-repo");

            FileUtils.deleteDirectory(sourceFile);

            createDirectory(wagon, resourceToCreate, ".");

            for (String resource : resources) {
                writeTestFile(resource);
            }

            wagon.connect(testRepository, getAuthInfo());

            wagon.putDirectory(sourceFile, ".");

            List<String> resourceNames = new ArrayList<>(resources.length + 1);

            resourceNames.add(resourceToCreate);
            Collections.addAll(resourceNames, resources);

            assertResourcesAreInRemoteSide(wagon, resourceNames);

            wagon.disconnect();
        }

        tearDownWagonTestingFixtures();
    }

    /**
     * Create a directory with a resource and check that the other ones don't exist
     *
     * @param wagon
     * @param resourceToCreate name of the resource to be created
     * @param dirName          directory name to create
     * @throws Exception
     */
    protected void createDirectory(Wagon wagon, String resourceToCreate, String dirName) throws Exception {
        writeTestFile(resourceToCreate);
    }

    protected void assertResourcesAreInRemoteSide(Wagon wagon, List<String> resourceNames)
            throws IOException, TransferFailedException, ResourceDoesNotExistException, AuthorizationException {
        for (String resourceName : resourceNames) {
            File destFile = FileTestUtils.createUniqueFile(getName(), resourceName);

            destFile.deleteOnExit();

            wagon.get(resourceName, destFile);
        }
    }

    /**
     * Assert that a resource does not exist in the remote wagon system
     *
     * @param wagon        wagon to get the resource from
     * @param resourceName name of the resource
     * @throws IOException             if a temp file can't be created
     * @throws AuthorizationException
     * @throws TransferFailedException
     * @since 1.0-beta-1
     */
    protected void assertNotExists(Wagon wagon, String resourceName)
            throws IOException, TransferFailedException, AuthorizationException {
        File tmpFile = File.createTempFile("wagon", null);
        try {
            wagon.get(resourceName, tmpFile);
            fail("Resource exists: " + resourceName);
        } catch (ResourceDoesNotExistException e) {
            // ok
        } finally {
            tmpFile.delete();
        }
    }

    private void writeTestFile(String child) throws IOException {
        File dir = new File(sourceFile, child);
        dir.getParentFile().mkdirs();
        FileUtils.fileWrite(dir.getAbsolutePath(), child);
    }

    public void testFailedGet() throws Exception {
        setupWagonTestingFixtures();

        setupRepositories();

        message("Getting test artifact from test repository " + testRepository);

        Wagon wagon = getWagon();

        wagon.addTransferListener(checksumObserver);

        wagon.connect(testRepository, getAuthInfo());

        destFile = FileTestUtils.createUniqueFile(getName(), getName());

        destFile.deleteOnExit();

        try {
            wagon.get("fubar.txt", destFile);
            fail("File was found when it shouldn't have been");
        } catch (ResourceDoesNotExistException e) {
            // expected
            assertTrue(true);
        } finally {
            wagon.removeTransferListener(checksumObserver);

            wagon.disconnect();

            tearDownWagonTestingFixtures();
        }
    }

    public void testFailedGetIfNewer() throws Exception {
        if (supportsGetIfNewer()) {
            setupWagonTestingFixtures();
            setupRepositories();
            message("Getting test artifact from test repository " + testRepository);
            Wagon wagon = getWagon();
            wagon.addTransferListener(checksumObserver);
            wagon.connect(testRepository, getAuthInfo());
            destFile = FileTestUtils.createUniqueFile(getName(), getName());
            destFile.deleteOnExit();
            try {
                wagon.getIfNewer("fubar.txt", destFile, 0);
                fail("File was found when it shouldn't have been");
            } catch (ResourceDoesNotExistException e) {
                // expected
                assertTrue(true);
            } finally {
                wagon.removeTransferListener(checksumObserver);

                wagon.disconnect();

                tearDownWagonTestingFixtures();
            }
        }
    }

    /**
     * Test {@link Wagon#getFileList(String)}.
     *
     * @throws Exception
     * @since 1.0-beta-2
     */
    public void testWagonGetFileList() throws Exception {
        setupWagonTestingFixtures();

        setupRepositories();

        String dirName = "file-list";

        String filenames[] = new String[] {
            "test-resource.txt", "test-resource.pom", "test-resource b.txt", "more-resources.dat", ".index.txt"
        };

        for (String filename : filenames) {
            putFile(dirName + "/" + filename, dirName + "/" + filename, filename + "\n");
        }

        Wagon wagon = getWagon();

        wagon.connect(testRepository, getAuthInfo());

        try {
            List<String> list = wagon.getFileList(dirName);
            assertNotNull("file list should not be null.", list);
            assertTrue(
                    "file list should contain more items (actually contains '" + list + "').",
                    list.size() >= filenames.length);

            for (String filename : filenames) {
                assertTrue("Filename '" + filename + "' should be in list.", list.contains(filename));
            }

            // WAGON-250
            list = wagon.getFileList("");
            assertNotNull("file list should not be null.", list);
            assertTrue("file list should contain items (actually contains '" + list + "').", !list.isEmpty());
            assertTrue(list.contains("file-list/"));
            assertFalse(list.contains("file-list"));
            assertFalse(list.contains("."));
            assertFalse(list.contains(".."));
            assertFalse(list.contains("./"));
            assertFalse(list.contains("../"));
        } catch (UnsupportedOperationException e) {
            // Some providers don't support this
            Assume.assumeFalse(false);
        } finally {
            wagon.disconnect();

            tearDownWagonTestingFixtures();
        }
    }

    /**
     * Test {@link Wagon#getFileList(String)} when the directory does not exist.
     *
     * @throws Exception
     * @since 1.0-beta-2
     */
    public void testWagonGetFileListWhenDirectoryDoesNotExist() throws Exception {
        setupWagonTestingFixtures();

        setupRepositories();

        String dirName = "file-list-unexisting";

        Wagon wagon = getWagon();

        wagon.connect(testRepository, getAuthInfo());

        try {
            wagon.getFileList(dirName);
            fail("getFileList on unexisting directory must throw ResourceDoesNotExistException");
        } catch (ResourceDoesNotExistException e) {
            // expected
        } catch (UnsupportedOperationException e) {
            // Some providers don't support this
            Assume.assumeFalse(false);
        } finally {
            wagon.disconnect();

            tearDownWagonTestingFixtures();
        }
    }

    /**
     * Test for an existing resource.
     *
     * @throws Exception
     * @since 1.0-beta-2
     */
    public void testWagonResourceExists() throws Exception {
        setupWagonTestingFixtures();

        setupRepositories();

        Wagon wagon = getWagon();

        putFile();

        wagon.connect(testRepository, getAuthInfo());

        assertTrue(sourceFile.getName() + " does not exist", wagon.resourceExists(sourceFile.getName()));

        wagon.disconnect();

        tearDownWagonTestingFixtures();
    }

    /**
     * Test for an invalid resource.
     *
     * @throws Exception
     * @since 1.0-beta-2
     */
    public void testWagonResourceNotExists() throws Exception {
        setupWagonTestingFixtures();

        setupRepositories();

        Wagon wagon = getWagon();

        wagon.connect(testRepository, getAuthInfo());

        assertFalse(wagon.resourceExists("a/bad/resource/name/that/should/not/exist.txt"));

        wagon.disconnect();

        tearDownWagonTestingFixtures();
    }

    // ----------------------------------------------------------------------
    // File <--> File round trip testing
    // ----------------------------------------------------------------------
    // We are testing taking a file, our sourcefile, and placing it into the
    // test repository that we have setup.
    // ----------------------------------------------------------------------

    protected void putFile(String resourceName, String testFileName, String content) throws Exception {
        sourceFile = new File(FileTestUtils.getTestOutputDir(), testFileName);
        sourceFile.getParentFile().mkdirs();
        FileUtils.fileWrite(sourceFile.getAbsolutePath(), content);

        Wagon wagon = getWagon();

        ProgressAnswer progressAnswer = replayMockForPut(resourceName, content, wagon);

        message("Putting test artifact: " + resourceName + " into test repository " + testRepository);

        connectWagon(wagon);

        wagon.put(sourceFile, resourceName);

        disconnectWagon(wagon);

        verifyMock(progressAnswer, content.length());
    }

    protected ProgressAnswer replayMockForPut(String resourceName, String content, Wagon wagon) {
        Resource resource = new Resource(resourceName);
        mockTransferListener.transferInitiated(createTransferEvent(
                wagon, resource, TransferEvent.TRANSFER_INITIATED, TransferEvent.REQUEST_PUT, sourceFile));
        resource = new Resource(resourceName);
        resource.setContentLength(content.length());
        resource.setLastModified(sourceFile.lastModified());
        mockTransferListener.transferStarted(createTransferEvent(
                wagon, resource, TransferEvent.TRANSFER_STARTED, TransferEvent.REQUEST_PUT, sourceFile));
        mockTransferListener.transferProgress(
                eq(createTransferEvent(
                        wagon, resource, TransferEvent.TRANSFER_PROGRESS, TransferEvent.REQUEST_PUT, sourceFile)),
                anyObject(byte[].class),
                anyInt());
        ProgressAnswer progressAnswer = new ProgressAnswer();
        expectLastCall().andStubAnswer(progressAnswer);

        mockTransferListener.debug(anyString());
        expectLastCall().anyTimes();

        mockTransferListener.transferCompleted(createTransferEvent(
                wagon, resource, TransferEvent.TRANSFER_COMPLETED, TransferEvent.REQUEST_PUT, sourceFile));

        replay(mockTransferListener);
        return progressAnswer;
    }

    protected TransferEvent createTransferEvent(
            Wagon wagon, Resource resource, int eventType, int requestType, File file) {
        TransferEvent transferEvent = new TransferEvent(wagon, resource, eventType, requestType);
        transferEvent.setLocalFile(file);
        return transferEvent;
    }

    protected int putFile() throws Exception {
        String content = TEST_CONTENT;
        putFile(resource, "test-resource", content);
        return content.length();
    }

    protected void getFile(int expectedSize) throws Exception {
        destFile = FileTestUtils.createUniqueFile(getName(), getName());
        destFile.deleteOnExit();

        Wagon wagon = getWagon();

        ProgressAnswer progressAnswer = replaceMockForGet(wagon, expectedSize);

        message("Getting test artifact from test repository " + testRepository);

        connectWagon(wagon);

        wagon.get(this.resource, destFile);

        disconnectWagon(wagon);

        verifyMock(progressAnswer, expectedSize);
    }

    protected void verifyMock(ProgressAnswer progressAnswer, int length) {
        verify(mockTransferListener);

        assertEquals(length, progressAnswer.getSize());

        reset(mockTransferListener);
    }

    protected void disconnectWagon(Wagon wagon) throws ConnectionException {
        wagon.removeTransferListener(mockTransferListener);

        wagon.removeTransferListener(checksumObserver);

        wagon.disconnect();
    }

    protected void connectWagon(Wagon wagon) throws ConnectionException, AuthenticationException {
        wagon.addTransferListener(checksumObserver);

        wagon.addTransferListener(mockTransferListener);

        wagon.connect(testRepository, getAuthInfo());
    }

    /**
     *
     * some test (mock on transfertprogress call) relies on the fact that InputStream #read(byte[] b, int off, int len)
     * read all bytes. But javadoc says: ""
     */
    protected boolean assertOnTransferProgress() {
        return false;
    }

    protected ProgressAnswer replaceMockForGet(Wagon wagon, int expectedSize) {
        Resource resource = new Resource(this.resource);
        mockTransferListener.transferInitiated(createTransferEvent(
                wagon, resource, TransferEvent.TRANSFER_INITIATED, TransferEvent.REQUEST_GET, destFile));
        resource = new Resource(this.resource);
        resource.setContentLength(getExpectedContentLengthOnGet(expectedSize));
        resource.setLastModified(getExpectedLastModifiedOnGet(testRepository, resource));
        TransferEvent te =
                createTransferEvent(wagon, resource, TransferEvent.TRANSFER_STARTED, TransferEvent.REQUEST_GET, null);
        mockTransferListener.transferStarted(te);
        mockTransferListener.transferProgress(
                eq(new TransferEvent(wagon, resource, TransferEvent.TRANSFER_PROGRESS, TransferEvent.REQUEST_GET)),
                anyObject(byte[].class),
                anyInt());

        ProgressAnswer progressAnswer = new ProgressAnswer();

        if (assertOnTransferProgress()) {
            expectLastCall().andAnswer(progressAnswer);
        } else {
            expectLastCall().andAnswer(progressAnswer);
            expectLastCall().anyTimes();
        }
        mockTransferListener.debug(anyString());
        expectLastCall().anyTimes();

        mockTransferListener.transferCompleted(createTransferEvent(
                wagon, resource, TransferEvent.TRANSFER_COMPLETED, TransferEvent.REQUEST_GET, destFile));

        replay(mockTransferListener);
        return progressAnswer;
    }

    protected int getExpectedContentLengthOnGet(int expectedSize) {
        return expectedSize;
    }

    protected long getExpectedLastModifiedOnGet(Repository repository, Resource resource) {
        // default implementation - prone to failing if the time between test file creation and completion of putFile()
        // cross the "second" boundary, causing the "remote" and local files to have different times.

        return sourceFile.lastModified();
    }

    protected void fileRoundTripTesting() throws Exception {
        message("File round trip testing ...");

        int expectedSize = putFile();

        assertNotNull("check checksum is not null", checksumObserver.getActualChecksum());

        assertEquals("compare checksums", TEST_CKSUM, checksumObserver.getActualChecksum());

        checksumObserver = new ChecksumObserver();

        getFile(expectedSize);

        assertNotNull("check checksum is not null", checksumObserver.getActualChecksum());

        assertEquals("compare checksums", TEST_CKSUM, checksumObserver.getActualChecksum());

        // Now compare the conents of the artifact that was placed in
        // the repository with the contents of the artifact that was
        // retrieved from the repository.

        String sourceContent = FileUtils.fileRead(sourceFile);

        String destContent = FileUtils.fileRead(destFile);

        assertEquals(sourceContent, destContent);
    }

    // ----------------------------------------------------------------------
    //
    // ----------------------------------------------------------------------

    protected Repository createFileRepository(String url) {
        File path = new File(url.substring(7));

        path.mkdirs();

        Repository repository = new Repository();

        repository.setUrl(url);

        return repository;
    }

    protected static String cksum(String content) {
        String checkSum;
        try {
            ChecksumObserver obs = new ChecksumObserver();
            byte[] buf = content.getBytes(StandardCharsets.ISO_8859_1);
            obs.transferProgress(null, buf, buf.length);
            obs.transferCompleted(null);
            checkSum = obs.getActualChecksum();
        } catch (Exception e) {
            checkSum = null;
        }
        return checkSum;
    }
}
