Merge lp:~jml/launchpad/testtools-experiment into lp:launchpad

Proposed by Jonathan Lange
Status: Merged
Approved by: Jonathan Lange
Approved revision: no longer in the source branch.
Merged at revision: 11980
Proposed branch: lp:~jml/launchpad/testtools-experiment
Merge into: lp:launchpad
Diff against target: 2758 lines (+471/-515)
26 files modified
lib/canonical/librarian/client.py (+2/-1)
lib/canonical/librarian/testing/server.py (+5/-0)
lib/canonical/testing/layers.py (+31/-27)
lib/lp/buildmaster/tests/mock_slaves.py (+16/-25)
lib/lp/buildmaster/tests/test_builder.py (+52/-84)
lib/lp/buildmaster/tests/test_manager.py (+24/-24)
lib/lp/code/model/tests/test_recipebuilder.py (+13/-27)
lib/lp/codehosting/codeimport/tests/test_workermonitor.py (+30/-31)
lib/lp/codehosting/puller/tests/test_scheduler.py (+36/-43)
lib/lp/codehosting/sshserver/tests/test_daemon.py (+3/-12)
lib/lp/codehosting/sshserver/tests/test_session.py (+6/-11)
lib/lp/codehosting/tests/helpers.py (+12/-7)
lib/lp/codehosting/tests/test_sftp.py (+28/-33)
lib/lp/codehosting/vfs/tests/test_branchfs.py (+27/-47)
lib/lp/codehosting/vfs/tests/test_branchfsclient.py (+11/-10)
lib/lp/registry/tests/test_distributionmirror_prober.py (+21/-0)
lib/lp/services/sshserver/tests/test_auth.py (+25/-18)
lib/lp/services/twistedsupport/tests/test_loggingsupport.py (+16/-15)
lib/lp/services/twistedsupport/tests/test_processmonitor.py (+32/-35)
lib/lp/services/twistedsupport/tests/test_twistedsupport.py (+9/-5)
lib/lp/services/twistedsupport/tests/test_xmlrpc.py (+1/-8)
lib/lp/services/twistedsupport/xmlrpc.py (+23/-2)
lib/lp/soyuz/tests/test_binarypackagebuildbehavior.py (+26/-34)
lib/lp/testing/__init__.py (+13/-0)
lib/lp/translations/tests/test_translationtemplatesbuildbehavior.py (+8/-15)
versions.cfg (+1/-1)
To merge this branch: bzr merge lp:~jml/launchpad/testtools-experiment
Reviewer Review Type Date Requested Status
Robert Collins (community) Approve
Review via email: mp+39698@code.launchpad.net

Commit message

[r=lifeless][ui=none][no-qa] Use testtools support for running Deferred-using tests, rather than twisted.trial.

Description of the change

This branch completely obliterates the TwistedLayer, TwistedLaunchpadZopelessLayer and the TwistedAppServerLayer.

Instead of using twisted.trial.unittest.TestCase to run tests, this branch leverages a new, unreleased feature of testtools that allows for custom running logic.

This means all of our tests can now inherit from lp.testing.TestCase, even if they need Twisted support. What *that* means is less boilerplate and more handy tools for writing tests.

To post a comment you must log in.
Revision history for this message
Jonathan Lange (jml) wrote :

This depends on some changes to testtools that have yet to land in trunk: https://code.launchpad.net/~jml/testtools/learning-from-launchpad/+merge/39697

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

A small meta thought; it might be nice to present this as two changes;
 - stop using the unneeded stuff
 - garbage collect.

Reviewing it anyhow.

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

+ Content(
216 + UTF8_TEXT,
217 + lambda: open(tachandler.logfile, 'r').read()))

should be

+ Content(
216 + UTF8_TEXT,
217 + lambda: open(tachandler.logfile, 'r').readlines()))

for performance (read works because 'foo' iterates as 'f', 'o', 'o').

However, the fixture.getDetails API is an even nicer way to do this, and useFixture automatically glues that in. So you should be changing the fixture, not digging into it here. For a primitive version of the same, see my 'librarian' branch which hasn't landed yet (test fallout) but has a getLogChunks() method which contains the necessary logic to get the librarian log file contents (and thus pulling that up to the base TacHandler class, and inserting a call to that into self.addDetail in setUp() of TacHandler should be all thats needed).

For this pattern:
+ # Avoid circular imports.
368 + from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
369 self.publisher = SoyuzTestPublisher()

I suggest either bzrlib's lazy_import, or a self.make_publisher() helper'.

There are some tests that can be improved further. Like
+ self.assertTrue(logfile_lfa.filename.endswith('_FULLYBUILT.txt.gz'))
->
self.assertThat(logfile_lfa.filename, EndsWith('_FULLYBUILT.txt.gz'))

and
1909 # Restore the globals that our tests fiddle with.
1910 distributionmirror_prober.host_requests = self.orig_host_requests
1911 distributionmirror_prober.host_timeouts = self.orig_host_timeouts
that would be nice as a fixture

If there are no major changes to fix the remaining XXX, doit.

review: Approve
Revision history for this message
Jonathan Lange (jml) wrote :

On Sat, Oct 30, 2010 at 10:01 PM, Robert Collins
<email address hidden> wrote:
> Review: Approve
> +            Content(
> 216     +                UTF8_TEXT,
> 217     +                lambda: open(tachandler.logfile, 'r').read()))
>
> should be
>
> +            Content(
> 216     +                UTF8_TEXT,
> 217     +                lambda: open(tachandler.logfile, 'r').readlines()))
>
> for performance (read works because 'foo' iterates as 'f', 'o', 'o').
>

Changed.

> However, the fixture.getDetails API is an even nicer way to do this, and useFixture automatically glues that in. So you should be changing the fixture, not digging into it here.  For a primitive version of the same, see my 'librarian' branch which hasn't landed yet (test fallout) but has a getLogChunks() method which contains the necessary logic to get the librarian log file contents (and thus pulling that up to the base TacHandler class, and inserting a call to that into self.addDetail in setUp() of TacHandler should be all thats needed).
>

I'll be glad to do this in a follow-up branch.

> For this pattern:
> +        # Avoid circular imports.
> 368     +        from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
> 369              self.publisher = SoyuzTestPublisher()
>
> I suggest either bzrlib's lazy_import, or a self.make_publisher() helper'.
>

I did the latter.

> There are some tests that can be improved further. Like
> +        self.assertTrue(logfile_lfa.filename.endswith('_FULLYBUILT.txt.gz'))
> ->
> self.assertThat(logfile_lfa.filename, EndsWith('_FULLYBUILT.txt.gz'))
>

If testtools had an EndsWith already… Filed
https://bugs.edge.launchpad.net/testtools/+bug/669166.

> and
> 1909             # Restore the globals that our tests fiddle with.
> 1910             distributionmirror_prober.host_requests = self.orig_host_requests
> 1911             distributionmirror_prober.host_timeouts = self.orig_host_timeouts
> that would be nice as a fixture
>

Indeed. When I saw it, I thought that it would be nice to have some
kind of abstraction – probably a fixture – that allowed me to declare
"this test is going to modify these bits of global state; please
restore them when done".

> If there are no major changes to fix the remaining XXX, doit.

Well, I did as you recommended and backed out the removal of layers.

Other than that, the fix for the failing test was to make sure that
previous tests actually used AsynchronousDeferredRunTest.

Not landing yet, because it's likely to have intermittent failures and
I won't be around to debug. Running through ec2 test rather than ec2
land.

jml

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/librarian/client.py'
2--- lib/canonical/librarian/client.py 2010-11-06 12:50:22 +0000
3+++ lib/canonical/librarian/client.py 2010-11-24 19:57:36 +0000
4@@ -248,7 +248,8 @@
5 # Read response
6 response = self.state.f.readline().strip()
7 if not response.startswith('200'):
8- raise UploadFailed('Server said: ' + response)
9+ raise UploadFailed(
10+ 'Could not upload %s. Server said: %s' % (name, response))
11
12 status, ids = response.split()
13 contentID, aliasID = ids.split('/', 1)
14
15=== modified file 'lib/canonical/librarian/testing/server.py'
16--- lib/canonical/librarian/testing/server.py 2010-10-26 20:44:10 +0000
17+++ lib/canonical/librarian/testing/server.py 2010-11-24 19:57:36 +0000
18@@ -194,9 +194,14 @@
19 # error.
20 return os.path.join(self.root, 'librarian.log')
21
22+ def logChunks(self):
23+ """Get a list with the contents of the librarian log in it."""
24+ return open(self.logfile, 'rb').readlines()
25+
26
27 _global_fixture = LibrarianServerFixture()
28
29+
30 def LibrarianTestSetup():
31 """Support the stateless lie."""
32 return _global_fixture
33
34=== modified file 'lib/canonical/testing/layers.py'
35--- lib/canonical/testing/layers.py 2010-11-11 11:55:53 +0000
36+++ lib/canonical/testing/layers.py 2010-11-24 19:57:36 +0000
37@@ -630,34 +630,38 @@
38 """
39 _reset_between_tests = True
40
41- _is_setup = False
42+ librarian_fixture = None
43
44 @classmethod
45 @profiled
46 def setUp(cls):
47- cls._is_setup = True
48- if not LibrarianLayer._reset_between_tests:
49+ if not cls._reset_between_tests:
50 raise LayerInvariantError(
51 "_reset_between_tests changed before LibrarianLayer "
52 "was actually used."
53 )
54- the_librarian = LibrarianTestSetup()
55- the_librarian.setUp()
56- LibrarianLayer._check_and_reset()
57+ cls.librarian_fixture = LibrarianTestSetup()
58+ cls.librarian_fixture.setUp()
59+ cls._check_and_reset()
60
61 @classmethod
62 @profiled
63 def tearDown(cls):
64- if not cls._is_setup:
65+ if cls.librarian_fixture is None:
66 return
67- cls._is_setup = False
68- if not LibrarianLayer._reset_between_tests:
69- raise LayerInvariantError(
70- "_reset_between_tests not reset before LibrarianLayer "
71- "shutdown"
72- )
73- LibrarianLayer._check_and_reset()
74- LibrarianTestSetup().tearDown()
75+ try:
76+ cls._check_and_reset()
77+ finally:
78+ librarian = cls.librarian_fixture
79+ cls.librarian_fixture = None
80+ try:
81+ if not cls._reset_between_tests:
82+ raise LayerInvariantError(
83+ "_reset_between_tests not reset before LibrarianLayer "
84+ "shutdown"
85+ )
86+ finally:
87+ librarian.cleanUp()
88
89 @classmethod
90 @profiled
91@@ -676,20 +680,20 @@
92 "the Librarian is restarted if it absolutely must be "
93 "shutdown: " + str(e)
94 )
95- if LibrarianLayer._reset_between_tests:
96- LibrarianTestSetup().clear()
97+ if cls._reset_between_tests:
98+ cls.librarian_fixture.clear()
99
100 @classmethod
101 @profiled
102 def testSetUp(cls):
103- LibrarianLayer._check_and_reset()
104+ cls._check_and_reset()
105
106 @classmethod
107 @profiled
108 def testTearDown(cls):
109- if LibrarianLayer._hidden:
110- LibrarianLayer.reveal()
111- LibrarianLayer._check_and_reset()
112+ if cls._hidden:
113+ cls.reveal()
114+ cls._check_and_reset()
115
116 # Flag maintaining state of hide()/reveal() calls
117 _hidden = False
118@@ -706,17 +710,17 @@
119 We do this by altering the configuration so the Librarian client
120 looks for the Librarian server on the wrong port.
121 """
122- LibrarianLayer._hidden = True
123- if LibrarianLayer._fake_upload_socket is None:
124+ cls._hidden = True
125+ if cls._fake_upload_socket is None:
126 # Bind to a socket, but don't listen to it. This way we
127 # guarantee that connections to the given port will fail.
128- LibrarianLayer._fake_upload_socket = socket.socket(
129+ cls._fake_upload_socket = socket.socket(
130 socket.AF_INET, socket.SOCK_STREAM)
131 assert config.librarian.upload_host == 'localhost', (
132 'Can only hide librarian if it is running locally')
133- LibrarianLayer._fake_upload_socket.bind(('127.0.0.1', 0))
134+ cls._fake_upload_socket.bind(('127.0.0.1', 0))
135
136- host, port = LibrarianLayer._fake_upload_socket.getsockname()
137+ host, port = cls._fake_upload_socket.getsockname()
138 librarian_data = dedent("""
139 [librarian]
140 upload_port: %s
141@@ -730,7 +734,7 @@
142
143 This just involves restoring the config to the original value.
144 """
145- LibrarianLayer._hidden = False
146+ cls._hidden = False
147 config.pop('hide_librarian')
148
149
150
151=== modified file 'lib/lp/buildmaster/tests/mock_slaves.py'
152--- lib/lp/buildmaster/tests/mock_slaves.py 2010-10-27 16:45:11 +0000
153+++ lib/lp/buildmaster/tests/mock_slaves.py 2010-11-24 19:57:36 +0000
154@@ -13,6 +13,7 @@
155 'CorruptBehavior',
156 'DeadProxy',
157 'LostBuildingBrokenSlave',
158+ 'make_publisher',
159 'MockBuilder',
160 'OkSlave',
161 'SlaveTestHelpers',
162@@ -46,8 +47,17 @@
163 from lp.soyuz.model.binarypackagebuildbehavior import (
164 BinaryPackageBuildBehavior,
165 )
166+from lp.services.twistedsupport.xmlrpc import fix_bug_2518
167 from lp.testing.sampledata import I386_ARCHITECTURE_NAME
168
169+fix_bug_2518()
170+
171+def make_publisher():
172+ """Make a Soyuz test publisher."""
173+ # Avoid circular imports.
174+ from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
175+ return SoyuzTestPublisher()
176+
177
178 class MockBuilder:
179 """Emulates a IBuilder class."""
180@@ -290,17 +300,12 @@
181
182 :return: A `BuilddSlaveTestSetup` object.
183 """
184- tachandler = BuilddSlaveTestSetup()
185- tachandler.setUp()
186- # Basically impossible to do this w/ TrialTestCase. But it would be
187- # really nice to keep it.
188- #
189- # def addLogFile(exc_info):
190- # self.addDetail(
191- # 'xmlrpc-log-file',
192- # Content(UTF8_TEXT, lambda: open(tachandler.logfile, 'r').read()))
193- # self.addOnException(addLogFile)
194- self.addCleanup(tachandler.tearDown)
195+ tachandler = self.useFixture(BuilddSlaveTestSetup())
196+ self.addDetail(
197+ 'xmlrpc-log-file',
198+ Content(
199+ UTF8_TEXT,
200+ lambda: open(tachandler.logfile, 'r').readlines()))
201 return tachandler
202
203 def getClientSlave(self, reactor=None, proxy=None):
204@@ -308,20 +313,6 @@
205
206 Points to a fixed URL that is also used by `BuilddSlaveTestSetup`.
207 """
208- # Twisted has a bug! We need to monkey patch
209- # QueryProtocol.handleResponse() so that it terminates the
210- # connection properly, otherwise the Trial test can leave the
211- # reactor dirty which fails the test.
212- # See http://twistedmatrix.com/trac/ticket/2518
213- saved_handleResponse = xmlrpc.QueryProtocol.handleResponse
214- def _handleResponse(self, contents):
215- self.factory.parseResponse(contents)
216- self.transport.loseConnection()
217- xmlrpc.QueryProtocol.handleResponse = _handleResponse
218- def restore_handleResponse():
219- xmlrpc.QueryProtocol.handleResponse = saved_handleResponse
220- self.addCleanup(restore_handleResponse)
221-
222 return BuilderSlave.makeBuilderSlave(
223 self.TEST_URL, 'vmhost', reactor, proxy)
224
225
226=== modified file 'lib/lp/buildmaster/tests/test_builder.py'
227--- lib/lp/buildmaster/tests/test_builder.py 2010-11-17 16:52:19 +0000
228+++ lib/lp/buildmaster/tests/test_builder.py 2010-11-24 19:57:36 +0000
229@@ -7,15 +7,23 @@
230 import signal
231 import xmlrpclib
232
233-from twisted.web.client import getPage
234+from testtools.deferredruntest import (
235+ assert_fails_with,
236+ AsynchronousDeferredRunTest,
237+ AsynchronousDeferredRunTestForBrokenTwisted,
238+ SynchronousDeferredRunTest,
239+ )
240
241 from twisted.internet.defer import CancelledError
242 from twisted.internet.task import Clock
243 from twisted.python.failure import Failure
244-from twisted.trial.unittest import TestCase as TrialTestCase
245+from twisted.web.client import getPage
246
247 from zope.component import getUtility
248-from zope.security.proxy import removeSecurityProxy
249+from zope.security.proxy import (
250+ isinstance as zope_isinstance,
251+ removeSecurityProxy,
252+ )
253
254 from canonical.buildd.slave import BuilderStatus
255 from canonical.config import config
256@@ -29,8 +37,6 @@
257 from canonical.testing.layers import (
258 DatabaseFunctionalLayer,
259 LaunchpadZopelessLayer,
260- TwistedLaunchpadZopelessLayer,
261- TwistedLayer,
262 )
263 from lp.buildmaster.enums import BuildStatus
264 from lp.buildmaster.interfaces.builder import (
265@@ -57,6 +63,7 @@
266 CorruptBehavior,
267 DeadProxy,
268 LostBuildingBrokenSlave,
269+ make_publisher,
270 MockBuilder,
271 OkSlave,
272 SlaveTestHelpers,
273@@ -73,26 +80,12 @@
274 BinaryPackageBuildBehavior,
275 )
276 from lp.testing import (
277- ANONYMOUS,
278- login_as,
279- logout,
280+ TestCase,
281 TestCaseWithFactory,
282 )
283-from lp.testing.factory import LaunchpadObjectFactory
284 from lp.testing.fakemethod import FakeMethod
285
286
287-def make_publisher():
288- """Make a test publisher.
289-
290- Exists only to work around circular import problems. When the
291- canonical/launchpad/database/__init__.py globs go away, this can probably
292- go away too.
293- """
294- from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
295- return SoyuzTestPublisher()
296-
297-
298 class TestBuilder(TestCaseWithFactory):
299 """Basic unit tests for `Builder`."""
300
301@@ -131,21 +124,14 @@
302 self.assertIs(None, bq)
303
304
305-class TestBuilderWithTrialBase(TrialTestCase):
306+class TestBuilder(TestCaseWithFactory):
307
308- layer = TwistedLaunchpadZopelessLayer
309+ layer = LaunchpadZopelessLayer
310+ run_tests_with = AsynchronousDeferredRunTest.make_factory(timeout=10)
311
312 def setUp(self):
313- super(TestBuilderWithTrialBase, self)
314- self.slave_helper = SlaveTestHelpers()
315- self.slave_helper.setUp()
316- self.addCleanup(self.slave_helper.cleanUp)
317- self.factory = LaunchpadObjectFactory()
318- login_as(ANONYMOUS)
319- self.addCleanup(logout)
320-
321-
322-class TestBuilderWithTrial(TestBuilderWithTrialBase):
323+ super(TestBuilder, self).setUp()
324+ self.slave_helper = self.useFixture(SlaveTestHelpers())
325
326 def test_updateStatus_aborts_lost_and_broken_slave(self):
327 # A slave that's 'lost' should be aborted; when the slave is
328@@ -164,12 +150,12 @@
329 def test_resumeSlaveHost_nonvirtual(self):
330 builder = self.factory.makeBuilder(virtualized=False)
331 d = builder.resumeSlaveHost()
332- return self.assertFailure(d, CannotResumeHost)
333+ return assert_fails_with(d, CannotResumeHost)
334
335 def test_resumeSlaveHost_no_vmhost(self):
336 builder = self.factory.makeBuilder(virtualized=True, vm_host=None)
337 d = builder.resumeSlaveHost()
338- return self.assertFailure(d, CannotResumeHost)
339+ return assert_fails_with(d, CannotResumeHost)
340
341 def test_resumeSlaveHost_success(self):
342 reset_config = """
343@@ -192,7 +178,7 @@
344 self.addCleanup(config.pop, 'reset fail')
345 builder = self.factory.makeBuilder(virtualized=True, vm_host="pop")
346 d = builder.resumeSlaveHost()
347- return self.assertFailure(d, CannotResumeHost)
348+ return assert_fails_with(d, CannotResumeHost)
349
350 def test_handleTimeout_resume_failure(self):
351 reset_fail_config = """
352@@ -203,7 +189,7 @@
353 builder = self.factory.makeBuilder(virtualized=True, vm_host="pop")
354 builder.builderok = True
355 d = builder.handleTimeout(QuietFakeLogger(), 'blah')
356- return self.assertFailure(d, CannotResumeHost)
357+ return assert_fails_with(d, CannotResumeHost)
358
359 def _setupBuilder(self):
360 processor = self.factory.makeProcessor(name="i386")
361@@ -349,8 +335,9 @@
362 candidate.markAsBuilding(builder)
363
364 # At this point we should see a valid behaviour on the builder:
365- self.assertNotIdentical(
366- IdleBuildBehavior, builder.current_build_behavior)
367+ self.assertFalse(
368+ zope_isinstance(
369+ builder.current_build_behavior, IdleBuildBehavior))
370
371 # Now reset the job and try to rescue the builder.
372 candidate.destroySelf()
373@@ -364,11 +351,17 @@
374 return d.addCallback(check_builder)
375
376
377-class TestBuilderSlaveStatus(TestBuilderWithTrialBase):
378-
379+class TestBuilderSlaveStatus(TestCaseWithFactory):
380 # Verify what IBuilder.slaveStatus returns with slaves in different
381 # states.
382
383+ layer = LaunchpadZopelessLayer
384+ run_tests_with = AsynchronousDeferredRunTest
385+
386+ def setUp(self):
387+ super(TestBuilderSlaveStatus, self).setUp()
388+ self.slave_helper = self.useFixture(SlaveTestHelpers())
389+
390 def assertStatus(self, slave, builder_status=None,
391 build_status=None, logtail=False, filemap=None,
392 dependencies=None):
393@@ -815,24 +808,17 @@
394 self.builder.current_build_behavior, BinaryPackageBuildBehavior)
395
396
397-class TestSlave(TrialTestCase):
398+class TestSlave(TestCase):
399 """
400 Integration tests for BuilderSlave that verify how it works against a
401 real slave server.
402 """
403
404- layer = TwistedLayer
405+ run_tests_with = AsynchronousDeferredRunTest.make_factory(timeout=10)
406
407 def setUp(self):
408 super(TestSlave, self).setUp()
409- self.slave_helper = SlaveTestHelpers()
410- self.slave_helper.setUp()
411- self.addCleanup(self.slave_helper.cleanUp)
412-
413- # XXX: JonathanLange 2010-09-20 bug=643521: There are also tests for
414- # BuilderSlave in buildd-slave.txt and in other places. The tests here
415- # ought to become the canonical tests for BuilderSlave vs running buildd
416- # XML-RPC server interaction.
417+ self.slave_helper = self.useFixture(SlaveTestHelpers())
418
419 # XXX 2010-10-06 Julian bug=655559
420 # This is failing on buildbot but not locally; it's trying to abort
421@@ -929,7 +915,7 @@
422 self.slave_helper.getServerSlave()
423 slave = self.slave_helper.getClientSlave()
424 d = slave.sendFileToSlave('blahblah', None, None, None)
425- return self.assertFailure(d, CannotFetchFile)
426+ return assert_fails_with(d, CannotFetchFile)
427
428 def test_sendFileToSlave_actually_there(self):
429 tachandler = self.slave_helper.getServerSlave()
430@@ -1019,17 +1005,15 @@
431 return d
432
433
434-class TestSlaveTimeouts(TrialTestCase):
435+class TestSlaveTimeouts(TestCase):
436 # Testing that the methods that call callRemote() all time out
437 # as required.
438
439- layer = TwistedLayer
440+ run_tests_with = AsynchronousDeferredRunTestForBrokenTwisted
441
442 def setUp(self):
443 super(TestSlaveTimeouts, self).setUp()
444- self.slave_helper = SlaveTestHelpers()
445- self.slave_helper.setUp()
446- self.addCleanup(self.slave_helper.cleanUp)
447+ self.slave_helper = self.useFixture(SlaveTestHelpers())
448 self.clock = Clock()
449 self.proxy = DeadProxy("url")
450 self.slave = self.slave_helper.getClientSlave(
451@@ -1037,7 +1021,7 @@
452
453 def assertCancelled(self, d):
454 self.clock.advance(config.builddmaster.socket_timeout + 1)
455- return self.assertFailure(d, CancelledError)
456+ return assert_fails_with(d, CancelledError)
457
458 def test_timeout_abort(self):
459 return self.assertCancelled(self.slave.abort())
460@@ -1063,17 +1047,15 @@
461 self.slave.build(None, None, None, None, None))
462
463
464-class TestSlaveConnectionTimeouts(TrialTestCase):
465+class TestSlaveConnectionTimeouts(TestCase):
466 # Testing that we can override the default 30 second connection
467 # timeout.
468
469- layer = TwistedLayer
470+ run_test = SynchronousDeferredRunTest
471
472 def setUp(self):
473 super(TestSlaveConnectionTimeouts, self).setUp()
474- self.slave_helper = SlaveTestHelpers()
475- self.slave_helper.setUp()
476- self.addCleanup(self.slave_helper.cleanUp)
477+ self.slave_helper = self.useFixture(SlaveTestHelpers())
478 self.clock = Clock()
479 self.proxy = ProxyWithConnectionTimeout("fake_url")
480 self.slave = self.slave_helper.getClientSlave(
481@@ -1082,12 +1064,7 @@
482 def test_connection_timeout(self):
483 # The default timeout of 30 seconds should not cause a timeout,
484 # only the config value should.
485- timeout_config = """
486- [builddmaster]
487- socket_timeout: 180
488- """
489- config.push('timeout', timeout_config)
490- self.addCleanup(config.pop, 'timeout')
491+ self.pushConfig('builddmaster', socket_timeout=180)
492
493 d = self.slave.echo()
494 # Advance past the 30 second timeout. The real reactor will
495@@ -1097,15 +1074,9 @@
496 self.clock.advance(31)
497 self.assertFalse(d.called)
498
499- # Now advance past the real socket timeout and expect a
500- # Failure.
501-
502- def got_timeout(failure):
503- self.assertIsInstance(failure.value, CancelledError)
504-
505- d.addBoth(got_timeout)
506 self.clock.advance(config.builddmaster.socket_timeout + 1)
507 self.assertTrue(d.called)
508+ return assert_fails_with(d, CancelledError)
509
510 def test_BuilderSlave_uses_ProxyWithConnectionTimeout(self):
511 # Make sure that BuilderSlaves use the custom proxy class.
512@@ -1113,19 +1084,16 @@
513 self.assertIsInstance(slave._server, ProxyWithConnectionTimeout)
514
515
516-class TestSlaveWithLibrarian(TrialTestCase):
517+class TestSlaveWithLibrarian(TestCaseWithFactory):
518 """Tests that need more of Launchpad to run."""
519
520- layer = TwistedLaunchpadZopelessLayer
521+ layer = LaunchpadZopelessLayer
522+ run_tests_with = AsynchronousDeferredRunTestForBrokenTwisted.make_factory(
523+ timeout=20)
524
525 def setUp(self):
526- super(TestSlaveWithLibrarian, self)
527- self.slave_helper = SlaveTestHelpers()
528- self.slave_helper.setUp()
529- self.addCleanup(self.slave_helper.cleanUp)
530- self.factory = LaunchpadObjectFactory()
531- login_as(ANONYMOUS)
532- self.addCleanup(logout)
533+ super(TestSlaveWithLibrarian, self).setUp()
534+ self.slave_helper = self.useFixture(SlaveTestHelpers())
535
536 def test_ensurepresent_librarian(self):
537 # ensurepresent, when given an http URL for a file will download the
538
539=== modified file 'lib/lp/buildmaster/tests/test_manager.py'
540--- lib/lp/buildmaster/tests/test_manager.py 2010-10-27 14:25:19 +0000
541+++ lib/lp/buildmaster/tests/test_manager.py 2010-11-24 19:57:36 +0000
542@@ -8,6 +8,11 @@
543 import time
544 import xmlrpclib
545
546+from testtools.deferredruntest import (
547+ assert_fails_with,
548+ AsynchronousDeferredRunTest,
549+ )
550+
551 import transaction
552
553 from twisted.internet import (
554@@ -19,7 +24,6 @@
555 deferLater,
556 )
557 from twisted.python.failure import Failure
558-from twisted.trial.unittest import TestCase as TrialTestCase
559 from zope.component import getUtility
560 from zope.security.proxy import removeSecurityProxy
561
562@@ -34,8 +38,7 @@
563 )
564 from canonical.testing.layers import (
565 LaunchpadScriptLayer,
566- TwistedLaunchpadZopelessLayer,
567- TwistedLayer,
568+ LaunchpadZopelessLayer,
569 ZopelessDatabaseLayer,
570 )
571 from lp.buildmaster.enums import BuildStatus
572@@ -52,47 +55,44 @@
573 from lp.buildmaster.tests.mock_slaves import (
574 BrokenSlave,
575 BuildingSlave,
576+ make_publisher,
577 OkSlave,
578 )
579 from lp.registry.interfaces.distribution import IDistributionSet
580 from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
581-from lp.testing import TestCaseWithFactory
582+from lp.testing import (
583+ TestCase,
584+ TestCaseWithFactory,
585+ )
586 from lp.testing.factory import LaunchpadObjectFactory
587 from lp.testing.fakemethod import FakeMethod
588 from lp.testing.sampledata import BOB_THE_BUILDER_NAME
589
590
591-class TestSlaveScannerScan(TrialTestCase):
592+class TestSlaveScannerScan(TestCase):
593 """Tests `SlaveScanner.scan` method.
594
595 This method uses the old framework for scanning and dispatching builds.
596 """
597- layer = TwistedLaunchpadZopelessLayer
598+ layer = LaunchpadZopelessLayer
599+ run_tests_with = AsynchronousDeferredRunTest.make_factory(timeout=20)
600
601 def setUp(self):
602- """Setup TwistedLayer, TrialTestCase and BuilddSlaveTest.
603+ """Set up BuilddSlaveTest.
604
605 Also adjust the sampledata in a way a build can be dispatched to
606 'bob' builder.
607 """
608- from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
609- TwistedLayer.testSetUp()
610- TrialTestCase.setUp(self)
611- self.slave = BuilddSlaveTestSetup()
612- self.slave.setUp()
613+ super(TestSlaveScannerScan, self).setUp()
614+ self.slave = self.useFixture(BuilddSlaveTestSetup())
615
616 # Creating the required chroots needed for dispatching.
617- test_publisher = SoyuzTestPublisher()
618+ test_publisher = make_publisher()
619 ubuntu = getUtility(IDistributionSet).getByName('ubuntu')
620 hoary = ubuntu.getSeries('hoary')
621 test_publisher.setUpDefaultDistroSeries(hoary)
622 test_publisher.addFakeChroots()
623
624- def tearDown(self):
625- self.slave.tearDown()
626- TrialTestCase.tearDown(self)
627- TwistedLayer.testTearDown()
628-
629 def _resetBuilder(self, builder):
630 """Reset the given builder and its job."""
631
632@@ -298,7 +298,7 @@
633 d = scanner.scan()
634 # Because the builder is not ok, we can't use _checkNoDispatch.
635 d.addCallback(
636- lambda ignored: self.assertIdentical(None, builder.currentjob))
637+ lambda ignored: self.assertIs(None, builder.currentjob))
638 return d
639
640 def test_scan_of_broken_slave(self):
641@@ -308,7 +308,7 @@
642 builder.failure_count = 0
643 scanner = self._getScanner(builder_name=builder.name)
644 d = scanner.scan()
645- return self.assertFailure(d, xmlrpclib.Fault)
646+ return assert_fails_with(d, xmlrpclib.Fault)
647
648 def _assertFailureCounting(self, builder_count, job_count,
649 expected_builder_count, expected_job_count):
650@@ -423,9 +423,9 @@
651 return d.addCallback(check)
652
653
654-class TestBuilddManager(TrialTestCase):
655+class TestBuilddManager(TestCase):
656
657- layer = TwistedLaunchpadZopelessLayer
658+ layer = LaunchpadZopelessLayer
659
660 def _stub_out_scheduleNextScanCycle(self):
661 # stub out the code that adds a callLater, so that later tests
662@@ -511,10 +511,10 @@
663 self.assertEqual("failnotes", self.builder.failnotes)
664
665
666-class TestNewBuilders(TrialTestCase):
667+class TestNewBuilders(TestCase):
668 """Test detecting of new builders."""
669
670- layer = TwistedLaunchpadZopelessLayer
671+ layer = LaunchpadZopelessLayer
672
673 def _getScanner(self, manager=None, clock=None):
674 return NewBuildersScanner(manager=manager, clock=clock)
675
676=== modified file 'lib/lp/code/model/tests/test_recipebuilder.py'
677--- lib/lp/code/model/tests/test_recipebuilder.py 2010-11-24 04:25:11 +0000
678+++ lib/lp/code/model/tests/test_recipebuilder.py 2010-11-24 19:57:36 +0000
679@@ -7,17 +7,20 @@
680
681 __metaclass__ = type
682
683+from testtools import run_test_with
684+from testtools.deferredruntest import (
685+ assert_fails_with,
686+ AsynchronousDeferredRunTest,
687+ )
688 import unittest
689
690 import transaction
691 from twisted.internet import defer
692-from twisted.trial.unittest import TestCase as TrialTestCase
693 from zope.security.proxy import removeSecurityProxy
694
695 from canonical.launchpad.scripts.logger import BufferLogger
696 from canonical.testing.layers import (
697 LaunchpadFunctionalLayer,
698- TwistedLaunchpadZopelessLayer,
699 )
700 from lp.buildmaster.enums import BuildFarmJobType
701 from lp.buildmaster.interfaces.builder import CannotBuild
702@@ -38,16 +41,14 @@
703 from lp.soyuz.model.processor import ProcessorFamilySet
704 from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
705 from lp.testing import (
706- ANONYMOUS,
707- login_as,
708- logout,
709 person_logged_in,
710 TestCaseWithFactory,
711 )
712-from lp.testing.factory import LaunchpadObjectFactory
713-
714-
715-class RecipeBuilderTestsMixin:
716+
717+
718+class TestRecipeBuilder(TestCaseWithFactory):
719+
720+ layer = LaunchpadFunctionalLayer
721
722 def makeJob(self, recipe_registrant=None, recipe_owner=None):
723 """Create a sample `ISourcePackageRecipeBuildJob`."""
724@@ -80,11 +81,6 @@
725 job = IBuildFarmJobBehavior(job)
726 return job
727
728-
729-class TestRecipeBuilder(TestCaseWithFactory, RecipeBuilderTestsMixin):
730-
731- layer = LaunchpadFunctionalLayer
732-
733 def test_providesInterface(self):
734 # RecipeBuildBehavior provides IBuildFarmJobBehavior.
735 recipe_builder = RecipeBuildBehavior(None)
736@@ -258,18 +254,7 @@
737 self.assertEquals(
738 job.build, SourcePackageRecipeBuild.getById(job.build.id))
739
740-
741-class TestDispatchBuildToSlave(TrialTestCase, RecipeBuilderTestsMixin):
742-
743- layer = TwistedLaunchpadZopelessLayer
744-
745- def setUp(self):
746- super(TestDispatchBuildToSlave, self).setUp()
747- self.factory = LaunchpadObjectFactory()
748- login_as(ANONYMOUS)
749- self.addCleanup(logout)
750- self.layer.switchDbUser('testadmin')
751-
752+ @run_test_with(AsynchronousDeferredRunTest)
753 def test_dispatchBuildToSlave(self):
754 # Ensure dispatchBuildToSlave will make the right calls to the slave
755 job = self.makeJob()
756@@ -304,6 +289,7 @@
757 build_args[4], job._extraBuildArgs(distroarchseries))
758 return d.addCallback(check_dispatch)
759
760+ @run_test_with(AsynchronousDeferredRunTest)
761 def test_dispatchBuildToSlave_nochroot(self):
762 # dispatchBuildToSlave will fail when there is not chroot tarball
763 # available for the distroseries to build for.
764@@ -314,7 +300,7 @@
765 job.setBuilder(builder)
766 logger = BufferLogger()
767 d = defer.maybeDeferred(job.dispatchBuildToSlave, "someid", logger)
768- return self.assertFailure(d, CannotBuild)
769+ return assert_fails_with(d, CannotBuild)
770
771
772 def test_suite():
773
774=== modified file 'lib/lp/codehosting/codeimport/tests/test_workermonitor.py'
775--- lib/lp/codehosting/codeimport/tests/test_workermonitor.py 2010-08-20 20:31:18 +0000
776+++ lib/lp/codehosting/codeimport/tests/test_workermonitor.py 2010-11-24 19:57:36 +0000
777@@ -1,4 +1,4 @@
778-# Copyright 2009 Canonical Ltd. This software is licensed under the
779+# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
780 # GNU Affero General Public License version 3 (see the file LICENSE).
781
782 """Tests for the CodeImportWorkerMonitor and related classes."""
783@@ -18,6 +18,11 @@
784 from bzrlib.branch import Branch
785 from bzrlib.tests import TestCase as BzrTestCase
786 import transaction
787+from testtools.deferredruntest import (
788+ assert_fails_with,
789+ AsynchronousDeferredRunTest,
790+ flush_logged_errors,
791+ )
792 from twisted.internet import (
793 defer,
794 error,
795@@ -25,7 +30,6 @@
796 reactor,
797 )
798 from twisted.python import log
799-from twisted.trial.unittest import TestCase as TrialTestCase
800 from twisted.web import xmlrpc
801 from zope.component import getUtility
802
803@@ -33,9 +37,8 @@
804 from canonical.launchpad.scripts.logger import QuietFakeLogger
805 from canonical.launchpad.xmlrpc.faults import NoSuchCodeImportJob
806 from canonical.testing.layers import (
807- TwistedAppServerLayer,
808- TwistedLaunchpadZopelessLayer,
809- TwistedLayer,
810+ LaunchpadZopelessLayer,
811+ ZopelessAppServerLayer,
812 )
813 from lp.code.enums import (
814 CodeImportResultStatus,
815@@ -71,6 +74,7 @@
816 makeFailure,
817 ProcessTestsMixin,
818 )
819+from lp.services.twistedsupport.xmlrpc import fix_bug_2518
820 from lp.testing import (
821 login,
822 logout,
823@@ -79,9 +83,10 @@
824 from lp.testing.factory import LaunchpadObjectFactory
825
826
827-class TestWorkerMonitorProtocol(ProcessTestsMixin, TrialTestCase):
828-
829- layer = TwistedLayer
830+fix_bug_2518()
831+
832+
833+class TestWorkerMonitorProtocol(ProcessTestsMixin, TestCase):
834
835 class StubWorkerMonitor:
836
837@@ -94,7 +99,7 @@
838 def setUp(self):
839 self.worker_monitor = self.StubWorkerMonitor()
840 self.log_file = StringIO.StringIO()
841- ProcessTestsMixin.setUp(self)
842+ super(TestWorkerMonitorProtocol, self).setUp()
843
844 def makeProtocol(self):
845 """See `ProcessTestsMixin.makeProtocol`."""
846@@ -195,7 +200,7 @@
847 raise self.no_such_job_exception
848
849
850-class TestWorkerMonitorUnit(TrialTestCase, TestCase):
851+class TestWorkerMonitorUnit(TestCase):
852 """Unit tests for most of the `CodeImportWorkerMonitor` class.
853
854 We have to pay attention to the fact that several of the methods of the
855@@ -204,10 +209,8 @@
856 they did.
857 """
858
859- layer = TwistedLaunchpadZopelessLayer
860-
861- # This works around a clash between the TrialTestCase and our TestCase.
862- skip = None
863+ layer = LaunchpadZopelessLayer
864+ run_tests_with = AsynchronousDeferredRunTest.make_factory(timeout=20)
865
866 class WorkerMonitor(CodeImportWorkerMonitor):
867 """A subclass of CodeImportWorkerMonitor that stubs logging OOPSes."""
868@@ -216,7 +219,7 @@
869 log.err(failure)
870
871 def assertOopsesLogged(self, exc_types):
872- failures = self.flushLoggedErrors()
873+ failures = flush_logged_errors()
874 self.assertEqual(len(exc_types), len(failures))
875 for fail, exc_type in zip(failures, exc_types):
876 self.assert_(fail.check(exc_type))
877@@ -262,7 +265,7 @@
878 # getWorkerArguments didn't find the supplied job, getWorkerArguments
879 # translates this to an 'ExitQuietly' exception.
880 worker_monitor = self.makeWorkerMonitorWithoutJob()
881- return self.assertFailure(
882+ return assert_fails_with(
883 worker_monitor.getWorkerArguments(), ExitQuietly)
884
885 def test_getWorkerArguments_endpoint_failure_raises(self):
886@@ -270,7 +273,7 @@
887 # handled in any special way by getWorkerArguments.
888 worker_monitor = self.makeWorkerMonitorWithoutJob(
889 exception=ZeroDivisionError())
890- return self.assertFailure(
891+ return assert_fails_with(
892 worker_monitor.getWorkerArguments(), ZeroDivisionError)
893
894 def test_getWorkerArguments_arbitrary_fault_raises(self):
895@@ -278,7 +281,7 @@
896 # handled in any special way by getWorkerArguments.
897 worker_monitor = self.makeWorkerMonitorWithoutJob(
898 exception=xmlrpc.Fault(1, ''))
899- return self.assertFailure(
900+ return assert_fails_with(
901 worker_monitor.getWorkerArguments(), xmlrpc.Fault)
902
903 def test_updateHeartbeat(self):
904@@ -341,7 +344,7 @@
905 self.assertEqual(
906 [('finishJobID', job_id, 'SUCCESS', '')],
907 worker_monitor.codeimport_endpoint.calls)
908- errors = self.flushLoggedErrors(ZeroDivisionError)
909+ errors = flush_logged_errors(ZeroDivisionError)
910 self.assertEqual(1, len(errors))
911 return worker_monitor.finishJob(
912 CodeImportResultStatus.SUCCESS).addCallback(
913@@ -431,10 +434,11 @@
914 def test_callFinishJobLogsTracebackOnFailure(self):
915 # When callFinishJob is called with a failure, it dumps the traceback
916 # of the failure into the log file.
917+ self.layer.force_dirty_database()
918 worker_monitor = self.makeWorkerMonitorWithJob()
919 ret = worker_monitor.callFinishJob(makeFailure(RuntimeError))
920 def check_log_file(ignored):
921- failures = self.flushLoggedErrors(RuntimeError)
922+ failures = flush_logged_errors(RuntimeError)
923 self.assertEqual(1, len(failures))
924 fail = failures[0]
925 traceback_file = StringIO.StringIO()
926@@ -455,14 +459,11 @@
927 self.assertEqual(calls, [])
928
929
930-class TestWorkerMonitorRunNoProcess(TrialTestCase, BzrTestCase):
931+class TestWorkerMonitorRunNoProcess(BzrTestCase):
932 """Tests for `CodeImportWorkerMonitor.run` that don't launch a subprocess.
933 """
934
935- # This works around a clash between the TrialTestCase and the BzrTestCase.
936- skip = None
937-
938- layer = TwistedLayer
939+ run_tests_with = AsynchronousDeferredRunTest
940
941 class WorkerMonitor(CodeImportWorkerMonitor):
942 """See `CodeImportWorkerMonitor`.
943@@ -574,12 +575,10 @@
944 return protocol
945
946
947-class TestWorkerMonitorIntegration(TrialTestCase, BzrTestCase):
948-
949- layer = TwistedAppServerLayer
950-
951- # This works around a clash between the TrialTestCase and the BzrTestCase.
952- skip = None
953+class TestWorkerMonitorIntegration(BzrTestCase):
954+
955+ layer = ZopelessAppServerLayer
956+ run_tests_with = AsynchronousDeferredRunTest.make_factory(timeout=20)
957
958 def setUp(self):
959 BzrTestCase.setUp(self)
960
961=== modified file 'lib/lp/codehosting/puller/tests/test_scheduler.py'
962--- lib/lp/codehosting/puller/tests/test_scheduler.py 2010-08-20 20:31:18 +0000
963+++ lib/lp/codehosting/puller/tests/test_scheduler.py 2010-11-24 19:57:36 +0000
964@@ -1,4 +1,4 @@
965-# Copyright 2009 Canonical Ltd. This software is licensed under the
966+# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
967 # GNU Affero General Public License version 3 (see the file LICENSE).
968
969 # pylint: disable-msg=W0222,W0231
970@@ -18,6 +18,11 @@
971 )
972 from bzrlib.urlutils import join as urljoin
973 import pytz
974+from testtools.deferredruntest import (
975+ assert_fails_with,
976+ AsynchronousDeferredRunTest,
977+ flush_logged_errors,
978+ )
979 from twisted.internet import (
980 defer,
981 error,
982@@ -25,15 +30,13 @@
983 )
984 from twisted.protocols.basic import NetstringParseError
985 from twisted.python import failure
986-from twisted.trial.unittest import TestCase as TrialTestCase
987 from zope.component import getUtility
988
989 from canonical.config import config
990 from canonical.launchpad.webapp import errorlog
991 from canonical.testing import (
992 reset_logging,
993- TwistedAppServerLayer,
994- TwistedLayer,
995+ ZopelessAppServerLayer,
996 )
997 from lp.code.enums import BranchType
998 from lp.code.interfaces.branchlookup import IBranchLookup
999@@ -49,7 +52,7 @@
1000 ProcessTestsMixin,
1001 suppress_stderr,
1002 )
1003-from lp.testing.factory import ObjectFactory
1004+from lp.testing import TestCase
1005
1006
1007 class FakeCodehostingEndpointProxy:
1008@@ -73,15 +76,17 @@
1009 return defer.succeed(0)
1010
1011
1012-class TestJobScheduler(TrialTestCase):
1013+class TestJobScheduler(TestCase):
1014
1015 def setUp(self):
1016+ super(TestJobScheduler, self).setUp()
1017 self.masterlock = 'master.lock'
1018
1019 def tearDown(self):
1020 reset_logging()
1021 if os.path.exists(self.masterlock):
1022 os.unlink(self.masterlock)
1023+ super(TestJobScheduler, self).tearDown()
1024
1025 def makeJobScheduler(self, branch_type_names=()):
1026 return scheduler.JobScheduler(
1027@@ -113,14 +118,14 @@
1028 manager.codehosting_endpoint.calls)
1029
1030
1031-class TestPullerWireProtocol(TrialTestCase):
1032+class TestPullerWireProtocol(TestCase):
1033 """Tests for the `PullerWireProtocol`.
1034
1035 Some of the docstrings and comments in this class refer to state numbers
1036 -- see the docstring of `PullerWireProtocol` for what these mean.
1037 """
1038
1039- layer = TwistedLayer
1040+ run_tests_with = AsynchronousDeferredRunTest
1041
1042 class StubTransport:
1043 def loseConnection(self):
1044@@ -142,6 +147,7 @@
1045 self.failure = failure
1046
1047 def setUp(self):
1048+ super(TestPullerWireProtocol, self).setUp()
1049 self.puller_protocol = self.StubPullerProtocol()
1050 self.protocol = scheduler.PullerWireProtocol(self.puller_protocol)
1051 self.protocol.makeConnection(self.StubTransport())
1052@@ -218,11 +224,10 @@
1053 self.assertUnexpectedErrorCalled(NetstringParseError)
1054
1055
1056-class TestPullerMonitorProtocol(
1057- ProcessTestsMixin, TrialTestCase):
1058+class TestPullerMonitorProtocol(ProcessTestsMixin, TestCase):
1059 """Tests for the process protocol used by the job manager."""
1060
1061- layer = TwistedLayer
1062+ run_tests_with = AsynchronousDeferredRunTest
1063
1064 class StubPullerListener:
1065 """Stub listener object that records calls."""
1066@@ -251,7 +256,8 @@
1067
1068 def setUp(self):
1069 self.listener = self.StubPullerListener()
1070- ProcessTestsMixin.setUp(self)
1071+ super(TestPullerMonitorProtocol, self).setUp()
1072+ TestCase.setUp(self)
1073
1074 def assertProtocolSuccess(self):
1075 """Assert that the protocol saw no unexpected errors."""
1076@@ -319,7 +325,7 @@
1077 self.clock.advance(config.supermirror.worker_timeout - 1)
1078 self.protocol.do_branchChanged('', '', '', '', '', '')
1079 self.clock.advance(2)
1080- return self.assertFailure(
1081+ return assert_fails_with(
1082 self.termination_deferred, error.TimeoutError)
1083
1084 def test_mirrorFailedDoesNotResetTimeout(self):
1085@@ -332,7 +338,7 @@
1086 self.clock.advance(config.supermirror.worker_timeout - 1)
1087 self.protocol.do_mirrorFailed('error message', 'OOPS')
1088 self.clock.advance(2)
1089- return self.assertFailure(
1090+ return assert_fails_with(
1091 self.termination_deferred, error.TimeoutError)
1092
1093 def test_terminatesWithError(self):
1094@@ -348,7 +354,7 @@
1095 self.protocol.errReceived('error message')
1096 self.simulateProcessExit(clean=False)
1097
1098- return self.assertFailure(
1099+ return assert_fails_with(
1100 self.termination_deferred, error.ProcessTerminated)
1101
1102 def test_stderrFailsProcess(self):
1103@@ -377,7 +383,7 @@
1104 # have for the worker's death.
1105 self.protocol.do_startMirroring()
1106 self.simulateProcessExit(clean=False)
1107- return self.assertFailure(
1108+ return assert_fails_with(
1109 self.termination_deferred, error.ProcessTerminated)
1110
1111 def test_errorBeforeStatusReport(self):
1112@@ -389,7 +395,7 @@
1113 self.assertEqual(
1114 self.listener.calls,
1115 ['startMirroring', ('mirrorFailed', 'traceback', None)])
1116- return self.assertFailure(
1117+ return assert_fails_with(
1118 self.termination_deferred, error.ProcessTerminated)
1119
1120 @suppress_stderr
1121@@ -410,23 +416,23 @@
1122 self.protocol.errReceived('traceback')
1123 self.simulateProcessExit(clean=False)
1124 self.assertEqual(
1125- self.flushLoggedErrors(RuntimeError), [runtime_error_failure])
1126- return self.assertFailure(
1127+ flush_logged_errors(RuntimeError), [runtime_error_failure])
1128+ return assert_fails_with(
1129 self.termination_deferred, error.ProcessTerminated)
1130
1131
1132-class TestPullerMaster(TrialTestCase):
1133+class TestPullerMaster(TestCase):
1134
1135- layer = TwistedLayer
1136+ run_tests_with = AsynchronousDeferredRunTest
1137
1138 def setUp(self):
1139+ super(TestPullerMaster, self).setUp()
1140 self.status_client = FakeCodehostingEndpointProxy()
1141 self.arbitrary_branch_id = 1
1142 self.eventHandler = scheduler.PullerMaster(
1143 self.arbitrary_branch_id, 'arbitrary-source', 'arbitrary-dest',
1144 BranchType.HOSTED, None, logging.getLogger(), self.status_client,
1145 set(['oops-prefix']))
1146- self.factory = ObjectFactory()
1147
1148 def test_unexpectedError(self):
1149 """The puller master logs an OOPS when it receives an unexpected
1150@@ -492,22 +498,18 @@
1151 return deferred.addCallback(checkMirrorFailed)
1152
1153
1154-class TestPullerMasterSpawning(TrialTestCase):
1155+class TestPullerMasterSpawning(TestCase):
1156
1157- layer = TwistedLayer
1158+ run_tests_with = AsynchronousDeferredRunTest
1159
1160 def setUp(self):
1161- self.factory = ObjectFactory()
1162+ super(TestPullerMasterSpawning, self).setUp()
1163 self.available_oops_prefixes = set(['foo'])
1164 self.eventHandler = self.makePullerMaster(
1165 'HOSTED', oops_prefixes=self.available_oops_prefixes)
1166- self._realSpawnProcess = reactor.spawnProcess
1167- reactor.spawnProcess = self.spawnProcess
1168+ self.patch(reactor, 'spawnProcess', self.spawnProcess)
1169 self.commands_spawned = []
1170
1171- def tearDown(self):
1172- reactor.spawnProcess = self._realSpawnProcess
1173-
1174 def makePullerMaster(self, branch_type_name, default_stacked_on_url=None,
1175 oops_prefixes=None):
1176 if default_stacked_on_url is None:
1177@@ -614,19 +616,14 @@
1178 """
1179
1180
1181-class TestPullerMasterIntegration(TrialTestCase, PullerBranchTestCase):
1182+class TestPullerMasterIntegration(PullerBranchTestCase):
1183 """Tests for the puller master that launch sub-processes."""
1184
1185- layer = TwistedAppServerLayer
1186-
1187- # XXX: Hacky workaround for Trial. It interprets the skip method as a
1188- # reason to skip the tests, but the default test result object doesn't
1189- # support skipping, hence errors.
1190- skip = None
1191+ layer = ZopelessAppServerLayer
1192+ run_tests_with = AsynchronousDeferredRunTest.make_factory(timeout=10)
1193
1194 def setUp(self):
1195- TrialTestCase.setUp(self)
1196- PullerBranchTestCase.setUp(self)
1197+ super(TestPullerMasterIntegration, self).setUp()
1198 self.makeCleanDirectory(config.codehosting.mirrored_branches_root)
1199 self.bzr_tree = self.make_branch_and_tree('src-branch')
1200 url = urljoin(self.serveOverHTTP(), 'src-branch')
1201@@ -637,10 +634,6 @@
1202 self.db_branch = getUtility(IBranchLookup).get(branch_id)
1203 self.client = FakeCodehostingEndpointProxy()
1204
1205- def run(self, result):
1206- # We want to use Trial's run() method so we can return Deferreds.
1207- return TrialTestCase.run(self, result)
1208-
1209 def _dumpError(self, failure):
1210 # XXX: JonathanLange 2007-10-17: It would be nice if we didn't have to
1211 # do this manually, and instead the test automatically gave us the
1212
1213=== modified file 'lib/lp/codehosting/sshserver/tests/test_daemon.py'
1214--- lib/lp/codehosting/sshserver/tests/test_daemon.py 2010-08-20 20:31:18 +0000
1215+++ lib/lp/codehosting/sshserver/tests/test_daemon.py 2010-11-24 19:57:36 +0000
1216@@ -5,14 +5,10 @@
1217
1218 __metaclass__ = type
1219
1220-import unittest
1221-
1222 from twisted.conch.ssh.common import NS
1223 from twisted.conch.ssh.keys import Key
1224 from twisted.test.proto_helpers import StringTransport
1225-from twisted.trial.unittest import TestCase as TrialTestCase
1226
1227-from canonical.testing.layers import TwistedLayer
1228 from lp.codehosting.sshserver.daemon import (
1229 get_key_path,
1230 get_portal,
1231@@ -21,6 +17,7 @@
1232 )
1233 from lp.services.sshserver.auth import SSHUserAuthServer
1234 from lp.services.sshserver.service import Factory
1235+from lp.testing import TestCase
1236
1237
1238 class StringTransportWith_setTcpKeepAlive(StringTransport):
1239@@ -32,11 +29,9 @@
1240 self._keepAlive = flag
1241
1242
1243-class TestFactory(TrialTestCase):
1244+class TestFactory(TestCase):
1245 """Tests for our SSH factory."""
1246
1247- layer = TwistedLayer
1248-
1249 def makeFactory(self):
1250 """Create and start the factory that our SSH server uses."""
1251 factory = Factory(
1252@@ -89,8 +84,4 @@
1253 mind1 = server_transport1.service.getMind()
1254 mind2 = server_transport2.service.getMind()
1255
1256- self.assertNotIdentical(mind1.cache, mind2.cache)
1257-
1258-
1259-def test_suite():
1260- return unittest.TestLoader().loadTestsFromName(__name__)
1261+ self.assertIsNot(mind1.cache, mind2.cache)
1262
1263=== modified file 'lib/lp/codehosting/sshserver/tests/test_session.py'
1264--- lib/lp/codehosting/sshserver/tests/test_session.py 2010-10-06 20:42:14 +0000
1265+++ lib/lp/codehosting/sshserver/tests/test_session.py 2010-11-24 19:57:36 +0000
1266@@ -1,4 +1,4 @@
1267-# Copyright 2009 Canonical Ltd. This software is licensed under the
1268+# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
1269 # GNU Affero General Public License version 3 (see the file LICENSE).
1270
1271 """Tests for SSH session support on the codehosting SSH server."""
1272@@ -6,7 +6,6 @@
1273 __metaclass__ = type
1274
1275 import socket
1276-import unittest
1277
1278 from twisted.conch.interfaces import ISession
1279 from twisted.conch.ssh import connection
1280@@ -116,7 +115,7 @@
1281 # Note: The dataReceived code calls 'log.err' which ends up getting
1282 # printed during the test run. How do I suppress that or even
1283 # better, check that it does so?
1284- # self.flushLoggedErrors() doesn't seem to do anything.
1285+ # flush_logged_errors() doesn't seem to do anything.
1286 self.exiter.dataReceived('bogus\n')
1287 self.assertEqual([('childConnectionLost', 'exit', 'invalid data'),
1288 ('processEnded', (255 << 8))], self.proc.log)
1289@@ -250,8 +249,8 @@
1290 self.failUnless(isinstance(session, ExecOnlySession),
1291 "ISession(avatar) doesn't adapt to ExecOnlySession. "
1292 "Got %r instead." % (session,))
1293- self.assertIdentical(self.avatar, session.avatar)
1294- self.assertIdentical(reactor, session.reactor)
1295+ self.assertIs(self.avatar, session.avatar)
1296+ self.assertIs(reactor, session.reactor)
1297
1298 def test_environment(self):
1299 # The environment for the executed process can be specified in the
1300@@ -344,8 +343,8 @@
1301 isinstance(session, RestrictedExecOnlySession),
1302 "ISession(avatar) doesn't adapt to RestrictedExecOnlySession. "
1303 "Got %r instead." % (session,))
1304- self.assertIdentical(self.avatar, session.avatar)
1305- self.assertIdentical(reactor, session.reactor)
1306+ self.assertIs(self.avatar, session.avatar)
1307+ self.assertIs(reactor, session.reactor)
1308 self.assertEqual('foo', session.allowed_command)
1309 self.assertEqual('bar baz', session.executed_command_template)
1310
1311@@ -412,7 +411,3 @@
1312 ['bzr', 'lp-serve',
1313 '--inet', str(self.avatar.user_id)],
1314 list(arguments))
1315-
1316-
1317-def test_suite():
1318- return unittest.TestLoader().loadTestsFromName(__name__)
1319
1320=== modified file 'lib/lp/codehosting/tests/helpers.py'
1321--- lib/lp/codehosting/tests/helpers.py 2010-10-04 19:50:45 +0000
1322+++ lib/lp/codehosting/tests/helpers.py 2010-11-24 19:57:36 +0000
1323@@ -1,4 +1,4 @@
1324-# Copyright 2009 Canonical Ltd. This software is licensed under the
1325+# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
1326 # GNU Affero General Public License version 3 (see the file LICENSE).
1327
1328 """Common helpers for codehosting tests."""
1329@@ -26,27 +26,32 @@
1330 TestNotApplicable,
1331 TestSkipped,
1332 )
1333+
1334+from testtools.deferredruntest import (
1335+ AsynchronousDeferredRunTest,
1336+ )
1337+
1338 from twisted.internet import (
1339 defer,
1340 threads,
1341 )
1342 from twisted.python.util import mergeFunctionMetadata
1343-from twisted.trial.unittest import TestCase as TrialTestCase
1344
1345 from canonical.config import config
1346-from canonical.testing.layers import TwistedLayer
1347 from lp.code.enums import BranchType
1348 from lp.codehosting.vfs import branch_id_to_path
1349-
1350-
1351-class AvatarTestCase(TrialTestCase):
1352+from lp.testing import TestCase
1353+
1354+
1355+class AvatarTestCase(TestCase):
1356 """Base class for tests that need a LaunchpadAvatar with some basic sample
1357 data.
1358 """
1359
1360- layer = TwistedLayer
1361+ run_tests_with = AsynchronousDeferredRunTest
1362
1363 def setUp(self):
1364+ super(AvatarTestCase, self).setUp()
1365 # A basic user dict, 'alice' is a member of no teams (aside from the
1366 # user themself).
1367 self.aliceUserDict = {
1368
1369=== modified file 'lib/lp/codehosting/tests/test_sftp.py'
1370--- lib/lp/codehosting/tests/test_sftp.py 2010-10-26 15:47:24 +0000
1371+++ lib/lp/codehosting/tests/test_sftp.py 2010-11-24 19:57:36 +0000
1372@@ -1,11 +1,10 @@
1373-# Copyright 2009 Canonical Ltd. This software is licensed under the
1374+# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
1375 # GNU Affero General Public License version 3 (see the file LICENSE).
1376
1377 """Tests for the transport-backed SFTP server implementation."""
1378
1379 from contextlib import closing
1380 import os
1381-import unittest
1382
1383 from bzrlib import (
1384 errors as bzr_errors,
1385@@ -14,15 +13,19 @@
1386 from bzrlib.tests import TestCaseInTempDir
1387 from bzrlib.transport import get_transport
1388 from bzrlib.transport.memory import MemoryTransport
1389+
1390+from testtools.deferredruntest import (
1391+ assert_fails_with,
1392+ AsynchronousDeferredRunTest,
1393+ )
1394+
1395 from twisted.conch.interfaces import ISFTPServer
1396 from twisted.conch.ls import lsLine
1397 from twisted.conch.ssh import filetransfer
1398 from twisted.internet import defer
1399 from twisted.python import failure
1400 from twisted.python.util import mergeFunctionMetadata
1401-from twisted.trial.unittest import TestCase as TrialTestCase
1402
1403-from canonical.testing.layers import TwistedLayer
1404 from lp.codehosting.inmemory import (
1405 InMemoryFrontend,
1406 XMLRPCWrapper,
1407@@ -33,6 +36,7 @@
1408 )
1409 from lp.codehosting.sshserver.daemon import CodehostingAvatar
1410 from lp.services.sshserver.sftp import FileIsADirectory
1411+from lp.testing import TestCase
1412 from lp.testing.factory import LaunchpadObjectFactory
1413
1414
1415@@ -105,12 +109,12 @@
1416 self.assertIsInstance(transport, FatLocalTransport)
1417
1418
1419-class TestSFTPAdapter(TrialTestCase):
1420+class TestSFTPAdapter(TestCase):
1421
1422- layer = TwistedLayer
1423+ run_tests_with = AsynchronousDeferredRunTest
1424
1425 def setUp(self):
1426- TrialTestCase.setUp(self)
1427+ TestCase.setUp(self)
1428 frontend = InMemoryFrontend()
1429 self.factory = frontend.getLaunchpadObjectFactory()
1430 self.codehosting_endpoint = XMLRPCWrapper(
1431@@ -162,16 +166,15 @@
1432 return self._factory.getUniqueString('%41%42%43-')
1433
1434
1435-class TestSFTPFile(TrialTestCase, TestCaseInTempDir, SFTPTestMixin):
1436+class TestSFTPFile(TestCaseInTempDir, SFTPTestMixin):
1437 """Tests for `TransportSFTPServer` and `TransportSFTPFile`."""
1438
1439- layer = TwistedLayer
1440+ run_tests_with = AsynchronousDeferredRunTest
1441
1442 # This works around a clash between the TrialTestCase and the BzrTestCase.
1443 skip = None
1444
1445 def setUp(self):
1446- TrialTestCase.setUp(self)
1447 TestCaseInTempDir.setUp(self)
1448 SFTPTestMixin.setUp(self)
1449 transport = AsyncTransport(
1450@@ -181,7 +184,7 @@
1451 def assertSFTPError(self, sftp_code, function, *args, **kwargs):
1452 """Assert that calling functions fails with `sftp_code`."""
1453 deferred = defer.maybeDeferred(function, *args, **kwargs)
1454- deferred = self.assertFailure(deferred, filetransfer.SFTPError)
1455+ deferred = assert_fails_with(deferred, filetransfer.SFTPError)
1456 def check_sftp_code(exception):
1457 self.assertEqual(sftp_code, exception.code)
1458 return exception
1459@@ -356,7 +359,7 @@
1460 os.mkdir(directory)
1461 deferred = self.openFile(directory, filetransfer.FXF_WRITE, {})
1462 deferred.addCallback(lambda handle: handle.writeChunk(0, 'bar'))
1463- return self.assertFailure(deferred, filetransfer.SFTPError)
1464+ return assert_fails_with(deferred, filetransfer.SFTPError)
1465
1466 def test_readChunk(self):
1467 # readChunk reads a chunk of data from the file.
1468@@ -389,7 +392,7 @@
1469 filename = self.getPathSegment()
1470 deferred = self.openFile(filename, 0, {})
1471 deferred.addCallback(lambda handle: handle.readChunk(1, 2))
1472- return self.assertFailure(deferred, filetransfer.SFTPError)
1473+ return assert_fails_with(deferred, filetransfer.SFTPError)
1474
1475 def test_setAttrs(self):
1476 # setAttrs on TransportSFTPFile does nothing.
1477@@ -414,19 +417,15 @@
1478 filename = self.getPathSegment()
1479 deferred = self.openFile(filename, 0, {})
1480 deferred.addCallback(lambda handle: handle.getAttrs())
1481- return self.assertFailure(deferred, filetransfer.SFTPError)
1482-
1483-
1484-class TestSFTPServer(TrialTestCase, TestCaseInTempDir, SFTPTestMixin):
1485+ return assert_fails_with(deferred, filetransfer.SFTPError)
1486+
1487+
1488+class TestSFTPServer(TestCaseInTempDir, SFTPTestMixin):
1489 """Tests for `TransportSFTPServer` and `TransportSFTPFile`."""
1490
1491- layer = TwistedLayer
1492-
1493- # This works around a clash between the TrialTestCase and the BzrTestCase.
1494- skip = None
1495+ run_tests_with = AsynchronousDeferredRunTest
1496
1497 def setUp(self):
1498- TrialTestCase.setUp(self)
1499 TestCaseInTempDir.setUp(self)
1500 SFTPTestMixin.setUp(self)
1501 transport = AsyncTransport(
1502@@ -453,7 +452,7 @@
1503 # SFTPErrors.
1504 nonexistent_file = self.getPathSegment()
1505 deferred = self.sftp_server.getAttrs(nonexistent_file, False)
1506- return self.assertFailure(deferred, filetransfer.SFTPError)
1507+ return assert_fails_with(deferred, filetransfer.SFTPError)
1508
1509 def test_removeFile(self):
1510 # removeFile removes the file.
1511@@ -468,14 +467,14 @@
1512 # Errors in removeFile are translated into SFTPErrors.
1513 filename = self.getPathSegment()
1514 deferred = self.sftp_server.removeFile(filename)
1515- return self.assertFailure(deferred, filetransfer.SFTPError)
1516+ return assert_fails_with(deferred, filetransfer.SFTPError)
1517
1518 def test_removeFile_directory(self):
1519 # Errors in removeFile are translated into SFTPErrors.
1520 filename = self.getPathSegment()
1521 self.build_tree_contents([(filename+'/',)])
1522 deferred = self.sftp_server.removeFile(filename)
1523- return self.assertFailure(deferred, filetransfer.SFTPError)
1524+ return assert_fails_with(deferred, filetransfer.SFTPError)
1525
1526 def test_renameFile(self):
1527 # renameFile renames the file.
1528@@ -493,7 +492,7 @@
1529 orig_filename = self.getPathSegment()
1530 new_filename = self.getPathSegment()
1531 deferred = self.sftp_server.renameFile(orig_filename, new_filename)
1532- return self.assertFailure(deferred, filetransfer.SFTPError)
1533+ return assert_fails_with(deferred, filetransfer.SFTPError)
1534
1535 def test_makeDirectory(self):
1536 # makeDirectory makes the directory.
1537@@ -512,7 +511,7 @@
1538 nonexistent_child = '%s/%s' % (nonexistent, self.getPathSegment())
1539 deferred = self.sftp_server.makeDirectory(
1540 nonexistent_child, {'permissions': 0777})
1541- return self.assertFailure(deferred, filetransfer.SFTPError)
1542+ return assert_fails_with(deferred, filetransfer.SFTPError)
1543
1544 def test_removeDirectory(self):
1545 # removeDirectory removes the directory.
1546@@ -527,7 +526,7 @@
1547 # Errors in removeDirectory are translated into SFTPErrors.
1548 directory = self.getPathSegment()
1549 deferred = self.sftp_server.removeDirectory(directory)
1550- return self.assertFailure(deferred, filetransfer.SFTPError)
1551+ return assert_fails_with(deferred, filetransfer.SFTPError)
1552
1553 def test_gotVersion(self):
1554 # gotVersion returns an empty dictionary.
1555@@ -592,7 +591,7 @@
1556 # Errors in openDirectory are translated into SFTPErrors.
1557 nonexistent = self.getPathSegment()
1558 deferred = self.sftp_server.openDirectory(nonexistent)
1559- return self.assertFailure(deferred, filetransfer.SFTPError)
1560+ return assert_fails_with(deferred, filetransfer.SFTPError)
1561
1562 def test_openDirectoryMemory(self):
1563 """openDirectory works on MemoryTransport."""
1564@@ -669,7 +668,3 @@
1565 self.sftp_server.translateError,
1566 failure.Failure(exception), 'methodName')
1567 self.assertIs(result, exception)
1568-
1569-
1570-def test_suite():
1571- return unittest.TestLoader().loadTestsFromName(__name__)
1572
1573=== modified file 'lib/lp/codehosting/vfs/tests/test_branchfs.py'
1574--- lib/lp/codehosting/vfs/tests/test_branchfs.py 2010-10-04 19:50:45 +0000
1575+++ lib/lp/codehosting/vfs/tests/test_branchfs.py 2010-11-24 19:57:36 +0000
1576@@ -1,4 +1,4 @@
1577-# Copyright 2009 Canonical Ltd. This software is licensed under the
1578+# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
1579 # GNU Affero General Public License version 3 (see the file LICENSE).
1580
1581 # pylint: disable-msg=W0231
1582@@ -8,7 +8,6 @@
1583 __metaclass__ = type
1584
1585 import os
1586-import unittest
1587
1588 from bzrlib import errors
1589 from bzrlib.bzrdir import (
1590@@ -36,11 +35,15 @@
1591 escape,
1592 local_path_to_url,
1593 )
1594+
1595+from testtools.deferredruntest import (
1596+ assert_fails_with,
1597+ AsynchronousDeferredRunTest,
1598+ )
1599+
1600 from twisted.internet import defer
1601-from twisted.trial.unittest import TestCase as TrialTestCase
1602
1603 from canonical.testing.layers import (
1604- TwistedLayer,
1605 ZopelessDatabaseLayer,
1606 )
1607 from lp.code.enums import BranchType
1608@@ -187,7 +190,7 @@
1609 self.assertEqual([(1, True)], log)
1610
1611
1612-class TestBranchIDToPath(unittest.TestCase):
1613+class TestBranchIDToPath(TestCase):
1614 """Tests for branch_id_to_path."""
1615
1616 def test_branch_id_to_path(self):
1617@@ -205,8 +208,6 @@
1618 class MixinBaseLaunchpadServerTests:
1619 """Common tests for _BaseLaunchpadServer subclasses."""
1620
1621- layer = TwistedLayer
1622-
1623 def setUp(self):
1624 frontend = InMemoryFrontend()
1625 self.codehosting_api = frontend.getCodehostingEndpoint()
1626@@ -236,11 +237,9 @@
1627 self.server.get_url() in _get_protocol_handlers().keys())
1628
1629
1630-class TestLaunchpadServer(MixinBaseLaunchpadServerTests, TrialTestCase,
1631- BzrTestCase):
1632+class TestLaunchpadServer(MixinBaseLaunchpadServerTests, BzrTestCase):
1633
1634- # This works around a clash between the TrialTestCase and the BzrTestCase.
1635- skip = None
1636+ run_tests_with = AsynchronousDeferredRunTest
1637
1638 def setUp(self):
1639 BzrTestCase.setUp(self)
1640@@ -300,7 +299,7 @@
1641 # for, say, a product that doesn't exist.
1642 branch_url = '/~%s/no-such-product/new-branch' % (self.requester.name)
1643 deferred = self.server.createBranch(branch_url)
1644- deferred = self.assertFailure(deferred, errors.PermissionDenied)
1645+ deferred = assert_fails_with(deferred, errors.PermissionDenied)
1646 def check_exception(exception):
1647 self.assertEqual(branch_url, exception.path)
1648 self.assertEqual(
1649@@ -363,12 +362,11 @@
1650
1651
1652 class TestLaunchpadInternalServer(MixinBaseLaunchpadServerTests,
1653- TrialTestCase, BzrTestCase,
1654+ BzrTestCase,
1655 LaunchpadInternalServerTests):
1656 """Tests for `LaunchpadInternalServer`, used by the puller and scanner."""
1657
1658- # This works around a clash between the TrialTestCase and the BzrTestCase.
1659- skip = None
1660+ run_tests_with = AsynchronousDeferredRunTest
1661
1662 def setUp(self):
1663 BzrTestCase.setUp(self)
1664@@ -380,14 +378,13 @@
1665 'lp-test:///', XMLRPCWrapper(codehosting_api), MemoryTransport())
1666
1667
1668-class TestDirectDatabaseLaunchpadServer(TestCaseWithFactory, TrialTestCase,
1669+class TestDirectDatabaseLaunchpadServer(TestCaseWithFactory,
1670 LaunchpadInternalServerTests):
1671 """Tests for `DirectDatabaseLaunchpadServer`."""
1672
1673 layer = ZopelessDatabaseLayer
1674
1675- # This works around a clash between the TrialTestCase and the BzrTestCase.
1676- skip = None
1677+ run_tests_with = AsynchronousDeferredRunTest
1678
1679 def setUp(self):
1680 super(TestDirectDatabaseLaunchpadServer, self).setUp()
1681@@ -397,13 +394,10 @@
1682
1683
1684
1685-class TestAsyncVirtualTransport(TrialTestCase, TestCaseInTempDir):
1686+class TestAsyncVirtualTransport(TestCaseInTempDir):
1687 """Tests for `AsyncVirtualTransport`."""
1688
1689- layer = TwistedLayer
1690-
1691- # This works around a clash between the TrialTestCase and the BzrTestCase.
1692- skip = None
1693+ run_tests_with = AsynchronousDeferredRunTest
1694
1695 class VirtualServer(Server):
1696 """Very simple server that provides a AsyncVirtualTransport."""
1697@@ -499,9 +493,6 @@
1698 `_ensureDeferred`. See these methods for more information.
1699 """
1700
1701- # See comment on TestLaunchpadServer.
1702- layer = TwistedLayer
1703-
1704 def setUp(self):
1705 frontend = InMemoryFrontend()
1706 self.factory = frontend.getLaunchpadObjectFactory()
1707@@ -522,7 +513,7 @@
1708
1709 :return: A `Deferred`. You must return this from your test.
1710 """
1711- return self.assertFailure(
1712+ return assert_fails_with(
1713 self._ensureDeferred(function, *args, **kwargs), exception)
1714
1715 def assertFiresFailureWithSubstring(self, exc_type, msg, function,
1716@@ -799,10 +790,9 @@
1717 transport.rmdir, '~testuser/firefox/baz')
1718
1719
1720-class TestLaunchpadTransportSync(LaunchpadTransportTests, TrialTestCase):
1721+class TestLaunchpadTransportSync(LaunchpadTransportTests, TestCase):
1722
1723- # This works around a clash between the TrialTestCase and the BzrTestCase.
1724- skip = None
1725+ run_tests_with = AsynchronousDeferredRunTest
1726
1727 def _ensureDeferred(self, function, *args, **kwargs):
1728 def call_function_and_check_not_deferred():
1729@@ -814,21 +804,20 @@
1730 return defer.maybeDeferred(call_function_and_check_not_deferred)
1731
1732 def setUp(self):
1733- TrialTestCase.setUp(self)
1734+ TestCase.setUp(self)
1735 LaunchpadTransportTests.setUp(self)
1736
1737 def getTransport(self):
1738 return get_transport(self.server.get_url())
1739
1740 def test_ensureDeferredFailsWhenDeferredReturned(self):
1741- return self.assertFailure(
1742+ return assert_fails_with(
1743 self._ensureDeferred(defer.succeed, None), AssertionError)
1744
1745
1746-class TestLaunchpadTransportAsync(LaunchpadTransportTests, TrialTestCase):
1747+class TestLaunchpadTransportAsync(LaunchpadTransportTests, TestCase):
1748
1749- # This works around a clash between the TrialTestCase and the BzrTestCase.
1750- skip = None
1751+ run_tests_with = AsynchronousDeferredRunTest
1752
1753 def _ensureDeferred(self, function, *args, **kwargs):
1754 deferred = function(*args, **kwargs)
1755@@ -836,7 +825,7 @@
1756 return deferred
1757
1758 def setUp(self):
1759- TrialTestCase.setUp(self)
1760+ TestCase.setUp(self)
1761 LaunchpadTransportTests.setUp(self)
1762
1763 def getTransport(self):
1764@@ -1015,14 +1004,10 @@
1765 self.assertFormatStringsPassed(branch)
1766
1767
1768-class TestLaunchpadTransportReadOnly(TrialTestCase, BzrTestCase):
1769+class TestLaunchpadTransportReadOnly(BzrTestCase):
1770 """Tests for read-only operations on the LaunchpadTransport."""
1771
1772- # See comment on TestLaunchpadServer.
1773- layer = TwistedLayer
1774-
1775- # This works around a clash between the TrialTestCase and the BzrTestCase.
1776- skip = None
1777+ run_tests_with = AsynchronousDeferredRunTest
1778
1779 def setUp(self):
1780 BzrTestCase.setUp(self)
1781@@ -1087,8 +1072,3 @@
1782 lp_server = get_lp_server(1, 'http://xmlrpc.example.invalid', '')
1783 transport = lp_server._transport_dispatch._rw_dispatch.base_transport
1784 self.assertIsInstance(transport, ChrootTransport)
1785-
1786-
1787-def test_suite():
1788- return unittest.TestLoader().loadTestsFromName(__name__)
1789-
1790
1791=== modified file 'lib/lp/codehosting/vfs/tests/test_branchfsclient.py'
1792--- lib/lp/codehosting/vfs/tests/test_branchfsclient.py 2010-08-20 20:31:18 +0000
1793+++ lib/lp/codehosting/vfs/tests/test_branchfsclient.py 2010-11-24 19:57:36 +0000
1794@@ -1,4 +1,4 @@
1795-# Copyright 2009 Canonical Ltd. This software is licensed under the
1796+# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
1797 # GNU Affero General Public License version 3 (see the file LICENSE).
1798
1799 # pylint: disable-msg=W0702
1800@@ -7,9 +7,9 @@
1801
1802 __metaclass__ = type
1803
1804-import unittest
1805-
1806-from twisted.trial.unittest import TestCase
1807+from testtools.deferredruntest import (
1808+ AsynchronousDeferredRunTest,
1809+ )
1810
1811 from lp.code.interfaces.codehosting import BRANCH_TRANSPORT
1812 from lp.codehosting.inmemory import (
1813@@ -20,13 +20,19 @@
1814 BranchFileSystemClient,
1815 NotInCache,
1816 )
1817-from lp.testing import FakeTime
1818+from lp.testing import (
1819+ FakeTime,
1820+ TestCase,
1821+ )
1822
1823
1824 class TestBranchFileSystemClient(TestCase):
1825 """Tests for `BranchFileSystemClient`."""
1826
1827+ run_tests_with = AsynchronousDeferredRunTest
1828+
1829 def setUp(self):
1830+ super(TestBranchFileSystemClient, self).setUp()
1831 frontend = InMemoryFrontend()
1832 self.factory = frontend.getLaunchpadObjectFactory()
1833 self.user = self.factory.makePerson()
1834@@ -250,8 +256,3 @@
1835 client.translatePath('/' + branch1.unique_name + '/different')
1836 self.assertEqual(
1837 [branch1.unique_name, branch2.unique_name], seen_branches)
1838-
1839-
1840-def test_suite():
1841- return unittest.TestLoader().loadTestsFromName(__name__)
1842-
1843
1844=== modified file 'lib/lp/registry/tests/test_distributionmirror_prober.py'
1845--- lib/lp/registry/tests/test_distributionmirror_prober.py 2010-10-04 19:50:45 +0000
1846+++ lib/lp/registry/tests/test_distributionmirror_prober.py 2010-11-24 19:57:36 +0000
1847@@ -617,6 +617,13 @@
1848 self.callbacks = MirrorCDImageProberCallbacks(
1849 mirror, warty, flavour, log_file)
1850
1851+ def tearDown(self):
1852+ # XXX: JonathanLange 2010-11-22: These tests leave stacks of delayed
1853+ # calls around. They need to be updated to use Twisted correctly.
1854+ # For the meantime, just blat the reactor.
1855+ for delayed_call in reactor.getDelayedCalls():
1856+ delayed_call.cancel()
1857+
1858 def test_mirrorcdimageseries_creation_and_deletion(self):
1859 callbacks = self.callbacks
1860 all_success = [(defer.SUCCESS, '200'), (defer.SUCCESS, '200')]
1861@@ -685,6 +692,13 @@
1862 self.callbacks = ArchiveMirrorProberCallbacks(
1863 mirror, warty, pocket, component, url, log_file)
1864
1865+ def tearDown(self):
1866+ # XXX: JonathanLange 2010-11-22: These tests leave stacks of delayed
1867+ # calls around. They need to be updated to use Twisted correctly.
1868+ # For the meantime, just blat the reactor.
1869+ for delayed_call in reactor.getDelayedCalls():
1870+ delayed_call.cancel()
1871+
1872 def test_failure_propagation(self):
1873 # Make sure that deleteMirrorSeries() does not propagate
1874 # ProberTimeout, BadResponseCode or ConnectionSkipped failures.
1875@@ -753,6 +767,13 @@
1876 # RequestManager.host_locks here.
1877 RequestManager.host_locks.clear()
1878
1879+ def tearDown(self):
1880+ # XXX: JonathanLange 2010-11-22: These tests leave stacks of delayed
1881+ # calls around. They need to be updated to use Twisted correctly.
1882+ # For the meantime, just blat the reactor.
1883+ for delayed_call in reactor.getDelayedCalls():
1884+ delayed_call.cancel()
1885+
1886 def test_MirrorCDImageSeries_records_are_deleted_before_probing(self):
1887 mirror = DistributionMirror.byName('releases-mirror2')
1888 self.failUnless(mirror.cdimage_series.count() > 0)
1889
1890=== modified file 'lib/lp/services/sshserver/tests/test_auth.py'
1891--- lib/lp/services/sshserver/tests/test_auth.py 2010-08-20 20:31:18 +0000
1892+++ lib/lp/services/sshserver/tests/test_auth.py 2010-11-24 19:57:36 +0000
1893@@ -2,7 +2,12 @@
1894 # GNU Affero General Public License version 3 (see the file LICENSE).
1895
1896 import os
1897-import unittest
1898+
1899+from testtools.deferredruntest import (
1900+ assert_fails_with,
1901+ flush_logged_errors,
1902+ AsynchronousDeferredRunTest,
1903+ )
1904
1905 from twisted.conch.checkers import SSHPublicKeyDatabase
1906 from twisted.conch.error import ConchError
1907@@ -27,13 +32,12 @@
1908 from twisted.internet import defer
1909 from twisted.python import failure
1910 from twisted.python.util import sibpath
1911-from twisted.trial.unittest import TestCase as TrialTestCase
1912 from zope.interface import implements
1913
1914 from canonical.launchpad.xmlrpc import faults
1915-from canonical.testing.layers import TwistedLayer
1916 from lp.services.sshserver import auth
1917 from lp.services.twistedsupport import suppress_stderr
1918+from lp.testing import TestCase
1919
1920
1921 class MockRealm:
1922@@ -85,7 +89,7 @@
1923 pass
1924
1925
1926-class UserAuthServerMixin:
1927+class UserAuthServerMixin(object):
1928 def setUp(self):
1929 self.portal = Portal(MockRealm())
1930 self.transport = MockSSHTransport(self.portal)
1931@@ -117,7 +121,11 @@
1932 self.fail("No banner logged.")
1933
1934
1935-class TestUserAuthServer(UserAuthServerMixin, unittest.TestCase):
1936+class TestUserAuthServer(TestCase, UserAuthServerMixin):
1937+
1938+ def setUp(self):
1939+ TestCase.setUp(self)
1940+ UserAuthServerMixin.setUp(self)
1941
1942 def test_sendBanner(self):
1943 # sendBanner should send an SSH 'packet' with type MSG_USERAUTH_BANNER
1944@@ -184,7 +192,7 @@
1945 auth.UserDisplayedUnauthorizedLogin(self.error_message))
1946
1947
1948-class TestAuthenticationBannerDisplay(UserAuthServerMixin, TrialTestCase):
1949+class TestAuthenticationBannerDisplay(UserAuthServerMixin, TestCase):
1950 """Check that auth error information is passed through to the client.
1951
1952 Normally, SSH servers provide minimal information on failed authentication.
1953@@ -196,16 +204,18 @@
1954 Section 5.4 for more information.
1955 """
1956
1957- layer = TwistedLayer
1958+ run_tests_with = AsynchronousDeferredRunTest
1959
1960 def setUp(self):
1961 UserAuthServerMixin.setUp(self)
1962+ TestCase.setUp(self)
1963 self.portal.registerChecker(MockChecker())
1964 self.user_auth.serviceStarted()
1965 self.key_data = self._makeKey()
1966
1967 def tearDown(self):
1968 self.user_auth.serviceStopped()
1969+ TestCase.tearDown(self)
1970
1971 def _makeKey(self):
1972 keydir = sibpath(__file__, 'keys')
1973@@ -306,7 +316,7 @@
1974 return d.addCallback(check)
1975
1976
1977-class TestPublicKeyFromLaunchpadChecker(TrialTestCase):
1978+class TestPublicKeyFromLaunchpadChecker(TestCase):
1979 """Tests for the SSH server authentication mechanism.
1980
1981 PublicKeyFromLaunchpadChecker accepts the SSH authentication information
1982@@ -316,7 +326,7 @@
1983 MSG_USERAUTH_BANNER message.
1984 """
1985
1986- layer = TwistedLayer
1987+ run_tests_with = AsynchronousDeferredRunTest
1988
1989 class FakeAuthenticationEndpoint:
1990 """A fake client for enough of `IAuthServer` for this test.
1991@@ -374,6 +384,7 @@
1992 return failure.Failure(UnauthorizedLogin())
1993
1994 def setUp(self):
1995+ TestCase.setUp(self)
1996 self.authserver = self.FakeAuthenticationEndpoint()
1997
1998 def test_successful(self):
1999@@ -395,10 +406,10 @@
2000 checker = self.makeChecker(True)
2001 d = checker.requestAvatarId(creds)
2002 def flush_errback(f):
2003- self.flushLoggedErrors(BadKeyError)
2004+ flush_logged_errors(BadKeyError)
2005 return f
2006 d.addErrback(flush_errback)
2007- return self.assertFailure(d, UnauthorizedLogin)
2008+ return assert_fails_with(d, UnauthorizedLogin)
2009
2010 def assertLoginError(self, checker, creds, error_message):
2011 """Logging in with 'creds' against 'checker' fails with 'message'.
2012@@ -411,7 +422,7 @@
2013 :param error_message: String excepted to match the exception's message.
2014 :return: Deferred. You must return this from your test.
2015 """
2016- d = self.assertFailure(
2017+ d = assert_fails_with(
2018 checker.requestAvatarId(creds),
2019 auth.UserDisplayedUnauthorizedLogin)
2020 d.addCallback(
2021@@ -449,7 +460,7 @@
2022 # We cannot use assertLoginError because we are checking that we fail
2023 # with UnauthorizedLogin and not its subclass
2024 # UserDisplayedUnauthorizedLogin.
2025- d = self.assertFailure(
2026+ d = assert_fails_with(
2027 checker.requestAvatarId(creds),
2028 UnauthorizedLogin)
2029 d.addCallback(
2030@@ -494,7 +505,7 @@
2031 'invalid-user', 'invalid key 2', mind)
2032 d = checker.requestAvatarId(creds_1)
2033 def try_second_key(failure):
2034- return self.assertFailure(
2035+ return assert_fails_with(
2036 checker.requestAvatarId(creds_2),
2037 UnauthorizedLogin)
2038 d.addErrback(try_second_key)
2039@@ -504,7 +515,3 @@
2040 return r
2041 d.addCallback(check_one_call)
2042 return d
2043-
2044-
2045-def test_suite():
2046- return unittest.TestLoader().loadTestsFromName(__name__)
2047
2048=== modified file 'lib/lp/services/twistedsupport/tests/test_loggingsupport.py'
2049--- lib/lp/services/twistedsupport/tests/test_loggingsupport.py 2010-08-20 20:31:18 +0000
2050+++ lib/lp/services/twistedsupport/tests/test_loggingsupport.py 2010-11-24 19:57:36 +0000
2051@@ -1,4 +1,4 @@
2052-# Copyright 2009 Canonical Ltd. This software is licensed under the
2053+# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
2054 # GNU Affero General Public License version 3 (see the file LICENSE).
2055
2056 """Tests for the integration between Twisted's logging and Launchpad's."""
2057@@ -13,15 +13,18 @@
2058 import StringIO
2059 import tempfile
2060 from textwrap import dedent
2061-import unittest
2062
2063 import pytz
2064+
2065+from testtools.deferredruntest import (
2066+ AsynchronousDeferredRunTest,
2067+ flush_logged_errors,
2068+ )
2069+
2070 from twisted.python import log
2071-from twisted.trial.unittest import TestCase
2072
2073 from canonical.config import config
2074 from canonical.launchpad.webapp.errorlog import globalErrorUtility
2075-from canonical.testing.layers import TwistedLayer
2076 from lp.services.twistedsupport.loggingsupport import (
2077 LaunchpadLogFile,
2078 OOPSLoggingObserver,
2079@@ -30,7 +33,7 @@
2080 makeFailure,
2081 suppress_stderr,
2082 )
2083-from lp.testing import TestCase as LaunchpadTestCase
2084+from lp.testing import TestCase
2085
2086
2087 UTC = pytz.utc
2088@@ -38,9 +41,10 @@
2089
2090 class LoggingSupportTests(TestCase):
2091
2092- layer = TwistedLayer
2093+ run_tests_with = AsynchronousDeferredRunTest
2094
2095 def setUp(self):
2096+ super(LoggingSupportTests, self).setUp()
2097 self.temp_dir = tempfile.mkdtemp()
2098 self.addCleanup(shutil.rmtree, self.temp_dir)
2099 config.push('testing', dedent("""
2100@@ -59,6 +63,7 @@
2101 def tearDown(self):
2102 config.pop('testing')
2103 globalErrorUtility.configure()
2104+ super(LoggingSupportTests, self).tearDown()
2105
2106 def assertLogMatches(self, pattern):
2107 """Assert that the messages logged by self.logger matches a regexp."""
2108@@ -73,13 +78,13 @@
2109 error_time = datetime.datetime.now(UTC)
2110 fail = makeFailure(RuntimeError)
2111 log.err(fail, error_time=error_time)
2112- self.flushLoggedErrors(RuntimeError)
2113+ flush_logged_errors(RuntimeError)
2114 oops = globalErrorUtility.getOopsReport(error_time)
2115 self.assertEqual(oops.type, 'RuntimeError')
2116 self.assertLogMatches('^Logged OOPS id.*')
2117
2118
2119-class TestLaunchpadLogFile(LaunchpadTestCase):
2120+class TestLaunchpadLogFile(TestCase):
2121
2122 def setUp(self):
2123 super(TestLaunchpadLogFile, self).setUp()
2124@@ -138,11 +143,11 @@
2125 self.assertEqual(['test.log'], self.listTestFiles())
2126 self.assertEqual([], log_file.listLogs())
2127
2128- ignored_file = self.createTestFile('boing')
2129+ self.createTestFile('boing')
2130 self.assertEqual([], log_file.listLogs())
2131
2132- old_log = self.createTestFile('test.log.2000-12-31')
2133- compressed_log = self.createTestFile('test.log.2000-12-30.bz2')
2134+ self.createTestFile('test.log.2000-12-31')
2135+ self.createTestFile('test.log.2000-12-30.bz2')
2136 self.assertEqual(
2137 ['test.log.2000-12-31', 'test.log.2000-12-30.bz2'],
2138 [os.path.basename(log_path) for log_path in log_file.listLogs()])
2139@@ -179,7 +184,3 @@
2140 ['test.log', 'test.log.2.bz2', 'test.log.3'],
2141 self.listTestFiles())
2142
2143-
2144-def test_suite():
2145- return unittest.TestLoader().loadTestsFromName(__name__)
2146-
2147
2148=== modified file 'lib/lp/services/twistedsupport/tests/test_processmonitor.py'
2149--- lib/lp/services/twistedsupport/tests/test_processmonitor.py 2010-10-04 19:50:45 +0000
2150+++ lib/lp/services/twistedsupport/tests/test_processmonitor.py 2010-11-24 19:57:36 +0000
2151@@ -1,4 +1,4 @@
2152-# Copyright 2009 Canonical Ltd. This software is licensed under the
2153+# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
2154 # GNU Affero General Public License version 3 (see the file LICENSE).
2155
2156 # pylint: disable-msg=W0702
2157@@ -7,8 +7,11 @@
2158
2159 __metaclass__ = type
2160
2161-
2162-import unittest
2163+from testtools.deferredruntest import (
2164+ assert_fails_with,
2165+ AsynchronousDeferredRunTest,
2166+ flush_logged_errors,
2167+ )
2168
2169 from twisted.internet import (
2170 defer,
2171@@ -16,9 +19,7 @@
2172 task,
2173 )
2174 from twisted.python import failure
2175-from twisted.trial.unittest import TestCase as TrialTestCase
2176
2177-from canonical.testing.layers import TwistedLayer
2178 from lp.services.twistedsupport import suppress_stderr
2179 from lp.services.twistedsupport.processmonitor import (
2180 ProcessMonitorProtocol,
2181@@ -27,6 +28,7 @@
2182 ProcessWithTimeout,
2183 run_process_with_timeout,
2184 )
2185+from lp.testing import TestCase
2186
2187
2188 def makeFailure(exception_factory, *args, **kwargs):
2189@@ -91,6 +93,7 @@
2190 self.protocol.processEnded(failure.Failure(exc))
2191
2192 def setUp(self):
2193+ super(ProcessTestsMixin, self).setUp()
2194 self.termination_deferred = defer.Deferred()
2195 self.clock = task.Clock()
2196 self.protocol = self.makeProtocol()
2197@@ -99,10 +102,10 @@
2198 self.protocol.connectionMade()
2199
2200
2201-class TestProcessWithTimeout(ProcessTestsMixin, TrialTestCase):
2202+class TestProcessWithTimeout(ProcessTestsMixin, TestCase):
2203 """Tests for `ProcessWithTimeout`."""
2204
2205- layer = TwistedLayer
2206+ run_tests_with = AsynchronousDeferredRunTest
2207 TIMEOUT = 100
2208
2209 def makeProtocol(self):
2210@@ -133,12 +136,11 @@
2211 self.assertFalse(self._deferred.called)
2212
2213
2214-class TestProcessProtocolWithTwoStageKill(
2215- ProcessTestsMixin, TrialTestCase):
2216+class TestProcessProtocolWithTwoStageKill(ProcessTestsMixin, TestCase):
2217
2218 """Tests for `ProcessProtocolWithTwoStageKill`."""
2219
2220- layer = TwistedLayer
2221+ run_tests_with = AsynchronousDeferredRunTest
2222
2223 def makeProtocol(self):
2224 """See `ProcessMonitorProtocolTestsMixin.makeProtocol`."""
2225@@ -182,11 +184,10 @@
2226 self.failIf(saved_delayed_call.active())
2227
2228
2229-class TestProcessMonitorProtocol(
2230- ProcessTestsMixin, TrialTestCase):
2231+class TestProcessMonitorProtocol(ProcessTestsMixin, TestCase):
2232 """Tests for `ProcessMonitorProtocol`."""
2233
2234- layer = TwistedLayer
2235+ run_tests_with = AsynchronousDeferredRunTest
2236
2237 def makeProtocol(self):
2238 """See `ProcessMonitorProtocolTestsMixin.makeProtocol`."""
2239@@ -203,7 +204,7 @@
2240 # When the child process terminates with a non-zero exit code, pass on
2241 # the error.
2242 self.simulateProcessExit(clean=False)
2243- return self.assertFailure(
2244+ return assert_fails_with(
2245 self.termination_deferred, error.ProcessTerminated)
2246
2247 def test_unexpectedError(self):
2248@@ -214,7 +215,7 @@
2249 self.assertEqual(
2250 [('signalProcess', 'INT')],
2251 self.protocol.transport.calls)
2252- return self.assertFailure(
2253+ return assert_fails_with(
2254 self.termination_deferred, RuntimeError)
2255
2256 def test_runNotification(self):
2257@@ -232,7 +233,7 @@
2258 self.assertEqual(
2259 [('signalProcess', 'INT')],
2260 self.protocol.transport.calls)
2261- return self.assertFailure(
2262+ return assert_fails_with(
2263 self.termination_deferred, RuntimeError)
2264
2265 def test_runNotificationSerialization(self):
2266@@ -258,7 +259,7 @@
2267 self.assertEqual(calls, [])
2268 deferred.errback(makeFailure(RuntimeError))
2269 self.assertEqual(calls, [])
2270- return self.assertFailure(
2271+ return assert_fails_with(
2272 self.termination_deferred, RuntimeError)
2273
2274 def test_waitForPendingNotification(self):
2275@@ -282,7 +283,7 @@
2276 self.protocol.runNotification(lambda : deferred)
2277 self.simulateProcessExit()
2278 deferred.errback(makeFailure(RuntimeError))
2279- return self.assertFailure(
2280+ return assert_fails_with(
2281 self.termination_deferred, RuntimeError)
2282
2283 @suppress_stderr
2284@@ -297,8 +298,8 @@
2285 runtime_error_failure = makeFailure(RuntimeError)
2286 deferred.errback(runtime_error_failure)
2287 self.assertEqual(
2288- self.flushLoggedErrors(RuntimeError), [runtime_error_failure])
2289- return self.assertFailure(
2290+ flush_logged_errors(RuntimeError), [runtime_error_failure])
2291+ return assert_fails_with(
2292 self.termination_deferred, error.ProcessTerminated)
2293
2294 @suppress_stderr
2295@@ -312,15 +313,15 @@
2296 runtime_error_failure = makeFailure(RuntimeError)
2297 deferred.errback(runtime_error_failure)
2298 self.assertEqual(
2299- self.flushLoggedErrors(RuntimeError), [runtime_error_failure])
2300- return self.assertFailure(
2301+ flush_logged_errors(RuntimeError), [runtime_error_failure])
2302+ return assert_fails_with(
2303 self.termination_deferred, TypeError)
2304
2305-class TestProcessMonitorProtocolWithTimeout(
2306- ProcessTestsMixin, TrialTestCase):
2307+
2308+class TestProcessMonitorProtocolWithTimeout(ProcessTestsMixin, TestCase):
2309 """Tests for `ProcessMonitorProtocolWithTimeout`."""
2310
2311- layer = TwistedLayer
2312+ run_tests_with = AsynchronousDeferredRunTest
2313
2314 timeout = 5
2315
2316@@ -333,7 +334,7 @@
2317 # If we don't receive any messages after the configured timeout
2318 # period, then we kill the child process.
2319 self.clock.advance(self.timeout + 1)
2320- return self.assertFailure(
2321+ return assert_fails_with(
2322 self.termination_deferred, error.TimeoutError)
2323
2324 def test_resetTimeout(self):
2325@@ -355,10 +356,10 @@
2326 return self.termination_deferred
2327
2328
2329-class TestRunProcessWithTimeout(TrialTestCase):
2330+class TestRunProcessWithTimeout(TestCase):
2331 """Tests for `run_process_with_timeout`."""
2332
2333- layer = TwistedLayer
2334+ run_tests_with = AsynchronousDeferredRunTest.make_factory(timeout=10)
2335
2336 def test_run_process_with_timeout_invalid_args(self):
2337 # `run_process_with_timeout` expects the process 'args' to be a
2338@@ -379,13 +380,13 @@
2339 # On failed process, the errback is fired with a `ProcessTerminated`
2340 # failure.
2341 d = run_process_with_timeout(('false',))
2342- return self.assertFailure(d, error.ProcessTerminated)
2343+ return assert_fails_with(d, error.ProcessTerminated)
2344
2345 def test_run_process_with_timeout_broken(self):
2346 # On broken process, the errback is fired with a `ProcessTerminated`
2347 # failure.
2348 d = run_process_with_timeout(('does-not-exist',))
2349- return self.assertFailure(d, error.ProcessTerminated)
2350+ return assert_fails_with(d, error.ProcessTerminated)
2351
2352 def test_run_process_with_timeout_timeout(self):
2353 # On process timeout, the errback is fired with `TimeoutError`
2354@@ -394,8 +395,4 @@
2355 d = run_process_with_timeout(
2356 ('sleep', '2'), timeout=1, clock=clock)
2357 clock.advance(2)
2358- return self.assertFailure(d, error.TimeoutError)
2359-
2360-
2361-def test_suite():
2362- return unittest.TestLoader().loadTestsFromName(__name__)
2363+ return assert_fails_with(d, error.TimeoutError)
2364
2365=== modified file 'lib/lp/services/twistedsupport/tests/test_twistedsupport.py'
2366--- lib/lp/services/twistedsupport/tests/test_twistedsupport.py 2010-10-15 15:01:39 +0000
2367+++ lib/lp/services/twistedsupport/tests/test_twistedsupport.py 2010-11-24 19:57:36 +0000
2368@@ -1,15 +1,17 @@
2369-# Copyright 2009 Canonical Ltd. This software is licensed under the
2370+# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
2371 # GNU Affero General Public License version 3 (see the file LICENSE).
2372
2373 """Tests for things found directly in `lp.services.twistedsupport`."""
2374
2375 __metaclass__ = type
2376
2377-import unittest
2378+from testtools.deferredruntest import (
2379+ assert_fails_with,
2380+ AsynchronousDeferredRunTest,
2381+ )
2382
2383 from twisted.internet import defer
2384 from twisted.internet.task import Clock
2385-from twisted.trial.unittest import TestCase as TrialTestCase
2386
2387 from lp.services.twistedsupport import (
2388 cancel_on_timeout,
2389@@ -42,14 +44,16 @@
2390 self.assertRaises(AssertionError, extract_result, deferred)
2391
2392
2393-class TestCancelOnTimeout(TrialTestCase):
2394+class TestCancelOnTimeout(TestCase):
2395 """Tests for lp.services.twistedsupport.cancel_on_timeout."""
2396
2397+ run_tests_with = AsynchronousDeferredRunTest
2398+
2399 def test_deferred_is_cancelled(self):
2400 clock = Clock()
2401 d = cancel_on_timeout(defer.Deferred(), 1, clock)
2402 clock.advance(2)
2403- return self.assertFailure(d, defer.CancelledError)
2404+ return assert_fails_with(d, defer.CancelledError)
2405
2406 def test_deferred_is_not_cancelled(self):
2407 clock = Clock()
2408
2409=== modified file 'lib/lp/services/twistedsupport/tests/test_xmlrpc.py'
2410--- lib/lp/services/twistedsupport/tests/test_xmlrpc.py 2010-09-22 18:24:15 +0000
2411+++ lib/lp/services/twistedsupport/tests/test_xmlrpc.py 2010-11-24 19:57:36 +0000
2412@@ -5,10 +5,7 @@
2413
2414 __metaclass__ = type
2415
2416-import unittest
2417-
2418 from twisted.python.failure import Failure
2419-from twisted.trial.unittest import TestCase
2420
2421 from lp.services.twistedsupport import extract_result
2422 from lp.services.twistedsupport.xmlrpc import (
2423@@ -17,6 +14,7 @@
2424 trap_fault,
2425 )
2426 from lp.services.xmlrpc import LaunchpadFault
2427+from lp.testing import TestCase
2428
2429
2430 class TestFaultOne(LaunchpadFault):
2431@@ -130,8 +128,3 @@
2432 d = proxy.callRemote('not_ok', 2, 3, c=8)
2433 error = self.assertRaises(RuntimeError, extract_result, d)
2434 self.assertEqual(str(error), str((8, 3, 2)))
2435-
2436-
2437-
2438-def test_suite():
2439- return unittest.TestLoader().loadTestsFromName(__name__)
2440
2441=== modified file 'lib/lp/services/twistedsupport/xmlrpc.py'
2442--- lib/lp/services/twistedsupport/xmlrpc.py 2010-09-22 18:32:22 +0000
2443+++ lib/lp/services/twistedsupport/xmlrpc.py 2010-11-24 19:57:36 +0000
2444@@ -11,7 +11,7 @@
2445 ]
2446
2447 from twisted.internet import defer
2448-from twisted.web.xmlrpc import Fault
2449+from twisted.web import xmlrpc
2450
2451
2452 class BlockingProxy:
2453@@ -50,6 +50,27 @@
2454 method_name, *args, **kwargs)
2455
2456
2457+class DisconnectingQueryProtocol(xmlrpc.QueryProtocol):
2458+
2459+ def connectionMade(self):
2460+ self._response = None
2461+ xmlrpc.QueryProtocol.connectionMade(self)
2462+
2463+ def handleResponse(self, contents):
2464+ self.transport.loseConnection()
2465+ self._response = contents
2466+
2467+ def connectionLost(self, reason):
2468+ xmlrpc.QueryProtocol.connectionLost(self, reason)
2469+ if self._response is not None:
2470+ response, self._response = self._response, None
2471+ self.factory.parseResponse(response)
2472+
2473+
2474+def fix_bug_2518():
2475+ # XXX: See http://twistedmatrix.com/trac/ticket/2518.
2476+ xmlrpc._QueryFactory.protocol = DisconnectingQueryProtocol
2477+
2478
2479 def trap_fault(failure, *fault_classes):
2480 """Trap a fault, based on fault code.
2481@@ -60,7 +81,7 @@
2482 does not match the given codes.
2483 :return: The Fault if it matches one of the codes.
2484 """
2485- failure.trap(Fault)
2486+ failure.trap(xmlrpc.Fault)
2487 fault = failure.value
2488 if fault.faultCode in [cls.error_code for cls in fault_classes]:
2489 return fault
2490
2491=== modified file 'lib/lp/soyuz/tests/test_binarypackagebuildbehavior.py'
2492--- lib/lp/soyuz/tests/test_binarypackagebuildbehavior.py 2010-10-29 14:41:29 +0000
2493+++ lib/lp/soyuz/tests/test_binarypackagebuildbehavior.py 2010-11-24 19:57:36 +0000
2494@@ -11,8 +11,11 @@
2495 import tempfile
2496 import transaction
2497
2498+from testtools.deferredruntest import (
2499+ AsynchronousDeferredRunTest,
2500+ )
2501+
2502 from twisted.internet import defer
2503-from twisted.trial import unittest as trialtest
2504
2505 from zope.component import getUtility
2506 from zope.security.proxy import removeSecurityProxy
2507@@ -20,7 +23,7 @@
2508 from canonical.config import config
2509 from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet
2510 from canonical.launchpad.scripts.logger import QuietFakeLogger
2511-from canonical.testing.layers import TwistedLaunchpadZopelessLayer
2512+from canonical.testing.layers import LaunchpadZopelessLayer
2513
2514 from lp.buildmaster.enums import (
2515 BuildStatus,
2516@@ -43,17 +46,11 @@
2517 )
2518 from lp.soyuz.enums import (
2519 ArchivePurpose,
2520- PackagePublishingStatus,
2521- )
2522-from lp.testing import (
2523- ANONYMOUS,
2524- login_as,
2525- logout,
2526- )
2527-from lp.testing.factory import LaunchpadObjectFactory
2528-
2529-
2530-class TestBinaryBuildPackageBehavior(trialtest.TestCase):
2531+ )
2532+from lp.testing import TestCaseWithFactory
2533+
2534+
2535+class TestBinaryBuildPackageBehavior(TestCaseWithFactory):
2536 """Tests for the BinaryPackageBuildBehavior.
2537
2538 In particular, these tests are about how the BinaryPackageBuildBehavior
2539@@ -63,13 +60,11 @@
2540 interesting parameters.
2541 """
2542
2543- layer = TwistedLaunchpadZopelessLayer
2544+ layer = LaunchpadZopelessLayer
2545+ run_tests_with = AsynchronousDeferredRunTest
2546
2547 def setUp(self):
2548 super(TestBinaryBuildPackageBehavior, self).setUp()
2549- self.factory = LaunchpadObjectFactory()
2550- login_as(ANONYMOUS)
2551- self.addCleanup(logout)
2552 self.layer.switchDbUser('testadmin')
2553
2554 def assertExpectedInteraction(self, ignored, call_log, builder, build,
2555@@ -266,7 +261,7 @@
2556 str(e))
2557
2558
2559-class TestBinaryBuildPackageBehaviorBuildCollection(trialtest.TestCase):
2560+class TestBinaryBuildPackageBehaviorBuildCollection(TestCaseWithFactory):
2561 """Tests for the BinaryPackageBuildBehavior.
2562
2563 Using various mock slaves, we check how updateBuild() behaves in
2564@@ -280,7 +275,8 @@
2565 # examine that behaviour separately somehow, but the old tests gave
2566 # NO clue as to what, exactly, they were testing.
2567
2568- layer = TwistedLaunchpadZopelessLayer
2569+ layer = LaunchpadZopelessLayer
2570+ run_tests_with = AsynchronousDeferredRunTest
2571
2572 def _cleanup(self):
2573 if os.path.exists(config.builddmaster.root):
2574@@ -288,9 +284,6 @@
2575
2576 def setUp(self):
2577 super(TestBinaryBuildPackageBehaviorBuildCollection, self).setUp()
2578- self.factory = LaunchpadObjectFactory()
2579- login_as(ANONYMOUS)
2580- self.addCleanup(logout)
2581 self.layer.switchDbUser('testadmin')
2582
2583 self.builder = self.factory.makeBuilder()
2584@@ -310,10 +303,10 @@
2585 def assertBuildProperties(self, build):
2586 """Check that a build happened by making sure some of its properties
2587 are set."""
2588- self.assertNotIdentical(None, build.builder)
2589- self.assertNotIdentical(None, build.date_finished)
2590- self.assertNotIdentical(None, build.duration)
2591- self.assertNotIdentical(None, build.log)
2592+ self.assertIsNot(None, build.builder)
2593+ self.assertIsNot(None, build.date_finished)
2594+ self.assertIsNot(None, build.duration)
2595+ self.assertIsNot(None, build.log)
2596
2597 def test_packagefail_collection(self):
2598 # When a package fails to build, make sure the builder notes are
2599@@ -363,7 +356,7 @@
2600 self.assertEqual(
2601 "Builder returned BUILDERFAIL when asked for its status",
2602 self.builder.failnotes)
2603- self.assertIdentical(None, self.candidate.builder)
2604+ self.assertIs(None, self.candidate.builder)
2605 self.assertEqual(BuildStatus.NEEDSBUILD, self.build.status)
2606 job = self.candidate.specific_job.job
2607 self.assertEqual(JobStatus.WAITING, job.status)
2608@@ -374,7 +367,7 @@
2609 def test_building_collection(self):
2610 # The builder is still building the package.
2611 self.builder.setSlaveForTesting(BuildingSlave())
2612-
2613+
2614 def got_update(ignored):
2615 # The fake log is returned from the BuildingSlave() mock.
2616 self.assertEqual("This is a build log", self.candidate.logtail)
2617@@ -412,7 +405,7 @@
2618 self.assertEqual(self.build.status, BuildStatus.UPLOADING)
2619 # We do not store any upload log information when the binary
2620 # upload processing succeeded.
2621- self.assertIdentical(None, self.build.upload_log)
2622+ self.assertIs(None, self.build.upload_log)
2623
2624 d = self.builder.updateBuild(self.candidate)
2625 return d.addCallback(got_update)
2626@@ -422,9 +415,9 @@
2627 self.builder.setSlaveForTesting(waiting_slave)
2628 score = self.candidate.lastscore
2629
2630- def got_update(ignored):
2631- self.assertIdentical(None, self.candidate.builder)
2632- self.assertIdentical(None, self.candidate.date_started)
2633+ def got_update(ignored):
2634+ self.assertIs(None, self.candidate.builder)
2635+ self.assertIs(None, self.candidate.date_started)
2636 self.assertEqual(score, self.candidate.lastscore)
2637 self.assertEqual(BuildStatus.NEEDSBUILD, self.build.status)
2638 job = self.candidate.specific_job.job
2639@@ -449,7 +442,7 @@
2640 # The new librarian file is stored compressed with a .gz
2641 # extension and text/plain file type for easy viewing in
2642 # browsers, as it decompresses and displays the file inline.
2643- self.assertTrue(logfile_lfa.filename).endswith('_FULLYBUILT.txt.gz')
2644+ self.assertTrue(logfile_lfa.filename.endswith('_FULLYBUILT.txt.gz'))
2645 self.assertEqual('text/plain', logfile_lfa.mimetype)
2646 self.layer.txn.commit()
2647
2648@@ -490,4 +483,3 @@
2649
2650 d = self.builder.updateBuild(self.candidate)
2651 return d.addCallback(got_update)
2652-
2653
2654=== modified file 'lib/lp/testing/__init__.py'
2655--- lib/lp/testing/__init__.py 2010-11-04 00:51:34 +0000
2656+++ lib/lp/testing/__init__.py 2010-11-24 19:57:36 +0000
2657@@ -488,14 +488,27 @@
2658 content = Content(UTF8_TEXT, oops.get_chunks)
2659 self.addDetail("oops-%d" % i, content)
2660
2661+ def attachLibrarianLog(self, fixture):
2662+ """Include the logChunks from fixture in the test details."""
2663+ # Evaluate the log when called, not later, to permit the librarian to
2664+ # be shutdown before the detail is rendered.
2665+ chunks = fixture.logChunks()
2666+ content = Content(UTF8_TEXT, lambda:chunks)
2667+ self.addDetail('librarian-log', content)
2668+
2669 def setUp(self):
2670 testtools.TestCase.setUp(self)
2671 from lp.testing.factory import ObjectFactory
2672+ from canonical.testing.layers import LibrarianLayer
2673 self.factory = ObjectFactory()
2674 # Record the oopses generated during the test run.
2675 self.oopses = []
2676 self.useFixture(ZopeEventHandlerFixture(self._recordOops))
2677 self.addCleanup(self.attachOopses)
2678+ if LibrarianLayer.librarian_fixture is not None:
2679+ self.addCleanup(
2680+ self.attachLibrarianLog,
2681+ LibrarianLayer.librarian_fixture)
2682 set_permit_timeout_from_features(False)
2683
2684 @adapter(ErrorReportEvent)
2685
2686=== modified file 'lib/lp/translations/tests/test_translationtemplatesbuildbehavior.py'
2687--- lib/lp/translations/tests/test_translationtemplatesbuildbehavior.py 2010-10-29 10:17:14 +0000
2688+++ lib/lp/translations/tests/test_translationtemplatesbuildbehavior.py 2010-11-24 19:57:36 +0000
2689@@ -6,7 +6,9 @@
2690 import logging
2691 import os
2692
2693-from twisted.trial.unittest import TestCase as TrialTestCase
2694+from testtools.deferredruntest import (
2695+ AsynchronousDeferredRunTest,
2696+ )
2697
2698 import transaction
2699 from zope.component import getUtility
2700@@ -17,7 +19,6 @@
2701 from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet
2702 from canonical.testing.layers import (
2703 LaunchpadZopelessLayer,
2704- TwistedLaunchpadZopelessLayer,
2705 )
2706 from lp.buildmaster.tests.mock_slaves import (
2707 SlaveTestHelpers,
2708@@ -28,12 +29,8 @@
2709 )
2710 from lp.buildmaster.interfaces.buildqueue import IBuildQueueSet
2711 from lp.testing import (
2712- ANONYMOUS,
2713- login_as,
2714- logout,
2715 TestCaseWithFactory,
2716 )
2717-from lp.testing.factory import LaunchpadObjectFactory
2718 from lp.testing.fakemethod import FakeMethod
2719 from lp.translations.enums import RosettaImportStatus
2720 from lp.translations.interfaces.translationimportqueue import (
2721@@ -100,19 +97,15 @@
2722
2723
2724 class TestTranslationTemplatesBuildBehavior(
2725- TrialTestCase, MakeBehaviorMixin):
2726+ TestCaseWithFactory, MakeBehaviorMixin):
2727 """Test `TranslationTemplatesBuildBehavior`."""
2728
2729- layer = TwistedLaunchpadZopelessLayer
2730+ layer = LaunchpadZopelessLayer
2731+ run_tests_with = AsynchronousDeferredRunTest
2732
2733 def setUp(self):
2734- super(TestTranslationTemplatesBuildBehavior, self)
2735- self.slave_helper = SlaveTestHelpers()
2736- self.slave_helper.setUp()
2737- self.addCleanup(self.slave_helper.cleanUp)
2738- self.factory = LaunchpadObjectFactory()
2739- login_as(ANONYMOUS)
2740- self.addCleanup(logout)
2741+ super(TestTranslationTemplatesBuildBehavior, self).setUp()
2742+ self.slave_helper = self.useFixture(SlaveTestHelpers())
2743
2744 def _becomeBuilddMaster(self):
2745 """Log into the database as the buildd master."""
2746
2747=== modified file 'versions.cfg'
2748--- versions.cfg 2010-11-19 18:24:11 +0000
2749+++ versions.cfg 2010-11-24 19:57:36 +0000
2750@@ -66,7 +66,7 @@
2751 soupmatchers = 0.1r53
2752 sourcecodegen = 0.6.9
2753 storm = 0.18
2754-testtools = 0.9.8-r128
2755+testtools = 0.9.8-r137
2756 transaction = 1.0.0
2757 Twisted = 10.1.0
2758 uuid = 1.30