Merge lp:~lifeless/launchpad/test into lp:launchpad

Proposed by Robert Collins
Status: Merged
Approved by: Michael Hudson-Doyle
Approved revision: no longer in the source branch.
Merged at revision: 11667
Proposed branch: lp:~lifeless/launchpad/test
Merge into: lp:launchpad
Diff against target: 1190 lines (+292/-161)
36 files modified
lib/canonical/buildd/tests/harness.py (+6/-9)
lib/canonical/buildd/tests/test_buildd_slave.py (+3/-2)
lib/canonical/launchpad/daemons/tachandler.py (+34/-18)
lib/canonical/launchpad/doc/old-testing.txt (+4/-3)
lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py (+1/-1)
lib/canonical/librarian/ftests/test_harness.py (+0/-13)
lib/canonical/librarian/librariangc.py (+4/-3)
lib/canonical/librarian/testing/__init__.py (+6/-0)
lib/canonical/librarian/testing/server.py (+80/-53)
lib/canonical/librarian/testing/tests/__init__.py (+6/-0)
lib/canonical/librarian/testing/tests/test_fakelibrarian.py (+1/-1)
lib/canonical/librarian/testing/tests/test_server_fixture.py (+29/-0)
lib/canonical/librarian/tests/test_sigdumpmem.py (+5/-4)
lib/canonical/testing/layers.py (+26/-6)
lib/canonical/zeca/ftests/harness.py (+5/-4)
lib/lp/archiveuploader/tests/__init__.py (+1/-1)
lib/lp/bugs/browser/bugtarget.py (+2/-1)
lib/lp/bugs/model/bug.py (+8/-2)
lib/lp/buildmaster/tests/test_builder.py (+1/-1)
lib/lp/buildmaster/tests/test_manager.py (+8/-9)
lib/lp/hardwaredb/doc/hwdb-submission.txt (+1/-1)
lib/lp/poppy/tests/test_poppy.py (+16/-6)
lib/lp/soyuz/browser/tests/distroseriesqueue-views.txt (+1/-1)
lib/lp/soyuz/doc/buildd-dispatching.txt (+9/-6)
lib/lp/soyuz/doc/distroseriesqueue-notify.txt (+2/-2)
lib/lp/soyuz/doc/distroseriesqueue.txt (+1/-1)
lib/lp/soyuz/doc/package-diff.txt (+1/-1)
lib/lp/soyuz/doc/soyuz-set-of-uploads.txt (+4/-3)
lib/lp/soyuz/doc/soyuz-upload.txt (+3/-2)
lib/lp/soyuz/scripts/tests/test_copypackage.py (+1/-1)
lib/lp/soyuz/scripts/tests/test_queue.py (+1/-1)
lib/lp/soyuz/scripts/tests/test_sync_source.py (+1/-1)
lib/lp/soyuz/stories/soyuz/xx-queue-pages.txt (+1/-1)
lib/lp/testing/fakelibrarian.py (+16/-0)
lib/lp/translations/doc/translationtemplatesbuildbehavior.txt (+3/-2)
lib/lp/translations/utilities/tests/test_file_importer.py (+1/-1)
To merge this branch: bzr merge lp:~lifeless/launchpad/test
Reviewer Review Type Date Requested Status
Michael Hudson-Doyle Approve
Review via email: mp+36674@code.launchpad.net

Commit message

Start consolidation and rationalisation of Librarian test helper code.

Description of the change

Start to consolidate and rationalise the Librarian test helper support code. Functionally similar, but with less duplicated code and somewhat clearer handling of both existing services and services that don't shut down.

To post a comment you must log in.
Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

Hi Rob, this is mostly a great improvement. It's great to see this old old crufty code get a spring clean!

LibrarianServerFixture.__init__'s docstring seems to have wandered to a strange place.

Same file, bit further down:

# The try:except here can be removed if someone audits the callers.

Audits the callers for what? Can you expand please.

All else looks good.

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

Thats an Attribute Docstring - see PEP257.

I've expanded the audit comment - callers need to cleanUp if setUp fails (or we need to decide that the fixture must not need a cleanUp if setUp fails)).

That is, infact, probably how we want to play it, so I'll look at an enhancement to fixtures to make that easy to do.

-Rob

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/buildd/tests/harness.py'
2--- lib/canonical/buildd/tests/harness.py 2010-02-19 20:17:08 +0000
3+++ lib/canonical/buildd/tests/harness.py 2010-10-03 20:53:47 +0000
4@@ -61,7 +61,8 @@
5 class BuilddSlaveTestSetup(TacTestSetup):
6 r"""Setup BuildSlave for use by functional tests
7
8- >>> BuilddSlaveTestSetup().setUp()
9+ >>> fixture = BuilddSlaveTestSetup()
10+ >>> fixture.setUp()
11
12 Make sure the server is running
13
14@@ -69,11 +70,11 @@
15 >>> s = xmlrpclib.Server('http://localhost:8221/rpc/')
16 >>> s.echo('Hello World')
17 ['Hello World']
18- >>> BuilddSlaveTestSetup().tearDown()
19+ >>> fixture.tearDown()
20
21 Again for luck !
22
23- >>> BuilddSlaveTestSetup().setUp()
24+ >>> fixture.setUp()
25 >>> s = xmlrpclib.Server('http://localhost:8221/rpc/')
26
27 >>> s.echo('Hello World')
28@@ -95,7 +96,7 @@
29 >>> s.status()
30 ['BuilderStatus.IDLE', '']
31
32- >>> BuilddSlaveTestSetup().tearDown()
33+ >>> fixture.tearDown()
34 """
35 def setUpRoot(self):
36 """Recreate empty root directory to avoid problems."""
37@@ -109,11 +110,7 @@
38 # When we are about running it seriously we need :
39 # * install sbuild package
40 # * to copy the scripts for sbuild
41-
42- def tearDown(self):
43- """Tear down the system normally and additionaly remove the root."""
44- TacTestSetup.tearDown(self)
45- remove_tree(self.root)
46+ self.addCleanup(remove_tree, self.root)
47
48 @property
49 def root(self):
50
51=== modified file 'lib/canonical/buildd/tests/test_buildd_slave.py'
52--- lib/canonical/buildd/tests/test_buildd_slave.py 2010-05-20 11:19:56 +0000
53+++ lib/canonical/buildd/tests/test_buildd_slave.py 2010-10-03 20:53:47 +0000
54@@ -176,11 +176,12 @@
55
56 def setUp(self):
57 super(XMLRPCBuildDSlaveTests, self).setUp()
58- BuilddSlaveTestSetup().setUp()
59+ self.slave = BuilddSlaveTestSetup()
60+ self.slave.setUp()
61 self.server = xmlrpclib.Server('http://localhost:8221/rpc/')
62
63 def tearDown(self):
64- BuilddSlaveTestSetup().tearDown()
65+ self.slave.tearDown()
66 super(XMLRPCBuildDSlaveTests, self).tearDown()
67
68 def test_build_unknown_builder(self):
69
70=== modified file 'lib/canonical/launchpad/daemons/tachandler.py'
71--- lib/canonical/launchpad/daemons/tachandler.py 2010-08-20 20:31:18 +0000
72+++ lib/canonical/launchpad/daemons/tachandler.py 2010-10-03 20:53:47 +0000
73@@ -26,13 +26,26 @@
74 import subprocess
75 import sys
76 import time
77+import warnings
78
79+from fixtures import Fixture
80 from twisted.application import service
81 from twisted.python import log
82
83 # This file is used by launchpad-buildd, so it cannot import any
84 # Launchpad code!
85
86+def _kill_may_race(pid, signal_number):
87+ """Kill a pid accepting that it may not exist."""
88+ try:
89+ os.kill(pid, signal_number)
90+ except OSError, e:
91+ if e.errno in (errno.ESRCH, errno.ECHILD):
92+ # Process has already been killed.
93+ return
94+ # Some other issue (e.g. different user owns it)
95+ raise
96+
97 def two_stage_kill(pid, poll_interval=0.1, num_polls=50):
98 """Kill process 'pid' with SIGTERM. If it doesn't die, SIGKILL it.
99
100@@ -42,12 +55,7 @@
101 :param num_polls: The number of polls to do before doing a SIGKILL.
102 """
103 # Kill the process.
104- try:
105- os.kill(pid, SIGTERM)
106- except OSError, e:
107- if e.errno in (errno.ESRCH, errno.ECHILD):
108- # Process has already been killed.
109- return
110+ _kill_may_race(pid, SIGTERM)
111
112 # Poll until the process has ended.
113 for i in range(num_polls):
114@@ -65,11 +73,7 @@
115 return
116
117 # The process is still around, so terminate it violently.
118- try:
119- os.kill(pid, SIGKILL)
120- except OSError:
121- # Already terminated
122- pass
123+ _kill_may_race(pid, SIGKILL)
124
125
126 def get_pid_from_file(pidfile_path):
127@@ -120,17 +124,27 @@
128 """Error raised by TacTestSetup."""
129
130
131-class TacTestSetup:
132+class TacTestSetup(Fixture):
133 """Setup an TAC file as daemon for use by functional tests.
134
135- You can override setUpRoot to set up a root directory for the daemon.
136+ You must override setUpRoot to set up a root directory for the daemon.
137 """
138
139 def setUp(self, spew=False, umask=None):
140- # Before we run, we want to make sure that we have cleaned up any
141- # previous runs. Although tearDown() should have been called already,
142- # we can't guarantee it.
143- self.tearDown()
144+ Fixture.setUp(self)
145+ if get_pid_from_file(self.pidfile):
146+ # An attempt to run while there was an existing live helper
147+ # was made. Note that this races with helpers which use unique
148+ # roots, so when moving/eliminating this code check subclasses
149+ # for workarounds and remove those too.
150+ pid = get_pid_from_file(self.pidfile)
151+ warnings.warn("Attempt to start Tachandler with an existing "
152+ "instance (%d) running in %s." % (pid, self.pidfile),
153+ DeprecationWarning, stacklevel=2)
154+ two_stage_kill(pid)
155+ if get_pid_from_file(self.pidfile):
156+ raise TacException(
157+ "Could not kill stale process %s." % (self.pidfile,))
158
159 # setUp() watches the logfile to determine when the daemon has fully
160 # started. If it sees an old logfile, then it will find the LOG_MAGIC
161@@ -156,6 +170,7 @@
162 # stdout/stderr are written to.
163 proc = subprocess.Popen(args, stdout=subprocess.PIPE,
164 stderr=subprocess.STDOUT)
165+ self.addCleanup(self.killTac)
166 # XXX: JonathanLange 2008-03-19: This can raise EINTR. We should
167 # really catch it and try again if that happens.
168 stdout = proc.stdout.read()
169@@ -201,7 +216,8 @@
170 self.tacfile, self.logfile, open(self.logfile).read()))
171
172 def tearDown(self):
173- self.killTac()
174+ # For compatibility - migrate to cleanUp.
175+ self.cleanUp()
176
177 def killTac(self):
178 """Kill the TAC file if it is running."""
179
180=== modified file 'lib/canonical/launchpad/doc/old-testing.txt'
181--- lib/canonical/launchpad/doc/old-testing.txt 2009-08-13 15:12:16 +0000
182+++ lib/canonical/launchpad/doc/old-testing.txt 2010-10-03 20:53:47 +0000
183@@ -253,14 +253,15 @@
184 You probably really want LaunchpadFunctionalTestSetup so you can access
185 the Librarian as a Utility.
186
187->>> from canonical.librarian.ftests.harness import LibrarianTestSetup
188+>>> from canonical.librarian.testing.server import LibrarianTestSetup
189 >>> from canonical.launchpad.ftests import login, ANONYMOUS
190 >>> from zope.app import zapi
191 >>> from canonical.librarian.interfaces import ILibrarianClient
192 >>> from StringIO import StringIO
193
194 >>> LaunchpadFunctionalTestSetup().setUp()
195->>> LibrarianTestSetup().setUp()
196+>>> librarian = LibrarianTestSetup()
197+>>> librarian.setUp()
198 >>> login(ANONYMOUS)
199
200 >>> some_content = StringIO()
201@@ -283,7 +284,7 @@
202 >>> data == some_content.getvalue()
203 True
204
205->>> LibrarianTestSetup().tearDown()
206+>>> librarian.tearDown()
207 >>> LaunchpadFunctionalTestSetup().tearDown()
208
209 >>> from canonical.testing import reset_logging
210
211=== modified file 'lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py'
212--- lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py 2010-08-20 20:31:18 +0000
213+++ lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py 2010-10-03 20:53:47 +0000
214@@ -18,7 +18,7 @@
215 from canonical.config import config
216 from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities
217 from canonical.launchpad.webapp.errorlog import ErrorReportingUtility
218-from canonical.librarian.ftests.harness import fillLibrarianFile
219+from canonical.librarian.testing.server import fillLibrarianFile
220 from canonical.librarian.interfaces import LibrarianServerError
221 from canonical.testing import (
222 BaseLayer,
223
224=== removed file 'lib/canonical/librarian/ftests/test_harness.py'
225--- lib/canonical/librarian/ftests/test_harness.py 2010-07-14 14:11:15 +0000
226+++ lib/canonical/librarian/ftests/test_harness.py 1970-01-01 00:00:00 +0000
227@@ -1,13 +0,0 @@
228-# Copyright 2009 Canonical Ltd. This software is licensed under the
229-# GNU Affero General Public License version 3 (see the file LICENSE).
230-
231-__metaclass__ = type
232-
233-import doctest
234-
235-def test_suite():
236- return doctest.DocTestSuite(
237- 'canonical.librarian.ftests.harness',
238- optionflags=doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
239- )
240-
241
242=== modified file 'lib/canonical/librarian/librariangc.py'
243--- lib/canonical/librarian/librariangc.py 2010-04-23 01:48:11 +0000
244+++ lib/canonical/librarian/librariangc.py 2010-10-03 20:53:47 +0000
245@@ -632,8 +632,9 @@
246 dirnames.remove('incoming')
247 if 'lost+found' in dirnames:
248 dirnames.remove('lost+found')
249- if 'librarian.pid' in filenames:
250- filenames.remove('librarian.pid')
251+ filenames = set(filenames)
252+ filenames.discard('librarian.pid')
253+ filenames.discard('librarian.log')
254
255 for dirname in dirnames[:]:
256 if len(dirname) != 2:
257@@ -650,7 +651,7 @@
258 # We need everything in order to ensure we visit files in the
259 # same order we retrieve wanted files from the database.
260 dirnames.sort()
261- filenames.sort()
262+ filenames = sorted(filenames)
263
264 # Noise in the storage area, or maybe we are looking at the wrong
265 # path?
266
267=== added directory 'lib/canonical/librarian/testing'
268=== added file 'lib/canonical/librarian/testing/__init__.py'
269--- lib/canonical/librarian/testing/__init__.py 1970-01-01 00:00:00 +0000
270+++ lib/canonical/librarian/testing/__init__.py 2010-10-03 20:53:47 +0000
271@@ -0,0 +1,6 @@
272+# Copyright 2010 Canonical Ltd. This software is licensed under the
273+# GNU Affero General Public License version 3 (see the file LICENSE).
274+
275+"""Test support for working with the librarian."""
276+
277+__metaclass__ = type
278
279=== renamed file 'lib/lp/testing/fakelibrarian.py' => 'lib/canonical/librarian/testing/fake.py'
280=== renamed file 'lib/canonical/librarian/ftests/harness.py' => 'lib/canonical/librarian/testing/server.py'
281--- lib/canonical/librarian/ftests/harness.py 2010-02-02 16:52:46 +0000
282+++ lib/canonical/librarian/testing/server.py 2010-10-03 20:53:47 +0000
283@@ -7,21 +7,30 @@
284 __all__ = [
285 'cleanupLibrarianFiles',
286 'fillLibrarianFile',
287+ 'LibrarianServerFixture',
288 'LibrarianTestSetup',
289 ]
290
291 import os
292 import shutil
293 import tempfile
294+import warnings
295+
296+from fixtures import Fixture
297
298 import canonical
299 from canonical.config import config
300-from canonical.launchpad.daemons.tachandler import TacException, TacTestSetup
301+from canonical.launchpad.daemons.tachandler import (
302+ get_pid_from_file,
303+ TacException,
304+ TacTestSetup,
305+ two_stage_kill,
306+ )
307 from canonical.librarian.storage import _relFileLocation
308
309
310-class LibrarianTestSetup:
311- """Set up librarian servers for use by functional tests.
312+class LibrarianServerFixture(TacTestSetup):
313+ """Librarian server fixture.
314
315 >>> from urllib import urlopen
316 >>> from canonical.config import config
317@@ -33,7 +42,8 @@
318 ... config.librarian.restricted_download_host,
319 ... config.librarian.restricted_download_port)
320
321- >>> LibrarianTestSetup().setUp()
322+ >>> fixture = LibrarianServerFixture()
323+ >>> fixture.setUp()
324
325 Set a socket timeout, so that this test cannot hang indefinitely.
326
327@@ -42,8 +52,8 @@
328 None
329 >>> socket.setdefaulttimeout(1)
330
331- After setUp() is called, two librarian instances are started. The
332- regular one:
333+ After setUp() is called, two librarian ports are available:
334+ The regular one:
335
336 >>> 'Copyright' in urlopen(librarian_url).read()
337 True
338@@ -59,9 +69,9 @@
339 >>> os.path.isdir(config.librarian_server.root)
340 True
341
342- After tearDown() is called, both instances are shut down:
343+ After tearDown() is called, both ports are closed:
344
345- >>> LibrarianTestSetup().tearDown()
346+ >>> fixture.tearDown()
347
348 >>> urlopen(librarian_url).read()
349 Traceback (most recent call last):
350@@ -80,39 +90,73 @@
351
352 That fixture can be started and stopped multiple time in succession:
353
354- >>> LibrarianTestSetup().setUp()
355+ >>> fixture.setUp()
356 >>> 'Copyright' in urlopen(librarian_url).read()
357 True
358
359 Tidy up.
360
361- >>> LibrarianTestSetup().tearDown()
362+ >>> fixture.tearDown()
363 >>> socket.setdefaulttimeout(None)
364+
365+ :ivar: pid pid of the external process.
366 """
367
368+ def __init__(self):
369+ Fixture.__init__(self)
370+ self._pid = None
371+ # Track whether the fixture has been setup or not.
372+ self._setup = False
373+
374 def setUp(self):
375 """Start both librarian instances."""
376- if (os.environ.get('LP_PERSISTENT_TEST_SERVICES') is not None and
377- os.path.exists(TacLibrarianTestSetup().pidfile)):
378+ if (self._persistent_servers() and self.pid):
379 return
380- self.setUpRoot()
381+ else:
382+ # self.pid may have been evaluated - nuke it.
383+ self._pid = None
384+ # The try:except here can be removed if someone audits the callers to
385+ # make sure that they call cleanUp if setUp fails.
386 try:
387- TacLibrarianTestSetup().setUp()
388+ TacTestSetup.setUp(self)
389 except TacException:
390- # Remove the directory usually removed in tearDown.
391- self.tearDownRoot()
392+ self.cleanUp()
393 raise
394+ else:
395+ self._pid = self._read_pid()
396+ self._setup = True
397+ self.addCleanup(setattr, self, '_setup', False)
398
399- def tearDown(self):
400+ def cleanUp(self):
401 """Shut downs both librarian instances."""
402- if os.environ.get('LP_PERSISTENT_TEST_SERVICES') is not None:
403- return
404- TacLibrarianTestSetup().tearDown()
405- self.tearDownRoot()
406+ if self._persistent_servers():
407+ return
408+ if not self._setup:
409+ warnings.warn("Attempt to tearDown inactive fixture.",
410+ DeprecationWarning, stacklevel=3)
411+ return
412+ TacTestSetup.cleanUp(self)
413
414 def clear(self):
415 """Clear all files from the Librarian"""
416- cleanupLibrarianFiles()
417+ # Make this smarter if our tests create huge numbers of files
418+ root = config.librarian_server.root
419+ if os.path.isdir(os.path.join(root, '00')):
420+ shutil.rmtree(os.path.join(root, '00'))
421+
422+ @property
423+ def pid(self):
424+ if self._pid:
425+ return self._pid
426+ if self._persistent_servers():
427+ self._pid = self._read_pid()
428+ return self._pid
429+
430+ def _read_pid(self):
431+ return get_pid_from_file(self.pidfile)
432+
433+ def _persistent_servers(self):
434+ return os.environ.get('LP_PERSISTENT_TEST_SERVICES') is not None
435
436 @property
437 def root(self):
438@@ -126,26 +170,13 @@
439 if os.path.exists(self.root):
440 self.tearDownRoot()
441 os.makedirs(self.root, 0700)
442+ self.addCleanup(self.tearDownRoot)
443
444 def tearDownRoot(self):
445 """Remove the librarian root archive."""
446 if os.path.isdir(self.root):
447 shutil.rmtree(self.root)
448
449-
450-class TacLibrarianTestSetup(TacTestSetup):
451- """Start the regular librarian instance."""
452-
453- def setUpRoot(self):
454- """Taken care by LibrarianTestSetup."""
455-
456- def tearDownRoot(self):
457- """Taken care by LibrarianTestSetup."""
458-
459- @property
460- def root(self):
461- return config.librarian_server.root
462-
463 @property
464 def tacfile(self):
465 return os.path.abspath(os.path.join(
466@@ -158,20 +189,18 @@
467 return os.path.join(self.root, 'librarian.pid')
468
469 @property
470- def _log_directory(self):
471- # Since the root gets deleted after the tests complete, and since we
472- # may still want to access the log file for post-mortem debugging, put
473- # the log file in the parent directory of root, or the temporary
474- # directory if that doesn't exist.
475- log_directory = os.path.dirname(self.root)
476- if os.path.isdir(log_directory):
477- return log_directory
478- else:
479- return tempfile.tempdir
480-
481- @property
482 def logfile(self):
483- return os.path.join(self._log_directory, 'librarian.log')
484+ # Store the log in the server root; if its wanted after a test, that
485+ # test can use addDetail to grab the log and include it in its
486+ # error.
487+ return os.path.join(self.root, 'librarian.log')
488+
489+
490+_global_fixture = LibrarianServerFixture()
491+
492+def LibrarianTestSetup():
493+ """Support the stateless lie."""
494+ return _global_fixture
495
496
497 def fillLibrarianFile(fileid, content='Fake Content'):
498@@ -186,9 +215,7 @@
499 libfile.write(content)
500 libfile.close()
501
502+
503 def cleanupLibrarianFiles():
504 """Remove all librarian files present in disk."""
505- # Make this smarter if our tests create huge numbers of files
506- root = config.librarian_server.root
507- if os.path.isdir(os.path.join(root, '00')):
508- shutil.rmtree(os.path.join(root, '00'))
509+ _global_fixture.clear()
510
511=== added directory 'lib/canonical/librarian/testing/tests'
512=== added file 'lib/canonical/librarian/testing/tests/__init__.py'
513--- lib/canonical/librarian/testing/tests/__init__.py 1970-01-01 00:00:00 +0000
514+++ lib/canonical/librarian/testing/tests/__init__.py 2010-10-03 20:53:47 +0000
515@@ -0,0 +1,6 @@
516+# Copyright 2010 Canonical Ltd. This software is licensed under the
517+# GNU Affero General Public License version 3 (see the file LICENSE).
518+
519+"""Tests of the librarian test support code."""
520+
521+__metaclass__ = type
522
523=== renamed file 'lib/lp/testing/tests/test_fakelibrarian.py' => 'lib/canonical/librarian/testing/tests/test_fakelibrarian.py'
524--- lib/lp/testing/tests/test_fakelibrarian.py 2010-09-18 09:14:59 +0000
525+++ lib/canonical/librarian/testing/tests/test_fakelibrarian.py 2010-10-03 20:53:47 +0000
526@@ -17,6 +17,7 @@
527 LibraryFileAliasSet,
528 )
529 from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet
530+from canonical.librarian.testing.fake import FakeLibrarian
531 from canonical.launchpad.webapp.testing import verifyObject
532 from canonical.librarian.client import LibrarianClient
533 from canonical.librarian.interfaces import ILibrarianClient
534@@ -25,7 +26,6 @@
535 LaunchpadFunctionalLayer,
536 )
537 from lp.testing import TestCaseWithFactory
538-from lp.testing.fakelibrarian import FakeLibrarian
539
540
541 class LibraryAccessScenarioMixin:
542
543=== added file 'lib/canonical/librarian/testing/tests/test_server_fixture.py'
544--- lib/canonical/librarian/testing/tests/test_server_fixture.py 1970-01-01 00:00:00 +0000
545+++ lib/canonical/librarian/testing/tests/test_server_fixture.py 2010-10-03 20:53:47 +0000
546@@ -0,0 +1,29 @@
547+# Copyright 2010 Canonical Ltd. This software is licensed under the
548+# GNU Affero General Public License version 3 (see the file LICENSE).
549+
550+"""Test the LibrarianServerFixture."""
551+
552+__metaclass__ = type
553+
554+import doctest
555+import unittest
556+
557+from canonical.librarian.testing.server import LibrarianServerFixture
558+from lp.testing import TestCase
559+
560+def test_suite():
561+ result = unittest.TestLoader().loadTestsFromName(__name__)
562+ result.addTest(doctest.DocTestSuite(
563+ 'canonical.librarian.testing.server',
564+ optionflags=doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
565+ ))
566+ return result
567+
568+
569+class TestLibrarianServerFixture(TestCase):
570+
571+ def test_on_init_no_pid(self):
572+ fixture = LibrarianServerFixture()
573+ if fixture._persistent_servers():
574+ self.skip('persistent server running.')
575+ self.assertEqual(None, fixture.pid)
576
577=== modified file 'lib/canonical/librarian/tests/test_sigdumpmem.py'
578--- lib/canonical/librarian/tests/test_sigdumpmem.py 2010-04-20 14:27:26 +0000
579+++ lib/canonical/librarian/tests/test_sigdumpmem.py 2010-10-03 20:53:47 +0000
580@@ -9,7 +9,7 @@
581 import time
582
583 from canonical.librarian.interfaces import DUMP_FILE, SIGDUMPMEM
584-from canonical.librarian.ftests.harness import TacLibrarianTestSetup
585+from canonical.librarian.testing.server import LibrarianTestSetup
586 from canonical.testing.layers import LibrarianLayer
587 from lp.testing import TestCase
588
589@@ -23,9 +23,10 @@
590 os.unlink(DUMP_FILE)
591 self.assertFalse(os.path.exists(DUMP_FILE))
592
593- # We rely on the fact that the librarian was started by the test
594- # runner here as we use the LibrarianLayer.
595- pid = int(open(TacLibrarianTestSetup().pidfile).read())
596+ # Use the global instance used by the Layer machinery; it would
597+ # be nice to be able to access those without globals / magical
598+ # 'constructors'.
599+ pid = LibrarianTestSetup().pid
600
601 # Send the signal and ensure the dump file is created.
602 os.kill(pid, SIGDUMPMEM)
603
604=== modified file 'lib/canonical/testing/layers.py'
605--- lib/canonical/testing/layers.py 2010-09-29 05:53:47 +0000
606+++ lib/canonical/testing/layers.py 2010-10-03 20:53:47 +0000
607@@ -85,6 +85,7 @@
608 from zope.app.publication.httpfactory import chooseClasses
609 from zope.app.testing.functional import FunctionalTestSetup, ZopePublication
610 from zope.component import getUtility, provideUtility
611+from zope.component import globalregistry
612 from zope.component.interfaces import ComponentLookupError
613 from zope.security.management import getSecurityPolicy
614 from zope.security.simplepolicies import PermissiveSecurityPolicy
615@@ -116,7 +117,7 @@
616 from canonical.lazr.timeout import (
617 get_default_timeout_function, set_default_timeout_function)
618 from canonical.lp import initZopeless
619-from canonical.librarian.ftests.harness import LibrarianTestSetup
620+from canonical.librarian.testing.server import LibrarianTestSetup
621 from canonical.testing import reset_logging
622 from canonical.testing.profiled import profiled
623 from canonical.testing.smtpd import SMTPController
624@@ -262,7 +263,6 @@
625 # about killing memcached - just do it quickly.
626 if not BaseLayer.persist_test_services:
627 kill_by_pidfile(MemcachedLayer.getPidFile(), num_polls=0)
628- LibrarianTestSetup().tearDown()
629 # Kill any database left lying around from a previous test run.
630 try:
631 DatabaseLayer.connect().close()
632@@ -851,6 +851,24 @@
633 @profiled
634 def tearDown(cls):
635 pass
636+
637+ @classmethod
638+ def tearDownHelper(cls):
639+ """Helper for when LaunchpadLayer is mixed with unteardownable layers.
640+
641+ E.g. FunctionalLayer causes other layer tearDown to not occur, which is
642+ why atexit is used, but because test runners delegate rather than
643+ returning, the librarian and other servers are only killed *at the end
644+ of the whole test run*, which leads to multiple instances running, so
645+ we manually run the teardown for these layers.
646+ """
647+ try:
648+ MemcachedLayer.tearDown()
649+ finally:
650+ try:
651+ LibrarianLayer.tearDown()
652+ finally:
653+ DatabaseLayer.tearDown()
654
655 @classmethod
656 @profiled
657@@ -1212,7 +1230,7 @@
658 @classmethod
659 @profiled
660 def tearDown(cls):
661- pass
662+ LaunchpadLayer.tearDownHelper()
663
664 @classmethod
665 @profiled
666@@ -1314,13 +1332,15 @@
667 # XXX flacoste 2006-10-25 bug=68189: This should be configured from
668 # ZCML but execute_zcml_for_scripts() doesn't cannot support a
669 # different testing configuration.
670- provideUtility(TestMailBox(), IMailBox)
671+ cls._mailbox = TestMailBox()
672+ provideUtility(cls._mailbox, IMailBox)
673
674 @classmethod
675 @profiled
676 def tearDown(cls):
677- # Signal Layer cannot be torn down fully
678- raise NotImplementedError
679+ if not globalregistry.base.unregisterUtility(cls._mailbox):
680+ raise NotImplementedError('failed to unregister mailbox')
681+ LaunchpadLayer.tearDownHelper()
682
683 @classmethod
684 @profiled
685
686=== modified file 'lib/canonical/zeca/ftests/harness.py'
687--- lib/canonical/zeca/ftests/harness.py 2009-08-20 13:52:29 +0000
688+++ lib/canonical/zeca/ftests/harness.py 2010-10-03 20:53:47 +0000
689@@ -17,7 +17,8 @@
690 class ZecaTestSetup(TacTestSetup):
691 r"""Setup a zeca for use by functional tests
692
693- >>> ZecaTestSetup().setUp()
694+ >>> fixture = ZecaTestSetup()
695+ >>> fixture.setUp()
696
697 Make sure the server is running
698
699@@ -98,17 +99,17 @@
700 <title>Submit a key</title>
701 ...
702
703- >>> ZecaTestSetup().tearDown()
704+ >>> fixture.tearDown()
705
706 And again for luck
707
708- >>> ZecaTestSetup().setUp()
709+ >>> fixture.setUp()
710
711 >>> print urlopen(root_url).readline()
712 Copyright 2004-2009 Canonical Ltd.
713 <BLANKLINE>
714
715- >>> ZecaTestSetup().tearDown()
716+ >>> fixture.tearDown()
717 """
718 def setUpRoot(self):
719 """Recreate root directory and copy needed keys"""
720
721=== modified file 'lib/lp/archiveuploader/tests/__init__.py'
722--- lib/lp/archiveuploader/tests/__init__.py 2010-09-16 12:27:46 +0000
723+++ lib/lp/archiveuploader/tests/__init__.py 2010-10-03 20:53:47 +0000
724@@ -22,7 +22,7 @@
725
726 from zope.component import getGlobalSiteManager
727
728-from canonical.librarian.ftests.harness import fillLibrarianFile
729+from canonical.librarian.testing.server import fillLibrarianFile
730 from lp.archiveuploader.uploadpolicy import (
731 AbstractUploadPolicy,
732 findPolicyByName,
733
734=== modified file 'lib/lp/bugs/browser/bugtarget.py'
735--- lib/lp/bugs/browser/bugtarget.py 2010-09-25 14:29:32 +0000
736+++ lib/lp/bugs/browser/bugtarget.py 2010-10-03 20:53:47 +0000
737@@ -588,7 +588,8 @@
738 bug.linkAttachment(
739 owner=self.user, file_alias=attachment['file_alias'],
740 description=attachment['description'],
741- comment=attachment_comment)
742+ comment=attachment_comment,
743+ send_notifications=False)
744 notifications.append(
745 'The file "%s" was attached to the bug report.' %
746 cgi.escape(attachment['file_alias'].filename))
747
748=== modified file 'lib/lp/bugs/model/bug.py'
749--- lib/lp/bugs/model/bug.py 2010-09-24 14:29:15 +0000
750+++ lib/lp/bugs/model/bug.py 2010-10-03 20:53:47 +0000
751@@ -1218,13 +1218,18 @@
752 owner, filealias, comment, is_patch, description)
753
754 def linkAttachment(self, owner, file_alias, comment, is_patch=False,
755- description=None):
756+ description=None, send_notifications=True):
757 """See `IBug`.
758
759 This method should only be called by addAttachment() and
760 FileBugViewBase.submit_bug_action, otherwise
761 we may get inconsistent settings of bug.private and
762 file_alias.restricted.
763+
764+ :param send_notifications: Control sending of notifications for this
765+ attachment. This is disabled when adding attachments from 'extra
766+ data' in the filebug form, because that triggered hundreds of DB
767+ inserts and thus timeouts. Defaults to sending notifications.
768 """
769 if is_patch:
770 attach_type = BugAttachmentType.PATCH
771@@ -1244,7 +1249,8 @@
772
773 return getUtility(IBugAttachmentSet).create(
774 bug=self, filealias=file_alias, attach_type=attach_type,
775- title=title, message=message, send_notifications=True)
776+ title=title, message=message,
777+ send_notifications=send_notifications)
778
779 def hasBranch(self, branch):
780 """See `IBug`."""
781
782=== modified file 'lib/lp/buildmaster/tests/test_builder.py'
783--- lib/lp/buildmaster/tests/test_builder.py 2010-09-23 12:35:21 +0000
784+++ lib/lp/buildmaster/tests/test_builder.py 2010-10-03 20:53:47 +0000
785@@ -495,12 +495,12 @@
786 """
787 tachandler = BuilddSlaveTestSetup()
788 tachandler.setUp()
789+ self.addCleanup(tachandler.tearDown)
790 def addLogFile(exc_info):
791 self.addDetail(
792 'xmlrpc-log-file',
793 Content(UTF8_TEXT, lambda: open(tachandler.logfile, 'r').read()))
794 self.addOnException(addLogFile)
795- self.addCleanup(tachandler.tearDown)
796 return tachandler
797
798 def getClientSlave(self):
799
800=== modified file 'lib/lp/buildmaster/tests/test_manager.py'
801--- lib/lp/buildmaster/tests/test_manager.py 2010-09-22 11:26:19 +0000
802+++ lib/lp/buildmaster/tests/test_manager.py 2010-10-03 20:53:47 +0000
803@@ -610,7 +610,8 @@
804 """
805 TwistedLayer.testSetUp()
806 TrialTestCase.setUp(self)
807- BuilddSlaveTestSetup().setUp()
808+ self.slave = BuilddSlaveTestSetup()
809+ self.slave.setUp()
810
811 # Creating the required chroots needed for dispatching.
812 login('foo.bar@canonical.com')
813@@ -622,7 +623,7 @@
814 login(ANONYMOUS)
815
816 def tearDown(self):
817- BuilddSlaveTestSetup().tearDown()
818+ self.slave.tearDown()
819 TrialTestCase.tearDown(self)
820 TwistedLayer.testTearDown()
821
822@@ -1152,8 +1153,9 @@
823
824 def testBuilddManagerRuns(self):
825 # The `buildd-manager.tac` starts and stops correctly.
826- BuilddManagerTestSetup().setUp()
827- BuilddManagerTestSetup().tearDown()
828+ fixture = BuilddManagerTestSetup()
829+ fixture.setUp()
830+ fixture.tearDown()
831
832 # XXX Julian 2010-08-06 bug=614275
833 # These next 2 tests are in the wrong place, they should be near the
834@@ -1164,10 +1166,8 @@
835
836 def disabled_testBuilddManagerLogging(self):
837 # The twistd process logs as execpected.
838- test_setup = BuilddManagerTestSetup()
839+ test_setup = self.useFixture(BuilddManagerTestSetup())
840 logfilepath = test_setup.logfile
841- test_setup.setUp()
842- self.addCleanup(test_setup.tearDown)
843 # The process logs to its logfile.
844 self.assertTrue(is_file_growing(logfilepath))
845 # After rotating the log, the process keeps using the old file, no
846@@ -1192,8 +1192,7 @@
847 # Prefill the log file to just under 1000000 bytes.
848 test_setup.precreateLogfile(
849 "2010-07-27 12:36:54+0200 [-] Starting scanning cycle.\n", 18518)
850- test_setup.setUp()
851- self.addCleanup(test_setup.tearDown)
852+ self.useFixture(test_setup)
853 # The process logs to the logfile.
854 self.assertTrue(is_file_growing(logfilepath))
855 # No rotation occured.
856
857=== modified file 'lib/lp/hardwaredb/doc/hwdb-submission.txt'
858--- lib/lp/hardwaredb/doc/hwdb-submission.txt 2010-04-01 04:05:10 +0000
859+++ lib/lp/hardwaredb/doc/hwdb-submission.txt 2010-10-03 20:53:47 +0000
860@@ -253,7 +253,7 @@
861 let's add one. Let's add invalid data in order to see how invalid
862 submissions are processed.
863
864- >>> from canonical.librarian.ftests.harness import fillLibrarianFile
865+ >>> from canonical.librarian.testing.server import fillLibrarianFile
866 >>> submission = submission_set.getBySubmissionKey('test_submission_id_1')
867 >>> fillLibrarianFile(
868 ... submission.raw_submission.id, 'nonsense')
869
870=== modified file 'lib/lp/poppy/tests/test_poppy.py'
871--- lib/lp/poppy/tests/test_poppy.py 2010-08-20 20:31:18 +0000
872+++ lib/lp/poppy/tests/test_poppy.py 2010-10-03 20:53:47 +0000
873@@ -151,17 +151,27 @@
874
875
876 class PoppyTac(TacTestSetup):
877+ """A SFTP Poppy server fixture.
878+
879+ This class has two distinct roots:
880+ - the POPPY_ROOT where the test looks for uploaded output.
881+ - the server root where ssh keys etc go.
882+ """
883
884 def __init__(self, fs_root):
885- os.environ['POPPY_ROOT'] = fs_root
886- self.setUpRoot()
887+ self.fs_root = fs_root
888+ # The setUp check for stale pids races with self._root being assigned,
889+ # so store a plausible path temporarily. Once all fixtures use unique
890+ # environments this can go.
891+ self._root = '/var/does/not/exist'
892+
893+ def setUp(self):
894+ os.environ['POPPY_ROOT'] = self.fs_root
895 super(PoppyTac, self).setUp(umask='0')
896
897 def setUpRoot(self):
898 self._root = tempfile.mkdtemp()
899-
900- def tearDownRoot(self):
901- shutil.rmtree(self._root)
902+ self.addCleanup(shutil.rmtree, self.root)
903
904 @property
905 def root(self):
906@@ -174,7 +184,7 @@
907
908 @property
909 def logfile(self):
910- return os.path.join('/tmp', 'poppy-sftp.log')
911+ return os.path.join(self.root, 'poppy-sftp.log')
912
913 @property
914 def pidfile(self):
915
916=== modified file 'lib/lp/soyuz/browser/tests/distroseriesqueue-views.txt'
917--- lib/lp/soyuz/browser/tests/distroseriesqueue-views.txt 2010-08-26 15:28:34 +0000
918+++ lib/lp/soyuz/browser/tests/distroseriesqueue-views.txt 2010-10-03 20:53:47 +0000
919@@ -294,5 +294,5 @@
920
921 We created librarian files that need cleaning up before leaving the test.
922
923- >>> from canonical.librarian.ftests.harness import cleanupLibrarianFiles
924+ >>> from canonical.librarian.testing.server import cleanupLibrarianFiles
925 >>> cleanupLibrarianFiles()
926
927=== modified file 'lib/lp/soyuz/doc/buildd-dispatching.txt'
928--- lib/lp/soyuz/doc/buildd-dispatching.txt 2010-09-24 10:39:27 +0000
929+++ lib/lp/soyuz/doc/buildd-dispatching.txt 2010-10-03 20:53:47 +0000
930@@ -13,7 +13,8 @@
931 Setup the test builder:
932
933 >>> from canonical.buildd.tests import BuilddSlaveTestSetup
934- >>> BuilddSlaveTestSetup().setUp()
935+ >>> fixture = BuilddSlaveTestSetup()
936+ >>> fixture.setUp()
937
938 Setup a suitable chroot for Hoary i386:
939
940@@ -168,7 +169,7 @@
941 Shutdown builder, mark the build record as failed and remove the
942 buildqueue record, so the build was eliminated:
943
944- >>> BuilddSlaveTestSetup().tearDown()
945+ >>> fixture.tearDown()
946
947 >>> from lp.buildmaster.enums import BuildStatus
948 >>> build.status = BuildStatus.FAILEDTOBUILD
949@@ -243,7 +244,8 @@
950
951 Start buildd-slave to be able to dispatch jobs.
952
953- >>> BuilddSlaveTestSetup().setUp()
954+ >>> fixture = BuilddSlaveTestSetup()
955+ >>> fixture.setUp()
956
957 Before dispatching we can check if the builder is protected against
958 mistakes in code that results in a attempt to build a virtual job in
959@@ -280,7 +282,7 @@
960 buildqueue record and make 'bob' builder non-virtual again, so the
961 environment is back to the initial state.
962
963- >>> BuilddSlaveTestSetup().tearDown()
964+ >>> fixture.tearDown()
965
966 >>> build.status = BuildStatus.FAILEDTOBUILD
967 >>> ppa_job.destroySelf()
968@@ -319,12 +321,13 @@
969 accept such jobs until we have finished the EMBARGOED archive
970 implementation.
971
972- >>> BuilddSlaveTestSetup().setUp()
973+ >>> fixture = BuilddSlaveTestSetup()
974+ >>> fixture.setUp()
975 >>> removeSecurityProxy(bob_builder)._dispatchBuildCandidate(sec_job)
976 Traceback (most recent call last):
977 ...
978 AssertionError: Soyuz is not yet capable of building SECURITY uploads.
979- >>> BuilddSlaveTestSetup().tearDown()
980+ >>> fixture.tearDown()
981
982 To solve this problem temporarily until we start building security
983 uploads, we will mark builds targeted to the SECURITY pocket as
984
985=== modified file 'lib/lp/soyuz/doc/distroseriesqueue-notify.txt'
986--- lib/lp/soyuz/doc/distroseriesqueue-notify.txt 2009-05-13 14:05:27 +0000
987+++ lib/lp/soyuz/doc/distroseriesqueue-notify.txt 2010-10-03 20:53:47 +0000
988@@ -179,7 +179,7 @@
989 provided that everything is already committed to the database (which is not
990 the case when nascent upload runs). This example demonstrates this usage:
991
992- >>> from canonical.librarian.ftests.harness import fillLibrarianFile
993+ >>> from canonical.librarian.testing.server import fillLibrarianFile
994 >>> changes_file = open(changes_file_path,"r")
995 >>> fillLibrarianFile(1, content=changes_file.read())
996 >>> changes_file.close()
997@@ -259,5 +259,5 @@
998
999 Clean up, otherwise stuff is left lying around in /var/tmp.
1000
1001- >>> from canonical.librarian.ftests.harness import cleanupLibrarianFiles
1002+ >>> from canonical.librarian.testing.server import cleanupLibrarianFiles
1003 >>> cleanupLibrarianFiles()
1004
1005=== modified file 'lib/lp/soyuz/doc/distroseriesqueue.txt'
1006--- lib/lp/soyuz/doc/distroseriesqueue.txt 2010-08-25 11:01:59 +0000
1007+++ lib/lp/soyuz/doc/distroseriesqueue.txt 2010-10-03 20:53:47 +0000
1008@@ -1026,7 +1026,7 @@
1009
1010 Clean up the librarian files:
1011
1012- >>> from canonical.librarian.ftests.harness import cleanupLibrarianFiles
1013+ >>> from canonical.librarian.testing.server import cleanupLibrarianFiles
1014 >>> cleanupLibrarianFiles()
1015
1016
1017
1018=== modified file 'lib/lp/soyuz/doc/package-diff.txt'
1019--- lib/lp/soyuz/doc/package-diff.txt 2010-08-25 11:01:59 +0000
1020+++ lib/lp/soyuz/doc/package-diff.txt 2010-10-03 20:53:47 +0000
1021@@ -643,7 +643,7 @@
1022 ... '1.0-2', archive=foobar.archive)
1023 >>> transaction.commit()
1024
1025- >>> from canonical.librarian.ftests.harness import fillLibrarianFile
1026+ >>> from canonical.librarian.testing.server import fillLibrarianFile
1027 >>> [orig, upload_diff, dsc] = pub.sourcepackagerelease.files
1028 >>> fillLibrarianFile(dsc.libraryfile.id)
1029
1030
1031=== modified file 'lib/lp/soyuz/doc/soyuz-set-of-uploads.txt'
1032--- lib/lp/soyuz/doc/soyuz-set-of-uploads.txt 2010-09-16 12:27:46 +0000
1033+++ lib/lp/soyuz/doc/soyuz-set-of-uploads.txt 2010-10-03 20:53:47 +0000
1034@@ -59,7 +59,8 @@
1035 relevant launchpad person.
1036
1037 >>> from canonical.zeca.ftests.harness import ZecaTestSetup
1038- >>> ZecaTestSetup().setUp()
1039+ >>> zeca = ZecaTestSetup()
1040+ >>> zeca.setUp()
1041
1042 Import public keyring into current LPDB.
1043
1044@@ -90,7 +91,7 @@
1045
1046 Add disk content for file inherited from ubuntu/breezy-autotest:
1047
1048- >>> from canonical.librarian.ftests.harness import fillLibrarianFile
1049+ >>> from canonical.librarian.testing.server import fillLibrarianFile
1050 >>> fillLibrarianFile(54)
1051
1052 Now that the infrastructure is ready, we prepare a set of useful methods.
1053@@ -754,5 +755,5 @@
1054 >>> shutil.rmtree("/var/tmp/archive/")
1055 >>> shutil.rmtree(temp_dir)
1056
1057- >>> ZecaTestSetup().tearDown()
1058+ >>> zeca.tearDown()
1059
1060
1061=== modified file 'lib/lp/soyuz/doc/soyuz-upload.txt'
1062--- lib/lp/soyuz/doc/soyuz-upload.txt 2010-09-02 13:01:23 +0000
1063+++ lib/lp/soyuz/doc/soyuz-upload.txt 2010-10-03 20:53:47 +0000
1064@@ -260,7 +260,8 @@
1065 a different process.
1066
1067 >>> from canonical.zeca.ftests.harness import ZecaTestSetup
1068- >>> ZecaTestSetup().setUp()
1069+ >>> zeca = ZecaTestSetup()
1070+ >>> zeca.setUp()
1071
1072
1073 Include non-free in the database. This will be done by the
1074@@ -763,7 +764,7 @@
1075 Remove the test archive from filesystem.
1076
1077 >>> shutil.rmtree("/var/tmp/archive/")
1078- >>> ZecaTestSetup().tearDown()
1079+ >>> zeca.tearDown()
1080
1081
1082 Feito! ;-)
1083
1084=== modified file 'lib/lp/soyuz/scripts/tests/test_copypackage.py'
1085--- lib/lp/soyuz/scripts/tests/test_copypackage.py 2010-08-27 11:19:54 +0000
1086+++ lib/lp/soyuz/scripts/tests/test_copypackage.py 2010-10-03 20:53:47 +0000
1087@@ -17,7 +17,7 @@
1088 from canonical.config import config
1089 from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet
1090 from canonical.launchpad.scripts import BufferLogger
1091-from canonical.librarian.ftests.harness import fillLibrarianFile
1092+from canonical.librarian.testing.server import fillLibrarianFile
1093 from canonical.testing import (
1094 DatabaseLayer,
1095 LaunchpadFunctionalLayer,
1096
1097=== modified file 'lib/lp/soyuz/scripts/tests/test_queue.py'
1098--- lib/lp/soyuz/scripts/tests/test_queue.py 2010-09-16 09:19:15 +0000
1099+++ lib/lp/soyuz/scripts/tests/test_queue.py 2010-10-03 20:53:47 +0000
1100@@ -32,7 +32,7 @@
1101 PackageUploadBuild,
1102 )
1103 from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet
1104-from canonical.librarian.ftests.harness import (
1105+from canonical.librarian.testing.server import (
1106 cleanupLibrarianFiles,
1107 fillLibrarianFile,
1108 )
1109
1110=== modified file 'lib/lp/soyuz/scripts/tests/test_sync_source.py'
1111--- lib/lp/soyuz/scripts/tests/test_sync_source.py 2010-09-16 19:00:35 +0000
1112+++ lib/lp/soyuz/scripts/tests/test_sync_source.py 2010-10-03 20:53:47 +0000
1113@@ -24,7 +24,7 @@
1114
1115 from canonical.config import config
1116 from canonical.launchpad.scripts import BufferLogger
1117-from canonical.librarian.ftests.harness import (
1118+from canonical.librarian.testing.server import (
1119 cleanupLibrarianFiles,
1120 fillLibrarianFile,
1121 )
1122
1123=== modified file 'lib/lp/soyuz/stories/soyuz/xx-queue-pages.txt'
1124--- lib/lp/soyuz/stories/soyuz/xx-queue-pages.txt 2010-08-24 12:05:25 +0000
1125+++ lib/lp/soyuz/stories/soyuz/xx-queue-pages.txt 2010-10-03 20:53:47 +0000
1126@@ -574,6 +574,6 @@
1127
1128 == Clean up ==
1129
1130- >>> from canonical.librarian.ftests.harness import cleanupLibrarianFiles
1131+ >>> from canonical.librarian.testing.server import cleanupLibrarianFiles
1132 >>> cleanupLibrarianFiles()
1133
1134
1135=== added file 'lib/lp/testing/fakelibrarian.py'
1136--- lib/lp/testing/fakelibrarian.py 1970-01-01 00:00:00 +0000
1137+++ lib/lp/testing/fakelibrarian.py 2010-10-03 20:53:47 +0000
1138@@ -0,0 +1,16 @@
1139+# Copyright 2010 Canonical Ltd. This software is licensed under the
1140+# GNU Affero General Public License version 3 (see the file LICENSE).
1141+
1142+"""See canonical.librarian.testing.fake."""
1143+
1144+import warnings
1145+
1146+from canonical.librarian.testing.fake import FakeLibrarian as _FakeLibrarian
1147+
1148+
1149+def FakeLibrarian(*args, **kwargs):
1150+ """Forward to the new home with a deprecation warning."""
1151+ warnings.warn("Stale import: please import FakeLibrarian from "
1152+ "canonical.librarian.testing.fake instead.", DeprecationWarning,
1153+ stacklevel=2)
1154+ return _FakeLibrarian(*args, **kwargs)
1155
1156=== modified file 'lib/lp/translations/doc/translationtemplatesbuildbehavior.txt'
1157--- lib/lp/translations/doc/translationtemplatesbuildbehavior.txt 2010-09-23 18:17:21 +0000
1158+++ lib/lp/translations/doc/translationtemplatesbuildbehavior.txt 2010-10-03 20:53:47 +0000
1159@@ -18,7 +18,8 @@
1160 ... JobStatus.FAILED))
1161
1162 >>> from canonical.buildd.tests import BuilddSlaveTestSetup
1163- >>> BuilddSlaveTestSetup().setUp()
1164+ >>> fixture = BuilddSlaveTestSetup()
1165+ >>> fixture.setUp()
1166
1167 >>> from canonical.librarian.interfaces import ILibrarianClient
1168 >>> from StringIO import StringIO
1169@@ -105,4 +106,4 @@
1170
1171 Clean up after this test.
1172
1173- >>> BuilddSlaveTestSetup().tearDown()
1174+ >>> fixture.tearDown()
1175
1176=== modified file 'lib/lp/translations/utilities/tests/test_file_importer.py'
1177--- lib/lp/translations/utilities/tests/test_file_importer.py 2010-09-18 09:14:59 +0000
1178+++ lib/lp/translations/utilities/tests/test_file_importer.py 2010-10-03 20:53:47 +0000
1179@@ -8,10 +8,10 @@
1180 from zope.component import getUtility
1181 from zope.security.proxy import removeSecurityProxy
1182
1183+from canonical.librarian.testing.fake import FakeLibrarian
1184 from canonical.testing import ZopelessDatabaseLayer
1185 from lp.registry.interfaces.person import IPersonSet
1186 from lp.testing import TestCaseWithFactory
1187-from lp.testing.fakelibrarian import FakeLibrarian
1188 from lp.translations.interfaces.translationgroup import TranslationPermission
1189 from lp.translations.interfaces.translationimporter import (
1190 OutdatedTranslationError,