Lightweight analysis tool for detecting mutability in Java classes

Overview

Latest Version Email Join the chat at https://gitter.im/MutabilityDetector/main Build Status

What is Mutability Detector?

Mutability Detector is designed to analyse Java classes and report on whether instances of a given class are immutable. It can be used:

  • In a unit test, with an assertion like assertImmutable(MyClass.class). Is your class actually immutable? What about after that change you just made?
  • As a FindBugs plugin. Those classes you annotated with @Immutable, are they actually?
  • At runtime. Does your API require being given immutable objects?
  • From the command line. Do you want to quickly run Mutability Detector over an entire code base?

Why Try To Detect Mutability?

Developing classes to be immutable has several benefits. An immutable object is one which cannot be changed once it is constructed. While writing concurrent programs, using immutable objects can greatly simplify complex systems, as sharing an object across threads is much safer. There are a few rules for what makes an object immutable, and it is easy to break the rules and render the object unsafe. This could lead to subtle, hard-to-detect bugs which could lower the integrity of the system. Using an automated tool to recognise mutability where it's not intended can reduce the complexity of writing immutable classes.

Mutability Detector analyses on the strict side, very few classes are found to be perfectly immutable, for instance, java.lang.String and java.lang.Integer are not immutable because of a non-final field, and primitive array field, respectively. Mutability Detector will not be released under a 1.0 version until these cases can be correctly analysed.

If this sounds like it may be interesting or useful to you, continue reading for more information on getting started. You may also want to take a look at the Mutability Detector Blog.

Getting Started

To use Mutability Detector directly, either from the command line, at runtime in your application, or as part of your unit tests, grab the jar available from Maven Central. Or you can declare it in your Maven-compatible build tool, with the following coordinates:

<dependency>
    <groupId>org.mutabilitydetector</groupId>
    <artifactId>MutabilityDetector</artifactId>
    <version>[latest version here]</version>
    <scope>test</scope>
</dependency>

Latest Version

Using Mutability Detector in Unit Testing

Just add MutabilityDetector to your unit testing classpath. Adding your first assertion is as simple as:

import static org.mutabilitydetector.unittesting.MutabilityAssert.assertImmutable;

@Test public void checkMyClassIsImmutable() {
    assertImmutable(MyClass.class); 
}

Though it is possible (or likely) that you will have to configure the assertion to deal with any false positives that arise. See the JavaDoc on MutabilityAssert for further information.

Using Mutability Detector from the Command Line

An example of how to run it is probably the most useful. If you want to analyse MyCodebase.jar use:

java -jar MutabilityDetector.jar -classpath path/to/MyCodebase.jar

Mutability Detector can handle jars as seen above, or directories of class files (thanks go to the authors of classpath-explorer). So if your codebase was in the filesystem as directories and .class files, and the directory MyCodebase was the root of that, you could run:

java -jar MutabilityDetector.jar -classpath path/to/MyCodebase

The output is a list of the analysed classes against the result of asking "Is immutable?", ie. IMMUTABLE, NOT_IMMUTABLE, EFFECTIVELY_IMMUTABLE.

Execute java -jar MutabilityDetector.jar --help for a complete listing of the command line options.

Using Mutability Detector within Your Application

It is possible to use Mutability Detector at runtime. For example, consider if you have a library which requires that objects passed to it are immutable. On receiving such an object, you can ask Mutability Detector if it is actually immutable.

Check out the code snippet in this example, which shows correct usage against trunk code.

FindBugs Plugin

To have Mutability Detector inspect your classes during a FindBugs analysis, grab the MutabilityDetector4FindBugs jar, and configure it to be picked up by FindBugs during a normal analysis, as described here.

Mutability Detector will perform it's analysis on any classes annotated with @Immutable.

MutabilityDetector4FindBugs is also available from Maven Central, with the following coordinates:

<dependency>
    <groupId>org.mutabilitydetector</groupId>
    <artifactId>MutabilityDetector4FindBugs</artifactId>
    <version>[latest version here]</version>
    <scope>test</scope>
</dependency>

MutabilityDetector4FindBugs Latest Version

Comments
  • Maven build failure due to multiple test failures

    Maven build failure due to multiple test failures

    Whilst fixing #33, there was a build failure with the maven build of @MutabilityDetector, due to multiple test failures, see gist https://gist.github.com/4420898.

    Issue was temporarily resolved by building @MutabilityDetector by selecting the skip tests option in the maven build setting (Run Configuration).

    On examining the tests, its appears these are minor typos in the expected aspect of the test cases!

    bug question Eclipse CLI maven Windows 
    opened by neomatrix369 15
  • Replace Guava with Java 8

    Replace Guava with Java 8

    0.9.6 is the last release which will support being executed on pre-Java 8 JVMs, so we are now free to use Java 8 features. Currently, MutabilityDetector includes the Guava library as part of it's shaded jar. The less dependencies in this jar the better, and there's a decent chance one can be removed. I can't quite remember everything Guava is used for, but it's possible that it's limited to Optional, Function/Predicate, and FluentIterable, which can all be replaced by Java 8 features*. Also, it will mean we can remove some icky code that's a direct result of including Guava in the jar.

    This issue will be completed when Guava can be removed from the classpath, or closed as not worth it, if it's found that not everything can be reasonably replaced by Java 8 features.

    • not that Guava doesn't have lots of other cool and useful stuff, I'm not saying it's bad, just that usage is pretty limited.
    up-for-grabs 
    opened by Grundlefleck 13
  • Can Subclass checking is incorrect when inner class constructs instance of outer, immutable class

    Can Subclass checking is incorrect when inner class constructs instance of outer, immutable class

    The following class is considered mutable:

    public class OnlyPrivateConstructors {
        private final String field;
    
        private OnlyPrivateConstructors(String field) {
            this.field = field;
        }
    
        public String getField() {
            return field;
        }
    
        public static class Builder {
            public OnlyPrivateConstructors build() {
                return new OnlyPrivateConstructors("hi");
            }
        }
    }
    

    With the message:

    Expected: org.mutabilitydetector.issues.OnlyPrivateConstructors to be IMMUTABLE
         but: org.mutabilitydetector.issues.OnlyPrivateConstructors is actually NOT_IMMUTABLE
        Reasons:
            Can be subclassed, therefore parameters declared to be this type could be mutable subclasses at runtime. [Class: org.mutabilitydetector.issues.OnlyPrivateConstructors]
        Allowed reasons:
            None.
    

    If the call to new OnlyPrivateConstructors() is commented out, the analysis correctly calls this class immutable. This pattern is a common way of implementing the Builder pattern (as described in Effective Java, iirc). It should not render the outer class as immutable.

    opened by Grundlefleck 13
  • java.util.Optional is considered mutable

    java.util.Optional is considered mutable

    After looking at the test results once issue #56, I noticed this in one of the error messages from the test:

    Field can have a mutable type (java.util.Optional) assigned to it. [Field: cause, Class: com.equalexperts.logging.LogicalLogRecord]

    I think that instances of java.util.Optional should probably be considered immutable so long as the class they are referencing is immutable. It's not in my case, as java.lang.Throwable isn't really immutable, but I suspect that's not why the error was raised.

    Thoughts?

    opened by seanjreilly 12
  • Add support for immutable collections of Google Guava

    Add support for immutable collections of Google Guava

    Google Guava provides several immutable utility classes, for example ImmutableList.

    If there is an assignment to a final field in a constructor like

    this.foo = ImmutableList.of();
    

    it is reported as

    org.mutabilitydetector.unittesting.MutabilityAssertionError: 
      Expected: ... to be IMMUTABLE
           but: ... is actually NOT_IMMUTABLE
          Reasons:
              Field can have an abstract type (com.google.common.collect.ImmutableList) assigned to it. [Field: foo, Class: ...]
          Allowed reasons:
              None.
    
    enhancement newcomer 
    opened by heri333 12
  • Migrate from Google Code to GitHub

    Migrate from Google Code to GitHub

    Original author: [email protected] (July 19, 2012 20:43:27)

    It has been suggested that I move the project from googlecode to GitHub to improve the likelihood of collaboration.

    I'm open to the idea, but a bit wary of the problems it may cause:

    • transferring wiki/issues etc
    • confusion for users having two sites (or the problem of closing the google code version altogether and having old links not work)
    • safely migrating version control history

    Intended benefits are:

    • increased collaboration, GitHub provides a much easier way of suggesting improvements by way of pull requests
    • would be easier to stop using a nested scm structure (googlecode project holds 3 projects in one)

    I'm inclined to be a bit lazy about this, and maybe see if there is more desire for collaborating.

    Original issue: http://code.google.com/p/mutability-detector/issues/detail?id=28

    imported 
    opened by Grundlefleck 12
  • Possible Java 8 issue

    Possible Java 8 issue

    I'm testing that each value in an enum is immutable. Here's a rough example:

        @Test
        public void enumInstance_shouldBeEffectivelyImmutable() throws Exception {
            assertInstancesOf(MyEnum.FOO.getClass(), areImmutable());
        }
    

    Compiling and running in Java 7 works with no problems. However, when I try the same thing using Java 8 I get a big nasty error (stack trace included below).

    org.mutabilitydetector.checkers.MutabilityAnalysisException: 
    An unhandled error occurred. Please read message at end of this output.
    
    Class being analysed: uk.gov.gds.performance.collector.CollectorLogMessage
    Checker that failed: CanSubclassChecker
    Classes analysed so far:
    
    An unhandled error occurred. This is probably my fault, not yours, and I am sorry.
    I'd love to get an opportunity to fix this, please report as an issue at:
     https://github.com/MutabilityDetector/MutabilityDetector/issues/ 
    Pasting in this error message and stack trace, and if possible, 
    information about the code causing the error. 
    For example, one of: 
        .class files (preferably with source);
        compilable .java files; 
        a jar (again preferably with source);
        or, if your project is open source, information on where I can get the code from
            (I'm happy to checkout and build your project in order to investigate the error).
    
    Apologies, and thank you for using Mutability Detector.
    
    
        at org.mutabilitydetector.checkers.UnhandledExceptionBuilder.unhandledException(UnhandledExceptionBuilder.java:54)
        at org.mutabilitydetector.checkers.CheckerRunner.attemptRecovery(CheckerRunner.java:79)
        at org.mutabilitydetector.checkers.CheckerRunner.run(CheckerRunner.java:66)
        at org.mutabilitydetector.checkers.AllChecksRunner.runCheckers(AllChecksRunner.java:65)
        at org.mutabilitydetector.ThreadUnsafeAnalysisSession.requestAnalysis(ThreadUnsafeAnalysisSession.java:118)
        at org.mutabilitydetector.ThreadUnsafeAnalysisSession.resultFor(ThreadUnsafeAnalysisSession.java:104)
        at org.mutabilitydetector.unittesting.MutabilityAsserter.getResultFor(MutabilityAsserter.java:184)
        at org.mutabilitydetector.unittesting.MutabilityAsserter.assertInstancesOf(MutabilityAsserter.java:109)
        at org.mutabilitydetector.unittesting.MutabilityAssert.assertInstancesOf(MutabilityAssert.java:658)
        at com.equalexperts.logging.LogMessageContractTest.enumInstance_shouldBeEffectivelyImmutable(LogMessageContractTest.java:67)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
        at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
        at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
        at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
        at org.junit.runners.Suite.runChild(Suite.java:127)
        at org.junit.runners.Suite.runChild(Suite.java:26)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
        at org.junit.runners.Suite.runChild(Suite.java:127)
        at org.junit.runners.Suite.runChild(Suite.java:26)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
        at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
        at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)
        at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:202)
        at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:65)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
    Caused by: java.lang.IllegalArgumentException
        at org.mutabilitydetector.repackaged.org.objectweb.asm.ClassReader.<init>(ClassReader.java:167)
        at org.mutabilitydetector.repackaged.org.objectweb.asm.ClassReader.<init>(ClassReader.java:153)
        at org.mutabilitydetector.repackaged.org.objectweb.asm.ClassReader.<init>(ClassReader.java:468)
        at org.mutabilitydetector.checkers.CheckerRunner.analyseFromDefaultClassLoader(CheckerRunner.java:99)
        at org.mutabilitydetector.checkers.CheckerRunner.run(CheckerRunner.java:63)
        ... 49 more
    
    
    opened by seanjreilly 11
  • Immutability test failing

    Immutability test failing

    import java.util.ArrayList;
    import java.util.List;
    
    public final class Student {
        private final int id;
        private final String name;
        private final List<String> hobbies;
    
        Student(int id, String name, List<String> hobbies) {
            this.id = id;
            this.name = name;
            this.hobbies = hobbies;
        }
    
        public int getId() {
            return id;
        }
    
        public String getName() {
            return name;
        }
    
        public List<String> getHobbies() {
            return new ArrayList<> (hobbies);
        }
    
    }
    
    

    When I tried to test for immutability using "assertImmutable(Student.class);", I am getting following error.

    Attempt to wrap mutable collection using a non-whitelisted unmodifiable wrapper method. [Field: hobbies.....]

    opened by harikrishna553 10
  • The fix for #90 is missing test coverage

    The fix for #90 is missing test coverage

    Issue #90 has been fixed, but the fix was merged without test coverage. This issue is to provide test coverage to help prevent regressions of the problem that led to #90.

    newcomer up-for-grabs 
    opened by Grundlefleck 9
  • Improve error message for Collections being wrapped without safe copy

    Improve error message for Collections being wrapped without safe copy

    Currently the error message for a collection field being wrapped without a safe copy is "Attempts to wrap mutable collection type without safely performing a copy first". It would be useful to provide a hint how a safe copy can be performed for the current use case. For instance for a List this can be achieved with:

    Collections.unmodifiableList(new ArrayList(sourceList));
    

    The goal of this issue is to improve the current error message with such hints how the copy can be done so that Mutability Detector does not report an error anymore.

    Here a test which asserts the current error message:

        public final static class ClassWrappingCollectionWithoutCopy {
            private final Collection<String> collection;
    
            public ClassWrappingCollectionWithoutCopy(Collection<String> collection) {
                this.collection = Collections.unmodifiableCollection(collection);
            }
        }
    
        @Test
        public void isImmutableMutableTypeToField_ClassWrappingCollectionWithoutCopy() throws Exception {
            try {
                assertImmutable(ClassWrappingCollectionWithoutCopy.class);
                fail("Error should be thrown");
            } catch (MutabilityAssertionError e) {
                assertThat(e.getMessage(), is("\n"+
                        "Expected: org.mutabilitydetector.ErrorLocationTest$ClassWrappingCollectionWithoutCopy to be IMMUTABLE\n" +
                        "     but: org.mutabilitydetector.ErrorLocationTest$ClassWrappingCollectionWithoutCopy is actually NOT_IMMUTABLE\n" +
                        "    Reasons:\n" +
                        "        Attempts to wrap mutable collection type without safely performing a copy first. [Field: collection, Class: org.mutabilitydetector.ErrorLocationTest$ClassWrappingCollectionWithoutCopy]\n" +
                        "    Allowed reasons:\n" +
                        "        None."));
            }
        }
    
    newcomer up-for-grabs 
    opened by marcgs 9
  • Support List.of et al as creating immutable collections

    Support List.of et al as creating immutable collections

    Java 11 (I think) introduced List.of() methods that return immutable collections. Mutability Detector should understand that calls to this method will produce an immutable collection, so that if they are assigned to a field of type List, it's not considered mutable.

    List.of happens to be the only one I mentioned, there is also, at least Set.of, I'm not sure if there are others in JDK11. We should support them all.

    opened by Grundlefleck 8
  • `java.util.Arrays` shouldn't be marked as `IMMUTABLE`

    `java.util.Arrays` shouldn't be marked as `IMMUTABLE`

    Similarly to

    java.util.Arrays#sort(int[]) modifies the state of the parameters, therefore the method isn't pure, hence it's confusing to call the otherwise stateless class as IMMUTABLE.

        @Test
        void validate_Arrays() {
            var analysisSession = DefaultCachingAnalysisSession.createWithCurrentClassPath(NO_CONFIGURATION);
            assertEquals(NOT_IMMUTABLE, analysisSession.resultFor(Dotted.fromClass(Arrays.class)).isImmutable);
        }
    

    results in

    expected: <NOT_IMMUTABLE> but was: <IMMUTABLE>
    Expected :NOT_IMMUTABLE
    Actual   :IMMUTABLE
    
    opened by paplorinc 0
  • `StringBuilder` shouldn't be marked as IMMUTABLE

    `StringBuilder` shouldn't be marked as IMMUTABLE

    StringBuilder is definitely NOT immutable, but most of the mutations seem to happen in the parent, in AbstractStringBuilder which don't seem to be considered:

        @Test
        void validate_StringBuilder() {
            var analysisSession = DefaultCachingAnalysisSession.createWithCurrentClassPath(NO_CONFIGURATION);
            assertEquals(NOT_IMMUTABLE, analysisSession.resultFor(Dotted.fromClass(StringBuilder.class)).isImmutable);
        }
    

    results in

    expected: <NOT_IMMUTABLE> but was: <IMMUTABLE>
    Expected :NOT_IMMUTABLE
    Actual   :IMMUTABLE
    
    opened by paplorinc 0
  • Add `java.lang.Math` to `JdkConfiguration` whitelist

    Add `java.lang.Math` to `JdkConfiguration` whitelist

    https://github.com/MutabilityDetector/MutabilityDetector/blob/master/src/main/java/org/mutabilitydetector/config/JdkConfiguration.java#L73 should contain java.lang.Math as well.

    Field is visible outwith this class, and is not declared final
    

    referring to https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/lang/Math.java#L3295-L3296, which are probably opened for testability anyway.

    opened by paplorinc 0
  • StackOverflowError in MutableTypeToFieldChecker

    StackOverflowError in MutableTypeToFieldChecker

    Steps to reproduce: Add https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-params/5.9.1 dependency and run the following test:

        @Test
        void validate_FieldConversionMapping() throws Exception {
            var analysisSession = DefaultCachingAnalysisSession.createWithCurrentClassPath(NO_CONFIGURATION);
            analysisSession.resultFor(Dotted.fromClass(FieldConversionMapping.class));
        }
    

    you'll get:

    
    
    An unhandled error occurred. Please read message at end of this output.
    
    Class being analysed: org.junit.jupiter.params.shadow.com.univocity.parsers.common.fields.FieldConversionMapping
    Checker that failed: MutableTypeToFieldChecker
    Classes analysed so far:
    
    An unhandled error occurred while analysing the class 'org.junit.jupiter.params.shadow.com.univocity.parsers.common.fields.FieldConversionMapping'.
    
    This is probably my fault, not yours, and I am sorry.
    I'd love to get an opportunity to fix this, please report as an issue at:
     https://github.com/MutabilityDetector/MutabilityDetector/issues/ 
    Pasting in this error message and stack trace, and if possible, 
    information about the code causing the error. 
    For example, one of: 
        .class files (preferably with source);
        compilable .java files; 
        a jar (again preferably with source);
        or, if your project is open source, information on where I can get the code from
            (I'm happy to checkout and build your project in order to investigate the error).
    
    Apologies, and thank you for using Mutability Detector.
    
    
    org.mutabilitydetector.checkers.MutabilityAnalysisException: 
    An unhandled error occurred. Please read message at end of this output.
    
    Class being analysed: org.junit.jupiter.params.shadow.com.univocity.parsers.common.fields.FieldConversionMapping
    Checker that failed: MutableTypeToFieldChecker
    Classes analysed so far:
    
    An unhandled error occurred while analysing the class 'org.junit.jupiter.params.shadow.com.univocity.parsers.common.fields.FieldConversionMapping'.
    
    This is probably my fault, not yours, and I am sorry.
    I'd love to get an opportunity to fix this, please report as an issue at:
     https://github.com/MutabilityDetector/MutabilityDetector/issues/ 
    Pasting in this error message and stack trace, and if possible, 
    information about the code causing the error. 
    For example, one of: 
        .class files (preferably with source);
        compilable .java files; 
        a jar (again preferably with source);
        or, if your project is open source, information on where I can get the code from
            (I'm happy to checkout and build your project in order to investigate the error).
    
    Apologies, and thank you for using Mutability Detector.
    
    
    	at app//org.mutabilitydetector.checkers.UnhandledExceptionBuilder.unhandledException(UnhandledExceptionBuilder.java:62)
    	at app//org.mutabilitydetector.checkers.CheckerRunner.attemptRecovery(CheckerRunner.java:121)
    	at app//org.mutabilitydetector.checkers.CheckerRunner.runVisitor(CheckerRunner.java:89)
    	at app//org.mutabilitydetector.checkers.CheckerRunner.run(CheckerRunner.java:69)
    	at app//org.mutabilitydetector.checkers.AllChecksRunner.runCheckers(AllChecksRunner.java:75)
    	at app//org.mutabilitydetector.DefaultCachingAnalysisSession.requestAnalysis(DefaultCachingAnalysisSession.java:141)
    	at app//org.mutabilitydetector.DefaultCachingAnalysisSession.resultFor(DefaultCachingAnalysisSession.java:120)
    	at app//com.lorinc.pap.statest.visitor.PureStMethodAnalyzerTest.validate_FieldConversionMapping(PureStMethodAnalyzerTest.java:110)
    	at [email protected]/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at [email protected]/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    	at [email protected]/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	at [email protected]/java.lang.reflect.Method.invoke(Method.java:566)
    	at app//org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
    	at app//org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    	at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    	at app//org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
    	at app//org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
    	at app//org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
    	at app//org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
    	at app//org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
    	at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    	at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    	at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    	at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    	at app//org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
    	at app//org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
    	at app//org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
    	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    	at app//org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
    	at app//org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
    	at app//org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
    	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
    	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    	at app//org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    	at [email protected]/java.util.ArrayList.forEach(ArrayList.java:1541)
    	at app//org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    	at app//org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    	at [email protected]/java.util.ArrayList.forEach(ArrayList.java:1541)
    	at app//org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    	at app//org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    	at app//org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
    	at app//org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    	at app//org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
    	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
    	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
    	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
    	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
    	at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
    	at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
    	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
    	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
    	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
    	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
    	at [email protected]/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at [email protected]/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    	at [email protected]/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	at [email protected]/java.lang.reflect.Method.invoke(Method.java:566)
    	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
    	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
    	at com.sun.proxy.$Proxy2.stop(Unknown Source)
    	at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
    	at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
    	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
    	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
    	at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
    	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
    	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
    	at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
    	at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
    Caused by: org.mutabilitydetector.checkers.MutabilityAnalysisException: 
    An unhandled error occurred. Please read message at end of this output.
    
    Class being analysed: org.junit.jupiter.params.shadow.com.univocity.parsers.common.fields.AbstractConversionMapping
    Checker that failed: MutableTypeToFieldChecker
    Classes analysed so far:
        java.util.LinkedHashMap$LinkedValues
        java.util.TreeMap$AscendingSubMap$AscendingEntrySetView
        org.junit.jupiter.params.shadow.com.univocity.parsers.common.fields.FieldConversionMapping$4
        java.util.LinkedHashMap
        java.util.LinkedHashMap$Entry
        java.util.TreeMap$AscendingSubMap
        java.util.TreeMap$Entry
        java.util.Map
        java.util.TreeMap$KeySet
        org.junit.jupiter.params.shadow.com.univocity.parsers.common.fields.FieldConversionMapping$3
        java.util.ArrayList
        java.util.LinkedHashMap$LinkedEntrySet
        java.util.TreeMap
        java.util.TreeMap$DescendingSubMap
        java.util.HashMap$KeySet
        java.util.List
        java.util.TreeMap$EntrySet
        java.util.Comparator
        java.util.TreeMap$Values
        java.util.HashMap$TreeNode
        org.junit.jupiter.params.shadow.com.univocity.parsers.common.fields.FieldConversionMapping$1
        java.util.HashMap$Values
        java.util.NavigableMap
        java.util.LinkedHashMap$LinkedKeySet
        org.junit.jupiter.params.shadow.com.univocity.parsers.common.fields.FieldConversionMapping$2
        java.util.HashMap$EntrySet
        java.util.HashMap
        java.lang.Object
        java.util.HashMap$Node
        java.util.TreeMap$DescendingSubMap$DescendingEntrySetView
    
    An unhandled error occurred while analysing the class 'org.junit.jupiter.params.shadow.com.univocity.parsers.common.fields.AbstractConversionMapping'.
    
    This is probably my fault, not yours, and I am sorry.
    I'd love to get an opportunity to fix this, please report as an issue at:
     https://github.com/MutabilityDetector/MutabilityDetector/issues/ 
    Pasting in this error message and stack trace, and if possible, 
    information about the code causing the error. 
    For example, one of: 
        .class files (preferably with source);
        compilable .java files; 
        a jar (again preferably with source);
        or, if your project is open source, information on where I can get the code from
            (I'm happy to checkout and build your project in order to investigate the error).
    
    Apologies, and thank you for using Mutability Detector.
    
    
    	at app//org.mutabilitydetector.checkers.UnhandledExceptionBuilder.unhandledException(UnhandledExceptionBuilder.java:62)
    	at app//org.mutabilitydetector.checkers.CheckerRunner.attemptRecovery(CheckerRunner.java:121)
    	at app//org.mutabilitydetector.checkers.CheckerRunner.runVisitor(CheckerRunner.java:89)
    	at app//org.mutabilitydetector.checkers.CheckerRunner.run(CheckerRunner.java:69)
    	at app//org.mutabilitydetector.checkers.AllChecksRunner.runCheckers(AllChecksRunner.java:75)
    	at app//org.mutabilitydetector.DefaultCachingAnalysisSession.requestAnalysis(DefaultCachingAnalysisSession.java:141)
    	at app//org.mutabilitydetector.DefaultCachingAnalysisSession.processTransitiveAnalysis(DefaultCachingAnalysisSession.java:125)
    	at app//org.mutabilitydetector.checkers.info.MutableTypeInformation.requestAnalysisIfNoCyclicReferenceDetected(MutableTypeInformation.java:67)
    	at app//org.mutabilitydetector.checkers.info.MutableTypeInformation.resultOf(MutableTypeInformation.java:59)
    	at app//org.mutabilitydetector.checkers.MutableTypeToFieldChecker$AssignMutableTypeToFieldChecker.checkIfClassIsMutable(MutableTypeToFieldChecker.java:174)
    	at app//org.mutabilitydetector.checkers.MutableTypeToFieldChecker$AssignMutableTypeToFieldChecker.visitFieldAssignmentFrame(MutableTypeToFieldChecker.java:156)
    	at app//org.mutabilitydetector.checkers.FieldAssignmentVisitor.visitEnd(FieldAssignmentVisitor.java:92)
    	at app//org.mutabilitydetector.internal.org.objectweb.asm.ClassReader.readMethod(ClassReader.java:1495)
    	at app//org.mutabilitydetector.internal.org.objectweb.asm.ClassReader.accept(ClassReader.java:721)
    	at app//org.mutabilitydetector.internal.org.objectweb.asm.ClassReader.accept(ClassReader.java:401)
    	at app//org.mutabilitydetector.checkers.CheckerRunner.analyse(CheckerRunner.java:112)
    	at app//org.mutabilitydetector.checkers.CheckerRunner.analyseFromClassLoader(CheckerRunner.java:107)
    	at app//org.mutabilitydetector.checkers.CheckerRunner.runVisitor(CheckerRunner.java:86)
    	... 90 more
    Caused by: java.lang.StackOverflowError
    	at org.mutabilitydetector.checkers.ImmutableCollectionChecker.lastMeaningfulNode(ImmutableCollectionChecker.java:238)
    	at org.mutabilitydetector.checkers.ImmutableCollectionChecker.lastMeaningfulNode(ImmutableCollectionChecker.java:238)
    	at org.mutabilitydetector.checkers.ImmutableCollectionChecker.lastMeaningfulNode(ImmutableCollectionChecker.java:238)
    [...]
    

    I'm using JDK 11.0.16.1 and MutabilityDetector 0 .10.6

    opened by paplorinc 0
  • Extend functionality to verify method purity checks

    Extend functionality to verify method purity checks

    An immutable class already implies that its methods are pure, but sometimes we're only interested in the purity of a single method of an otherwise mutable class.

    Basically we would need to check that for the same params (fields?) the return value is the same.

    • We should allow reads of immutable class state, but not of mutable ones (unless configured explicitly to allow that);
    • We should allow field writes of newly created objects (the ones we can trace) but not class state (except for lazy init maybe);
    • We should allow (configurable?) static reads, but not writes;

    Open question:

    • Can we handle reflective calls reliably?
    • What's a pure constructor?
      • doesn't write static state
      • doesn't call impure methods (e.g. Random)
      • can write local state and throw exception
    • Whitelistable native calls with several severities:
      • String::internand Object.getClass are basically caching
      • System::arraycopy is basically pure, but instead of returning it modifies the inputs
      • Unlike e.g. System::nanoTime which is never pure
    • When does UNSAFE usage invalidate purity?
    • Is it pure if throwing depends only on local state (i.e. is predictable)?
      • Can non-empty void methods therefore be pure?
    • Check asserts or logging or caching?
    • Class init and static init blocks - similar to caching
    • Local purity - if run on the same computer (architecture), it returns the same result?
    • Are utility classes (no class state, just static methods) immutable, if any of the methods mutates the parameters (e.g. Arrays#sort)
    opened by paplorinc 0
Releases(MutabilityDetector-0.10.1)
  • MutabilityDetector-0.10.1(Jan 9, 2019)

  • MutabilityDetector-0.9.6(Nov 10, 2016)

    The most significant changes in this release are:

    • improved message when constructing collection fields with unwrapped collections. See #51, #52, thanks go to new contributors @badgersow and @kwahsog.
    • hardcoded results can be configured to apply to MutabilityDetector.assertX methods. This is useful if you want to make assertions programatically, and don't want, for example, assertImmutable(String.class) to fail. See #64 , and thanks to new contributor @alexsalesdev .
    • MutabilityDetector assertion methods are now thread safe. See #63.
    • The command line interface can now give a summary of the analysis, included number of classes scanned, and time taken. See #66 and thanks again to @alexsalesdev .
    Source code(tar.gz)
    Source code(zip)
Owner
Mutability Detector
Mutability Detector
Exercico com Junit 5, UML, Interação de classes e Exception

AcessoClube Exercico com Junit 5, UML, Interação de classes e Exception Exercicio: Projete e desenvolva um sistema de controle de acesso a um clube co

Mateus Samartini 3 May 3, 2021
Este é um projeto Maven que contém vários métodos e classes criados, além de vários testes unitários. Os métodos desse projeto não contém uma implementação de fato, sendo assim você desenvolvedor(a) deverá escreve-lo.

Complete o código em Java O projeto tem como objetivo auxiliar aqueles que estão iniciando sua jornada em programação, mais precisamente, em Java. Est

Felix Gilioli 44 Nov 3, 2022
Core for open source libraries, included some important Classes for those libs.

OpenSource Core You could also read the CHINESE version of README This is a very useful Java class library. In this update, we have merged the origina

Theodore Hills 10 Nov 16, 2022
Astranaut's core classes

Astranaut Core Brief This project contains classes describing a tree, primarily an abstract syntax tree (AST) of some programming language, and functi

CQFN 2 Sep 13, 2022
Testcontainers is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.

Testcontainers Testcontainers is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium we

null 6.7k Jan 9, 2023
🕵️ Lightweight utility to intercept WebDriver and WebElement method calls.

Lightweight utility to intercept webdriver and webelement method calls. Supports both Selenium and Appium drivers About | To Get Started | Installatio

Sudharsan Selvaraj 24 Jul 1, 2022
A tool for mocking HTTP services

WireMock - a web service test double for all occasions Key Features HTTP response stubbing, matchable on URL, header and body content patterns Request

Tom Akehurst 5.3k Dec 31, 2022
ShotDroid is a pentesting tool for android.

ShotDroid is a pentesting tool for android. There are 3 tools that have their respective functions, Get files from Android directory, internal and external storage, Android Keylogger + Reverse Shell and Take a webcam shot of the face from the front camera of the phone and PC.

null 179 Jan 8, 2023
simple web3j Demo to be continue,use web3j Brainless Trading,tool for arbitrage automatic trading, copying other transfer,tracking agency addresses, setting profit points, setting prices, grabbing blocks

simple web3j Demo to be continue,use web3j Brainless Trading,tool for arbitrage automatic trading, copying other transfer,tracking agency addresses, setting profit points, setting prices, grabbing blocks

Nate River 262 Jan 7, 2023
WireMock - A tool for mocking HTTP services

WireMock only uses log4j in its test dependencies. Neither the thin nor standalone JAR depends on or embeds log4j, so you can continue to use WireMock 2.32.0 without any risk of exposue to the recently discovered vulnerability.

null 5.3k Dec 31, 2022
Gatling is a load test tool. It officially supports HTTP, WebSocket, Server-Sent-Events and JMS.

Gatling What is Gatling ? Gatling is a load test tool. It officially supports HTTP, WebSocket, Server-Sent-Events and JMS. Motivation Finding fancy GU

Gatling 5.8k Dec 27, 2022
High-level contextual steps in your tests for any reporting tool

Xteps High-level contextual steps in your tests for any reporting tool. License Maven Central Javadoc Xteps Xteps Allure Xteps ReportPortal How to use

Evgenii Plugatar 8 Dec 11, 2022
A Java architecture test library, to specify and assert architecture rules in plain Java

ArchUnit is a free, simple and extensible library for checking the architecture of your Java code. That is, ArchUnit can check dependencies between pa

TNG Technology Consulting GmbH 2.5k Jan 2, 2023
HATEOAS with HAL for Java. Create hypermedia APIs by easily serializing your Java models into HAL JSON.

hate HATEOAS with HAL for Java. Create hypermedia APIs by easily serializing your Java models into HAL JSON. More info in the wiki. Install with Maven

null 20 Oct 5, 2022
Never debug a test again: Detailed failure reports and hassle free assertions for Java tests - Power Asserts for Java

Scott Test Reporter for Maven and Gradle Get extremely detailed failure messages for your tests without assertion libraries, additional configuration

Dávid Csákvári 133 Nov 17, 2022
TCP Chat Application - Java networking, java swing

TCP-Chat-Application-in-Java TCP Chat Application - Java networking, java swing Java – Multithread Chat System Java Project on core Java, Java swing &

Muhammad Asad 5 Feb 4, 2022
A sample repo to help you handle basic auth for automation test in Java-selenium on LambdaTest. Run your Java Selenium tests on LambdaTest platform.

How to handle basic auth for automation test in Java-selenium on LambdaTest Prerequisites Install and set environment variable for java. Windows - htt

null 12 Jul 13, 2022
A sample repo to help you clear browser cache with Selenium 4 Java on LambdaTest cloud. Run your Java Selenium tests on LambdaTest platform.

How to clear browser cache with Selenium 4 Java on LambdaTest cloud Prerequisites Install and set environment variable for java. Windows - https://www

null 12 Jul 13, 2022