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

Proposed by Jeroen T. Vermeulen
Status: Rejected
Rejected by: Jeroen T. Vermeulen
Proposed branch: lp:~jtv/launchpad/db-bug-499404
Merge into: lp:launchpad/db-devel
Diff against target: 462 lines (+376/-6)
9 files modified
database/schema/comments.sql (+5/-0)
database/schema/patch-2207-22-0.sql (+16/-0)
database/schema/security.cfg (+1/-0)
lib/lp/buildmaster/interfaces/buildfarmjob.py (+6/-6)
lib/lp/translations/configure.zcml (+16/-0)
lib/lp/translations/interfaces/translationtemplatesbuildjob.py (+52/-0)
lib/lp/translations/model/translationtemplatesbuildbehavior.py (+81/-0)
lib/lp/translations/model/translationtemplatesbuildjob.py (+93/-0)
lib/lp/translations/tests/test_translationtemplatesbuildjob.py (+106/-0)
To merge this branch: bzr merge lp:~jtv/launchpad/db-bug-499404
Reviewer Review Type Date Requested Status
Jonathan Lange (community) db Needs Fixing
Tim Penhey (community) Disapprove
Stuart Bishop (community) db Approve
Muharem Hrnjadovic (community) code Approve
Review via email: mp+16564@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :

= Bug 499404 =

This implements some new classes that will be needed for Rosetta to run jobs on the generalised build farm. The job in question is generating translation templates based on a source-code branch, and will require a lot more work before it goes operational.

Generalisation of the build farm is ongoing work, so its APIs etc. are not complete yet. What you find here is:

1. An implementation of IBuildFarmJob—a new class representing a job that can be dispatched to the build farm. It's called TranslationTemplatesBuildJob. The only "payload" in this new class is a reference to the branch that the job is to check out. There's also a reference to Job, which holds the generic part of the jobbing information.

2. A BuildFarmJobSet utility—to produce and navigate jobs of the new type. It also creates a BuildQueue record for each job it creates; these records are matched to the records of the new type in that they both refer to the same Job record.

3. A new IBuildFarmJobBehavior implementation for dispatching the new job type to the build farm, with an adapter associating it with TranslationTemplatesBuildJob. More may be needed there in the future.

There's not much I can do to test the main IBuildFarmJobBehavior method right now; we'll need more of the building to be operational before we get to that. But work is in progress and I'm filing separate bugs for this.

To test:
{{{
./bin/test -vv -t translationtemplatesbuild
}}}

No lint.

Jeroen

Revision history for this message
Muharem Hrnjadovic (al-maisan) wrote :

This is still very much work in progress but as such it looks good!

review: Approve (code)
Revision history for this message
Stuart Bishop (stub) wrote :

Mainly fine.

I prefer the non-unique index names to have an __idx suffix (avoids some probably non-existant namespace issues).

The ON DELETE CASCADE is an issue. If someone attempts to delete a Branch that has a running job, I suspect we actually want to generate an error (or will things somehow progress just fine despite the branch disappearing part of the way through the process?). There is quite a bit of logic in branch deletion on when branches can be deleted, and the DB constraints serve as a safety net for that. The ON DELETE CASCADE on the job column seems sane.

The DB patch is already using an assigned patch number, so nothing to change there.

review: Needs Information (db)
Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :

> I prefer the non-unique index names to have an __idx suffix (avoids some
> probably non-existant namespace issues).

Done.

> The ON DELETE CASCADE is an issue. If someone attempts to delete a Branch that
> has a running job, I suspect we actually want to generate an error (or will
> things somehow progress just fine despite the branch disappearing part of the
> way through the process?). There is quite a bit of logic in branch deletion on
> when branches can be deleted, and the DB constraints serve as a safety net for
> that. The ON DELETE CASCADE on the job column seems sane.

I didn't feel like weighing down that cleanup logic even further—only to simulate a regular cascade AFAICS. But I'll go the safe route and remove the cascading for now.

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

The database patch looks good, but it leaves me wondering, where do the results of the job go?

On the code side, the interface that you have there looks an awful lot like IBranchJob -- should it subclass from it? A lot of the branch jobs use IFooJobSource, rather than IFooJobSet. Perhaps it's worth considering using similar names.

jml

review: Needs Information (db)
Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :

> The database patch looks good, but it leaves me wondering, where do the
> results of the job go?

That goes through completely separate channels. The slaves that run these jobs are untrusted, so they're not allowed anywhere near the database. A master-side script will pick up the files they produce (as already happens for the existing Soyuz build jobs) and "upload" them to the regular Translations import queue.

> On the code side, the interface that you have there looks an awful lot like
> IBranchJob -- should it subclass from it? A lot of the branch jobs use
> IFooJobSource, rather than IFooJobSet. Perhaps it's worth considering using
> similar names.

An interesting idea, but this class doesn't have a "metadata" attribute yet. It may still sprout one; at that point it'd be the sensible thing to do. I've added a note.

Revision history for this message
Stuart Bishop (stub) wrote :

Fine if we drop ON DELETE CASCADE from the branch foreign key definition.

review: Approve (db)
Revision history for this message
Tim Penhey (thumper) wrote :

I don't think this database patch is necessary. The is a branch job, it should use the branch job table.

review: Disapprove
Revision history for this message
Stuart Bishop (stub) wrote :

> Fine if we drop ON DELETE CASCADE from the branch foreign key definition.

And change the SERIAL UNIQUE to SERIAL PRIMARY KEY.

(which we would have picked up when staging failed to rebuild since we can't replicate tables without primary keys).

Using BranchJob may indeed be a better alternative - it already has everything you need. If you want a separate table I think we need some sort of rationalization.

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

Thinking more about it, I think that Tim is right -- we should use BranchJob for this. There are other branch job implementations with empty metadata dicts -- it's an entirely cromulent approach, and we shouldn't add new tables without a good reason.

Revision history for this message
Jonathan Lange (jml) :
review: Needs Fixing (db)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'database/schema/comments.sql'
--- database/schema/comments.sql 2009-12-01 13:45:58 +0000
+++ database/schema/comments.sql 2010-01-06 10:28:19 +0000
@@ -1837,6 +1837,11 @@
1837COMMENT ON COLUMN TranslationImportQueueEntry.status IS 'The status of the import: 1 Approved, 2 Imported, 3 Deleted, 4 Failed, 5 Needs Review, 6 Blocked.';1837COMMENT ON COLUMN TranslationImportQueueEntry.status IS 'The status of the import: 1 Approved, 2 Imported, 3 Deleted, 4 Failed, 5 Needs Review, 6 Blocked.';
1838COMMENT ON COLUMN TranslationImportQueueEntry.error_output IS 'Error output from last import attempt.';1838COMMENT ON COLUMN TranslationImportQueueEntry.error_output IS 'Error output from last import attempt.';
18391839
1840-- TranslationTemplatesBuildJob
1841COMMENT ON TABLE TranslationTemplatesBuildJob IS 'Buildfarm job for generating translation templates from a branch.';
1842COMMENT ON COLUMN TranslationTemplatesBuildJob.branch IS 'Source code branch that the job will generate templates for.';
1843COMMENT ON COLUMN TranslationTemplatesBuildJob.job IS 'Base Job details.';
1844
1840-- Archive1845-- Archive
1841COMMENT ON TABLE Archive IS 'A package archive. Commonly either a distribution''s main_archive or a ppa''s archive.';1846COMMENT ON TABLE Archive IS 'A package archive. Commonly either a distribution''s main_archive or a ppa''s archive.';
1842COMMENT ON COLUMN Archive.owner IS 'Identifies the PPA owner when it has one.';1847COMMENT ON COLUMN Archive.owner IS 'Identifies the PPA owner when it has one.';
18431848
=== added file 'database/schema/patch-2207-22-0.sql'
--- database/schema/patch-2207-22-0.sql 1970-01-01 00:00:00 +0000
+++ database/schema/patch-2207-22-0.sql 2010-01-06 10:28:20 +0000
@@ -0,0 +1,16 @@
1-- Copyright 2009 Canonical Ltd. This software is licensed under the
2-- GNU Affero General Public License version 3 (see the file LICENSE).
3
4SET client_min_messages=ERROR;
5
6CREATE TABLE TranslationTemplatesBuildJob (
7 id SERIAL UNIQUE,
8 branch integer NOT NULL REFERENCES Branch(id),
9 job integer NOT NULL REFERENCES Job(id) ON DELETE CASCADE);
10
11CREATE INDEX translationtemplatesbuildjob__branch__idx
12 ON TranslationTemplatesBuildJob(branch);
13CREATE INDEX translationtemplatesbuildjob__job__idx
14 ON TranslationTemplatesBuildJob(job);
15
16INSERT INTO LaunchpadDatabaseRevision VALUES (2207, 22, 0);
017
=== modified file 'database/schema/security.cfg'
--- database/schema/security.cfg 2010-01-06 07:05:19 +0000
+++ database/schema/security.cfg 2010-01-06 10:28:20 +0000
@@ -293,6 +293,7 @@
293public.translationgroup = SELECT, INSERT, UPDATE293public.translationgroup = SELECT, INSERT, UPDATE
294public.translationimportqueueentry = SELECT, INSERT, UPDATE, DELETE294public.translationimportqueueentry = SELECT, INSERT, UPDATE, DELETE
295public.translationmessage = SELECT, INSERT, UPDATE295public.translationmessage = SELECT, INSERT, UPDATE
296public.translationtemplatesbuildjob = SELECT, INSERT
296public.translator = SELECT, INSERT, UPDATE, DELETE297public.translator = SELECT, INSERT, UPDATE, DELETE
297public.usertouseremail = SELECT, UPDATE298public.usertouseremail = SELECT, UPDATE
298public.validpersoncache = SELECT299public.validpersoncache = SELECT
299300
=== modified file 'lib/lp/buildmaster/interfaces/buildfarmjob.py'
--- lib/lp/buildmaster/interfaces/buildfarmjob.py 2009-12-24 14:18:35 +0000
+++ lib/lp/buildmaster/interfaces/buildfarmjob.py 2010-01-06 10:28:19 +0000
@@ -46,24 +46,24 @@
46 Build a package from a bazaar branch and a recipe.46 Build a package from a bazaar branch and a recipe.
47 """)47 """)
4848
49 TRANSLATION = DBItem(4, """49 TRANSLATIONTEMPLATESBUILD = DBItem(4, """
50 TranslationJob50 TranslationTemplatesBuildJob
5151
52 Perform a translation job.52 Generate translation templates from a bazaar branch.
53 """)53 """)
5454
5555
56class IBuildFarmJob(Interface):56class IBuildFarmJob(Interface):
57 """Operations that Soyuz build farm jobs must implement."""57 """Operations that jobs for the build farm must implement."""
5858
59 def score():59 def score():
60 """Calculate a job score appropriate for the job type in question."""60 """Calculate a job score appropriate for the job type in question."""
6161
62 def getLogFileName():62 def getLogFileName():
63 """The preferred file name for the log of this Soyuz job."""63 """The preferred file name for the log of this job."""
6464
65 def getName():65 def getName():
66 """An appropriate name for this Soyuz job."""66 """An appropriate name for this job."""
6767
68 def jobStarted():68 def jobStarted():
69 """'Job started' life cycle event, handle as appropriate."""69 """'Job started' life cycle event, handle as appropriate."""
7070
=== modified file 'lib/lp/translations/configure.zcml'
--- lib/lp/translations/configure.zcml 2009-12-28 22:58:18 +0000
+++ lib/lp/translations/configure.zcml 2010-01-06 10:28:20 +0000
@@ -572,6 +572,22 @@
572 interface="lp.translations.interfaces.poexportrequest.IPOExportRequestSet"/>572 interface="lp.translations.interfaces.poexportrequest.IPOExportRequestSet"/>
573 </securedutility>573 </securedutility>
574574
575 <class
576 class="lp.translations.model.translationtemplatesbuildjob.TranslationTemplatesBuildJob">
577 <allow interface="lp.buildmaster.interfaces.buildfarmjob.IBuildFarmJob"/>
578 <allow interface="lp.translations.interfaces.translationtemplatesbuildjob.ITranslationTemplatesBuildJob"/>
579 </class>
580 <securedutility
581 class="lp.translations.model.translationtemplatesbuildjob.TranslationTemplatesBuildJobSet"
582 provides="lp.translations.interfaces.translationtemplatesbuildjob.ITranslationTemplatesBuildJobSet">
583 <allow interface="lp.translations.interfaces.translationtemplatesbuildjob.ITranslationTemplatesBuildJobSet"/>
584 </securedutility>
585 <adapter
586 for="lp.translations.interfaces.translationtemplatesbuildjob.ITranslationTemplatesBuildJob"
587 provides="lp.buildmaster.interfaces.buildfarmjobbehavior.IBuildFarmJobBehavior"
588 factory="lp.translations.model.translationtemplatesbuildbehavior.TranslationTemplatesBuildBehavior"
589 permission="zope.Public"/>
590
575 <webservice:register module="lp.translations.interfaces.webservice" />591 <webservice:register module="lp.translations.interfaces.webservice" />
576592
577</configure>593</configure>
578594
=== added file 'lib/lp/translations/interfaces/translationtemplatesbuildjob.py'
--- lib/lp/translations/interfaces/translationtemplatesbuildjob.py 1970-01-01 00:00:00 +0000
+++ lib/lp/translations/interfaces/translationtemplatesbuildjob.py 2010-01-06 10:28:19 +0000
@@ -0,0 +1,52 @@
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# pylint: disable-msg=E0213
5
6__metaclass__ = type
7
8__all__ = [
9 'ITranslationTemplatesBuildJob',
10 'ITranslationTemplatesBuildJobSet',
11 ]
12
13from zope.interface import Interface
14from zope.schema import Int
15
16from lazr.restful.fields import Reference
17
18from canonical.launchpad import _
19
20from lp.services.job.interfaces.job import IJob
21from lp.code.interfaces.branch import IBranch
22
23
24class ITranslationTemplatesBuildJob(Interface):
25 """Build-farm job object for building translation templates."""
26
27 id = Int(title=_("ID"), required=True, readonly=True)
28
29 job = Reference(
30 title=_("Generic Job record"),
31 readonly=True, required=True, schema=IJob)
32
33 branch = Reference(
34 title=_("Source code branch"),
35 readonly=True, required=True, schema=IBranch)
36
37
38class ITranslationTemplatesBuildJobSet(Interface):
39 """The container for `ITranslationTemplatesBuildJob`s."""
40
41 def new(branch):
42 """Create new `ITranslationTemplatesBuildJob`.
43
44 Also creates the matching `IBuildQueue` and `IJob` entries.
45
46 :param branch: A `Branch` that this job is to check out and
47 generate templates for.
48 :return: A new `ITranslationTemplatesBuildJob`.
49 """
50
51 def getForJob(job):
52 """Find `ITranslationTemplatesBuildJob` matching given `Job`."""
053
=== added file 'lib/lp/translations/model/translationtemplatesbuildbehavior.py'
--- lib/lp/translations/model/translationtemplatesbuildbehavior.py 1970-01-01 00:00:00 +0000
+++ lib/lp/translations/model/translationtemplatesbuildbehavior.py 2010-01-06 10:28:19 +0000
@@ -0,0 +1,81 @@
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"""An `IBuildFarmJobBehavior` for `TranslationTemplatesBuildJob`.
5
6Dispatches translation template build jobs to build-farm slaves.
7"""
8
9__metaclass__ = type
10__all__ = [
11 'TranslationTemplatesBuildBehavior',
12 ]
13
14import socket
15import xmlrpclib
16
17from zope.component import getUtility
18from zope.interface import implements
19
20from canonical.launchpad.interfaces import ILaunchpadCelebrities
21
22from lp.buildmaster.interfaces.buildfarmjobbehavior import (
23 IBuildFarmJobBehavior)
24from lp.soyuz.interfaces.builder import BuildSlaveFailure
25from lp.translations.interfaces.translationtemplatesbuildjob import (
26 ITranslationTemplatesBuildJobSet)
27from lp.buildmaster.model.buildfarmjobbehavior import (
28 BuildFarmJobBehaviorBase)
29
30
31class TranslationTemplatesBuildBehavior(BuildFarmJobBehaviorBase):
32 """Dispatches `TranslationTemplateBuildJob`s to slaves."""
33 # Note: If this class had a "metadata" dict, it'd effectively be
34 # implementing IBranchJob as well.
35 implements(IBuildFarmJobBehavior)
36
37 # XXX JeroenVermeulen 2009-12-24 bug=499405: What really goes here?
38 build_type = 'translation-templates'
39
40 def dispatchBuildToSlave(self, build_queue_item, logger):
41 """See `IBuildFarmJobBehavior`."""
42 # XXX JeroenVermeulen 2009-12-24 bug=500110: This method is not
43 # covered by tests yet. Either unify it with Soyuz code into a
44 # generalised method, or test it.
45 templatesbuildjob = self._findTranslationTemplatesBuildJob(
46 build_queue_item)
47 chroot = self._getChroot()
48 chroot_sha1 = chroot.content.sha1
49 self._builder.cacheFileOnSlave(logger, chroot)
50 buildid = templatesbuildjob.getName()
51
52 args = { 'branch_url': build_queue_item.branch.url }
53 filemap = {}
54
55 try:
56 status, info = self._builder.slave.build(
57 buildid, self.build_type, chroot_sha1, filemap, args)
58 except xmlrpclib.Fault, info:
59 # Mark builder as 'failed'.
60 logger.debug(
61 "Disabling builder: %s" % self._builder.url, exc_info=1)
62 self._builder.failbuilder(
63 "Exception (%s) when setting up to new job" % info)
64 raise BuildSlaveFailure
65 except socket.error, info:
66 error_message = "Exception (%s) when setting up new job" % info
67 self._builder.handleTimeout(logger, error_message)
68 raise BuildSlaveFailure
69
70 def _getChroot(self):
71 ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
72 return ubuntu.currentseries.nominatedarchindep
73
74 def _findTranslationTemplatesBuildJob(self, build_queue_item):
75 """Find the `TranslationTemplatesBuildJob` for a job.
76
77 :param build_queue_item: A `BuildQueue` entry.
78 :return: The matching `TranslationTemplatesBuildJob`.
79 """
80 buildjobset = getUtility(ITranslationTemplatesBuildJobSet)
81 return buildjobset.getForJob(build_queue_item.job)
082
=== added file 'lib/lp/translations/model/translationtemplatesbuildjob.py'
--- lib/lp/translations/model/translationtemplatesbuildjob.py 1970-01-01 00:00:00 +0000
+++ lib/lp/translations/model/translationtemplatesbuildjob.py 2010-01-06 10:28:20 +0000
@@ -0,0 +1,93 @@
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__all__ = [
6 'TranslationTemplatesBuildJob'
7 ]
8
9import re
10from datetime import timedelta
11
12from zope.component import getUtility
13from zope.interface import implements
14
15from storm.locals import Int, Reference, Storm
16
17from canonical.launchpad.webapp.interfaces import (
18 DEFAULT_FLAVOR, IStoreSelector, MAIN_STORE, MASTER_FLAVOR)
19
20from lp.buildmaster.interfaces.buildfarmjob import BuildFarmJobType
21from lp.buildmaster.model.buildfarmjob import BuildFarmJob
22from lp.services.job.model.job import Job
23from lp.soyuz.model.buildqueue import BuildQueue
24from lp.translations.interfaces.translationtemplatesbuildjob import (
25 ITranslationTemplatesBuildJob, ITranslationTemplatesBuildJobSet)
26
27
28class TranslationTemplatesBuildJob(BuildFarmJob, Storm):
29 """An `IBuildFarmJob` implementation that generates templates."""
30 implements(ITranslationTemplatesBuildJob)
31
32 __storm_table__ = 'TranslationTemplatesBuildJob'
33
34 unsafe_chars = '[^a-zA-Z0-9_+-]'
35
36 id = Int(primary=True)
37
38 job_id = Int(name='job', allow_none=False)
39 job = Reference(job_id, 'Job.id')
40
41 branch_id = Int(name='branch', allow_none=False)
42 branch = Reference(branch_id, 'Branch.id')
43
44 def score(self):
45 """See `IBuildFarmJob`."""
46 # Arbitrary score that sorta-kinda seems to match the sort of
47 # number that BuildPackageJob might give a job like this,
48 # perhaps. It may not matter that much since these jobs are
49 # fast.
50 return 4010
51
52 def getLogFileName(self):
53 """See `IBuildFarmJob`."""
54 sanitized_name = re.sub(self.unsafe_chars, '_', self.getName())
55 return "translationtemplates_%s" % sanitized_name
56
57 def getName(self):
58 """See `IBuildFarmJob`."""
59 return '%s-%d' % (self.branch.name, self.id)
60
61
62class TranslationTemplatesBuildJobSet:
63 """See `ITranslationTemplatesBuildJobSet`."""
64 implements(ITranslationTemplatesBuildJobSet)
65
66 duration_estimate = timedelta(seconds=10)
67
68 def new(self, branch):
69 """See `ITranslationTemplatesBuildJobSet`."""
70 store = getUtility(IStoreSelector).get(MAIN_STORE, MASTER_FLAVOR)
71 job = Job()
72 store.add(job)
73
74 specific_job = TranslationTemplatesBuildJob()
75 specific_job.branch = branch
76 specific_job.job = job
77 store.add(specific_job)
78
79 duration_estimate = self.duration_estimate
80 build_queue_entry = BuildQueue(
81 estimated_duration=duration_estimate,
82 job_type=BuildFarmJobType.TRANSLATIONTEMPLATESBUILD,
83 job=job.id)
84 store.add(build_queue_entry)
85
86 return specific_job
87
88 def getForJob(self, job):
89 """See `ITranslationTemplatesBuildJobSet`."""
90 store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR)
91 return store.find(
92 TranslationTemplatesBuildJob,
93 TranslationTemplatesBuildJob.job == job).one()
094
=== added file 'lib/lp/translations/tests/test_translationtemplatesbuildjob.py'
--- lib/lp/translations/tests/test_translationtemplatesbuildjob.py 1970-01-01 00:00:00 +0000
+++ lib/lp/translations/tests/test_translationtemplatesbuildjob.py 2010-01-06 10:28:19 +0000
@@ -0,0 +1,106 @@
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
6from unittest import TestLoader
7
8from zope.component import getUtility
9from zope.security.proxy import removeSecurityProxy
10
11from canonical.launchpad.webapp.testing import verifyObject
12from canonical.testing import ZopelessDatabaseLayer
13
14from lp.testing import TestCaseWithFactory
15
16from lp.buildmaster.interfaces.buildfarmjob import IBuildFarmJob
17from lp.buildmaster.interfaces.buildfarmjobbehavior import (
18 IBuildFarmJobBehavior)
19from lp.services.job.model.job import Job
20from lp.soyuz.interfaces.buildqueue import IBuildQueueSet
21from lp.soyuz.model.buildqueue import BuildQueue
22from lp.translations.interfaces.translationtemplatesbuildjob import (
23 ITranslationTemplatesBuildJob, ITranslationTemplatesBuildJobSet)
24
25
26def get_job_id(job):
27 """Peek inside a `Job` and retrieve its id."""
28 return removeSecurityProxy(job).id
29
30
31class TestTranslationTemplatesBuildJob(TestCaseWithFactory):
32 """Test `TranslationTemplatesBuildJob`."""
33
34 layer = ZopelessDatabaseLayer
35
36 def setUp(self):
37 super(TestTranslationTemplatesBuildJob, self).setUp()
38 self.jobset = getUtility(ITranslationTemplatesBuildJobSet)
39 self.branch = self.factory.makeBranch()
40 self.specific_job = self.jobset.new(self.branch)
41
42 def test_new_TranslationTemplatesBuildJob(self):
43 # TranslationTemplateBuildJob implements IBuildFarmJob and
44 # ITranslationTemplatesBuildJob.
45 verifyObject(IBuildFarmJob, self.specific_job)
46 verifyObject(ITranslationTemplatesBuildJob, self.specific_job)
47
48 # Each of these jobs knows the branch it will operate on.
49 self.assertEqual(self.branch, self.specific_job.branch)
50
51 def test_has_Job(self):
52 # Associated with each TranslationTemplateBuildJob is a Job.
53 base_job = self.specific_job.job
54 self.assertIsInstance(base_job, Job)
55
56 # From a Job, the TranslationTemplatesBuildJobSet can find the
57 # TranslationTemplatesBuildJob back for us.
58 self.assertEqual(self.specific_job, self.jobset.getForJob(base_job))
59
60 def test_has_BuildQueue(self):
61 # There's also a BuildQueue item associated with the job.
62 queueset = getUtility(IBuildQueueSet)
63 job_id = get_job_id(self.specific_job.job)
64 buildqueue = queueset.get(job_id)
65
66 self.assertIsInstance(buildqueue, BuildQueue)
67 self.assertEqual(job_id, get_job_id(buildqueue.job))
68
69 def test_getName(self):
70 # Each job gets a unique name.
71 other_job = self.jobset.new(self.branch)
72 self.assertNotEqual(self.specific_job.getName(), other_job.getName())
73
74 def test_getLogFileName(self):
75 # Each job has a unique log file name.
76 other_job = self.jobset.new(self.branch)
77 self.assertNotEqual(
78 self.specific_job.getLogFileName(), other_job.getLogFileName())
79
80
81class TestTranslationTemplatesBuildBehavior(TestCaseWithFactory):
82 """Test `TranslationTemplatesBuildBehavior`."""
83
84 layer = ZopelessDatabaseLayer
85
86 def setUp(self):
87 super(TestTranslationTemplatesBuildBehavior, self).setUp()
88 self.jobset = getUtility(ITranslationTemplatesBuildJobSet)
89 self.branch = self.factory.makeBranch()
90 self.specific_job = self.jobset.new(self.branch)
91 self.behavior = IBuildFarmJobBehavior(self.specific_job)
92
93 def test_getChroot(self):
94 chroot = self.behavior._getChroot()
95 self.assertNotEqual(None, chroot)
96
97 def test_findTranslationTemplatesBuildJob(self):
98 buildqueue = self.jobset.getForJob(self.specific_job.job)
99
100 self.assertEqual(
101 self.specific_job,
102 self.behavior._findTranslationTemplatesBuildJob(buildqueue))
103
104
105def test_suite():
106 return TestLoader().loadTestsFromName(__name__)

Subscribers

People subscribed via source and target branches

to status/vote changes: