通过平分(搜索)修订历史记录和不可测试的提交(修订版)来查找错误

时间:2009-06-06 09:05:36

标签: algorithm debugging version-control

大多数现代版本控制工具都有一个命令来查找通过二进制搜索(二等分)引入错误的更改。此类命令可能是内置的,也可能是作为扩展或插件提供的。示例包括Git中的git-bisect,Mercurial中的“hg bisect”(之前可用作hbisect扩展名)和Bazaar的bzr-bisect插件。

即使存在非线性历史(分支点和合并),挑战也是以自动或半自动的方式进行。目标通常是在最少的步骤中找到“坏”修订,或者更详细地找到提交以测试哪个,如果可能的话,将提交的图提交到测试(提交的DAG)的一半。我认为,这个问题很好地解决了。

不稳定提交存在问题,例如如果某些修订代码甚至没有编译,或者它编译它不会启动/运行(或找到与您正在搜索的错误无关的错误)。这意味着您现在有三个可能的状态,而不是简单地将提交标记为“好”或“坏”:

  • - 错误不存在
  • 糟糕 - 越野行为
  • 未知 untestable ) - 不知道是否存在错误

某些版本控制系统(SCM)允许您“跳过”此类提交,通常转到父修订版作为下一个要测试的版本。


问题是:

  • 如果您处理了这种情况,意味着您使用了二分法并偶然发现了不可测试的修订版,您的经验是什么,这些不可测试的提交的分发?它们是单独发生的(单个不可测试的提交),还是它们出现在范围内(修订版本a..b是不可测试的)?您是否发现自己处于提交后必须跳过提交的情况?

  • 是否存在一些材料模型(就像列表/线性历史的简单二等分,甚至用于二等分修改的任意DAG)或算法(可能是启发式),它允许优化跳过不可测试的提交。目标是再次在存在不可测试提交(或无关错误)的情况下最小化(平均)测试版本数量。

  • 您是否使用版本控制系统,或某些附加/扩展/插件用于修订控制系统,或者某些实现此类算法的第三方工具,除了允许通过转到“跳过”不可测试的提交邻居修改?这个VCS或工具是什么?它使用什么算法(如果你知道的话)?

希望这会导致更容易(半)自动发现错误......


已于2009年6月6日添加:
当使用Git的高级功能时,有一种情况是你可以有一个完整的分支的不稳定提交(或者至少很难测试),即你使用“子树的地方“合并以加入两个独立项目的历史记录(例如,使用”子树“合并单独开发的一些驱动程序的完整Linux内核)。在提出处理不稳定提交的算法时需要考虑这一点:非线性历史可以有一个完整的不稳定提交分支,算法必须考虑拓扑(稍微)。

3 个答案:

答案 0 :(得分:3)

显然,已经检查过的内容无法提供帮助。我工作的大型代码库需要所有签入才能实际构建。这是通过让开发人员将其更改提交到签入服务器来完成的,该签入服务器将有一系列更改等待进入。每个更改都按照提交的顺序为所有目标平台构建。如果构建失败,则拒绝签入。如果成功,则运行一套自动回归/单元测试。如果任何测试失败,则拒绝办理登机手续。如果成功,则将签入提交到存储库。

如果你有这样一个系统,它会大大减少unbuildable / untestable修订的数量。错误的构建仅限于库存管理员在签入服务器外部执行古怪的操作。

在没有这种选择的环境中,我没有进行严格的统计分析,但我发现有些无法修改的修订版本发生在口袋里。一次办理登机手续会弄乱大量的东西,然后会有一系列小额登记手续试图纠正这些混乱局面。然后事情一般都很好。

答案 1 :(得分:0)

您可以将二分/二元搜索算法的各个元素重新定义为具有相邻“未知”状态的修订范围,而不是单个修订。

换句话说,如果在二进制搜索期间发现未知状态,则开始向前和向后进行子搜索,以找到修订范围的边界,为您提供明确的答案。这可能是两个方向的线性搜索,所以它会慢一点,你必须假设大多数修订都不是不可测试的。

这将最终输出出现错误的一系列修订版,例如修订版之间的某个版本(58,63)。然后,您必须手动搜索此范围。

答案 2 :(得分:0)

只是一个想法:我知道你正在考虑的另一个问题是在有噪音的情况下进行测试。想到跳过的一种方法是将它们视为随机响应好/坏,并使用对这些错误具有鲁棒性的二分算法,例如: http://www.disp.uniroma2.it/users/grandoni/FGItcs.pdf “存在内存故障时的最佳弹性排序和搜索”。 I. Finocchi,F。Grandoni和G. F. Italiano。

将该算法应用于git-bisect的效果是远离跳过点,并在发现已经遵循错误分支时重新运行搜索。与上面的论文不同,你知道哪些点不可靠,所以你可以回溯。