我有一个非线程安全的类:
class Foo { /* Abstract base class, code which is not thread safe */ };
此外,如果你有foo1和foo2对象,你不能调用foo1-> someFunc()直到foo2-> anotherFunc()返回(这可能发生在两个线程).这是情况,它无法更改(Foo子类实际上是python脚本的包装器).
为了防止不必要的电话,我创建了以下内容 -
class FooWrapper { public: FooWrapper(Foo* foo, FooWrappersMutex* mutex); /* Wrapped functions from Foo */ };
在内部,FooWrapper使用共享互斥锁包装对Foo函数的调用.
我想测试FooWrapper的线程安全性.我最大的问题是线程是由操作系统管理的,这意味着我对执行的控制较少.我想测试的是以下场景:
线程1在函数内部调用fooWrapper1-> someFunc()并阻塞
线程2调用fooWrapper2-> anotherFunc()并立即返回(因为someFunc()仍在执行)
线程1完成执行
什么是最简单的自动测试这样的场景?
我在Win32上使用QT,虽然我更喜欢QT至少是跨平台的解决方案.
您可能想查看CHESS: Microsoft Research的并发软件系统测试工具.它是多线程程序(.NET和本机代码)的测试框架.
如果我理解正确,它会用自己的操作系统替换操作系统的线程库,以便它可以控制线程切换.然后,它分析程序,找出线程执行流可以交错的每种可能方式,并为每个可能的交错重新运行测试套件.
为什么不创建一个假Foo
包装器调用假,而不是仅仅检查特定线程是否已完成,其中函数记录它们实际启动/完成的时间.那么你的屈服线程只需等待足够长的时间就可以区分记录时间之间的差异.在你的测试中你可以断言another_func
开始时间是在开始时间之后some_func
,它的完成时间是在some_func
完成时间之前.由于您的假类仅记录时间,因此这应足以保证包装器类正常工作.
编辑:当然,你知道你的Foo
对象可能是一个反模式,即顺序耦合.根据它的作用,你可以通过简单地让第二种方法在第一种方法尚未被调用时不做任何事来处理它.使用顺序耦合链接中的示例,这类似于在按下加速踏板时汽车不执行任何操作,如果汽车尚未启动.如果不采取任何措施,您可以等待稍后再试,在当前线程中启动"启动序列",或将其作为错误处理.所有这些东西都可以由你的包装器强制执行,并且可能更容易测试.
如果需要对另一个方法进行干预调用,您可能还需要注意确保相同的方法不会按顺序调用两次.