Skip to content

测试策略

Lincheck 提供了两种用于测试并发数据结构的策略:模型检查和压力测试。

在本文中,您将了解这些策略之间的区别,以及在选择测试策略时需要注意的事项。

模型检查

通过模型检查,Lincheck 会模拟可能的线程交错,并报告那些导致错误行为的交错。

要使用模型检查策略来测试数据结构,请使用 ModelCheckingOptions() 声明一个测试函数:

kotlin
@Test
fun modelCheckingTest() = ModelCheckingOptions()
   .check(this::class)

当使用模型检查策略时,Lincheck 会在共享内存访问(readwrite)点或同步点(如锁的获取与释放、park/unparkwait/notify 等)插入显式的线程切换指令。

控制线程切换使 Lincheck 能够:

  • 确定性地探索程序的不同可能执行调度。
  • 提供详细的执行跟踪。

目前,模型检查要求 Lincheck 假设执行过程符合顺序一致内存模型。这意味着 Lincheck 不会模拟,也无法捕获与指令重排、内存缓存行为以及在宽松的 Java 内存模型下其他类似影响相关的错误。

压力测试

通过压力测试,Lincheck 会多次执行每个场景,以增加发现错误的机会。

要使用压力测试,请使用 StressOptions() 声明一个测试函数:

kotlin
@Test
fun stressTest() = StressOptions()
   .check(this::class)

与模型检查不同,Lincheck 不会控制或跟踪线程切换。这使得压力测试速度更快,且不需要 Lincheck 对内存模型做出任何假设。 然而,对于压力测试,测试是不可复现的,且 Lincheck 无法提供执行跟踪。

选择策略

在选择策略时,请考虑以下几点:

模型检查压力测试
速度较慢。较快。
可复现性如果输入数据未更改,测试将返回完全相同的结果。由于线程调度可能会随运行次数而变化,测试可能会返回不同的结果。
假设
  • 假设顺序一致内存模型。
  • 会遗漏该模型之外的错误行为所引起的错误。
  • 不对内存模型做任何假设。
  • 有机会捕获任何错误行为,无论其根本原因是什么。
详尽程度同时报告并发场景和导致错误行为的执行跟踪。仅报告并发场景。
标准库覆盖范围
  • 不模拟某些标准库功能(如弱引用)的行为。
  • 会遗漏由此类功能引起的错误。
有机会捕获由于使用任何功能而引起的错误。

下一步

了解如何通过自定义场景生成、启用停滞执行检测以及为库提供线程安全保证来配置测试策略

另请参阅