[Python-Dev] Need help with test_mutants.py
Guido van Rossum
guido at python.org
Thu Aug 24 23:03:25 CEST 2006
On 8/24/06, Tim Peters <tim.peters at gmail.com> wrote:
> [Guido]
> > There's a unit test "test_mutants" which I don't understand. If anyone
> > remembers what it's doing, please contact me -- after ripping out
> > dictionary ordering in Py3k,
>
> Is any form of dictionary comparison still supported, and, if so, what
> does "dict1 cmp_op dict2" mean now?
Only == and != are supported between dicts. All the work is done by
dict_equal().
> > it stops working.
>
> Traceback?
Not particularly interesting: without changes, the code immediately
bombs like this:
trying w/ lengths 90 90 .
Traceback (most recent call last):
File "../Lib/test/test_mutants.py", line 152, in <module>
test(100)
File "../Lib/test/test_mutants.py", line 149, in test
test_one(random.randrange(1, 100))
File "../Lib/test/test_mutants.py", line 135, in test_one
c = cmp(dict1, dict2)
TypeError: unorderable types: dict() > dict()
> > In particular, the code in test_one() requires changes, but I don't
> > know how... Please help!
>
> The keys and values of dict1 and dict2 are filled with objects of a
> user-defined class whose __cmp__ method randomly mutates dict1 and
> dict2. dict1 and dict2 are initially forced to have the same number
> of elements, so in current Python:
>
> c = cmp(dict1, dict2)
>
> triggers a world of pain, with the internal dict code doing fancy
> stuff comparing keys and values. However, every key and value
> comparison /may/ mutate the dicts in arbitrary ways, so this is
> testing whether the dict comparison implementation blows up
> (segfaults, etc) when the dicts it's comparing mutate during
> comparison.
>
> If it's only ordering comparisons that have gone away for dicts, then,
> e.g., replacing
>
> c = cmp(dict1, dict2)
>
> with
>
> c = dict1 == dict2
>
> instead will still meet the test's intent.
I made that change, and changed class Horrid to define __eq__ instead
of __cmp__. Since dict_equal() only invokes PyObject_RichCompareBool()
with op==Py_EQ that should be all that's needed.
Now when I run it, it spits out an apaprently infinite number of dots.
Putting a print in that __eq__ method suggests it is never called. Do
you understand this?
If I change Horrid.__hash__ to always return 42, I get output like this:
trying w/ lengths 12 14
trying w/ lengths 48 52
trying w/ lengths 19 18
trying w/ lengths 10 9
trying w/ lengths 48 46
trying w/ lengths 58 55
trying w/ lengths 50 48
trying w/ lengths 45 50
trying w/ lengths 19 19 .
Traceback (most recent call last):
File "../Lib/test/test_mutants.py", line 158, in <module>
test(100)
File "../Lib/test/test_mutants.py", line 155, in test
test_one(random.randrange(1, 100))
File "../Lib/test/test_mutants.py", line 141, in test_one
c = dict1 == dict2
File "../Lib/test/test_mutants.py", line 99, in __eq__
return self.i == other.i
AttributeError: 'Horrid' object has no attribute 'i'
Segmentation fault
But it doesn't always end with a segfault -- most of the time, the
AttributeError is the last thing printed.
> No particular /result/ is expected. The test passes if and only if
> Python doesn't crash. When the test was introduced, it uncovered at
> least six distinct failure (crashing) modes across the first 20 times
> it was run, so it's well worth keeping around in some form.
Well, it looks like it did provoke another crash, so I'll play with it
some more. Thanks!
--
--Guido van Rossum (home page: http://www.python.org/~guido/)
More information about the Python-Dev
mailing list