So yesterday we found a bug in RATS (Rawhide Acceptance Test Suite – the scripts we use for testing Rawhide and other Fedora candidate trees). The test found no problems with the Fedora 13 release candidate tree we’d just made, but when we tried to install it, the installer died because the kernel had missing dependencies. Huh? The tests are supposed to check that!
We checked the logs, and the test script hadn’t even checked the kernel package. But ‘kernel’ was definitely in the list of packages that were supposed to be checked – and it was still in the list after we got through the loop that checked all the packages. But it never got tested. What gives?
The cause turned out to be an embarrassing mistake on my part. Consider the following python snippet:
meats = ('bacon', 'pork', 'beef') input = ['one', 'two', 'pork', 'three', 'four'] for n in input: if n in meats: input.remove(n) else: print n
What would you expect to see as output? Probably ‘one, two, three, four’, right? Instead, you’ll get:
one two four
Shortening a list while you’re iterating over it turns out to be a bad idea. You can append to the list just fine, and the loop will happily iterate over the new items you added once it gets to the end of the list. But if you remove an item, bad things happen. Here’s what happens:
When the loop is processing
'pork', it’s processing the third item in the list. When you remove
'pork', the list gets shifted up, so now
'three' becomes the third item in the list.
Then we hit the end of the loop and move to the fourth item in the list – without ever processing
So it turns RATS was removing the package before ‘kernel’ in the package list – which was the right thing to do – but that caused us to accidentally skip ‘kernel’, leading to the false positive result from the test.
Long story short: Never remove items from a list while you’re looping over it.