Mercurial_ The Definitive Guide - Bryan O'Sullivan [70]
user: Bryan O'Sullivan date: Tue May 05 06:44:23 2009 +0000 summary: buggy changeset Even though we had 40 changesets to search through, the hg bisect command let us find the changeset that introduced our “bug” with only five tests. Because the number of tests that the hg bisect command performs grows logarithmically with the number of changesets to search, the advantage that it has over the “brute force” search approach increases with every changeset you add. Cleaning Up After Your Search When you’re finished using the hg bisect command in a repository, you can use the hg bisect --reset command to drop the information it was using to drive your search. The command doesn’t use much space, so it doesn’t matter if you forget to run this command. However, hg bisect won’t let you start a new search in that repository until you do a hg bisect --reset. $ hg bisect --reset Tips for Finding Bugs Effectively Give Consistent Input The hg bisect command requires that you correctly report the result of every test you perform. If you tell it that a test failed when it really succeeded, it might be able to detect the inconsistency. If it can identify an inconsistency in your reports, it will tell you that a particular changeset is both good and bad. However, it can’t do this perfectly; it’s about as likely to report the wrong changeset as the source of the bug. Automate As Much As Possible When I started using the hg bisect command, I tried a few times to run my tests by hand, on the command line. This is an approach that I, at least, am not suited to. After a few tries, I found that I was making enough mistakes that I was having to restart my searches several times before finally getting correct results. My initial problems with driving the hg bisect command by hand occurred even with simple searches on small repositories; if the problem you’re looking for is more subtle, or the number of tests that hg bisect must perform increases, the likelihood of operator error ruining the search is much higher. Once I started automating my tests, I had much better results. The key to automated testing is twofold: always test for the same symptom, and always feed consistent input to the hg bisect command. In my tutorial example above, the grep command tests for the symptom, and the if statement takes the result of this check and ensures that we always feed the same input to the hg bisect command. The mytest function marries these together in a reproducible way, so that every test is uniform and consistent. Check Your Results Because the output of a hg bisect search is only as good as the input you give it, don’t take the changeset it reports as the absolute truth. A simple way to cross-check its report is to manually run your test at each of the following changesets: The changeset that it reports as the first bad revision. Your test should still report this as bad. The parent of that changeset (either parent, if it’s a merge). Your test should report this changeset as good. A child of that changeset. Your test should report this changeset as bad. Beware Interference Between Bugs It’s possible that your search for one bug could be disrupted by the presence of another. For example, let’s say your software crashes at revision 100, and worked correctly at revision 50. Unknown to you, someone else introduced a different crashing bug at revision 60, and fixed it at revision 80. This could distort your results in one of several ways. It is possible that this other bug completely “masks” yours, which is to say that it occurs before your bug has a chance to manifest itself. If you can’t avoid that other bug (for example, it prevents your project from building), and so can’t tell whether your bug is present in a particular changeset, the hg bisect command cannot help you directly. Instead, you can mark a changeset as untested by running hg bisect --skip. A different problem could arise if your test for a bug’s presence is not specific enough. If you check for