GithubHelp home page GithubHelp logo

vmlens / vmlens Goto Github PK

View Code? Open in Web Editor NEW
103.0 8.0 11.0 5.91 MB

unit-testing multi-threaded applications on the JVM made easy

Home Page: https://vmlens.com

License: Apache License 2.0

Java 53.48% HTML 1.73% JavaScript 0.01% CSS 0.63% Scala 43.32% Mustache 0.83%
java testing multithreading concurrent

vmlens's Introduction

vmlens, unit-testing multi-threaded applications on the JVM made easy

Why vmlens?

Running your tests with multiple threads does not work. Bugs depend on a specific thread interleaving, which is often impossible to reach by simply rerunning your test multiple times. And data races only occur on specific hardware architectures and JVMs.

Therefore vmlens uses the Java Memory Model to execute all possible thread interleavings and to check for data races in the program flow. This blog post describes how vmlens uses the Java Memory Model to test all thread interleavings.

Easy to use

Using vmlens is easy.

Surround your test with a while loop iterating over all thread interleavings using the class AllInterleaving.

Example

The following example shows how to write multi-threaded tests with vmlens:

import com.vmlens.api.AllInterleavings;
public class TestUpdateWrong {
    public void update(ConcurrentHashMap<Integer, Integer> map) {
        Integer result = map.get(1);
        if (result == null) {
            map.put(1, 1);
        } else {
            map.put(1, result + 1);
        }
    }
    @Test
    public void testUpdate() throws InterruptedException {
        try (AllInterleavings allInterleavings = 
                new AllInterleavings("TestUpdateWrong");) {
	// surround the test with a while loop, iterationg over
	// the class AllInterleavings
            while (allInterleavings.hasNext()) {
                final ConcurrentHashMap<Integer, Integer> map = 
                        new ConcurrentHashMap<Integer, Integer>();
                Thread first = new Thread(() -> {
                    update(map);
                });
                Thread second = new Thread(() -> {
                    update(map);
                });
                first.start();
                second.start();
                first.join();
                second.join();
                assertEquals(2,map.get(1).intValue());
            }
        }
    }
}

In your test method, you surround the code you want to test with a while loop iterating over the class AllInterleavings. vmlens executes the block inside the while loop multiple times, for each thread interleaving once. If the test fails vmlens shows the thread interleaving which led to the failure. If the test succeeds vmlens shows the last thread interleaving.

The above example test fails, and vmlens reports the interleaving which led to the failed assertion:

In maven, you can see this report by clicking on the link TestUpdateWrong in the file target/interleave/elements.html. In eclipse you can see the report by clicking on the link TestUpdateWrong in the view under Window -> Show View -> Other... -> vmlens -> vmlens Explorer.

The maven reports are described here. The eclipse views are described here.

How to run the test

You can run the test in eclipse using the vmlens run short cut for JUnit. Right click on the JUnit class -> Run As -> JUnit Test traced with vmlens.

To run the test with maven put the vmlens interleave plugin in your maven pom.xml as described here.

Next steps

Read here more about how to use vmlens for testing multi-threaded software. And download and run the example tests.

Download

Eclipse

Install from marketplace:

  1. Start Eclipse (version 4.4 or greater)
  2. Drag to your running Eclipse* workspace. *Requires Eclipse Marketplace Client

Or install directly from the update site:

  1. Start Eclipse
  2. Select Help>Install New Software…
  3. Work with: https://vmlens.com/download/site/

To use the class AllInterleavings you need to include the jar api-1.1.5.jar into your classpath. You can download this jar from maven central here.

The usage of the eclipse plugin is described here.

MAVEN

To use vmlens with maven, configure a plugin tag to tell maven that the vmlens plugin should be executed at the test phase. And include the jar com.vmlens.api as test dependency.

<project>
<!-- to include the class AllInterleavings into the test class path.  -->	
<dependency>
  <groupId>com.vmlens</groupId>
  <artifactId>api</artifactId>
  <version>1.1.5</version>
  <scope>test</scope>
</dependency>	
	
<build>
  <plugins>
<!-- to run the vmlens maven plugin during the maven test phase  -->	 
    <plugin>
    <groupId>com.vmlens</groupId>
    <artifactId>interleave</artifactId>
    <version>1.1.5</version>
    <executions>
      <execution>
        <goals>
          <goal>test</goal>
        </goals>
      </execution>
    </executions>
    </plugin>
     ...
    </plugins>
</build>
      ...
</project>

The usage of the maven plugin is described here.

Documentation

Support

Post an issue in our issue tracker or send a message to our mailing list.

Stay in touch

Follow @ThomasKrieger and join our mailing list.

Build

To build vmlens, go to vmlens and run

mvn clean install

You need JDK 11 or higher and a toolchains.xml containing a tag for JDK 8. Example toolchains.xml:

<?xml version="1.0" encoding="UTF8"?>
<toolchains>
<!-- JDK toolchains -->
  <toolchain>
    <type>jdk</type>
      <provides>
        <version>1.8</version>
        <vendor>sun</vendor>
      </provides>
      <configuration>
        <jdkHome>/path/to/jdk/1.8</jdkHome>
      </configuration>
  </toolchain>
</toolchains>

License

Apache License 2.0

vmlens's People

Contributors

thomaskrieger avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vmlens's Issues

jUnit 5 support

Hello. I'm getting started with vmlens on a project already using jUnit 5. But seems like it is not yet supported by vmlens.

To make sure I cloned https://github.com/vmlens/vmlens-examples and tried to swap jUnit 4 with 5 for both Maven and Gradle.

  • Maven's output with jUnit 5 got reduced from 3 issues to one (only the one related to CHM.compute left). So it somehow works but provides different output for the same set of tests.
  • If I replace jUnit version in Gradle build, the Gradle's output is empty (for gradle clean interleave). And interleave's issues.html says: No tests to run

It would be great to support jUnit 5 since it becomes a default choice for new projects

UnsupportedOperationException when using onlyTraceIn

When I try to use the Gradle plugin with the onlyTraceIn option I get an UnsupportedOperationException

How to reproduce?

Check out the gradle-plugin-test branch from here

Execute the following command

./gradlew clean test interleave --stacktrace

Details

I used the vmlens documentation to configure Gradle support to my project.

image

Note, that running mvn test is just fine and showing the issues

Running vmlens examples with Java 17 fails

Running the test in the vmlens-example project produces the following exception.

org.gradle.api.UncheckedIOException: java.io.InvalidClassException: org.gradle.api.internal.tasks.testing.worker.TestWorker; local class incompatible: stream classdesc serialVersionUID = 3693551109956383254, local class serialVersionUID = 9179962266607461973
	at org.gradle.internal.UncheckedException.throwAsUncheckedException(UncheckedException.java:62)
	at org.gradle.internal.UncheckedException.throwAsUncheckedException(UncheckedException.java:41)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.deserializeWorker(SystemApplicationClassLoaderWorker.java:156)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:121)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: java.io.InvalidClassException: org.gradle.api.internal.tasks.testing.worker.TestWorker; local class incompatible: stream classdesc serialVersionUID = 3693551109956383254, local class serialVersionUID = 9179962266607461973
	at java.base/java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:728)
	at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2062)
	at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1909)
	at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2235)
	at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1744)
	at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:514)
	at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:472)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.deserializeWorker(SystemApplicationClassLoaderWorker.java:153)
	... 4 more

Turn off reporting for the Maven plugin?

Hello,

When I use vmlens to test my code, I need to wait a very long time for the reports to finish. In the general case, the unit tests are all ok, and I don't case about the reports. (They will not show any issues.) Is there a way to turn off report generation, and only have the reports generated when the unit tests fail? Or better yet, only when I want them to be generated?

With kind regards,

Jurrie

AllInterleavings.hasNext hardwired to "false"?

Apologies if I should have misunderstood this completely, but the TestUpdateWrong example does not work for me.
Looking a bit closer into it I found that "hasNext" is always false on this line:

while (allInterleavings.hasNext()) {

And to my surprise it comes down to a hard-wired "false" in AllInterleavings:

private static boolean hasNext(Object object)
{
	return false;
}

Dependency used:
testImplementation("com.vmlens:api:1.1.5")

No report and almost no error output on Maven run

I applied the documented Maven specific config to my project and created a test.

Only output on mvn verify was

agent stopped
agent ended
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 0, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[ERROR]
[INFO] vmlens-maven-plugin processed 5% of the trace files.
[INFO] vmlens-maven-plugin processed 6% of the trace files.
[INFO] vmlens-maven-plugin processed 11% of the trace files.

My project runs on adopt-JDK v8 ([email protected]), and am using Maven 3.6.2.

Any pointers/ideas to what is happening here?

Add Gradle plungin

It would be great to have Gradle integration and be able to run the tests during a Gradle build.

Maven configuration syntax to suppress these types of data races?

I'm trying to suppress some H2 data races to get my test run to pass, I've tried several variants of the syntax I see in the docs, but I'm not able to suppress them:

0 java.lang.String[]
org.h2.util.StringUtils.cache(java.lang.String) (StringUtils.java:971)
1 java.lang.String[][]
org.h2.util.StringUtils.toUpperEnglish(java.lang.String) (StringUtils.java:87)
2 org.h2.value.ValueInt[]
org.h2.value.ValueInt.get(int) (ValueInt.java:56)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.