From fb64e130f8ad141c876b752935908f5c51af9521 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Tue, 11 Jul 2017 21:02:06 +0200 Subject: [PATCH 1/2] Memoization tests --- .../pmd/lang/java/oom/Metrics.java | 6 +- .../lang/java/oom/ParameterizedMetricKey.java | 16 +- .../lang/java/oom/signature/Signature.java | 20 +-- .../pmd/lang/java/oom/DataStructureTest.java | 163 ++++++++++++++++++ .../pmd/lang/java/oom/MetricsVisitorTest.java | 6 +- .../java/oom/ParameterizedMetricKeyTest.java | 113 ++++++++++++ .../pmd/lang/java/oom/ReinitialiserRule.java | 18 -- 7 files changed, 290 insertions(+), 52 deletions(-) create mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/oom/ParameterizedMetricKeyTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/oom/ReinitialiserRule.java diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/oom/Metrics.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/oom/Metrics.java index 47d8e5cac2..69016f35c0 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/oom/Metrics.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/oom/Metrics.java @@ -35,15 +35,13 @@ public final class Metrics { * * @return The top level package stats */ - /* default */ - static PackageStats getTopLevelPackageStats() { + /* default */ static PackageStats getTopLevelPackageStats() { return TOP_LEVEL_PACKAGE; } /** Sets whether computations are forced or not. Used for tests. */ - /* default */ - static void reset() { + /* default */ static void reset() { TOP_LEVEL_PACKAGE.reset(); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/oom/ParameterizedMetricKey.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/oom/ParameterizedMetricKey.java index 5de7b50d77..1fecf4ea48 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/oom/ParameterizedMetricKey.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/oom/ParameterizedMetricKey.java @@ -35,25 +35,13 @@ import net.sourceforge.pmd.lang.java.oom.api.MetricVersion; @Override public String toString() { - return "ParameterizedMetricKey{key=" + key + ", version=" + version + '}'; + return "ParameterizedMetricKey{key=" + key.name() + ", version=" + version.name() + '}'; } @Override public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - ParameterizedMetricKey that = (ParameterizedMetricKey) o; - - if (!key.equals(that.key)) { - return false; - } - return version.equals(that.version); + return this == o; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/oom/signature/Signature.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/oom/signature/Signature.java index e11efec86a..75dbbfa864 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/oom/signature/Signature.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/oom/signature/Signature.java @@ -13,26 +13,20 @@ import net.sourceforge.pmd.lang.java.ast.AccessNode; */ public abstract class Signature { + /** Visibility. */ public final Visibility visibility; - public Signature(Visibility visibility) { + /** + * Initialises the visibility. + * + * @param visibility The visibility of the signature + */ + protected Signature(Visibility visibility) { this.visibility = visibility; } - @Override - public boolean equals(Object o) { - return o instanceof Signature && visibility == ((Signature) o).visibility; - } - - - @Override - public int hashCode() { - return visibility.hashCode(); - } - - /** * The visibility of a node. */ diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/oom/DataStructureTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/oom/DataStructureTest.java index 25aafd7b3c..8d3e2ae8a2 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/oom/DataStructureTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/oom/DataStructureTest.java @@ -4,23 +4,39 @@ package net.sourceforge.pmd.lang.java.oom; +import static net.sourceforge.pmd.lang.java.oom.MetricsVisitorTest.parseAndVisitForClass15; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + import org.junit.Before; import org.junit.Test; import net.sourceforge.pmd.lang.java.ParserTst; +import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; +import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorReducedAdapter; import net.sourceforge.pmd.lang.java.ast.QualifiedName; +import net.sourceforge.pmd.lang.java.oom.api.ClassMetric; +import net.sourceforge.pmd.lang.java.oom.api.Metric.Version; +import net.sourceforge.pmd.lang.java.oom.api.MetricKey; +import net.sourceforge.pmd.lang.java.oom.api.MetricVersion; +import net.sourceforge.pmd.lang.java.oom.api.OperationMetric; import net.sourceforge.pmd.lang.java.oom.signature.FieldSigMask; import net.sourceforge.pmd.lang.java.oom.signature.FieldSignature; import net.sourceforge.pmd.lang.java.oom.signature.OperationSigMask; import net.sourceforge.pmd.lang.java.oom.signature.OperationSignature; +import net.sourceforge.pmd.lang.java.oom.testdata.MetricsVisitorTestData; /** * Tests functionality of the whole data structure (PackageStats, ClassStats, OperationStats). The behaviour of the @@ -30,13 +46,39 @@ import net.sourceforge.pmd.lang.java.oom.signature.OperationSignature; */ public class DataStructureTest extends ParserTst { + MetricKey classMetricKey = new MetricKey() { + @Override + public String name() { + return null; + } + + + @Override + public ClassMetric getCalculator() { + return new RandomMetric(); + } + }; + MetricKey opMetricKey = new MetricKey() { + @Override + public String name() { + return null; + } + + + @Override + public OperationMetric getCalculator() { + return new RandomMetric(); + } + }; private PackageStats pack; + @Before public void setUp() { pack = new PackageStats(); } + @Test public void testAddClass() { QualifiedName qname = QualifiedName.parseName("org.foo.Boo"); @@ -48,6 +90,7 @@ public class DataStructureTest extends ParserTst { assertNotNull(pack.getClassStats(qname, false)); } + @Test public void testAddOperation() { final String TEST = "package org.foo; class Boo{ " @@ -65,6 +108,7 @@ public class DataStructureTest extends ParserTst { assertTrue(pack.hasMatchingSig(qname, new OperationSigMask())); } + @Test public void testAddField() { final String TEST = "package org.foo; class Boo{ " @@ -82,4 +126,123 @@ public class DataStructureTest extends ParserTst { clazz.addField(fieldName, signature); assertTrue(pack.hasMatchingSig(qname, fieldName, new FieldSigMask())); } + + + @Test + public void memoizationTest() { + + final List res = new ArrayList<>(); + final PackageStats toplevel = Metrics.getTopLevelPackageStats(); + + ASTCompilationUnit acu = parseAndVisitForClass15(MetricsVisitorTestData.class); + + acu.jjtAccept(new JavaParserVisitorReducedAdapter() { + @Override + public Object visit(ASTMethodOrConstructorDeclaration node, Object data) { + res.add((int) toplevel.compute(opMetricKey, node, true, Version.STANDARD)); + return super.visit(node, data); + } + + + @Override + public Object visit(ASTAnyTypeDeclaration node, Object data) { + res.add((int) toplevel.compute(classMetricKey, node, true, Version.STANDARD)); + return super.visit(node, data); + } + }, null); + + System.out.println(); + + final List cmp = new ArrayList<>(); + + acu.jjtAccept(new JavaParserVisitorReducedAdapter() { + @Override + public Object visit(ASTMethodOrConstructorDeclaration node, Object data) { + cmp.add((int) toplevel.compute(opMetricKey, node, false, Version.STANDARD)); + return super.visit(node, data); + } + + + @Override + public Object visit(ASTAnyTypeDeclaration node, Object data) { + cmp.add((int) toplevel.compute(classMetricKey, node, false, Version.STANDARD)); + return super.visit(node, data); + } + }, null); + + assertEquals(res, cmp); + + } + + + @Test + public void forceMemoizationTest() { + + final List res = new ArrayList<>(); + final PackageStats toplevel = Metrics.getTopLevelPackageStats(); + + ASTCompilationUnit acu = parseAndVisitForClass15(MetricsVisitorTestData.class); + + acu.jjtAccept(new JavaParserVisitorReducedAdapter() { + @Override + public Object visit(ASTMethodOrConstructorDeclaration node, Object data) { + res.add((int) toplevel.compute(opMetricKey, node, true, Version.STANDARD)); + return super.visit(node, data); + } + + + @Override + public Object visit(ASTAnyTypeDeclaration node, Object data) { + res.add((int) toplevel.compute(classMetricKey, node, true, Version.STANDARD)); + return super.visit(node, data); + } + }, null); + + System.out.println(); + + final List cmp = new ArrayList<>(); + + acu.jjtAccept(new JavaParserVisitorReducedAdapter() { + @Override + public Object visit(ASTMethodOrConstructorDeclaration node, Object data) { + cmp.add((int) toplevel.compute(opMetricKey, node, true, Version.STANDARD)); + return super.visit(node, data); + } + + + @Override + public Object visit(ASTAnyTypeDeclaration node, Object data) { + cmp.add((int) toplevel.compute(classMetricKey, node, true, Version.STANDARD)); + return super.visit(node, data); + } + }, null); + + for (int i = 0; i < res.size(); i++) { + assertNotEquals(res.get(i), cmp.get(i)); + } + + } + + + /** + * Test metric. + */ + private class RandomMetric extends AbstractMetric implements ClassMetric, OperationMetric { + + private Random random = new Random(); + + + @Override + public double computeFor(ASTAnyTypeDeclaration node, MetricVersion version) { + return random.nextInt(); + } + + + @Override + public double computeFor(ASTMethodOrConstructorDeclaration node, MetricVersion version) { + return random.nextInt(); + } + } + + } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/oom/MetricsVisitorTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/oom/MetricsVisitorTest.java index 802668e4cc..759cfc34d7 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/oom/MetricsVisitorTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/oom/MetricsVisitorTest.java @@ -108,7 +108,7 @@ public class MetricsVisitorTest { } - private ASTCompilationUnit parseAndVisitForClass15(Class clazz) { + /* default */ static ASTCompilationUnit parseAndVisitForClass15(Class clazz) { return parseAndVisitForClass(clazz, "1.5"); } @@ -117,7 +117,7 @@ public class MetricsVisitorTest { // the classpath. Normally the IDE doesn't put source directories themselves // directly in the classpath, only // the output directories are in the classpath. - private ASTCompilationUnit parseAndVisitForClass(Class clazz, String version) { + private static ASTCompilationUnit parseAndVisitForClass(Class clazz, String version) { String sourceFile = clazz.getName().replace('.', '/') + ".java"; InputStream is = ClassTypeResolverTest.class.getClassLoader().getResourceAsStream(sourceFile); if (is == null) { @@ -133,7 +133,7 @@ public class MetricsVisitorTest { return parseAndVisitForString(source, version); } - private ASTCompilationUnit parseAndVisitForString(String source, String version) { + private static ASTCompilationUnit parseAndVisitForString(String source, String version) { LanguageVersionHandler languageVersionHandler = LanguageRegistry.getLanguage(JavaLanguageModule.NAME) .getVersion(version).getLanguageVersionHandler(); ASTCompilationUnit acu = (ASTCompilationUnit) languageVersionHandler diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/oom/ParameterizedMetricKeyTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/oom/ParameterizedMetricKeyTest.java new file mode 100644 index 0000000000..785199f28e --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/oom/ParameterizedMetricKeyTest.java @@ -0,0 +1,113 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.oom; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import net.sourceforge.pmd.lang.java.oom.api.ClassMetric; +import net.sourceforge.pmd.lang.java.oom.api.ClassMetricKey; +import net.sourceforge.pmd.lang.java.oom.api.MetricKey; +import net.sourceforge.pmd.lang.java.oom.api.MetricVersion; +import net.sourceforge.pmd.lang.java.oom.api.OperationMetricKey; + +/** + * @author Clément Fournier + */ +public class ParameterizedMetricKeyTest { + + @Test + public void testIdentity() { + for (ClassMetricKey key : ClassMetricKey.values()) { + ParameterizedMetricKey key1 = ParameterizedMetricKey.getInstance(key, Version.DUMMY1); + ParameterizedMetricKey key2 = ParameterizedMetricKey.getInstance(key, Version.DUMMY1); + assertEquals(key1, key2); + assertTrue(key1 == key2); + } + + for (OperationMetricKey key : OperationMetricKey.values()) { + ParameterizedMetricKey key1 = ParameterizedMetricKey.getInstance(key, Version.DUMMY1); + ParameterizedMetricKey key2 = ParameterizedMetricKey.getInstance(key, Version.DUMMY1); + assertEquals(key1, key2); + assertTrue(key1 == key2); + } + } + + + @Test + public void testVersioning() { + for (ClassMetricKey key : ClassMetricKey.values()) { + ParameterizedMetricKey key1 = ParameterizedMetricKey.getInstance(key, Version.DUMMY1); + ParameterizedMetricKey key2 = ParameterizedMetricKey.getInstance(key, Version.DUMMY2); + assertNotEquals(key1, key2); + assertFalse(key1 == key2); + } + + for (OperationMetricKey key : OperationMetricKey.values()) { + ParameterizedMetricKey key1 = ParameterizedMetricKey.getInstance(key, Version.DUMMY1); + ParameterizedMetricKey key2 = ParameterizedMetricKey.getInstance(key, Version.DUMMY2); + assertNotEquals(key1, key2); + assertFalse(key1 == key2); + } + } + + + @Test + public void testToString() { + for (ClassMetricKey key : ClassMetricKey.values()) { + ParameterizedMetricKey key1 = ParameterizedMetricKey.getInstance(key, Version.DUMMY1); + assertTrue(key1.toString().contains(key1.key.name())); + assertTrue(key1.toString().contains(key1.version.name())); + } + } + + + @Test + public void testAdHocMetricKey() { + MetricKey adHocKey = new MetricKey() { + @Override + public String name() { + return "metric"; + } + + + @Override + public ClassMetric getCalculator() { + return null; + } + }; + + MetricVersion adHocVersion = new MetricVersion() { + @Override + public String name() { + return "version"; + } + }; + + ParameterizedMetricKey key1 = ParameterizedMetricKey.getInstance(adHocKey, adHocVersion); + ParameterizedMetricKey key2 = ParameterizedMetricKey.getInstance(adHocKey, adHocVersion); + + assertNotNull(key1); + assertNotNull(key2); + assertTrue(key1 == key2); + assertEquals(key1, key2); + assertTrue(key1.toString().contains(key1.key.name())); + assertTrue(key1.toString().contains(key1.version.name())); + + } + + + private enum Version implements MetricVersion { + DUMMY1, + DUMMY2 + } + + +} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/oom/ReinitialiserRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/oom/ReinitialiserRule.java deleted file mode 100644 index 8803e7cd0b..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/oom/ReinitialiserRule.java +++ /dev/null @@ -1,18 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.oom; - -import org.junit.rules.ExternalResource; - -/** - * @author Clément Fournier - */ -public class ReinitialiserRule extends ExternalResource { - - @Override - protected void after() { - Metrics.reset(); - } -} From f44a08d9d5810269bd0c3fae9ac304e06c5f7d8a Mon Sep 17 00:00:00 2001 From: oowekyala Date: Fri, 14 Jul 2017 16:32:02 +0200 Subject: [PATCH 2/2] Fix memo tests --- .../pmd/lang/java/oom/DataStructureTest.java | 112 ++++++------------ 1 file changed, 34 insertions(+), 78 deletions(-) diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/oom/DataStructureTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/oom/DataStructureTest.java index 8d3e2ae8a2..37af812f68 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/oom/DataStructureTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/oom/DataStructureTest.java @@ -130,100 +130,56 @@ public class DataStructureTest extends ParserTst { @Test public void memoizationTest() { - - final List res = new ArrayList<>(); - final PackageStats toplevel = Metrics.getTopLevelPackageStats(); - ASTCompilationUnit acu = parseAndVisitForClass15(MetricsVisitorTestData.class); - acu.jjtAccept(new JavaParserVisitorReducedAdapter() { - @Override - public Object visit(ASTMethodOrConstructorDeclaration node, Object data) { - res.add((int) toplevel.compute(opMetricKey, node, true, Version.STANDARD)); - return super.visit(node, data); - } - - - @Override - public Object visit(ASTAnyTypeDeclaration node, Object data) { - res.add((int) toplevel.compute(classMetricKey, node, true, Version.STANDARD)); - return super.visit(node, data); - } - }, null); - - System.out.println(); - - final List cmp = new ArrayList<>(); - - acu.jjtAccept(new JavaParserVisitorReducedAdapter() { - @Override - public Object visit(ASTMethodOrConstructorDeclaration node, Object data) { - cmp.add((int) toplevel.compute(opMetricKey, node, false, Version.STANDARD)); - return super.visit(node, data); - } - - - @Override - public Object visit(ASTAnyTypeDeclaration node, Object data) { - cmp.add((int) toplevel.compute(classMetricKey, node, false, Version.STANDARD)); - return super.visit(node, data); - } - }, null); - - assertEquals(res, cmp); + List expected = visitWith(acu, true); + List real = visitWith(acu, false); + assertEquals(expected, real); } @Test public void forceMemoizationTest() { - - final List res = new ArrayList<>(); - final PackageStats toplevel = Metrics.getTopLevelPackageStats(); - ASTCompilationUnit acu = parseAndVisitForClass15(MetricsVisitorTestData.class); - acu.jjtAccept(new JavaParserVisitorReducedAdapter() { - @Override - public Object visit(ASTMethodOrConstructorDeclaration node, Object data) { - res.add((int) toplevel.compute(opMetricKey, node, true, Version.STANDARD)); - return super.visit(node, data); - } + List reference = visitWith(acu, true); + List real = visitWith(acu, true); + assertEquals(reference.size(), real.size()); - @Override - public Object visit(ASTAnyTypeDeclaration node, Object data) { - res.add((int) toplevel.compute(classMetricKey, node, true, Version.STANDARD)); - return super.visit(node, data); - } - }, null); - - System.out.println(); - - final List cmp = new ArrayList<>(); - - acu.jjtAccept(new JavaParserVisitorReducedAdapter() { - @Override - public Object visit(ASTMethodOrConstructorDeclaration node, Object data) { - cmp.add((int) toplevel.compute(opMetricKey, node, true, Version.STANDARD)); - return super.visit(node, data); - } - - - @Override - public Object visit(ASTAnyTypeDeclaration node, Object data) { - cmp.add((int) toplevel.compute(classMetricKey, node, true, Version.STANDARD)); - return super.visit(node, data); - } - }, null); - - for (int i = 0; i < res.size(); i++) { - assertNotEquals(res.get(i), cmp.get(i)); + // we force recomputation so each result should be different + for (int i = 0; i < reference.size(); i++) { + assertNotEquals(reference.get(i), real.get(i)); } - } + private List visitWith(ASTCompilationUnit acu, final boolean force) { + final PackageStats toplevel = Metrics.getTopLevelPackageStats(); + + final List result = new ArrayList<>(); + + acu.jjtAccept(new JavaParserVisitorReducedAdapter() { + @Override + public Object visit(ASTMethodOrConstructorDeclaration node, Object data) { + result.add((int) toplevel.compute(opMetricKey, node, force, Version.STANDARD)); + return super.visit(node, data); + } + + + @Override + public Object visit(ASTAnyTypeDeclaration node, Object data) { + result.add((int) toplevel.compute(classMetricKey, node, force, Version.STANDARD)); + return super.visit(node, data); + } + }, null); + + return result; + } + + + /** * Test metric. */