Operation execution options
Lincheck provides a set of options for controlling how specific operations are executed, such as running operations on a single thread, executing an operation only once, marking the operation as blocking, and others.
In this article, you will learn about different execution options and how to set them.
Single-thread operation groups
Certain operations are required to never run concurrently, such as operations in single-producer single-consumer queues.
To create a group of operations that are never executed in parallel, use the nonParallelGroup option when declaring the operations:
Lincheck ensures that the operations from the non-parallel group are never executed in parallel with each other. However, these operations can still run in parallel with operations outside of the non-parallel group:
Single-use operations
Use the runOnce option to execute the operation only once per test invocation:
An example of a generated scenario:
Blocking operations
Use the blocking option if the operation is intended to block the execution. If the test checks for non-blocking guarantees, Lincheck does not fail a test when the execution stalls on an operation marked with the blocking option:
Cancelable operations
Use the cancellableOnSuspension option if the operation can be canceled when it suspends:
Consider the following channel test:
|
|
|---|---|
If
| ----------------------------------- |
| Thread 1 | Thread 2 |
| ----------------------------------- |
| send(3) | send(3) + cancel |
| receive() | send(2) + cancel |
| receive() | receive() |
| receive() | receive() |
| send(1) + cancel | receive() |
| ----------------------------------- |
| Lincheck explores the scenarios where
| --------------------------------------- |
| Thread 1 | Thread 2 |
| --------------------------------------- |
| send(3) | send(3) + cancel |
| receive() + cancel | send(2) + cancel |
| receive() + cancel | receive() |
| receive() + cancel | receive() + cancel |
| send(1) + cancel | receive() + cancel |
| --------------------------------------- |
|
Prompt cancellation
If cancellableOnSuspension is enabled and the operation should support prompt cancellation, you can also set promptCancellation to true:
Consider the following channel test:
|
|
|---|---|
Lincheck can only try to cancel the operation after it has actually been suspended. If the operation was resumed before Lincheck attempts cancellation, the cancellation fails and the operation completes normally:
| --------------------------------------- |
| Thread 1 | Thread 2 |
| --------------------------------------- |
| send(2) | send(2) |
| send(2) + cancel | receive() + cancel |
| receive() + cancel | receive() |
| receive() | send(3) + cancel |
| send(2) | receive() |
| --------------------------------------- |
| Lincheck can cancel the operation even if it has already resumed, but didn't have a chance to run. This models the real-life behavior where a coroutine can be canceled between the moment it is resumed and the moment it actually processes the result:
| ---------------------------------------------- |
| Thread 1 | Thread 2 |
| ---------------------------------------------- |
| send(2) | send(2) |
| send(2) + cancel | receive() + cancel |
| receive() + cancel | receive() + prompt_cancel |
| receive() | send(3) + cancel |
| send(2) | receive() |
| ---------------------------------------------- |
|