From e05e852a3983050c5b5f873be258fe38a176788d Mon Sep 17 00:00:00 2001 From: Peter Donald Date: Sat, 2 Feb 2002 07:12:08 +0000 Subject: [PATCH] Add in a unit test that validates the dependency relationships between different packages. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271064 13f79535-47bb-0310-9956-ffa450edef68 --- .../myrmidon/DependencyMetricsTest.java | 215 ++++++++++++++++++ .../myrmidon/DependencyMetricsTest.java | 215 ++++++++++++++++++ 2 files changed, 430 insertions(+) create mode 100644 proposal/myrmidon/src/test/org/apache/myrmidon/DependencyMetricsTest.java create mode 100644 proposal/myrmidon/src/testcases/org/apache/myrmidon/DependencyMetricsTest.java diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/DependencyMetricsTest.java b/proposal/myrmidon/src/test/org/apache/myrmidon/DependencyMetricsTest.java new file mode 100644 index 000000000..69055ade2 --- /dev/null +++ b/proposal/myrmidon/src/test/org/apache/myrmidon/DependencyMetricsTest.java @@ -0,0 +1,215 @@ +/* + * Copyright (C) The Apache Software Foundation. All rights reserved. + * + * This software is published under the terms of the Apache Software License + * version 1.1, a copy of which has been included with this distribution in + * the LICENSE.txt file. + */ +package org.apache.myrmidon; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import jdepend.framework.JDepend; +import jdepend.framework.JavaPackage; +import junit.framework.TestCase; + +/** + * An abstract Unit test that can be used to test Dependency metrics + * fall in acceptable limits. + * + * @author Peter Donald + * @version $Revision$ $Date$ + */ +public class DependencyMetricsTest + extends TestCase +{ + private JDepend m_jDepend; + + public DependencyMetricsTest( final String name ) + { + super( name ); + } + + /** + * Sets up the test fixture. + * + * Called before every test case method. + */ + protected void setUp() + { + m_jDepend = new JDepend(); + + try + { + + m_jDepend.addDirectory( "src/java" ); + //m_jDepend.addDirectory( "src/main" ); + } + catch( final IOException ioe ) + { + fail( ioe.getMessage() ); + } + + m_jDepend.analyze(); + } + + /** + * Tears down the test fixture. + * + * Called after every test case method. + */ + protected void tearDown() + { + m_jDepend = null; + } + + /** + * Utility method to retrieve JDpenden instance that contains statistics. + */ + protected final JDepend getJDepend() + { + return m_jDepend; + } + + /** + * Make sure that the launcher classes in org.apache.myrmidon.launcher.* + * are completely decoupled from the rest of the system. + */ + public void testLauncherDecoupled() + { + final JDepend jDepend = getJDepend(); + final String name = "org.apache.myrmidon.launcher"; + final JavaPackage javaPackage = jDepend.getPackage( name ); + + final Collection afferentSet = javaPackage.getAfferents(); + final Iterator afferents = afferentSet.iterator(); + while( afferents.hasNext() ) + { + final JavaPackage afferent = (JavaPackage)afferents.next(); + final String afferentName = afferent.getName(); + if( !afferentName.startsWith( name ) ) + { + fail( "The launcher package " + name + " depends on external classes " + + "contained in " + afferentName + ". No classes besides " + + "those in the launcher hierarchy should be referenced" ); + } + } + } + + /** + * Make sure that the implementations of the myrmidon kernel components + * (ie org.apache.myrmidon.component.X.*) are not referenced by anyone + * except by other objects in the same package or child packages. + */ + public void testNoComponentImplSharing() + { + final JDepend jDepend = getJDepend(); + final Collection packageSet = jDepend.getPackages(); + + final Iterator packages = packageSet.iterator(); + while( packages.hasNext() ) + { + final JavaPackage javaPackage = (JavaPackage)packages.next(); + final String name = javaPackage.getName(); + final String componentPackage = "org.apache.myrmidon.component."; + if( !name.startsWith( componentPackage ) ) + { + continue; + } + final int start = componentPackage.length() + 1; + final int end = name.indexOf( '.', start ); + final String component = name.substring( end ); + + final Collection afferentSet = javaPackage.getAfferents(); + final Iterator afferents = afferentSet.iterator(); + while( afferents.hasNext() ) + { + final JavaPackage efferent = (JavaPackage)afferents.next(); + final String efferentName = efferent.getName(); + if( !efferentName.startsWith( component ) ) + { + fail( "The package " + name + " is referred to by classes " + + "contained in " + efferentName + ". No classes besides " + + "those part of the particular implementation of kernel " + + "component should reference the implementations" ); + } + } + } + } + + /** + * Make sure that aut does not depend on any other ant classes + * and thus can be cleanly decoupled. + */ + public void testAutDecoupled() + { + final JDepend jDepend = getJDepend(); + final Collection packageSet = jDepend.getPackages(); + + final Iterator packages = packageSet.iterator(); + while( packages.hasNext() ) + { + final JavaPackage javaPackage = (JavaPackage)packages.next(); + final String name = javaPackage.getName(); + if( !name.startsWith( "org.apache.aut" ) ) + { + continue; + } + + final Collection efferentSet = javaPackage.getEfferents(); + final Iterator efferents = efferentSet.iterator(); + while( efferents.hasNext() ) + { + final JavaPackage efferent = (JavaPackage)efferents.next(); + final String efferentName = efferent.getName(); + if( efferentName.startsWith( "org.apache.myrmidon" ) || + efferentName.startsWith( "org.apache.antlib" ) || + efferentName.startsWith( "org.apache.tools.ant" ) ) + { + fail( "The package " + name + " depends on classes " + + "contained in " + efferentName ); + } + } + } + } + + /** + * Make sure there are no circular dependencies between packages because + * circular dependencies are evil!!! + */ + public void testNoCircularity() + { + final JDepend jDepend = getJDepend(); + final Collection packageSet = jDepend.getPackages(); + final Iterator packages = packageSet.iterator(); + while( packages.hasNext() ) + { + final JavaPackage javaPackage = (JavaPackage)packages.next(); + if( javaPackage.containsCycle() ) + { + final ArrayList cycle = new ArrayList(); + javaPackage.collectCycle( cycle ); + + final ArrayList names = getPackageNames( cycle ); + fail( "The package " + javaPackage.getName() + " contains a cycle " + + "with a path " + names ); + } + } + } + + private ArrayList getPackageNames( final ArrayList cycle ) + { + final ArrayList names = new ArrayList(); + + final int size = cycle.size(); + for( int i = 0; i < size; i++ ) + { + final JavaPackage javaPackage = (JavaPackage)cycle.get( i ); + names.add( javaPackage.getName() ); + } + + return names; + } +} diff --git a/proposal/myrmidon/src/testcases/org/apache/myrmidon/DependencyMetricsTest.java b/proposal/myrmidon/src/testcases/org/apache/myrmidon/DependencyMetricsTest.java new file mode 100644 index 000000000..69055ade2 --- /dev/null +++ b/proposal/myrmidon/src/testcases/org/apache/myrmidon/DependencyMetricsTest.java @@ -0,0 +1,215 @@ +/* + * Copyright (C) The Apache Software Foundation. All rights reserved. + * + * This software is published under the terms of the Apache Software License + * version 1.1, a copy of which has been included with this distribution in + * the LICENSE.txt file. + */ +package org.apache.myrmidon; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import jdepend.framework.JDepend; +import jdepend.framework.JavaPackage; +import junit.framework.TestCase; + +/** + * An abstract Unit test that can be used to test Dependency metrics + * fall in acceptable limits. + * + * @author Peter Donald + * @version $Revision$ $Date$ + */ +public class DependencyMetricsTest + extends TestCase +{ + private JDepend m_jDepend; + + public DependencyMetricsTest( final String name ) + { + super( name ); + } + + /** + * Sets up the test fixture. + * + * Called before every test case method. + */ + protected void setUp() + { + m_jDepend = new JDepend(); + + try + { + + m_jDepend.addDirectory( "src/java" ); + //m_jDepend.addDirectory( "src/main" ); + } + catch( final IOException ioe ) + { + fail( ioe.getMessage() ); + } + + m_jDepend.analyze(); + } + + /** + * Tears down the test fixture. + * + * Called after every test case method. + */ + protected void tearDown() + { + m_jDepend = null; + } + + /** + * Utility method to retrieve JDpenden instance that contains statistics. + */ + protected final JDepend getJDepend() + { + return m_jDepend; + } + + /** + * Make sure that the launcher classes in org.apache.myrmidon.launcher.* + * are completely decoupled from the rest of the system. + */ + public void testLauncherDecoupled() + { + final JDepend jDepend = getJDepend(); + final String name = "org.apache.myrmidon.launcher"; + final JavaPackage javaPackage = jDepend.getPackage( name ); + + final Collection afferentSet = javaPackage.getAfferents(); + final Iterator afferents = afferentSet.iterator(); + while( afferents.hasNext() ) + { + final JavaPackage afferent = (JavaPackage)afferents.next(); + final String afferentName = afferent.getName(); + if( !afferentName.startsWith( name ) ) + { + fail( "The launcher package " + name + " depends on external classes " + + "contained in " + afferentName + ". No classes besides " + + "those in the launcher hierarchy should be referenced" ); + } + } + } + + /** + * Make sure that the implementations of the myrmidon kernel components + * (ie org.apache.myrmidon.component.X.*) are not referenced by anyone + * except by other objects in the same package or child packages. + */ + public void testNoComponentImplSharing() + { + final JDepend jDepend = getJDepend(); + final Collection packageSet = jDepend.getPackages(); + + final Iterator packages = packageSet.iterator(); + while( packages.hasNext() ) + { + final JavaPackage javaPackage = (JavaPackage)packages.next(); + final String name = javaPackage.getName(); + final String componentPackage = "org.apache.myrmidon.component."; + if( !name.startsWith( componentPackage ) ) + { + continue; + } + final int start = componentPackage.length() + 1; + final int end = name.indexOf( '.', start ); + final String component = name.substring( end ); + + final Collection afferentSet = javaPackage.getAfferents(); + final Iterator afferents = afferentSet.iterator(); + while( afferents.hasNext() ) + { + final JavaPackage efferent = (JavaPackage)afferents.next(); + final String efferentName = efferent.getName(); + if( !efferentName.startsWith( component ) ) + { + fail( "The package " + name + " is referred to by classes " + + "contained in " + efferentName + ". No classes besides " + + "those part of the particular implementation of kernel " + + "component should reference the implementations" ); + } + } + } + } + + /** + * Make sure that aut does not depend on any other ant classes + * and thus can be cleanly decoupled. + */ + public void testAutDecoupled() + { + final JDepend jDepend = getJDepend(); + final Collection packageSet = jDepend.getPackages(); + + final Iterator packages = packageSet.iterator(); + while( packages.hasNext() ) + { + final JavaPackage javaPackage = (JavaPackage)packages.next(); + final String name = javaPackage.getName(); + if( !name.startsWith( "org.apache.aut" ) ) + { + continue; + } + + final Collection efferentSet = javaPackage.getEfferents(); + final Iterator efferents = efferentSet.iterator(); + while( efferents.hasNext() ) + { + final JavaPackage efferent = (JavaPackage)efferents.next(); + final String efferentName = efferent.getName(); + if( efferentName.startsWith( "org.apache.myrmidon" ) || + efferentName.startsWith( "org.apache.antlib" ) || + efferentName.startsWith( "org.apache.tools.ant" ) ) + { + fail( "The package " + name + " depends on classes " + + "contained in " + efferentName ); + } + } + } + } + + /** + * Make sure there are no circular dependencies between packages because + * circular dependencies are evil!!! + */ + public void testNoCircularity() + { + final JDepend jDepend = getJDepend(); + final Collection packageSet = jDepend.getPackages(); + final Iterator packages = packageSet.iterator(); + while( packages.hasNext() ) + { + final JavaPackage javaPackage = (JavaPackage)packages.next(); + if( javaPackage.containsCycle() ) + { + final ArrayList cycle = new ArrayList(); + javaPackage.collectCycle( cycle ); + + final ArrayList names = getPackageNames( cycle ); + fail( "The package " + javaPackage.getName() + " contains a cycle " + + "with a path " + names ); + } + } + } + + private ArrayList getPackageNames( final ArrayList cycle ) + { + final ArrayList names = new ArrayList(); + + final int size = cycle.size(); + for( int i = 0; i < size; i++ ) + { + final JavaPackage javaPackage = (JavaPackage)cycle.get( i ); + names.add( javaPackage.getName() ); + } + + return names; + } +}