From a79d3e6557381cdad139d1ab2ee5d7921f78a081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 14 Nov 2024 16:13:30 +0100 Subject: [PATCH] Add unit tests --- .../java/internal/JavaLanguageProperties.java | 2 +- .../internal/infer/InferenceContext.java | 1 + .../internal/infer/TypeInferenceLogger.java | 10 +- .../internal/infer/InferenceCtxUnitTests.java | 93 +++++++++++++++++++ 4 files changed, 103 insertions(+), 3 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageProperties.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageProperties.java index 7fafea029e..7590d48f6f 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageProperties.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageProperties.java @@ -22,7 +22,7 @@ public class JavaLanguageProperties extends JvmLanguagePropertyBundle { PropertyFactory.enumProperty("xTypeInferenceLogging", EnumUtils.getEnumMap(InferenceLoggingVerbosity.class)) .desc("Verbosity of the type inference logging") - .defaultValue(InferenceLoggingVerbosity.DISABLED) + .defaultValue(InferenceLoggingVerbosity.VERBOSE) .build(); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/InferenceContext.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/InferenceContext.java index 73b843439f..8cc251fa0e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/InferenceContext.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/InferenceContext.java @@ -525,6 +525,7 @@ final class InferenceContext { * we try again to make progress. */ private boolean solve(VarWalkStrategy walker) { + graphWasChanged = false; incorporate(); while (walker.hasNext()) { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/TypeInferenceLogger.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/TypeInferenceLogger.java index 2c9cfff9ef..cb7fe3e6d3 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/TypeInferenceLogger.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/TypeInferenceLogger.java @@ -22,6 +22,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import net.sourceforge.pmd.lang.java.ast.JavaNode; +import net.sourceforge.pmd.lang.java.internal.JavaLanguageProperties; import net.sourceforge.pmd.lang.java.symbols.JTypeDeclSymbol; import net.sourceforge.pmd.lang.java.types.JMethodSig; import net.sourceforge.pmd.lang.java.types.JTypeMirror; @@ -34,6 +35,12 @@ import net.sourceforge.pmd.util.StringUtil; /** * A strategy to log the execution traces of {@link Infer}. + * The default does nothing, so the logger calls can be optimized out + * at runtime, while not having to check that logging is enabled at the + * call sites. + * + *

To enable logging for the CLI, use the language property ({@link JavaLanguageProperties}) + * {@code xTypeInferenceLogging}. From tests, see {@code JavaParsingHelper#logTypeInferenceVerbose()}. */ @SuppressWarnings("PMD.UncommentedEmptyMethodBody") public interface TypeInferenceLogger { @@ -64,8 +71,7 @@ public interface TypeInferenceLogger { default void applicabilityTest(InferenceContext ctx) { } - default void finishApplicabilityTest() { - } + default void finishApplicabilityTest() { } default void startArgsChecks() { } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/internal/infer/InferenceCtxUnitTests.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/internal/infer/InferenceCtxUnitTests.java index 5e33c6dd01..ba1d834261 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/internal/infer/InferenceCtxUnitTests.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/internal/infer/InferenceCtxUnitTests.java @@ -8,7 +8,10 @@ import static net.sourceforge.pmd.lang.java.types.TestUtilitiesForTypesKt.captur import static net.sourceforge.pmd.lang.java.types.internal.infer.BaseTypeInferenceUnitTest.Bound.eqBound; import static net.sourceforge.pmd.lang.java.types.internal.infer.BaseTypeInferenceUnitTest.Bound.lower; import static net.sourceforge.pmd.lang.java.types.internal.infer.BaseTypeInferenceUnitTest.Bound.upper; +import static net.sourceforge.pmd.util.CollectionUtil.setOf; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsInAnyOrder; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -19,11 +22,17 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import java.util.List; +import java.util.Set; + +import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.Test; import net.sourceforge.pmd.lang.java.types.JTypeMirror; import net.sourceforge.pmd.lang.java.types.TypeOps; import net.sourceforge.pmd.lang.java.types.internal.infer.InferenceVar.BoundKind; +import net.sourceforge.pmd.lang.java.types.internal.infer.VarWalkStrategy.GraphWalk; +import net.sourceforge.pmd.util.IteratorUtil; /** * @@ -331,4 +340,88 @@ class InferenceCtxUnitTests extends BaseTypeInferenceUnitTest { assertThat(a, hasBoundsExactly(upper(ts.BOOLEAN.box()))); } + + private static @NotNull List> createBatchSetsFromGraph(InferenceContext ctx) { + GraphWalk graphWalk = new GraphWalk(ctx, false); + List> batches = IteratorUtil.toList(graphWalk); + return batches; + } + + @Test + void testGraphBuilding() { + InferenceContext ctx = emptyCtx(); + InferenceVar a = newIvar(ctx); + InferenceVar b = newIvar(ctx); + + List> batches = createBatchSetsFromGraph(ctx); + // no dependency: unordered + assertThat(batches, containsInAnyOrder(setOf(a), setOf(b))); + } + + @Test + void testGraphBuildingWithDependency() { + InferenceContext ctx = emptyCtx(); + InferenceVar a = newIvar(ctx); + InferenceVar b = newIvar(ctx); + + // a -> b + addSubtypeConstraint(ctx, a, ts.arrayType(b)); + + List> batches = createBatchSetsFromGraph(ctx); + + assertThat(batches, contains(setOf(b), setOf(a))); + } + + @Test + void testGraphBuildingWithDependency2() { + InferenceContext ctx = emptyCtx(); + InferenceVar a = newIvar(ctx); + InferenceVar b = newIvar(ctx); + + // a -> b + // b -> a (because of propagation) + addSubtypeConstraint(ctx, a, b); + + List> batches = createBatchSetsFromGraph(ctx); + + assertThat(batches, contains(setOf(b, a))); + } + + + + + @Test + void testGraphBuildingWithExtraDependency() { + InferenceContext ctx = emptyCtx(); + InferenceVar a = newIvar(ctx); + InferenceVar b = newIvar(ctx); + + // b -> a + ctx.addInstantiationDependencies(setOf(b), setOf(a)); + + List> batches = createBatchSetsFromGraph(ctx); + + assertThat(batches, contains(setOf(a), setOf(b))); + } + + @Test + void testGraphBuildingWithDependencyCycle() { + InferenceContext ctx = emptyCtx(); + InferenceVar a = newIvar(ctx); + InferenceVar b = newIvar(ctx); + InferenceVar c = newIvar(ctx); + + // a -> b, b -> a, + // a -> c, b -> c + a.addBound(BoundKind.UPPER, b); + a.addBound(BoundKind.EQ, listType(c)); + b.addBound(BoundKind.LOWER, a); + b.addBound(BoundKind.LOWER, listType(c)); + + + List> batches = createBatchSetsFromGraph(ctx); + + assertThat(batches, contains(setOf(c), setOf(b, a))); + } + }