You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@ant.apache.org by jl...@apache.org on 2013/06/14 09:15:14 UTC

svn commit: r1492972 - in /ant/ivy/core/trunk: src/java/org/apache/ivy/ant/ test/java/org/apache/ivy/ant/ test/java/org/apache/ivy/ant/testutil/

Author: jlboudart
Date: Fri Jun 14 07:15:14 2013
New Revision: 1492972

URL: http://svn.apache.org/r1492972
Log:
First draft of dependency update checker task
Extract ant test listener as a reusable class for test to check log output

Added:
    ant/ivy/core/trunk/src/java/org/apache/ivy/ant/IvyDependencyUpdateChecker.java
    ant/ivy/core/trunk/test/java/org/apache/ivy/ant/IvyDependencyUpdateCheckerTest.java
    ant/ivy/core/trunk/test/java/org/apache/ivy/ant/ivy-simple3.xml
    ant/ivy/core/trunk/test/java/org/apache/ivy/ant/testutil/
    ant/ivy/core/trunk/test/java/org/apache/ivy/ant/testutil/AntTaskTestCase.java
    ant/ivy/core/trunk/test/java/org/apache/ivy/ant/testutil/AntTestListener.java
Modified:
    ant/ivy/core/trunk/test/java/org/apache/ivy/ant/IvyDependencyTreeTest.java

Added: ant/ivy/core/trunk/src/java/org/apache/ivy/ant/IvyDependencyUpdateChecker.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/ant/IvyDependencyUpdateChecker.java?rev=1492972&view=auto
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/ant/IvyDependencyUpdateChecker.java (added)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/ant/IvyDependencyUpdateChecker.java Fri Jun 14 07:15:14 2013
@@ -0,0 +1,200 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+package org.apache.ivy.ant;
+
+import java.io.IOException;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.ivy.core.module.descriptor.Configuration;
+import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
+import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.core.report.ResolveReport;
+import org.apache.ivy.core.resolve.IvyNode;
+import org.apache.ivy.core.resolve.ResolveOptions;
+import org.apache.tools.ant.BuildException;
+
+public class IvyDependencyUpdateChecker extends IvyPostResolveTask {
+
+    private String revisionToCheck = "latest.integration";
+
+    private boolean download = false;
+
+    private boolean checkIfChanged = false;
+
+    public void doExecute() throws BuildException {
+        prepareAndCheck();
+
+        ModuleDescriptor originalModuleDescriptor = getResolvedReport().getModuleDescriptor();
+        // clone module descriptor
+        DefaultModuleDescriptor latestModuleDescriptor = new DefaultModuleDescriptor(
+                originalModuleDescriptor.getModuleRevisionId(),
+                originalModuleDescriptor.getStatus(), originalModuleDescriptor.getPublicationDate());
+        // copy configurations
+        for (int i = 0; i < originalModuleDescriptor.getConfigurations().length; i++) {
+            Configuration configuration = originalModuleDescriptor.getConfigurations()[i];
+            latestModuleDescriptor.addConfiguration(configuration);
+        }
+        // clone dependency and add new one with the requested revisionToCheck
+        for (int i = 0; i < originalModuleDescriptor.getDependencies().length; i++) {
+            DependencyDescriptor dependencyDescriptor = originalModuleDescriptor.getDependencies()[i];
+            ModuleRevisionId upToDateMrid = ModuleRevisionId.newInstance(
+                dependencyDescriptor.getDependencyRevisionId(), revisionToCheck);
+            latestModuleDescriptor.addDependency(dependencyDescriptor.clone(upToDateMrid));
+        }
+
+        // resolve
+        ResolveOptions resolveOptions = new ResolveOptions();
+        resolveOptions.setDownload(isDownload());
+        resolveOptions.setLog(getLog());
+        resolveOptions.setConfs(splitConfs(getConf()));
+        resolveOptions.setCheckIfChanged(checkIfChanged);
+
+        ResolveReport latestReport;
+        try {
+            latestReport = getIvyInstance().getResolveEngine().resolve(latestModuleDescriptor,
+                resolveOptions);
+
+            displayDependencyUpdates(getResolvedReport(), latestReport);
+            displayNewDependencyOnLatest(getResolvedReport(), latestReport);
+            displayMissingDependencyOnLatest(getResolvedReport(), latestReport);
+
+        } catch (ParseException e) {
+            throw new BuildException("impossible to resolve dependencies:\n\t" + e, e);
+        } catch (IOException e) {
+            throw new BuildException("impossible to resolve dependencies:\n\t" + e, e);
+        }
+
+    }
+
+    private void displayDependencyUpdates(ResolveReport originalReport, ResolveReport latestReport) {
+        log("Dependencies updates available :");
+        boolean dependencyUpdateDetected = false;
+        for (Iterator iterator = latestReport.getDependencies().iterator(); iterator.hasNext();) {
+            IvyNode latest = (IvyNode) iterator.next();
+            for (Iterator iterator2 = originalReport.getDependencies().iterator(); iterator2
+                    .hasNext();) {
+                IvyNode originalDependency = (IvyNode) iterator2.next();
+                if (originalDependency.getModuleId().equals(latest.getModuleId())) {
+                    if (!originalDependency.getResolvedId().getRevision()
+                            .equals(latest.getResolvedId().getRevision())) {
+                        // is this dependency a transitive dependency ? or direct dependency
+                        // (unfortunatly
+                        // .isTranstive() methods doesn't have the same meaning)
+                        boolean isTransitiveDependency = latest.getDependencyDescriptor(latest
+                                .getRoot()) == null;
+                        StringBuilder sb = new StringBuilder();
+                        sb.append("\t")//
+                                .append(originalDependency.getResolvedId().getOrganisation()) //
+                                .append('#')//
+                                .append(originalDependency.getResolvedId().getName())//
+                                .append(isTransitiveDependency ? " (transitive)" : "") //
+                                .append("\t")//
+                                .append(originalDependency.getResolvedId().getRevision())//
+                                .append(" -> ")//
+                                .append(latest.getResolvedId().getRevision());
+                        log(sb.toString());
+                        dependencyUpdateDetected = true;
+                    }
+
+                }
+            }
+        }
+        if (!dependencyUpdateDetected) {
+            log("\tAll dependencies are up to date");
+        }
+    }
+
+    private void displayMissingDependencyOnLatest(ResolveReport originalReport,
+            ResolveReport latestReport) {
+        List/* <ModuleRevisionId> */listOfMissingDependencyOnLatest = new ArrayList/*
+                                                                                    * <ModuleRevisionId
+                                                                                    * >
+                                                                                    */();
+        for (Iterator iterator = originalReport.getDependencies().iterator(); iterator.hasNext();) {
+            IvyNode originalDependency = (IvyNode) iterator.next();
+            boolean dependencyFound = false;
+            for (Iterator iterator2 = latestReport.getDependencies().iterator(); iterator2
+                    .hasNext();) {
+                IvyNode latest = (IvyNode) iterator2.next();
+                if (originalDependency.getModuleId().equals(latest.getModuleId())) {
+                    dependencyFound = true;
+                }
+            }
+            if (!dependencyFound) {
+                listOfMissingDependencyOnLatest.add(originalDependency.getId());
+            }
+        }
+
+        if (listOfMissingDependencyOnLatest.size() > 0) {
+            log("List of missing dependency on latest resolve :");
+            for (Iterator iterator = listOfMissingDependencyOnLatest.iterator(); iterator.hasNext();) {
+                ModuleRevisionId moduleRevisionId = (ModuleRevisionId) iterator.next();
+                log("\t" + moduleRevisionId.toString());
+            }
+        }
+    }
+
+    private void displayNewDependencyOnLatest(ResolveReport originalReport,
+            ResolveReport latestReport) {
+        List/* <ModuleRevisionId> */listOfNewDependencyOnLatest = new ArrayList/* <ModuleRevisionId> */();
+        for (Iterator iterator = latestReport.getDependencies().iterator(); iterator.hasNext();) {
+            IvyNode latest = (IvyNode) iterator.next();
+
+            boolean dependencyFound = false;
+            for (Iterator iterator2 = originalReport.getDependencies().iterator(); iterator2
+                    .hasNext();) {
+                IvyNode originalDependency = (IvyNode) iterator2.next();
+                if (originalDependency.getModuleId().equals(latest.getModuleId())) {
+                    dependencyFound = true;
+                }
+            }
+            if (!dependencyFound) {
+                listOfNewDependencyOnLatest.add(latest.getId());
+            }
+        }
+        if (listOfNewDependencyOnLatest.size() > 0) {
+            log("List of new dependency on latest resolve :");
+            for (Iterator iterator = listOfNewDependencyOnLatest.iterator(); iterator.hasNext();) {
+                ModuleRevisionId moduleRevisionId = (ModuleRevisionId) iterator.next();
+                log("\t" + moduleRevisionId.toString());
+            }
+        }
+    }
+
+    public String getRevisionToCheck() {
+        return revisionToCheck;
+    }
+
+    public void setRevisionToCheck(String revisionToCheck) {
+        this.revisionToCheck = revisionToCheck;
+    }
+
+    public boolean isDownload() {
+        return download;
+    }
+
+    public void setDownload(boolean download) {
+        this.download = download;
+    }
+
+}

Modified: ant/ivy/core/trunk/test/java/org/apache/ivy/ant/IvyDependencyTreeTest.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/test/java/org/apache/ivy/ant/IvyDependencyTreeTest.java?rev=1492972&r1=1492971&r2=1492972&view=diff
==============================================================================
--- ant/ivy/core/trunk/test/java/org/apache/ivy/ant/IvyDependencyTreeTest.java (original)
+++ ant/ivy/core/trunk/test/java/org/apache/ivy/ant/IvyDependencyTreeTest.java Fri Jun 14 07:15:14 2013
@@ -19,29 +19,22 @@ package org.apache.ivy.ant;
 
 import java.io.File;
 
-import junit.framework.TestCase;
-
-import org.apache.tools.ant.BuildEvent;
+import org.apache.ivy.ant.testutil.AntTaskTestCase;
 import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.BuildListener;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.taskdefs.Delete;
 
-public class IvyDependencyTreeTest extends TestCase {
+public class IvyDependencyTreeTest extends AntTaskTestCase {
     private File cache;
 
     private IvyDependencyTree dependencyTree;
 
-    private AntTestListener antTestListener;
-
     private Project project;
 
     protected void setUp() throws Exception {
         createCache();
-        project = AntTestHelper.newProject();
+        project = configureProject();
         project.setProperty("ivy.settings.file", "test/repositories/ivysettings.xml");
-        antTestListener = new AntTestListener(Project.MSG_INFO);
-        project.addBuildListener(antTestListener);
 
         dependencyTree = new IvyDependencyTree();
         dependencyTree.setProject(project);
@@ -119,105 +112,4 @@ public class IvyDependencyTreeTest exten
         assertLogContaining("\\- org1#mod1.2;2.2");
     }
 
-    public void assertLogContaining(String substring) {
-        String realLog = antTestListener.getLog();
-        assertTrue("expecting log to contain \"" + substring + "\" log was \"" + realLog + "\"",
-            realLog.contains(substring));
-    }
-
-    public void assertLogNotContaining(String substring) {
-        String realLog = antTestListener.getLog();
-        assertFalse("expecting log to contain \"" + substring + "\" log was \"" + realLog + "\"",
-            realLog.contains(substring));
-    }
-
-    /**
-     * Our own personal build listener.
-     */
-    private class AntTestListener implements BuildListener {
-        private int logLevel;
-
-        private StringBuffer buildLog = new StringBuffer();
-
-        /**
-         * Constructs a test listener which will ignore log events above the given level.
-         */
-        public AntTestListener(int logLevel) {
-            this.logLevel = logLevel;
-        }
-
-        /**
-         * Fired before any targets are started.
-         */
-        public void buildStarted(BuildEvent event) {
-        }
-
-        /**
-         * Fired after the last target has finished. This event will still be thrown if an error
-         * occurred during the build.
-         * 
-         * @see BuildEvent#getException()
-         */
-        public void buildFinished(BuildEvent event) {
-        }
-
-        /**
-         * Fired when a target is started.
-         * 
-         * @see BuildEvent#getTarget()
-         */
-        public void targetStarted(BuildEvent event) {
-            // System.out.println("targetStarted " + event.getTarget().getName());
-        }
-
-        /**
-         * Fired when a target has finished. This event will still be thrown if an error occurred
-         * during the build.
-         * 
-         * @see BuildEvent#getException()
-         */
-        public void targetFinished(BuildEvent event) {
-            // System.out.println("targetFinished " + event.getTarget().getName());
-        }
-
-        /**
-         * Fired when a task is started.
-         * 
-         * @see BuildEvent#getTask()
-         */
-        public void taskStarted(BuildEvent event) {
-            // System.out.println("taskStarted " + event.getTask().getTaskName());
-        }
-
-        /**
-         * Fired when a task has finished. This event will still be throw if an error occurred
-         * during the build.
-         * 
-         * @see BuildEvent#getException()
-         */
-        public void taskFinished(BuildEvent event) {
-            // System.out.println("taskFinished " + event.getTask().getTaskName());
-        }
-
-        /**
-         * Fired whenever a message is logged.
-         * 
-         * @see BuildEvent#getMessage()
-         * @see BuildEvent#getPriority()
-         */
-        public void messageLogged(BuildEvent event) {
-            if (event.getPriority() > logLevel) {
-                // ignore event
-                return;
-            }
-
-            buildLog.append(event.getMessage());
-        }
-
-        public String getLog() {
-            return buildLog.toString();
-        }
-
-    }
-
 }

Added: ant/ivy/core/trunk/test/java/org/apache/ivy/ant/IvyDependencyUpdateCheckerTest.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/test/java/org/apache/ivy/ant/IvyDependencyUpdateCheckerTest.java?rev=1492972&view=auto
==============================================================================
--- ant/ivy/core/trunk/test/java/org/apache/ivy/ant/IvyDependencyUpdateCheckerTest.java (added)
+++ ant/ivy/core/trunk/test/java/org/apache/ivy/ant/IvyDependencyUpdateCheckerTest.java Fri Jun 14 07:15:14 2013
@@ -0,0 +1,237 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+package org.apache.ivy.ant;
+
+import java.io.File;
+
+import org.apache.ivy.Ivy;
+import org.apache.ivy.ant.testutil.AntTaskTestCase;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.Delete;
+
+public class IvyDependencyUpdateCheckerTest extends AntTaskTestCase {
+    private File cache;
+
+    private IvyDependencyUpdateChecker dependencyUpdateChecker;
+
+    protected void setUp() throws Exception {
+        createCache();
+        Project project = configureProject();
+        project.setProperty("ivy.settings.file", "test/repositories/ivysettings.xml");
+        project.setProperty("ivy.cache.dir", cache.getAbsolutePath());
+
+        dependencyUpdateChecker = new IvyDependencyUpdateChecker();
+        dependencyUpdateChecker.setProject(project);
+    }
+
+    private void createCache() {
+        cache = new File("build/cache");
+        cache.mkdirs();
+    }
+
+    protected void tearDown() throws Exception {
+        cleanCache();
+    }
+
+    private void cleanCache() {
+        Delete del = new Delete();
+        del.setProject(new Project());
+        del.setDir(cache);
+        del.execute();
+    }
+
+    public void testSimple() throws Exception {
+        // depends on org="org1" name="mod1.1" rev="1.0"
+        // has transitive dependecy on org="org1" name="mod1.2" rev="2.0"
+        dependencyUpdateChecker.setFile(new File("test/java/org/apache/ivy/ant/ivy-simple3.xml"));
+        dependencyUpdateChecker.execute();
+
+        assertEquals("resolve-simple", getIvy().getVariable("ivy.module"));
+        assertEquals("1.0", getIvy().getVariable("ivy.revision"));
+
+        assertLogContaining("Dependencies updates available :");
+        assertLogContaining("org1#mod1.1\t1.0 -> 2.0");
+        assertLogContaining("org1#mod1.2 (transitive)\t2.0 -> 2.1");
+    }
+
+    public void testResolveWithoutIvyFile() throws Exception {
+        // depends on org="org1" name="mod1.2" rev="2.0"
+
+        dependencyUpdateChecker.setFile(new File("test/java/org/apache/ivy/ant/ivy-simple.xml"));
+        dependencyUpdateChecker.setConf("default");
+        dependencyUpdateChecker.setHaltonfailure(false);
+        dependencyUpdateChecker.execute();
+
+        assertLogContaining("Dependencies updates available :");
+        assertLogContaining("org1#mod1.2\t2.0 -> 2.2");
+    }
+
+    public void testInline() throws Exception {
+        // same as before, but expressing dependency directly without ivy file
+        dependencyUpdateChecker.setOrganisation("org1");
+        dependencyUpdateChecker.setModule("mod1.2");
+        dependencyUpdateChecker.setRevision("2.0");
+        dependencyUpdateChecker.setInline(true);
+        dependencyUpdateChecker.execute();
+
+        assertLogContaining("Dependencies updates available :");
+        assertLogContaining("org1#mod1.2\t2.0 -> 2.2");
+
+    }
+
+    public void testInlineForNonExistingModule() throws Exception {
+        try {
+            dependencyUpdateChecker.setOrganisation("org1XXYZ");
+            dependencyUpdateChecker.setModule("mod1.2");
+            dependencyUpdateChecker.setRevision("2.0");
+            dependencyUpdateChecker.setInline(true);
+            dependencyUpdateChecker.setHaltonfailure(true);
+            dependencyUpdateChecker.execute();
+            fail("failure didn't raised an exception with default haltonfailure setting");
+        } catch (BuildException ex) {
+            // ok => should raise an exception
+        }
+    }
+
+    public void testFailure() throws Exception {
+        try {
+            dependencyUpdateChecker
+                    .setFile(new File("test/java/org/apache/ivy/ant/ivy-failure.xml"));
+            dependencyUpdateChecker.execute();
+            fail("failure didn't raised an exception with default haltonfailure setting");
+        } catch (BuildException ex) {
+            // ok => should raise an exception
+        }
+    }
+
+    public void testFailureWithMissingConfigurations() throws Exception {
+        try {
+            dependencyUpdateChecker
+                    .setFile(new File("test/java/org/apache/ivy/ant/ivy-simple.xml"));
+            dependencyUpdateChecker.setConf("default,unknown");
+            dependencyUpdateChecker.execute();
+            fail("missing configurations didn't raised an exception");
+        } catch (BuildException ex) {
+            assertTrue(ex.getMessage().indexOf("unknown") != -1);
+        }
+    }
+
+    public void testFailureOnBadDependencyIvyFile() throws Exception {
+        try {
+            dependencyUpdateChecker.setFile(new File(
+                    "test/java/org/apache/ivy/ant/ivy-failure2.xml"));
+            dependencyUpdateChecker.execute();
+            fail("failure didn't raised an exception with default haltonfailure setting");
+        } catch (BuildException ex) {
+            // ok => should raise an exception
+        }
+    }
+
+    public void testFailureOnBadStatusInDependencyIvyFile() throws Exception {
+        try {
+            dependencyUpdateChecker.setFile(new File(
+                    "test/java/org/apache/ivy/ant/ivy-failure3.xml"));
+            dependencyUpdateChecker.execute();
+            fail("failure didn't raised an exception with default haltonfailure setting");
+        } catch (BuildException ex) {
+            // ok => should raise an exception
+        }
+    }
+
+    public void testHaltOnFailure() throws Exception {
+        try {
+            dependencyUpdateChecker
+                    .setFile(new File("test/java/org/apache/ivy/ant/ivy-failure.xml"));
+            dependencyUpdateChecker.setHaltonfailure(false);
+            dependencyUpdateChecker.execute();
+        } catch (BuildException ex) {
+            ex.printStackTrace();
+            fail("failure raised an exception with haltonfailure set to false");
+        }
+    }
+
+    public void testExcludedConf() throws Exception {
+        dependencyUpdateChecker.setFile(new File("test/java/org/apache/ivy/ant/ivy-multiconf.xml"));
+        dependencyUpdateChecker.setConf("*,!default");
+        dependencyUpdateChecker.execute();
+
+        // assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.1", "2.0"))
+        // .exists());
+        // assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org1", "mod1.2", "2.0"))
+        // .exists());
+
+        assertLogContaining("Dependencies updates available :");
+        assertLogContaining("All dependencies are up to date");
+        // test the properties
+        Project project = dependencyUpdateChecker.getProject();
+        assertFalse(project.getProperty("ivy.resolved.configurations").indexOf("default") > -1);
+    }
+
+    public void testResolveWithAbsoluteFile() {
+        // IVY-396
+        File ivyFile = new File("test/java/org/apache/ivy/ant/ivy-simple.xml");
+        dependencyUpdateChecker.getProject().setProperty("ivy.dep.file", ivyFile.getAbsolutePath());
+        dependencyUpdateChecker.execute();
+
+        // assertTrue(getResolvedIvyFileInCache(
+        // ModuleRevisionId.newInstance("apache", "resolve-simple", "1.0")).exists());
+    }
+
+    public void testResolveWithRelativeFile() {
+        // IVY-396
+        dependencyUpdateChecker.getProject().setProperty("ivy.dep.file",
+            "test/java/org/apache/ivy/ant/ivy-simple.xml");
+        dependencyUpdateChecker.execute();
+
+        // assertTrue(getResolvedIvyFileInCache(
+        // ModuleRevisionId.newInstance("apache", "resolve-simple", "1.0")).exists());
+
+        assertLogContaining("Dependencies updates available :");
+        assertLogContaining("org1#mod1.2\t2.0 -> 2.2");
+    }
+
+    private Ivy getIvy() {
+        return dependencyUpdateChecker.getIvyInstance();
+    }
+
+    public void testSimpleExtends() throws Exception {
+        dependencyUpdateChecker.setFile(new File(
+                "test/java/org/apache/ivy/ant/ivy-extends-multiconf.xml"));
+        dependencyUpdateChecker.execute();
+        assertEquals("1", dependencyUpdateChecker.getProject().getProperty("ivy.parents.count"));
+        assertEquals("apache",
+            dependencyUpdateChecker.getProject().getProperty("ivy.parent[0].organisation"));
+        assertEquals("resolve-simple",
+            dependencyUpdateChecker.getProject().getProperty("ivy.parent[0].module"));
+        assertEquals("1.0",
+            dependencyUpdateChecker.getProject().getProperty("ivy.parent[0].revision"));
+        assertEquals(null, dependencyUpdateChecker.getProject().getProperty("ivy.parent[0].branch"));
+
+        assertLogContaining("Dependencies updates available :");
+        assertLogContaining("org1#mod1.1\t1.1 -> 2.0");
+        assertLogContaining("org1#mod1.1\t1.0 -> 2.0");
+        assertLogContaining("org1#mod1.2\t2.1 -> 2.2");
+        assertLogContaining("org2#mod2.1\t0.3 -> 0.7");
+
+        // inherited from parent
+        assertLogContaining("org1#mod1.2\t2.0 -> 2.2");
+
+    }
+
+}

Added: ant/ivy/core/trunk/test/java/org/apache/ivy/ant/ivy-simple3.xml
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/test/java/org/apache/ivy/ant/ivy-simple3.xml?rev=1492972&view=auto
==============================================================================
--- ant/ivy/core/trunk/test/java/org/apache/ivy/ant/ivy-simple3.xml (added)
+++ ant/ivy/core/trunk/test/java/org/apache/ivy/ant/ivy-simple3.xml Fri Jun 14 07:15:14 2013
@@ -0,0 +1,28 @@
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one
+   or more contributor license agreements.  See the NOTICE file
+   distributed with this work for additional information
+   regarding copyright ownership.  The ASF licenses this file
+   to you under the Apache License, Version 2.0 (the
+   "License"); you may not use this file except in compliance
+   with the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing,
+   software distributed under the License is distributed on an
+   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+   KIND, either express or implied.  See the License for the
+   specific language governing permissions and limitations
+   under the License.    
+-->
+<ivy-module version="1.0"> 
+	<info organisation="apache"
+	       module="resolve-simple"
+	       revision="1.0"
+	       status="release"
+	/>
+	<dependencies>
+		<dependency org="org1" name="mod1.1" rev="1.0"/>
+	</dependencies>
+</ivy-module>

Added: ant/ivy/core/trunk/test/java/org/apache/ivy/ant/testutil/AntTaskTestCase.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/test/java/org/apache/ivy/ant/testutil/AntTaskTestCase.java?rev=1492972&view=auto
==============================================================================
--- ant/ivy/core/trunk/test/java/org/apache/ivy/ant/testutil/AntTaskTestCase.java (added)
+++ ant/ivy/core/trunk/test/java/org/apache/ivy/ant/testutil/AntTaskTestCase.java Fri Jun 14 07:15:14 2013
@@ -0,0 +1,57 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+package org.apache.ivy.ant.testutil;
+
+import junit.framework.TestCase;
+
+import org.apache.ivy.ant.AntTestHelper;
+import org.apache.tools.ant.Project;
+
+public class AntTaskTestCase extends TestCase {
+
+    private AntTestListener antTestListener;
+
+    public Project configureProject() {
+        Project project = AntTestHelper.newProject();
+        antTestListener = new AntTestListener(Project.MSG_INFO);
+        project.addBuildListener(antTestListener);
+        return project;
+    }
+
+    public void assertLogContaining(String substring) {
+        checkAntListener();
+        String realLog = antTestListener.getLog();
+        assertTrue("expecting log to contain \"" + substring + "\" log was \"" + realLog + "\"",
+            realLog.contains(substring));
+    }
+
+    public void assertLogNotContaining(String substring) {
+        checkAntListener();
+        String realLog = antTestListener.getLog();
+        assertFalse("expecting log to contain \"" + substring + "\" log was \"" + realLog + "\"",
+            realLog.contains(substring));
+    }
+
+    private void checkAntListener() {
+        if (antTestListener == null) {
+            throw new IllegalStateException(
+                    "Project is not properly configure, please invoke configureProject method first");
+        }
+    }
+
+}

Added: ant/ivy/core/trunk/test/java/org/apache/ivy/ant/testutil/AntTestListener.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/test/java/org/apache/ivy/ant/testutil/AntTestListener.java?rev=1492972&view=auto
==============================================================================
--- ant/ivy/core/trunk/test/java/org/apache/ivy/ant/testutil/AntTestListener.java (added)
+++ ant/ivy/core/trunk/test/java/org/apache/ivy/ant/testutil/AntTestListener.java Fri Jun 14 07:15:14 2013
@@ -0,0 +1,110 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+package org.apache.ivy.ant.testutil;
+
+import org.apache.tools.ant.BuildEvent;
+import org.apache.tools.ant.BuildListener;
+
+/**
+ * Our own personal build listener.
+ */
+public class AntTestListener implements BuildListener {
+    private int logLevel;
+
+    private StringBuffer buildLog = new StringBuffer();
+
+    /**
+     * Constructs a test listener which will ignore log events above the given level.
+     */
+    public AntTestListener(int logLevel) {
+        this.logLevel = logLevel;
+    }
+
+    /**
+     * Fired before any targets are started.
+     */
+    public void buildStarted(BuildEvent event) {
+    }
+
+    /**
+     * Fired after the last target has finished. This event will still be thrown if an error
+     * occurred during the build.
+     * 
+     * @see BuildEvent#getException()
+     */
+    public void buildFinished(BuildEvent event) {
+    }
+
+    /**
+     * Fired when a target is started.
+     * 
+     * @see BuildEvent#getTarget()
+     */
+    public void targetStarted(BuildEvent event) {
+        // System.out.println("targetStarted " + event.getTarget().getName());
+    }
+
+    /**
+     * Fired when a target has finished. This event will still be thrown if an error occurred during
+     * the build.
+     * 
+     * @see BuildEvent#getException()
+     */
+    public void targetFinished(BuildEvent event) {
+        // System.out.println("targetFinished " + event.getTarget().getName());
+    }
+
+    /**
+     * Fired when a task is started.
+     * 
+     * @see BuildEvent#getTask()
+     */
+    public void taskStarted(BuildEvent event) {
+        // System.out.println("taskStarted " + event.getTask().getTaskName());
+    }
+
+    /**
+     * Fired when a task has finished. This event will still be throw if an error occurred during
+     * the build.
+     * 
+     * @see BuildEvent#getException()
+     */
+    public void taskFinished(BuildEvent event) {
+        // System.out.println("taskFinished " + event.getTask().getTaskName());
+    }
+
+    /**
+     * Fired whenever a message is logged.
+     * 
+     * @see BuildEvent#getMessage()
+     * @see BuildEvent#getPriority()
+     */
+    public void messageLogged(BuildEvent event) {
+        if (event.getPriority() > logLevel) {
+            // ignore event
+            return;
+        }
+
+        buildLog.append(event.getMessage());
+    }
+
+    public String getLog() {
+        return buildLog.toString();
+    }
+
+}