/*
 *  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
 *
 *      https://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.ivy.core.resolve;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.ivy.Ivy;
import org.apache.ivy.TestHelper;
import org.apache.ivy.core.cache.ArtifactOrigin;
import org.apache.ivy.core.cache.DefaultRepositoryCacheManager;
import org.apache.ivy.core.deliver.DeliverOptions;
import org.apache.ivy.core.module.descriptor.Artifact;
import org.apache.ivy.core.module.descriptor.DefaultArtifact;
import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
import org.apache.ivy.core.module.descriptor.ExtendsDescriptor;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.apache.ivy.core.module.id.ArtifactRevisionId;
import org.apache.ivy.core.module.id.ModuleId;
import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.apache.ivy.core.report.ArtifactDownloadReport;
import org.apache.ivy.core.report.ConfigurationResolveReport;
import org.apache.ivy.core.report.DownloadStatus;
import org.apache.ivy.core.report.ResolveReport;
import org.apache.ivy.core.settings.IvySettings;
import org.apache.ivy.plugins.circular.CircularDependencyException;
import org.apache.ivy.plugins.circular.ErrorCircularDependencyStrategy;
import org.apache.ivy.plugins.circular.IgnoreCircularDependencyStrategy;
import org.apache.ivy.plugins.circular.WarnCircularDependencyStrategy;
import org.apache.ivy.plugins.conflict.StrictConflictException;
import org.apache.ivy.plugins.matcher.ExactPatternMatcher;
import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorParser;
import org.apache.ivy.plugins.repository.AbstractRepository;
import org.apache.ivy.plugins.repository.Resource;
import org.apache.ivy.plugins.resolver.BasicResolver;
import org.apache.ivy.plugins.resolver.DependencyResolver;
import org.apache.ivy.plugins.resolver.DualResolver;
import org.apache.ivy.plugins.resolver.FileSystemResolver;
import org.apache.ivy.util.CacheCleaner;
import org.apache.ivy.util.FileUtil;
import org.apache.ivy.util.MockMessageLogger;
import org.apache.ivy.util.XMLHelper;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;

import static org.apache.ivy.util.StringUtils.joinArray;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

public final class ResolveTest {

    private Ivy ivy;

    private File cache, workDir, deliverDir;

    @Before
    public void setUp() throws Exception {
        cache = new File("build/cache");
        System.setProperty("ivy.cache.dir", cache.getAbsolutePath());
        createCache();

        deliverDir = new File("build/test/deliver");
        deliverDir.mkdirs();

        workDir = new File("build/test/work");
        workDir.mkdirs();

        ivy = Ivy.newInstance();
        ivy.configure(new File("test/repositories/ivysettings.xml"));
    }

    private void createCache() {
        cache.mkdirs();
    }

    @After
    public void tearDown() {
        CacheCleaner.deleteDir(cache);
        FileUtil.forceDelete(deliverDir);
        FileUtil.forceDelete(workDir);
    }

    @Test
    public void testResolveWithRetainingArtifactName() throws Exception {
        ((DefaultRepositoryCacheManager) ivy.getSettings().getDefaultRepositoryCacheManager())
                .setArtifactPattern(ivy.substitute("[module]/[originalname].[ext]"));
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod15.2/ivy-1.1.xml"),
            getResolveOptions(new String[] {"default"}));
        assertNotNull(report);

        ArtifactDownloadReport[] dReports = report.getConfigurationReport("default")
                .getDownloadReports(ModuleRevisionId.newInstance("org15", "mod15.1", "1.1"));
        assertNotNull(dReports);
        assertEquals("number of downloaded artifacts not correct", 1, dReports.length);

        Artifact artifact = dReports[0].getArtifact();
        assertNotNull(artifact);

        String cachePath = getArchivePathInCache(artifact);
        assertTrue("artifact name has not been retained: " + cachePath,
            cachePath.endsWith("library.jar"));

        dReports = report.getConfigurationReport("default").getDownloadReports(
            ModuleRevisionId.newInstance("org14", "mod14.1", "1.1"));
        assertNotNull(dReports);
        assertEquals("number of downloaded artifacts not correct", 1, dReports.length);

        artifact = dReports[0].getArtifact();
        assertNotNull(artifact);

        cachePath = getArchivePathInCache(artifact);
        assertTrue("artifact name has not been retained: " + cachePath,
            cachePath.endsWith("mod14.1-1.1.jar"));
    }

    @Test
    public void testResolveWithRetainingArtifactNameAndExtraAttributes() throws Exception {
        ((DefaultRepositoryCacheManager) ivy.getSettings().getDefaultRepositoryCacheManager())
                .setArtifactPattern(ivy.substitute("[module]/[originalname].[ext]"));
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod15.4/ivy-1.1.xml"),
            getResolveOptions(new String[] {"default"}).setValidate(false));
        assertNotNull(report);

        Map<String, String> extra = new HashMap<>();
        extra.put("extra", "foo");
        ArtifactDownloadReport[] dReports = report.getConfigurationReport("default")
                .getDownloadReports(ModuleRevisionId.newInstance("org15", "mod15.3", "1.1", extra));
        assertNotNull(dReports);
        assertEquals("number of downloaded artifacts not correct", 1, dReports.length);

        Artifact artifact = dReports[0].getArtifact();
        assertNotNull(artifact);

        String cachePath = getArchivePathInCache(artifact);
        assertTrue("artifact name has not been retained: " + cachePath,
            cachePath.endsWith("library.jar"));

        dReports = report.getConfigurationReport("default").getDownloadReports(
            ModuleRevisionId.newInstance("org14", "mod14.1", "1.1"));
        assertNotNull(dReports);
        assertEquals("number of downloaded artifacts not correct", 1, dReports.length);

        artifact = dReports[0].getArtifact();
        assertNotNull(artifact);

        cachePath = getArchivePathInCache(artifact);
        assertTrue("artifact name has not been retained: " + cachePath,
            cachePath.endsWith("mod14.1-1.1.jar"));
    }

    @Test
    public void testArtifactOrigin() throws Exception {
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org1/mod1.1/ivys/ivy-1.0.xml"),
            getResolveOptions(new String[] {"default"}));
        assertNotNull(report);

        ArtifactDownloadReport[] dReports = report.getConfigurationReport("default")
                .getDownloadReports(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"));
        assertNotNull(dReports);
        assertEquals("number of downloaded artifacts not correct", 1, dReports.length);

        Artifact artifact = dReports[0].getArtifact();
        assertNotNull(artifact);

        String expectedLocation = new File("test/repositories/1/org1/mod1.2/jars/mod1.2-2.0.jar")
                .getAbsolutePath();

        // verify the origin in the report
        ArtifactOrigin reportOrigin = dReports[0].getArtifactOrigin();
        assertNotNull(reportOrigin);
        assertTrue("isLocal for artifact not correct", reportOrigin.isLocal());
        assertEquals("location for artifact not correct", expectedLocation,
            reportOrigin.getLocation());

        // verify the saved origin on disk
        ArtifactOrigin ivyOrigin = getSavedArtifactOrigin(artifact);
        assertNotNull(ivyOrigin);
        assertTrue("isLocal for artifact not correct", ivyOrigin.isLocal());
        assertEquals("location for artifact not correct", expectedLocation, ivyOrigin.getLocation());

        // now resolve the same artifact again and verify the origin of the (not-downloaded)
        // artifact
        report = ivy.resolve(new File("test/repositories/1/org1/mod1.1/ivys/ivy-1.0.xml"),
            getResolveOptions(new String[] {"default"}));
        assertNotNull(report);

        dReports = report.getConfigurationReport("default").getDownloadReports(
            ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"));
        assertNotNull(dReports);
        assertEquals("number of downloaded artifacts not correct", 1, dReports.length);
        assertEquals("download status not correct", DownloadStatus.NO,
            dReports[0].getDownloadStatus());
        reportOrigin = dReports[0].getArtifactOrigin();
        assertNotNull(reportOrigin);
        assertTrue("isLocal for artifact not correct", reportOrigin.isLocal());
        assertEquals("location for artifact not correct", expectedLocation,
            reportOrigin.getLocation());
    }

    @Test
    public void testUseOrigin() throws Exception {
        ((DefaultRepositoryCacheManager) ivy.getSettings().getDefaultRepositoryCacheManager())
                .setUseOrigin(true);

        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org1/mod1.1/ivys/ivy-1.0.xml"),
            getResolveOptions(new String[] {"default"}));
        assertNotNull(report);

        ArtifactDownloadReport[] dReports = report.getConfigurationReport("default")
                .getDownloadReports(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"));
        assertNotNull(dReports);
        assertEquals("number of downloaded artifacts not correct.", 1, dReports.length);
        assertEquals(
            "download status not correct: should not download the artifact in useOrigin mode.",
            DownloadStatus.NO, dReports[0].getDownloadStatus());

        Artifact artifact = dReports[0].getArtifact();
        assertNotNull(artifact);

        String expectedLocation = new File("test/repositories/1/org1/mod1.2/jars/mod1.2-2.0.jar")
                .getAbsolutePath();

        ArtifactOrigin origin = getSavedArtifactOrigin(artifact);
        File artInCache = new File(cache, getArchivePathInCache(artifact, origin));
        assertFalse("should not download artifact in useOrigin mode.", artInCache.exists());
        assertEquals("location for artifact not correct.", expectedLocation,
            getArchiveFileInCache(artifact).getAbsolutePath());
    }

    @Test
    public void testResolveSimple() throws Exception {
        // mod1.1 depends on mod1.2
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org1/mod1.1/ivys/ivy-1.0.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org1", "mod1.1", "1.0");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testResolveBadStatus() throws Exception {
        // mod1.4 depends on modfailure, modfailure has a bad status
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org1/mod1.4/ivys/ivy-1.1.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        assertTrue(report.hasError());
    }

    @Test
    public void testResolveWithXmlEntities() {
        testResolveWithXmlEntities(null, 0);
        testResolveWithXmlEntities("prohibit", 0);
        testResolveWithXmlEntities("ignore", 0);
        testResolveWithXmlEntities("local-only", 2);
        testResolveWithXmlEntities("LOCAL_ONLY", 2);
        testResolveWithXmlEntities("all", 2);
    }

    private void testResolveWithXmlEntities(String externalResourcesSystemProperty,
            int expectedNumberOfDependencies) {
        Ivy ivy = new Ivy();
        Throwable th = null;
        Properties p = (Properties) System.getProperties().clone();
        try {
            System.setProperty(XMLHelper.ALLOW_DOCTYPE_PROCESSING, "true");
            if (externalResourcesSystemProperty != null) {
                System.setProperty(XMLHelper.EXTERNAL_RESOURCES, externalResourcesSystemProperty);
            }
            ivy.configure(new File("test/repositories/xml-entities/ivysettings.xml"));
            ResolveReport report = ivy.resolve(new File("test/repositories/xml-entities/ivy.xml"),
                getResolveOptions(new String[] {"*"}));
            assertNotNull(report);
            assertFalse(report.hasError());
            assertNotNull(report.getDependencies());
            assertEquals("number of dependencies while setting " + externalResourcesSystemProperty,
                expectedNumberOfDependencies, report.getDependencies().size());
        } catch (Throwable e) {
            th = e;
        } finally {
            System.setProperties(p);
        }
        assertNull(th);
    }

    @Test
    public void testResolveWithXmlEntitiesButNoSystemProperty() {
        Ivy ivy = new Ivy();
        Throwable th = null;
        try {
            ivy.configure(new File("test/repositories/xml-entities/ivysettings.xml"));
            ResolveReport report = ivy.resolve(new File("test/repositories/xml-entities/ivy.xml"),
                getResolveOptions(new String[] {"*"}));
            assertNotNull(report);
            assertFalse(report.hasError());
        } catch (Throwable e) {
            th = e;
        }
        assertNotNull(th);
    }

    @Test
    public void testResolveNoRevisionInPattern() throws Exception {
        // module1 depends on latest version of module2, for which there is no revision in the
        // pattern
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/norev/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File("test/repositories/norev/ivy.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        assertFalse(report.hasError());
    }

    @Test
    public void testResolveLatestWithNoRevisionInPattern() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/norev/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File("test/repositories/norev/ivy-latest.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        assertFalse(report.hasError());
    }

    @Test
    public void testResolveNoRevisionInDep() throws Exception {
        // mod1.4 depends on mod1.6, in which the ivy file has no revision
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org1/mod1.4/ivys/ivy-1.2.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        assertTrue(report.hasError());
    }

    /**
     * Test case for IVY-258.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-258">IVY-258</a>
     */
    @Test
    public void testResolveNoRevisionNowhere() throws Exception {
        // module1 depends on latest version of module2, which contains no revision in its ivy file,
        // nor in the pattern
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/IVY-258/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File("test/repositories/IVY-258/ivy.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        ((BasicResolver) ivy.getSettings().getResolver("myresolver")).setCheckconsistency(false);
        report = ivy.resolve(new File("test/repositories/IVY-258/ivy.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());
    }

    /**
     * Test case for IVY-448.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-448">IVY-448</a>
     */
    @Test
    public void testResolveWithConflictManagerPerModule() throws Exception {
        // all modules from myorg
        // module1
        // -> module2-1.0
        // -> module3-2.0
        // module2
        // -> module3-1.0
        // settings use 'all' as default conflict manager, and latest-revision for modules from
        // myorg
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/IVY-448/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File("test/repositories/IVY-448/ivy.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        // rev 1.0 should have been evicted by latest-revision conflict manager
        assertTrue(getArchiveFileInCache(ivy, "myorg", "module3", "2.0", "module3", "jar", "jar")
                .exists());
        assertFalse(getArchiveFileInCache(ivy, "myorg", "module3", "1.0", "module3", "jar", "jar")
                .exists());
    }

    /**
     * Test case for IVY-465.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-465">IVY-465</a>
     */
    @Test
    public void testResolveWithConflictManagerDefinedInModule() throws Exception {
        // #M1;1.0 -> #M2;1.0
        // #M2;1.0 -> {org1#mod1.2;1.1 org1#mod1.2;2.0} with
        // <conflict org="org1" module="mod1.2" rev="1.1,2.0" />

        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/IVY-465/M1/ivys/ivy-1.0.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        ArtifactDownloadReport[] adrs = report.getConfigurationReport("default")
                .getDownloadedArtifactsReports();
        assertEquals(2, adrs.length);
        assertEquals("1.1", adrs[0].getArtifact().getId().getRevision());
        assertEquals("2.0", adrs[1].getArtifact().getId().getRevision());
    }

    /**
     * Test case for IVY-1404.
     *
     * @see <a href="https://issues.apache.org/jira/browse/IVY-1404">IVY-1404</a>
     * @throws Exception if something goes wrong
     */
    @Test
    public void testResolveWithConflictManagerDefinedAtHigherLevel() throws Exception {
        // #M1;1.0 -> #M2;1.0
        // #M1;2.0 -> {#M2;1.0 #M3;1.0}
        // #M2;1.0 -> org1#mod1.2;1.1
        // #M3;1.0 -> org1#mod1.2;2.0
        // #M1;1.0 has conflict manager: <conflict org="org1" module="mod1.2" rev="1.1,2.0" />

        ResolveReport report = ivy.resolve(new File(
                        "test/repositories/1/IVY-1404/M1/ivys/ivy-1.0.xml"),
                getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        ArtifactDownloadReport[] adrs = report.getConfigurationReport("default")
                .getDownloadedArtifactsReports();
        assertEquals(2, adrs.length);
        assertEquals("1.1", adrs[0].getArtifact().getId().getRevision());
        assertEquals("2.0", adrs[1].getArtifact().getId().getRevision());
    }

    @Test
    public void testResolveRequiresDescriptor() throws Exception {
        // mod1.1 depends on mod1.2, mod1.2 has no ivy file
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/ivysettings.xml"));
        ((FileSystemResolver) ivy.getSettings().getResolver("1"))
                .setDescriptor(FileSystemResolver.DESCRIPTOR_REQUIRED);
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org1/mod1.1/ivys/ivy-1.0.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        assertTrue(report.hasError());
    }

    @Test
    public void testResolveOtherConfiguration() throws Exception {
        ResolveReport report = ivy.resolve(ResolveTest.class.getResource("ivy-other.xml"),
            getResolveOptions(new String[] {"test"}));

        assertNotNull(report);
        assertFalse(report.hasError());

        assertEquals("Number of artifacts not correct", 1, report.getConfigurationReport("test")
                .getArtifactsNumber());
    }

    /**
     * Test case for IVY-198.
     *
     * @see <a href="https://issues.apache.org/jira/browse/IVY-198">IVY-198</a>
     * @throws Exception if something goes wrong
     */
    @Test
    public void testResolveWithSlashes() throws Exception {
        // module depends on mod1.2
        ResolveReport report = ivy.resolve(ResolveTest.class.getResource("ivy-198.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("myorg/mydep", "system/module", "1.0");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(
            ModuleRevisionId.newInstance("yourorg/yourdep", "yoursys/yourmod", "1.0")).exists());
        assertTrue(getArchiveFileInCache("yourorg/yourdep", "yoursys/yourmod", "1.0", "yourmod",
            "jar", "jar").exists());
    }

    @Test
    public void testFromCache() throws Exception {
        // mod1.1 depends on mod1.2

        // we first do a simple resolve so that module is in cache
        ivy.resolve(new File("test/repositories/1/org1/mod1.1/ivys/ivy-1.0.xml"),
            getResolveOptions(new String[] {"*"}));

        // we now use a badly configured ivy, so that it can't find module in repository
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/bugIVY-56/ivysettings.xml"));
        ivy.getSettings().setDefaultCache(cache);
        ivy.getSettings().validate();

        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org1/mod1.1/ivys/ivy-1.0.xml"),
            getResolveOptions(ivy.getSettings(), new String[] {"*"}));
        assertFalse(report.hasError());

        ModuleDescriptor md = report.getModuleDescriptor();

        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org1", "mod1.1", "1.0");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(ivy, mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testFromCache2() throws Exception {
        // mod1.1 depends on mod1.2

        Ivy ivy = ivyTestCache();

        // set up repository
        FileUtil.forceDelete(new File("build/testCache2"));
        File art = new File("build/testCache2/mod1.2-2.0.jar");
        FileUtil.copy(new File("test/repositories/1/org1/mod1.2/jars/mod1.2-2.0.jar"), art, null);

        // we first do a simple resolve so that module is in cache
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org1/mod1.1/ivys/ivy-1.0.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        // now we clean the repository to simulate repo not available (network pb for instance)
        FileUtil.forceDelete(new File("build/testCache2"));

        // now do a new resolve: it should use cached data
        report = ivy.resolve(new File("test/repositories/1/org1/mod1.1/ivys/ivy-1.0.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        ModuleDescriptor md = report.getModuleDescriptor();

        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org1", "mod1.1", "1.0");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(ivy, mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testDynamicFromCache() throws Exception {
        // mod1.4;1.0.2 depends on mod1.2;[1.0,2.0[

        Ivy ivy = ivyTestCache();
        ivy.getSettings().setVariable("ivy.cache.ttl.default", "10s", true);

        // set up repository
        FileUtil.forceDelete(new File("build/testCache2"));
        FileUtil.copy(new File("test/repositories/1/org1/mod1.2/jars/mod1.2-2.0.jar"), new File(
                "build/testCache2/mod1.2-1.5.jar"), null);

        // we first do a simple resolve so that module is in cache
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org1/mod1.4/ivys/ivy-1.0.2.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        assertEquals(Collections.singleton(ModuleRevisionId.newInstance("org1", "mod1.2", "1.5")),
                report.getConfigurationReport("default").getModuleRevisionIds());

        // now we clean the repository to simulate repo not available (network pb for instance)
        FileUtil.forceDelete(new File("build/testCache2"));

        // now do a new resolve: it should use cached data
        report = ivy.resolve(new File("test/repositories/1/org1/mod1.4/ivys/ivy-1.0.2.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        assertEquals(Collections.singleton(ModuleRevisionId.newInstance("org1", "mod1.2", "1.5")),
                report.getConfigurationReport("default").getModuleRevisionIds());
    }

    @Test
    public void testDynamicFromCacheWithMD() throws Exception {
        // same as above, but this time the dependency has a module descriptor
        // mod1.4;1.0.2 depends on mod1.2;[1.0,2.0[

        Ivy ivy = ivyTestCache();
        ivy.getSettings().setVariable("ivy.cache.ttl.default", "10s", true);

        // set up repository
        FileUtil.forceDelete(new File("build/testCache2"));
        FileUtil.copy(ResolveTest.class.getResourceAsStream("ivy-mod1.2-1.5.xml"), new File(
                "build/testCache2/ivy-mod1.2-1.5.xml"), null);
        FileUtil.copy(new File("test/repositories/1/org1/mod1.2/jars/mod1.2-2.0.jar"), new File(
                "build/testCache2/mod1.2-1.5.jar"), null);

        // we first do a simple resolve so that module is in cache
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org1/mod1.4/ivys/ivy-1.0.2.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        assertEquals(Collections.singleton(ModuleRevisionId.newInstance("org1", "mod1.2", "1.5")),
                report.getConfigurationReport("default").getModuleRevisionIds());

        // now we clean the repository to simulate repo not available (network pb for instance)
        FileUtil.forceDelete(new File("build/testCache2"));

        // now do a new resolve: it should use cached data
        report = ivy.resolve(new File("test/repositories/1/org1/mod1.4/ivys/ivy-1.0.2.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        assertEquals(Collections.singleton(ModuleRevisionId.newInstance("org1", "mod1.2", "1.5")),
                report.getConfigurationReport("default").getModuleRevisionIds());
    }

    @Test
    public void testDynamicFromCacheWithMDAfterOneTTLExpiration() throws Exception {
        // same as above, but this time we make a second resolve after ttl expiration before trying
        // to use the cached resolved information
        // mod1.4;1.0.2 depends on mod1.2;[1.0,2.0[

        Ivy ivy = ivyTestCache();
        ivy.getSettings().setVariable("ivy.cache.ttl.default", "500ms", true);

        // set up repository
        FileUtil.forceDelete(new File("build/testCache2"));
        FileUtil.copy(ResolveTest.class.getResourceAsStream("ivy-mod1.2-1.5.xml"), new File(
                "build/testCache2/ivy-mod1.2-1.5.xml"), null);
        FileUtil.copy(new File("test/repositories/1/org1/mod1.2/jars/mod1.2-2.0.jar"), new File(
                "build/testCache2/mod1.2-1.5.jar"), null);

        // we first do a simple resolve so that module is in cache
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org1/mod1.4/ivys/ivy-1.0.2.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        assertEquals(Collections.singleton(ModuleRevisionId.newInstance("org1", "mod1.2", "1.5")),
                report.getConfigurationReport("default").getModuleRevisionIds());

        // now we wait for ttl expiration
        Thread.sleep(700);

        // we resolve again, it should work fine
        report = ivy.resolve(new File("test/repositories/1/org1/mod1.4/ivys/ivy-1.0.2.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        assertEquals(Collections.singleton(ModuleRevisionId.newInstance("org1", "mod1.2", "1.5")),
                report.getConfigurationReport("default").getModuleRevisionIds());

        // now we clean the repository to simulate repo not available (network pb for instance)
        FileUtil.forceDelete(new File("build/testCache2"));

        // now do a new resolve: it should use cached data
        report = ivy.resolve(new File("test/repositories/1/org1/mod1.4/ivys/ivy-1.0.2.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        assertEquals(Collections.singleton(ModuleRevisionId.newInstance("org1", "mod1.2", "1.5")),
                report.getConfigurationReport("default").getModuleRevisionIds());
    }

    @Test
    public void testDynamicFromCacheWithTTL0() throws Exception {
        // mod1.4;1.0.2 depends on mod1.2;[1.0,2.0[

        Ivy ivy = ivyTestCache();
        ivy.getSettings().setVariable("ivy.cache.ttl.default", "0ms", true);

        // set up repository
        FileUtil.forceDelete(new File("build/testCache2"));
        FileUtil.copy(new File("test/repositories/1/org1/mod1.2/jars/mod1.2-2.0.jar"), new File("build/testCache2/mod1.2-1.5.jar"), null);

        // we first do a simple resolve so that module is in cache
        ResolveReport report = ivy.resolve(new File("test/repositories/1/org1/mod1.4/ivys/ivy-1.0.2.xml"), getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        assertEquals(Collections.singleton(ModuleRevisionId.newInstance("org1", "mod1.2", "1.5")), report.getConfigurationReport("default").getModuleRevisionIds());

        // now we update the repository
        FileUtil.copy(new File("test/repositories/1/org1/mod1.2/jars/mod1.2-2.0.jar"), new File("build/testCache2/mod1.2-1.6.jar"), null);

        // now do a new resolve: it should not use cached data
        report = ivy.resolve(new File("test/repositories/1/org1/mod1.4/ivys/ivy-1.0.2.xml"), getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        assertEquals(Collections.singleton(ModuleRevisionId.newInstance("org1", "mod1.2", "1.6")), report.getConfigurationReport("default").getModuleRevisionIds());
    }

    @Test
    public void testDynamicFromCacheWithTTL() throws Exception {
        // mod1.4;1.0.2 depends on mod1.2;[1.0,2.0[
        Ivy ivy = ivyTestCache();
        ivy.getSettings().setVariable("ivy.cache.ttl.default", "10s", true);
        ((DefaultRepositoryCacheManager) ivy.getSettings().getDefaultRepositoryCacheManager())
                .addTTL(ModuleRevisionId.newInstance("org1", "*", "*").getAttributes(),
                    ExactPatternMatcher.INSTANCE, 500);

        // set up repository
        FileUtil.forceDelete(new File("build/testCache2"));
        FileUtil.copy(new File("test/repositories/1/org1/mod1.2/jars/mod1.2-2.0.jar"), new File(
                "build/testCache2/mod1.2-1.5.jar"), null);

        // we first do a simple resolve so that module is in cache
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org1/mod1.4/ivys/ivy-1.0.2.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        // now we update the repository
        FileUtil.copy(new File("test/repositories/1/org1/mod1.2/jars/mod1.2-2.0.jar"), new File(
                "build/testCache2/mod1.2-1.6.jar"), null);

        // now do a new resolve: it should use cached data
        report = ivy.resolve(new File("test/repositories/1/org1/mod1.4/ivys/ivy-1.0.2.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        assertEquals(Collections.singleton(ModuleRevisionId.newInstance("org1", "mod1.2", "1.5")),
                report.getConfigurationReport("default").getModuleRevisionIds());

        // wait for org1 TTL to expire
        Thread.sleep(700);

        // now do a new resolve: it should resolve the dynamic revision again
        report = ivy.resolve(new File("test/repositories/1/org1/mod1.4/ivys/ivy-1.0.2.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        assertEquals(Collections.singleton(ModuleRevisionId.newInstance("org1", "mod1.2", "1.6")),
                report.getConfigurationReport("default").getModuleRevisionIds());
    }

    @Test
    public void testRefreshDynamicFromCache() throws Exception {
        // mod1.4;1.0.2 depends on mod1.2;[1.0,2.0[
        Ivy ivy = ivyTestCache();
        ivy.getSettings().setVariable("ivy.cache.ttl.default", "10s", true);

        // set up repository
        FileUtil.forceDelete(new File("build/testCache2"));
        FileUtil.copy(new File("test/repositories/1/org1/mod1.2/jars/mod1.2-2.0.jar"), new File(
                "build/testCache2/mod1.2-1.5.jar"), null);

        // we first do a simple resolve so that module is in cache
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org1/mod1.4/ivys/ivy-1.0.2.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        // now we update the repository
        FileUtil.copy(new File("test/repositories/1/org1/mod1.2/jars/mod1.2-2.0.jar"), new File(
                "build/testCache2/mod1.2-1.6.jar"), null);

        // now do a new resolve: it should use cached data
        report = ivy.resolve(new File("test/repositories/1/org1/mod1.4/ivys/ivy-1.0.2.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        assertEquals(Collections.singleton(ModuleRevisionId.newInstance("org1", "mod1.2", "1.5")),
                report.getConfigurationReport("default").getModuleRevisionIds());

        // resolve again with refresh: it should find the new version
        report = ivy.resolve(new File("test/repositories/1/org1/mod1.4/ivys/ivy-1.0.2.xml"),
            getResolveOptions(new String[] {"*"}).setRefresh(true));
        assertFalse(report.hasError());

        assertEquals(Collections.singleton(ModuleRevisionId.newInstance("org1", "mod1.2", "1.6")),
                report.getConfigurationReport("default").getModuleRevisionIds());

        FileUtil.forceDelete(new File("build/testCache2"));
    }

    /**
     * Configures an Ivy instance using a resolver locating modules on file system, in a
     * build/testCache2 location which is created for the test and removed after, and can thus
     * easily simulate a repository availability problem
     *
     * @return the configured ivy instance
     */
    private Ivy ivyTestCache() {
        Ivy ivy = Ivy.newInstance();
        DualResolver resolver = new DualResolver();
        resolver.setName("dual");
        FileSystemResolver r = new FileSystemResolver();
        r.setName("1");
        r.addIvyPattern(ivy.getSettings().getBaseDir().getPath()
                + "/build/testCache2/ivy-[module]-[revision].xml");
        resolver.add(r);
        r = new FileSystemResolver();
        r.setName("2");
        r.addArtifactPattern(ivy.getSettings().getBaseDir().getPath()
                + "/build/testCache2/[artifact]-[revision].[ext]");
        resolver.add(r);
        ivy.getSettings().addResolver(resolver);
        ivy.getSettings().setDefaultResolver("dual");
        return ivy;
    }

    @Test
    public void testFromCacheOnly() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/bugIVY-56/ivysettings.xml"));
        ivy.getSettings().setDefaultCache(cache);

        // ResolveReport report = ivy.resolve(new
        // File("test/repositories/1/org1/mod1.1/ivys/ivy-1.0.xml"),
        // getResolveOptions(new String[] {"*"}));
        // // should have an error, the conf is bad and the dependency should not be found
        // assertTrue(report.hasError());

        // put necessary stuff in cache, and it should now be ok
        File ivyfile = getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"));
        File art = getArchiveFileInCache(ivy, "org1", "mod1.2", "2.0", "mod1.2", "jar", "jar");
        FileUtil.copy(ResolveTest.class.getResource("ivy-mod1.2.xml"), ivyfile, null, null);
        FileUtil.copy(new File("test/repositories/1/org1/mod1.2/jars/mod1.2-2.0.jar"), art, null);

        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org1/mod1.1/ivys/ivy-1.0.xml"),
            getResolveOptions(ivy.getSettings(), new String[] {"*"}));
        assertFalse(report.hasError());
    }

    @Test
    public void testChangeCacheLayout() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/ivysettings.xml"));
        DefaultRepositoryCacheManager cacheMgr = (DefaultRepositoryCacheManager) ivy.getSettings()
                .getDefaultRepositoryCacheManager();

        cacheMgr.setIvyPattern("[module]/ivy.xml");
        cacheMgr.setArtifactPattern("[artifact].[ext]");

        // mod1.1 depends on mod1.2
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org1/mod1.1/ivys/ivy-1.0.xml"),
            getResolveOptions(ivy.getSettings(), new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org1", "mod1.1", "1.0");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(ivy, mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ivy, ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(new File(cache, "mod1.2/ivy.xml").exists());
        assertTrue(getArchiveFileInCache(ivy, "org1", "mod1.2", "2.0", "mod1.2", "jar", "jar")
                .exists());
        assertTrue(new File(cache, "mod1.2.jar").exists());
    }

    @Test
    public void testChangeCacheLayout2() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/ivysettings.xml"));
        ivy.getSettings().setDefaultRepositoryCacheBasedir(
            new File(ivy.getSettings().getDefaultCache(), "repository").getAbsolutePath());
        ivy.getSettings().setDefaultResolutionCacheBasedir(
            new File(ivy.getSettings().getDefaultCache(), "workspace").getAbsolutePath());
        ivy.getSettings().validate();
        DefaultRepositoryCacheManager cacheMgr = (DefaultRepositoryCacheManager) ivy.getSettings()
                .getDefaultRepositoryCacheManager();

        cacheMgr.setIvyPattern("[module]/ivy.xml");
        cacheMgr.setArtifactPattern("[artifact].[ext]");

        // mod1.1 depends on mod1.2
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org1/mod1.1/ivys/ivy-1.0.xml"),
            getResolveOptions(ivy.getSettings(), new String[] {"*"}));
        assertNotNull(report);
        assertFalse(report.hasError());

        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org1", "mod1.1", "1.0");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(ivy, mrid).toString().contains("workspace"));
        assertTrue(getResolvedIvyFileInCache(ivy, mrid).exists());
        assertTrue(getConfigurationResolveReportInCache(ivy, report.getResolveId(), "default")
                .exists());

        // dependencies
        assertTrue(getIvyFileInCache(ivy, ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(new File(cache, "repository/mod1.2/ivy.xml").exists());
        assertTrue(getArchiveFileInCache(ivy, "org1", "mod1.2", "2.0", "mod1.2", "jar", "jar")
                .exists());
        assertTrue(new File(cache, "repository/mod1.2.jar").exists());
    }

    @Test
    public void testMultipleCache() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/ivysettings-multicache.xml"));

        // mod2.1 depends on mod1.1 which depends on mod1.2
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.1/ivys/ivy-0.3.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        assertFalse(report.hasError());

        // dependencies
        DefaultArtifact depArtifact = TestHelper.newArtifact("org1", "mod1.1", "1.0", "mod1.1",
            "jar", "jar");
        ModuleRevisionId depMrid = ModuleRevisionId.newInstance("org1", "mod1.1", "1.0");
        DefaultRepositoryCacheManager cacheMgr1 = (DefaultRepositoryCacheManager) ivy.getSettings()
                .getDefaultRepositoryCacheManager();
        DefaultRepositoryCacheManager cacheMgr2 = (DefaultRepositoryCacheManager) ivy.getSettings()
                .getRepositoryCacheManager("cache2");

        // ivy file should be cached in default cache, and artifact in cache2
        assertTrue(cacheMgr1.getIvyFileInCache(depMrid).exists());
        assertFalse(cacheMgr1.getArchiveFileInCache(depArtifact).exists());
        assertEquals(new File(cache, "repo1/mod1.1/ivy-1.0.xml").getCanonicalFile(), cacheMgr1
                .getIvyFileInCache(depMrid).getCanonicalFile());

        assertFalse(cacheMgr2.getIvyFileInCache(depMrid).exists());
        assertTrue(cacheMgr2.getArchiveFileInCache(depArtifact).exists());
        assertEquals(new File(cache, "repo2/mod1.1-1.0/mod1.1.jar").getCanonicalFile(), cacheMgr2
                .getArchiveFileInCache(depArtifact).getCanonicalFile());
    }

    @Test
    public void testForceLocal() throws Exception {
        // mod2.1 depends on mod1.1 which depends on mod1.2
        // a local build for mod1.2 is available
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/ivysettings-local.xml"));
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.1/ivys/ivy-0.3.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.1", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.1", "1.0", "mod1.1", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(
            ModuleRevisionId.newInstance("org1", "mod1.2", "local-20080708091023")).exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "local-20080708091023", "mod1.2", "jar",
            "jar").exists());

        assertTrue(getArchiveFileInCache("org1", "mod1.3", "3.0", "mod1.3-A", "jar", "jar")
                .exists());

        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testForceLocal2() throws Exception {
        // mod2.3 -> mod2.1;[0.0,0.4] -> mod1.1 -> mod1.2
        // a local build for mod2.1 and mod1.2 is available
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/ivysettings-local.xml"));
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.3/ivys/ivy-0.8.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        // dependencies
        assertTrue(getIvyFileInCache(
            ModuleRevisionId.newInstance("org2", "mod2.1", "0.3-local-20050213110000")).exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.1", "0.3-local-20050213110000", "mod2.1",
            "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.1", "1.1"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.1", "1.1", "mod1.1", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(
            ModuleRevisionId.newInstance("org1", "mod1.2", "local-20080708091023")).exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "local-20080708091023", "mod1.2", "jar",
            "jar").exists());

        assertTrue(getArchiveFileInCache("org1", "mod1.3", "3.0", "mod1.3-A", "jar", "jar")
                .exists());

        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org2", "mod2.1", "0.4"))
                .exists());
        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testForceLocal3() throws Exception {
        // mod2.1 depends on mod1.1 which depends on mod1.2
        // a local build for mod1.2 is available
        // we do a first resolve without local build so that cache contains mod1.2;2.0 module
        ivy.resolve(new File("test/repositories/1/org2/mod2.1/ivys/ivy-0.3.xml"),
            getResolveOptions(new String[] {"*"}));

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/ivysettings-local.xml"));
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.1/ivys/ivy-0.3.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.1", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.1", "1.0", "mod1.1", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(
            ModuleRevisionId.newInstance("org1", "mod1.2", "local-20080708091023")).exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "local-20080708091023", "mod1.2", "jar",
            "jar").exists());

        assertTrue(getArchiveFileInCache("org1", "mod1.3", "3.0", "mod1.3-A", "jar", "jar")
                .exists());
    }

    @Test
    public void testResolveExtends() throws Exception {
        // mod6.1 depends on mod1.2 2.0 in conf default, and conf extension extends default
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org6/mod6.1/ivys/ivy-0.3.xml"),
            getResolveOptions(new String[] {"extension"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org6", "mod6.1", "0.3");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies from default
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testResolveExtended() throws Exception {
        // mod6.1 depends on mod1.2 2.0 in conf default, and conf extension extends default
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org6/mod6.1/ivys/ivy-0.3.xml"),
            getResolveOptions(new String[] {"default"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org6", "mod6.1", "0.3");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies from default
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testResolveExtendedAndExtends() throws Exception {
        // mod6.1 depends on mod1.2 2.0 in conf default, and conf extension extends default
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org6/mod6.1/ivys/ivy-0.3.xml"),
            getResolveOptions(new String[] {"default", "extension"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org6", "mod6.1", "0.3");
        assertEquals(mrid, md.getModuleRevisionId());
        ConfigurationResolveReport crr = report.getConfigurationReport("default");
        assertNotNull(crr);
        assertEquals(1, crr.getArtifactsNumber());
        crr = report.getConfigurationReport("extension");
        assertNotNull(crr);
        assertEquals(1, crr.getArtifactsNumber());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testResolveMultipleExtends() throws Exception {
        // mod6.2 has two confs default and extension
        // mod6.2 depends on mod6.1 in conf (default->extension)
        // conf extension extends default
        // mod6.1 has two confs default and extension
        // mod6.1 depends on mod1.2 2.0 in conf (default->default)
        // conf extension extends default
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org6/mod6.2/ivys/ivy-0.3.xml"),
            getResolveOptions(new String[] {"default", "extension"}));
        assertNotNull(report);
        assertFalse(report.hasError());
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org6", "mod6.2", "0.3");
        assertEquals(mrid, md.getModuleRevisionId());
        ConfigurationResolveReport crr = report.getConfigurationReport("default");
        assertNotNull(crr);
        assertEquals(2, crr.getArtifactsNumber());
        crr = report.getConfigurationReport("extension");
        assertNotNull(crr);
        assertEquals(2, crr.getArtifactsNumber());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org6", "mod6.1", "0.4"))
                .exists());
        assertTrue(getArchiveFileInCache("org6", "mod6.1", "0.4", "mod6.1", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-240.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-240">IVY-240</a>
     */
    @Test
    public void testResolveMultipleExtendsAndConfs() throws Exception {
        // mod6.3 1.1 has four confs libraries, run (extends libraries), compile (extends run) and
        // test (extends libraries)
        // mod6.3 depends on mod6.2 2.0 in conf (run->default)
        // mod6.3 depends on mod6.1 2.+ in conf (test->default)
        // mod6.2 2.0 depends on mod6.1 2.0 in conf (default->standalone)
        // mod6.1 2.0 has two confs default and standalone
        // mod6.1 2.0 depends on mod1.2 2.2 in conf (default->default)
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod6.3/ivy-1.1.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        assertFalse(report.hasError());
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ConfigurationResolveReport crr = report.getConfigurationReport("libraries");
        assertEquals(0, crr.getArtifactsNumber());

        crr = report.getConfigurationReport("run");
        assertEquals(2, crr.getArtifactsNumber());
        assertContainsArtifact("org6", "mod6.2", "2.0", "mod6.2", "jar", "jar", crr);
        assertContainsArtifact("org6", "mod6.1", "2.0", "mod6.1", "jar", "jar", crr);

        crr = report.getConfigurationReport("compile");
        assertEquals(2, crr.getArtifactsNumber());
        assertContainsArtifact("org6", "mod6.2", "2.0", "mod6.2", "jar", "jar", crr);
        assertContainsArtifact("org6", "mod6.1", "2.0", "mod6.1", "jar", "jar", crr);

        crr = report.getConfigurationReport("test");
        assertEquals(2, crr.getArtifactsNumber());
        assertContainsArtifact("org6", "mod6.1", "2.0", "mod6.1", "jar", "jar", crr);
        assertContainsArtifact("org1", "mod1.2", "2.2", "mod1.2", "jar", "jar", crr);
    }

    /**
     * Test case for IVY-188.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-188">IVY-188</a>
     */
    @Test
    public void testResolveMultipleConfsWithLatest() throws Exception {
        // mod6.2 has two confs compile and run
        // depends on mod6.1 in conf (compile->default)
        // depends on mod1.2 latest (which is 2.2) in conf (run->default)
        // mod6.1
        // depends on mod1.2 2.2
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org6/mod6.2/ivys/ivy-0.6.xml"),
            getResolveOptions(new String[] {"compile", "run"}));
        assertNotNull(report);
        assertFalse(report.hasError());

        ConfigurationResolveReport crr = report.getConfigurationReport("compile");
        assertNotNull(crr);
        assertEquals(2, crr.getArtifactsNumber());
        crr = report.getConfigurationReport("run");
        assertNotNull(crr);
        assertEquals(1, crr.getArtifactsNumber());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.2"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.2", "mod1.2", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-173.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-173">IVY-173</a>
     */
    @Test
    public void testResolveMultipleConfsWithConflicts() throws Exception {
        // mod6.2 has two confs compile and run
        // depends on mod1.2 2.1 in conf (compile->default)
        // depends on mod1.1 1.0 in conf (*->default)
        // depends on mod6.1 in conf (*->default)
        // mod6.1
        // depends on mod1.2 2.1
        // mod1.1
        // depends on mod1.2 2.0
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org6/mod6.2/ivys/ivy-0.5.xml"),
            getResolveOptions(new String[] {"compile", "run"}));
        assertNotNull(report);
        assertFalse(report.hasError());
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org6", "mod6.2", "0.5");
        assertEquals(mrid, md.getModuleRevisionId());
        ConfigurationResolveReport crr = report.getConfigurationReport("compile");
        assertNotNull(crr);
        assertEquals(3, crr.getArtifactsNumber());
        crr = report.getConfigurationReport("run");
        assertNotNull(crr);
        assertEquals(3, crr.getArtifactsNumber());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org6", "mod6.1", "0.5"))
                .exists());
        assertTrue(getArchiveFileInCache("org6", "mod6.1", "0.5", "mod6.1", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.1", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.1", "1.0", "mod1.1", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.1"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.1", "mod1.2", "jar", "jar").exists());

        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testResolveMultipleExtends2() throws Exception {
        // same as before, except that mod6.2 depends on mod1.2 2.1 extension->default
        // so mod1.2 2.0 should be evicted in conf extension
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org6/mod6.2/ivys/ivy-0.4.xml"),
            getResolveOptions(new String[] {"default", "extension"}));
        assertNotNull(report);
        assertFalse(report.hasError());
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org6", "mod6.2", "0.4");
        assertEquals(mrid, md.getModuleRevisionId());
        ConfigurationResolveReport crr = report.getConfigurationReport("default");
        assertNotNull(crr);
        assertEquals(2, crr.getArtifactsNumber());
        IvyNode node = crr.getDependency(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"));
        assertNotNull(node);
        assertFalse(node.isEvicted("default"));
        crr = report.getConfigurationReport("extension");
        assertNotNull(crr);
        assertEquals(2, crr.getArtifactsNumber());
        node = crr.getDependency(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"));
        assertNotNull(node);
        assertTrue(node.isEvicted("extension"));
        node = crr.getDependency(ModuleRevisionId.newInstance("org1", "mod1.2", "2.1"));
        assertNotNull(node);
        assertFalse(node.isEvicted("extension"));

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org6", "mod6.1", "0.4"))
                .exists());
        assertTrue(getArchiveFileInCache("org6", "mod6.1", "0.4", "mod6.1", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.1"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.1", "mod1.2", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-261.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-261">IVY-261</a>
     */
    @Test
    public void testResolveSeveralDefaultWithArtifacts() throws Exception {
        // mod1.6 depends on
        // mod1.4, which depends on mod1.3 and selects one of its artifacts
        // mod1.3 and selects two of its artifacts
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org1/mod1.6/ivys/ivy-1.0.3.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        // dependencies
        assertTrue(getArchiveFileInCache("org1", "mod1.3", "3.0", "mod1.3-A", "jar", "jar")
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.3", "3.0", "mod1.3-B", "jar", "jar")
                .exists());
    }

    /**
     * Test case for IVY-537.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-537">IVY-537</a>
     */
    @Test
    public void testResolveConflictsWithArtifacts() throws Exception {
        // #mod2.6;0.12 -> {#mod1.6;1.0.4 #mod2.5;0.6.2 }
        // #mod1.6;1.0.4 -> #mod1.3;3.0 artifacts A and B
        // #mod2.5;0.6.2 -> #mod1.3;3.1 artifact C
        // #mod1.3;3.1 has only A and C artifacts, not B.
        // Both A and C should be downloaded, and a message should tell that B was not available.
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.6/ivys/ivy-0.12.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        // dependencies
        assertTrue(getArchiveFileInCache("org1", "mod1.3", "3.1", "mod1.3-A", "jar", "jar")
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.3", "3.1", "mod1.3-C", "jar", "jar")
                .exists());
    }

    /**
     * Test case for IVY-283.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-283">IVY-283</a>
     */
    @Test
    public void testResolveSeveralDefaultWithArtifactsAndConfs() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/IVY-283/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File("test/repositories/IVY-283/ivy.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        // dependencies
        ConfigurationResolveReport crr = report.getConfigurationReport("build");
        assertNotNull(crr);
        assertEquals(3,
            crr.getDownloadReports(ModuleRevisionId.newInstance("medicel", "C", "1.0")).length);

        assertTrue(getArchiveFileInCache(ivy, "medicel", "C", "1.0", "lib_c_a", "jar", "jar")
                .exists());
        assertTrue(getArchiveFileInCache(ivy, "medicel", "C", "1.0", "lib_c_b", "jar", "jar")
                .exists());
        assertTrue(getArchiveFileInCache(ivy, "medicel", "C", "1.0", "lib_c_d", "jar", "jar")
                .exists());
    }

    /**
     * Second test case for IVY-283.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-283">IVY-283</a>
     */
    @Test
    public void testResolveSeveralDefaultWithArtifactsAndConfs2() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/IVY-283/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File("test/repositories/IVY-283/ivy-d.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        // dependencies
        ConfigurationResolveReport crr = report.getConfigurationReport("build");
        assertNotNull(crr);
        assertEquals(
            9,
            crr.getDownloadReports(ModuleRevisionId.newInstance("medicel", "module_a", "local")).length);

        assertTrue(getArchiveFileInCache(ivy, "medicel", "module_a", "local", "lib_a_a", "jar",
            "jar").exists());
        assertTrue(getArchiveFileInCache(ivy, "medicel", "module_a", "local", "lib_a_b", "jar",
            "jar").exists());
        assertTrue(getArchiveFileInCache(ivy, "medicel", "module_a", "local", "lib_a_c", "jar",
            "jar").exists());
        assertTrue(getArchiveFileInCache(ivy, "medicel", "module_a", "local", "lib_a_d", "jar",
            "jar").exists());
        assertTrue(getArchiveFileInCache(ivy, "medicel", "module_a", "local", "lib_a_e", "jar",
            "jar").exists());
        assertTrue(getArchiveFileInCache(ivy, "medicel", "module_a", "local", "lib_a_f", "jar",
            "jar").exists());
        assertTrue(getArchiveFileInCache(ivy, "medicel", "module_a", "local", "lib_a_g", "jar",
            "jar").exists());
        assertTrue(getArchiveFileInCache(ivy, "medicel", "module_a", "local", "lib_a_h", "jar",
            "jar").exists());
        assertTrue(getArchiveFileInCache(ivy, "medicel", "module_a", "local", "lib_a_i", "jar",
            "jar").exists());
    }

    @Test
    public void testResolveWithStartPublicConf() throws Exception {
        // mod2.2 depends on mod1.3 and selects its artifacts
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.2/ivys/ivy-0.8.xml"),
            getResolveOptions(new String[] {"*(public)"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org2", "mod2.2", "0.8");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.3", "3.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.3", "3.0", "mod1.3-A", "jar", "jar")
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.3", "3.0", "mod1.3-B", "jar", "jar")
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.3", "3.0", "mod1.3", "jar", "jar").exists());
    }

    @Test
    public void testResolveWithPrivateConf() throws Exception {
        // mod2.2 depends on mod1.3 and selects its artifacts
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.2/ivys/ivy-0.8.xml"),
            getResolveOptions(new String[] {"*(private)"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org2", "mod2.2", "0.8");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.3", "3.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.3", "3.0", "mod1.3-A", "jar", "jar")
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.3", "3.0", "mod1.3-B", "jar", "jar")
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.3", "3.0", "mod1.3", "jar", "jar").exists());
    }

    @Test
    public void testResolveDefaultWithArtifactsConf1() throws Exception {
        // mod2.2 depends on mod1.3 and selects its artifacts
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.2/ivys/ivy-0.5.xml"),
            getResolveOptions(new String[] {"myconf1"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org2", "mod2.2", "0.5");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.3", "3.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.3", "3.0", "mod1.3-A", "jar", "jar")
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.3", "3.0", "mod1.3-B", "jar", "jar")
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.3", "3.0", "mod1.3", "jar", "jar").exists());
    }

    @Test
    public void testResolveDefaultWithArtifactsConf2() throws Exception {
        // mod2.2 depends on mod1.3 and selects its artifacts
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.2/ivys/ivy-0.5.xml"),
            getResolveOptions(new String[] {"myconf2"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org2", "mod2.2", "0.5");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.3", "3.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.3", "3.0", "mod1.3-A", "jar", "jar")
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.3", "3.0", "mod1.3-B", "jar", "jar")
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.3", "3.0", "mod1.3", "jar", "jar").exists());
    }

    @Test
    public void testResolveDefaultWithArtifactsAndConfMapping() throws Exception {
        // mod2.2 depends on mod1.3 and specify its artifacts and a conf mapping
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.2/ivys/ivy-0.5.1.xml"),
            getResolveOptions(new String[] {"myconf1"}));
        assertNotNull(report);
        assertFalse(report.hasError());
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org2", "mod2.2", "0.5.1");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.3", "3.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.3", "3.0", "mod1.3-A", "jar", "jar")
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.3", "3.0", "mod1.3-B", "jar", "jar")
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.3", "3.0", "mod1.3", "jar", "jar").exists());
    }

    @Test
    public void testResolveWithIncludeArtifactsConf1() throws Exception {
        // mod2.3 depends on mod2.1 and selects its artifacts in myconf1
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.3/ivys/ivy-0.4.xml"),
            getResolveOptions(new String[] {"myconf1"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org2", "mod2.3", "0.4");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org2", "mod2.1", "0.3"))
                .exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21A", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21B", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.3", "mod2.1", "jar", "jar").exists());
    }

    @Test
    public void testResolveWithIncludeArtifactsConf2() throws Exception {
        // mod2.3 depends on mod2.1 and selects its artifacts in myconf1
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.3/ivys/ivy-0.4.xml"),
            getResolveOptions(new String[] {"myconf2"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org2", "mod2.3", "0.4");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org2", "mod2.1", "0.3"))
                .exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21A", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21B", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.3", "mod2.1", "jar", "jar").exists());
    }

    @Test
    public void testResolveWithIncludeArtifactsWithoutConf() throws Exception {
        // mod2.3 depends on mod2.1 and selects its artifacts
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.3/ivys/ivy-0.5.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org2", "mod2.3", "0.5");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org2", "mod2.1", "0.3"))
                .exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21A", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21B", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.3", "mod2.1", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-541.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-541">IVY-541</a>
     */
    @Test
    public void testResolveWithIncludeArtifactsTransitive() throws Exception {
        // mod2.6 depends on mod2.3 and mod2.1
        // mod2.3 depends on mod2.1 and selects its artifacts
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.6/ivys/ivy-0.5.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org2", "mod2.1", "0.3"))
                .exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21A", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21B", "jar", "jar").exists());
    }

    @Test
    public void testResolveWithExcludesArtifacts() throws Exception {
        // mod2.3 depends on mod2.1 and selects its artifacts
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.3/ivys/ivy-0.6.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org2", "mod2.3", "0.6");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org2", "mod2.1", "0.3"))
                .exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21A", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21B", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.3", "mod2.1", "jar", "jar").exists());
    }

    @Test
    public void testResolveWithExcludesArtifacts2() throws Exception {
        // mod2.3 depends on mod2.1 and badly excludes artifacts with incorrect matcher
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.3/ivys/ivy-0.6.2.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org2", "mod2.3", "0.6.2");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org2", "mod2.1", "0.3"))
                .exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21A", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21B", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.3", "mod2.1", "jar", "jar").exists());
    }

    @Test
    public void testResolveWithExcludesArtifacts3() throws Exception {
        // mod2.3 depends on mod2.1 and excludes artifacts with exact matcher
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.3/ivys/ivy-0.6.3.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org2", "mod2.3", "0.6.3");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org2", "mod2.1", "0.3"))
                .exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21A", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21B", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.3", "mod2.1", "jar", "jar").exists());
    }

    @Test
    public void testResolveWithExcludesArtifacts4() throws Exception {
        // mod2.3 depends on mod2.1 and excludes artifacts with regexp matcher
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.3/ivys/ivy-0.6.4.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org2", "mod2.3", "0.6.4");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org2", "mod2.1", "0.3"))
                .exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21A", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21B", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.3", "mod2.1", "jar", "jar").exists());
    }

    @Test
    public void testResolveWithExcludesArtifacts5() throws Exception {
        // mod2.3 depends on mod2.1 and excludes artifacts with glob matcher
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.3/ivys/ivy-0.6.5.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org2", "mod2.3", "0.6.5");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org2", "mod2.1", "0.3"))
                .exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21A", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21B", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.3", "mod2.1", "jar", "jar").exists());
    }

    @Test
    public void testResolveTransitiveDependencies() throws Exception {
        // mod2.1 depends on mod1.1 which depends on mod1.2
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.1/ivys/ivy-0.3.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org2", "mod2.1", "0.3");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.1", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.1", "1.0", "mod1.1", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testResolveTransitiveDependenciesWithOverride() throws Exception {
        // mod2.1 depends on mod1.1 which depends on mod1.2
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.1/ivys/ivy-0.6.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org2", "mod2.1", "0.6");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.1", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.1", "1.0", "mod1.1", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "1.0", "mod1.2", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-1131.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-1131">IVY-1131</a>
     */
    @Test
    public void testResolveTransitiveDependenciesWithOverrideAndDynamicResolveMode()
            throws Exception {
        // mod2.1 depends on mod1.1 which depends on mod1.2
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.1/ivys/ivy-0.6.xml"),
            getResolveOptions(new String[] {"*"})
                    .setResolveMode(ResolveOptions.RESOLVEMODE_DYNAMIC));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org2", "mod2.1", "0.6");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.1", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.1", "1.0", "mod1.1", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "1.0", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testResolveTransitiveDisabled() throws Exception {
        // mod2.1 depends on mod1.1 which depends on mod1.2
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.1/ivys/ivy-0.3.xml"),
            getResolveOptions(new String[] {"*"}).setTransitive(false));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org2", "mod2.1", "0.3");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.1", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.1", "1.0", "mod1.1", "jar", "jar").exists());

        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testDependenciesOrder() throws Exception {
        ResolveReport report = ivy.resolve(ResolveTest.class.getResource("ivy-225.xml"),
            getResolveOptions(new String[] {"default"}));

        List<ModuleRevisionId> revisions = new ArrayList<>(report
                .getConfigurationReport("default").getModuleRevisionIds());
        assertTrue("number of revisions is not correct", revisions.size() >= 3);

        int mod12Index = revisions.indexOf(ModuleRevisionId.newInstance("org1", "mod1.2", "1.1"));
        int mod32Index = revisions.indexOf(ModuleRevisionId.newInstance("org3", "mod3.2", "1.4"));
        int mod51Index = revisions.indexOf(ModuleRevisionId.newInstance("org5", "mod5.1", "4.2"));

        // verify the order of the modules in the ivy file
        assertTrue("[ org1 | mod1.2 | 1.1 ] was not found", mod12Index > -1);
        assertTrue("[ org1 | mod1.2 | 1.1 ] must come before [ org3 | mod3.2 | 1.4 ]",
            mod12Index < mod32Index);
        assertTrue("[ org3 | mod3.2 | 1.4 ] must come before [ org5 | mod5.1 | 4.2 ]",
            mod32Index < mod51Index);
    }

    @Test
    public void testDisableTransitivityPerConfiguration() throws Exception {
        // mod2.1 (compile, runtime) depends on mod1.1 which depends on mod1.2
        // compile conf is not transitive

        // first we resolve compile conf only
        ivy.resolve(new File("test/repositories/1/org2/mod2.1/ivys/ivy-0.3.1.xml"),
            getResolveOptions(new String[] {"compile"}));

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.1", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.1", "1.0", "mod1.1", "jar", "jar").exists());

        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        // then we resolve runtime conf
        ivy.resolve(new File("test/repositories/1/org2/mod2.1/ivys/ivy-0.3.1.xml"),
            getResolveOptions(new String[] {"runtime"}));

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        // same as before, but resolve both confs in one call
        ResolveReport r = ivy.resolve(
            new File("test/repositories/1/org2/mod2.1/ivys/ivy-0.3.1.xml"),
            getResolveOptions(new String[] {"runtime", "compile"}));
        assertFalse(r.hasError());
        assertEquals(1, r.getConfigurationReport("compile").getArtifactsNumber());
        assertEquals(2, r.getConfigurationReport("runtime").getArtifactsNumber());
    }

    @Test
    public void testDisableTransitivityPerConfiguration2() throws Exception {
        // mod2.1 (compile, runtime) depends on mod1.1 which depends on mod1.2
        // compile conf is not transitive
        // compile extends runtime

        // first we resolve compile conf only
        ivy.resolve(new File("test/repositories/1/org2/mod2.1/ivys/ivy-0.3.2.xml"),
            getResolveOptions(new String[] {"compile"}));

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.1", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.1", "1.0", "mod1.1", "jar", "jar").exists());

        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        // then we resolve runtime conf
        ivy.resolve(new File("test/repositories/1/org2/mod2.1/ivys/ivy-0.3.2.xml"),
            getResolveOptions(new String[] {"runtime"}));

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        // same as before, but resolve both confs in one call
        ResolveReport r = ivy.resolve(
            new File("test/repositories/1/org2/mod2.1/ivys/ivy-0.3.2.xml"),
            getResolveOptions(new String[] {"runtime", "compile"}));
        assertFalse(r.hasError());
        assertEquals(1, r.getConfigurationReport("compile").getArtifactsNumber());
        assertEquals(2, r.getConfigurationReport("runtime").getArtifactsNumber());
    }

    @Test
    public void testDisableTransitivityPerConfiguration3() throws Exception {
        // mod2.1 (compile, runtime) depends on mod1.1 which depends on mod1.2
        // compile conf is not transitive
        // runtime extends compile

        // first we resolve compile conf only
        ivy.resolve(new File("test/repositories/1/org2/mod2.1/ivys/ivy-0.3.3.xml"),
            getResolveOptions(new String[] {"compile"}));

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.1", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.1", "1.0", "mod1.1", "jar", "jar").exists());

        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        // then we resolve runtime conf
        ivy.resolve(new File("test/repositories/1/org2/mod2.1/ivys/ivy-0.3.3.xml"),
            getResolveOptions(new String[] {"runtime"}));

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        // same as before, but resolve both confs in one call
        ResolveReport r = ivy.resolve(
            new File("test/repositories/1/org2/mod2.1/ivys/ivy-0.3.3.xml"),
            getResolveOptions(new String[] {"runtime", "compile"}));
        assertFalse(r.hasError());
        assertEquals(1, r.getConfigurationReport("compile").getArtifactsNumber());
        assertEquals(2, r.getConfigurationReport("runtime").getArtifactsNumber());
    }

    @Test
    public void testDisableTransitivityPerConfiguration4() throws Exception {
        // mod2.2 (A,B,compile) depends on mod 2.1 (A->runtime;B->compile)
        // compile is not transitive and extends A and B
        //
        // mod2.1 (compile, runtime) depends on mod1.1 which depends on mod1.2
        // compile conf is not transitive and extends runtime

        ResolveReport r = ivy.resolve(new File("test/repositories/1/org2/mod2.2/ivys/ivy-0.6.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(r.hasError());

        // here we should get all three recursive dependencies
        assertEquals(
                new HashSet<>(Arrays.asList(
                        ModuleRevisionId.newInstance("org2", "mod2.1", "0.3.2"),
                        ModuleRevisionId.newInstance("org1", "mod1.1", "1.0"),
                        ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))),
            r.getConfigurationReport("A").getModuleRevisionIds());

        // here we should get only mod2.1 and mod1.1 cause compile is not transitive in mod2.1
        assertEquals(
                new HashSet<>(Arrays.asList(
                        ModuleRevisionId.newInstance("org2", "mod2.1", "0.3.2"),
                        ModuleRevisionId.newInstance("org1", "mod1.1", "1.0"))),
            r.getConfigurationReport("B").getModuleRevisionIds());

        // here we should get only mod2.1 cause compile is not transitive
        assertEquals(Collections.singleton(ModuleRevisionId.newInstance("org2", "mod2.1", "0.3.2")),
                r.getConfigurationReport("compile").getModuleRevisionIds());
    }

    @Test
    public void testDisableTransitivityPerConfiguration5() throws Exception {
        // mod2.2 (A,B,compile) depends on
        // mod 2.1 (A->runtime;B->compile)
        // mod1.1 (A->*) ]0.9.9,1.0] (which resolves to 1.0)
        // compile is not transitive and extends A and B
        //
        // mod2.1 (compile, runtime) depends on mod1.1 1.0 which depends on mod1.2 2.0
        // compile conf is not transitive and extends runtime

        ResolveReport r = ivy.resolve(new File("test/repositories/1/org2/mod2.2/ivys/ivy-0.7.xml"),
            getResolveOptions(new String[] {"A", "B", "compile"}));
        assertFalse(r.hasError());

        // here we should get all three recursive dependencies
        assertEquals(
                new HashSet<>(Arrays.asList(
                        ModuleRevisionId.newInstance("org2", "mod2.1", "0.3.2"),
                        ModuleRevisionId.newInstance("org1", "mod1.1", "1.0"),
                        ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))),
            r.getConfigurationReport("A").getModuleRevisionIds());

        // here we should get only mod2.1 and mod1.1 cause compile is not transitive in mod2.1
        assertEquals(
                new HashSet<>(Arrays.asList(
                        ModuleRevisionId.newInstance("org2", "mod2.1", "0.3.2"),
                        ModuleRevisionId.newInstance("org1", "mod1.1", "1.0"))),
            r.getConfigurationReport("B").getModuleRevisionIds());

        // here we should get only mod2.1 cause compile is not transitive
        assertEquals(
                new HashSet<>(Arrays.asList(
                        ModuleRevisionId.newInstance("org2", "mod2.1", "0.3.2"),
                        ModuleRevisionId.newInstance("org1", "mod1.1", "1.0"))),
            r.getConfigurationReport("compile").getModuleRevisionIds());
    }

    @Test
    public void testResolveDiamond() throws Exception {
        // mod4.1 depends on
        // - mod1.1 which depends on mod1.2
        // - mod3.1 which depends on mod1.2
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod4.1/ivy-4.0.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org4", "mod4.1", "4.0");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.1", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.1", "1.0", "mod1.1", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org3", "mod3.1", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org3", "mod3.1", "1.0", "mod3.1", "jar", "jar").exists());
    }

    @Test
    public void testResolveConflict() throws Exception {
        // mod4.1 v 4.1 depends on
        // - mod1.1 v 1.0 which depends on mod1.2 v 2.0
        // - mod3.1 v 1.1 which depends on mod1.2 v 2.1
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod4.1/ivy-4.1.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org4", "mod4.1", "4.1");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        ConfigurationResolveReport crr = report.getConfigurationReport("default");
        assertNotNull(crr);
        assertEquals(0,
            crr.getDownloadReports(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0")).length);
        assertEquals(1,
            crr.getDownloadReports(ModuleRevisionId.newInstance("org1", "mod1.2", "2.1")).length);

        File r = getConfigurationResolveReportInCache(ResolveOptions.getDefaultResolveId(md),
            "default");
        assertTrue(r.exists());
        final boolean[] found = new boolean[] {false};
        SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
        saxParser.parse(r, new DefaultHandler() {
            @Override
            public void startElement(String uri, String localName, String qName,
                                     Attributes attributes) {
                if ("revision".equals(qName) && "2.0".equals(attributes.getValue("name"))) {
                    found[0] = true;
                }
            }
        });
        assertTrue(found[0]); // the report should contain the evicted revision

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.1", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.1", "1.0", "mod1.1", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org3", "mod3.1", "1.1"))
                .exists());
        assertTrue(getArchiveFileInCache("org3", "mod3.1", "1.1", "mod3.1", "jar", "jar").exists());

        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.1"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.1", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testResolveConflict2() throws Exception {
        // mod4.1 v 4.14 depends on
        // - mod1.1 v 1.0 which depends on mod1.2 v 2.0
        // - mod3.1 v 1.1 which depends on mod1.2 v 2.1
        // - mod6.1 v 0.3 which depends on mod1.2 v 2.0
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod4.1/ivy-4.14.xml"),
            getResolveOptions(new String[] {"*"}));

        // dependencies
        ConfigurationResolveReport crr = report.getConfigurationReport("default");
        assertNotNull(crr);
        assertEquals(0,
            crr.getDownloadReports(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0")).length);
        assertEquals(1,
            crr.getDownloadReports(ModuleRevisionId.newInstance("org1", "mod1.2", "2.1")).length);

        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org4", "mod4.1", "4.14");
        File r = getConfigurationResolveReportInCache(
            ResolveOptions.getDefaultResolveId(mrid.getModuleId()), "default");
        assertTrue(r.exists());
        final boolean[] found = new boolean[] {false};
        SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
        saxParser.parse(r, new DefaultHandler() {
            @Override
            public void startElement(String uri, String localName, String qName,
                    Attributes attributes) {
                if ("revision".equals(qName) && "2.0".equals(attributes.getValue("name"))) {
                    found[0] = true;
                }
            }
        });
        assertTrue(found[0]); // the report should contain the evicted revision

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.1", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.1", "1.0", "mod1.1", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org3", "mod3.1", "1.1"))
                .exists());
        assertTrue(getArchiveFileInCache("org3", "mod3.1", "1.1", "mod3.1", "jar", "jar").exists());

        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.1"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.1", "mod1.2", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-264.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-264">IVY-264</a>
     */
    @Test
    public void testResolveConflict3() throws Exception {
        // a depends on x latest, y latest, z latest
        // x and z depends on commons-lang 1.0.1
        // y depends on commons-lang 2.0
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/IVY-264/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File("test/repositories/IVY-264/ivy.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        // dependencies
        ConfigurationResolveReport crr = report.getConfigurationReport("default");
        assertNotNull(crr);
        assertEquals(
            0,
            crr.getDownloadReports(ModuleRevisionId.newInstance("myorg", "commons-lang", "1.0.1")).length);
        assertEquals(
            1,
            crr.getDownloadReports(ModuleRevisionId.newInstance("myorg", "commons-lang", "2.0")).length);

        assertFalse(getArchiveFileInCache(ivy, "myorg", "commons-lang", "1.0.1", "commons-lang",
            "jar", "jar").exists());

        assertTrue(getArchiveFileInCache(ivy, "myorg", "commons-lang", "2.0", "commons-lang",
            "jar", "jar").exists());
    }

    @Test
    public void testResolveMergeTransitiveAfterConflict() throws Exception {
        // mod20.4 -> mod20.3;1.0 mod20.2;1.0
        // mod20.3;1.0 -> mod20.1;1.0
        // mod20.2;1.0 -> mod20.1;1.1 (transitive false)
        // mod20.1;1.0 -> mod1.2;1.0
        // mod20.1;1.1 -> mod1.2;1.0
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org20/mod20.4/ivys/ivy-1.0.xml"),
            getResolveOptions(new String[] {"*"}));

        // dependencies
        ConfigurationResolveReport crr = report.getConfigurationReport("default");
        assertNotNull(crr);
        assertEquals(1,
            crr.getDownloadReports(ModuleRevisionId.newInstance("org1", "mod1.2", "1.0")).length);

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "1.0", "mod1.2", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-618.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-618">IVY-618</a>
     */
    @Test
    public void testResolveConflictFromPoms() throws Exception {
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod17.1/ivy-1.0.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        assertFalse(report.hasError());
    }

    @Test
    public void testTransitiveEviction() throws Exception {
        // mod7.3 depends on mod7.2 v1.0 and on mod7.1 v2.0
        // mod7.2 v1.0 depends on mod7.1 v1.0 (which then should be evicted)
        // mod7.1 v1.0 depends on mod 1.2 v2.0 (which should be evicted by transitivity)

        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod7.3/ivy-1.0.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org7", "mod7.3", "1.0");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org7", "mod7.2", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org7", "mod7.2", "1.0", "mod7.2", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org7", "mod7.1", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org7", "mod7.1", "2.0", "mod7.1", "jar", "jar").exists());

        assertFalse(getArchiveFileInCache("org7", "mod7.1", "1.0", "mod7.1", "jar", "jar").exists());

        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-199.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-199">IVY-199</a>
     */
    @Test
    public void testTransitiveEviction2() throws Exception {
        // mod4.1 v 4.13 depends on
        // - mod3.2 v 1.2.1 which depends on
        // - mod3.1 v 1.0 which depends on mod1.2 v 2.0
        // - mod1.2 v 2.1
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod4.1/ivy-4.13.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.1"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.1", "mod1.2", "jar", "jar").exists());

        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-590.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-590">IVY-590</a>
     */
    @Test
    public void testTransitiveEvictionWithExtendingConf() throws Exception {
        ResolveReport report = ivy.resolve(ResolveTest.class.getResource("ivy-590.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        // test eviction
        ConfigurationResolveReport compileReport = report.getConfigurationReport("compile");
        IvyNode[] evicted = compileReport.getEvictedNodes();
        assertNotNull(evicted);

        Collection<ModuleRevisionId> evictedModules = new ArrayList<>();
        for (IvyNode anEvicted : evicted) {
            evictedModules.add(anEvicted.getId());
        }

        assertTrue(evictedModules.contains(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0")));
    }

    @Test
    public void testResolveConflictInConf() throws Exception {
        // conflicts in separate confs are not conflicts

        // mod2.1 conf A depends on mod1.1 which depends on mod1.2 2.0
        // mod2.1 conf B depends on mod1.2 2.1
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.1/ivys/ivy-0.4.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org2", "mod2.1", "0.4");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.1", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.1", "1.0", "mod1.1", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.1"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.1", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testEvictWithConf() throws Exception {
        // bug 105 - test #1

        // mod6.1 r1.0 depends on
        // mod5.1 r4.2 conf A
        // mod5.2 r1.0 which depends on mod5.1 r4.0 conf B
        //
        // mod5.1 r4.2 conf B depends on mod1.2 r2.0
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod6.1/ivy-1.0.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org6", "mod6.1", "1.0");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org5", "mod5.1", "4.2"))
                .exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.2", "art51A", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.2", "art51B", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org5", "mod5.2", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.2", "1.0", "mod5.2", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        // should have been evicted before download
        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org5", "mod5.1", "4.0"))
                .exists());
        assertFalse(getArchiveFileInCache("org5", "mod5.1", "4.0", "art51A", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org5", "mod5.1", "4.0", "art51B", "jar", "jar").exists());
    }

    @Test
    public void testEvictWithConf2() throws Exception {
        // same as preceding one but with inverse order, so that
        // eviction is done after download
        // bug 105 - test #2

        // mod6.1 r1.1 depends on
        // mod5.2 r1.0 which depends on mod5.1 r4.0 conf B
        // mod5.1 r4.2 conf A
        //
        // mod5.1 r4.2 conf B depends on mod1.2 r2.0
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod6.1/ivy-1.1.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org6", "mod6.1", "1.1");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org5", "mod5.1", "4.2"))
                .exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.2", "art51A", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.2", "art51B", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org5", "mod5.2", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.2", "1.0", "mod5.2", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        // even late eviction should avoid artifact downloading
        assertFalse(getArchiveFileInCache("org5", "mod5.1", "4.0", "art51A", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org5", "mod5.1", "4.0", "art51B", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-681.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-681">IVY-681</a>
     */
    @Test
    public void testEvictWithConf3() throws Exception {
        // same as first one but the conf requested in evicted module is no longer present in
        // selected revision

        // mod6.1 r1.4 depends on
        // mod5.1 r4.3 conf A
        // mod5.2 r1.0 which depends on mod5.1 r4.0 conf B
        //
        // mod5.1 r4.3 has only conf A, not B
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod6.1/ivy-1.4.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org5", "mod5.1", "4.3"))
                .exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.3", "art51A", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org5", "mod5.2", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.2", "1.0", "mod5.2", "jar", "jar").exists());

        assertFalse(getArchiveFileInCache("org5", "mod5.1", "4.0", "art51A", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org5", "mod5.1", "4.0", "art51B", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-861.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-861">IVY-861</a>
     */
    @Test
    public void testFailWithMissingConf() throws Exception {
        // mod6.1 r1.5 depends on
        // mod5.1 [1.0,4.3] conf unknown which doesn't exist in mod5.1;4.3
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod6.1/ivy-1.5.xml"),
            getResolveOptions(new String[] {"*"}));
        assertTrue("missing conf should have raised an error in report", report.hasError());
        assertTrue(joinArray(report.getAllProblemMessages().toArray(new String[0]), "\n").contains("'unknown'"));
    }

    @Test
    public void testEvictWithConfInMultiConf() throws Exception {
        // same as preceding ones but the conflict appears in several root confs
        // bug 105 - test #3

        // mod6.1 r1.2 conf A and conf B depends on
        // mod5.2 r1.0 which depends on mod5.1 r4.0 conf B
        // mod5.1 r4.2 conf A
        //
        // mod5.1 r4.2 conf B depends on mod1.2 r2.0
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod6.1/ivy-1.2.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org6", "mod6.1", "1.2");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org5", "mod5.1", "4.2"))
                .exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.2", "art51A", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.2", "art51B", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org5", "mod5.2", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.2", "1.0", "mod5.2", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        // all artifacts should be present in both confs
        ConfigurationResolveReport crr = report.getConfigurationReport("A");
        assertNotNull(crr);
        assertEquals(2,
            crr.getDownloadReports(ModuleRevisionId.newInstance("org5", "mod5.1", "4.2")).length);

        crr = report.getConfigurationReport("B");
        assertNotNull(crr);
        assertEquals(2,
            crr.getDownloadReports(ModuleRevisionId.newInstance("org5", "mod5.1", "4.2")).length);

        // even late eviction should avoid artifact downloading
        assertFalse(getArchiveFileInCache("org5", "mod5.1", "4.0", "art51A", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org5", "mod5.1", "4.0", "art51B", "jar", "jar").exists());
    }

    @Test
    public void testEvictWithConfInMultiConf2() throws Exception {
        // same as preceding one but the conflict appears in a root conf and not in another
        // which should keep the evicted
        // bug 105 - test #4

        // mod6.1 r1.3 conf A depends on
        // mod5.2 r1.0 which depends on mod5.1 r4.0 conf B
        //
        // mod6.1 r1.3 conf B depends on
        // mod5.2 r1.0 which depends on mod5.1 r4.0 conf B
        // mod5.1 r4.2 conf A
        //
        // mod5.1 r4.2 conf B depends on mod1.2 r2.0
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod6.1/ivy-1.3.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org6", "mod6.1", "1.3");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org5", "mod5.1", "4.2"))
                .exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.2", "art51A", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.2", "art51B", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org5", "mod5.1", "4.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.0", "art51A", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.0", "art51B", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org5", "mod5.2", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.2", "1.0", "mod5.2", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        // 4.2 artifacts should be present in conf B only
        ConfigurationResolveReport crr = report.getConfigurationReport("A");
        assertNotNull(crr);
        assertEquals(0,
            crr.getDownloadReports(ModuleRevisionId.newInstance("org5", "mod5.1", "4.2")).length);

        crr = report.getConfigurationReport("B");
        assertNotNull(crr);
        assertEquals(2,
            crr.getDownloadReports(ModuleRevisionId.newInstance("org5", "mod5.1", "4.2")).length);
    }

    /**
     * Test case for IVY-644.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-644">IVY-644</a>
     */
    @Test
    public void testMultipleEviction() throws Exception {

        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/IVY-644/M1/ivys/ivy-1.0.xml"), getResolveOptions(new String[] {
                "test", "runtime"})); // NB the order impact the bug
        assertFalse(report.hasError());
    }

    @Test
    public void testResolveForce() throws Exception {
        // mod4.1 v 4.2 depends on
        // - mod1.2 v 2.0 and forces it
        // - mod3.1 v 1.1 which depends on mod1.2 v 2.1
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod4.1/ivy-4.2.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org4", "mod4.1", "4.2");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org3", "mod3.1", "1.1"))
                .exists());
        assertTrue(getArchiveFileInCache("org3", "mod3.1", "1.1", "mod3.1", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.1"))
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.1", "mod1.2", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-193.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-193">IVY-193</a>
     */
    @Test
    public void testResolveForceAfterConflictSolved() throws Exception {
        // mod4.1 v 4.9 depends on
        // - mod3.2 v 1.1 which depends on mod1.2 v 2.0
        // - mod3.1 v 1.1 which depends on mod1.2 v 2.1
        // - mod1.2 v 2.0 and forces it
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod4.1/ivy-4.9.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org4", "mod4.1", "4.9");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.1", "mod1.2", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-193.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-193">IVY-193</a>
     */
    @Test
    public void testResolveForceAfterDependencyExist() throws Exception {
        // mod4.1 v 4.10 depends on
        // - mod3.1 v 1.0.1 which depends on mod1.2 v 2.0 and forces it
        // - mod3.2 v 1.2 which depends on mod1.2 v 2.1 and on mod3.1 v1.0.1
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod4.1/ivy-4.10.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);

        // dependencies
        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.1"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.1", "mod1.2", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-193.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-193">IVY-193</a>
     */
    @Test
    public void testResolveForceInDepOnly() throws Exception {
        // mod4.1 v 4.11 depends on
        // - mod1.2 v 2.0
        // - mod3.2 v 1.3 which depends on
        // - mod3.1 v1.1 which depends on
        // - mod1.2 v 2.1
        // - mod1.2 v 1.0 and forces it
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod4.1/ivy-4.11.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.1", "mod1.2", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.2", "1.0", "mod1.2", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-193.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-193">IVY-193</a>
     */
    @Test
    public void testResolveForceInDepOnly2() throws Exception {
        // mod4.1 v 4.12 depends on
        // - mod3.1 v1.0 which depends on
        // - mod1.2 v 2.0
        // - mod3.2 v 1.4 which depends on
        // - mod1.2 v 2.0 and forces it
        // - mod3.1 v1.1 which depends on
        // - mod1.2 v 2.1
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod4.1/ivy-4.12.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.1", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testResolveWithDynamicRevisionsAndArtifactLockStrategy() throws Exception {
        // mod4.1 v 4.5 depends on
        // - mod1.2 v 1+ and forces it
        // - mod3.1 v 1.2 which depends on mod1.2 v 2+
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/ivysettings-artifact-lock.xml"));
        ivy.resolve(new File("test/repositories/2/mod4.1/ivy-4.5.xml"),
            getResolveOptions(new String[] {"*"}));

        List<File> lockFiles = new ArrayList<>();
        findLockFiles(cache, lockFiles);
        assertTrue("There were lockfiles left in the cache: " + lockFiles, lockFiles.isEmpty());
    }

    private void findLockFiles(File dir, List<File> result) {
        File[] files = dir.listFiles();
        for (File file : files) {
            if (file.isDirectory()) {
                findLockFiles(file, result);
            } else if (file.getName().endsWith(".lck")) {
                result.add(file);
            }
        }
    }

    @Test
    public void testResolveForceWithDynamicRevisions() throws Exception {
        // mod4.1 v 4.5 depends on
        // - mod1.2 v 1+ and forces it
        // - mod3.1 v 1.2 which depends on mod1.2 v 2+
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod4.1/ivy-4.5.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org4", "mod4.1", "4.5");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org3", "mod3.1", "1.2"))
                .exists());
        assertTrue(getArchiveFileInCache("org3", "mod3.1", "1.2", "mod3.1", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "1.1"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "1.1", "mod1.2", "jar", "jar").exists());

        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.2"))
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.2", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testResolveForceWithDynamicRevisionsAndSeveralConfs() throws Exception {
        // mod4.1 v 4.6 (conf compile, runtime extends compile, test extends runtime) depends on
        // - mod1.2 v 1+ and forces it in conf compile
        // - mod3.1 v 1.2 in conf test which depends on mod1.2 v 2+
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod4.1/ivy-4.6.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org4", "mod4.1", "4.6");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org3", "mod3.1", "1.2"))
                .exists());
        assertTrue(getArchiveFileInCache("org3", "mod3.1", "1.2", "mod3.1", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "1.1"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "1.1", "mod1.2", "jar", "jar").exists());

        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.2"))
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.2", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testResolveForceWithDynamicRevisionsAndSeveralConfs2() throws Exception {
        // mod4.1 v 4.7 (conf compile, test extends compile) depends on
        // - mod1.2 v 1+ and forces it in conf compile
        // - mod3.1 v 1.3 in conf test->runtime
        // which defines confs compile, runtime extends compile
        // which depends on mod1.2 v 2+ in conf compile->default
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod4.1/ivy-4.7.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org4", "mod4.1", "4.7");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org3", "mod3.1", "1.3"))
                .exists());
        assertTrue(getArchiveFileInCache("org3", "mod3.1", "1.3", "mod3.1", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "1.1"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "1.1", "mod1.2", "jar", "jar").exists());

        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.2"))
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.2", "mod1.2", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-182.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-182">IVY-182</a>
     */
    @Test
    public void testResolveForceWithDynamicRevisionsAndCyclicDependencies() throws Exception {
        // * has no revision
        // * declares conf compile, test extends compile,
        // * depends on
        // - mod1.2 v 1+ and forces it in conf compile
        // - mod3.1 v 1+ in conf test->runtime excluding mod4.1 (to avoid cyclic dep failure)
        // which defines confs compile, runtime extends compile
        // which depends on mod1.2 v 2+ in conf compile->default
        // which depends on mod4.1 v 4+ in conf compile->compile
        ResolveReport report = ivy.resolve(ResolveTest.class.getResource("ivy-182.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleId mid = new ModuleId("test", "IVY-182");
        assertEquals(mid, md.getModuleRevisionId().getModuleId());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org3", "mod3.1", "1.4"))
                .exists());
        assertTrue(getArchiveFileInCache("org3", "mod3.1", "1.4", "mod3.1", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "1.1"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "1.1", "mod1.2", "jar", "jar").exists());

        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.2"))
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.2", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testResolveContradictoryConflictResolution() throws Exception {
        // mod10.1 v 1.0 depends on
        // - mod1.2 v 2.0 and forces it
        // - mod4.1 v 4.1 (which selects mod1.2 v 2.1 and evicts mod1.2 v 2.0)
        // mod4.1 v 4.1 depends on
        // - mod1.1 v 1.0 which depends on mod1.2 v 2.0
        // - mod3.1 v 1.1 which depends on mod1.2 v 2.1
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod10.1/ivy-1.0.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org10", "mod10.1", "1.0");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // conflicting dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.1"))
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.1", "mod1.2", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-130.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-130">IVY-130</a>
     */
    @Test
    public void testResolveContradictoryConflictResolution2() throws Exception {
        // Only mod1.2 v2.0 should be resolved and not v2.1 (because of force)
        // mod10.1 v 1.1 depends on
        // - mod1.2 v 2.0 and forces it
        // - mod4.1 v 4.3
        // mod4.1 v 4.3 depends on
        // - mod1.2 v 2.1
        // - mod3.1 v 1.1 which depends on mod1.2 v 2.1
        ivy.resolve(new File("test/repositories/2/mod10.1/ivy-1.1.xml"),
            getResolveOptions(new String[] {"*"}));

        // conflicting dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());

        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.1"))
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.1", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testResolveContradictoryConflictResolution3() throws Exception {
        // mod 1.2 v2.0 should be selected (despite conflict manager in 4.1, because of force in
        // 10.1)
        // mod10.1 v 1.3 depends on
        // - mod1.2 v 2.0 and forces it
        // - mod4.1 v 4.4
        // mod4.1 v 4.4 depends on
        // - mod1.2 v 2.0 but selects mod1.2 v 2.1
        // - mod3.1 v 1.1 which depends on mod1.2 v 2.1
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod10.1/ivy-1.3.xml"),
            getResolveOptions(new String[] {"*"}));

        IvyNode[] evicted = report.getConfigurationReport("default").getEvictedNodes();
        assertEquals(1, evicted.length);
        assertEquals(ModuleRevisionId.newInstance("org1", "mod1.2", "2.1"),
            evicted[0].getResolvedId());
    }

    @Test
    public void testExtends() throws Exception {
        // mod 5.2 depends on mod5.1 conf B
        // mod5.1 conf B publishes art51B
        // mod5.1 conf B extends conf A
        // mod5.1 conf A publishes art51A
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod5.2/ivy-1.0.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org5", "mod5.2", "1.0");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org5", "mod5.1", "4.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.0", "art51B", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.0", "art51A", "jar", "jar").exists());
    }

    @Test
    public void testMultiConfs() throws Exception {
        // mod 5.2 depends on mod5.1 conf B in its conf B and conf A in its conf A
        // mod5.1 conf B publishes art51B
        // mod5.1 conf A publishes art51A
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod5.2/ivy-2.0.xml"),
            getResolveOptions(new String[] {"B", "A"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org5", "mod5.2", "2.0");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        ModuleRevisionId depId = ModuleRevisionId.newInstance("org5", "mod5.1", "4.1");

        ConfigurationResolveReport crr = report.getConfigurationReport("A");
        assertNotNull(crr);
        assertEquals(1, crr.getDownloadReports(depId).length);

        File r = new File(cache, ResolveOptions.getDefaultResolveId(mrid.getModuleId()) + "-A.xml");
        assertTrue(r.exists());
        final boolean[] found = new boolean[] {false};
        SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
        saxParser.parse(r, new DefaultHandler() {
            @Override
            public void startElement(String uri, String localName, String qName,
                    Attributes attributes) {
                if ("artifact".equals(qName) && "art51B".equals(attributes.getValue("name"))) {
                    found[0] = true;
                }
            }
        });
        assertFalse(found[0]);

        assertTrue(getIvyFileInCache(depId).exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.1", "art51A", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.1", "art51B", "jar", "jar").exists());
    }

    @Test
    public void testThisConfiguration() throws Exception {
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod14.4/ivy-1.1.xml"),
            getResolveOptions(new String[] {"compile"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);

        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org14", "mod14.4", "1.1");
        assertEquals(mrid, md.getModuleRevisionId());
        ConfigurationResolveReport crr = report.getConfigurationReport("compile");
        assertNotNull(crr);
        assertEquals(4, crr.getArtifactsNumber());
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org14", "mod14.3", "1.1"))
                .exists());
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org14", "mod14.2", "1.1"))
                .exists());
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org14", "mod14.1", "1.1"))
                .exists());
        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org8", "mod8.3", "1.0"))
                .exists());
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org8", "mod8.1", "1.0"))
                .exists());

        CacheCleaner.deleteDir(cache);
        createCache();
        report = ivy.resolve(new File("test/repositories/2/mod14.4/ivy-1.1.xml"),
            getResolveOptions(new String[] {"standalone"}));
        crr = report.getConfigurationReport("standalone");
        assertNotNull(crr);
        assertEquals(7, crr.getArtifactsNumber());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org14", "mod14.3", "1.1"))
                .exists());
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org14", "mod14.1", "1.1"))
                .exists());
        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org14", "mod14.2", "1.1"))
                .exists());
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org14", "mod14.3", "1.1"))
                .exists());
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org8", "mod8.3", "1.0"))
                .exists());
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org8", "mod8.1", "1.0"))
                .exists());
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org8", "mod8.4", "1.1"))
                .exists());
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org8", "mod8.2", "1.1"))
                .exists());
    }

    @Test
    public void testLatest() throws Exception {
        // mod1.4 depends on latest mod1.2
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org1/mod1.4/ivys/ivy-1.0.1.xml"),
            getResolveOptions(new String[] {"default"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org1", "mod1.4", "1.0.1");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        ModuleRevisionId depId = ModuleRevisionId.newInstance("org1", "mod1.2", "2.2");

        ConfigurationResolveReport crr = report.getConfigurationReport("default");
        assertNotNull(crr);
        assertEquals(1, crr.getDownloadReports(depId).length);

        File r = getConfigurationResolveReportInCache(
            ResolveOptions.getDefaultResolveId(mrid.getModuleId()), "default");
        assertTrue(r.exists());
        final boolean[] found = new boolean[] {false};
        SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
        saxParser.parse(r, new DefaultHandler() {
            @Override
            public void startElement(String uri, String localName, String qName,
                    Attributes attributes) {
                if ("artifact".equals(qName) && "mod1.2".equals(attributes.getValue("name"))) {
                    found[0] = true;
                }
            }
        });
        assertTrue(found[0]);

        assertTrue(getIvyFileInCache(depId).exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.2", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testLatestMultiple() throws Exception {
        // mod1.5 depends on
        // latest mod1.4, which depends on mod1.2 2.2
        // latest mod1.2 (which is 2.2)
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org1/mod1.5/ivys/ivy-1.0.2.xml"),
            getResolveOptions(new String[] {"default"}));
        assertFalse(report.hasError());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.4", "2.0"))
                .exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.2"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.2", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testLatestWhenReleased() throws Exception {
        // The test verify that latest.integration dependencies can be resolved with released
        // version also.
        ResolveReport report = ivy.resolve(ResolveTest.class.getResource("ivy-latestreleased.xml"),
            getResolveOptions(new String[] {"default"}));
        assertFalse(report.hasError());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod_released", "1.1"))
                .exists());
    }

    /**
     * Test case for IVY-602.
     * Verify that latest.integration dependencies can be resolved when using a resolver with
     * multiple patterns, when only the first pattern finds something
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-602">IVY-602</a>
     */
    @Test
    public void testLatestWithMultiplePatterns() throws Exception {
        // mod9.2 depends on latest.integration of mod6.2
        Ivy ivy = Ivy.newInstance();
        ivy.configure(new File("test/repositories/ivysettings-IVY602.xml"));

        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org9/mod9.2/ivys/ivy-1.3.xml"),
            getResolveOptions(new String[] {"default"}));
        assertNotNull(report);
        assertFalse(report.hasError());

        assertTrue(getArchiveFileInCache("org6", "mod6.2", "2.0", "mod6.2", "jar", "jar").exists());
    }

    @Test
    public void testResolveModeDynamic1() throws Exception {
        // mod1.1;1.0.1 -> mod1.2;2.0|latest.integration
        ResolveReport report = ivy.resolve(
            new File("test/repositories/1/org1/mod1.1/ivys/ivy-1.0.1.xml"),
            getResolveOptions(new String[] {"default"}).setResolveMode(
                ResolveOptions.RESOLVEMODE_DYNAMIC));
        assertNotNull(report);

        ModuleRevisionId depId = ModuleRevisionId.newInstance("org1", "mod1.2", "2.2");

        ConfigurationResolveReport crr = report.getConfigurationReport("default");
        assertEquals(1, crr.getDownloadReports(depId).length);

        assertTrue(getIvyFileInCache(depId).exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.2", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testResolveModeDynamic2() throws Exception {
        // same as ResolveModeDynamic1, but resolve mode is set in settings
        Map<String, String> attributes = new HashMap<>();
        attributes.put("organisation", "org1");
        attributes.put("module", "mod1.2");
        ivy.getSettings().addModuleConfiguration(attributes, ExactPatternMatcher.INSTANCE, null,
            null, null, ResolveOptions.RESOLVEMODE_DYNAMIC);
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org1/mod1.1/ivys/ivy-1.0.1.xml"),
            getResolveOptions(new String[] {"default"}));
        assertNotNull(report);

        ModuleRevisionId depId = ModuleRevisionId.newInstance("org1", "mod1.2", "2.2");

        ConfigurationResolveReport crr = report.getConfigurationReport("default");
        assertEquals(1, crr.getDownloadReports(depId).length);

        assertTrue(getIvyFileInCache(depId).exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.2", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testResolveModeDynamicWithBranch1() throws Exception {
        // bar1;5 -> foo1#branch1|;2|[0,4]
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/branches/ivysettings.xml"));

        ResolveReport report = ivy.resolve(new File(
                "test/repositories/branches/bar/bar1/trunk/5/ivy.xml"),
            getResolveOptions(new String[] {"*"})
                    .setResolveMode(ResolveOptions.RESOLVEMODE_DYNAMIC));
        assertFalse(report.hasError());

        assertTrue(getArchiveFileInCache(ivy, "foo#foo1#trunk;3", "foo1", "jar", "jar").exists());
    }

    @Test
    public void testResolveModeDynamicWithBranch2() throws Exception {
        // bar1;5 -> foo1#trunk|branch1;3|[0,4]
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/branches/ivysettings.xml"));

        ResolveReport report = ivy.resolve(new File(
                "test/repositories/branches/bar/bar1/trunk/6/ivy.xml"),
            getResolveOptions(new String[] {"*"})
                    .setResolveMode(ResolveOptions.RESOLVEMODE_DYNAMIC));
        assertFalse(report.hasError());

        assertTrue(getArchiveFileInCache(ivy, "foo#foo1#branch1;4", "foo1", "jar", "jar").exists());
    }

    @Test
    public void testResolveModeDefaultOverrideSettings() throws Exception {
        // same as ResolveModeDynamic2, but resolve mode is set in settings, and overridden when
        // calling resolve
        Map<String, String> attributes = new HashMap<>();
        attributes.put("organisation", "org1");
        attributes.put("module", "mod1.2");
        ivy.getSettings().addModuleConfiguration(attributes, ExactPatternMatcher.INSTANCE, null,
            null, null, ResolveOptions.RESOLVEMODE_DYNAMIC);
        ResolveReport report = ivy.resolve(
            new File("test/repositories/1/org1/mod1.1/ivys/ivy-1.0.1.xml"),
            getResolveOptions(new String[] {"default"}).setResolveMode(
                ResolveOptions.RESOLVEMODE_DEFAULT));
        assertNotNull(report);

        ModuleRevisionId depId = ModuleRevisionId.newInstance("org1", "mod1.2", "2.0");

        ConfigurationResolveReport crr = report.getConfigurationReport("default");
        assertEquals(1, crr.getDownloadReports(depId).length);

        assertTrue(getIvyFileInCache(depId).exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testVersionRange1() throws Exception {
        // mod 1.4 depends on mod1.2 [1.0,2.0[
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org1/mod1.4/ivys/ivy-1.0.2.xml"),
            getResolveOptions(new String[] {"default"}));
        assertFalse(report.hasError());

        // dependencies
        ModuleRevisionId depId = ModuleRevisionId.newInstance("org1", "mod1.2", "1.1");

        ConfigurationResolveReport crr = report.getConfigurationReport("default");
        assertNotNull(crr);
        assertEquals(1, crr.getDownloadReports(depId).length);

        assertTrue(getIvyFileInCache(depId).exists());
    }

    @Test
    public void testVersionRange2() throws Exception {
        // mod 1.4 depends on mod1.2 [1.5,2.0[
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org1/mod1.4/ivys/ivy-1.0.3.xml"),
            getResolveOptions(new String[] {"default"}));
        assertTrue(report.hasError());
    }

    @Test
    public void testLatestMilestone() throws Exception {
        // mod9.2 depends on latest.milestone of mod6.4
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org9/mod9.2/ivys/ivy-1.1.xml"),
            getResolveOptions(new String[] {"default"}));
        assertFalse(report.hasError());

        // dependencies
        ModuleRevisionId depId = ModuleRevisionId.newInstance("org6", "mod6.4", "3");

        ConfigurationResolveReport crr = report.getConfigurationReport("default");
        assertNotNull(crr);
        assertEquals(1, crr.getDownloadReports(depId).length);

        assertTrue(getIvyFileInCache(depId).exists());
    }

    /**
     * Test case for IVY-318.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-318">IVY-318</a>
     */
    @Test
    public void testLatestMilestone2() throws Exception {
        // mod9.2 depends on latest.milestone of mod6.2, but there is no milestone
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org9/mod9.2/ivys/ivy-1.2.xml"),
            getResolveOptions(new String[] {"default"}));
        // we should have an error since there is no milestone version, it should be considered as a
        // non resolved dependency
        assertTrue(report.hasError());

        // dependencies
        ConfigurationResolveReport crr = report.getConfigurationReport("default");
        assertNotNull(crr);
        assertEquals(0, crr.getArtifactsNumber());
    }

    /**
     * Test case for IVY-56.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-56">IVY-56</a>
     */
    @Test
    public void testIVY56() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/bugIVY-56/ivysettings.xml"));

        try {
            ResolveReport report = ivy.resolve(ResolveTest.class.getResource("ivy-56.xml"),
                getResolveOptions(new String[] {"default"}));
            assertNotNull(report);
        } finally {
            FileUtil.forceDelete(ivy.getSettings().getDefaultCache());
        }
    }

    /**
     * Test case for IVY-214.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-214">IVY-214</a>
     */
    @Test
    public void testIVY214() throws Exception {
        ResolveReport report = ivy.resolve(ResolveTest.class.getResource("ivy-214.xml"),
            getResolveOptions(new String[] {"compile"}));

        assertNotNull(report);
        assertFalse(report.hasError());

        assertEquals("Number of artifacts not correct", 1, report.getConfigurationReport("compile")
                .getArtifactsNumber());
    }

    /**
     * Test case for IVY-218.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-218">IVY-218</a>
     */
    @Test
    public void testIVY218() throws Exception {
        ResolveReport report = ivy.resolve(ResolveTest.class.getResource("ivy-218.xml"),
            getResolveOptions(new String[] {"test"}));

        assertNotNull(report);
        assertFalse(report.hasError());

        assertEquals("Number of artifacts not correct", 3, report.getConfigurationReport("test")
                .getArtifactsNumber());
    }

    /**
     * Test case for IVY-729.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-729">IVY-729</a>
     */
    @Test
    public void testIVY729() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/IVY-729/ivysettings.xml"));

        ResolveReport report = ivy.resolve(new File("test/repositories/IVY-729/ivy.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());
    }

    /**
     * Circular dependency: mod6.3 depends on mod6.2, which itself depends on mod6.3;
     * circular dependency strategy set to error.
     */
    @Test
    public void testCircular() throws Exception {
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod6.3/ivy-1.0.xml"), getResolveOptions(new String[] {"default"}));
        assertFalse(report.hasError());

        ivy.getSettings().setCircularDependencyStrategy(IgnoreCircularDependencyStrategy.getInstance());
        report = ivy.resolve(new File("test/repositories/2/mod6.3/ivy-1.0.xml"), getResolveOptions(new String[] {"default"}));
        assertFalse(report.hasError());

        ivy.getSettings().setCircularDependencyStrategy(WarnCircularDependencyStrategy.getInstance());
        report = ivy.resolve(new File("test/repositories/2/mod6.3/ivy-1.0.xml"), getResolveOptions(new String[] {"default"}));
        assertFalse(report.hasError());

        ivy.getSettings().setCircularDependencyStrategy(ErrorCircularDependencyStrategy.getInstance());
        Exception e = assertThrows(CircularDependencyException.class, () ->
            ivy.resolve(new File("test/repositories/2/mod6.3/ivy-1.0.xml"), getResolveOptions(new String[] {"default"})));
        assertEquals("org6#mod6.3;1.0->org6#mod6.2;1.0->org6#mod6.3;latest.integration", e.getMessage());
    }

    /**
     * Circular dependency: mod 9.1 (no revision) depends on mod9.2, which depends on mod9.1 2.+;
     * circular dependency strategy set to error.
     *
     * @throws Exception if something goes wrong
     */
    @Test
    public void testCircular2() throws Exception {
        ResolveReport report = ivy.resolve(new File("test/repositories/circular/ivy.xml"), getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        ivy.getSettings().setCircularDependencyStrategy(ErrorCircularDependencyStrategy.getInstance());
        Exception e = assertThrows(CircularDependencyException.class, () ->
            ivy.resolve(new File("test/repositories/circular/ivy.xml"), getResolveOptions(new String[] {"*"})));
        assertEquals("org8#mod8.5;NONE->org8#mod8.6;2.+->org8#mod8.5;2.+", e.getMessage());
    }

    /**
     * Test case for IVY-400.
     * Circular dependency: mod6.3 depends on mod6.2, which itself depends on mod6.3,
     * in both configuration default and test; circular dependency strategy set to error.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-400">IVY-400</a>
     */
    @Test
    public void testCircular3() throws Exception {
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod6.3/ivy-1.2.xml"), getResolveOptions(new String[] {"default", "test"}));
        assertFalse(report.hasError());
        // we should have mod 6.2 artifact in both configurations
        assertEquals(1, report.getConfigurationReport("default").getArtifactsNumber());
        assertEquals(1, report.getConfigurationReport("test").getArtifactsNumber());

        ivy.getSettings().setCircularDependencyStrategy(IgnoreCircularDependencyStrategy.getInstance());
        report = ivy.resolve(new File("test/repositories/2/mod6.3/ivy-1.2.xml"), getResolveOptions(new String[] {"default", "test"}));
        assertFalse(report.hasError());
        assertEquals(1, report.getConfigurationReport("default").getArtifactsNumber());
        assertEquals(1, report.getConfigurationReport("test").getArtifactsNumber());

        ivy.getSettings().setCircularDependencyStrategy(WarnCircularDependencyStrategy.getInstance());
        report = ivy.resolve(new File("test/repositories/2/mod6.3/ivy-1.2.xml"), getResolveOptions(new String[] {"default", "test"}));
        assertFalse(report.hasError());
        assertEquals(1, report.getConfigurationReport("default").getArtifactsNumber());
        assertEquals(1, report.getConfigurationReport("test").getArtifactsNumber());

        ivy.getSettings().setCircularDependencyStrategy(ErrorCircularDependencyStrategy.getInstance());
        Exception e = assertThrows(CircularDependencyException.class, () ->
            ivy.resolve(new File("test/repositories/2/mod6.3/ivy-1.2.xml"), getResolveOptions(new String[] {"default", "test"})));
        assertEquals("org6#mod6.3;1.2->org6#mod6.2;1.1->...", e.getMessage());
    }

    @Test
    public void testRegularCircular() throws Exception {
        // mod11.1 depends on mod11.2 but excludes itself
        // mod11.2 depends on mod11.1
        ivy.getSettings().setCircularDependencyStrategy(
            ErrorCircularDependencyStrategy.getInstance());
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod11.1/ivy-1.0.xml"),
            getResolveOptions(new String[] {"test"}));

        assertNotNull(report);
        assertFalse(report.hasError());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org11", "mod11.2", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org11", "mod11.2", "1.0", "mod11.2", "jar", "jar")
                .exists());

        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org11", "mod11.1", "1.0"))
                .exists());
        assertFalse(getArchiveFileInCache("org11", "mod11.1", "1.0", "mod11.1", "jar", "jar")
                .exists());
    }

    @Test
    public void testResolveDualChain() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(ResolveTest.class.getResource("dualchainresolverconf.xml"));

        DependencyResolver resolver = ivy.getSettings().getResolver("default");
        assertNotNull(resolver);
        assertTrue(resolver instanceof DualResolver);

        // first without cache
        ivy.resolve(ResolveTest.class.getResource("ivy-dualchainresolver.xml"),
            getResolveOptions(new String[] {"default"}));

        assertTrue(new File("build/cache/xerces/xerces/ivy-2.6.2.xml").exists());
        assertTrue(new File("build/cache/xerces/xerces/jars/xmlParserAPIs-2.6.2.jar").exists());
        assertTrue(new File("build/cache/xerces/xerces/jars/xercesImpl-2.6.2.jar").exists());

        // second with cache for ivy file only
        new File("build/cache/xerces/xerces/jars/xmlParserAPIs-2.6.2.jar").delete();
        new File("build/cache/xerces/xerces/jars/xercesImpl-2.6.2.jar").delete();
        assertFalse(new File("build/cache/xerces/xerces/jars/xmlParserAPIs-2.6.2.jar").exists());
        assertFalse(new File("build/cache/xerces/xerces/jars/xercesImpl-2.6.2.jar").exists());
        ivy.resolve(ResolveTest.class.getResource("ivy-dualchainresolver.xml"),
            getResolveOptions(new String[] {"default"}));

        assertTrue(new File("build/cache/xerces/xerces/ivy-2.6.2.xml").exists());
        assertTrue(new File("build/cache/xerces/xerces/jars/xmlParserAPIs-2.6.2.jar").exists());
        assertTrue(new File("build/cache/xerces/xerces/jars/xercesImpl-2.6.2.jar").exists());
    }

    @Test
    public void testBug148() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/bug148/ivysettings.xml"));
        ivy.getSettings().setDefaultCache(cache);

        ivy.resolve(ResolveTest.class.getResource("ivy-148.xml"),
            getResolveOptions(new String[] {"*"}));

        assertTrue(new File("build/cache/jtv-foo/bar/ivy-1.1.0.0.xml").exists());
        assertTrue(new File("build/cache/jtv-foo/bar/jars/bar-1.1.0.0.jar").exists());
        assertTrue(new File("build/cache/idautomation/barcode/ivy-4.10.xml").exists());
        assertTrue(new File("build/cache/idautomation/barcode/jars/LinearBarCode-4.10.jar")
                .exists());
    }

    @Test
    public void testBug148b() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/bug148/ivysettings.xml"));
        ivy.getSettings().setDefaultCache(cache);

        ivy.resolve(ResolveTest.class.getResource("ivy-148b.xml"),
            getResolveOptions(new String[] {"*"}));

        assertTrue(new File("build/cache/jtv-foo/bar/ivy-1.1.0.0.xml").exists());
        assertTrue(new File("build/cache/jtv-foo/bar/jars/bar-1.1.0.0.jar").exists());
        assertTrue(new File("build/cache/idautomation/barcode/ivy-4.10.xml").exists());
        assertTrue(new File("build/cache/idautomation/barcode/jars/LinearBarCode-4.10.jar")
                .exists());
    }

    /**
     * Test case for IVY-1178.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-1178">IVY-1178</a>
     */
    @Test
    public void testIVY1178() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/IVY-1178/ivysettings.xml"));
        ResolveReport report = ivy.resolve(ResolveTest.class.getResource("ivy-1178.xml"),
            getResolveOptions(new String[] {"*"}));

        assertNotNull(report);
        assertNotNull(report.getUnresolvedDependencies());
        assertEquals("Number of unresolved dependencies not correct", 0,
            report.getUnresolvedDependencies().length);

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("myorg", "modD", "1.1")).exists());
        assertTrue(getArchiveFileInCache("myorg", "modD", "1.1", "modD", "jar", "jar").exists());

        // evicted dependencies
        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("myorg", "modD", "1.0"))
                .exists());
        assertFalse(getArchiveFileInCache("myorg", "modD", "1.0", "modD", "jar", "jar").exists());

        // transitive dependencies of modD-1.1 (must not exist: transitive="false" !)
        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("myorg", "modE", "1.1"))
                .exists());
        assertFalse(getArchiveFileInCache("myorg", "modE", "1.1", "modE", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-1236.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-1236">IVY-1236</a>
     */
    @Test
    public void testIVY1236() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/IVY-1236/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File("test/repositories/IVY-1236/ivy.xml"),
            getResolveOptions(new String[] {"*"}));

        assertNotNull(report);
        assertNotNull(report.getUnresolvedDependencies());
        assertEquals("Number of unresolved dependencies not correct", 0,
            report.getUnresolvedDependencies().length);

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("myorg", "modB", "1.0")).exists());
        assertTrue(getArchiveFileInCache("myorg", "modB", "1.0", "modB", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("myorg", "modB", "1.0", "modB-A", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-1233.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-1233">IVY-1233</a>
     */
    @Test
    public void testIVY1233() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/IVY-1233/ivysettings.xml"));
        ivy.getSettings().setDefaultCache(cache);

        ResolveReport rr = ivy.resolve(new File("test/repositories/IVY-1233/ivy.xml"),
            getResolveOptions(new String[] {"*"}));
        ConfigurationResolveReport crr = rr.getConfigurationReport("default");
        Set<ModuleRevisionId> modRevIds = crr.getModuleRevisionIds();
        assertEquals(3, modRevIds.size());
        assertTrue(modRevIds.contains(ModuleRevisionId.newInstance("test", "a", "1.0")));
        assertTrue(modRevIds.contains(ModuleRevisionId.newInstance("test", "b", "2.0")));
        assertTrue(modRevIds.contains(ModuleRevisionId.newInstance("test", "c", "3.0")));
    }

    /**
     * Test case for IVY-1333.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-1333">IVY-1333</a>
     */
    @Test
    public void testIVY1333() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/IVY-1333/ivysettings.xml"));
        ivy.getSettings().setDefaultCache(cache);

        ResolveReport rr = ivy.resolve(new File("test/repositories/IVY-1333/ivy.xml"),
            getResolveOptions(new String[] {"*"}));
        ConfigurationResolveReport crr = rr.getConfigurationReport("default");
        Set<ModuleRevisionId> modRevIds = crr.getModuleRevisionIds();
        assertEquals(3, modRevIds.size());
        assertTrue(modRevIds.contains(ModuleRevisionId.newInstance("org", "dep1", "1.0")));
        assertTrue(modRevIds.contains(ModuleRevisionId.newInstance("org", "dep2", "1.0")));

        Map<String, String> extra = new HashMap<>();
        extra.put("o:a", "58701");
        assertTrue(modRevIds.contains(ModuleRevisionId.newInstance("org", "badArtifact",
            "1.0.0.m4", extra)));
    }

    /**
     * Test case for IVY-1347.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-1347">IVY-1347</a>
     */
    @Test
    public void testIVY1347() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/IVY-1347/ivysettings.xml"));
        ivy.getSettings().setDefaultCache(cache);

        ResolveReport rr = ivy.resolve(new File(
                "test/repositories/IVY-1347/childone/childtwo/ivy.xml"),
            getResolveOptions(new String[] {"*"}));
        ModuleDescriptor md = rr.getModuleDescriptor();
        assertNotNull(md);

        ExtendsDescriptor[] parents = md.getInheritedDescriptors();
        assertNotNull(parents);
        assertEquals(1, parents.length);

        ModuleRevisionId parent = parents[0].getParentRevisionId();
        assertEquals(ModuleRevisionId.newInstance("foo", "parent", "1.0"), parent);
    }

    /**
     * Test case for IVY-999.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-999">IVY-999</a>
     */
    @Test
    public void testIVY999() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/IVY-999/ivysettings.xml"));
        ivy.getSettings().setDefaultCache(cache);

        ResolveReport rr = ivy.resolve(ResolveTest.class.getResource("ivy-999.xml"),
            getResolveOptions(new String[] {"*"}));
        ConfigurationResolveReport crr = rr.getConfigurationReport("default");
        Set<ModuleRevisionId> modRevIds = crr.getModuleRevisionIds();

        assertTrue(modRevIds.contains(ModuleRevisionId.newInstance("junit", "junit", "4.4")));
        assertFalse(modRevIds.contains(ModuleRevisionId.newInstance("junit", "junit", "3.8")));
    }

    /**
     * Test case for IVY-1366.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-1366">IVY-1366</a>
     */
    @Test
    public void testIVY1366() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/IVY-1366/ivysettings.xml"));

        ResolveReport report = ivy.resolve(new File("test/repositories/IVY-1366/ivy.xml"),
            new ResolveOptions().setConfs(new String[] {"runtime"}));
        assertFalse(report.hasError());

        List<Artifact> artifacts = report.getArtifacts();
        assertEquals(3, artifacts.size());
        assertEquals("test#a;1!a.jar", artifacts.get(0).toString());
        assertEquals("test#c;1!c.jar", artifacts.get(1).toString());
        assertEquals("test#b;1!b.jar", artifacts.get(2).toString());
    }

    @Test
    public void testBadFiles() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/badfile/ivysettings.xml"));

        ResolveReport report = ivy.resolve(
            new File("test/repositories/badfile/ivys/ivy-badorg.xml"),
            getResolveOptions(new String[] {"*"}));
        assertTrue("bad org should have raised an error in report", report.hasError());
        assertTrue(joinArray(report.getAllProblemMessages().toArray(new String[0]), "\n").contains("'badorg'"));

        report = ivy.resolve(new File("test/repositories/badfile/ivys/ivy-badmodule.xml"),
            getResolveOptions(new String[] {"*"}));
        assertTrue("bad module should have raised an error in report", report.hasError());
        assertTrue(joinArray(report.getAllProblemMessages().toArray(new String[0]), "\n").contains("'badmodule'"));

        report = ivy.resolve(new File("test/repositories/badfile/ivys/ivy-badbranch.xml"),
            getResolveOptions(new String[] {"*"}));
        assertTrue("bad branch should have raised an error in report", report.hasError());
        assertTrue(joinArray(report.getAllProblemMessages().toArray(new String[0]), "\n").contains("'badbranch'"));

        report = ivy.resolve(new File("test/repositories/badfile/ivys/ivy-badrevision.xml"),
            getResolveOptions(new String[] {"*"}));
        assertTrue("bad revision should have raised an error in report", report.hasError());
        assertTrue(joinArray(report.getAllProblemMessages().toArray(new String[0]), "\n").contains("'badrevision'"));

        report = ivy.resolve(new File("test/repositories/badfile/ivys/ivy-badxml.xml"),
            getResolveOptions(new String[] {"*"}));
        assertTrue("bad xml should have raised an error in report", report.hasError());
        assertTrue(joinArray(report.getAllProblemMessages().toArray(new String[0]), "\n").contains("badatt"));
    }

    @Test
    public void testTransitiveSetting() throws Exception {
        // mod2.4 depends on mod1.1 with transitive set to false
        // mod1.1 depends on mod1.2, which should not be resolved because of the transitive setting
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.4/ivys/ivy-0.3.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org2", "mod2.4", "0.3");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.1", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.1", "1.0", "mod1.1", "jar", "jar").exists());

        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-105.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-105">IVY-105</a>
     */
    @Test
    public void testTransitiveSetting2() throws Exception {
        // mod2.7 depends on mod1.1 and mod2.4
        // mod2.4 depends on mod1.1 with transitive set to false
        // mod1.1 depends on mod1.2
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.7/ivys/ivy-0.6.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.1", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.1", "1.0", "mod1.1", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testResolverDirectlyUsingCache() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(ResolveTest.class.getResource("badcacheconf.xml"));
        File depIvyFileInCache = getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.1",
            "1.0"));
        FileUtil.copy(File.createTempFile("test", "xml"), depIvyFileInCache, null); // creates a
        // fake
        // dependency
        // file in cache
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.4/ivys/ivy-0.3.xml"),
            getResolveOptions(new String[] {"*"}));

        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org2", "mod2.4", "0.3");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(depIvyFileInCache.exists());
        assertFalse(getArchiveFileInCache(ivy, "org1", "mod1.1", "1.0", "mod1.1", "jar", "jar")
                .exists());
    }

    @Test
    public void testVisibility1() throws Exception {
        ivy.resolve(new File("test/repositories/2/mod8.2/ivy-1.0.xml"),
            getResolveOptions(new String[] {"*"}));

        assertFalse(getArchiveFileInCache("org8", "mod8.1", "1.0", "a-private", "txt", "txt")
                .exists());
    }

    @Test
    public void testVisibility2() throws Exception {
        ivy.resolve(new File("test/repositories/2/mod8.3/ivy-1.0.xml"),
            getResolveOptions(new String[] {"private"}));

        assertFalse(getArchiveFileInCache("org8", "mod8.1", "1.0", "a-private", "txt", "txt")
                .exists());
        assertTrue(getArchiveFileInCache("org8", "mod8.1", "1.0", "a", "txt", "txt").exists());
    }

    @Test
    public void testVisibility3() throws Exception {
        ivy.resolve(new File("test/repositories/2/mod8.4/ivy-1.0.xml"),
            getResolveOptions(new String[] {"*"}));

        assertFalse(getArchiveFileInCache("org8", "mod8.1", "1.0", "a-private", "txt", "txt")
                .exists());
        assertTrue(getArchiveFileInCache("org8", "mod8.1", "1.0", "a", "txt", "txt").exists());
    }

    @Test
    public void testVisibility4() throws Exception {
        ivy.resolve(new File("test/repositories/2/mod8.4/ivy-1.1.xml"),
            getResolveOptions(new String[] {"*"}));

        assertTrue(getArchiveFileInCache("org8", "mod8.1", "1.1", "a-private", "txt", "txt")
                .exists());
        assertTrue(getArchiveFileInCache("org8", "mod8.1", "1.1", "a", "txt", "txt").exists());
    }

    // /////////////////////////////////////////////////////////
    // here comes a series of test provided by Chris Rudd
    // about configuration mapping and eviction
    // /////////////////////////////////////////////////////////

    /**
     * Test case for IVY-84.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-84">IVY-84</a>
     */
    @Test
    public void testConfigurationMapping1() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/IVY-84/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File("test/repositories/IVY-84/tests/1/ivy.xml"),
            getResolveOptions(new String[] {"*"}));

        ConfigurationResolveReport conf = report.getConfigurationReport("default");

        assertContainsArtifact("test", "a", "1.0.2", "a", "txt", "txt", conf);
        assertDoesntContainArtifact("test", "a", "1.0.2", "a-bt", "txt", "txt", conf);
        assertContainsArtifact("test", "b", "1.0.2", "b", "txt", "txt", conf);
        assertDoesntContainArtifact("test", "b", "1.0.2", "b-bt", "txt", "txt", conf);
        assertContainsArtifact("test", "c", "1.0.2", "c", "txt", "txt", conf);
        assertDoesntContainArtifact("test", "c", "1.0.2", "c-bt", "txt", "txt", conf);
    }

    /**
     * Test case for IVY-84.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-84">IVY-84</a>
     */
    @Test
    public void testConfigurationMapping2() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/IVY-84/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File("test/repositories/IVY-84/tests/2/ivy.xml"),
            getResolveOptions(new String[] {"*"}));

        ConfigurationResolveReport conf = report.getConfigurationReport("default");

        assertContainsArtifact("test", "a", "1.0.1", "a", "txt", "txt", conf);
        assertDoesntContainArtifact("test", "a", "1.0.1", "a-bt", "txt", "txt", conf);
        assertContainsArtifact("test", "b", "1.0.1", "b", "txt", "txt", conf);
        assertDoesntContainArtifact("test", "b", "1.0.1", "b-bt", "txt", "txt", conf);
        assertContainsArtifact("test", "c", "1.0.1", "c", "txt", "txt", conf);
        assertDoesntContainArtifact("test", "c", "1.0.1", "c-bt", "txt", "txt", conf);
    }

    /**
     * Test case for IVY-84.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-84">IVY-84</a>
     */
    @Test
    public void testConfigurationMapping3() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/IVY-84/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File("test/repositories/IVY-84/tests/3/ivy.xml"),
            getResolveOptions(new String[] {"buildtime"}));

        ConfigurationResolveReport conf = report.getConfigurationReport("buildtime");

        assertContainsArtifact("test", "a", "1.0.2", "a-bt", "txt", "txt", conf);
        assertDoesntContainArtifact("test", "a", "1.0.2", "a", "txt", "txt", conf);
        assertContainsArtifact("test", "b", "1.0.1", "b-bt", "txt", "txt", conf);
        assertDoesntContainArtifact("test", "b", "1.0.1", "b", "txt", "txt", conf);
        assertContainsArtifact("test", "c", "1.0.1", "c-bt", "txt", "txt", conf);
        assertDoesntContainArtifact("test", "c", "1.0.1", "c", "txt", "txt", conf);
    }

    /**
     * Test case for IVY-84.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-84">IVY-84</a>
     */
    @Test
    public void testConfigurationMapping4() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/IVY-84/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File("test/repositories/IVY-84/tests/4/ivy.xml"),
            getResolveOptions(new String[] {"default"}));

        ConfigurationResolveReport conf = report.getConfigurationReport("default");

        assertContainsArtifact("test", "a", "1.0.2", "a", "txt", "txt", conf);
        assertDoesntContainArtifact("test", "a", "1.0.2", "a-bt", "txt", "txt", conf);
        assertContainsArtifact("test", "b", "1.0.1", "b", "txt", "txt", conf);
        assertDoesntContainArtifact("test", "b", "1.0.1", "b-bt", "txt", "txt", conf);
        assertContainsArtifact("test", "c", "1.0.1", "c", "txt", "txt", conf);
        assertDoesntContainArtifact("test", "c", "1.0.1", "c-bt", "txt", "txt", conf);
    }

    /**
     * Test case for IVY-84.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-84">IVY-84</a>
     */
    @Test
    public void testConfigurationMapping5() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/IVY-84/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File("test/repositories/IVY-84/tests/5/ivy.xml"),
            getResolveOptions(new String[] {"*"}));

        ConfigurationResolveReport conf = report.getConfigurationReport("default");

        assertContainsArtifact("test", "a", "1.0.2", "a", "txt", "txt", conf);
        assertDoesntContainArtifact("test", "a", "1.0.2", "a-bt", "txt", "txt", conf);
        assertContainsArtifact("test", "b", "1.0.1", "b", "txt", "txt", conf);
        assertDoesntContainArtifact("test", "b", "1.0.1", "b-bt", "txt", "txt", conf);
        assertContainsArtifact("test", "c", "1.0.1", "c", "txt", "txt", conf);
        assertDoesntContainArtifact("test", "c", "1.0.1", "c-bt", "txt", "txt", conf);
    }

    /**
     * Test case for IVY-84.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-84">IVY-84</a>
     */
    @Test
    public void testConfigurationMapping6() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/IVY-84/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File("test/repositories/IVY-84/tests/6/ivy.xml"),
            getResolveOptions(new String[] {"default", "buildtime"}));

        ConfigurationResolveReport conf = report.getConfigurationReport("default");

        assertContainsArtifact("test", "a", "1.0.2", "a", "txt", "txt", conf);
        assertDoesntContainArtifact("test", "a", "1.0.2", "a-bt", "txt", "txt", conf);
        assertContainsArtifact("test", "b", "1.0.1", "b", "txt", "txt", conf);
        assertDoesntContainArtifact("test", "b", "1.0.1", "b-bt", "txt", "txt", conf);
        assertContainsArtifact("test", "c", "1.0.1", "c", "txt", "txt", conf);
        assertDoesntContainArtifact("test", "c", "1.0.1", "c-bt", "txt", "txt", conf);
    }

    /**
     * Test case for IVY-84.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-84">IVY-84</a>
     */
    @Test
    public void testConfigurationMapping7() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/IVY-84/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File("test/repositories/IVY-84/tests/7/ivy.xml"),
            getResolveOptions(new String[] {"buildtime", "default"}));

        ConfigurationResolveReport conf = report.getConfigurationReport("default");

        assertContainsArtifact("test", "a", "1.0.2", "a", "txt", "txt", conf);
        assertDoesntContainArtifact("test", "a", "1.0.2", "a-bt", "txt", "txt", conf);
        assertContainsArtifact("test", "b", "1.0.1", "b", "txt", "txt", conf);
        assertDoesntContainArtifact("test", "b", "1.0.1", "b-bt", "txt", "txt", conf);
        assertContainsArtifact("test", "c", "1.0.1", "c", "txt", "txt", conf);
        assertDoesntContainArtifact("test", "c", "1.0.1", "c-bt", "txt", "txt", conf);
    }

    /**
     * Test case for IVY-97.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-97">IVY-97</a>
     */
    @Test
    public void testIVY97() throws Exception {
        // mod9.2 depends on mod9.1 and mod1.2
        // mod9.1 depends on mod1.2
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org9/mod9.2/ivys/ivy-1.0.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org9", "mod9.2", "1.0");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org9", "mod9.1", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org9", "mod9.1", "1.0", "mod9.1", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testResolveMultipleSameDependency() throws Exception {
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/multiple-same-deps/mod1/ivys/ivy-1.0.xml"),
            getResolveOptions(new String[] {"*"}));

        assertTrue(getArchiveFileInCache("multiple-same-deps", "mod31", "1.0", "mod31", "jar",
            "jar").exists());
        assertTrue(getArchiveFileInCache("multiple-same-deps", "mod32", "1.0", "mod32", "jar",
            "jar").exists());
        assertTrue(getArchiveFileInCache("multiple-same-deps", "mod33", "1.0", "mod33", "jar",
            "jar").exists());

        ConfigurationResolveReport runtimeReport = report.getConfigurationReport("runtime");
        runtimeReport.getModuleRevisionIds().contains(
            ModuleRevisionId.parse("multiple-same-deps#mod31;1.0"));
        runtimeReport.getModuleRevisionIds().contains(
            ModuleRevisionId.parse("multiple-same-deps#mod32;1.0"));
        runtimeReport.getModuleRevisionIds().contains(
            ModuleRevisionId.parse("multiple-same-deps#mod33;1.0"));
        ConfigurationResolveReport compileReport = report.getConfigurationReport("compile");
        compileReport.getModuleRevisionIds().contains(
            ModuleRevisionId.parse("multiple-same-deps#mod31;1.0"));
        compileReport.getModuleRevisionIds().contains(
            ModuleRevisionId.parse("multiple-same-deps#mod32;1.0"));
        compileReport.getModuleRevisionIds().contains(
            ModuleRevisionId.parse("multiple-same-deps#mod33;1.0"));
    }

    @Test
    public void testResolveTransitiveExcludesSimple() throws Exception {
        // mod2.5 depends on mod2.3 and excludes one artifact from mod2.1
        // mod2.3 depends on mod2.1
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.5/ivys/ivy-0.6.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org2", "mod2.5", "0.6");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org2", "mod2.3", "0.7"))
                .exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.3", "0.7", "mod2.3", "jar", "jar").exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org2", "mod2.1", "0.3"))
                .exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21A", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21B", "jar", "jar").exists());
    }

    @Test
    public void testResolveTransitiveExcludesDiamond1() throws Exception {
        // mod2.6 depends on mod2.3 and mod2.5
        // mod2.3 depends on mod2.1 and excludes art21B
        // mod2.5 depends on mod2.1 and excludes art21A
        ivy.resolve(new File("test/repositories/1/org2/mod2.6/ivys/ivy-0.6.xml"),
            getResolveOptions(new String[] {"*"}));

        assertTrue(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21A", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21B", "jar", "jar").exists());
    }

    @Test
    public void testResolveTransitiveExcludesDiamond2() throws Exception {
        // mod2.6 depends on mod2.3 and mod2.5
        // mod2.3 depends on mod2.1 and excludes art21B
        // mod2.5 depends on mod2.1 and excludes art21B
        ivy.resolve(new File("test/repositories/1/org2/mod2.6/ivys/ivy-0.7.xml"),
            getResolveOptions(new String[] {"*"}));

        assertTrue(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21A", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21B", "jar", "jar").exists());
    }

    @Test
    public void testResolveTransitiveExcludesDiamond3() throws Exception {
        // mod2.6 depends on mod2.3 and mod2.5 and on mod2.1 for which it excludes art21A
        // mod2.3 depends on mod2.1 and excludes art21B
        // mod2.5 depends on mod2.1 and excludes art21B
        ivy.resolve(new File("test/repositories/1/org2/mod2.6/ivys/ivy-0.8.xml"),
            getResolveOptions(new String[] {"*"}));

        assertTrue(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21A", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21B", "jar", "jar").exists());
    }

    @Test
    public void testResolveTransitiveExcludes2() throws Exception {
        // mod2.6 depends on mod2.3 for which it excludes art21A
        // mod2.3 depends on mod2.1 and excludes art21B
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.6/ivys/ivy-0.9.xml"),
            getResolveOptions(new String[] {"*"}));
        ModuleDescriptor md = report.getModuleDescriptor();
        assertEquals(ModuleRevisionId.newInstance("org2", "mod2.6", "0.9"),
            md.getModuleRevisionId());

        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21A", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.3", "art21B", "jar", "jar").exists());
    }

    @Test
    public void testResolveExcludesModule() throws Exception {
        // mod2.6 depends on mod2.1 and excludes mod1.1
        // mod2.1 depends on mod1.1 which depends on mod1.2
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.6/ivys/ivy-0.10.xml"),
            getResolveOptions(new String[] {"*"}));
        ModuleDescriptor md = report.getModuleDescriptor();
        assertEquals(ModuleRevisionId.newInstance("org2", "mod2.6", "0.10"),
            md.getModuleRevisionId());

        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.1", "1.0"))
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.1", "1.0", "mod1.1", "jar", "jar").exists());
        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testResolveExcludesModule2() throws Exception {
        // root depends on a and (x 2 excluding y)
        // a depends on x 1
        // x 1 depends on y 1
        // x 2 depends on y 2
        ivy.configure(new File("test/repositories/IVY-1486/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File(
                        "test/repositories/IVY-1486/org/root/ivy-1.xml"),
                getResolveOptions(new String[] {"*"}));
        ModuleDescriptor md = report.getModuleDescriptor();
        assertEquals(ModuleRevisionId.newInstance("org", "root", "1"),
                md.getModuleRevisionId());
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org", "x", "2"))
                .exists());
        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org", "y", "2"))
                .exists());
        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org", "y", "1"))
                .exists());
    }

    @Test
    public void testResolveExcludesModule3() throws Exception {
        // Ensure that search for unexcluded paths doesn't get confused by the exclusion
        // of parents.
        ivy.configure(new File("test/repositories/IVY-1486/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File(
                        "test/repositories/IVY-1486/org/root/ivy-2.xml"),
                getResolveOptions(new String[] {"*"}));
        ModuleDescriptor md = report.getModuleDescriptor();
        assertEquals(ModuleRevisionId.newInstance("org", "root", "2"),
                md.getModuleRevisionId());
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org", "l", "1"))
                .exists());
        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org", "l", "2"))
                .exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org", "h", "2"))
                .exists());
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org", "i", "2"))
                .exists());
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org", "j", "2"))
                .exists());
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org", "k", "2"))
                .exists());
    }

    @Test
    public void testResolveExcludesModuleWide() throws Exception {
        // mod2.6 depends on mod2.1 and excludes mod1.1 module wide
        // mod2.1 depends on mod1.1 which depends on mod1.2
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.6/ivys/ivy-0.11.xml"),
            getResolveOptions(new String[] {"*"}));
        ModuleDescriptor md = report.getModuleDescriptor();
        assertEquals(ModuleRevisionId.newInstance("org2", "mod2.6", "0.11"),
            md.getModuleRevisionId());

        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.1", "1.0"))
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.1", "1.0", "mod1.1", "jar", "jar").exists());
        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testResolveExcludesConf() throws Exception {
        // mod2.6 depends on mod2.3 in conf default and mod2.5 in conf exclude
        // mod2.5 depends on mod2.3
        // mod2.6 globally exclude mod2.3 in conf exclude
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.6/ivys/ivy-0.13.xml"),
            getResolveOptions(new String[] {"include"}));
        ModuleDescriptor md = report.getModuleDescriptor();
        assertEquals(ModuleRevisionId.newInstance("org2", "mod2.6", "0.13"),
            md.getModuleRevisionId());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org2", "mod2.3", "0.4"))
                .exists());
    }

    @Test
    public void testResolveExcludesConf2() throws Exception {
        // same as testResolveExcludesConf
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.6/ivys/ivy-0.13.xml"),
            getResolveOptions(new String[] {"exclude"}));
        ModuleDescriptor md = report.getModuleDescriptor();
        assertEquals(ModuleRevisionId.newInstance("org2", "mod2.6", "0.13"),
            md.getModuleRevisionId());

        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org2", "mod2.3", "0.4"))
                .exists());
    }

    @Test
    public void testResolveExcludesConf3() throws Exception {
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/org2/mod2.6/ivys/ivy-0.14.xml"),
            getResolveOptions(new String[] {"exclude"}));
        ModuleDescriptor md = report.getModuleDescriptor();
        assertEquals(ModuleRevisionId.newInstance("org2", "mod2.6", "0.14"),
            md.getModuleRevisionId());

        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org2", "mod2.5", "0.9"))
                .exists());
    }

    @Test
    public void testResolveExceptConfiguration() throws Exception {
        // mod10.2 depends on mod5.1 conf *, !A
        ivy.resolve(new File("test/repositories/2/mod10.2/ivy-2.0.xml"),
            getResolveOptions(new String[] {"*"}));

        assertFalse(getArchiveFileInCache("org5", "mod5.1", "4.1", "art51A", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.1", "art51B", "jar", "jar").exists());
    }

    /**
     * Test for issues IVY-982 and IVY-1547,
     * which have to do with resolve engine ignoring negated configurations
     * on the left side of the maps-to operator.
     */
    @Test
    public void testResolveWithNegation() throws Exception {
        ConfigurationResolveReport crp;
        ResolveReport report = ivy.resolve(new File(
                "test/java/org/apache/ivy/core/resolve/ivy-982.xml"),
                getResolveOptions(new String[] {"*"}));

        // mod1.2: A->default
        // mod2.1: *,!A->A
        // mod2.2: *,!A->myconf1; *,!A,!B->myconf2
        assertFalse(report.hasError());

        ModuleRevisionId mod12 = ModuleRevisionId.newInstance("org1", "mod1.2", "2.0");
        ModuleRevisionId mod21 = ModuleRevisionId.newInstance("org2", "mod2.1", "0.5");
        ModuleRevisionId mod22 = ModuleRevisionId.newInstance("org2", "mod2.2", "0.9");

        crp = report.getConfigurationReport("A");
        assertTrue(crp.getDependency(mod12) != null);
        assertTrue(Arrays.asList(crp.getDependency(mod12).getConfigurations(crp.getConfiguration()))
            .containsAll(Collections.singletonList("default")));
        assertEquals(crp.getDependency(mod21), null);
        assertEquals(crp.getDependency(mod22), null);

        crp = report.getConfigurationReport("B");
        assertEquals(crp.getDependency(mod12), null);
        assertTrue(crp.getDependency(mod21) != null);
        assertTrue(Arrays.asList(crp.getDependency(mod21).getConfigurations(crp.getConfiguration()))
            .containsAll(Collections.singletonList("A")));
        assertTrue(crp.getDependency(mod22) != null);
        assertTrue(Arrays.asList(crp.getDependency(mod22).getConfigurations(crp.getConfiguration()))
            .containsAll(Collections.singletonList("myconf1")));

        crp = report.getConfigurationReport("C");
        assertEquals(crp.getDependency(mod12), null);
        assertTrue(crp.getDependency(mod21) != null);
        assertTrue(Arrays.asList(crp.getDependency(mod21).getConfigurations(crp.getConfiguration()))
            .containsAll(Collections.singletonList("A")));
        assertTrue(crp.getDependency(mod22) != null);
        assertTrue(Arrays.asList(crp.getDependency(mod22).getConfigurations(crp.getConfiguration()))
            .containsAll(Arrays.asList("myconf1", "myconf2")));
    }

    @Test
    public void testResolveIntersectConfiguration1() throws Exception {
        // mod5.2;3.0 -> mod5.1;4.4 (*->@)
        // mod5.1;4.4 -> mod1.2;2.0 (B,xplatform->default)
        // mod5.1;4.4 -> mod2.2;0.9 (B,windows->myconf1;B,linux->myconf2)
        // mod5.1;4.4 -> mod2.1;0.5 (B,windows->A+B)
        ivy.resolve(new File("test/repositories/2/mod5.2/ivy-3.0.xml"),
            getResolveOptions(new String[] {"A"}));

        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.4", "art51A", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org5", "mod5.1", "4.4", "art51B", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org5", "mod5.1", "4.4", "art51B", "dll", "dll").exists());
        assertFalse(getArchiveFileInCache("org5", "mod5.1", "4.4", "art51B", "so", "so").exists());
    }

    @Test
    public void testResolveIntersectConfiguration2() throws Exception {
        // mod5.2;3.0 -> mod5.1;4.4 (*->@)
        // mod5.1;4.4 -> mod1.2;2.0 (B,xplatform->default)
        // mod5.1;4.4 -> mod2.2;0.9 (B,windows->myconf1;B,linux->myconf2)
        // mod5.1;4.4 -> mod2.1;0.5 (B,windows->A+B)
        ivy.resolve(new File("test/repositories/2/mod5.2/ivy-3.0.xml"),
            getResolveOptions(new String[] {"B"}));

        assertFalse(getArchiveFileInCache("org5", "mod5.1", "4.4", "art51A", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.4", "art51B", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.4", "art51B", "dll", "dll").exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.4", "art51B", "so", "so").exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.2", "0.9", "art22-1", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.2", "0.9", "art22-2", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.5", "art21A", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.5", "art21B", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.1", "0.5", "art21AB", "jar", "jar").exists());
    }

    @Test
    public void testResolveIntersectConfiguration3() throws Exception {
        // mod5.2;3.0 -> mod5.1;4.4 (*->@)
        // mod5.1;4.4 -> mod1.2;2.0 (B,xplatform->default)
        // mod5.1;4.4 -> mod2.2;0.9 (B,windows->myconf1;B,linux->myconf2)
        // mod5.1;4.4 -> mod2.1;0.5 (B,windows->A+B)
        ivy.resolve(new File("test/repositories/2/mod5.2/ivy-3.0.xml"),
            getResolveOptions(new String[] {"B+windows"}));

        assertFalse(getArchiveFileInCache("org5", "mod5.1", "4.4", "art51A", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.4", "art51B", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.4", "art51B", "dll", "dll").exists());
        assertFalse(getArchiveFileInCache("org5", "mod5.1", "4.4", "art51B", "so", "so").exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.2", "0.9", "art22-1", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.2", "0.9", "art22-2", "jar", "jar")
                .exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.5", "art21A", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.5", "art21B", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.1", "0.5", "art21AB", "jar", "jar").exists());
    }

    @Test
    public void testResolveIntersectConfiguration4() throws Exception {
        // mod5.2;3.0 -> mod5.1;4.4 (*->@)
        // mod5.1;4.4 -> mod1.2;2.0 (B,xplatform->default)
        // mod5.1;4.4 -> mod2.2;0.9 (B,windows->myconf1;B,linux->myconf2)
        // mod5.1;4.4 -> mod2.1;0.5 (B,windows->A+B)
        // mod5.1;4.4 -> mod2.8;0.6 (windows,linux->@+thread+debug;A,B->*)
        ivy.resolve(new File("test/repositories/2/mod5.2/ivy-3.0.xml"),
            getResolveOptions(new String[] {"B+linux"}));

        assertFalse(getArchiveFileInCache("org5", "mod5.1", "4.4", "art51A", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.4", "art51B", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org5", "mod5.1", "4.4", "art51B", "dll", "dll").exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.4", "art51B", "so", "so").exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.2", "0.9", "art22-1", "jar", "jar")
                .exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.2", "0.9", "art22-2", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.5", "art21A", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.5", "art21B", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.5", "art21AB", "jar", "jar")
                .exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.8", "0.6", "art28-linux-debug-thread",
            "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.8", "0.6", "art28-linux-debug", "jar",
            "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.8", "0.6", "art28-windows-debug-thread",
            "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.8", "0.6", "art28-windows-debug", "jar",
            "jar").exists());
    }

    @Test
    public void testConfigurationGroups() throws Exception {
        // mod5.2;3.1 -> mod5.1;4.5 (*->@)
        // mod5.1;4.5 -> mod1.2;2.0 (B,*[axis=platform]->default)
        // mod5.1;4.5 -> mod2.2;0.9 (B,windows->myconf1;B,linux->myconf2)
        // mod5.1;4.5 -> mod2.1;0.5 (B,windows->A+B)
        // mod5.1;4.5 -> mod2.8;0.6 (windows,linux->@+thread+debug;A,B->*)
        ivy.resolve(new File("test/repositories/2/mod5.2/ivy-3.1.xml"),
            getResolveOptions(new String[] {"B+linux"}));

        assertFalse(getArchiveFileInCache("org5", "mod5.1", "4.5", "art51A", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.5", "art51B", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org5", "mod5.1", "4.5", "art51B", "dll", "dll").exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.5", "art51B", "so", "so").exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.2", "0.9", "art22-1", "jar", "jar")
                .exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.2", "0.9", "art22-2", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.5", "art21A", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.5", "art21B", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.1", "0.5", "art21AB", "jar", "jar")
                .exists());
        assertTrue(getArchiveFileInCache("org2", "mod2.8", "0.6", "art28-linux-debug-thread",
            "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.8", "0.6", "art28-linux-debug", "jar",
            "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.8", "0.6", "art28-windows-debug-thread",
            "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org2", "mod2.8", "0.6", "art28-windows-debug", "jar",
            "jar").exists());
    }

    @Test
    public void testResolveFallbackConfiguration() throws Exception {
        // mod10.2 depends on mod5.1 conf runtime(default)
        ivy.resolve(new File("test/repositories/2/mod10.2/ivy-1.0.xml"),
            getResolveOptions(new String[] {"*"}));

        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.0", "art51A", "jar", "jar").exists());
    }

    @Test
    public void testResolveFallbackConfiguration2() throws Exception {
        // mod10.2 depends on mod5.1 conf runtime(*)
        ivy.resolve(new File("test/repositories/2/mod10.2/ivy-1.1.xml"),
            getResolveOptions(new String[] {"*"}));

        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.0", "art51A", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.0", "art51B", "jar", "jar").exists());
    }

    @Test
    public void testResolveFallbackConfiguration3() throws Exception {
        // mod10.2 depends on mod5.1 conf runtime(*),compile(*)
        ivy.resolve(new File("test/repositories/2/mod10.2/ivy-1.2.xml"),
            getResolveOptions(new String[] {"*"}));

        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.0", "art51A", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache("org5", "mod5.1", "4.0", "art51B", "jar", "jar").exists());
    }

    @Test
    public void testResolveFallbackConfiguration4() throws Exception {
        // mod10.2 depends on mod5.1 conf runtime()
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod10.2/ivy-1.3.xml"),
            getResolveOptions(new String[] {"*"}));
        assertFalse(report.hasError());

        assertFalse(getArchiveFileInCache("org5", "mod5.1", "4.0", "art51A", "jar", "jar").exists());
        assertFalse(getArchiveFileInCache("org5", "mod5.1", "4.0", "art51B", "jar", "jar").exists());
    }

    @Test
    public void testResolveMaven2() throws Exception {
        // test3 depends on test2 which depends on test
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/m2/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/m2/org/apache/test3/1.0/test3-1.0.pom"),
            getResolveOptions(new String[] {"test"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org.apache", "test3", "1.0");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org.apache", "test2", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache(ivy, "org.apache", "test2", "1.0", "test2", "jar", "jar")
                .exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org.apache", "test", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache(ivy, "org.apache", "test", "1.0", "test", "jar", "jar")
                .exists());
    }

    @Test
    public void testResolveMaven2WithConflict() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/m2/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/m2/org/apache/test3/1.1/test3-1.1.pom"),
            getResolveOptions(new String[] {"default"}));
        assertFalse(report.hasError());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org.apache", "test2", "1.1"))
                .exists());
        assertTrue(getArchiveFileInCache(ivy, "org.apache", "test2", "1.1", "test2", "jar", "jar")
                .exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org.apache", "test", "1.1"))
                .exists());
        assertTrue(getArchiveFileInCache(ivy, "org.apache", "test", "1.1", "test", "jar", "jar")
                .exists());

        assertContainsArtifact(report.getConfigurationReport("default"),
            getArtifact("org.apache", "test2", "1.1", "test2", "jar", "jar"));
        assertContainsArtifact(report.getConfigurationReport("default"),
            getArtifact("org.apache", "test", "1.1", "test", "jar", "jar"));
    }

    @Test
    public void testResolveMaven2WithConflict2() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/m2/ivysettings.xml"));
        ResolveReport report = ivy.resolve(ResolveTest.class.getResource("ivy-874.xml"),
            getResolveOptions(new String[] {"default"}));
        assertFalse(report.hasError());

        assertContainsArtifact(report.getConfigurationReport("default"),
            getArtifact("org.apache", "test3", "1.1", "test3", "jar", "jar"));
        assertContainsArtifact(report.getConfigurationReport("default"),
            getArtifact("org.apache", "test2", "1.1", "test2", "jar", "jar"));
        assertContainsArtifact(report.getConfigurationReport("default"),
            getArtifact("org.apache", "test", "1.2", "test", "jar", "jar"));
    }

    @Test
    public void testResolveMaven2RelocationOfGroupId() throws Exception {
        // Same as testResolveMaven2 but with a relocated module pointing to the module
        // used in testResolveMaven2.
        ivy = new Ivy();
        ivy.configure(new File("test/repositories/m2/ivysettings.xml"));
        ivy.pushContext();
        try {
            ResolveReport report = ivy.resolve(new File(
                    "test/repositories/m2/org/relocated/test3/1.0/test3-1.0.pom"),
                getResolveOptions(new String[] {"*"}));
            assertNotNull(report);

            // dependencies
            assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org.apache", "test2", "1.0"))
                    .exists());
            assertTrue(getArchiveFileInCache(ivy, "org.apache", "test2", "1.0", "test2", "jar",
                "jar").exists());

            assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org.apache", "test", "1.0"))
                    .exists());
            assertTrue(getArchiveFileInCache(ivy, "org.apache", "test", "1.0", "test", "jar", "jar")
                    .exists());
        } finally {
            ivy.popContext();
        }
    }

    @Test
    public void testResolveMaven2FullRelocation() throws Exception {
        // Same as testResolveMaven2 but with a relocated module pointing to the module
        // used in testResolveMaven2.
        ivy = new Ivy();
        ivy.configure(new File("test/repositories/m2/ivysettings.xml"));
        ivy.pushContext();
        try {
            ResolveReport report = ivy.resolve(new File(
                    "test/repositories/m2/org/relocated/test3full/1.1/test3full-1.1.pom"),
                getResolveOptions(new String[] {"*"}));
            assertNotNull(report);

            // dependencies
            assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org.apache", "test2", "1.0"))
                    .exists());
            assertTrue(getArchiveFileInCache(ivy, "org.apache", "test2", "1.0", "test2", "jar",
                "jar").exists());

            assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org.apache", "test", "1.0"))
                    .exists());
            assertTrue(getArchiveFileInCache(ivy, "org.apache", "test", "1.0", "test", "jar", "jar")
                    .exists());
        } finally {
            ivy.popContext();
        }
    }

    @Test
    public void testResolveVersionRelocationChainedWithGroupRelocation() throws Exception {
        ivy = new Ivy();
        ivy.configure(new File("test/repositories/m2/ivysettings.xml"));
        ivy.pushContext();
        try {
            ResolveReport report = ivy.resolve(new File(
                    "test/repositories/m2/org/relocated/test3/1.1/test3-1.1.pom"),
                getResolveOptions(new String[] {"*"}));
            assertNotNull(report);

            // dependencies
            assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org.apache", "test2", "1.0"))
                    .exists());
            assertTrue(getArchiveFileInCache(ivy, "org.apache", "test2", "1.0", "test2", "jar",
                "jar").exists());

            assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org.apache", "test", "1.0"))
                    .exists());
            assertTrue(getArchiveFileInCache(ivy, "org.apache", "test", "1.0", "test", "jar", "jar")
                    .exists());
        } finally {
            ivy.popContext();
        }
    }

    @Test
    public void testResolveTransitivelyToRelocatedPom() throws Exception {
        ivy = new Ivy();
        ivy.configure(new File("test/repositories/m2/ivysettings.xml"));
        ivy.pushContext();
        try {
            ResolveReport report = ivy.resolve(new File(
                    "test/repositories/m2/org/relocated/testRelocationUser/1.0/"
                            + "testRelocationUser-1.0.pom"),
                getResolveOptions(new String[] {"compile"}));
            assertNotNull(report);
            assertFalse(report.hasError());
            // dependencies
            assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org.apache", "test2", "1.0"))
                    .exists());
            assertTrue(getArchiveFileInCache(ivy, "org.apache", "test2", "1.0", "test2", "jar",
                "jar").exists());

            assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org.apache", "test", "1.0"))
                    .exists());
            assertTrue(getArchiveFileInCache(ivy, "org.apache", "test", "1.0", "test", "jar", "jar")
                    .exists());
        } finally {
            ivy.popContext();
        }
    }

    @Test
    public void testResolveTransitivelyToPomRelocatedToNewVersion() throws Exception {
        ivy = new Ivy();
        ivy.configure(new File("test/repositories/m2/ivysettings.xml"));
        ivy.pushContext();
        try {
            ResolveReport report = ivy.resolve(new File(
                    "test/repositories/m2/org/relocated/testRelocationUser/1.1/"
                            + "testRelocationUser-1.1.pom"),
                getResolveOptions(new String[] {"compile"}));
            assertNotNull(report);
            assertFalse(report.hasError());
            // dependencies
            assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org.apache", "test2", "1.0"))
                    .exists());
            assertTrue(getArchiveFileInCache(ivy, "org.apache", "test2", "1.0", "test2", "jar",
                "jar").exists());

            assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org.apache", "test", "1.0"))
                    .exists());
            assertTrue(getArchiveFileInCache(ivy, "org.apache", "test", "1.0", "test", "jar", "jar")
                    .exists());
        } finally {
            ivy.popContext();
        }
    }

    /**
     * Test case for IVY-418.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-418">IVY-418</a>
     */
    @Test
    public void testResolveMaven2Classifiers() throws Exception {
        // test-classifier depends on test-classified with classifier asl
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/m2/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/m2/org/apache/test-classifier/1.0/test-classifier-1.0.pom"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId
                .newInstance("org.apache", "test-classifier", "1.0");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(
            ModuleRevisionId.newInstance("org.apache", "test-classified", "1.0")).exists());

        Map<String, String> cmap = new HashMap<>();
        cmap.put("classifier", "asl");
        assertTrue(getArchiveFileInCache(ivy, "org.apache", "test-classified", /* branch */ null,
            "1.0", "test-classified", "jar", "jar", cmap).exists());
    }

    /**
     * Test case for IVY-1041.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-1041">IVY-1041</a>
     */
    @Test
    public void testResolveMaven2ClassifiersWithoutPOM() throws Exception {
        // test-classifier depends on test-classified with classifier asl
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/m2/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/m2/org/apache/test-classifier/2.0/test-classifier-2.0.pom"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId
                .newInstance("org.apache", "test-classifier", "2.0");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        File depIvyFileInCache = getIvyFileInCache(
            ModuleRevisionId.newInstance("org.apache", "test-classified", "2.0"));
        assertTrue(depIvyFileInCache.exists());

        // validate the cached Ivy file (IVY-1649)
        XmlModuleDescriptorParser.getInstance().parseDescriptor(ivy.getSettings(),
                                                                depIvyFileInCache.toURI().toURL(),
                                                                true);

        Map<String, String> cmap = new HashMap<>();
        cmap.put("classifier", "asl");
        assertTrue(getArchiveFileInCache(ivy, "org.apache", "test-classified", /* branch */ null,
            "2.0", "test-classified", "jar", "jar", cmap).exists());
    }

    @Test
    public void testResolveMaven2GetSources() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/m2/ivysettings.xml"));
        ResolveReport report = ivy.resolve(
            ResolveTest.class.getResource("ivy-m2-with-sources.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        assertFalse(report.hasError());

        assertTrue(getIvyFileInCache(
            ModuleRevisionId.newInstance("org.apache", "test-sources", "1.0")).exists());
        File jarFileInCache = getArchiveFileInCache(ivy, "org.apache", "test-sources", "1.0",
            "test-sources", "jar", "jar");
        assertTrue(jarFileInCache.exists());
        File sourceFileInCache = getArchiveFileInCache(ivy, "org.apache", "test-sources", null,
            "1.0", "test-sources", "source", "jar",
            Collections.singletonMap("classifier", "sources"));
        assertTrue(sourceFileInCache.exists());
        assertTrue(jarFileInCache.length() != sourceFileInCache.length());
    }

    /**
     * Test case for IVY-1138.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-1138">IVY-1138</a>
     */
    @Test
    public void testResolveMaven2GetSourcesWithSrcClassifier() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/m2/ivysettings.xml"));
        ResolveReport report = ivy.resolve(ResolveTest.class.getResource("ivy-m2-with-src.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        assertFalse(report.hasError());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org.apache", "test-src", "1.0"))
                .exists());
        File jarFileInCache = getArchiveFileInCache(ivy, "org.apache", "test-src", "1.0",
            "test-src", "jar", "jar");
        assertTrue(jarFileInCache.exists());
        File sourceFileInCache = getArchiveFileInCache(ivy, "org.apache", "test-src", null, "1.0",
            "test-src", "source", "jar", Collections.singletonMap("classifier", "src"));
        assertTrue(sourceFileInCache.exists());
        assertTrue(jarFileInCache.length() != sourceFileInCache.length());
    }

    @Test
    public void testResolveMaven2GetSourcesAndJavadocAuto() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/m2/ivysettings.xml"));
        ResolveReport report = ivy.resolve(
            ResolveTest.class.getResource("ivy-m2-with-sources-and-javadoc-auto.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        assertFalse(report.hasError());

        assertTrue(getIvyFileInCache(
            ModuleRevisionId.newInstance("org.apache", "test-sources", "1.0")).exists());
        File jarFileInCache = getArchiveFileInCache(ivy, "org.apache", "test-sources", "1.0",
            "test-sources", "jar", "jar");
        assertTrue(jarFileInCache.exists());
        File sourceFileInCache = getArchiveFileInCache(ivy, "org.apache", "test-sources", null,
            "1.0", "test-sources", "source", "jar",
            Collections.singletonMap("classifier", "sources"));
        assertTrue(sourceFileInCache.exists());
        assertTrue(jarFileInCache.length() != sourceFileInCache.length());
        File javadocFileInCache = getArchiveFileInCache(ivy, "org.apache", "test-sources", null,
            "1.0", "test-sources", "javadoc", "jar",
            Collections.singletonMap("classifier", "javadoc"));
        assertTrue(javadocFileInCache.exists());
        assertTrue(jarFileInCache.length() != javadocFileInCache.length());
    }

    @Test
    public void testResolveMaven2WithVersionProperty() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/m2/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/m2/org/apache/test-version/1.0/test-version-1.0.pom"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org.apache", "test-version", "1.0");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(
            ModuleRevisionId.newInstance("org.apache", "test-classifier", "1.0")).exists());
        assertTrue(getArchiveFileInCache(ivy, "org.apache", "test-classifier", "1.0",
            "test-classifier", "jar", "jar").exists());
    }

    @Test
    public void testResolveMaven2ParentPomChainResolver() throws Exception {
        // test has a dependency on test2 but there is no version listed. test has a parent of
        // parent(2.0)
        // then parent2. Both parents have a dependencyManagement element for test2, and each list
        // the version as
        // ${pom.version}. The parent version should take precedence over parent2,
        // so the version should be test2 version 2.0. Test3 is also a dependency of parent, and
        // it's version is listed
        // as 1.0 in parent2 (dependencies inherited from parent comes after).
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/parentPom/ivysettings.xml"));
        ivy.getSettings().setDefaultResolver("parentChain");

        ResolveReport report = ivy.resolve(new File(
                "test/repositories/parentPom/org/apache/dm/test/1.0/test-1.0.pom"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org.apache.dm", "test", "1.0");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // test the report to make sure the right dependencies are listed
        List<IvyNode> dependencies = report.getDependencies();
        assertEquals(2, dependencies.size());

        IvyNode ivyNode;
        ivyNode = dependencies.get(0);
        assertNotNull(ivyNode);

        // Bad assertions based on IVY-1301 bug, corrected below:
        // mrid = ModuleRevisionId.newInstance("org.apache.dm", "test2", "2.0");
        // assertEquals(mrid, ivyNode.getId());
        // // dependencies
        // assertTrue(getIvyFileInCache(
        // ModuleRevisionId.newInstance("org.apache.dm", "test2", "2.0")).exists());
        // assertTrue(getArchiveFileInCache(ivy, "org.apache.dm", "test2", "2.0",
        // "test2", "jar", "jar").exists());

        mrid = ModuleRevisionId.newInstance("org.apache.dm", "test2", "1.0");
        assertEquals(mrid, ivyNode.getId());
        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org.apache.dm", "test2", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache(ivy, "org.apache.dm", "test2", "1.0", "test2", "jar",
            "jar").exists());

        ivyNode = dependencies.get(1);
        assertNotNull(ivyNode);
        mrid = ModuleRevisionId.newInstance("org.apache.dm", "test3", "1.0");
        assertEquals(mrid, ivyNode.getId());
        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org.apache.dm", "test3", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache(ivy, "org.apache.dm", "test3", "1.0", "test3", "jar",
            "jar").exists());
    }

    @Test
    public void testErrorResolveMaven2ParentPomWithCycle() throws Exception {
        // IVY-1545
        // test6 has parent parent4, parent4 parent is parent5, parent5 parent is parent4, a cycle.
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/parentPom/ivysettings.xml"));
        ivy.getSettings().setDefaultResolver("parentChain");

        try {
            ivy.resolve(
                new File("test/repositories/parentPom/org/apache/dm/test6/1.0/test6-1.0.pom"),
                getResolveOptions(new String[] {"*"}));

            // don't expect to get here, should suffer StackOverflowError if cycle is not detected
            fail("Expected CircularDependencyException from parent cycle detection");
        } catch (CircularDependencyException e) {
            // ok
            assertEquals("org.apache.dm#parent4;1.0->org.apache.dm#parent5;1.0", e.getMessage());
        }
    }

    /**
     * Tests that when a pom {@code A1} has a {@code dependencyManagement} section with a {@code import} scoped
     * dependency and such a dependency has the same parent {@code P}, as {@code A1}, then a {@link CircularDependencyException}
     * isn't thrown
     *
     * @throws Exception
     * @see <a href="https://issues.apache.org/jira/browse/IVY-1588">IVY-1588</a> for more details
     */
    @Test
    public void testDepMgmtImportWithSameParent() throws Exception {
        // - sibling1 has parent "org.apache.dm:parent:1.0"
        // - sibling1 further has dependencyManagement section with a dependency on sibling2 with scope=import
        // - sibling2 has parent "org.apache.dm:parent:1.0" (same parent as sibling1)
        // This should *not* trigger a CircularDependencyException for the parent
        final Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/parentPom/ivysettings.xml"));
        ivy.getSettings().setDefaultResolver("parentChain");
        final File pom = new File("test/repositories/parentPom/org/apache/dm/sibling1/1.0/sibling1-1.0.pom");
        final ResolveReport report = ivy.resolve(pom, getResolveOptions(new String[]{"*"}));
        assertNotNull("Resolve report is null", report);
        assertFalse("Resolve report has errors", report.hasError());
    }

    @Test
    public void testErrorResolveMaven2SelfAsParent() throws Exception {
        // IVY-1545
        // test7 has parent == self
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/parentPom/ivysettings.xml"));
        ivy.getSettings().setDefaultResolver("parentChain");

        try {
            ivy.resolve(
                new File("test/repositories/parentPom/org/apache/dm/test7/1.0/test7-1.0.pom"),
                getResolveOptions(new String[] {"*"}));

            // don't expect to get here, should suffer StackOverflowError if cycle is not detected
            fail("Expected CircularDependencyException from parent cycle detection");
        } catch (CircularDependencyException e) {
            // ok
            assertEquals("org.apache.dm#test7;1.0", e.getMessage());
        }
    }

    /**
     * Test case for IVY-1186.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-1186">IVY-1186</a>
     */
    @Test
    public void testResolveMaven2ParentPomWithNamespace() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/parentPom/ivysettings-namespace.xml"));

        ResolveReport report = ivy.resolve(
            ModuleRevisionId.newInstance("org.apache.systemDm", "test", "1.0"),
            getResolveOptions(new String[] {"*(public)"}), true);
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        // assertEquals(mrid, md.getModuleRevisionId());
        // assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // test the report to make sure the right dependencies are listed
        List<IvyNode> dependencies = report.getDependencies();
        assertEquals(3, dependencies.size()); // the test module + it's 2 dependencies

        IvyNode ivyNode = dependencies.get(0);
        assertNotNull(ivyNode);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org.apache.systemDm", "test", "1.0");
        assertEquals(mrid, ivyNode.getId());
        // dependencies
        assertTrue(getIvyFileInCache(
            ModuleRevisionId.newInstance("org.apache.systemDm", "test", "1.0")).exists());
        assertTrue(getArchiveFileInCache(ivy, "org.apache.systemDm", "test", "1.0", "test", "jar",
            "jar").exists());

        ivyNode = dependencies.get(1);
        assertNotNull(ivyNode);
        mrid = ModuleRevisionId.newInstance("org.apache.systemDm", "test2", "2.0");
        assertEquals(mrid, ivyNode.getId());
        // dependencies
        assertTrue(getIvyFileInCache(
            ModuleRevisionId.newInstance("org.apache.systemDm", "test2", "2.0")).exists());
        assertTrue(getArchiveFileInCache(ivy, "org.apache.systemDm", "test2", "2.0", "test2",
            "jar", "jar").exists());

        ivyNode = dependencies.get(2);
        assertNotNull(ivyNode);
        mrid = ModuleRevisionId.newInstance("org.apache.systemDm", "test3", "1.0");
        assertEquals(mrid, ivyNode.getId());
        // dependencies
        assertTrue(getIvyFileInCache(
            ModuleRevisionId.newInstance("org.apache.systemDm", "test3", "1.0")).exists());
        assertTrue(getArchiveFileInCache(ivy, "org.apache.systemDm", "test3", "1.0", "test3",
            "jar", "jar").exists());
    }

    @Test
    public void testResolveMaven2ParentPomDualResolver() throws Exception {
        // test has a dependency on test2 but there is no version listed. test
        // has a parent of parent(2.0) then parent2. Both parents have a
        // dependencyManagement element for test2, and each list the version as
        // ${pom.version}. The parent version should take precedence over
        // parent2, so the version should be test2 version 2.0. Test3 is also a
        // dependency of parent, and it's version is listed
        // as 1.0 in parent2. (dependencies inherited from parent comes after)

        // now run tests with dual resolver
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/parentPom/ivysettings.xml"));
        ivy.getSettings().setDefaultResolver("parentDual");

        ResolveReport report = ivy.resolve(new File(
                "test/repositories/parentPom/org/apache/dm/test/1.0/test-1.0.pom"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org.apache.dm", "test", "1.0");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // test the report to make sure the right dependencies are listed
        List<IvyNode> dependencies = report.getDependencies();
        assertEquals(2, dependencies.size());

        IvyNode ivyNode;
        ivyNode = dependencies.get(0);
        assertNotNull(ivyNode);

        // Bad assertions based on IVY-1301 bug, corrected below:
        // mrid = ModuleRevisionId.newInstance("org.apache.dm", "test2", "2.0");
        // assertEquals(mrid, ivyNode.getId());
        // // dependencies
        // assertTrue(getIvyFileInCache(
        // ModuleRevisionId.newInstance("org.apache.dm", "test2", "2.0")).exists());
        // assertTrue(getArchiveFileInCache(ivy, "org.apache.dm", "test2", "2.0",
        // "test2", "jar", "jar").exists());

        mrid = ModuleRevisionId.newInstance("org.apache.dm", "test2", "1.0");
        assertEquals(mrid, ivyNode.getId());
        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org.apache.dm", "test2", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache(ivy, "org.apache.dm", "test2", "1.0", "test2", "jar",
            "jar").exists());

        ivyNode = dependencies.get(1);
        assertNotNull(ivyNode);
        mrid = ModuleRevisionId.newInstance("org.apache.dm", "test3", "1.0");
        assertEquals(mrid, ivyNode.getId());
        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org.apache.dm", "test3", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache(ivy, "org.apache.dm", "test3", "1.0", "test3", "jar",
            "jar").exists());
    }

    @Test
    public void testResolveMaven2ParentPomDependencyManagementOverrideTransitiveVersion()
            throws Exception {
        // test;2.0 has a dependency on test2;3.0.
        // test has a parent of parent(2.0) then parent2.
        // Both parents have a dependencyManagement element for test2, and each
        // list the version as ${pom.version}. The version for test2 in test
        // should take precedence, so the version should be test2 version 3.0.
        // test2;3.0 -> test4;2.0, but parent has a dependencyManagement
        // section specifying test4;1.0.
        // since maven 2.0.6, the information in parent should override
        // transitive dependency version, and thus we should get test4;1.0
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/parentPom/ivysettings.xml"));
        ivy.getSettings().setDefaultResolver("parentChain");

        ResolveReport report = ivy.resolve(new File(
                "test/repositories/parentPom/org/apache/dm/test/2.0/test-2.0.pom"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);

        // test the report to make sure the right dependencies are listed
        List<IvyNode> dependencies = report.getDependencies();
        assertEquals(3, dependencies.size());

        IvyNode ivyNode;
        ivyNode = dependencies.get(0);
        assertNotNull(ivyNode);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org.apache.dm", "test2", "3.0");
        assertEquals(mrid, ivyNode.getId());
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org.apache.dm", "test2", "3.0"))
                .exists());
        assertTrue(getArchiveFileInCache(ivy, "org.apache.dm", "test2", "3.0", "test2", "jar",
            "jar").exists());

        ivyNode = dependencies.get(2);
        assertNotNull(ivyNode);
        mrid = ModuleRevisionId.newInstance("org.apache.dm", "test4", "1.0");
        assertEquals(mrid, ivyNode.getId());
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org.apache.dm", "test4", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache(ivy, "org.apache.dm", "test4", "1.0", "test4", "jar",
            "jar").exists());
    }

    /**
     * Test case for IVY-1376.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-1376">IVY-1376</a>
     */
    @Test
    public void testResolveMaven2ParentPomDependencyManagementWithImport() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/parentPom/ivysettings.xml"));
        ivy.getSettings().setDefaultResolver("parentChain");

        ResolveReport report = ivy.resolve(new File(
                "test/repositories/parentPom/org/apache/dm/test/3.0/test-3.0.pom"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);

        // test the report to make sure the right dependencies are listed
        List<IvyNode> dependencies = report.getDependencies();
        assertFalse(report.hasError());
        assertEquals(2, dependencies.size());

        IvyNode ivyNode;
        ivyNode = dependencies.get(0);
        assertNotNull(ivyNode);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("org.apache.dm", "test5", "2.0");
        assertEquals(mrid, ivyNode.getId());
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org.apache.dm", "test5", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache(ivy, "org.apache.dm", "test5", "2.0", "test5", "jar",
            "jar").exists());
    }

    /**
     * Test case for IVY-501.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-501">IVY-501</a>
     */
    @Test
    public void testResolveMaven2Snapshot1() throws Exception {
        // here we test maven SNAPSHOT versions handling,
        // with m2 snapshotRepository/uniqueVersion set to true
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/m2/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/m2/org/apache/test4/1.0/test4-1.0.pom"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        assertFalse(report.hasError());

        // dependencies
        assertTrue(getIvyFileInCache(
            ModuleRevisionId.newInstance("org.apache", "test-SNAPSHOT1", "2.0.2-SNAPSHOT"))
                .exists());
        assertTrue(getArchiveFileInCache(ivy, "org.apache", "test-SNAPSHOT1", "2.0.2-SNAPSHOT",
            "test-SNAPSHOT1", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-1036.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-1036">IVY-1036</a>
     */
    @Test
    public void testResolveMaven2Snapshot1AsLatestIntegration() throws Exception {
        // here we test maven SNAPSHOT versions handling,
        // with m2 snapshotRepository/uniqueVersion set to true
        // but retrieving by latest.integration
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/m2/ivysettings.xml"));
        ResolveReport report = ivy.resolve(
            ModuleRevisionId.newInstance("org.apache", "test-SNAPSHOT1", "latest.integration"),
            getResolveOptions(new String[] {"*(public)"}), true);
        assertNotNull(report);
        assertFalse(report.hasError());

        // dependencies
        assertTrue(getIvyFileInCache(
            ModuleRevisionId.newInstance("org.apache", "test-SNAPSHOT1", "2.0.2-SNAPSHOT"))
                .exists());
        assertTrue(getArchiveFileInCache(ivy, "org.apache", "test-SNAPSHOT1", "2.0.2-SNAPSHOT",
            "test-SNAPSHOT1", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-501.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-501">IVY-501</a>
     */
    @Test
    public void testResolveMaven2Snapshot2() throws Exception {
        // here we test maven SNAPSHOT versions handling,
        // without m2 snapshotRepository/uniqueVersion set to true
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/m2/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/m2/org/apache/test4/1.1/test4-1.1.pom"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        assertFalse(report.hasError());

        // dependencies
        assertTrue(getIvyFileInCache(
            ModuleRevisionId.newInstance("org.apache", "test-SNAPSHOT2", "2.0.2-SNAPSHOT"))
                .exists());
        assertTrue(getArchiveFileInCache(ivy, "org.apache", "test-SNAPSHOT2", "2.0.2-SNAPSHOT",
            "test-SNAPSHOT2", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-1036.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-1036">IVY-1036</a>
     */
    @Test
    public void testResolveMaven2Snapshot2AsLatestIntegration() throws Exception {
        // here we test maven SNAPSHOT versions handling,
        // with m2 snapshotRepository/uniqueVersion set to true
        // but retrieving by latest.integration
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/m2/ivysettings.xml"));
        ResolveReport report = ivy.resolve(
            ModuleRevisionId.newInstance("org.apache", "test-SNAPSHOT2", "latest.integration"),
            getResolveOptions(new String[] {"*(public)"}), true);
        assertNotNull(report);
        assertFalse(report.hasError());

        // dependencies
        assertTrue(getIvyFileInCache(
            ModuleRevisionId.newInstance("org.apache", "test-SNAPSHOT2", "2.0.2-SNAPSHOT"))
                .exists());
        assertTrue(getArchiveFileInCache(ivy, "org.apache", "test-SNAPSHOT2", "2.0.2-SNAPSHOT",
            "test-SNAPSHOT2", "jar", "jar").exists());
    }

    @Test
    public void testNamespaceMapping() throws Exception {
        // the dependency is in another namespace
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/namespace/ivysettings.xml"));
        ResolveReport report = ivy.resolve(ResolveTest.class.getResource("ivy-namespace.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("apache", "namespace", "1.0");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // ivy file
        File ivyFile = getIvyFileInCache(ModuleRevisionId.newInstance("systemorg", "systemmod",
            "1.0"));
        assertTrue(ivyFile.exists());
        ModuleDescriptor parsedMD = XmlModuleDescriptorParser.getInstance().parseDescriptor(
            ivy.getSettings(), ivyFile.toURI().toURL(), true);
        assertEquals("systemorg", parsedMD.getModuleRevisionId().getOrganisation());
        assertEquals("systemmod", parsedMD.getModuleRevisionId().getName());

        // dependencies
        assertTrue(getArchiveFileInCache(ivy, "systemorg", "systemmod", "1.0", "A", "jar", "jar")
                .exists());
    }

    @Test
    public void testNamespaceMapping2() throws Exception {
        // the dependency is in another namespace and has itself a dependency on a module available
        // in the same namespace
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/namespace/ivysettings.xml"));
        ResolveReport report = ivy.resolve(ResolveTest.class.getResource("ivy-namespace2.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("apache", "namespace", "2.0");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("systemorg", "systemmod2", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache(ivy, "systemorg", "systemmod2", "1.0", "B", "jar", "jar")
                .exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("systemorg", "systemmod", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache(ivy, "systemorg", "systemmod", "1.0", "A", "jar", "jar")
                .exists());
    }

    @Test
    public void testNamespaceMapping3() throws Exception {
        // same as 2 but with poms
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/namespace/ivysettings.xml"));
        ResolveReport report = ivy.resolve(ResolveTest.class.getResource("ivy-namespace3.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("apache", "namespace", "3.0");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(getResolvedIvyFileInCache(mrid).exists());

        // dependencies
        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("systemorg2", "system-2", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache(ivy, "systemorg2", "system-2", "1.0", "2", "jar", "jar")
                .exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("systemorg2", "system-1", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache(ivy, "systemorg2", "system-1", "1.0", "1", "jar", "jar")
                .exists());
    }

    @Test
    public void testNamespaceMapping4() throws Exception {
        // same as 2 but with incorrect dependency asked: the first ivy file asks for a dependency
        // in the resolver namespace and not the system one: this should fail
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/namespace/ivysettings.xml"));
        ResolveReport report = ivy.resolve(ResolveTest.class.getResource("ivy-namespace4.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleDescriptor md = report.getModuleDescriptor();
        assertNotNull(md);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("apache", "namespace", "4.0");
        assertEquals(mrid, md.getModuleRevisionId());

        assertTrue(report.hasError());
    }

    @Test
    public void testNamespaceMapping5() throws Exception {
        // Verifies that mapping version numbers works
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/namespace/ivysettings.xml"));
        ResolveReport report = ivy.resolve(ResolveTest.class.getResource("ivy-namespace5.xml"),
            getResolveOptions(new String[] {"*"}));
        assertNotNull(report);
        ModuleRevisionId mrid = ModuleRevisionId.newInstance("systemorg3", "systemmod3", "1.0");
        assertTrue(getIvyFileInCache(mrid).exists());
    }

    /**
     * Test case for IVY-1151.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-1151">IVY-1151</a>
     */
    @Test
    public void testIVY151() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/multirevisions/ivysettings.xml"));
        ResolveReport report = ivy.resolve(new File("test/repositories/multirevisions/ivy.xml"),
            getResolveOptions(new String[] {"compile", "test"}));

        assertNotNull(report);
        assertNotNull(report.getUnresolvedDependencies());
        assertEquals("Number of unresolved dependencies not correct", 0,
            report.getUnresolvedDependencies().length);
    }

    @Test
    public void testCheckRevision() throws Exception {
        // mod12.2 depends on mod12.1 1.0 which depends on mod1.2
        // mod12.1 doesn't have revision in its ivy file
        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod12.2/ivy-1.0.xml"),
            getResolveOptions(new String[] {"*"}));

        assertTrue(report.hasError());

        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org12", "mod12.1", "1.0"))
                .exists());
        assertFalse(getArchiveFileInCache("org12", "mod12.1", "1.0", "mod12.1", "jar", "jar")
                .exists());

        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
    }

    @Test
    public void testTrustRevision() throws Exception {
        // mod12.2 depends on mod12.1 1.0 which depends on mod1.2
        // mod12.1 doesn't have revision in its ivy file

        ((BasicResolver) ivy.getSettings().getResolver("2-ivy")).setCheckconsistency(false);

        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod12.2/ivy-1.0.xml"),
            getResolveOptions(new String[] {"*"}));

        assertFalse(report.hasError());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org12", "mod12.1", "1.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org12", "mod12.1", "1.0", "mod12.1", "jar", "jar")
                .exists());

        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
                .exists());
        assertTrue(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-168.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-168">IVY-168</a>
     */
    @Test
    public void testTransitiveConfMapping() throws Exception {
        // mod13.3 depends on mod13.2 which depends on mod13.1
        // each module has two confs: j2ee and compile
        // each module only publishes one artifact in conf compile
        // each module has the following conf mapping on its dependencies: *->@
        // moreover, mod13.1 depends on mod1.2 in with the following conf mapping: compile->default
        // thus conf j2ee should be empty for each modules

        ResolveReport report = ivy.resolve(new File("test/repositories/2/mod13.3/ivy-1.0.xml"),
            getResolveOptions(new String[] {"*"}));

        assertFalse(report.hasError());

        assertEquals(3, report.getConfigurationReport("compile").getArtifactsNumber());
        assertEquals(0, report.getConfigurationReport("j2ee").getArtifactsNumber());
    }

    @Test
    public void testExtraAttributes() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/extra-attributes/ivysettings.xml"));
        ivy.getSettings().setDefaultCache(cache);

        FileSystemResolver fResolver = (FileSystemResolver) ivy.getSettings().getDefaultResolver();
        fResolver.setCheckconsistency(false); // important for testing IVY-929

        ResolveReport report = ivy.resolve(ResolveTest.class.getResource("ivy-extra-att.xml"),
            getResolveOptions(ivy.getSettings(), new String[] {"*"}).setValidate(false));
        assertFalse(report.hasError());

        assertTrue(new File(cache, "apache/mymodule/task1/1854/ivy.xml").exists());
        assertTrue(new File(cache, "apache/mymodule/task1/1854/mymodule-windows.jar").exists());
        assertTrue(new File(cache, "apache/mymodule/task1/1854/mymodule-linux.jar").exists());

        Set<ModuleRevisionId> moduleRevisions = report.getConfigurationReport("default")
                .getModuleRevisionIds();
        assertEquals(1, moduleRevisions.size());
        ModuleRevisionId resolveModRevId = moduleRevisions.iterator().next();
        assertEquals("apache", resolveModRevId.getOrganisation());
        assertEquals("mymodule", resolveModRevId.getName());
        assertEquals("1854", resolveModRevId.getRevision());
        assertEquals("task1", resolveModRevId.getExtraAttribute("eatt"));
        assertEquals("another", resolveModRevId.getExtraAttribute("eatt2"));
    }

    /**
     * Test case for IVY-773.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-773">IVY-773</a>
     */
    @Test
    public void testExtraAttributes2() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/extra-attributes/ivysettings.xml"));
        ivy.getSettings().setDefaultCache(cache);
        ivy.getSettings().validate();

        ResolveReport report = ivy.resolve(ResolveTest.class.getResource("ivy-extra-att2.xml"),
            getResolveOptions(ivy.getSettings(), new String[] {"*"}).setValidate(false));
        assertFalse(report.hasError());

        assertTrue(new File(cache, "apache/mymodule/task2/1748/ivy.xml").exists());
        assertTrue(new File(cache, "apache/mymodule/task2/1748/ivy.xml.original").exists());
        assertTrue(new File(cache, "apache/mymodule/task2/1748/mymodule-windows.jar").exists());
        assertTrue(new File(cache, "apache/mymodule/task2/1748/mymodule-linux.jar").exists());

        assertTrue(new File(cache, "apache/module2/task2/1976/ivy.xml").exists());
        assertTrue(new File(cache, "apache/module2/task2/1976/module2-windows.jar").exists());
        assertTrue(new File(cache, "apache/module2/task2/1976/module2-linux.jar").exists());
    }

    /**
     * Test case for IVY-745.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-745">IVY-745</a>
     */
    @Test
    public void testExtraAttributes3() throws Exception {
        MockMessageLogger mockLogger = new MockMessageLogger();
        Ivy ivy = new Ivy();
        ivy.getLoggerEngine().setDefaultLogger(mockLogger);
        ivy.configure(new File("test/repositories/extra-attributes/ivysettings.xml"));
        ivy.getSettings().setDefaultCache(cache);
        ivy.getSettings().validate();

        ResolveReport report = ivy.resolve(ResolveTest.class.getResource("ivy-extra-att3.xml"),
            getResolveOptions(ivy.getSettings(), new String[] {"*"}).setValidate(false));

        assertTrue(report.hasError());
        // should report error about missing extra attribute in dependency module descriptor
        mockLogger.assertLogContains("expected='task2' found='null'");
    }

    /**
     * Second test case for IVY-745.¨
     * Now we disable consistency checking, everything must work fine.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-745">IVY-745</a>
     */
    @Test
    public void testExtraAttributes4() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/extra-attributes/ivysettings.xml"));
        ivy.getSettings().setDefaultCache(cache);
        ((FileSystemResolver) ivy.getSettings().getResolver("default")).setCheckconsistency(false);
        ivy.getSettings().validate();

        ResolveReport report = ivy.resolve(ResolveTest.class.getResource("ivy-extra-att3.xml"),
            getResolveOptions(ivy.getSettings(), new String[] {"*"}).setValidate(false));

        assertFalse(report.hasError());

        assertTrue(new File(cache, "apache/mymodule/task2/1749/ivy.xml").exists());
        assertTrue(new File(cache, "apache/mymodule/task2/1749/ivy.xml.original").exists());
        assertTrue(new File(cache, "apache/mymodule/task2/1749/mymodule-windows.jar").exists());
        assertTrue(new File(cache, "apache/mymodule/task2/1749/mymodule-linux.jar").exists());
    }

    @Test
    public void testNamespaceExtraAttributes() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/extra-attributes/ivysettings.xml"));
        ivy.getSettings().setDefaultCache(cache);

        ResolveReport report = ivy.resolve(ResolveTest.class.getResource("ivy-extra-att-ns.xml"),
            getResolveOptions(ivy.getSettings(), new String[] {"*"}).setValidate(true));
        assertFalse(report.hasError());

        assertTrue(new File(cache, "apache/mymodule/task1/1855/ivy.xml").exists());
        assertTrue(new File(cache, "apache/mymodule/task1/1855/mymodule-windows.jar").exists());
        assertTrue(new File(cache, "apache/mymodule/task1/1855/mymodule-linux.jar").exists());
    }

    @Test
    public void testBranches1() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/branches/ivysettings.xml"));

        ResolveReport report = ivy.resolve(new File(
                "test/repositories/branches/bar/bar1/trunk/1/ivy.xml"),
            getResolveOptions(new String[] {"*"}).setValidate(false));
        assertFalse(report.hasError());

        assertTrue(getArchiveFileInCache(ivy, "foo#foo1#trunk;3", "foo1", "jar", "jar").exists());
    }

    @Test
    public void testBranches2() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/branches/ivysettings.xml"));

        ResolveReport report = ivy.resolve(new File(
                "test/repositories/branches/bar/bar1/trunk/2/ivy.xml"),
            getResolveOptions(new String[] {"*"}).setValidate(false));
        assertFalse(report.hasError());

        assertTrue(getArchiveFileInCache(ivy, "foo#foo1#branch1;4", "foo1", "jar", "jar").exists());
    }

    @Test
    public void testBranches3() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/branches/ivysettings-defaultbranch1.xml"));

        ResolveReport report = ivy.resolve(new File(
                "test/repositories/branches/bar/bar1/trunk/1/ivy.xml"),
            getResolveOptions(new String[] {"*"}).setValidate(false));
        assertFalse(report.hasError());

        assertTrue(getArchiveFileInCache(ivy, "foo#foo1#branch1;4", "foo1", "jar", "jar").exists());
    }

    @Test
    public void testBranches4() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/branches/ivysettings.xml"));

        ResolveReport report = ivy.resolve(new File(
                "test/repositories/branches/bar/bar1/trunk/3/ivy.xml"),
            getResolveOptions(new String[] {"*"}).setValidate(false));
        assertFalse(report.hasError());

        assertTrue(getArchiveFileInCache(ivy, "foo#foo1#trunk;3", "foo1", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache(ivy, "bar#bar2#trunk;2", "bar2", "jar", "jar").exists());
    }

    @Test
    public void testBranches5() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/branches/ivysettings-fooonbranch1.xml"));

        ResolveReport report = ivy.resolve(new File(
                "test/repositories/branches/bar/bar1/trunk/3/ivy.xml"),
            getResolveOptions(new String[] {"*"}).setValidate(false));
        assertFalse(report.hasError());

        assertTrue(getArchiveFileInCache(ivy, "foo#foo1#branch1;4", "foo1", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache(ivy, "bar#bar2#trunk;2", "bar2", "jar", "jar").exists());
    }

    /**
     * Test case for IVY-717.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-717">IVY-717</a>
     */
    @Test
    public void testBranches6() throws Exception {
        // bar1;4 -> foo#foo1#${ivy.branch};5
        // foo#foo1#branch1;5 -> foo#foo2#${ivy.branch};1
        // foo#foo1#trunk;5 -> {}

        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/branches/ivysettings.xml"));

        ivy.setVariable("ivy.branch", "branch1");
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/branches/bar/bar1/trunk/4/ivy.xml"),
            getResolveOptions(new String[] {"*"}).setValidate(false));
        assertFalse(report.hasError());

        assertTrue(getArchiveFileInCache(ivy, "foo#foo1#branch1;5", "foo1", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache(ivy, "foo#foo2#branch1;1", "foo2", "jar", "jar").exists());

        ivy.setVariable("ivy.branch", "trunk");
        report = ivy.resolve(new File("test/repositories/branches/bar/bar1/trunk/4/ivy.xml"),
            getResolveOptions(new String[] {"*"}).setValidate(false));
        assertFalse(report.hasError());
        assertEquals(1, report.getConfigurationReport("default").getNodesNumber());
        assertTrue(getArchiveFileInCache(ivy, "foo#foo1#trunk;5", "foo1", "jar", "jar").exists());
    }

    @Test
    public void testExternalArtifacts() throws Exception {
        Ivy ivy = Ivy.newInstance();
        ivy.getSettings().setVariable("test.base.url",
            new File("test/repositories/external-artifacts").toURI().toURL().toExternalForm());
        ivy.configure(new File("test/repositories/external-artifacts/ivysettings.xml"));

        ResolveReport report = ivy.resolve(
            new File("test/repositories/external-artifacts/ivy.xml"),
            getResolveOptions(ivy.getSettings(), new String[] {"*"}).setValidate(false));
        assertFalse(report.hasError());

        assertTrue(getArchiveFileInCache(ivy, "apache", "A", "1.0", "a", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache(ivy, "apache", "B", "2.0", "b", "jar", "jar").exists());
        assertTrue(getArchiveFileInCache(ivy, "apache", "C", "3.0", "C", "jar", "jar").exists());
    }

    @Test
    public void testResolveWithMultipleIvyPatterns() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File("test/repositories/multi-ivypattern/ivysettings.xml"));

        ModuleRevisionId module = ModuleRevisionId.newInstance("org1", "mod1.1", "1.+");

        // use non-default options and settings
        ivy.getSettings().setDefaultUseOrigin(true);
        ResolveOptions options = getResolveOptions(ivy.getSettings(), new String[] {"*"});
        options.setTransitive(false);
        options.setDownload(false);
        ResolveReport report = ivy.getResolveEngine().resolve(module, options, false);

        List<IvyNode> dependencies = report.getDependencies();
        assertNotNull(dependencies);
        assertEquals(1, dependencies.size());
        IvyNode dependency = dependencies.get(0);
        assertEquals("1.1", dependency.getResolvedId().getRevision());
    }

    @Test
    public void testPrivateConfigurationTransferWhenConflict() throws Exception {
        ResolveReport report = ivy.resolve(new File(
                "test/repositories/1/orgConflictAndPrivateConf/root/ivys/ivy-1.0.xml"),
            getResolveOptions(new String[] {"assembly"}));
        assertFalse(report.hasError());
    }

    // //////////////////////////////////////////////////////////
    // helper methods to ease the tests
    // //////////////////////////////////////////////////////////

    private void assertContainsArtifact(String org, String module, String rev, String artName,
            String type, String ext, ConfigurationResolveReport conf) {
        Artifact art = getArtifact(org, module, rev, artName, type, ext);
        assertContainsArtifact(conf, art);
    }

    private void assertContainsArtifact(ConfigurationResolveReport conf, Artifact art) {
        assertTrue("artifact " + art + " should be part of " + conf.getConfiguration()
                + " from " + conf.getModuleDescriptor().getModuleRevisionId(),
                containsArtifact(art, conf.getDownloadedArtifactsReports()));
    }

    private void assertDoesntContainArtifact(String org, String module, String rev, String artName,
            String type, String ext, ConfigurationResolveReport conf) {
        Artifact art = getArtifact(org, module, rev, artName, type, ext);
        assertFalse("artifact " + art + " should NOT be part of " + conf.getConfiguration()
                + " from " + conf.getModuleDescriptor().getModuleRevisionId(),
                containsArtifact(art, conf.getDownloadedArtifactsReports()));
    }

    private Artifact getArtifact(String org, String module, String rev, String artName,
            String type, String ext) {
        return new DefaultArtifact(ModuleRevisionId.newInstance(org, module, rev), new Date(),
                artName, type, ext);
    }

    private boolean containsArtifact(Artifact art, ArtifactDownloadReport[] adrs) {
        for (ArtifactDownloadReport adr : adrs) {
            Artifact artifact = adr.getArtifact();
            if (artifact.getModuleRevisionId().equals(art.getModuleRevisionId())
                    && artifact.getName().equals(art.getName())
                    && artifact.getType().equals(art.getType())
                    && artifact.getExt().equals(art.getExt())) {
                return true;
            }
        }
        return false;
    }

    private String getArchivePathInCache(Artifact artifact) {
        return getRepositoryCacheManager(artifact.getModuleRevisionId()).getArchivePathInCache(
            artifact);
    }

    private String getArchivePathInCache(Artifact artifact, ArtifactOrigin origin) {
        return getRepositoryCacheManager(artifact.getModuleRevisionId()).getArchivePathInCache(
            artifact, origin);
    }

    private File getArchiveFileInCache(Artifact artifact) {
        return getRepositoryCacheManager(artifact.getModuleRevisionId()).getArchiveFileInCache(
            artifact);
    }

    private ArtifactOrigin getSavedArtifactOrigin(Artifact artifact) {
        return getRepositoryCacheManager(artifact.getModuleRevisionId()).getSavedArtifactOrigin(
            artifact);
    }

    private File getIvyFileInCache(ModuleRevisionId id) {
        return getRepositoryCacheManager(id).getIvyFileInCache(id);
    }

    private File getIvyFileInCache(Ivy ivy, ModuleRevisionId id) {
        return TestHelper.getRepositoryCacheManager(ivy, id).getIvyFileInCache(id);
    }

    private DefaultRepositoryCacheManager getRepositoryCacheManager(ModuleRevisionId id) {
        return TestHelper.getRepositoryCacheManager(ivy, id);
    }

    private File getResolvedIvyFileInCache(ModuleRevisionId mrid) {
        return ivy.getResolutionCacheManager().getResolvedIvyFileInCache(mrid);
    }

    private File getResolvedIvyFileInCache(Ivy ivy, ModuleRevisionId mrid) {
        return ivy.getResolutionCacheManager().getResolvedIvyFileInCache(mrid);
    }

    private File getConfigurationResolveReportInCache(String resolveId, String conf) {
        return ivy.getResolutionCacheManager()
                .getConfigurationResolveReportInCache(resolveId, conf);
    }

    private File getConfigurationResolveReportInCache(Ivy ivy, String resolveId, String conf) {
        return ivy.getResolutionCacheManager()
                .getConfigurationResolveReportInCache(resolveId, conf);
    }

    private File getArchiveFileInCache(String organisation, String module, String revision,
            String artifactName, String type, String ext) {
        return getArchiveFileInCache(ivy, organisation, module, revision, artifactName, type, ext);
    }

    private File getArchiveFileInCache(Ivy ivy, String organisation, String module, String branch,
            String revision, String artifactName, String type, String ext,
            Map<String, String> extraAttrs) {
        ModuleRevisionId mrid = ModuleRevisionId
                .newInstance(organisation, module, branch, revision);
        DefaultArtifact artifact = new DefaultArtifact(mrid, new Date(), artifactName, type, ext,
                extraAttrs);
        return TestHelper.getRepositoryCacheManager(ivy, mrid).getArchiveFileInCache(artifact);
    }

    private File getArchiveFileInCache(Ivy ivy, String organisation, String module,
            String revision, String artifactName, String type, String ext) {
        return TestHelper.getArchiveFileInCache(ivy, organisation, module, revision, artifactName,
            type, ext);
    }

    private File getArchiveFileInCache(Ivy ivy, String mrid, String artifactName, String type,
            String ext) {
        return TestHelper.getArchiveFileInCache(ivy, mrid, artifactName, type, ext);
    }

    private ResolveOptions getResolveOptions(String[] confs) {
        return getResolveOptions(ivy.getSettings(), confs);
    }

    private ResolveOptions getResolveOptions(IvySettings settings, String[] confs) {
        return new ResolveOptions().setConfs(confs);
    }

    @Test
    public void testExtraAttributesForcedDependencies() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File(
                "test/repositories/extra-attributes-forceddependencies/ivysettings-filerepo-attribs.xml"));
        ivy.getSettings().setDefaultCache(cache);

        ResolveReport report = ivy.resolve(
            ResolveTest.class.getResource("ivy-extra-attrib-forced-dependencies.xml"),
            getResolveOptions(ivy.getSettings(), new String[] {"*"}).setValidate(false));
        assertFalse(report.hasError());

        ivy.deliver("1.0.0", deliverDir.getAbsolutePath() + "/ivy-1.0.0.xml", new DeliverOptions()
                .setResolveId(report.getResolveId()).setValidate(false).setPubdate(new Date()));

        File deliveredIvyFile = new File(deliverDir, "ivy-1.0.0.xml");
        assertTrue(deliveredIvyFile.exists());
        ModuleDescriptor md = XmlModuleDescriptorParser.getInstance().parseDescriptor(
            ivy.getSettings(), deliveredIvyFile.toURI().toURL(), false);
        DependencyDescriptor[] dds = md.getDependencies();
        assertEquals(2, dds.length);
        assertEquals(
            ModuleRevisionId.newInstance("CAE-Visualization-Components", "SGL", "MAIN", "6.2.34.7"),
            dds[1].getDependencyRevisionId());

    }

    @Test
    public void testNoAttributesForcedDependencies() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File(
                "test/repositories/extra-attributes-forceddependencies/ivysettings-filerepo-noattribs.xml"));
        ivy.getSettings().setDefaultCache(cache);

        ResolveReport report = ivy.resolve(
            ResolveTest.class.getResource("ivy-extra-attrib-forced-dependencies.xml"),
            getResolveOptions(ivy.getSettings(), new String[] {"*"}).setValidate(false));
        assertFalse(report.hasError());

        ivy.deliver("1.0.0", deliverDir.getAbsolutePath() + "/ivy-1.0.0.xml", new DeliverOptions()
                .setResolveId(report.getResolveId()).setValidate(false).setPubdate(new Date()));

        File deliveredIvyFile = new File(deliverDir, "ivy-1.0.0.xml");
        assertTrue(deliveredIvyFile.exists());
        ModuleDescriptor md = XmlModuleDescriptorParser.getInstance().parseDescriptor(
            ivy.getSettings(), deliveredIvyFile.toURI().toURL(), false);
        DependencyDescriptor[] dds = md.getDependencies();
        assertEquals(2, dds.length);
        assertEquals(
            ModuleRevisionId.newInstance("CAE-Visualization-Components", "SGL", "MAIN", "6.2.34.7"),
            dds[1].getDependencyRevisionId());
    }

    @Test
    public void testExtraAttributesMultipleDependenciesHang() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File(
                "test/repositories/extra-attributes-multipledependencies/ivysettings-filerepo-attribs.xml"));
        ivy.getSettings().setDefaultCache(cache);

        ResolveReport report = ivy.resolve(
            ResolveTest.class.getResource("ivy-extra-att-multipledependencies.xml"),
            getResolveOptions(ivy.getSettings(), new String[] {"*"}).setValidate(false));
        assertFalse(report.hasError());
    }

    @Test
    public void testExtraAttributesMultipleDependenciesNoHang() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File(
                "test/repositories/extra-attributes-multipledependencies/ivysettings-filerepo-noattribs.xml"));
        ivy.getSettings().setDefaultCache(cache);

        ResolveReport report = ivy.resolve(
            ResolveTest.class.getResource("ivy-extra-att-multipledependencies.xml"),
            getResolveOptions(ivy.getSettings(), new String[] {"*"}).setValidate(false));
        assertFalse(report.hasError());
    }

    @Test
    public void testExtraAttributesMultipleDependenciesHang2() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File(
                "test/repositories/extra-attributes-multipledependencies/ivysettings-filerepo-attribs.xml"));
        ivy.getSettings().setDefaultCache(cache);

        ResolveReport report = ivy.resolve(
            ResolveTest.class.getResource("ivy-extra-att-multipledependencies2.xml"),
            getResolveOptions(ivy.getSettings(), new String[] {"*"}).setValidate(false));
        assertFalse(report.hasError());
    }

    @Test
    public void testExtraAttributesMultipleDependenciesNoHang2() throws Exception {
        Ivy ivy = new Ivy();
        ivy.configure(new File(
                "test/repositories/extra-attributes-multipledependencies/ivysettings-filerepo-noattribs.xml"));
        ivy.getSettings().setDefaultCache(cache);

        ResolveReport report = ivy.resolve(
            ResolveTest.class.getResource("ivy-extra-att-multipledependencies2.xml"),
            getResolveOptions(ivy.getSettings(), new String[] {"*"}).setValidate(false));
        assertFalse(report.hasError());
    }

    /**
     * Test case for IVY-956.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-956">IVY-956</a>
     */
    @Test(expected = StrictConflictException.class)
    public void testIVY956() throws Exception {
        ivy.getSettings().setDefaultConflictManager(
                ivy.getSettings().getConflictManager("latest-compatible"));
        ivy.resolve(ResolveTest.class.getResource("ivy-956.xml"),
                getResolveOptions(ivy.getSettings(), new String[] {"*"}).setValidate(false));
    }

    /**
     * Test case for IVY-1159.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-1159">IVY-1159</a>
     */
    @Test
    public void testIVY1159_orderIsModAModB() throws Exception {
        testIVY1159("ivy-depsorder_modA_then_modB.xml", false);

        File deliveredIvyFile = new File("build/test/deliver/ivy-1.xml");
        assertTrue(deliveredIvyFile.exists());
        ModuleDescriptor md = XmlModuleDescriptorParser.getInstance().parseDescriptor(
            ivy.getSettings(), deliveredIvyFile.toURI().toURL(), false);
        DependencyDescriptor[] dds = md.getDependencies();
        assertEquals(2, dds.length);
        assertEquals(ModuleRevisionId.newInstance("myorg", "modA", "0"),
            dds[0].getDependencyRevisionId());
        assertEquals(ModuleRevisionId.newInstance("myorg", "modB", "0"),
            dds[1].getDependencyRevisionId());
    }

    /**
     * Test case for IVY-1159.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-1159">IVY-1159</a>
     */
    @Test
    public void testIVY1159_orderIsModAModBReplaceForced() throws Exception {
        testIVY1159("ivy-depsorder_modA_then_modB.xml", true);

        File deliveredIvyFile = new File("build/test/deliver/ivy-1.xml");
        assertTrue(deliveredIvyFile.exists());
        ModuleDescriptor md = XmlModuleDescriptorParser.getInstance().parseDescriptor(
            ivy.getSettings(), deliveredIvyFile.toURI().toURL(), false);
        DependencyDescriptor[] dds = md.getDependencies();
        assertEquals(2, dds.length);
        assertEquals(ModuleRevisionId.newInstance("myorg", "modA", "1"),
            dds[0].getDependencyRevisionId());
        assertEquals(ModuleRevisionId.newInstance("myorg", "modB", "1"),
            dds[1].getDependencyRevisionId());
    }

    /**
     * Test case for IVY-1159.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-1159">IVY-1159</a>
     */
    @Test
    public void testIVY1159_orderIsModBModA() throws Exception {
        testIVY1159("ivy-depsorder_modB_then_modA.xml", false);

        File deliveredIvyFile = new File("build/test/deliver/ivy-1.xml");
        assertTrue(deliveredIvyFile.exists());
        ModuleDescriptor md = XmlModuleDescriptorParser.getInstance().parseDescriptor(
            ivy.getSettings(), deliveredIvyFile.toURI().toURL(), false);
        DependencyDescriptor[] dds = md.getDependencies();
        assertEquals(2, dds.length);
        assertEquals(ModuleRevisionId.newInstance("myorg", "modB", "0"),
            dds[0].getDependencyRevisionId());
        assertEquals(ModuleRevisionId.newInstance("myorg", "modA", "0"),
            dds[1].getDependencyRevisionId());
    }

    /**
     * Test case for IVY-1159.
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-1159">IVY-1159</a>
     */
    @Test
    public void testIVY1159_orderIsModBModAReplaceForced() throws Exception {
        testIVY1159("ivy-depsorder_modB_then_modA.xml", true);

        File deliveredIvyFile = new File("build/test/deliver/ivy-1.xml");
        assertTrue(deliveredIvyFile.exists());
        ModuleDescriptor md = XmlModuleDescriptorParser.getInstance().parseDescriptor(
            ivy.getSettings(), deliveredIvyFile.toURI().toURL(), false);
        DependencyDescriptor[] dds = md.getDependencies();
        assertEquals(2, dds.length);
        assertEquals(ModuleRevisionId.newInstance("myorg", "modB", "1"),
            dds[0].getDependencyRevisionId());
        assertEquals(ModuleRevisionId.newInstance("myorg", "modA", "1"),
            dds[1].getDependencyRevisionId());
    }

    private void testIVY1159(String modCIvyFile, boolean replaceForced) throws Exception {
        ivy = Ivy.newInstance();
        ivy.configure(new File("test/repositories/IVY-1159/ivysettings.xml"));

        ResolveOptions opts = new ResolveOptions();
        opts.setConfs(new String[] {"*"});
        opts.setResolveId("resolveid");
        opts.setRefresh(true);
        opts.setTransitive(true);

        ResolveReport report = ivy.resolve(new File("test/repositories/IVY-1159/" + modCIvyFile),
            opts);
        assertFalse(report.hasError());

        assertEquals(
                new HashSet<>(Arrays.asList(
                        ModuleRevisionId.newInstance("myorg", "modA", "1"),
                        ModuleRevisionId.newInstance("myorg", "modB", "1"))), report
                    .getConfigurationReport("default").getModuleRevisionIds());

        DeliverOptions dopts = new DeliverOptions();
        dopts.setReplaceForcedRevisions(replaceForced);
        dopts.setGenerateRevConstraint(true);
        dopts.setConfs(new String[] {"*"});
        dopts.setStatus("release");
        dopts.setPubdate(new Date());
        dopts.setResolveId("resolveid");
        String pubrev = "1";
        String deliveryPattern = "build/test/deliver/ivy-[revision].xml";

        ivy.deliver(pubrev, deliveryPattern, dopts);
    }

    @Test
    public void testUseCacheOnly() throws Exception {
        ResolveOptions option = getResolveOptions(new String[] {"*"}).setValidate(false);
        URL url = new File("test/repositories/1/usecacheonly/mod1/ivys/ivy-1.0.xml").toURI()
                .toURL();

        // normal resolve, the file goes in the cache
        ResolveReport report = ivy.resolve(url, option);
        assertFalse(report.hasError());

        option.setUseCacheOnly(true);

        // use cache only, hit the cache
        report = ivy.resolve(url, option);
        assertFalse(report.hasError());

        CacheCleaner.deleteDir(cache);
        createCache();

        // no more in the cache, missed
        report = ivy.resolve(url, option);
        assertTrue(report.hasError());

        option.setUseCacheOnly(false);

        // try with use origin: should fail as the cache is empty
        ivy.getSettings().setDefaultUseOrigin(true);
        option.setUseCacheOnly(true);
        report = ivy.resolve(url, option);
        assertTrue(report.hasError());

        // populate the cache
        option.setUseCacheOnly(false);
        report = ivy.resolve(url, option);
        assertFalse(report.hasError());

        // use origin should now work
        option.setUseCacheOnly(true);
        report = ivy.resolve(url, option);
        assertFalse(report.hasError());

        // ensure that we hit only the cache and never try to hit in the repository
        FileSystemResolver resolver = (FileSystemResolver) ivy.getSettings().getResolver("1");
        resolver.setRepository(new AbstractRepository() {
            public List<String> list(String parent) {
                throw new UnsupportedOperationException();
            }

            public Resource getResource(String source) {
                throw new UnsupportedOperationException();
            }

            public void get(String source, File destination) {
                throw new UnsupportedOperationException();
            }
        });
        report = ivy.resolve(url, option);
        assertFalse(report.hasError());
    }

    @Test
    public void testUseCacheOnlyWithRange() throws Exception {
        ResolveOptions option = getResolveOptions(new String[] {"*"});
        option.setValidate(false);

        ivy.getSettings().setDefaultUseOrigin(true);
        ivy.getSettings().setDefaultResolveMode("dynamic");

        URL url = new File("test/repositories/1/usecacheonly/mod3/ivys/ivy-1.0.xml").toURI()
                .toURL();

        // normal resolve, the file goes in the cache
        ResolveReport report = ivy.resolve(url, option);
        assertFalse(report.hasError());

        option.setUseCacheOnly(true);

        // use cache only, hit the cache
        report = ivy.resolve(url, option);
        assertFalse(report.hasError());
    }

    @Test
    public void testUseCacheOnlyWithChanging() throws Exception {
        ResolveOptions option = getResolveOptions(new String[] {"*"});
        option.setValidate(false);

        ivy.getSettings().setDefaultUseOrigin(true);

        URL url = new File("test/repositories/1/usecacheonly/mod4/ivys/ivy-1.0.xml").toURI()
                .toURL();

        // normal resolve, the file goes in the cache
        ResolveReport report = ivy.resolve(url, option);
        assertFalse(report.hasError());

        option.setUseCacheOnly(true);

        // use cache only, hit the cache
        report = ivy.resolve(url, option);
        assertFalse(report.hasError());

    }

    @Test
    public void testUnpack() throws Exception {
        ResolveOptions options = getResolveOptions(new String[] {"*"});

        URL url = new File("test/repositories/1/packaging/module1/ivys/ivy-1.0.xml").toURI()
                .toURL();

        // normal resolve, the file goes in the cache
        ResolveReport report = ivy.resolve(url, options);
        assertFalse(report.hasError());

        ArtifactDownloadReport adr = report.getAllArtifactsReports()[0];
        File cacheDir = ivy.getSettings().getDefaultRepositoryCacheBasedir();
        assertEquals(new File(cacheDir, "packaging/module2/jars/module2-1.0.jar"),
            adr.getLocalFile());
        assertEquals(new File(cacheDir, "packaging/module2/jar_unpackeds/module2-1.0"),
            adr.getUnpackedLocalFile());

        File[] jarContents = adr.getUnpackedLocalFile().listFiles();
        Arrays.sort(jarContents);
        assertEquals(new File(adr.getUnpackedLocalFile(), "META-INF"), jarContents[0]);
        assertEquals(new File(adr.getUnpackedLocalFile(), "test.txt"), jarContents[1]);
        assertEquals(new File(adr.getUnpackedLocalFile(), "META-INF/MANIFEST.MF"),
            jarContents[0].listFiles()[0]);
    }

    /**
     * Tests that if a pom.xml has multiple dependencies for the same module, but for different Maven classifiers,
     * then the resolution of such dependencies, preserves those multiple (Ivy) artifacts against the dependency
     *
     * @throws Exception if something goes wrong
     * @see <a href="https://issues.apache.org/jira/browse/IVY-1576">IVY-1576</a> for more details
     */
    @Test
    public void testMultiClassifierMavenDepResolution() throws Exception {
        final File pomFile = new File("test/repositories/m2/org/apache/test-classifier/1.0/test-classifier-1.0.pom");
        final ResolveReport resolveReport = ivy.resolve(pomFile.toURI().toURL(), new ResolveOptions().setConfs(new String[]{"*"}));
        assertFalse(resolveReport.hasError());
        final ModuleRevisionId dependencyId = ModuleRevisionId.newInstance("org.apache", "test-classified", "1.0");
        final ArtifactDownloadReport[] adrs = resolveReport.getArtifactsReports(dependencyId);
        assertNotNull("Artifact download reports is null for dependency " + dependencyId, adrs);
        assertEquals("Unexpected number of artifact download reports for dependency " + dependencyId, 3, adrs.length);
        final Set<String> classifiers = new HashSet<>();
        Collections.addAll(classifiers, "other", "asl", "unix");
        for (final ArtifactDownloadReport adr : adrs) {
            final Artifact artifact = adr.getArtifact();
            assertNotNull("Artifact is null for dependency " + dependencyId, artifact);
            final ArtifactRevisionId artifactId = artifact.getId();
            assertEquals("Unexpected artifact " + artifactId.getName(), "test-classified", artifactId.getName());
            final String classifier = artifact.getExtraAttribute("m:classifier");
            assertNotNull("No classifier extra attribute on artifact for dependency " + dependencyId, classifier);
            assertTrue("Unexpected classifier " + classifier + " on artifact " + artifact, classifiers.remove(classifier));
            // just make sure it's the correct jar file
            assertJarContains(adr.getLocalFile(), classifier + ".txt");
        }
        assertTrue("Missing artifact(s) with classifiers " + classifiers, classifiers.isEmpty());
    }


    /**
     * Tests the issue noted in IVY-1580.
     * <pre>
     *  org.apache:1580:1.0.0 depends on (Maven modules):
     *      -> org.apache:1580-foo-api:1.2.3
     *      -> org.apache:1580-foo-impl:1.2.3 which in turn depends on:
     *          -> org.apache:1580-foo-api:1.2.3 (in compile scope)
     *          -> org.apache:1580-foo-api:1.2.3 (type = test-jar, in test scope)
     * </pre>
     * It's expected that the resolution of org.apache:1580:1.0.0, correctly gets both the regular
     * jar of org.apache:1580-foo-api as well as the test-jar of the same org.apache:1580-foo-api.
     *
     * @see <a href="https://issues.apache.org/jira/browse/IVY-1580">IVY-1580</a>
     *
     * @throws Exception
     */
    @Test
    public void testIvy1580() throws Exception {
        final File ivyXML = new File("test/repositories/1/ivy-1580/ivy-1580.xml");
        final ResolveReport resolveReport = ivy.resolve(ivyXML.toURI().toURL(),
                new ResolveOptions().setConfs(new String[]{"*"}));
        assertFalse("Resolution report has failures", resolveReport.hasError());
        final String rootModuleConf = "default";
        // get the "default" conf, resolution report for the org.apache:1580:1.0.0 module (represented by the
        // ivy-1580.xml module descriptor)
        final ConfigurationResolveReport confReport = resolveReport.getConfigurationReport(rootModuleConf);
        assertNotNull(rootModuleConf + " conf resolution report for " +
                resolveReport.getModuleDescriptor().getModuleRevisionId() + " is null", confReport);

        final ModuleRevisionId apiDependencyId = ModuleRevisionId.newInstance("org.apache", "1580-foo-api", "1.2.3");
        final IvyNode apiDepNode = confReport.getDependency(apiDependencyId);
        assertNotNull("Dependency " + apiDependencyId + " not found in conf resolve report", apiDepNode);
        final Artifact[] apiArtifacts = apiDepNode.getArtifacts(rootModuleConf);
        assertNotNull("No artifacts available for dependency " + apiDependencyId, apiArtifacts);
        assertEquals("Unexpected number of artifacts for dependency " + apiDependencyId, 2, apiArtifacts.length);
        boolean foundTestJarType = false;
        boolean foundJarType = false;
        for (final Artifact apiArtifact : apiArtifacts) {
            assertEquals("Unexpected artifact name", "1580-foo-api", apiArtifact.getName());
            assertNotNull("Artifact type is null for " + apiArtifact, apiArtifact.getType());
            ArtifactDownloadReport apiDownloadReport = null;
            for (final ArtifactDownloadReport artifactDownloadReport : confReport.getAllArtifactsReports()) {
                if (artifactDownloadReport.getArtifact().equals(apiArtifact)) {
                    apiDownloadReport = artifactDownloadReport;
                    break;
                }
            }
            assertNotNull("No download report found for artifact " + apiArtifact, apiDownloadReport);
            final File apiJar = apiDownloadReport.getLocalFile();
            assertNotNull("artifact jar file is null for " + apiArtifact, apiJar);
            switch (apiArtifact.getType()) {
                case "test-jar" : {
                    assertFalse("More than 1 test-jar artifact found", foundTestJarType);
                    foundTestJarType = true;
                    assertJarContains(apiJar, "api-test-file.txt");
                    break;
                }
                case "jar" : {
                    assertFalse("More than 1 jar artifact found", foundJarType);
                    foundJarType = true;
                    assertJarContains(apiJar, "api-file.txt");
                    break;
                }
                default: {
                    fail("unexpected artifact type " + apiArtifact.getType() + " for artifact " + apiArtifact);
                }
            }
        }
        assertTrue("No test-jar artifact found for dependency " + apiDependencyId, foundTestJarType);
        assertTrue("No jar artifact found for dependency " + apiDependencyId, foundJarType);

        // just do some basic check on the impl module as well
        final ModuleRevisionId implDepId = ModuleRevisionId.newInstance("org.apache", "1580-foo-impl", "1.2.3");
        final IvyNode implDepNode = confReport.getDependency(implDepId);
        assertNotNull("Dependency " + implDepId + " not found in conf resolve report", implDepNode);

    }


    /**
     * Tests the issue noted in IVY-1586.
     * <pre>
     *  org.apache:1586:1.0.0 depends on (Maven modules):
     *      -> org.apache:1580-foo-api:1.2.3
     *      -> org.apache:1580-foo-impl:1.2.3 conf="default", which in turn depends on:
     *          -> org.apache:1580-foo-api:1.2.3 (in compile scope)
     *          -> org.apache:1580-foo-api:1.2.3 (type = test-jar, in test scope)
     * </pre>
     * It's expected that the resolution of org.apache:1586:1.0.0, gets the
     * "jar" type of org.apache:1580-foo-api and not the test-jar of the same org.apache:1580-foo-api,
     * since only the "default" conf is demanded via the org.apache:1580-foo-impl:1.2.3 dependency.
     *
     * @see <a href="https://issues.apache.org/jira/browse/IVY-1586">IVY-1586</a>
     *
     * @throws Exception
     */
    @Test
    public void testIvy1586() throws Exception {
        // do it twice (once in fresh cache and once with the cache populated)
        for (int i = 0; i < 2; i++) {
            if (i == 0) {
                ivy.getLoggerEngine().info("ResolveTest#testIvy1586 - Using a clean Ivy cache");
            } else {
                ivy.getLoggerEngine().info("ResolveTest#testIvy1586 - Using an already populated Ivy cache");
            }
            final File ivyXML = new File("test/repositories/1/ivy-1586/ivy-1586.xml");
            final ResolveReport resolveReport = ivy.resolve(ivyXML.toURI().toURL(),
                    new ResolveOptions().setConfs(new String[]{"*"}));
            assertFalse("Resolution report has failures", resolveReport.hasError());
            final String rootModuleConf = "default";
            // get the "default" conf, resolution report for the org.apache:1586:1.0.0 module (represented by the
            // ivy-1586.xml module descriptor)
            final ConfigurationResolveReport confReport = resolveReport.getConfigurationReport(rootModuleConf);
            assertNotNull(rootModuleConf + " conf resolution report for " +
                    resolveReport.getModuleDescriptor().getModuleRevisionId() + " is null", confReport);

            final ModuleRevisionId apiDependencyId = ModuleRevisionId.newInstance("org.apache", "1580-foo-api", "1.2.3");
            final IvyNode apiDepNode = confReport.getDependency(apiDependencyId);
            assertNotNull("Dependency " + apiDependencyId + " not found in conf resolve report", apiDepNode);
            final Artifact[] apiArtifacts = apiDepNode.getArtifacts(rootModuleConf);
            assertNotNull("No artifacts available for dependency " + apiDependencyId, apiArtifacts);
            assertEquals("Unexpected number of artifacts for dependency " + apiDependencyId, 1, apiArtifacts.length);
            final Artifact apiArtifact = apiArtifacts[0];
            assertEquals("Unexpected artifact name", "1580-foo-api", apiArtifact.getName());
            assertEquals("Unexpected type for artifact", "jar", apiArtifact.getType());
            ArtifactDownloadReport apiDownloadReport = null;
            for (final ArtifactDownloadReport artifactDownloadReport : confReport.getAllArtifactsReports()) {
                if (artifactDownloadReport.getArtifact().equals(apiArtifact)) {
                    apiDownloadReport = artifactDownloadReport;
                    break;
                }
            }
            assertNotNull("No download report found for artifact " + apiArtifact, apiDownloadReport);
            final File apiJar = apiDownloadReport.getLocalFile();
            assertNotNull("artifact jar file is null for " + apiArtifact, apiJar);
            assertJarContains(apiJar, "api-file.txt");

            // just do some basic check on the impl module as well
            final ModuleRevisionId implDepId = ModuleRevisionId.newInstance("org.apache", "1580-foo-impl", "1.2.3");
            final IvyNode implDepNode = confReport.getDependency(implDepId);
            assertNotNull("Dependency " + implDepId + " not found in conf resolve report", implDepNode);
        }
    }


    /**
     * Tests that when the internal metadata file containing the artifact origin location
     * points to {@code file:} URI, then the location is correctly parsed.
     * See IVY-1616
     */
    @Test
    public void testCacheUseOrigin() throws Exception {
        final Ivy current = new Ivy();
        current.configure(new File("test/repositories/ivysettings-caches-use-origin.xml"));
        // resolve and download an artifact and let the origin details be stored in the internal metadata files
        // in ivy cache
        ResolveReport report = current.resolve(ModuleRevisionId.newInstance("org.apache",
                "test","1.0"),
                getResolveOptions(new String[] {"*"}).setDownload(true), false);
        assertNotNull("Resolve report is null", report);
        assertFalse("Resolution has errors", report.hasError());
        // now set the "useOrigin" on caches to true, so that the next resolution uses the artifact origin
        // that was saved in previous resolution
        current.getSettings().setDefaultUseOrigin(true);
        // trigger the resolution again
        report = current.resolve(ModuleRevisionId.newInstance("org.apache",
                "test","1.0"),
                getResolveOptions(new String[] {"*"}).setDownload(true), false);
        assertNotNull("Resolve report is null", report);
        assertFalse("Resolution has errors", report.hasError());
    }

    private void assertJarContains(final File jar, final String jarEntryPath) throws IOException {
        try (final JarFile jarFile = new JarFile(jar)) {
            final JarEntry entry = jarFile.getJarEntry(jarEntryPath);
            assertNotNull(jarEntryPath + " is missing from jar file " + jar, entry);
        }
    }
}
