인자 생성 제약 조건(Argument generation constraints)
인자 생성 제약 조건(Argument generation constraints)
동시성 데이터 구조를 테스트할 때 Lincheck는 작업을 여러 스레드에 무작위로 배치하고 무작위 인자로 호출하여 동시성 시나리오 집합을 생성합니다. 인자 값의 범위를 제한하면 동시성 버그를 찾을 확률을 높일 수 있어요.
본문
동시성 데이터 구조를 테스트할 때 Lincheck는 작업을 여러 스레드에 무작위로 배치하고 무작위 인자로 호출하여 동시성 시나리오 집합을 생성합니다.
인자 값의 범위를 제한하면 동시성 버그를 찾을 확률을 높일 수 있어요. 예를 들어 해시 맵에서 동시 작업이 같은 키에 접근할 가능성을 높이려면 가능한 키 값의 범위를 제한하면 됩니다. 이렇게 하면 Lincheck가 경쟁 조건(race condition)과 같은 동시성 버그를 더 효율적으로 드러낼 수 있습니다.
Lincheck에서 생성되는 인자 값의 범위를 제한하는 방법은 다음과 같아요:
-
@Param어노테이션으로 인자 생성기(generator)를 선언합니다:@Param(name = "key", gen = IntGen::class, conf = "1:2") class MultiMapTest { }name– 인자 생성기의 이름입니다.gen– 생성기의 타입입니다.conf– 생성기의 설정 문자열입니다. 여기서는 Lincheck가 1부터 2까지의 정수 값을 생성합니다.
-
작업의 파라미터에
@Param을 붙여 제약 조건을 적용합니다:@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)
제약 조건이 적용되면 Lincheck는 지정된 범위 안의 값만 사용해 시나리오를 생성합니다:
| ---------------------------------- |
| Thread 1 | Thread 2 |
| ---------------------------------- |
| add(2, 0): void | add(2, -1): void |
| ---------------------------------- |
| get(2): [-1] | |
| ---------------------------------- |
생성기 타입
Lincheck는 다음과 같은 인자 생성기 타입을 제공합니다:
| 생성기 | 설정 템플릿 | 설명 |
| IntGen | "min:max" | min과 max 사이의 Int 값을 포함하여 생성합니다. 설정 문자열이 비어 있으면 Int.MIN_VALUE부터 Int.MAX_VALUE까지 전체 정수 범위를 사용합니다. 예: "1:3" -> [1, 2, 3] |
| StringGen | "maxWordLength:alphabet" | 주어진 alphabet에서 maxWordLength 길이까지의 무작위 문자열 값을 생성합니다. 기본 alphabet은 [a-zA-Z\d _]이고 기본 maxWordLength는 15입니다. "" 설정 문자열이면 기본값을 사용합니다. |
| EnumGen | "Enum.Const1,Enum.Const2,..." | 지정된 열거형(enum) 값 목록에서 무작위 값을 생성합니다. |
| BooleanGen | "" | true와 false 값을 생성합니다. 특정 설정 문자열이 필요하지 않습니다. 예: "" -> [true, false] |
| DoubleGen | "start:step:end" | start부터 end까지 step만큼 증가하며 Double 값을 생성합니다. 기본 step 값은 (end - start)/100입니다. "start:end" 형식으로 지정하면 기본 step을 사용합니다. 설정 문자열이 비어 있으면 step = 0.1로 Int.MIN_VALUE부터 Int.MAX_VALUE까지 값을 생성합니다. 예: "0.0:0.1:1.0" -> [0.0, 0.1, 0.2, ..., 0.9, 1.0] |
| FloatGen | "start:step:end" | DoubleGen과 동일하지만 값을 Float로 변환합니다. 예: "0.0:0.1:1.0" -> [0.0, 0.1, 0.2, ..., 0.9, 1.0] |
| LongGen | "min:max" | IntGen과 동일하지만 값을 Long으로 변환합니다. 예: "1:3" -> [1, 2, 3] |
| ShortGen | "min:max" | min과 max 사이의 Short 값을 포함하여 생성합니다. 설정 문자열이 비어 있으면 -32768부터 32767까지 전체 short 정수 범위를 사용합니다. 예: "1:3" -> [1, 2, 3] |
| ByteGen | "min:max" | min과 max 사이의 Byte 값을 포함하여 생성합니다. 설정 문자열이 비어 있으면 -128부터 127까지 전체 byte 범위를 사용합니다. 예: "1:3" -> [1, 2, 3] |
| ThreadIdGen | "" | 현재 스레드의 ID 번호를 반환합니다. 특정 설정 문자열이 필요하지 않습니다. 예: "" -> [1, 2] |