Lincheck 개요
Lincheck 개요
Lincheck는 JVM에서 동시성 코드를 테스트하기 위한 프레임워크입니다. 테스트를 실행할 때 Lincheck는 프로그램의 가능한 스레드 인터리빙(interleaving)을 탐색하고, 잘못된 동작을 유발하는 인터리빙을 보고해 줍니다.
Kotlin Multiplatform 프로젝트에서는 Lincheck로 JVM에서 실행되는 코드만 테스트할 수 있어요.
Lincheck의 동시성 테스트는 각 스레드에 대한 작업 목록과 기대하는 검증(assertion)만 나열하면 됩니다. 나머지는 Lincheck가 처리합니다:
class CounterTest {
@Test // Test function declaration
fun test() = Lincheck.runConcurrentTest {
var counter = 0
// Increments the counter concurrently
val t1 = thread { counter++ }
val t2 = thread { counter++ }
// Waits for the threads to finish
t1.join()
t2.join()
// Checks that both increments have been applied
assertEquals(2, counter)
}
}
테스트가 실패하면 Lincheck는 오류를 유발한 스레드 인터리빙과 스레드 전환 지점을 알려줍니다:
| ------------------------------------------------------------------------------- |
| Main Thread | Thread 1 | Thread 2 |
| ------------------------------------------------------------------------------- |
| thread(block = Lambda#2): Thread#1 | | |
| thread(block = Lambda#3): Thread#2 | | |
| switch (reason: waiting for Thread 1 to finish) | | |
| | | run() |
| | | counter ➜ 0 |
| | | switch |
| | run() | |
| | counter ➜ 0 | |
| | counter = 1 | |
| | | counter = 1 |
| Thread#1.join() | | |
| Thread#2.join() | | |
| counter.element ➜ 1 | | |
| assertEquals(2, 1): threw AssertionFailedError | | |
| ------------------------------------------------------------------------------- |
출처: Overview
본문
JVM이 동시성 코드를 실행할 때마다 스레드 간 작업의 실행 순서가 달라질 수 있어요. 예를 들어 어떤 작업이 다른 스레드의 다른 작업에 의해 중단될 수 있습니다. 이것 자체가 오류는 아니지만, 코드에 동시성 버그가 있으면 오류로 이어질 수 있죠.
실행 시나리오(execution scenario)는 작업이 스레드에 어떻게 분배되는지와 각 스레드 내에서의 실행 순서를 정의합니다.
실행 스케줄(execution schedule, 스레드 인터리빙이라고도 함)은 모든 스레드에 걸친 모든 작업의 실행 순서를 정의합니다.
Lincheck는 잘못된 동작을 유발하는 실행 스케줄을 찾기 위해 두 가지 테스트 전략을 구현합니다:
- 모델 체킹(Model checking). Lincheck는 프로그램에 명시적인 스레드 전환 명령을 삽입하여 스케줄링을 제어합니다. 이 명령은 동기화 지점이나 공유 메모리 접근 지점에 배치됩니다. 모델 체킹을 통해 Lincheck는 오류를 유발하는 정확한 실행 트레이스를 생성할 수 있어요.
- 스트레스 테스트(Stress testing). 운영 체제가 스케줄링을 제어합니다. Lincheck는 오류를 찾을 확률을 높이기 위해 각 시나리오를 여러 번 실행합니다.
Lincheck 둘러보기
- Lincheck 시작하기에서 Lincheck 기능을 단계별로 배워 보세요.
- Lincheck에서 동시성 데이터 구조를 테스트하는 선언적 접근 방식에 대해 배워 보세요.
더 알아보기
- Nikita Koval의 "How we test concurrent algorithms in Kotlin Coroutines": 영상. KotlinConf 2023
- Maria Sokolova의 "Lincheck: Testing concurrency on the JVM" 워크숍: 1부, 2부. Hydra 2021
- Nikita Koval 외의 "Lincheck: A Practical Framework for Testing Concurrent Data Structures on JVM": 논문. 2023
- Kotlin Metadata JVM 라이브러리
- Lincheck 시작하기