Testing strategies
Lincheck provides two strategies for testing concurrent data structures: model checking and stress testing.
In this article, you will learn the difference between the strategies and what to keep in mind when choosing a testing strategy.
Model checking
With model checking, Lincheck simulates possible thread interleavings and reports those that cause incorrect behavior.
To use model checking for testing a data structure, declare a test function using ModelCheckingOptions():
When using the model checking strategy, Lincheck inserts explicit thread-switch instructions at points of shared-memory access (read and write) or at synchronization points, such as lock acquisition and release, park/unpark, wait/notify, and others.
Controlling the thread switching enables Lincheck to:
Deterministically explore different possible execution schedules of a program.
Provide detailed execution traces.
Currently, model checking requires Lincheck to assume a sequentially consistent memory model of the execution. This means that Lincheck does not simulate and cannot catch bugs related to instruction reordering, memory cache behavior, and other similar effects under the relaxed Java memory model.
Stress testing
With stress testing, Lincheck executes each scenario multiple times to increase the chances of finding an error.
To use stress testing, declare a test function using StressOptions():
Unlike with model checking, Lincheck does not control or track thread switches. This makes stress testing faster and does not require Lincheck to make any assumptions about the memory model. However, with stress testing, tests are not reproducible, and Lincheck cannot provide an execution trace.
Choose a strategy
When choosing a strategy, consider the following:
Model checking | Stress testing | |
|---|---|---|
Speed | Slower. | Faster. |
Reproducibility | The tests return exactly the same results if the input data has not changed. | The tests might return different results as the thread schedules might change from run to run. |
Assumptions |
|
|
Verbosity | Reports both a concurrent scenario and an execution trace that led to incorrect behavior. | Reports only a concurrent scenario. |
Standard library coverage |
| Has a chance to catch a bug caused by the usage of any feature. |
What’s next
Learn how to configure a testing strategy by customizing scenario generation, enabling stalled execution detection, and providing thread-safety guarantees for libraries.