Testing arbitrary code
Lincheck provides a runConcurrentTest() function to test arbitrary concurrent code.
The runConcurrentTest() function executes a block of concurrent code multiple times and uses model checking to explore its potential execution schedules.
To test concurrent code with Lincheck:
Create a test class:
class NewConcurrentTest { // Tests }Create a test function as a member function using
runConcurrentTest().@Test fun test() = runConcurrentTest(100_000) { // Concurrent code }
Run the test. If it fails, Lincheck generates a report with an execution schedule that leads to incorrect behavior.
Example: test ConcurrentHashMap functions
Consider this test for ConcurrentHashMap functions:
The test fails due to Lincheck finding an execution schedule that leads to a deadlock:
Thread 2 maps
key2to the bucket at index 1, places a lock on this bucket, and starts executingcomputeIfAbsent("key1"). The execution switches from Thread 2 to Thread 1 before Thread 2 mapskey1and locks the bucket withkey1.Thread 1 maps
key1to the bucket at index 0, places a lock on this bucket, and starts executingcomputeIfAbsent("key2"). Thread 1 mapskey2to the bucket at index 1 and tries to lock the bucket, but it is already locked by Thread 2. The execution switches from Thread 1 to Thread 2.Thread 2 tries to lock the bucket with
key1, but it is already locked by Thread 1.
Both threads are locked, so the execution has encountered a deadlock.

What’s next
Learn how to test data structures using Lincheck.