RemotedTestCase.addCleanup exists but fails under Python 2.7

Bug #637674 reported by Andrew Bennetts
8
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Bazaar
Fix Released
Low
Martin Packman
subunit
Invalid
Undecided
Unassigned

Bug Description

bzr at one point has this code:

        # Only check for thread leaks if the test case supports cleanups
        addCleanup = getattr(test, "addCleanup", None)
        if addCleanup is not None:
            addCleanup(self._check_leaked_threads, test)

When 'test' is a RemotedTestCase and when run under Python 2.7, this fails, because: RemotedTestCase inherits from unittest.TestCase (and thus inherits the addCleanup method), but does not upcall to TestCase's __init__, so self._cleanups isn't initialised. Even if it did upcall, addCleanup wouldn't be respected because RemotedTestCase completely overrides run. The way this manifests itself is that 'bzr selftest --parallel=fork' hangs almost immediately.

I think the solution is probably to stop inheriting from TestCase: it ought to be enough to simply provide the same interface, and the friction with TestCase's __init__ is too great for RemotedTestCase to sensibly reuse it.

Tags: python27

Related branches

Revision history for this message
Robert Collins (lifeless) wrote : Re: [Bug 637674] [NEW] RemotedTestCase.addCleanup exists but fails under Python 2.7

On Tue, Sep 14, 2010 at 12:05 PM, Andrew Bennetts
<email address hidden> wrote:
> Public bug reported:
>
> bzr at one point has this code:
>
>        # Only check for thread leaks if the test case supports cleanups
>        addCleanup = getattr(test, "addCleanup", None)
>        if addCleanup is not None:
>            addCleanup(self._check_leaked_threads, test)

Thats buggy code though.

Revision history for this message
Andrew Bennetts (spiv) wrote :

Robert Collins wrote:
> > bzr at one point has this code:
> >
> >        # Only check for thread leaks if the test case supports cleanups
> >        addCleanup = getattr(test, "addCleanup", None)
> >        if addCleanup is not None:
> >            addCleanup(self._check_leaked_threads, test)
>
> Thats buggy code though.

I'm not surprised. Care to elaborate though? (I think I have a fair idea
why, but it'd prefer not to guess.)

Regardless, RemotedTestCase inheriting from TestCase without up-calling
seems pretty fragile, and likely to be a source of trouble as the standard
unittest.TestCase implementation keeps evolving.

Revision history for this message
Robert Collins (lifeless) wrote :

On Tue, Sep 14, 2010 at 7:27 PM, Andrew Bennetts
<email address hidden> wrote:
> Robert Collins wrote:
>> > bzr at one point has this code:
>> >
>> >        # Only check for thread leaks if the test case supports cleanups
>> >        addCleanup = getattr(test, "addCleanup", None)
>> >        if addCleanup is not None:
>> >            addCleanup(self._check_leaked_threads, test)
>>
>> Thats buggy code though.
>
> I'm not surprised.  Care to elaborate though?  (I think I have a fair idea
> why, but it'd prefer not to guess.)

TestCase offers two contracts:
 - the runner contract (run, debug, id, description, countTests)
 - the testcase contract (only for use by a subclass on self)

The code that bzr has is not in the runner contact, and by definition
not running under the testcase contract.

So its being fundamentally naughty.

> Regardless, RemotedTestCase inheriting from TestCase without up-calling
> seems pretty fragile, and likely to be a source of trouble as the standard
> unittest.TestCase implementation keeps evolving.

This is the first issue seen, subclassing matters to some clients
(also buggy) and its not wrong to not upcall when you don't -call at
all-.

The bzr code path shown will break with other third party
implementations as well - it has nothing to do with upcalling per se.

Revision history for this message
Martin Packman (gz) wrote :

Marking as also affects bzr as the opinion is the bzr code is wrong. I asked about this in code review but got no feedback, suggestions welcome.

Changed in bzr:
importance: Undecided → Low
status: New → Confirmed
Jelmer Vernooij (jelmer)
tags: added: python27
Revision history for this message
Martin Packman (gz) wrote :

With natty people have started caring about 2.7 so better resolve this now.

Changed in bzr:
assignee: nobody → Martin [gz] (gz)
status: Confirmed → In Progress
Martin Packman (gz)
Changed in bzr:
milestone: none → 2.3b5
status: In Progress → Fix Released
Revision history for this message
Jonathan Lange (jml) wrote :

It's not clear what the status of this bug is in subunit. Robert seems to imply that it's not a bug, but it's hard to gauge.

Changed in subunit:
status: New → Incomplete
Revision history for this message
Robert Collins (lifeless) wrote :

I'm marking this invalid because the subclassing is deliberate - there are type sniffers out there and merely meeting the contract wasn't enough in the past.

Changed in subunit:
status: Incomplete → Invalid
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.