/*******************************************************************************
 *  Copyright (c) 2008, 2016 IBM Corporation and others.
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  which accompanies this distribution, and is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 * 
 *  Contributors:
 *     IBM Corporation - initial API and implementation
 *     Red Hat Inc. - Bug 460967
 *******************************************************************************/
package org.eclipse.equinox.p2.tests.mirror;

import static org.junit.Assert.assertNotEquals;

import java.io.*;
import java.net.MalformedURLException;
import java.net.URI;
import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.artifact.processors.md5.Messages;
import org.eclipse.equinox.internal.p2.artifact.repository.*;
import org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactRepository;
import org.eclipse.equinox.internal.p2.core.helpers.OrderedProperties;
import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.internal.repository.comparator.MD5ArtifactComparator;
import org.eclipse.equinox.p2.internal.repository.tools.MirrorApplication;
import org.eclipse.equinox.p2.internal.repository.tools.RepositoryDescriptor;
import org.eclipse.equinox.p2.metadata.IArtifactKey;
import org.eclipse.equinox.p2.metadata.Version;
import org.eclipse.equinox.p2.query.IQuery;
import org.eclipse.equinox.p2.query.IQueryResult;
import org.eclipse.equinox.p2.repository.IRepository;
import org.eclipse.equinox.p2.repository.artifact.*;
import org.eclipse.equinox.p2.repository.artifact.spi.ArtifactDescriptor;
import org.eclipse.equinox.p2.tests.*;
import org.eclipse.equinox.spi.p2.publisher.PublisherHelper;
import org.eclipse.osgi.framework.log.FrameworkLog;
import org.eclipse.osgi.util.NLS;
import org.junit.*;
import org.junit.experimental.theories.*;
import org.junit.runner.RunWith;

/*
 * Modified from ArtifactMirrorApplicationTest
 */
@RunWith(Theories.class)
public class NewMirrorApplicationArtifactTest extends AbstractProvisioningTest {
	private static final String MISSING_ARTIFACT = "canonical: osgi.bundle,javax.wsdl,1.4.0.v200803061811.";
	protected File destRepoLocation;
	protected File sourceRepoLocation; //helloworldfeature
	protected File sourceRepo2Location; //anotherfeature
	protected File sourceRepo3Location; //helloworldfeature + yetanotherfeature
	protected File sourceRepo4Location; //helloworldfeature v1.0.1

	/* (non-Javadoc)
	 * @see org.eclipse.equinox.p2.tests.AbstractProvisioningTest#setUp()
	 */
	@Before
	public void setUp() throws Exception {
		super.setUp();
		//load all the repositories
		sourceRepoLocation = getTestData("0.0", "/testData/mirror/mirrorSourceRepo1 with space");
		sourceRepo2Location = getTestData("0.1", "/testData/mirror/mirrorSourceRepo2");
		sourceRepo3Location = getTestData("0.2", "/testData/mirror/mirrorSourceRepo3");
		sourceRepo4Location = getTestData("0.3", "/testData/mirror/mirrorSourceRepo4");

		//create destination location
		destRepoLocation = new File(getTempFolder(), "BasicMirrorApplicationTest");
		delete(destRepoLocation);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.equinox.p2.tests.AbstractProvisioningTest#tearDown()
	 */
	@After
	public void tearDown() throws Exception {
		//remove all the repositories
		getArtifactRepositoryManager().removeRepository(destRepoLocation.toURI());
		getArtifactRepositoryManager().removeRepository(sourceRepoLocation.toURI());
		getArtifactRepositoryManager().removeRepository(sourceRepo2Location.toURI());
		getArtifactRepositoryManager().removeRepository(sourceRepo3Location.toURI());
		getArtifactRepositoryManager().removeRepository(sourceRepo4Location.toURI());
		//delete the destination location (no left over files for the next test)
		delete(destRepoLocation);
		super.tearDown();
	}

	private StringBuffer basicRunMirrorApplication(String message, URI source, URI destination, Boolean append, Boolean formatDestination, String destName) throws Exception {
		MirrorApplication app = new MirrorApplication();

		if (destination != null) {
			RepositoryDescriptor dest = null;
			if (formatDestination != null && formatDestination)
				dest = createRepositoryDescriptor(destination, append, source, destName);
			else
				dest = createRepositoryDescriptor(destination, append, null, destName);
			app.addDestination(dest);
		}

		if (source != null) {
			RepositoryDescriptor src = createRepositoryDescriptor(source, null, null, null);
			app.addSource(src);
		}

		StringBuffer buffer = new StringBuffer();
		PrintStream out = System.out;
		try {
			System.setOut(new PrintStream(new StringBufferStream(buffer)));
			app.run(null);
		} finally {
			System.setOut(out);
		}
		return buffer;
	}

	private StringBuffer basicRunMirrorApplication(String message, URI source, URI destination, Boolean append, Boolean formatDestination) throws Exception {
		return basicRunMirrorApplication(message, source, destination, append, formatDestination, null);
	}

	private StringBuffer basicRunMirrorApplication(String message, URI source, URI destination) throws Exception {
		return basicRunMirrorApplication(message, source, destination, null, null, null);
	}

	private RepositoryDescriptor createRepositoryDescriptor(URI location, Boolean append, URI format, String name) {
		RepositoryDescriptor descriptor = new RepositoryDescriptor();
		descriptor.setLocation(location);
		descriptor.setKind("artifact");
		if (append != null)
			descriptor.setAppend(append);
		if (format != null)
			descriptor.setFormat(format);
		if (name != null)
			descriptor.setName(name);
		return descriptor;
	}

	/**
	 * just a wrapper method for compatibility
	 */
	private void runMirrorApplication(String message, File source, File destination, boolean append) {
		try {
			basicRunMirrorApplication(message, source.toURI(), destination.toURI(), append, false);
		} catch (Exception e) {
			fail(message, e);
		}
	}

	/**
	 * Tests mirroring all artifacts in a repository to an empty repository
	 * Source contains A, B
	 * Target contains
	 */
	private void artifactMirrorToEmpty(String message, boolean append, boolean format) {
		try {
			//destination repo is created blank
			basicRunMirrorApplication(message, sourceRepoLocation.toURI(), destRepoLocation.toURI(), append, format);
		} catch (Exception e) {
			fail(message, e);
		}
	}

	/**
	 * Tests mirroring all artifacts in a repository to a repository populated with non-duplicate entries
	 * Source contains A, B
	 * Target contains C, D
	 */
	private void artifactMirrorToPopulated(String message, boolean append) {
		//Setup: populate destination with non-duplicate artifacts
		runMirrorApplication(message + ".0", sourceRepo2Location, destRepoLocation, false); //value of append should not matter

		try {
			//Setup ensure setup completes successfully
			assertContentEquals(message + ".1", getArtifactRepositoryManager().loadRepository(sourceRepo2Location.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
		} catch (ProvisionException e) {
			fail(message + ".2", e);
		}

		//mirror test data
		runMirrorApplication(message + ".4", sourceRepoLocation, destRepoLocation, append);
	}

	/**
	 * Tests mirroring all artifacts in a repository to a repository populated with exact duplicate data
	 * Source contains A, B
	 * Target contains A, B
	 */
	private void artifactMirrorToFullDuplicate(String message, boolean append) {
		//Setup: populate destination with duplicate artifacts
		runMirrorApplication(message + ".0", sourceRepoLocation, destRepoLocation, false); //value of append should not matter

		try {
			//Setup: verify contents
			assertContentEquals(message + ".1", getArtifactRepositoryManager().loadRepository(sourceRepoLocation.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
		} catch (ProvisionException e) {
			fail(message + ".2", e);
		}

		//mirror test data
		runMirrorApplication(message + ".4", sourceRepoLocation, destRepoLocation, append);
	}

	/**
	 * Tests mirroring all artifacts in a repository to a repository populated with partially duplicate data
	 * Source contains A, B, C, D
	 * Target contains  A, B
	 */
	private void artifactMirrorToPartialDuplicate(String message, boolean append) {
		//Setup: populate destination with duplicate artifacts
		runMirrorApplication(message + ".0", sourceRepoLocation, destRepoLocation, false);

		try {
			//Setup: verify contents
			assertContentEquals(message + ".1", getArtifactRepositoryManager().loadRepository(sourceRepoLocation.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
		} catch (ProvisionException e) {
			fail(message + ".2", e);
		}

		//mirror test data
		runMirrorApplication(message + ".4", sourceRepo3Location, destRepoLocation, append);
	}

	/**
	 * Tests mirroring all artifacts in a repository to a repository populated with both full duplicate and non-duplicate data
	 * Source contains A, B
	 * Target contains A, B, C, D
	 */
	private void artifactMirrorToPopulatedWithFullDuplicate(String message, boolean append) {
		//Setup: populate destination with non-duplicate artifacts
		runMirrorApplication(message + ".0", sourceRepo3Location, destRepoLocation, false); //value of append should not matter

		try {
			//Setup: verify
			assertContentEquals(message + ".1", getArtifactRepositoryManager().loadRepository(sourceRepo3Location.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
		} catch (ProvisionException e) {
			fail(message + ".2", e);
		}

		//mirror duplicate data
		runMirrorApplication(message + ".4", sourceRepoLocation, destRepoLocation, append);
	}

	/**
	 * Tests mirroring all artifacts in a repository to a repository populated with both partial duplicate and non-duplicate data
	 * Source contains A, B, C, D
	 * Target contains A, B, E, F
	 */
	private void artifactMirrorToPopulatedWithPartialDuplicate(String message, boolean append) {
		//Setup: populate destination with non-duplicate artifacts
		runMirrorApplication(message + ".0", sourceRepo2Location, destRepoLocation, false); //value of append should not matter

		try {
			//Setup: verify
			assertContentEquals(message + ".1", getArtifactRepositoryManager().loadRepository(sourceRepo2Location.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
		} catch (ProvisionException e) {
			fail(message + ".2", e);
		}

		//Setup: populate destination with duplicate artifacts
		runMirrorApplication(message + ".4", sourceRepoLocation, destRepoLocation, true);

		try {
			//Setup: verify
			assertContains(message + ".5", getArtifactRepositoryManager().loadRepository(sourceRepoLocation.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
			assertContains(message + ".6", getArtifactRepositoryManager().loadRepository(sourceRepo2Location.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
		} catch (ProvisionException e) {
			fail(message + ".7", e);
		}

		//mirror duplicate data
		runMirrorApplication(message + ".9", sourceRepo3Location, destRepoLocation, append);
	}

	/**
	 * Tests mirroring all artifacts from an empty repository
	 * Source contains
	 */
	private File artifactMirrorEmpty(String message, boolean append) {
		//Setup: Create an empty repository
		File emptyRepository = new File(getTempFolder(), getUniqueString());
		//Setup: remove repository if it exists
		getArtifactRepositoryManager().removeRepository(emptyRepository.toURI());
		//Setup: delete any data that may be in the folder
		delete(emptyRepository);
		try {
			getArtifactRepositoryManager().createRepository(emptyRepository.toURI(), "Empty Repository", IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, null);
		} catch (ProvisionException e) {
			fail(message + ".1", e);
		}

		runMirrorApplication(message + ".0", emptyRepository, destRepoLocation, append);
		return emptyRepository; //return the repository for use in verification
	}

	/**
	 * Tests mirroring all artifacts from an empty repository
	 * Source contains
	 */
	private File artifactMirrorEmptyToPopulated(String message, boolean append) {
		//Setup: Populate the repository
		runMirrorApplication(message + ".0", sourceRepoLocation, destRepoLocation, false);

		return artifactMirrorEmpty(message + ".1", append); //create the empty repository, perform the mirror, pass the result back
	}

	/**
	 * Runs mirror app on source with missing artifact with "-ignoreErrors"
	 */
	private void mirrorWithError(boolean verbose) {
		File errorSourceLocation = getTestData("loading error data", "testData/artifactRepo/missingSingleArtifact");
		File validSourceLocation = getTestData("loading error data", "testData/artifactRepo/simple");
		//repo contains an artifact entry for a file that does not exist on disk. this should throw a file not found exception
		PrintStream out = System.out;
		try {
			System.setOut(new PrintStream(new StringBufferStream()));
			MirrorApplication app = new MirrorApplication();
			app.addSource(createRepositoryDescriptor(errorSourceLocation.toURI(), null, null, null));
			app.addSource(createRepositoryDescriptor(validSourceLocation.toURI(), null, null, null));
			app.addDestination(createRepositoryDescriptor(destRepoLocation.toURI(), null, null, null));
			//Set ignoreErrors flag. Set verbose flag if verbose == true
			app.setVerbose(verbose);
			app.setIgnoreErrors(true);
			//run the mirror application
			app.run(null);
		} catch (Exception e) {
			fail("Running mirror application with errored source failed", e);
		} finally {
			System.setOut(out);
		}
	}

	/**
	 * Tests mirroring all artifacts in a repository to an empty repository
	 * Source contains A, B
	 * Target contains
	 * Expected is A, B
	 */
	@Test
	public void testArtifactMirrorToEmpty() {
		artifactMirrorToEmpty("1.0", true, false); // run the test with append set to true

		try {
			//verify destination's content
			assertContentEquals("1.1", getArtifactRepositoryManager().loadRepository(sourceRepoLocation.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
		} catch (ProvisionException e) {
			fail("1.2", e);
		}
	}

	/**
	 * Tests mirroring all artifacts in a repository to an empty repository with "-writeMode clean"
	 * Source contains A, B
	 * Target contains
	 * Expected is A, B
	 */
	@Test
	public void testArtifactMirrorToEmptyWithClean() {
		artifactMirrorToEmpty("2.0", false, false);

		try {
			//verify destination's content
			assertContentEquals("2.1", getArtifactRepositoryManager().loadRepository(sourceRepoLocation.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
		} catch (ProvisionException e) {
			fail("2.2", e);
		}
	}

	/**
	 * Tests mirroring all artifacts in a repository to a repository populated with exact duplicate data
	 * Source contains A, B
	 * Target contains A, B
	 * Expected is A, B
	 */
	@Test
	public void testArtifactMirrorToFullDuplicate() {
		artifactMirrorToFullDuplicate("3.0", true); //run the test with append set to true

		try {
			//verify destination's content
			assertContentEquals("3.1", getArtifactRepositoryManager().loadRepository(sourceRepoLocation.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
		} catch (ProvisionException e) {
			fail("3.2", e);
		}
	}

	/**
	 * Tests mirroring all artifacts in a repository to a repository populated with exact duplicate data with "-writeMode clean"
	 * Source contains A, B
	 * Target contains A, B
	 * Expected is A, B
	 */
	@Test
	public void testArtifactMirrorToFullDuplicateWithClean() {
		artifactMirrorToFullDuplicate("4.0", false);

		try {
			//verify destination's content
			assertContentEquals("4.1", getArtifactRepositoryManager().loadRepository(sourceRepoLocation.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
		} catch (ProvisionException e) {
			fail("4.2", e);
		}
	}

	/**
	 * Tests mirroring all artifacts in a repository to a repository populated with non-duplicate entries
	 * Source contains A, B
	 * Target contains C, D
	 * Expected is A, B, C, D
	 */
	@Test
	public void testArtifactMirrorToPopulated() {
		artifactMirrorToPopulated("5.0", true); //run the test with append set to true

		try {
			//verify destination's content
			assertContains("5.1", getArtifactRepositoryManager().loadRepository(sourceRepoLocation.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
			assertContains("5.2", getArtifactRepositoryManager().loadRepository(sourceRepo2Location.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
			//checks that the destination has the correct number of keys (no extras)
			assertEquals("5.3", getArtifactKeyCount(sourceRepoLocation.toURI()) + getArtifactKeyCount(sourceRepo2Location.toURI()), getArtifactKeyCount(destRepoLocation.toURI()));
		} catch (ProvisionException e) {
			fail("5.4", e);
		}
	}

	/**
	 * Tests mirroring all artifacts in a repository to a repository populated with non-duplicate entries with "-writeMode clean"
	 * Source contains A, B
	 * Target contains C, D
	 * Expected is A, B
	 */
	@Test
	public void testArtifactMirrorToPopulatedWithClean() {
		artifactMirrorToPopulated("6.0", false);

		try {
			//verify destination's content
			assertContentEquals("6.1", getArtifactRepositoryManager().loadRepository(sourceRepoLocation.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
		} catch (ProvisionException e) {
			fail("6.2", e);
		}
	}

	/**
	 * Tests mirroring all artifacts in a repository to a repository populated with partially duplicate data
	 * Source contains A, B, C, D
	 * Target contains  A, B
	 * Expected is A, B, C, D
	 */
	@Test
	public void testArtifactMirrorToPartialDuplicate() {
		artifactMirrorToPartialDuplicate("7.0", true); //run the test with append set to true

		try {
			//verify destination's content
			assertContentEquals("7.1", getArtifactRepositoryManager().loadRepository(sourceRepo3Location.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
		} catch (ProvisionException e) {
			fail("7.2", e);
		}
	}

	/**
	 * Tests mirroring all artifacts in a repository to a repository populated with partially duplicate data with "-writeMode clean"
	 * Source contains A, B, C, D
	 * Target contains  A, B
	 * Expected is A, B, C, D
	 */
	@Test
	public void testArtifactMirrorToPartialDuplicateWithClean() {
		artifactMirrorToPartialDuplicate("8.0", false);

		try {
			//verify destination's content
			assertContentEquals("8.1", getArtifactRepositoryManager().loadRepository(sourceRepo3Location.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
		} catch (ProvisionException e) {
			fail("8.2", e);
		}
	}

	/**
	 * Tests mirroring all artifacts in a repository to a repository populated with both full duplicate and non-duplicate data
	 * Source contains A, B
	 * Target contains A, B, C, D
	 * Expected is A, B, C, D
	 */
	@Test
	public void testArtifactMirrorToPopulatedWithFullDuplicate() {
		artifactMirrorToPopulatedWithFullDuplicate("9.0", true); //run the test with append set to true

		try {
			//verify destination's content
			assertContentEquals("9.1", getArtifactRepositoryManager().loadRepository(sourceRepo3Location.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
		} catch (ProvisionException e) {
			fail("9.2", e);
		}
	}

	/**
	 * Tests mirroring all artifacts in a repository to a repository populated with both full duplicate and non-duplicate data with "-writeMode clean"
	 * Source contains A, B
	 * Target contains A, B, C, D
	 * Expected is A, B
	 */
	@Test
	public void testArtifactMirrorToPopulatedWithFullDuplicateWithClean() {
		artifactMirrorToPopulatedWithFullDuplicate("10.0", false);

		try {
			//verify destination's content
			assertContentEquals("10.1", getArtifactRepositoryManager().loadRepository(sourceRepoLocation.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
		} catch (ProvisionException e) {
			fail("10.2", e);
		}
	}

	/**
	 * Tests mirroring all artifacts in a repository to a repository populated with both partial duplicate and non-duplicate data
	 * Source contains A, B, C, D
	 * Target contains A, B, E, F
	 * Expected is A, B, C, D, E, F
	 */
	@Test
	public void testArtifactMirrorToPopulatedWithPartialDuplicate() {
		artifactMirrorToPopulatedWithPartialDuplicate("11.0", true); //run the test with append set to true

		try {
			//verify destination's content
			assertContains("11.1", getArtifactRepositoryManager().loadRepository(sourceRepo3Location.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
			assertContains("11.2", getArtifactRepositoryManager().loadRepository(sourceRepo2Location.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
			//checks that the destination has the correct number of keys (no extras)
			assertEquals("11.3", getArtifactKeyCount(sourceRepo2Location.toURI()) + getArtifactKeyCount(sourceRepo3Location.toURI()), getArtifactKeyCount(destRepoLocation.toURI()));
		} catch (ProvisionException e) {
			fail("11.4", e);
		}
	}

	/**
	 * Tests mirroring all artifacts in a repository to a repository populated with both partial duplicate and non-duplicate data with "-writeMode clean"
	 * Source contains A, B, C, D
	 * Target contains A, B, E, F
	 * Expected is A, B, C, D
	 */
	@Test
	public void testArtifactMirrorToPopulatedWithPartialDuplicateWithClean() {
		artifactMirrorToPopulatedWithPartialDuplicate("12.0", false);

		try {
			//verify destination's content
			assertContentEquals("12.1", getArtifactRepositoryManager().loadRepository(sourceRepo3Location.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
		} catch (ProvisionException e) {
			fail("12.2", e);
		}
	}

	/**
	 * Tests MirrorApplication's behaviour when given an invalid source repository
	 */
	@Test
	public void testArtifactMirrorFromInvalid() {
		File invalidRepository = new File(getTempFolder(), getUniqueString());
		delete(invalidRepository);

		try {
			basicRunMirrorApplication("13.1", invalidRepository.toURI(), destRepoLocation.toURI(), true, false);
			//we expect a provision exception to be thrown. We should never get here.
			fail("13.0 ProvisionExpection not thrown");
		} catch (ProvisionException e) {
			return; //correct type of exception has been thrown
		} catch (Exception e) {
			fail("13.2", e);
		}
	}

	/**
	 * Tests MirrorApplication's behaviour when given an invalid destination repository
	 */
	@Test
	public void testArtifactMirrorToInvalid() {
		URI invalidDestRepository = null;
		try {
			//Setup: create a URI pointing to an unmodifiable place
			invalidDestRepository = new URI("http://eclipse.org/equinox/foobar/abcdefg");

			//run the application with the modifiable destination
			basicRunMirrorApplication("14.1", sourceRepoLocation.toURI(), invalidDestRepository, true, false);
			//we're expecting an UnsupportedOperationException so we should never get here
			fail("14.0 UnsupportedOperationException not thrown");
		} catch (ProvisionException e) {
			assertEquals("Unexpected error message", NLS.bind(org.eclipse.equinox.p2.internal.repository.tools.Messages.exception_invalidDestination, URIUtil.toUnencodedString(invalidDestRepository)), e.getMessage());
			return; //correct type of exception has been thrown
		} catch (Exception e) {
			fail("14.2", e);
		} finally {
			if (invalidDestRepository != null)
				getArtifactRepositoryManager().removeRepository(invalidDestRepository);
		}
	}

	/**
	 * Tests MirrorApplication's behaviour when given both an invalid source and an invalid destination repository
	 */
	@Test
	public void testArtifactMirrorBothInvalid() {
		//Setup: create a file that is not a valid repository
		File invalidRepository = new File(getTempFolder(), getUniqueString());
		//Setup: delete any leftover data
		delete(invalidRepository);

		try {
			//Setup: create a URI pointing to an unmodifiable place
			URI invalidDestRepository = new URI("http://eclipse.org/equinox/foobar/abcdefg");
			basicRunMirrorApplication("15.1", invalidRepository.toURI(), invalidDestRepository, true, false);
			//We expect the ProvisionException to be thrown
			fail("15.0 ProvisionException not thrown");
		} catch (ProvisionException e) {
			return; //correct type of exception was thrown
		} catch (Exception e) {
			fail("15.2", e);
		}
	}

	/**
	 * Tests mirroring an empty repository to another empty repository
	 * Source contains
	 * Target contains
	 * Expected is
	 */
	@Test
	public void testArtifactMirrorEmptyToEmpty() {
		File emptyRepository = artifactMirrorEmpty("16.0", true);

		try {
			//verify destination's content
			assertContentEquals("16.1", getArtifactRepositoryManager().loadRepository(emptyRepository.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
		} catch (ProvisionException e) {
			fail("16.2", e);
		}

		//remove the emptyRepository
		getArtifactRepositoryManager().removeRepository(emptyRepository.toURI());
		//delete any left over data
		delete(emptyRepository);
	}

	/**
	 * Tests mirroring an empty repository to a populated repository
	 * Source contains
	 * Target contains A, B
	 * Expected is A, B
	 */
	@Test
	public void testArtifactMirrorEmptyToPopulated() {
		File emptyRepository = artifactMirrorEmptyToPopulated("17.0", true);

		try {
			//verify destination's content
			assertContains("17.1", getArtifactRepositoryManager().loadRepository(emptyRepository.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
			assertContentEquals("17.2", getArtifactRepositoryManager().loadRepository(sourceRepoLocation.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
		} catch (ProvisionException e) {
			fail("17.3", e);
		}

		//remove the empty repository
		getArtifactRepositoryManager().removeRepository(emptyRepository.toURI());
		//remove any leftover data
		delete(emptyRepository);
	}

	/**
	 * Tests mirroring an empty repository to a populated repository with "-writeMode clean"
	 * Source contains
	 * Target contains A, B
	 * Expected is
	 */
	@Test
	public void testArtifactMirrorEmptyToPopulatedWithClean() {
		File emptyRepository = artifactMirrorEmptyToPopulated("18.0", false);

		try {
			//verify destination's content
			assertContentEquals("18.1", getArtifactRepositoryManager().loadRepository(emptyRepository.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
		} catch (ProvisionException e) {
			fail("18.2", e);
		}

		//remove the empty repository
		getArtifactRepositoryManager().removeRepository(emptyRepository.toURI());
		//delete any leftover data
		delete(emptyRepository);
	}

	/**
	 * Tests mirroring a repository to itself
	 * Source contains A, B
	 * Target contains A, B
	 * Expected is A, B
	 */
	@Test
	public void testArtifactMirrorSourceIsDestination() {
		//Setup: Populate the repository
		runMirrorApplication("19.0", sourceRepoLocation, destRepoLocation, false);

		//run the application with the source and destination specified to the same place
		runMirrorApplication("19.1", destRepoLocation, destRepoLocation, true);

		try {
			//verify destination's content
			assertContentEquals("19.2", getArtifactRepositoryManager().loadRepository(sourceRepoLocation.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
		} catch (ProvisionException e) {
			fail("19.3", e);
		}
	}

	/**
	 * Tests mirroring a repository with a different version of the same package
	 * Source contains A, B (v1.0.1)
	 * Target contains A, B (v1.0.0)
	 * Expected is A, B (v1.0.0) and A, B (v1.0.1)
	 */
	@Test
	public void testArtifactMirrorDifferentVersions() {
		//Setup: Populate the repository
		runMirrorApplication("20.0", sourceRepoLocation, destRepoLocation, false);

		//run the application with the source and destination specified to the same place
		runMirrorApplication("20.1", sourceRepo4Location, destRepoLocation, true);

		try {
			//verify destination's content
			assertContains("20.2", getArtifactRepositoryManager().loadRepository(sourceRepoLocation.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
			assertContains("20.3", getArtifactRepositoryManager().loadRepository(sourceRepo4Location.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
			//checks that the destination has the correct number of keys (no extras)
			assertEquals("20.4", getArtifactKeyCount(sourceRepoLocation.toURI()) + getArtifactKeyCount(sourceRepo4Location.toURI()), getArtifactKeyCount(destRepoLocation.toURI()));
		} catch (ProvisionException e) {
			fail("20.5", e);
		}
	}

	/**
	 * Tests how mirror application handles an unspecified source
	 */
	@Test
	public void testArtifactMirrorNullSource() {
		try {
			basicRunMirrorApplication("21.1", null, destRepoLocation.toURI());
			//We expect the ProvisionException to be thrown
			fail("21.3 ProvisionException not thrown");
		} catch (ProvisionException e) {
			return; //expected type of exception has been thrown
		} catch (Exception e) {
			fail("21.2", e);
		}
	}

	/**
	 * Tests how mirror application handles an unspecified destination
	 */
	@Test
	public void testArtifactMirrorNullDestination() {
		try {
			basicRunMirrorApplication("22.1", sourceRepoLocation.toURI(), null);
			//We expect the ProvisionException to be thrown
			fail("22.3 ProvisionException not thrown");
		} catch (ProvisionException e) {
			return; //expected type of exception has been thrown
		} catch (Exception e) {
			fail("22.2", e);
		}
	}

	/**
	 * Tests how mirror application handles both an unspecified source and an unspecified destination
	 */
	@Test
	public void testArtifactMirrorNullBoth() {
		try {
			basicRunMirrorApplication("23.0", null, null);
			//We expect the ProvisionException to be thrown
			fail("23.2 ProvisionException not thrown");
		} catch (ProvisionException e) {
			return; //expected type of exception has been thrown
		} catch (Exception e) {
			fail("23.1", e);
		}
	}

	/**
	 * Ensures that a repository created by the mirror application is a copy of the source
	 */
	@Test
	public void testNewArtifactRepoProperties() {
		//run mirror application with source not preexisting
		artifactMirrorToEmpty("24.0", true, true);

		try {
			IArtifactRepository sourceRepository = getArtifactRepositoryManager().loadRepository(sourceRepoLocation.toURI(), null);
			IArtifactRepository destinationRepository = getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null);
			assertEquals("24.1", sourceRepository.getName(), destinationRepository.getName());
			assertRepositoryProperties("24.2", sourceRepository.getProperties(), destinationRepository.getProperties());
		} catch (ProvisionException e) {
			fail("24.3", e);
		}
	}

	/**
	 * Ensures that a repository created before the mirror application is run does not have its properties changed
	 */
	@Test
	public void testExistingArtifactRepoProperties() {
		//Setup: create the destination
		String name = "Destination Name";
		Map properties = null; //default properties
		try {
			//create the repository and get the resulting properties
			properties = getArtifactRepositoryManager().createRepository(destRepoLocation.toURI(), name, IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, properties).getProperties();
		} catch (ProvisionException e) {
			fail("25.0", e);
		}

		//run the mirror application
		artifactMirrorToEmpty("25.2", true, false);

		try {
			IArtifactRepository repository = getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null);
			assertEquals("25.3", name, repository.getName());
			assertRepositoryProperties("25.4", properties, repository.getProperties());
		} catch (ProvisionException e) {
			fail("25.5", e);
		}
	}

	/**
	 *  * Ensures that a repository created by the mirror application has specified name
	 * For Bug 256909
	 */
	@Test
	public void testNewArtifactRepoWithNewName() {
		String name = "Bug 256909 test - new";
		try {
			basicRunMirrorApplication("Bug 256909 Test", sourceRepoLocation.toURI(), destRepoLocation.toURI(), true, false, name);
		} catch (MalformedURLException e) {
			fail("Error creating URLs for Source/Detination", e);
		} catch (Exception e) {
			fail("Error running mirror application", e);
		}

		try {
			assertEquals("Assert name was set correct", name, getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null).getName());
		} catch (ProvisionException e) {
			fail("Cannot obtain destination", e);
		}
	}

	/**
	 * Ensures that an existing destination used by the mirror application is given specified name
	 * For Bug 256909
	 */
	@Test
	public void testExistingArtifactRepoWithNewName() {
		String oldName = "The original naem for Bug 256909 test - existing";
		String newName = "Bug 256909 test - existing";
		//Setup create the repository
		IArtifactRepository destinationRepo = null;
		try {
			destinationRepo = getArtifactRepositoryManager().createRepository(destRepoLocation.toURI(), oldName, IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, null);
		} catch (ProvisionException e) {
			fail("Error creating repo at destination", e);
		}
		assertEquals("Assert name is set correctly before mirror", oldName, destinationRepo.getName());

		StringBuffer buffer = new StringBuffer();
		PrintStream out = System.out;
		try {
			System.setOut(new PrintStream(new StringBufferStream(buffer)));
			MirrorApplication app = new MirrorApplication();
			app.addSource(createRepositoryDescriptor(sourceRepoLocation.toURI(), null, null, null));
			app.addDestination(createRepositoryDescriptor(destRepoLocation.toURI(), null, null, newName));
			//run the mirror application
			app.run(null);

		} catch (Exception e) {
			fail("Error running mirror application", e);
		} finally {
			System.setOut(out);
		}

		try {
			assertEquals("Assert name is set correctly after mirror", newName, getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null).getName());
		} catch (ProvisionException e) {
			fail("Error loading destination", e);
		}
	}

	/**
	 * Verifies that the mirror application copies files (including packed files) correctly
	 */
	@Test
	public void testArtifactFileCopying() {
		//Setup: load the repository containing packed data
		File packedRepoLocation = getTestData("26.0", "/testData/mirror/mirrorPackedRepo");

		try {
			basicRunMirrorApplication("26.1", packedRepoLocation.toURI(), destRepoLocation.toURI(), false, false);
		} catch (Exception e) {
			fail("26.3", e);
		}

		try {
			//Verify Contents
			assertContentEquals("26.4", getArtifactRepositoryManager().loadRepository(packedRepoLocation.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
			//Verify files on disk
			assertEqualArtifacts("26.5", (SimpleArtifactRepository) getArtifactRepositoryManager().loadRepository(packedRepoLocation.toURI(), null), (SimpleArtifactRepository) getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
		} catch (ProvisionException e) {
			fail("26.6", e);
		}
	}

	/**
	 * Verifies that the mirror application executes processing steps correctly
	 */
	@Test
	public void testArtifactProcessingSteps() {
		//Setup: load the repository containing packed data
		File packedRepoLocation = getTestData("27.0", "/testData/mirror/mirrorPackedRepo");
		IArtifactRepository packedRepo = null;
		IArtifactRepository destinationRepo = null;

		try {
			packedRepo = getArtifactRepositoryManager().loadRepository(packedRepoLocation.toURI(), null);
			destinationRepo = getArtifactRepositoryManager().createRepository(destRepoLocation.toURI(), "Test Repo", IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, null);
		} catch (ProvisionException e1) {
			fail("");
		}

		IQueryResult keys = packedRepo.query(ArtifactKeyQuery.ALL_KEYS, null);
		for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
			IArtifactKey key = (IArtifactKey) iterator.next();
			IArtifactDescriptor[] srcDescriptors = packedRepo.getArtifactDescriptors(key);

			for (int j = 0; j < srcDescriptors.length; j++) {
				if (!(srcDescriptors[j].getProperty(IArtifactDescriptor.FORMAT) == null) && srcDescriptors[j].getProperty(IArtifactDescriptor.FORMAT).equals(IArtifactDescriptor.FORMAT_PACKED)) {
					//if we have a packed artifact
					IArtifactDescriptor newDescriptor = new ArtifactDescriptor(key);
					Map properties = new OrderedProperties();
					properties.putAll(srcDescriptors[j].getProperties());
					properties.remove(IArtifactDescriptor.FORMAT);
					((ArtifactDescriptor) newDescriptor).addProperties(properties);
					//create appropriate descriptor
					try {
						OutputStream repositoryStream = null;
						try {
							//System.out.println("Mirroring: " + srcDescriptors[j].getArtifactKey() + " (Descriptor: " + srcDescriptors[j] + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
							repositoryStream = destinationRepo.getOutputStream(newDescriptor);
							if (repositoryStream == null)
								return;
							// TODO Is that ok to ignore the result?
							//TODO MAKE THIS WORK PROPERLY
							packedRepo.getArtifact(srcDescriptors[j], repositoryStream, new NullProgressMonitor());
						} finally {
							if (repositoryStream != null)
								repositoryStream.close();
						}
					} catch (ProvisionException e) {
						fail("27.1", e);
					} catch (IOException e) {
						fail("27.2", e);
					}
					//corresponding key should now be in the destination
					IArtifactDescriptor[] destDescriptors = destinationRepo.getArtifactDescriptors(key);
					boolean canonicalFound = false;
					for (int l = 0; !canonicalFound && (l < destDescriptors.length); l++) {
						//No processing steps mean item is canonical
						if (destDescriptors[l].getProcessingSteps().length == 0)
							canonicalFound = true;
					}
					if (!canonicalFound)
						fail("27.3 no canonical found for " + key.toString());

					//ensure the canonical matches that in the expected
					assertEqualArtifacts("27.3", (SimpleArtifactRepository) destinationRepo, (SimpleArtifactRepository) packedRepo);
				}
			}
		}
	}

	//for Bug 235683
	@Test
	public void testMirrorCompressedSource() {
		File compressedSource = getTestData("0", "/testData/mirror/mirrorCompressedRepo");

		//Setup: get the artifacts.jar file
		File compressedArtifactsXML = new File(compressedSource.getAbsoluteFile() + "/artifacts.jar");
		//Setup: make sure artifacts.jar exists
		assertTrue("1", compressedArtifactsXML.exists());

		try {
			basicRunMirrorApplication("2", compressedSource.toURI(), destRepoLocation.toURI(), false, false);
		} catch (MalformedURLException e) {
			fail("3", e);
		} catch (Exception e) {
			fail("4", e);
		}

		//get the artifacts.jar file
		File destArtifactsXML = new File(destRepoLocation.getAbsolutePath() + "/artifacts.jar");
		//make sure artifacts.jar exists
		assertTrue("5", destArtifactsXML.exists());
	}

	//for Bug 235683
	@Test
	public void testMirrorCompressedSourcetoUncompressedDestination() {
		File compressedSource = getTestData("0", "/testData/mirror/mirrorCompressedRepo");

		//Setup: get the artifacts.jar file
		File compressedArtifactsXML = new File(compressedSource.getAbsoluteFile() + "/artifacts.jar");
		//Setup: make sure artifacts.jar exists
		assertTrue("1", compressedArtifactsXML.exists());

		//Setup: create the destination
		try {
			String name = "Destination Name " + destRepoLocation;
			getArtifactRepositoryManager().createRepository(destRepoLocation.toURI(), name, IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, null);
		} catch (ProvisionException e) {
			fail("2", e);
		}

		assertTrue("2.1", new File(destRepoLocation, "artifacts.xml").exists());
		try {
			basicRunMirrorApplication("3", compressedSource.toURI(), destRepoLocation.toURI(), false, false);
		} catch (MalformedURLException e) {
			fail("4", e);
		} catch (Exception e) {
			fail("5", e);
		}

		//get the artifacts.jar file
		File destArtifactsXML = new File(destRepoLocation.getAbsolutePath() + "/artifacts.jar");
		//make sure artifacts.jar does not exist
		assertFalse("6", destArtifactsXML.exists());
		//get the artifacts.xml file
		destArtifactsXML = new File(destRepoLocation.getAbsolutePath() + "/artifacts.xml");
		//make sure artifacts.xml exists
		assertTrue("7", destArtifactsXML.exists());
	}

	//for Bug 235683
	@Test
	public void testMirrorUncompressedSourceToCompressedDestination() {
		File uncompressedSource = getTestData("0", "/testData/mirror/mirrorPackedRepo");

		//Setup: get the artifacts.xml file
		File artifactsXML = new File(uncompressedSource.getAbsoluteFile() + "/artifacts.xml");
		//Setup: make sure artifacts.xml exists
		assertTrue("1", artifactsXML.exists());

		//Setup: create the destination
		try {
			String name = "Destination Name " + destRepoLocation;
			Map property = new HashMap();
			property.put(IRepository.PROP_COMPRESSED, "true");
			getArtifactRepositoryManager().createRepository(destRepoLocation.toURI(), name, IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, property);
		} catch (ProvisionException e) {
			fail("2", e);
		}

		assertTrue("2.1", new File(destRepoLocation, "artifacts.jar").exists());
		try {
			basicRunMirrorApplication("3", uncompressedSource.toURI(), destRepoLocation.toURI(), false, false);
		} catch (MalformedURLException e) {
			fail("4", e);
		} catch (Exception e) {
			fail("5", e);
		}

		//get the artifacts.jar file
		File destArtifactsXML = new File(destRepoLocation.getAbsolutePath() + "/artifacts.jar");
		//make sure artifacts.jar does exist
		assertTrue("6", destArtifactsXML.exists());
		//get the artifacts.xml file
		destArtifactsXML = new File(destRepoLocation.getAbsolutePath() + "/artifacts.xml");
		//make sure artifacts.xml does not exist
		assertFalse("7", destArtifactsXML.exists());
	}

	@Test
	public void testMirrorApplicationWithCompositeSource() {
		//Setup Make composite repository
		File repoLocation = new File(getTempFolder(), "CompositeArtifactMirrorTest");
		AbstractProvisioningTest.delete(repoLocation);
		IArtifactRepository repo = null;
		try {
			repo = getArtifactRepositoryManager().createRepository(repoLocation.toURI(), "artifact name", IArtifactRepositoryManager.TYPE_COMPOSITE_REPOSITORY, null);
		} catch (ProvisionException e) {
			fail("Could not create repository");
		}
		//ensure proper type of repository has been created
		if (!(repo instanceof CompositeArtifactRepository))
			fail("Repository is not a CompositeArtifactRepository");
		//Populate source
		File child1 = getTestData("1", "/testData/mirror/mirrorSourceRepo1 with space");
		File child2 = getTestData("2", "/testData/mirror/mirrorSourceRepo2");
		((CompositeArtifactRepository) repo).addChild(child1.toURI());
		((CompositeArtifactRepository) repo).addChild(child2.toURI());

		runMirrorApplication("Mirroring from Composite Source", repoLocation, destRepoLocation, false);

		try {
			assertContentEquals("Verifying contents", repo, getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));

			//Verify that result is the same as mirroring from the 2 repositories separately
			assertContains("3", getArtifactRepositoryManager().loadRepository(sourceRepoLocation.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
			assertContains("4", getArtifactRepositoryManager().loadRepository(sourceRepo2Location.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
			//checks that the destination has the correct number of keys (no extras)
			assertEquals("5", getArtifactKeyCount(sourceRepoLocation.toURI()) + getArtifactKeyCount(sourceRepo2Location.toURI()), getArtifactKeyCount(destRepoLocation.toURI()));
		} catch (ProvisionException e) {
			fail("Could not load destination", e);
		}
	}

	//for Bug 250527
	@Test
	public void testIgnoreErrorsArgument() {
		//Error prints to stderr, redirect that to a file
		PrintStream oldErr = System.err;
		PrintStream newErr = null;
		try {
			try {
				destRepoLocation.mkdir();
				newErr = new PrintStream(new FileOutputStream(new File(destRepoLocation, "sys.err")));
			} catch (FileNotFoundException e) {
				fail("Error redirecting outputs", e);
			}
			System.setErr(newErr);

			//run test without verbose
			mirrorWithError(false);

		} finally {
			System.setErr(oldErr);
			if (newErr != null)
				newErr.close();
		}
		assertEquals("Verifying correct number of Keys", 2, getArtifactKeyCount(destRepoLocation.toURI()));
		//Because only 2 of the artifacts exists on disk, the number of artifacts in the destination should only be 1.
		//Order in which mirror application mirrors artifacts is random.

	}

	@DataPoints
	public static String[] defaultComparator = {null, MD5ArtifactComparator.MD5_COMPARATOR_ID};

	@Theory
	public void testCompareUsingMD5Comparator(String comparator) {
		//Setup create descriptors with different md5 values
		IArtifactKey dupKey = PublisherHelper.createBinaryArtifactKey("testKeyId", Version.create("1.2.3"));
		File artifact1 = getTestData("0.0", "/testData/mirror/mirrorSourceRepo1 with space/artifacts.xml");
		File artifact2 = getTestData("0.0", "/testData/mirror/mirrorSourceRepo2/artifacts.xml");
		IArtifactDescriptor descriptor1 = PublisherHelper.createArtifactDescriptor(dupKey, artifact1);
		IArtifactDescriptor descriptor2 = PublisherHelper.createArtifactDescriptor(dupKey, artifact2);

		assertEquals("Ensuring Descriptors are the same", descriptor1, descriptor2);
		assertNotEquals("Ensuring MD5 values are different", descriptor1.getProperty(IArtifactDescriptor.DOWNLOAD_MD5), descriptor2.getProperty(IArtifactDescriptor.DOWNLOAD_MD5));

		//Setup make repositories
		File repo1Location = getTestFolder(getUniqueString());
		File repo2Location = getTestFolder(getUniqueString());
		IArtifactRepository repo1 = null;
		IArtifactRepository repo2 = null;
		try {
			repo1 = getArtifactRepositoryManager().createRepository(repo1Location.toURI(), "Repo 1", IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, null);
			repo1.addDescriptor(descriptor1);
			repo2 = getArtifactRepositoryManager().createRepository(repo2Location.toURI(), "Repo 2", IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, null);
			repo2.addDescriptor(descriptor2);
		} catch (ProvisionException e) {
			fail("Error creating repositories", e);
		}

		PrintStream out = System.out;
		try {
			System.setOut(new PrintStream(new StringBufferStream()));
			MirrorApplication app = null;
			try {
				app = new MirrorApplication();
				app.addSource(createRepositoryDescriptor(repo1Location.toURI(), null, null, null));
				app.addDestination(createRepositoryDescriptor(repo2Location.toURI(), null, null, null));
				app.setVerbose(true);
				//Call a comparator
				app.setCompare(true);
				app.setComparatorID(comparator);
				//run the mirror application
				app.run(null);
			} catch (Exception e) {
				fail("Running mirror application with duplicate descriptors with different md5 values failed", e);
			}
		} finally {
			System.setOut(out);
		}

		IArtifactDescriptor[] destDescriptors = repo2.getArtifactDescriptors(descriptor2.getArtifactKey());
		assertEquals("Ensuring destination has correct number of descriptors", 1, destDescriptors.length);
		assertEquals("Ensuring proper descriptor exists in destination", descriptor2.getProperty(IArtifactDescriptor.DOWNLOAD_MD5), destDescriptors[0].getProperty(IArtifactDescriptor.DOWNLOAD_MD5));
		String msg = NLS.bind(Messages.warning_differentMD5, new Object[] {URIUtil.toUnencodedString(repo1.getLocation()), URIUtil.toUnencodedString(repo2.getLocation()), descriptor1});
		try {
			assertLogContainsLine(TestActivator.getLogFile(), msg);
		} catch (Exception e) {
			fail("error verifying output", e);
		}
	}

	@Theory
	public void testBaselineCompareUsingMD5Comparator(String comparator) {
		//Setup create descriptors with different md5 values
		IArtifactKey dupKey = PublisherHelper.createBinaryArtifactKey("testKeyId", Version.create("1.2.3"));
		File artifact1 = getTestData("0.0", "/testData/mirror/mirrorSourceRepo1 with space/content.xml");
		File artifact2 = getTestData("0.0", "/testData/mirror/mirrorSourceRepo2/content.xml");

		//Setup Copy the file to the baseline
		File repoLocation = getTestFolder(getUniqueString());
		File baselineLocation = getTestFolder(getUniqueString());
		File baselineBinaryDirectory = new File(baselineLocation, "binary");
		baselineBinaryDirectory.mkdir();
		File baselineContentLocation = new File(baselineBinaryDirectory, "testKeyId_1.2.3");
		AbstractProvisioningTest.copy("Copying File to baseline", artifact2, baselineContentLocation);

		IArtifactDescriptor descriptor1 = PublisherHelper.createArtifactDescriptor(dupKey, artifact1);
		IArtifactDescriptor descriptor2 = PublisherHelper.createArtifactDescriptor(dupKey, baselineContentLocation);

		assertEquals("Ensuring Descriptors are the same", descriptor1, descriptor2);
		assertNotEquals("Ensuring MD5 values are different", descriptor1.getProperty(IArtifactDescriptor.DOWNLOAD_MD5), descriptor2.getProperty(IArtifactDescriptor.DOWNLOAD_MD5));

		//Setup make repositories
		IArtifactRepository repo = null;
		IArtifactRepository baseline = null;
		try {
			repo = getArtifactRepositoryManager().createRepository(repoLocation.toURI(), "Repo 1", IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, null);
			repo.addDescriptor(descriptor1);
			baseline = getArtifactRepositoryManager().createRepository(baselineLocation.toURI(), "Repo 2", IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, null);
			baseline.addDescriptor(descriptor2);
		} catch (ProvisionException e) {
			fail("Error creating repositories", e);
		}

		MirrorApplication app = null;
		PrintStream out = System.out;
		try {
			System.setOut(new PrintStream(new StringBufferStream()));
			app = new MirrorApplication();
			app.addSource(createRepositoryDescriptor(repoLocation.toURI(), null, null, null));
			app.addDestination(createRepositoryDescriptor(destRepoLocation.toURI(), null, null, null));
			//Set baseline
			app.setBaseline(baselineLocation.toURI());
			app.setVerbose(true);
			//Call a comparator
			app.setCompare(true);
			app.setComparatorID(comparator);
			//run the mirror application
			app.run(null);
		} catch (Exception e) {
			fail("Running mirror application with baseline compare", e);

		} finally {
			System.setOut(out);
		}

		IArtifactRepository destination = null;
		try {
			destination = getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null);
		} catch (ProvisionException e) {
			fail("Error loading destination", e);
		}

		IArtifactDescriptor[] destDescriptors = destination.getArtifactDescriptors(descriptor2.getArtifactKey());
		assertEquals("Ensuring destination has correct number of descriptors", 1, destDescriptors.length);
		assertEquals("Ensuring destination contains the descriptor from the baseline", descriptor2.getProperty(IArtifactDescriptor.DOWNLOAD_MD5), destDescriptors[0].getProperty(IArtifactDescriptor.DOWNLOAD_MD5));
		String msg = NLS.bind(Messages.warning_differentMD5, new Object[] {URIUtil.toUnencodedString(baseline.getLocation()), URIUtil.toUnencodedString(repo.getLocation()), descriptor1});
		try {
			assertLogContainsLine(TestActivator.getLogFile(), msg);
		} catch (Exception e) {
			fail("error verifying output", e);
		}
	}

	//for Bug 259111
	@Test
	public void testDownloadRetry() {
		//repository that is known to force a retry
		class TestRetryArtifactRepository extends SimpleArtifactRepository {
			public boolean firstAttempt = true;
			IArtifactRepository source;

			public TestRetryArtifactRepository(String repositoryName, URI location, URI srcLocation, Map properties, IArtifactRepositoryManager manager) {
				super(getAgent(), repositoryName, location, properties);

				//initialize
				try {
					source = manager.loadRepository(srcLocation, null);
				} catch (ProvisionException e) {
					fail("Unable to load source for wrapping", e);
				}
				manager.removeRepository(srcLocation);
			}

			public synchronized Iterator<IArtifactKey> everything() {
				return ((SimpleArtifactRepository) source).everything();
			}

			public synchronized IArtifactDescriptor[] getArtifactDescriptors(IArtifactKey key) {
				return source.getArtifactDescriptors(key);
			}

			public IStatus getRawArtifact(IArtifactDescriptor descriptor, OutputStream destination, IProgressMonitor monitor) {
				if (firstAttempt) {
					firstAttempt = false;
					return new Status(IStatus.ERROR, Activator.ID, IArtifactRepository.CODE_RETRY, "Forcing Retry", new ProvisionException("Forcing retry"));
				}

				return source.getRawArtifact(descriptor, destination, monitor);
			}

			public synchronized boolean contains(IArtifactDescriptor descriptor) {
				return source.contains(descriptor);
			}

			public synchronized IQueryResult query(IQuery query, IProgressMonitor monitor) {
				return source.query(query, monitor);
			}
		}

		//set up test repository
		File retryRepoLoaction = new File(getTempFolder(), "259111 Repo");
		IArtifactRepository retryRepo = new TestRetryArtifactRepository("Test Repo", retryRepoLoaction.toURI(), sourceRepoLocation.toURI(), null, getArtifactRepositoryManager());
		((ArtifactRepositoryManager) getArtifactRepositoryManager()).addRepository(retryRepo);

		try {
			basicRunMirrorApplication("Forcing Retry", retryRepo.getLocation(), destRepoLocation.toURI());
		} catch (MalformedURLException e) {
			fail("Error creating arguments", e);
		} catch (Exception e) {
			fail("Error while running Mirror Application and forcing retry", e);
		}

		//ensure error was resulted
		assertFalse(((TestRetryArtifactRepository) retryRepo).firstAttempt);
		try {
			//verify destination's content
			assertContentEquals("Verifying content", getArtifactRepositoryManager().loadRepository(sourceRepoLocation.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
		} catch (ProvisionException e) {
			fail("Failure while verifying destination", e);
		}
	}

	//for Bug 259112
	@Test
	public void testErrorLoggingNoVerbose() {
		//initialize log file
		FrameworkLog log = ServiceHelper.getService(Activator.getContext(), FrameworkLog.class);
		assertNotNull("Assert log file is not null", log);
		assertTrue("Clearing log file", log.getFile().delete());

		PrintStream out = System.out;
		try {
			System.setOut(new PrintStream(new StringBufferStream()));
			//run test without verbose resulting in error
			mirrorWithError(false);
		} finally {
			System.setOut(out);
		}
		//verify log
		try {
			String[] parts = new String[] {"Artifact not found:", MISSING_ARTIFACT};
			assertLogContainsLine(log.getFile(), parts);
		} catch (Exception e) {
			fail("error verifying output", e);
		}

		//run without verbose
		artifactMirrorToFullDuplicate("Generating INFO entries", true);

		IArtifactRepository sourceRepository = null;
		try {
			sourceRepository = getArtifactRepositoryManager().loadRepository(sourceRepoLocation.toURI(), null);
		} catch (ProvisionException e) {
			fail("Error loading source repository for verification", e);
		}

		try {
			//Mirroring full duplicate, so any key will do.
			IQueryResult<IArtifactDescriptor> descriptors = sourceRepository.descriptorQueryable().query(ArtifactDescriptorQuery.ALL_DESCRIPTORS, null);
			IArtifactDescriptor descriptor = descriptors.iterator().next();
			//Mirroring full duplicate, so any descriptor will do.
			String message = NLS.bind(org.eclipse.equinox.internal.p2.artifact.repository.Messages.mirror_alreadyExists, descriptor, destRepoLocation.toURI());
			assertLogDoesNotContainLine(log.getFile(), message);
		} catch (Exception e) {
			fail("Error verifying log", e);
		}
	}

	//for Bug 259112
	@Test
	public void testErrorLoggingWithVerbose() {
		//initialize log file
		FrameworkLog log = ServiceHelper.getService(Activator.getContext(), FrameworkLog.class);
		assertNotNull("Assert log file is not null", log);
		assertTrue("Clearing log file", log.getFile().exists() && log.getFile().delete());

		//Comparator prints to stdout, redirect that to a file
		PrintStream oldOut = System.out;
		PrintStream newOut = null;
		PrintStream oldErr = System.err;
		PrintStream newErr = null;
		try {
			try {
				destRepoLocation.mkdir();
				newOut = new PrintStream(new FileOutputStream(new File(destRepoLocation, "sys.out")));
				newErr = new PrintStream(new FileOutputStream(new File(destRepoLocation, "sys.err")));
			} catch (FileNotFoundException e) {
				fail("Error redirecting output", e);
			}
			System.setOut(newOut);
			System.setErr(newErr);

			//run test with verbose, results in error
			mirrorWithError(true);

			//verify log
			try {
				String[] parts = new String[] {"Artifact not found:", MISSING_ARTIFACT};
				assertLogContainsLine(log.getFile(), parts);
			} catch (Exception e) {
				fail("error verifying output", e);
			}

			//run with verbose
			//populate destination with duplicate artifacts. We assume this works
			runMirrorApplication("Initializing Destiantion", sourceRepoLocation, destRepoLocation, false); //value of append should not matter

			try {
				MirrorApplication app = new MirrorApplication();
				app.addSource(createRepositoryDescriptor(sourceRepoLocation.toURI(), null, null, null));
				app.addDestination(createRepositoryDescriptor(destRepoLocation.toURI(), null, null, null));
				//set the arguments with verbose
				app.setVerbose(true);
				//run the mirror application
				app.run(null);
			} catch (Exception e) {
				fail("Error running mirror application to generate INFO items", e);
			}

		} finally {
			System.setOut(oldOut);
			if (newOut != null)
				newOut.close();
			System.setErr(oldErr);
			if (newErr != null)
				newErr.close();
		}

		IArtifactRepository sourceRepository = null;
		try {
			sourceRepository = getArtifactRepositoryManager().loadRepository(sourceRepoLocation.toURI(), null);
		} catch (ProvisionException e) {
			fail("Error loading source repository for verification", e);
		}

		try {
			//Mirroring full duplicate, so any key will do.
			IQueryResult<IArtifactDescriptor> descriptors = sourceRepository.descriptorQueryable().query(ArtifactDescriptorQuery.ALL_DESCRIPTORS, null);
			IArtifactDescriptor descriptor = descriptors.iterator().next();
			//Mirroring full duplicate, so any descriptor will do.
			String message = NLS.bind(org.eclipse.equinox.internal.p2.artifact.repository.Messages.mirror_alreadyExists, descriptor, destRepoLocation.toURI());
			assertLogContainsLine(log.getFile(), message);
		} catch (Exception e) {
			fail("Error verifying log", e);
		}
	}

	/**
	 * Test how the mirror application handles a repository specified as a local path
	 */
	@Test
	public void testArtifactMirrorNonURIDest() {
		try {
			basicRunMirrorApplication("Mirroring", sourceRepoLocation.toURI(), destRepoLocation.toURI());
			assertContentEquals("2.1", getArtifactRepositoryManager().loadRepository(sourceRepoLocation.toURI(), null), getArtifactRepositoryManager().loadRepository(destRepoLocation.toURI(), null));
		} catch (Exception e) {
			fail("Error mirroring", e);
		}
	}
}