Argument generation constraints
To test a concurrent data structure, Lincheck generates a set of concurrent scenarios by placing the operations randomly in different threads and invoking them with random arguments.
You can constrain the range of operation arguments to increase the chance of finding a concurrency bug. For example, concurrent operations in a hash map are more likely to access the same key if the range of possible key values is limited. This enables Lincheck to expose race conditions and other concurrency bugs more efficiently.
To limit the range of the generated argument values in Lincheck:
Use the
@Paramannotation to declare an argument generator:@Param(name = "key", gen = IntGen::class, conf = "1:2") class MultiMapTest { // Tests }name– the name of the argument generator.gen– the type of the generator.conf– the configuration string for the generator. Here, Lincheck generates integer values from 1 to 2.
Annotate the operations parameters with
@Paramto apply the constraints:@Operation fun add(@Param(name = "key") key: Int, value: Int) = map.add(key, value) @Operation fun get(@Param(name = "key") key: Int) = map.get(key)
With the constraints in place, Lincheck generates scenarios using only values within the specified range:
Generator types
Lincheck provides the following argument generator types:
Generator | Configuration template | Description |
|---|---|---|
|
| Generates |
|
| Generates random string values up to "2:abc" -> [
"a", "b", "c",
"aa", "bb", "cc",
"ab", "bc", "ac",
"ba", "cb", "ca"
] |
|
| Generates a random value from the specified list of enum values. "Enum.Const1,Enum.Const2" -> [
Enum.Const1,
Enum.Const2
] |
|
| Generates |
|
| Generates |
|
| Same as |
|
| Same as |
|
| Generates |
|
| Generates |
|
| Returns the ID number of the current thread. Does not require a specific configuration string. |
What's next
Learn how to restrict certain operations to a single thread in Lincheck.