Merge lp:~jtv/launchpad/bug-507678 into lp:launchpad/db-devel

Proposed by Jeroen T. Vermeulen
Status: Rejected
Rejected by: Jeroen T. Vermeulen
Proposed branch: lp:~jtv/launchpad/bug-507678
Merge into: lp:launchpad/db-devel
Diff against target: 575 lines (+418/-39) (has conflicts)
8 files modified
lib/lp/buildmaster/model/buildfarmjobbehavior.py (+15/-4)
lib/lp/buildmaster/tests/test_buildfarmjobbehavior.py (+41/-0)
lib/lp/testing/factory.py (+19/-0)
lib/lp/testing/fakemethod.py (+51/-0)
lib/lp/testing/tests/test_fakemethod.py (+85/-0)
lib/lp/translations/model/translationtemplatesbuildbehavior.py (+50/-1)
lib/lp/translations/tests/test_translationtemplatesbuildbehavior.py (+157/-0)
lib/lp/translations/tests/test_translationtemplatesbuildjob.py (+0/-34)
Text conflict in lib/lp/testing/factory.py
To merge this branch: bzr merge lp:~jtv/launchpad/bug-507678
Reviewer Review Type Date Requested Status
Eleanor Berger code Pending
Review via email: mp+19131@code.launchpad.net

Commit message

Retrieve results from translation-templates builds on the build farm.

To post a comment you must log in.
Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :
Download full text (3.7 KiB)

= Bug 507678 =

Continuing work on making the buildfarm generate translation templates from source branches. Here I'm jumping through the hoops to let the IBuildFarmJobBehavior implementation that we have for this kind of build-farm job retrieve a tarball produced by the slave.

The default BuildFarmJobBehaviorBase code for this assumed that there's an IBuildBase object (basically a generalization of soyuz's Build) attached to a build-farm job. It didn't seem worth it to implement IBuildBase just for this (I tried), I now override the only BuildFarmJobBehaviorBase method that requires it. I had to extend the infrastructure a bit along the way.

An important thing to note is that these pieces are still coming together; they're not actually a functional whole yet. But with the ongoing work on build-farm generalization, it's important to get and keep them integrated before bit-rot sets in.

Going through the diff step by step:

lib/lp/buildmaster/model/buildfarmjobbehavior.py

I extracted a method for reading and checking build status from a slave status dict. That makes it easy for my behavior class to reuse it.

lib/lp/buildmaster/tests/test_buildfarmjobbehavior.py

Tests the method I abstracted.

lib/lp/testing/factory.py

New factory method for the type of build-farm job that generates translation templates.

lib/lp/testing/fakemethod.py

Provides a generic stub for all sorts of functions and methods. I got tired of writing one-liners, injecting ad-hoc status variables into objects, and building one-off mock classes. Need to override a method in an object to return a dummy value or fail in a particular way? Just assign it to a FakeMethod.

Pylint had a truly silly complaint about this file, so I silenced it. There's a comment to the effect.

lib/lp/testing/tests/test_fakemethod.py

Unit-tests FakeMethod.

lib/lp/translations/model/translationtemplatesbuildbehavior.py

Grew some methods for retrieving a tarball of results from the build-farm slave. As yet we do not have the code in place that will generate the real templates.

lib/lp/translations/tests/test_translationtemplatesbuildbehavior.py

Tests the extensions to the behavior class. The starting point for this was an existing unit test that I ripped out of the next file in the diff.

Interaction with slaves makes testing this stuff very hard. About the best I can do is mock up all the infrastructure, unit-test my part, and hope the other classes do their job. It's not perfect, but it's a lot more automated testing than a lot of the other buildfarm work gets.

For this test I had to strike a balance black-box and white-box approaches: obviously the test needs a lot of inside knowledge about the classes it's dealing with, but I didn't make it check the fidgety details of what values are being passed around where. Those could change easily, as work on the build farm is still ongoing. Moreover, I have no real requirements for them other than "they should work."

lib/lp/translations/tests/test_translationtemplatesbuildjob.py

Lost a test case to the file above. What there was got simplified a bit, and setUp got replaced with explicit creation of objects.

To test these changes...

Read more...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/buildmaster/model/buildfarmjobbehavior.py'
--- lib/lp/buildmaster/model/buildfarmjobbehavior.py 2010-01-29 17:15:31 +0000
+++ lib/lp/buildmaster/model/buildfarmjobbehavior.py 2010-02-11 19:48:24 +0000
@@ -164,6 +164,20 @@
164 queueItem.job.fail()164 queueItem.job.fail()
165 queueItem.specific_job.jobAborted()165 queueItem.specific_job.jobAborted()
166166
167 def extractBuildStatus(self, slave_status):
168 """Read build status name.
169
170 :param slave_status: build status dict as passed to the
171 updateBuild_* methods.
172 :return: the unqualified status name, e.g. "OK".
173 """
174 status_string = slave_status['build_status']
175 lead_string = 'BuildStatus.'
176 assert status_string.startswith(lead_string), (
177 "Malformed status string: '%s'" % status_string)
178
179 return status_string[len(lead_string):]
180
167 def updateBuild_WAITING(self, queueItem, slave_status, logtail, logger):181 def updateBuild_WAITING(self, queueItem, slave_status, logtail, logger):
168 """Perform the actions needed for a slave in a WAITING state182 """Perform the actions needed for a slave in a WAITING state
169183
@@ -178,13 +192,10 @@
178 the uploader for processing.192 the uploader for processing.
179 """193 """
180 librarian = getUtility(ILibrarianClient)194 librarian = getUtility(ILibrarianClient)
181 build_status = slave_status['build_status']195 build_status = self.extractBuildStatus(slave_status)
182196
183 # XXX: dsilvers 2005-03-02: Confirm the builder has the right build?197 # XXX: dsilvers 2005-03-02: Confirm the builder has the right build?
184 assert build_status.startswith('BuildStatus.'), (
185 'Malformed status string: %s' % build_status)
186198
187 build_status = build_status[len('BuildStatus.'):]
188 queueItem.specific_job.build.handleStatus(199 queueItem.specific_job.build.handleStatus(
189 build_status, librarian, slave_status)200 build_status, librarian, slave_status)
190201
191202
=== added file 'lib/lp/buildmaster/tests/test_buildfarmjobbehavior.py'
--- lib/lp/buildmaster/tests/test_buildfarmjobbehavior.py 1970-01-01 00:00:00 +0000
+++ lib/lp/buildmaster/tests/test_buildfarmjobbehavior.py 2010-02-11 19:48:24 +0000
@@ -0,0 +1,41 @@
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"""Unit tests for BuildFarmJobBehaviorBase."""
5
6from unittest import TestCase, TestLoader
7
8from lp.buildmaster.model.buildfarmjobbehavior import BuildFarmJobBehaviorBase
9from lp.soyuz.interfaces.build import BuildStatus
10
11
12class FakeBuildFarmJob:
13 """Dummy BuildFarmJob."""
14 pass
15
16
17class TestBuildFarmJobBehaviorBase(TestCase):
18 """Test very small, basic bits of BuildFarmJobBehaviorBase."""
19
20 def setUp(self):
21 self.behavior = BuildFarmJobBehaviorBase(FakeBuildFarmJob())
22
23 def test_extractBuildStatus_baseline(self):
24 # extractBuildStatus picks the name of the build status out of a
25 # dict describing the slave's status.
26 slave_status = {'build_status': 'BuildStatus.BUILDING'}
27 self.assertEqual(
28 BuildStatus.BUILDING.name,
29 self.behavior.extractBuildStatus(slave_status))
30
31 def test_extractBuildStatus_malformed(self):
32 # extractBuildStatus errors out when the status string is not
33 # of the form it expects.
34 slave_status = {'build_status': 'BUILDING'}
35 self.assertRaises(
36 AssertionError,
37 self.behavior.extractBuildStatus, slave_status)
38
39
40def test_suite():
41 return TestLoader().loadTestsFromName(__name__)
042
=== modified file 'lib/lp/testing/factory.py'
--- lib/lp/testing/factory.py 2010-02-11 05:08:47 +0000
+++ lib/lp/testing/factory.py 2010-02-11 19:48:24 +0000
@@ -129,6 +129,7 @@
129from lp.soyuz.interfaces.publishing import PackagePublishingStatus129from lp.soyuz.interfaces.publishing import PackagePublishingStatus
130from lp.soyuz.interfaces.section import ISectionSet130from lp.soyuz.interfaces.section import ISectionSet
131from lp.soyuz.model.buildqueue import BuildQueue131from lp.soyuz.model.buildqueue import BuildQueue
132<<<<<<< TREE
132from lp.soyuz.model.processor import ProcessorFamilySet133from lp.soyuz.model.processor import ProcessorFamilySet
133from lp.soyuz.model.publishing import (134from lp.soyuz.model.publishing import (
134 SecureSourcePackagePublishingHistory,135 SecureSourcePackagePublishingHistory,
@@ -142,6 +143,12 @@
142 ITranslationGroupSet)143 ITranslationGroupSet)
143from lp.translations.interfaces.translationsperson import ITranslationsPerson144from lp.translations.interfaces.translationsperson import ITranslationsPerson
144from lp.translations.interfaces.translator import ITranslatorSet145from lp.translations.interfaces.translator import ITranslatorSet
146=======
147from lp.testing import run_with_login, time_counter
148from lp.translations.interfaces.translationtemplatesbuildjob import (
149 ITranslationTemplatesBuildJobSource)
150
151>>>>>>> MERGE-SOURCE
145152
146SPACE = ' '153SPACE = ' '
147154
@@ -1714,6 +1721,18 @@
1714 store.add(bq)1721 store.add(bq)
1715 return bq1722 return bq
17161723
1724 def makeTranslationTemplatesBuildJob(self, branch=None):
1725 """Make a new `TranslationTemplatesBuildJob`.
1726
1727 :param branch: The branch that the job should be for. If none
1728 is given, one will be created.
1729 """
1730 if branch is None:
1731 branch = self.makeBranch()
1732
1733 jobset = getUtility(ITranslationTemplatesBuildJobSource)
1734 return jobset.create(branch)
1735
1717 def makePOTemplate(self, productseries=None, distroseries=None,1736 def makePOTemplate(self, productseries=None, distroseries=None,
1718 sourcepackagename=None, owner=None, name=None,1737 sourcepackagename=None, owner=None, name=None,
1719 translation_domain=None, path=None):1738 translation_domain=None, path=None):
17201739
=== added file 'lib/lp/testing/fakemethod.py'
--- lib/lp/testing/fakemethod.py 1970-01-01 00:00:00 +0000
+++ lib/lp/testing/fakemethod.py 2010-02-11 19:48:24 +0000
@@ -0,0 +1,51 @@
1# Copyright 2009, 2010 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3
4# pylint: disable-msg=E0702
5
6
7__metaclass__ = type
8__all__ = [
9 'FakeMethod',
10 ]
11
12
13class FakeMethod:
14 """Catch any function or method call, and record the fact.
15
16 Use this for easy stubbing. The call operator can return a fixed
17 value, or raise a fixed exception object.
18
19 This is useful when unit-testing code that does things you don't
20 want to integration-test, e.g. because it wants to talk to remote
21 systems.
22 """
23
24 # How many times has this fake method been called?
25 call_count = 0
26
27 def __init__(self, result=None, failure=None):
28 """Set up a fake function or method.
29
30 :param result: Value to return.
31 :param failure: Exception to raise.
32 """
33 self.result = result
34 self.failure = failure
35
36 def __call__(self, *args, **kwargs):
37 """Catch an invocation to the method. Increment `call_count`.
38
39 Accepts any and all parameters. Raises the failure passed to
40 the constructor, if any; otherwise, returns the result value
41 passed to the constructor.
42 """
43 self.call_count += 1
44
45 if self.failure is None:
46 return self.result
47 else:
48 # pylint thinks this raises None, which is clearly not
49 # possible. That's why this test disables pylint message
50 # E0702.
51 raise self.failure
052
=== added file 'lib/lp/testing/tests/test_fakemethod.py'
--- lib/lp/testing/tests/test_fakemethod.py 1970-01-01 00:00:00 +0000
+++ lib/lp/testing/tests/test_fakemethod.py 2010-02-11 19:48:24 +0000
@@ -0,0 +1,85 @@
1# Copyright 2010 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3
4from unittest import TestCase, TestLoader
5
6from lp.testing.fakemethod import FakeMethod
7
8
9class RealActualClass:
10 """A class that's hard to test."""
11
12 doing_impossible_stuff = False
13 doing_possible_stuff = False
14
15 def impossibleMethod(self):
16 """A method that you can't afford to invoke in your test.
17
18 This is the method you're going to want to avoid calling. The
19 way to do that is to replace this method with a fake method.
20 """
21 self.doing_impossible_stuff = True
22 raise AssertionError("Trying to do impossible stuff.")
23
24 def testableMethod(self):
25 """This part of the class logic that you do want to exercise."""
26 self.doing_possible_stuff = True
27
28 def doComplicatedThings(self, argument):
29 """This is the top-level method you want to test.
30
31 Unfortunately this invokes impossibleMethod, making it hard.
32 """
33 self.impossibleMethod()
34 self.testableMethod()
35 return argument
36
37
38class CustomException(Exception):
39 """Some specific error that you want raised."""
40
41
42class TestFakeMethod(TestCase):
43 def test_fakeMethod(self):
44 # A class that you're testing can continue normally despite some
45 # of its methods being stubbed.
46 thing = RealActualClass()
47 thing.impossibleMethod = FakeMethod()
48
49 result = thing.doComplicatedThings(99)
50
51 self.assertEqual(99, result)
52 self.assertFalse(thing.doing_impossible_stuff)
53 self.assertTrue(thing.doing_possible_stuff)
54
55 def test_raiseFailure(self):
56 # A FakeMethod can raise an exception you specify.
57 ouch = CustomException("Ouch!")
58 func = FakeMethod(failure=ouch)
59 self.assertRaises(CustomException, func)
60
61 def test_returnResult(self):
62 # A FakeMethod can return a value you specify.
63 value = "Fixed return value."
64 func = FakeMethod(result=value)
65 self.assertEqual(value, func())
66
67 def test_countCalls(self):
68 # A FakeMethod counts the number of times it's been invoked.
69 func = FakeMethod()
70 for count in xrange(3):
71 self.assertEqual(count, func.call_count)
72 func()
73 self.assertEqual(count + 1, func.call_count)
74
75 def test_takeArguments(self):
76 # A FakeMethod invocation accepts any arguments it gets.
77 func = FakeMethod()
78 func()
79 func(1)
80 func(2, kwarg=3)
81 self.assertEqual(3, func.call_count)
82
83
84def test_suite():
85 return TestLoader().loadTestsFromName(__name__)
086
=== modified file 'lib/lp/translations/model/translationtemplatesbuildbehavior.py'
--- lib/lp/translations/model/translationtemplatesbuildbehavior.py 2010-01-15 01:20:20 +0000
+++ lib/lp/translations/model/translationtemplatesbuildbehavior.py 2010-02-11 19:48:24 +0000
@@ -13,6 +13,7 @@
1313
14from zope.component import getUtility14from zope.component import getUtility
15from zope.interface import implements15from zope.interface import implements
16from zope.security.proxy import removeSecurityProxy
1617
17from canonical.launchpad.interfaces import ILaunchpadCelebrities18from canonical.launchpad.interfaces import ILaunchpadCelebrities
1819
@@ -29,6 +30,9 @@
29 # Identify the type of job to the slave.30 # Identify the type of job to the slave.
30 build_type = 'translation-templates'31 build_type = 'translation-templates'
3132
33 # Filename for the tarball of templates that the slave builds.
34 templates_tarball_path = 'translation-templates.tar.gz'
35
32 def dispatchBuildToSlave(self, build_queue_item, logger):36 def dispatchBuildToSlave(self, build_queue_item, logger):
33 """See `IBuildFarmJobBehavior`."""37 """See `IBuildFarmJobBehavior`."""
34 chroot = self._getChroot()38 chroot = self._getChroot()
@@ -39,7 +43,7 @@
39 args = { 'branch_url': self.buildfarmjob.branch.url }43 args = { 'branch_url': self.buildfarmjob.branch.url }
40 filemap = {}44 filemap = {}
4145
42 status, info = self._builder.slave.build(46 self._builder.slave.build(
43 buildid, self.build_type, chroot_sha1, filemap, args)47 buildid, self.build_type, chroot_sha1, filemap, args)
4448
45 def _getChroot(self):49 def _getChroot(self):
@@ -49,3 +53,48 @@
49 def logStartBuild(self, logger):53 def logStartBuild(self, logger):
50 """See `IBuildFarmJobBehavior`."""54 """See `IBuildFarmJobBehavior`."""
51 logger.info("Starting templates build.")55 logger.info("Starting templates build.")
56
57 def _readTarball(self, buildqueue, filemap, logger):
58 """Read tarball with generated translation templates from slave."""
59 slave_filename = filemap.get(self.templates_tarball_path)
60 if slave_filename is None:
61 logger.error("Did not find templates tarball in slave output.")
62 return None
63
64 slave = removeSecurityProxy(buildqueue.builder.slave)
65 return slave.getFile(slave_filename).read()
66
67 def _uploadTarball(self, branch, tarball, logger):
68 """Upload tarball to productseries that want it."""
69 # XXX JeroenVermeulen 2010-01-28 bug=507680: Find productseries
70 # that want these templates, and upload to there.
71
72 def updateBuild_WAITING(self, queue_item, slave_status, logtail, logger):
73 """Deal with a finished ("WAITING" state, perversely) build job.
74
75 Retrieves tarball and logs from the slave, then cleans up the
76 slave so it's ready for a next job and destroys the queue item.
77
78 If this fails for whatever unforeseen reason, a future run will
79 retry it.
80 """
81 build_status = self.extractBuildStatus(slave_status)
82 build_id = slave_status['build_id']
83 filemap = slave_status['filemap']
84
85 logger.debug("Templates generation job %s finished with status %s" % (
86 build_id, build_status))
87
88 if build_status == 'OK':
89 logger.debug("Processing templates build %s" % build_id)
90 tarball = self._readTarball(queue_item, filemap, logger)
91 if tarball is None:
92 logger.error("Successful build %s produced no tarball." % (
93 build_id))
94 else:
95 logger.debug("Uploading translation templates tarball.")
96 self._uploadTarball(tarball, logger)
97 logger.debug("Upload complete.")
98
99 queue_item.builder.cleanSlave()
100 queue_item.destroySelf()
52101
=== added file 'lib/lp/translations/tests/test_translationtemplatesbuildbehavior.py'
--- lib/lp/translations/tests/test_translationtemplatesbuildbehavior.py 1970-01-01 00:00:00 +0000
+++ lib/lp/translations/tests/test_translationtemplatesbuildbehavior.py 2010-02-11 19:48:24 +0000
@@ -0,0 +1,157 @@
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"""Unit tests for TranslationTemplatesBuildBehavior."""
5
6import logging
7from StringIO import StringIO
8from unittest import TestLoader
9
10from zope.component import getUtility
11from zope.security.proxy import removeSecurityProxy
12
13from canonical.testing import ZopelessDatabaseLayer
14
15from canonical.launchpad.interfaces import ILaunchpadCelebrities
16from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet
17from lp.buildmaster.interfaces.buildfarmjobbehavior import (
18 IBuildFarmJobBehavior)
19from lp.soyuz.interfaces.build import BuildStatus
20from lp.soyuz.interfaces.buildqueue import IBuildQueueSet
21from lp.testing import TestCaseWithFactory
22from lp.testing.fakemethod import FakeMethod
23
24
25class FakeChrootContent:
26 """Pretend chroot contents."""
27 sha1 = "shasha"
28
29
30class FakeChroot:
31 """Pretend chroot."""
32 def __init__(self, *args, **kwargs):
33 """Constructor acts as a fake _getChroot."""
34 self.content = FakeChrootContent()
35
36
37class FakeSlave:
38 """Pretend build slave."""
39 def __init__(self, builderstatus):
40 self.build_started = False
41 self.status = {
42 'build_status': 'BuildStatus.%s' % builderstatus.name,
43 }
44
45 self.cacheFile = FakeMethod()
46 self.getFile = FakeMethod(result=StringIO("File from the slave."))
47
48 def build(self, buildid, build_type, chroot_sha1, filemap, args):
49 """Pretend to start a build."""
50 self.status['build_id'] = buildid
51 self.status['filemap'] = filemap
52 self.build_started = True
53
54
55class FakeBuilder:
56 """Pretend `Builder`."""
57 def __init__(self, slave):
58 self.slave = slave
59 self.cleanSlave = FakeMethod()
60
61 def slaveStatus(self):
62 return self.slave.status
63
64
65class FakeBuildQueue:
66 """Pretend `BuildQueue`."""
67 def __init__(self, behavior):
68 """Pretend to be a BuildQueue item for the given build behavior.
69
70 Copies its builder from the behavior object.
71 """
72 self.builder = behavior._builder
73 self.destroySelf = FakeMethod()
74
75
76class TestTranslationTemplatesBuildBehavior(TestCaseWithFactory):
77 """Test `TranslationTemplatesBuildBehavior`."""
78
79 layer = ZopelessDatabaseLayer
80
81 def _makeBehavior(self):
82 """Create a TranslationTemplatesBuildBehavior.
83
84 Anything that might communicate with build slaves and such
85 (which we can't really do here) is mocked up.
86 """
87 specific_job = self.factory.makeTranslationTemplatesBuildJob()
88 behavior = IBuildFarmJobBehavior(specific_job)
89 slave = FakeSlave(BuildStatus.NEEDSBUILD)
90 behavior._builder = FakeBuilder(slave)
91 return behavior
92
93 def _getBuildQueueItem(self, behavior):
94 """Get `BuildQueue` for an `IBuildFarmJobBehavior`."""
95 job = removeSecurityProxy(behavior.buildfarmjob.job)
96 return getUtility(IBuildQueueSet).getByJob(job.id)
97
98 def test_dispatchBuildToSlave(self):
99 behavior = self._makeBehavior()
100 behavior._getChroot = FakeChroot
101 buildqueue_item = self._getBuildQueueItem(behavior)
102
103 behavior.dispatchBuildToSlave(buildqueue_item, logging)
104
105 self.assertTrue(behavior._builder.slave.build_started)
106
107 def test_getChroot(self):
108 # _getChroot produces the current chroot for the current Ubuntu
109 # release, on the nominated architecture for
110 # architecture-independent builds.
111 ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
112 current_ubuntu = ubuntu.currentseries
113 distroarchseries = current_ubuntu.nominatedarchindep
114
115 # Set an arbitrary chroot file.
116 fake_chroot_file = getUtility(ILibraryFileAliasSet)[1]
117 distroarchseries.addOrUpdateChroot(fake_chroot_file)
118
119 behavior = self._makeBehavior()
120 chroot = behavior._getChroot()
121
122 self.assertNotEqual(None, chroot)
123 self.assertEqual(fake_chroot_file, chroot)
124
125 def test_readTarball(self):
126 behavior = self._makeBehavior()
127 buildqueue = FakeBuildQueue(behavior)
128 path = behavior.templates_tarball_path
129 self.assertEqual(
130 "File from the slave.",
131 behavior._readTarball(buildqueue, {path: path}, logging))
132
133 def test_updateBuild_WAITING(self):
134 behavior = self._makeBehavior()
135 behavior._getChroot = FakeChroot
136 behavior._uploadTarball = FakeMethod()
137 queue_item = FakeBuildQueue(behavior)
138 slave_status = behavior._builder.slave.status
139 builder = behavior._builder
140 slave = builder.slave
141
142 behavior.dispatchBuildToSlave(queue_item, logging)
143
144 self.assertEqual(0, queue_item.destroySelf.call_count)
145 self.assertEqual(0, builder.cleanSlave.call_count)
146 self.assertEqual(0, behavior._uploadTarball.call_count)
147
148 behavior.updateBuild_WAITING(queue_item, slave_status, None, logging)
149
150 self.assertEqual(1, queue_item.destroySelf.call_count)
151 self.assertEqual(1, builder.cleanSlave.call_count)
152 self.assertEqual(0, behavior._uploadTarball.call_count)
153
154
155def test_suite():
156 return TestLoader().loadTestsFromName(__name__)
157
0158
=== modified file 'lib/lp/translations/tests/test_translationtemplatesbuildjob.py'
--- lib/lp/translations/tests/test_translationtemplatesbuildjob.py 2010-01-15 01:20:20 +0000
+++ lib/lp/translations/tests/test_translationtemplatesbuildjob.py 2010-02-11 19:48:24 +0000
@@ -8,8 +8,6 @@
8from zope.component import getUtility8from zope.component import getUtility
9from zope.security.proxy import removeSecurityProxy9from zope.security.proxy import removeSecurityProxy
1010
11from canonical.launchpad.interfaces import (
12 ILaunchpadCelebrities, ILibraryFileAliasSet)
13from canonical.launchpad.webapp.testing import verifyObject11from canonical.launchpad.webapp.testing import verifyObject
14from canonical.testing import ZopelessDatabaseLayer12from canonical.testing import ZopelessDatabaseLayer
1513
@@ -17,8 +15,6 @@
1715
18from lp.buildmaster.interfaces.buildfarmjob import (16from lp.buildmaster.interfaces.buildfarmjob import (
19 IBuildFarmJob, ISpecificBuildFarmJobClass)17 IBuildFarmJob, ISpecificBuildFarmJobClass)
20from lp.buildmaster.interfaces.buildfarmjobbehavior import (
21 IBuildFarmJobBehavior)
22from lp.code.interfaces.branchjob import IBranchJob18from lp.code.interfaces.branchjob import IBranchJob
23from lp.services.job.model.job import Job19from lp.services.job.model.job import Job
24from lp.soyuz.interfaces.buildqueue import IBuildQueueSet20from lp.soyuz.interfaces.buildqueue import IBuildQueueSet
@@ -102,35 +98,5 @@
102 self.assertEqual(1000, self.specific_job.score())98 self.assertEqual(1000, self.specific_job.score())
10399
104100
105class TestTranslationTemplatesBuildBehavior(TestCaseWithFactory):
106 """Test `TranslationTemplatesBuildBehavior`."""
107
108 layer = ZopelessDatabaseLayer
109
110 def setUp(self):
111 super(TestTranslationTemplatesBuildBehavior, self).setUp()
112 self.jobset = getUtility(ITranslationTemplatesBuildJobSource)
113 self.branch = self.factory.makeBranch()
114 self.specific_job = self.jobset.create(self.branch)
115 self.behavior = IBuildFarmJobBehavior(self.specific_job)
116
117 def test_getChroot(self):
118 # _getChroot produces the current chroot for the current Ubuntu
119 # release, on the nominated architecture for
120 # architecture-independent builds.
121 ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
122 current_ubuntu = ubuntu.currentseries
123 distroarchseries = current_ubuntu.nominatedarchindep
124
125 # Set an arbitrary chroot file.
126 fake_chroot_file = getUtility(ILibraryFileAliasSet)[1]
127 distroarchseries.addOrUpdateChroot(fake_chroot_file)
128
129 chroot = self.behavior._getChroot()
130
131 self.assertNotEqual(None, chroot)
132 self.assertEqual(fake_chroot_file, chroot)
133
134
135def test_suite():101def test_suite():
136 return TestLoader().loadTestsFromName(__name__)102 return TestLoader().loadTestsFromName(__name__)

Subscribers

People subscribed via source and target branches

to status/vote changes: