关于如何为可能容易出现死锁和竞争条件的代码编写可重复单元测试的任何建议?
现在我倾向于跳过单元测试并专注于压力测试。问题是你可以进行5次压力测试并看到5种不同的结果。
编辑:我知道它可能只是一个梦想,但如果有一种方法来控制单个线程并导致它们一次执行一条指令,那么我可能会到达某个地方。
关于如何为可能容易出现死锁和竞争条件的代码编写可重复单元测试的任何建议?
现在我倾向于跳过单元测试并专注于压力测试。问题是你可以进行5次压力测试并看到5种不同的结果。
编辑:我知道它可能只是一个梦想,但如果有一种方法来控制单个线程并导致它们一次执行一条指令,那么我可能会到达某个地方。
看一眼 TypeMock 赛车手(它在Beta中)
编辑:实际上是Alpha
http://www.typemock.com/Typemock_software_development_tools.html
通常可以强迫 预见 竞争条件和死锁通过使用像ManualResetEvent之类的东西在释放之前让每个线程进入预期状态 - 即获取线程A以获得锁定并等待信号...获取线程B以请求锁定等...
但是 - 您通常可以编写这样的测试来调查可疑的bug,以证明它何时被修复并且不会重新浮出水面。你通常会围绕竞争条件进行设计(但最好是务实地测试它们)。
我不认为寻找竞争条件真的属于单元测试领域。根据定义,或多或少,测试竞争条件的唯一方法是伪随机的。除非你愿意正式努力证明锁定策略的正确性,否则你将不得不做一些压力测试。
您仍然需要编写单元测试,以验证算法的正确性,而不是锁定策略。
在对多线程代码进行压力测试时,您需要在每个线程有一个CPU的情况下进行测试,其中您有多个线程共享CPU,并且您拥有的CPU数多于线程数(如果可能)。
您可以通过查看锁定操作的顺序来编写一个检测潜在死锁的锁类。我们通过在获取所有锁定时注册的线程上下文来做到这一点(可以作为DEBUG only选项)。
这个想法是创建一个图形,其中节点代表锁定,A和B之间的有向边缘意味着“获取锁定B时保持锁定A”。让您的程序使用正常负载运行,然后检查图中的周期。一个循环意味着即使你的代码没有命中它也有可能发生死锁。
想不出一个好的自动化方式,但我最接近的是编写一个“暴露”死锁的单元测试,除了单元测试之外还使用了断点。我只是添加了一些关于添加断点的指令。需要进行一些手动操作,但是对于它们,您可以随时公开更糟糕的案例线程安排。
也许有人想出了一种自动化这种功能的好方法?我可以想象自动运行调试器,在特定行中断开一个线程,让另一个线程运行到特定条件,然后断言单元测试。
我以前在代码中使用了由请求中的某些参数触发的人为延迟。例如,一个请求告诉服务器延迟两次写入之间的写入,而另一次请求则在两次写入之间没有延迟。
Mark Bessey写道,这只对创建repro有用,而不是用于发现问题。
你有没有尝试过 Corensic Jinx?