Kotlin Help

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:

  1. Use the @Param annotation 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.

  2. Annotate the operations parameters with @Param to 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:

| ---------------------------------- | | Thread 1 | Thread 2 | | ---------------------------------- | | add(2, 0): void | add(2, -1): void | | ---------------------------------- | | get(2): [-1] | | | ---------------------------------- |

Generator types

Lincheck provides the following argument generator types:

Generator

Configuration template

Description

IntGen

"min:max"

Generates Int values between min and max, inclusive.

If the configuration string is empty, uses the full integer range from Int.MIN_VALUE to Int.MAX_VALUE.

Example: "1:3" -> [1, 2, 3]

StringGen

"maxWordLength:alphabet"
"maxWordLength"
""

Generates random string values up to maxWordLength from the provided alphabet. The default alphabet is [a-zA-Z\d _].
The default maxWordLength is 15.

Example:

"2:abc" -> [ "a", "b", "c", "aa", "bb", "cc", "ab", "bc", "ac", "ba", "cb", "ca" ]

EnumGen

"Enum.Const1,Enum.Const2,..."

Generates a random value from the specified list of enum values.

Example:

"Enum.Const1,Enum.Const2" -> [ Enum.Const1, Enum.Const2 ]

BooleanGen

""

Generates true and false values. Does not require a specific configuration string.

Example: "" -> [true, false]

DoubleGen

"start:step:end"
"start:end"
""

Generates Double values from start to end, incrementing by step.

Default step value is (end - start)/100.

If the configuration string is empty, generates values from Int.MIN_VALUE to Int.MAX_VALUE with step = 0.1.

Example: "0.0:0.1:1.0" -> [0.0, 0.1, 0.2, ..., 0.9, 1.0]

FloatGen

"start:step:end"
"start:end"
""

Same as DoubleGen with values converted to Float.

Example: "0.0:0.1:1.0" -> [0.0, 0.1, 0.2, ..., 0.9, 1.0]

LongGen

"min:max"

Same as IntGen with values converted to Long.

Example: "1:3" -> [1, 2, 3]

ShortGen

"min:max"

Generates Short values between min and max, inclusive.

If the configuration string is empty, uses the full short integer range from -32768 to 32767.

Example: "1:3" -> [1, 2, 3]

ByteGen

"min:max"

Generates Byte values between min and max, inclusive.

If the configuration string is empty, uses the full byte range from -128 to 127.

Example: "1:3" -> [1, 2, 3]

ThreadIdGen

""

Returns the ID number of the current thread. Does not require a specific configuration string.

Example: "" -> [1, 2]

What's next

Learn how to restrict certain operations to a single thread in Lincheck.

See also

02 July 2026