~launchpad-pqm/launchpad/devel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# Copyright 2010 Canonical Ltd.  This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).


__metaclass__ = type


from datetime import timedelta

from storm.locals import Store
from zope.security.proxy import removeSecurityProxy

from lp.buildmaster.enums import BuildStatus
from lp.code.mail.sourcepackagerecipebuild import (
    SourcePackageRecipeBuildMailer,
    )
from lp.services.config import config
from lp.services.webapp import canonical_url
from lp.testing import TestCaseWithFactory
from lp.testing.layers import LaunchpadFunctionalLayer


expected_body = u"""\
 * State: Successfully built
 * Recipe: person/recipe
 * Archive: archiveowner/ppa
 * Distroseries: distroseries
 * Duration: 5 minutes
 * Build Log: %s
 * Upload Log: 
 * Builder: http://launchpad.dev/builders/bob
"""

superseded_body = u"""\
 * State: Build for superseded Source
 * Recipe: person/recipe
 * Archive: archiveowner/ppa
 * Distroseries: distroseries
 * Duration: 
 * Build Log: 
 * Upload Log: 
 * Builder: 
"""

class TestSourcePackageRecipeBuildMailer(TestCaseWithFactory):

    layer = LaunchpadFunctionalLayer

    def makeStatusEmail(self, build):
        mailer = SourcePackageRecipeBuildMailer.forStatus(build)
        email = removeSecurityProxy(build.requester).preferredemail.email
        return mailer.generateEmail(email, build.requester)

    def test_generateEmail(self):
        """GenerateEmail produces the right headers and body."""
        person = self.factory.makePerson(name='person')
        cake = self.factory.makeSourcePackageRecipe(
            name=u'recipe', owner=person)
        pantry_owner = self.factory.makePerson(name='archiveowner')
        pantry = self.factory.makeArchive(name='ppa', owner=pantry_owner)
        secret = self.factory.makeDistroSeries(name=u'distroseries')
        build = self.factory.makeSourcePackageRecipeBuild(
            recipe=cake, distroseries=secret, archive=pantry,
            status=BuildStatus.FULLYBUILT, duration=timedelta(minutes=5))
        naked_build = removeSecurityProxy(build)
        naked_build.builder = self.factory.makeBuilder(name='bob')
        naked_build.log = self.factory.makeLibraryFileAlias()
        Store.of(build).flush()
        ctrl = self.makeStatusEmail(build)
        self.assertEqual(
            u'[recipe build #%d] of ~person recipe in distroseries: '
            'Successfully built' % (build.id), ctrl.subject)
        body, footer = ctrl.body.split('\n-- \n')
        self.assertEqual(
            expected_body % build.log.getURL(), body)
        build_url = canonical_url(build)
        self.assertEqual(
            '%s\nYou are the requester of the build.\n' % build_url, footer)
        self.assertEqual(
            config.canonical.noreply_from_address, ctrl.from_addr)
        self.assertEqual(
            'Requester', ctrl.headers['X-Launchpad-Message-Rationale'])
        self.assertEqual(
            'recipe-build-status',
            ctrl.headers['X-Launchpad-Notification-Type'])
        self.assertEqual(
            'FULLYBUILT', ctrl.headers['X-Launchpad-Build-State'])

    def test_generateEmail_with_null_fields(self):
        """GenerateEmail works when many fields are NULL."""
        person = self.factory.makePerson(name='person')
        cake = self.factory.makeSourcePackageRecipe(
            name=u'recipe', owner=person)
        pantry_owner = self.factory.makePerson(name='archiveowner')
        pantry = self.factory.makeArchive(name='ppa', owner=pantry_owner)
        secret = self.factory.makeDistroSeries(name=u'distroseries')
        build = self.factory.makeSourcePackageRecipeBuild(
            recipe=cake, distroseries=secret, archive=pantry,
            status=BuildStatus.SUPERSEDED)
        Store.of(build).flush()
        ctrl = self.makeStatusEmail(build)
        self.assertEqual(
            u'[recipe build #%d] of ~person recipe in distroseries: '
            'Build for superseded Source' % (build.id), ctrl.subject)
        body, footer = ctrl.body.split('\n-- \n')
        self.assertEqual(superseded_body, body)
        build_url = canonical_url(build)
        self.assertEqual(
            '%s\nYou are the requester of the build.\n' % build_url, footer)
        self.assertEqual(
            config.canonical.noreply_from_address, ctrl.from_addr)
        self.assertEqual(
            'Requester', ctrl.headers['X-Launchpad-Message-Rationale'])
        self.assertEqual(
            'recipe-build-status',
            ctrl.headers['X-Launchpad-Notification-Type'])
        self.assertEqual(
            'SUPERSEDED', ctrl.headers['X-Launchpad-Build-State'])

    def test_generateEmail_upload_failure(self):
        """GenerateEmail works when many fields are NULL."""
        build = self.factory.makeSourcePackageRecipeBuild()
        removeSecurityProxy(build).upload_log = (
            self.factory.makeLibraryFileAlias())
        upload_log_fragment = 'Upload Log: %s' % build.upload_log_url
        ctrl = self.makeStatusEmail(build)
        self.assertTrue(upload_log_fragment in ctrl.body)