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
=== modified file 'lib/canonical/buildd/tests/harness.py'
--- lib/canonical/buildd/tests/harness.py 2010-02-19 20:17:08 +0000
+++ lib/canonical/buildd/tests/harness.py 2010-10-03 20:53:47 +0000
@@ -61,7 +61,8 @@
61class BuilddSlaveTestSetup(TacTestSetup):61class BuilddSlaveTestSetup(TacTestSetup):
62 r"""Setup BuildSlave for use by functional tests62 r"""Setup BuildSlave for use by functional tests
6363
64 >>> BuilddSlaveTestSetup().setUp()64 >>> fixture = BuilddSlaveTestSetup()
65 >>> fixture.setUp()
6566
66 Make sure the server is running67 Make sure the server is running
6768
@@ -69,11 +70,11 @@
69 >>> s = xmlrpclib.Server('http://localhost:8221/rpc/')70 >>> s = xmlrpclib.Server('http://localhost:8221/rpc/')
70 >>> s.echo('Hello World')71 >>> s.echo('Hello World')
71 ['Hello World']72 ['Hello World']
72 >>> BuilddSlaveTestSetup().tearDown()73 >>> fixture.tearDown()
7374
74 Again for luck !75 Again for luck !
7576
76 >>> BuilddSlaveTestSetup().setUp()77 >>> fixture.setUp()
77 >>> s = xmlrpclib.Server('http://localhost:8221/rpc/')78 >>> s = xmlrpclib.Server('http://localhost:8221/rpc/')
7879
79 >>> s.echo('Hello World')80 >>> s.echo('Hello World')
@@ -95,7 +96,7 @@
95 >>> s.status()96 >>> s.status()
96 ['BuilderStatus.IDLE', '']97 ['BuilderStatus.IDLE', '']
9798
98 >>> BuilddSlaveTestSetup().tearDown()99 >>> fixture.tearDown()
99 """100 """
100 def setUpRoot(self):101 def setUpRoot(self):
101 """Recreate empty root directory to avoid problems."""102 """Recreate empty root directory to avoid problems."""
@@ -109,11 +110,7 @@
109 # When we are about running it seriously we need :110 # When we are about running it seriously we need :
110 # * install sbuild package111 # * install sbuild package
111 # * to copy the scripts for sbuild112 # * to copy the scripts for sbuild
112113 self.addCleanup(remove_tree, self.root)
113 def tearDown(self):
114 """Tear down the system normally and additionaly remove the root."""
115 TacTestSetup.tearDown(self)
116 remove_tree(self.root)
117114
118 @property115 @property
119 def root(self):116 def root(self):
120117
=== modified file 'lib/canonical/buildd/tests/test_buildd_slave.py'
--- lib/canonical/buildd/tests/test_buildd_slave.py 2010-05-20 11:19:56 +0000
+++ lib/canonical/buildd/tests/test_buildd_slave.py 2010-10-03 20:53:47 +0000
@@ -176,11 +176,12 @@
176176
177 def setUp(self):177 def setUp(self):
178 super(XMLRPCBuildDSlaveTests, self).setUp()178 super(XMLRPCBuildDSlaveTests, self).setUp()
179 BuilddSlaveTestSetup().setUp()179 self.slave = BuilddSlaveTestSetup()
180 self.slave.setUp()
180 self.server = xmlrpclib.Server('http://localhost:8221/rpc/')181 self.server = xmlrpclib.Server('http://localhost:8221/rpc/')
181182
182 def tearDown(self):183 def tearDown(self):
183 BuilddSlaveTestSetup().tearDown()184 self.slave.tearDown()
184 super(XMLRPCBuildDSlaveTests, self).tearDown()185 super(XMLRPCBuildDSlaveTests, self).tearDown()
185186
186 def test_build_unknown_builder(self):187 def test_build_unknown_builder(self):
187188
=== modified file 'lib/canonical/launchpad/daemons/tachandler.py'
--- lib/canonical/launchpad/daemons/tachandler.py 2010-08-20 20:31:18 +0000
+++ lib/canonical/launchpad/daemons/tachandler.py 2010-10-03 20:53:47 +0000
@@ -26,13 +26,26 @@
26import subprocess26import subprocess
27import sys27import sys
28import time28import time
29import warnings
2930
31from fixtures import Fixture
30from twisted.application import service32from twisted.application import service
31from twisted.python import log33from twisted.python import log
3234
33# This file is used by launchpad-buildd, so it cannot import any35# This file is used by launchpad-buildd, so it cannot import any
34# Launchpad code!36# Launchpad code!
3537
38def _kill_may_race(pid, signal_number):
39 """Kill a pid accepting that it may not exist."""
40 try:
41 os.kill(pid, signal_number)
42 except OSError, e:
43 if e.errno in (errno.ESRCH, errno.ECHILD):
44 # Process has already been killed.
45 return
46 # Some other issue (e.g. different user owns it)
47 raise
48
36def two_stage_kill(pid, poll_interval=0.1, num_polls=50):49def two_stage_kill(pid, poll_interval=0.1, num_polls=50):
37 """Kill process 'pid' with SIGTERM. If it doesn't die, SIGKILL it.50 """Kill process 'pid' with SIGTERM. If it doesn't die, SIGKILL it.
3851
@@ -42,12 +55,7 @@
42 :param num_polls: The number of polls to do before doing a SIGKILL.55 :param num_polls: The number of polls to do before doing a SIGKILL.
43 """56 """
44 # Kill the process.57 # Kill the process.
45 try:58 _kill_may_race(pid, SIGTERM)
46 os.kill(pid, SIGTERM)
47 except OSError, e:
48 if e.errno in (errno.ESRCH, errno.ECHILD):
49 # Process has already been killed.
50 return
5159
52 # Poll until the process has ended.60 # Poll until the process has ended.
53 for i in range(num_polls):61 for i in range(num_polls):
@@ -65,11 +73,7 @@
65 return73 return
6674
67 # The process is still around, so terminate it violently.75 # The process is still around, so terminate it violently.
68 try:76 _kill_may_race(pid, SIGKILL)
69 os.kill(pid, SIGKILL)
70 except OSError:
71 # Already terminated
72 pass
7377
7478
75def get_pid_from_file(pidfile_path):79def get_pid_from_file(pidfile_path):
@@ -120,17 +124,27 @@
120 """Error raised by TacTestSetup."""124 """Error raised by TacTestSetup."""
121125
122126
123class TacTestSetup:127class TacTestSetup(Fixture):
124 """Setup an TAC file as daemon for use by functional tests.128 """Setup an TAC file as daemon for use by functional tests.
125129
126 You can override setUpRoot to set up a root directory for the daemon.130 You must override setUpRoot to set up a root directory for the daemon.
127 """131 """
128132
129 def setUp(self, spew=False, umask=None):133 def setUp(self, spew=False, umask=None):
130 # Before we run, we want to make sure that we have cleaned up any134 Fixture.setUp(self)
131 # previous runs. Although tearDown() should have been called already,135 if get_pid_from_file(self.pidfile):
132 # we can't guarantee it.136 # An attempt to run while there was an existing live helper
133 self.tearDown()137 # was made. Note that this races with helpers which use unique
138 # roots, so when moving/eliminating this code check subclasses
139 # for workarounds and remove those too.
140 pid = get_pid_from_file(self.pidfile)
141 warnings.warn("Attempt to start Tachandler with an existing "
142 "instance (%d) running in %s." % (pid, self.pidfile),
143 DeprecationWarning, stacklevel=2)
144 two_stage_kill(pid)
145 if get_pid_from_file(self.pidfile):
146 raise TacException(
147 "Could not kill stale process %s." % (self.pidfile,))
134148
135 # setUp() watches the logfile to determine when the daemon has fully149 # setUp() watches the logfile to determine when the daemon has fully
136 # started. If it sees an old logfile, then it will find the LOG_MAGIC150 # started. If it sees an old logfile, then it will find the LOG_MAGIC
@@ -156,6 +170,7 @@
156 # stdout/stderr are written to.170 # stdout/stderr are written to.
157 proc = subprocess.Popen(args, stdout=subprocess.PIPE,171 proc = subprocess.Popen(args, stdout=subprocess.PIPE,
158 stderr=subprocess.STDOUT)172 stderr=subprocess.STDOUT)
173 self.addCleanup(self.killTac)
159 # XXX: JonathanLange 2008-03-19: This can raise EINTR. We should174 # XXX: JonathanLange 2008-03-19: This can raise EINTR. We should
160 # really catch it and try again if that happens.175 # really catch it and try again if that happens.
161 stdout = proc.stdout.read()176 stdout = proc.stdout.read()
@@ -201,7 +216,8 @@
201 self.tacfile, self.logfile, open(self.logfile).read()))216 self.tacfile, self.logfile, open(self.logfile).read()))
202217
203 def tearDown(self):218 def tearDown(self):
204 self.killTac()219 # For compatibility - migrate to cleanUp.
220 self.cleanUp()
205221
206 def killTac(self):222 def killTac(self):
207 """Kill the TAC file if it is running."""223 """Kill the TAC file if it is running."""
208224
=== modified file 'lib/canonical/launchpad/doc/old-testing.txt'
--- lib/canonical/launchpad/doc/old-testing.txt 2009-08-13 15:12:16 +0000
+++ lib/canonical/launchpad/doc/old-testing.txt 2010-10-03 20:53:47 +0000
@@ -253,14 +253,15 @@
253You probably really want LaunchpadFunctionalTestSetup so you can access253You probably really want LaunchpadFunctionalTestSetup so you can access
254the Librarian as a Utility.254the Librarian as a Utility.
255255
256>>> from canonical.librarian.ftests.harness import LibrarianTestSetup256>>> from canonical.librarian.testing.server import LibrarianTestSetup
257>>> from canonical.launchpad.ftests import login, ANONYMOUS257>>> from canonical.launchpad.ftests import login, ANONYMOUS
258>>> from zope.app import zapi258>>> from zope.app import zapi
259>>> from canonical.librarian.interfaces import ILibrarianClient259>>> from canonical.librarian.interfaces import ILibrarianClient
260>>> from StringIO import StringIO260>>> from StringIO import StringIO
261261
262>>> LaunchpadFunctionalTestSetup().setUp()262>>> LaunchpadFunctionalTestSetup().setUp()
263>>> LibrarianTestSetup().setUp()263>>> librarian = LibrarianTestSetup()
264>>> librarian.setUp()
264>>> login(ANONYMOUS)265>>> login(ANONYMOUS)
265266
266>>> some_content = StringIO()267>>> some_content = StringIO()
@@ -283,7 +284,7 @@
283>>> data == some_content.getvalue()284>>> data == some_content.getvalue()
284True285True
285286
286>>> LibrarianTestSetup().tearDown()287>>> librarian.tearDown()
287>>> LaunchpadFunctionalTestSetup().tearDown()288>>> LaunchpadFunctionalTestSetup().tearDown()
288289
289>>> from canonical.testing import reset_logging290>>> from canonical.testing import reset_logging
290291
=== modified file 'lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py'
--- lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py 2010-08-20 20:31:18 +0000
+++ lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py 2010-10-03 20:53:47 +0000
@@ -18,7 +18,7 @@
18from canonical.config import config18from canonical.config import config
19from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities19from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities
20from canonical.launchpad.webapp.errorlog import ErrorReportingUtility20from canonical.launchpad.webapp.errorlog import ErrorReportingUtility
21from canonical.librarian.ftests.harness import fillLibrarianFile21from canonical.librarian.testing.server import fillLibrarianFile
22from canonical.librarian.interfaces import LibrarianServerError22from canonical.librarian.interfaces import LibrarianServerError
23from canonical.testing import (23from canonical.testing import (
24 BaseLayer,24 BaseLayer,
2525
=== removed file 'lib/canonical/librarian/ftests/test_harness.py'
--- lib/canonical/librarian/ftests/test_harness.py 2010-07-14 14:11:15 +0000
+++ lib/canonical/librarian/ftests/test_harness.py 1970-01-01 00:00:00 +0000
@@ -1,13 +0,0 @@
1# Copyright 2009 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3
4__metaclass__ = type
5
6import doctest
7
8def test_suite():
9 return doctest.DocTestSuite(
10 'canonical.librarian.ftests.harness',
11 optionflags=doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
12 )
13
140
=== modified file 'lib/canonical/librarian/librariangc.py'
--- lib/canonical/librarian/librariangc.py 2010-04-23 01:48:11 +0000
+++ lib/canonical/librarian/librariangc.py 2010-10-03 20:53:47 +0000
@@ -632,8 +632,9 @@
632 dirnames.remove('incoming')632 dirnames.remove('incoming')
633 if 'lost+found' in dirnames:633 if 'lost+found' in dirnames:
634 dirnames.remove('lost+found')634 dirnames.remove('lost+found')
635 if 'librarian.pid' in filenames:635 filenames = set(filenames)
636 filenames.remove('librarian.pid')636 filenames.discard('librarian.pid')
637 filenames.discard('librarian.log')
637638
638 for dirname in dirnames[:]:639 for dirname in dirnames[:]:
639 if len(dirname) != 2:640 if len(dirname) != 2:
@@ -650,7 +651,7 @@
650 # We need everything in order to ensure we visit files in the651 # We need everything in order to ensure we visit files in the
651 # same order we retrieve wanted files from the database.652 # same order we retrieve wanted files from the database.
652 dirnames.sort()653 dirnames.sort()
653 filenames.sort()654 filenames = sorted(filenames)
654655
655 # Noise in the storage area, or maybe we are looking at the wrong656 # Noise in the storage area, or maybe we are looking at the wrong
656 # path?657 # path?
657658
=== added directory 'lib/canonical/librarian/testing'
=== added file 'lib/canonical/librarian/testing/__init__.py'
--- lib/canonical/librarian/testing/__init__.py 1970-01-01 00:00:00 +0000
+++ lib/canonical/librarian/testing/__init__.py 2010-10-03 20:53:47 +0000
@@ -0,0 +1,6 @@
1# Copyright 2010 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3
4"""Test support for working with the librarian."""
5
6__metaclass__ = type
07
=== renamed file 'lib/lp/testing/fakelibrarian.py' => 'lib/canonical/librarian/testing/fake.py'
=== renamed file 'lib/canonical/librarian/ftests/harness.py' => 'lib/canonical/librarian/testing/server.py'
--- lib/canonical/librarian/ftests/harness.py 2010-02-02 16:52:46 +0000
+++ lib/canonical/librarian/testing/server.py 2010-10-03 20:53:47 +0000
@@ -7,21 +7,30 @@
7__all__ = [7__all__ = [
8 'cleanupLibrarianFiles',8 'cleanupLibrarianFiles',
9 'fillLibrarianFile',9 'fillLibrarianFile',
10 'LibrarianServerFixture',
10 'LibrarianTestSetup',11 'LibrarianTestSetup',
11 ]12 ]
1213
13import os14import os
14import shutil15import shutil
15import tempfile16import tempfile
17import warnings
18
19from fixtures import Fixture
1620
17import canonical21import canonical
18from canonical.config import config22from canonical.config import config
19from canonical.launchpad.daemons.tachandler import TacException, TacTestSetup23from canonical.launchpad.daemons.tachandler import (
24 get_pid_from_file,
25 TacException,
26 TacTestSetup,
27 two_stage_kill,
28 )
20from canonical.librarian.storage import _relFileLocation29from canonical.librarian.storage import _relFileLocation
2130
2231
23class LibrarianTestSetup:32class LibrarianServerFixture(TacTestSetup):
24 """Set up librarian servers for use by functional tests.33 """Librarian server fixture.
2534
26 >>> from urllib import urlopen35 >>> from urllib import urlopen
27 >>> from canonical.config import config36 >>> from canonical.config import config
@@ -33,7 +42,8 @@
33 ... config.librarian.restricted_download_host,42 ... config.librarian.restricted_download_host,
34 ... config.librarian.restricted_download_port)43 ... config.librarian.restricted_download_port)
3544
36 >>> LibrarianTestSetup().setUp()45 >>> fixture = LibrarianServerFixture()
46 >>> fixture.setUp()
3747
38 Set a socket timeout, so that this test cannot hang indefinitely.48 Set a socket timeout, so that this test cannot hang indefinitely.
3949
@@ -42,8 +52,8 @@
42 None52 None
43 >>> socket.setdefaulttimeout(1)53 >>> socket.setdefaulttimeout(1)
4454
45 After setUp() is called, two librarian instances are started. The55 After setUp() is called, two librarian ports are available:
46 regular one:56 The regular one:
4757
48 >>> 'Copyright' in urlopen(librarian_url).read()58 >>> 'Copyright' in urlopen(librarian_url).read()
49 True59 True
@@ -59,9 +69,9 @@
59 >>> os.path.isdir(config.librarian_server.root)69 >>> os.path.isdir(config.librarian_server.root)
60 True70 True
6171
62 After tearDown() is called, both instances are shut down:72 After tearDown() is called, both ports are closed:
6373
64 >>> LibrarianTestSetup().tearDown()74 >>> fixture.tearDown()
6575
66 >>> urlopen(librarian_url).read()76 >>> urlopen(librarian_url).read()
67 Traceback (most recent call last):77 Traceback (most recent call last):
@@ -80,39 +90,73 @@
8090
81 That fixture can be started and stopped multiple time in succession:91 That fixture can be started and stopped multiple time in succession:
8292
83 >>> LibrarianTestSetup().setUp()93 >>> fixture.setUp()
84 >>> 'Copyright' in urlopen(librarian_url).read()94 >>> 'Copyright' in urlopen(librarian_url).read()
85 True95 True
8696
87 Tidy up.97 Tidy up.
8898
89 >>> LibrarianTestSetup().tearDown()99 >>> fixture.tearDown()
90 >>> socket.setdefaulttimeout(None)100 >>> socket.setdefaulttimeout(None)
101
102 :ivar: pid pid of the external process.
91 """103 """
92104
105 def __init__(self):
106 Fixture.__init__(self)
107 self._pid = None
108 # Track whether the fixture has been setup or not.
109 self._setup = False
110
93 def setUp(self):111 def setUp(self):
94 """Start both librarian instances."""112 """Start both librarian instances."""
95 if (os.environ.get('LP_PERSISTENT_TEST_SERVICES') is not None and113 if (self._persistent_servers() and self.pid):
96 os.path.exists(TacLibrarianTestSetup().pidfile)):
97 return114 return
98 self.setUpRoot()115 else:
116 # self.pid may have been evaluated - nuke it.
117 self._pid = None
118 # The try:except here can be removed if someone audits the callers to
119 # make sure that they call cleanUp if setUp fails.
99 try:120 try:
100 TacLibrarianTestSetup().setUp()121 TacTestSetup.setUp(self)
101 except TacException:122 except TacException:
102 # Remove the directory usually removed in tearDown.123 self.cleanUp()
103 self.tearDownRoot()
104 raise124 raise
125 else:
126 self._pid = self._read_pid()
127 self._setup = True
128 self.addCleanup(setattr, self, '_setup', False)
105129
106 def tearDown(self):130 def cleanUp(self):
107 """Shut downs both librarian instances."""131 """Shut downs both librarian instances."""
108 if os.environ.get('LP_PERSISTENT_TEST_SERVICES') is not None:132 if self._persistent_servers():
109 return133 return
110 TacLibrarianTestSetup().tearDown()134 if not self._setup:
111 self.tearDownRoot()135 warnings.warn("Attempt to tearDown inactive fixture.",
136 DeprecationWarning, stacklevel=3)
137 return
138 TacTestSetup.cleanUp(self)
112139
113 def clear(self):140 def clear(self):
114 """Clear all files from the Librarian"""141 """Clear all files from the Librarian"""
115 cleanupLibrarianFiles()142 # Make this smarter if our tests create huge numbers of files
143 root = config.librarian_server.root
144 if os.path.isdir(os.path.join(root, '00')):
145 shutil.rmtree(os.path.join(root, '00'))
146
147 @property
148 def pid(self):
149 if self._pid:
150 return self._pid
151 if self._persistent_servers():
152 self._pid = self._read_pid()
153 return self._pid
154
155 def _read_pid(self):
156 return get_pid_from_file(self.pidfile)
157
158 def _persistent_servers(self):
159 return os.environ.get('LP_PERSISTENT_TEST_SERVICES') is not None
116160
117 @property161 @property
118 def root(self):162 def root(self):
@@ -126,26 +170,13 @@
126 if os.path.exists(self.root):170 if os.path.exists(self.root):
127 self.tearDownRoot()171 self.tearDownRoot()
128 os.makedirs(self.root, 0700)172 os.makedirs(self.root, 0700)
173 self.addCleanup(self.tearDownRoot)
129174
130 def tearDownRoot(self):175 def tearDownRoot(self):
131 """Remove the librarian root archive."""176 """Remove the librarian root archive."""
132 if os.path.isdir(self.root):177 if os.path.isdir(self.root):
133 shutil.rmtree(self.root)178 shutil.rmtree(self.root)
134179
135
136class TacLibrarianTestSetup(TacTestSetup):
137 """Start the regular librarian instance."""
138
139 def setUpRoot(self):
140 """Taken care by LibrarianTestSetup."""
141
142 def tearDownRoot(self):
143 """Taken care by LibrarianTestSetup."""
144
145 @property
146 def root(self):
147 return config.librarian_server.root
148
149 @property180 @property
150 def tacfile(self):181 def tacfile(self):
151 return os.path.abspath(os.path.join(182 return os.path.abspath(os.path.join(
@@ -158,20 +189,18 @@
158 return os.path.join(self.root, 'librarian.pid')189 return os.path.join(self.root, 'librarian.pid')
159190
160 @property191 @property
161 def _log_directory(self):
162 # Since the root gets deleted after the tests complete, and since we
163 # may still want to access the log file for post-mortem debugging, put
164 # the log file in the parent directory of root, or the temporary
165 # directory if that doesn't exist.
166 log_directory = os.path.dirname(self.root)
167 if os.path.isdir(log_directory):
168 return log_directory
169 else:
170 return tempfile.tempdir
171
172 @property
173 def logfile(self):192 def logfile(self):
174 return os.path.join(self._log_directory, 'librarian.log')193 # Store the log in the server root; if its wanted after a test, that
194 # test can use addDetail to grab the log and include it in its
195 # error.
196 return os.path.join(self.root, 'librarian.log')
197
198
199_global_fixture = LibrarianServerFixture()
200
201def LibrarianTestSetup():
202 """Support the stateless lie."""
203 return _global_fixture
175204
176205
177def fillLibrarianFile(fileid, content='Fake Content'):206def fillLibrarianFile(fileid, content='Fake Content'):
@@ -186,9 +215,7 @@
186 libfile.write(content)215 libfile.write(content)
187 libfile.close()216 libfile.close()
188217
218
189def cleanupLibrarianFiles():219def cleanupLibrarianFiles():
190 """Remove all librarian files present in disk."""220 """Remove all librarian files present in disk."""
191 # Make this smarter if our tests create huge numbers of files221 _global_fixture.clear()
192 root = config.librarian_server.root
193 if os.path.isdir(os.path.join(root, '00')):
194 shutil.rmtree(os.path.join(root, '00'))
195222
=== added directory 'lib/canonical/librarian/testing/tests'
=== added file 'lib/canonical/librarian/testing/tests/__init__.py'
--- lib/canonical/librarian/testing/tests/__init__.py 1970-01-01 00:00:00 +0000
+++ lib/canonical/librarian/testing/tests/__init__.py 2010-10-03 20:53:47 +0000
@@ -0,0 +1,6 @@
1# Copyright 2010 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3
4"""Tests of the librarian test support code."""
5
6__metaclass__ = type
07
=== renamed file 'lib/lp/testing/tests/test_fakelibrarian.py' => 'lib/canonical/librarian/testing/tests/test_fakelibrarian.py'
--- lib/lp/testing/tests/test_fakelibrarian.py 2010-09-18 09:14:59 +0000
+++ lib/canonical/librarian/testing/tests/test_fakelibrarian.py 2010-10-03 20:53:47 +0000
@@ -17,6 +17,7 @@
17 LibraryFileAliasSet,17 LibraryFileAliasSet,
18 )18 )
19from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet19from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet
20from canonical.librarian.testing.fake import FakeLibrarian
20from canonical.launchpad.webapp.testing import verifyObject21from canonical.launchpad.webapp.testing import verifyObject
21from canonical.librarian.client import LibrarianClient22from canonical.librarian.client import LibrarianClient
22from canonical.librarian.interfaces import ILibrarianClient23from canonical.librarian.interfaces import ILibrarianClient
@@ -25,7 +26,6 @@
25 LaunchpadFunctionalLayer,26 LaunchpadFunctionalLayer,
26 )27 )
27from lp.testing import TestCaseWithFactory28from lp.testing import TestCaseWithFactory
28from lp.testing.fakelibrarian import FakeLibrarian
2929
3030
31class LibraryAccessScenarioMixin:31class LibraryAccessScenarioMixin:
3232
=== added file 'lib/canonical/librarian/testing/tests/test_server_fixture.py'
--- lib/canonical/librarian/testing/tests/test_server_fixture.py 1970-01-01 00:00:00 +0000
+++ lib/canonical/librarian/testing/tests/test_server_fixture.py 2010-10-03 20:53:47 +0000
@@ -0,0 +1,29 @@
1# Copyright 2010 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3
4"""Test the LibrarianServerFixture."""
5
6__metaclass__ = type
7
8import doctest
9import unittest
10
11from canonical.librarian.testing.server import LibrarianServerFixture
12from lp.testing import TestCase
13
14def test_suite():
15 result = unittest.TestLoader().loadTestsFromName(__name__)
16 result.addTest(doctest.DocTestSuite(
17 'canonical.librarian.testing.server',
18 optionflags=doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
19 ))
20 return result
21
22
23class TestLibrarianServerFixture(TestCase):
24
25 def test_on_init_no_pid(self):
26 fixture = LibrarianServerFixture()
27 if fixture._persistent_servers():
28 self.skip('persistent server running.')
29 self.assertEqual(None, fixture.pid)
030
=== modified file 'lib/canonical/librarian/tests/test_sigdumpmem.py'
--- lib/canonical/librarian/tests/test_sigdumpmem.py 2010-04-20 14:27:26 +0000
+++ lib/canonical/librarian/tests/test_sigdumpmem.py 2010-10-03 20:53:47 +0000
@@ -9,7 +9,7 @@
9import time9import time
1010
11from canonical.librarian.interfaces import DUMP_FILE, SIGDUMPMEM11from canonical.librarian.interfaces import DUMP_FILE, SIGDUMPMEM
12from canonical.librarian.ftests.harness import TacLibrarianTestSetup12from canonical.librarian.testing.server import LibrarianTestSetup
13from canonical.testing.layers import LibrarianLayer13from canonical.testing.layers import LibrarianLayer
14from lp.testing import TestCase14from lp.testing import TestCase
1515
@@ -23,9 +23,10 @@
23 os.unlink(DUMP_FILE)23 os.unlink(DUMP_FILE)
24 self.assertFalse(os.path.exists(DUMP_FILE))24 self.assertFalse(os.path.exists(DUMP_FILE))
2525
26 # We rely on the fact that the librarian was started by the test26 # Use the global instance used by the Layer machinery; it would
27 # runner here as we use the LibrarianLayer.27 # be nice to be able to access those without globals / magical
28 pid = int(open(TacLibrarianTestSetup().pidfile).read())28 # 'constructors'.
29 pid = LibrarianTestSetup().pid
2930
30 # Send the signal and ensure the dump file is created.31 # Send the signal and ensure the dump file is created.
31 os.kill(pid, SIGDUMPMEM)32 os.kill(pid, SIGDUMPMEM)
3233
=== modified file 'lib/canonical/testing/layers.py'
--- lib/canonical/testing/layers.py 2010-09-29 05:53:47 +0000
+++ lib/canonical/testing/layers.py 2010-10-03 20:53:47 +0000
@@ -85,6 +85,7 @@
85from zope.app.publication.httpfactory import chooseClasses85from zope.app.publication.httpfactory import chooseClasses
86from zope.app.testing.functional import FunctionalTestSetup, ZopePublication86from zope.app.testing.functional import FunctionalTestSetup, ZopePublication
87from zope.component import getUtility, provideUtility87from zope.component import getUtility, provideUtility
88from zope.component import globalregistry
88from zope.component.interfaces import ComponentLookupError89from zope.component.interfaces import ComponentLookupError
89from zope.security.management import getSecurityPolicy90from zope.security.management import getSecurityPolicy
90from zope.security.simplepolicies import PermissiveSecurityPolicy91from zope.security.simplepolicies import PermissiveSecurityPolicy
@@ -116,7 +117,7 @@
116from canonical.lazr.timeout import (117from canonical.lazr.timeout import (
117 get_default_timeout_function, set_default_timeout_function)118 get_default_timeout_function, set_default_timeout_function)
118from canonical.lp import initZopeless119from canonical.lp import initZopeless
119from canonical.librarian.ftests.harness import LibrarianTestSetup120from canonical.librarian.testing.server import LibrarianTestSetup
120from canonical.testing import reset_logging121from canonical.testing import reset_logging
121from canonical.testing.profiled import profiled122from canonical.testing.profiled import profiled
122from canonical.testing.smtpd import SMTPController123from canonical.testing.smtpd import SMTPController
@@ -262,7 +263,6 @@
262 # about killing memcached - just do it quickly.263 # about killing memcached - just do it quickly.
263 if not BaseLayer.persist_test_services:264 if not BaseLayer.persist_test_services:
264 kill_by_pidfile(MemcachedLayer.getPidFile(), num_polls=0)265 kill_by_pidfile(MemcachedLayer.getPidFile(), num_polls=0)
265 LibrarianTestSetup().tearDown()
266 # Kill any database left lying around from a previous test run.266 # Kill any database left lying around from a previous test run.
267 try:267 try:
268 DatabaseLayer.connect().close()268 DatabaseLayer.connect().close()
@@ -851,6 +851,24 @@
851 @profiled851 @profiled
852 def tearDown(cls):852 def tearDown(cls):
853 pass853 pass
854
855 @classmethod
856 def tearDownHelper(cls):
857 """Helper for when LaunchpadLayer is mixed with unteardownable layers.
858
859 E.g. FunctionalLayer causes other layer tearDown to not occur, which is
860 why atexit is used, but because test runners delegate rather than
861 returning, the librarian and other servers are only killed *at the end
862 of the whole test run*, which leads to multiple instances running, so
863 we manually run the teardown for these layers.
864 """
865 try:
866 MemcachedLayer.tearDown()
867 finally:
868 try:
869 LibrarianLayer.tearDown()
870 finally:
871 DatabaseLayer.tearDown()
854872
855 @classmethod873 @classmethod
856 @profiled874 @profiled
@@ -1212,7 +1230,7 @@
1212 @classmethod1230 @classmethod
1213 @profiled1231 @profiled
1214 def tearDown(cls):1232 def tearDown(cls):
1215 pass1233 LaunchpadLayer.tearDownHelper()
12161234
1217 @classmethod1235 @classmethod
1218 @profiled1236 @profiled
@@ -1314,13 +1332,15 @@
1314 # XXX flacoste 2006-10-25 bug=68189: This should be configured from1332 # XXX flacoste 2006-10-25 bug=68189: This should be configured from
1315 # ZCML but execute_zcml_for_scripts() doesn't cannot support a1333 # ZCML but execute_zcml_for_scripts() doesn't cannot support a
1316 # different testing configuration.1334 # different testing configuration.
1317 provideUtility(TestMailBox(), IMailBox)1335 cls._mailbox = TestMailBox()
1336 provideUtility(cls._mailbox, IMailBox)
13181337
1319 @classmethod1338 @classmethod
1320 @profiled1339 @profiled
1321 def tearDown(cls):1340 def tearDown(cls):
1322 # Signal Layer cannot be torn down fully1341 if not globalregistry.base.unregisterUtility(cls._mailbox):
1323 raise NotImplementedError1342 raise NotImplementedError('failed to unregister mailbox')
1343 LaunchpadLayer.tearDownHelper()
13241344
1325 @classmethod1345 @classmethod
1326 @profiled1346 @profiled
13271347
=== modified file 'lib/canonical/zeca/ftests/harness.py'
--- lib/canonical/zeca/ftests/harness.py 2009-08-20 13:52:29 +0000
+++ lib/canonical/zeca/ftests/harness.py 2010-10-03 20:53:47 +0000
@@ -17,7 +17,8 @@
17class ZecaTestSetup(TacTestSetup):17class ZecaTestSetup(TacTestSetup):
18 r"""Setup a zeca for use by functional tests18 r"""Setup a zeca for use by functional tests
1919
20 >>> ZecaTestSetup().setUp()20 >>> fixture = ZecaTestSetup()
21 >>> fixture.setUp()
2122
22 Make sure the server is running23 Make sure the server is running
2324
@@ -98,17 +99,17 @@
98 <title>Submit a key</title>99 <title>Submit a key</title>
99 ...100 ...
100101
101 >>> ZecaTestSetup().tearDown()102 >>> fixture.tearDown()
102103
103 And again for luck104 And again for luck
104105
105 >>> ZecaTestSetup().setUp()106 >>> fixture.setUp()
106107
107 >>> print urlopen(root_url).readline()108 >>> print urlopen(root_url).readline()
108 Copyright 2004-2009 Canonical Ltd.109 Copyright 2004-2009 Canonical Ltd.
109 <BLANKLINE>110 <BLANKLINE>
110111
111 >>> ZecaTestSetup().tearDown()112 >>> fixture.tearDown()
112 """113 """
113 def setUpRoot(self):114 def setUpRoot(self):
114 """Recreate root directory and copy needed keys"""115 """Recreate root directory and copy needed keys"""
115116
=== modified file 'lib/lp/archiveuploader/tests/__init__.py'
--- lib/lp/archiveuploader/tests/__init__.py 2010-09-16 12:27:46 +0000
+++ lib/lp/archiveuploader/tests/__init__.py 2010-10-03 20:53:47 +0000
@@ -22,7 +22,7 @@
2222
23from zope.component import getGlobalSiteManager23from zope.component import getGlobalSiteManager
2424
25from canonical.librarian.ftests.harness import fillLibrarianFile25from canonical.librarian.testing.server import fillLibrarianFile
26from lp.archiveuploader.uploadpolicy import (26from lp.archiveuploader.uploadpolicy import (
27 AbstractUploadPolicy,27 AbstractUploadPolicy,
28 findPolicyByName,28 findPolicyByName,
2929
=== modified file 'lib/lp/bugs/browser/bugtarget.py'
--- lib/lp/bugs/browser/bugtarget.py 2010-09-25 14:29:32 +0000
+++ lib/lp/bugs/browser/bugtarget.py 2010-10-03 20:53:47 +0000
@@ -588,7 +588,8 @@
588 bug.linkAttachment(588 bug.linkAttachment(
589 owner=self.user, file_alias=attachment['file_alias'],589 owner=self.user, file_alias=attachment['file_alias'],
590 description=attachment['description'],590 description=attachment['description'],
591 comment=attachment_comment)591 comment=attachment_comment,
592 send_notifications=False)
592 notifications.append(593 notifications.append(
593 'The file "%s" was attached to the bug report.' %594 'The file "%s" was attached to the bug report.' %
594 cgi.escape(attachment['file_alias'].filename))595 cgi.escape(attachment['file_alias'].filename))
595596
=== modified file 'lib/lp/bugs/model/bug.py'
--- lib/lp/bugs/model/bug.py 2010-09-24 14:29:15 +0000
+++ lib/lp/bugs/model/bug.py 2010-10-03 20:53:47 +0000
@@ -1218,13 +1218,18 @@
1218 owner, filealias, comment, is_patch, description)1218 owner, filealias, comment, is_patch, description)
12191219
1220 def linkAttachment(self, owner, file_alias, comment, is_patch=False,1220 def linkAttachment(self, owner, file_alias, comment, is_patch=False,
1221 description=None):1221 description=None, send_notifications=True):
1222 """See `IBug`.1222 """See `IBug`.
12231223
1224 This method should only be called by addAttachment() and1224 This method should only be called by addAttachment() and
1225 FileBugViewBase.submit_bug_action, otherwise1225 FileBugViewBase.submit_bug_action, otherwise
1226 we may get inconsistent settings of bug.private and1226 we may get inconsistent settings of bug.private and
1227 file_alias.restricted.1227 file_alias.restricted.
1228
1229 :param send_notifications: Control sending of notifications for this
1230 attachment. This is disabled when adding attachments from 'extra
1231 data' in the filebug form, because that triggered hundreds of DB
1232 inserts and thus timeouts. Defaults to sending notifications.
1228 """1233 """
1229 if is_patch:1234 if is_patch:
1230 attach_type = BugAttachmentType.PATCH1235 attach_type = BugAttachmentType.PATCH
@@ -1244,7 +1249,8 @@
12441249
1245 return getUtility(IBugAttachmentSet).create(1250 return getUtility(IBugAttachmentSet).create(
1246 bug=self, filealias=file_alias, attach_type=attach_type,1251 bug=self, filealias=file_alias, attach_type=attach_type,
1247 title=title, message=message, send_notifications=True)1252 title=title, message=message,
1253 send_notifications=send_notifications)
12481254
1249 def hasBranch(self, branch):1255 def hasBranch(self, branch):
1250 """See `IBug`."""1256 """See `IBug`."""
12511257
=== modified file 'lib/lp/buildmaster/tests/test_builder.py'
--- lib/lp/buildmaster/tests/test_builder.py 2010-09-23 12:35:21 +0000
+++ lib/lp/buildmaster/tests/test_builder.py 2010-10-03 20:53:47 +0000
@@ -495,12 +495,12 @@
495 """495 """
496 tachandler = BuilddSlaveTestSetup()496 tachandler = BuilddSlaveTestSetup()
497 tachandler.setUp()497 tachandler.setUp()
498 self.addCleanup(tachandler.tearDown)
498 def addLogFile(exc_info):499 def addLogFile(exc_info):
499 self.addDetail(500 self.addDetail(
500 'xmlrpc-log-file',501 'xmlrpc-log-file',
501 Content(UTF8_TEXT, lambda: open(tachandler.logfile, 'r').read()))502 Content(UTF8_TEXT, lambda: open(tachandler.logfile, 'r').read()))
502 self.addOnException(addLogFile)503 self.addOnException(addLogFile)
503 self.addCleanup(tachandler.tearDown)
504 return tachandler504 return tachandler
505505
506 def getClientSlave(self):506 def getClientSlave(self):
507507
=== modified file 'lib/lp/buildmaster/tests/test_manager.py'
--- lib/lp/buildmaster/tests/test_manager.py 2010-09-22 11:26:19 +0000
+++ lib/lp/buildmaster/tests/test_manager.py 2010-10-03 20:53:47 +0000
@@ -610,7 +610,8 @@
610 """610 """
611 TwistedLayer.testSetUp()611 TwistedLayer.testSetUp()
612 TrialTestCase.setUp(self)612 TrialTestCase.setUp(self)
613 BuilddSlaveTestSetup().setUp()613 self.slave = BuilddSlaveTestSetup()
614 self.slave.setUp()
614615
615 # Creating the required chroots needed for dispatching.616 # Creating the required chroots needed for dispatching.
616 login('foo.bar@canonical.com')617 login('foo.bar@canonical.com')
@@ -622,7 +623,7 @@
622 login(ANONYMOUS)623 login(ANONYMOUS)
623624
624 def tearDown(self):625 def tearDown(self):
625 BuilddSlaveTestSetup().tearDown()626 self.slave.tearDown()
626 TrialTestCase.tearDown(self)627 TrialTestCase.tearDown(self)
627 TwistedLayer.testTearDown()628 TwistedLayer.testTearDown()
628629
@@ -1152,8 +1153,9 @@
11521153
1153 def testBuilddManagerRuns(self):1154 def testBuilddManagerRuns(self):
1154 # The `buildd-manager.tac` starts and stops correctly.1155 # The `buildd-manager.tac` starts and stops correctly.
1155 BuilddManagerTestSetup().setUp()1156 fixture = BuilddManagerTestSetup()
1156 BuilddManagerTestSetup().tearDown()1157 fixture.setUp()
1158 fixture.tearDown()
11571159
1158 # XXX Julian 2010-08-06 bug=6142751160 # XXX Julian 2010-08-06 bug=614275
1159 # These next 2 tests are in the wrong place, they should be near the1161 # These next 2 tests are in the wrong place, they should be near the
@@ -1164,10 +1166,8 @@
11641166
1165 def disabled_testBuilddManagerLogging(self):1167 def disabled_testBuilddManagerLogging(self):
1166 # The twistd process logs as execpected.1168 # The twistd process logs as execpected.
1167 test_setup = BuilddManagerTestSetup()1169 test_setup = self.useFixture(BuilddManagerTestSetup())
1168 logfilepath = test_setup.logfile1170 logfilepath = test_setup.logfile
1169 test_setup.setUp()
1170 self.addCleanup(test_setup.tearDown)
1171 # The process logs to its logfile.1171 # The process logs to its logfile.
1172 self.assertTrue(is_file_growing(logfilepath))1172 self.assertTrue(is_file_growing(logfilepath))
1173 # After rotating the log, the process keeps using the old file, no1173 # After rotating the log, the process keeps using the old file, no
@@ -1192,8 +1192,7 @@
1192 # Prefill the log file to just under 1000000 bytes.1192 # Prefill the log file to just under 1000000 bytes.
1193 test_setup.precreateLogfile(1193 test_setup.precreateLogfile(
1194 "2010-07-27 12:36:54+0200 [-] Starting scanning cycle.\n", 18518)1194 "2010-07-27 12:36:54+0200 [-] Starting scanning cycle.\n", 18518)
1195 test_setup.setUp()1195 self.useFixture(test_setup)
1196 self.addCleanup(test_setup.tearDown)
1197 # The process logs to the logfile.1196 # The process logs to the logfile.
1198 self.assertTrue(is_file_growing(logfilepath))1197 self.assertTrue(is_file_growing(logfilepath))
1199 # No rotation occured.1198 # No rotation occured.
12001199
=== modified file 'lib/lp/hardwaredb/doc/hwdb-submission.txt'
--- lib/lp/hardwaredb/doc/hwdb-submission.txt 2010-04-01 04:05:10 +0000
+++ lib/lp/hardwaredb/doc/hwdb-submission.txt 2010-10-03 20:53:47 +0000
@@ -253,7 +253,7 @@
253let's add one. Let's add invalid data in order to see how invalid253let's add one. Let's add invalid data in order to see how invalid
254submissions are processed.254submissions are processed.
255255
256 >>> from canonical.librarian.ftests.harness import fillLibrarianFile256 >>> from canonical.librarian.testing.server import fillLibrarianFile
257 >>> submission = submission_set.getBySubmissionKey('test_submission_id_1')257 >>> submission = submission_set.getBySubmissionKey('test_submission_id_1')
258 >>> fillLibrarianFile(258 >>> fillLibrarianFile(
259 ... submission.raw_submission.id, 'nonsense')259 ... submission.raw_submission.id, 'nonsense')
260260
=== modified file 'lib/lp/poppy/tests/test_poppy.py'
--- lib/lp/poppy/tests/test_poppy.py 2010-08-20 20:31:18 +0000
+++ lib/lp/poppy/tests/test_poppy.py 2010-10-03 20:53:47 +0000
@@ -151,17 +151,27 @@
151151
152152
153class PoppyTac(TacTestSetup):153class PoppyTac(TacTestSetup):
154 """A SFTP Poppy server fixture.
155
156 This class has two distinct roots:
157 - the POPPY_ROOT where the test looks for uploaded output.
158 - the server root where ssh keys etc go.
159 """
154160
155 def __init__(self, fs_root):161 def __init__(self, fs_root):
156 os.environ['POPPY_ROOT'] = fs_root162 self.fs_root = fs_root
157 self.setUpRoot()163 # The setUp check for stale pids races with self._root being assigned,
164 # so store a plausible path temporarily. Once all fixtures use unique
165 # environments this can go.
166 self._root = '/var/does/not/exist'
167
168 def setUp(self):
169 os.environ['POPPY_ROOT'] = self.fs_root
158 super(PoppyTac, self).setUp(umask='0')170 super(PoppyTac, self).setUp(umask='0')
159171
160 def setUpRoot(self):172 def setUpRoot(self):
161 self._root = tempfile.mkdtemp()173 self._root = tempfile.mkdtemp()
162174 self.addCleanup(shutil.rmtree, self.root)
163 def tearDownRoot(self):
164 shutil.rmtree(self._root)
165175
166 @property176 @property
167 def root(self):177 def root(self):
@@ -174,7 +184,7 @@
174184
175 @property185 @property
176 def logfile(self):186 def logfile(self):
177 return os.path.join('/tmp', 'poppy-sftp.log')187 return os.path.join(self.root, 'poppy-sftp.log')
178188
179 @property189 @property
180 def pidfile(self):190 def pidfile(self):
181191
=== modified file 'lib/lp/soyuz/browser/tests/distroseriesqueue-views.txt'
--- lib/lp/soyuz/browser/tests/distroseriesqueue-views.txt 2010-08-26 15:28:34 +0000
+++ lib/lp/soyuz/browser/tests/distroseriesqueue-views.txt 2010-10-03 20:53:47 +0000
@@ -294,5 +294,5 @@
294294
295We created librarian files that need cleaning up before leaving the test.295We created librarian files that need cleaning up before leaving the test.
296296
297 >>> from canonical.librarian.ftests.harness import cleanupLibrarianFiles297 >>> from canonical.librarian.testing.server import cleanupLibrarianFiles
298 >>> cleanupLibrarianFiles()298 >>> cleanupLibrarianFiles()
299299
=== modified file 'lib/lp/soyuz/doc/buildd-dispatching.txt'
--- lib/lp/soyuz/doc/buildd-dispatching.txt 2010-09-24 10:39:27 +0000
+++ lib/lp/soyuz/doc/buildd-dispatching.txt 2010-10-03 20:53:47 +0000
@@ -13,7 +13,8 @@
13Setup the test builder:13Setup the test builder:
1414
15 >>> from canonical.buildd.tests import BuilddSlaveTestSetup15 >>> from canonical.buildd.tests import BuilddSlaveTestSetup
16 >>> BuilddSlaveTestSetup().setUp()16 >>> fixture = BuilddSlaveTestSetup()
17 >>> fixture.setUp()
1718
18Setup a suitable chroot for Hoary i386:19Setup a suitable chroot for Hoary i386:
1920
@@ -168,7 +169,7 @@
168Shutdown builder, mark the build record as failed and remove the169Shutdown builder, mark the build record as failed and remove the
169buildqueue record, so the build was eliminated:170buildqueue record, so the build was eliminated:
170171
171 >>> BuilddSlaveTestSetup().tearDown()172 >>> fixture.tearDown()
172173
173 >>> from lp.buildmaster.enums import BuildStatus174 >>> from lp.buildmaster.enums import BuildStatus
174 >>> build.status = BuildStatus.FAILEDTOBUILD175 >>> build.status = BuildStatus.FAILEDTOBUILD
@@ -243,7 +244,8 @@
243244
244Start buildd-slave to be able to dispatch jobs.245Start buildd-slave to be able to dispatch jobs.
245246
246 >>> BuilddSlaveTestSetup().setUp()247 >>> fixture = BuilddSlaveTestSetup()
248 >>> fixture.setUp()
247249
248Before dispatching we can check if the builder is protected against250Before dispatching we can check if the builder is protected against
249mistakes in code that results in a attempt to build a virtual job in251mistakes in code that results in a attempt to build a virtual job in
@@ -280,7 +282,7 @@
280buildqueue record and make 'bob' builder non-virtual again, so the282buildqueue record and make 'bob' builder non-virtual again, so the
281environment is back to the initial state.283environment is back to the initial state.
282284
283 >>> BuilddSlaveTestSetup().tearDown()285 >>> fixture.tearDown()
284286
285 >>> build.status = BuildStatus.FAILEDTOBUILD287 >>> build.status = BuildStatus.FAILEDTOBUILD
286 >>> ppa_job.destroySelf()288 >>> ppa_job.destroySelf()
@@ -319,12 +321,13 @@
319accept such jobs until we have finished the EMBARGOED archive321accept such jobs until we have finished the EMBARGOED archive
320implementation.322implementation.
321323
322 >>> BuilddSlaveTestSetup().setUp()324 >>> fixture = BuilddSlaveTestSetup()
325 >>> fixture.setUp()
323 >>> removeSecurityProxy(bob_builder)._dispatchBuildCandidate(sec_job)326 >>> removeSecurityProxy(bob_builder)._dispatchBuildCandidate(sec_job)
324 Traceback (most recent call last):327 Traceback (most recent call last):
325 ...328 ...
326 AssertionError: Soyuz is not yet capable of building SECURITY uploads.329 AssertionError: Soyuz is not yet capable of building SECURITY uploads.
327 >>> BuilddSlaveTestSetup().tearDown()330 >>> fixture.tearDown()
328331
329To solve this problem temporarily until we start building security332To solve this problem temporarily until we start building security
330uploads, we will mark builds targeted to the SECURITY pocket as333uploads, we will mark builds targeted to the SECURITY pocket as
331334
=== modified file 'lib/lp/soyuz/doc/distroseriesqueue-notify.txt'
--- lib/lp/soyuz/doc/distroseriesqueue-notify.txt 2009-05-13 14:05:27 +0000
+++ lib/lp/soyuz/doc/distroseriesqueue-notify.txt 2010-10-03 20:53:47 +0000
@@ -179,7 +179,7 @@
179provided that everything is already committed to the database (which is not179provided that everything is already committed to the database (which is not
180the case when nascent upload runs). This example demonstrates this usage:180the case when nascent upload runs). This example demonstrates this usage:
181181
182 >>> from canonical.librarian.ftests.harness import fillLibrarianFile182 >>> from canonical.librarian.testing.server import fillLibrarianFile
183 >>> changes_file = open(changes_file_path,"r")183 >>> changes_file = open(changes_file_path,"r")
184 >>> fillLibrarianFile(1, content=changes_file.read())184 >>> fillLibrarianFile(1, content=changes_file.read())
185 >>> changes_file.close()185 >>> changes_file.close()
@@ -259,5 +259,5 @@
259259
260Clean up, otherwise stuff is left lying around in /var/tmp.260Clean up, otherwise stuff is left lying around in /var/tmp.
261261
262 >>> from canonical.librarian.ftests.harness import cleanupLibrarianFiles262 >>> from canonical.librarian.testing.server import cleanupLibrarianFiles
263 >>> cleanupLibrarianFiles()263 >>> cleanupLibrarianFiles()
264264
=== modified file 'lib/lp/soyuz/doc/distroseriesqueue.txt'
--- lib/lp/soyuz/doc/distroseriesqueue.txt 2010-08-25 11:01:59 +0000
+++ lib/lp/soyuz/doc/distroseriesqueue.txt 2010-10-03 20:53:47 +0000
@@ -1026,7 +1026,7 @@
10261026
1027Clean up the librarian files:1027Clean up the librarian files:
10281028
1029 >>> from canonical.librarian.ftests.harness import cleanupLibrarianFiles1029 >>> from canonical.librarian.testing.server import cleanupLibrarianFiles
1030 >>> cleanupLibrarianFiles()1030 >>> cleanupLibrarianFiles()
10311031
10321032
10331033
=== modified file 'lib/lp/soyuz/doc/package-diff.txt'
--- lib/lp/soyuz/doc/package-diff.txt 2010-08-25 11:01:59 +0000
+++ lib/lp/soyuz/doc/package-diff.txt 2010-10-03 20:53:47 +0000
@@ -643,7 +643,7 @@
643 ... '1.0-2', archive=foobar.archive)643 ... '1.0-2', archive=foobar.archive)
644 >>> transaction.commit()644 >>> transaction.commit()
645645
646 >>> from canonical.librarian.ftests.harness import fillLibrarianFile646 >>> from canonical.librarian.testing.server import fillLibrarianFile
647 >>> [orig, upload_diff, dsc] = pub.sourcepackagerelease.files647 >>> [orig, upload_diff, dsc] = pub.sourcepackagerelease.files
648 >>> fillLibrarianFile(dsc.libraryfile.id)648 >>> fillLibrarianFile(dsc.libraryfile.id)
649649
650650
=== modified file 'lib/lp/soyuz/doc/soyuz-set-of-uploads.txt'
--- lib/lp/soyuz/doc/soyuz-set-of-uploads.txt 2010-09-16 12:27:46 +0000
+++ lib/lp/soyuz/doc/soyuz-set-of-uploads.txt 2010-10-03 20:53:47 +0000
@@ -59,7 +59,8 @@
59relevant launchpad person.59relevant launchpad person.
6060
61 >>> from canonical.zeca.ftests.harness import ZecaTestSetup61 >>> from canonical.zeca.ftests.harness import ZecaTestSetup
62 >>> ZecaTestSetup().setUp()62 >>> zeca = ZecaTestSetup()
63 >>> zeca.setUp()
6364
64Import public keyring into current LPDB.65Import public keyring into current LPDB.
6566
@@ -90,7 +91,7 @@
9091
91Add disk content for file inherited from ubuntu/breezy-autotest:92Add disk content for file inherited from ubuntu/breezy-autotest:
9293
93 >>> from canonical.librarian.ftests.harness import fillLibrarianFile94 >>> from canonical.librarian.testing.server import fillLibrarianFile
94 >>> fillLibrarianFile(54)95 >>> fillLibrarianFile(54)
9596
96Now that the infrastructure is ready, we prepare a set of useful methods.97Now that the infrastructure is ready, we prepare a set of useful methods.
@@ -754,5 +755,5 @@
754 >>> shutil.rmtree("/var/tmp/archive/")755 >>> shutil.rmtree("/var/tmp/archive/")
755 >>> shutil.rmtree(temp_dir)756 >>> shutil.rmtree(temp_dir)
756757
757 >>> ZecaTestSetup().tearDown()758 >>> zeca.tearDown()
758759
759760
=== modified file 'lib/lp/soyuz/doc/soyuz-upload.txt'
--- lib/lp/soyuz/doc/soyuz-upload.txt 2010-09-02 13:01:23 +0000
+++ lib/lp/soyuz/doc/soyuz-upload.txt 2010-10-03 20:53:47 +0000
@@ -260,7 +260,8 @@
260a different process.260a different process.
261261
262 >>> from canonical.zeca.ftests.harness import ZecaTestSetup262 >>> from canonical.zeca.ftests.harness import ZecaTestSetup
263 >>> ZecaTestSetup().setUp()263 >>> zeca = ZecaTestSetup()
264 >>> zeca.setUp()
264265
265266
266Include non-free in the database. This will be done by the267Include non-free in the database. This will be done by the
@@ -763,7 +764,7 @@
763Remove the test archive from filesystem.764Remove the test archive from filesystem.
764765
765 >>> shutil.rmtree("/var/tmp/archive/")766 >>> shutil.rmtree("/var/tmp/archive/")
766 >>> ZecaTestSetup().tearDown()767 >>> zeca.tearDown()
767768
768769
769Feito! ;-)770Feito! ;-)
770771
=== modified file 'lib/lp/soyuz/scripts/tests/test_copypackage.py'
--- lib/lp/soyuz/scripts/tests/test_copypackage.py 2010-08-27 11:19:54 +0000
+++ lib/lp/soyuz/scripts/tests/test_copypackage.py 2010-10-03 20:53:47 +0000
@@ -17,7 +17,7 @@
17from canonical.config import config17from canonical.config import config
18from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet18from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet
19from canonical.launchpad.scripts import BufferLogger19from canonical.launchpad.scripts import BufferLogger
20from canonical.librarian.ftests.harness import fillLibrarianFile20from canonical.librarian.testing.server import fillLibrarianFile
21from canonical.testing import (21from canonical.testing import (
22 DatabaseLayer,22 DatabaseLayer,
23 LaunchpadFunctionalLayer,23 LaunchpadFunctionalLayer,
2424
=== modified file 'lib/lp/soyuz/scripts/tests/test_queue.py'
--- lib/lp/soyuz/scripts/tests/test_queue.py 2010-09-16 09:19:15 +0000
+++ lib/lp/soyuz/scripts/tests/test_queue.py 2010-10-03 20:53:47 +0000
@@ -32,7 +32,7 @@
32 PackageUploadBuild,32 PackageUploadBuild,
33 )33 )
34from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet34from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet
35from canonical.librarian.ftests.harness import (35from canonical.librarian.testing.server import (
36 cleanupLibrarianFiles,36 cleanupLibrarianFiles,
37 fillLibrarianFile,37 fillLibrarianFile,
38 )38 )
3939
=== modified file 'lib/lp/soyuz/scripts/tests/test_sync_source.py'
--- lib/lp/soyuz/scripts/tests/test_sync_source.py 2010-09-16 19:00:35 +0000
+++ lib/lp/soyuz/scripts/tests/test_sync_source.py 2010-10-03 20:53:47 +0000
@@ -24,7 +24,7 @@
2424
25from canonical.config import config25from canonical.config import config
26from canonical.launchpad.scripts import BufferLogger26from canonical.launchpad.scripts import BufferLogger
27from canonical.librarian.ftests.harness import (27from canonical.librarian.testing.server import (
28 cleanupLibrarianFiles,28 cleanupLibrarianFiles,
29 fillLibrarianFile,29 fillLibrarianFile,
30 )30 )
3131
=== modified file 'lib/lp/soyuz/stories/soyuz/xx-queue-pages.txt'
--- lib/lp/soyuz/stories/soyuz/xx-queue-pages.txt 2010-08-24 12:05:25 +0000
+++ lib/lp/soyuz/stories/soyuz/xx-queue-pages.txt 2010-10-03 20:53:47 +0000
@@ -574,6 +574,6 @@
574574
575== Clean up ==575== Clean up ==
576576
577 >>> from canonical.librarian.ftests.harness import cleanupLibrarianFiles577 >>> from canonical.librarian.testing.server import cleanupLibrarianFiles
578 >>> cleanupLibrarianFiles()578 >>> cleanupLibrarianFiles()
579579
580580
=== added file 'lib/lp/testing/fakelibrarian.py'
--- lib/lp/testing/fakelibrarian.py 1970-01-01 00:00:00 +0000
+++ lib/lp/testing/fakelibrarian.py 2010-10-03 20:53:47 +0000
@@ -0,0 +1,16 @@
1# Copyright 2010 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3
4"""See canonical.librarian.testing.fake."""
5
6import warnings
7
8from canonical.librarian.testing.fake import FakeLibrarian as _FakeLibrarian
9
10
11def FakeLibrarian(*args, **kwargs):
12 """Forward to the new home with a deprecation warning."""
13 warnings.warn("Stale import: please import FakeLibrarian from "
14 "canonical.librarian.testing.fake instead.", DeprecationWarning,
15 stacklevel=2)
16 return _FakeLibrarian(*args, **kwargs)
017
=== modified file 'lib/lp/translations/doc/translationtemplatesbuildbehavior.txt'
--- lib/lp/translations/doc/translationtemplatesbuildbehavior.txt 2010-09-23 18:17:21 +0000
+++ lib/lp/translations/doc/translationtemplatesbuildbehavior.txt 2010-10-03 20:53:47 +0000
@@ -18,7 +18,8 @@
18 ... JobStatus.FAILED))18 ... JobStatus.FAILED))
1919
20 >>> from canonical.buildd.tests import BuilddSlaveTestSetup20 >>> from canonical.buildd.tests import BuilddSlaveTestSetup
21 >>> BuilddSlaveTestSetup().setUp()21 >>> fixture = BuilddSlaveTestSetup()
22 >>> fixture.setUp()
2223
23 >>> from canonical.librarian.interfaces import ILibrarianClient24 >>> from canonical.librarian.interfaces import ILibrarianClient
24 >>> from StringIO import StringIO25 >>> from StringIO import StringIO
@@ -105,4 +106,4 @@
105106
106Clean up after this test.107Clean up after this test.
107108
108 >>> BuilddSlaveTestSetup().tearDown()109 >>> fixture.tearDown()
109110
=== modified file 'lib/lp/translations/utilities/tests/test_file_importer.py'
--- lib/lp/translations/utilities/tests/test_file_importer.py 2010-09-18 09:14:59 +0000
+++ lib/lp/translations/utilities/tests/test_file_importer.py 2010-10-03 20:53:47 +0000
@@ -8,10 +8,10 @@
8from zope.component import getUtility8from zope.component import getUtility
9from zope.security.proxy import removeSecurityProxy9from zope.security.proxy import removeSecurityProxy
1010
11from canonical.librarian.testing.fake import FakeLibrarian
11from canonical.testing import ZopelessDatabaseLayer12from canonical.testing import ZopelessDatabaseLayer
12from lp.registry.interfaces.person import IPersonSet13from lp.registry.interfaces.person import IPersonSet
13from lp.testing import TestCaseWithFactory14from lp.testing import TestCaseWithFactory
14from lp.testing.fakelibrarian import FakeLibrarian
15from lp.translations.interfaces.translationgroup import TranslationPermission15from lp.translations.interfaces.translationgroup import TranslationPermission
16from lp.translations.interfaces.translationimporter import (16from lp.translations.interfaces.translationimporter import (
17 OutdatedTranslationError,17 OutdatedTranslationError,