C++ 单元测试线程:如何确认线程被阻塞
我正在为多线程系统编写一组单元测试。我想写一个测试来确认线程B被线程a阻塞。我目前的解决方案,我知道是不正确的,是让线程a休眠一段时间,然后让主线程确定线程B至少需要那么长的时间才能完成。我意识到这个测试并不是真正有效的,因为线程B可能只是被系统调度出来,并且需要很长时间才能运行,而与被阻塞无关C++ 单元测试线程:如何确认线程被阻塞,c++,multithreading,unit-testing,synchronous,C++,Multithreading,Unit Testing,Synchronous,我正在为多线程系统编写一组单元测试。我想写一个测试来确认线程B被线程a阻塞。我目前的解决方案,我知道是不正确的,是让线程a休眠一段时间,然后让主线程确定线程B至少需要那么长的时间才能完成。我意识到这个测试并不是真正有效的,因为线程B可能只是被系统调度出来,并且需要很长时间才能运行,而与被阻塞无关 更多信息,根据评论: 我不能详细说明,但是$dayjob已经实现了它自己的任务线程系统,与Android的AsyncTask没有太大区别,我的任务是(明白吗?)为它编写单元测试。我已经写了十几个单元测
更多信息,根据评论: 我不能详细说明,但是$dayjob已经实现了它自己的任务线程系统,与Android的AsyncTask没有太大区别,我的任务是(明白吗?)为它编写单元测试。我已经写了十几个单元测试,这些测试我很满意,而且完全是确定性的。但只有几个单元测试让我无法理解。在一些情况下,线程需要等待特定的条件,我需要确认它实际上是在该条件下被阻塞的,而不是碰巧在错误的时间睡眠 我提出的测试不会产生任何错误的失败,但是如果调度程序在错误的时间使线程进入睡眠状态,仍然可能产生错误的成功
更多信息:我不是在测试使用线程库的代码,而是在测试库本身 …另一个测试确认任务等待互斥锁 不要浪费时间测试库。专注于测试您自己的代码。如果您需要证明您的代码在特定条件下调用了特定对象(例如,给定的
std::mutex
)的特定方法(例如,lock
),那么这样做的方法不是验证调用线程是否确实被阻塞。测试它的方法是使用一个(又称“mock object”)作为互斥对象
您创建了一个对象,testdouble或“mock”,它符合mutex
API,但实际上不是一个mutex。然后,您的测试函数设置被测试单元锁定互斥锁的特定条件,它调用您的单元,然后查询模拟互斥锁对象,询问“是否调用了您的lock()
方法?”
设置特定条件可能需要通过其他“双重测试”对象。同样,根据您正在测试的单元的复杂性,您可能必须传入其他测试双重对象,以防止它在调用lock()
函数后碰撞测试线束
大多数面向对象语言的单元测试框架都有一些方法可以轻松创建测试双线程。我认为,多线程代码的测试是一个非常有趣的领域。我要说的是,您关注的内容太低了——您试图检测到“线程B被线程a阻塞”。您可能会遇到很多其他问题(竞争条件、数据竞争),比如共享变量没有用于存储/加载的适当内存屏障。这就是为什么我更愿意从以下两个方面关注您自己的程序的功能/状态:
对于您的特定情况,我们可能会测试测试是否在超时期间没有进展,并且仅为了调查/修复错误,我们会进行线程转储,并看到这是因为“线程B被线程a阻塞”。思考每个线程应该做什么?“进度”对每个线程或整个系统意味着什么?然后准备一个测试场景,并用超时来验证是否达到了最终进度。像“等待锁定”之类的“阻塞”?根据经验,从未发现这样的测试要求是必要的或有用的-如果线程卡住或循环,这通常是非常明显的。TBH,在多线程和/或分布式系统上,我从来没有发现单元测试作为一个整体是必要的或有用的:)我担心任何这样的工具会带来比它所能解决的更多的问题,但显然我没有经历过每一个测试环境。我不羡慕你,祝你好运……:)在某些全局数据或其他数据需要受保护访问的情况下,大多数操作系统都会提供带超时的锁等待,因此线程很容易检测到疯狂的锁等待并抱怨(例如,使用合适的日志消息)。这样的代码通常可以留在系统测试中,甚至是可交付的构建中,而没有性能损失,这样QA就不能抱怨交付的构建不是经过测试的构建:)“那么让主线程来确定”……是的,我担心您的设计正在接近一个事件范围,没有足够的引擎动力来逃脱。像“完成”这样的短语让我担心,我希望你已经设法避免了“创建/终止/加入”这个超大质量黑洞