1
# Copyright 2010 Canonical Ltd. This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
4
from __future__ import with_statement
6
"""Tests for `IBuildBase`.
8
XXX 2010-04-26 michael.nelson bug=567922.
9
These tests should be moved into test_packagebuild when buildbase is
10
deleted. For the moment, test_packagebuild inherits these tests to
11
ensure the new classes pass too.
15
from datetime import datetime
18
from zope.security.proxy import removeSecurityProxy
20
from canonical.config import config
21
from canonical.database.constants import UTC_NOW
22
from canonical.testing.layers import LaunchpadZopelessLayer
23
from lp.buildmaster.interfaces.buildbase import BuildStatus
24
from lp.buildmaster.model.buildbase import BuildBase
25
from lp.registry.interfaces.pocket import pocketsuffix
26
from lp.soyuz.tests.soyuzbuilddhelpers import WaitingSlave
27
from lp.testing import TestCase
28
from lp.testing.fakemethod import FakeMethod
31
class TestBuildBaseMixin:
32
"""Tests for `IBuildBase`."""
34
def test_getUploadDirLeaf(self):
35
# getUploadDirLeaf returns the current time, followed by the build
38
build_cookie = self.factory.getUniqueString()
39
upload_leaf = self.package_build.getUploadDirLeaf(
40
build_cookie, now=now)
42
'%s-%s' % (now.strftime("%Y%m%d-%H%M%S"), build_cookie),
45
def test_getUploadDir(self):
46
# getUploadDir is the absolute path to the directory in which things
48
build_cookie = self.factory.getUniqueInteger()
49
upload_leaf = self.package_build.getUploadDirLeaf(build_cookie)
50
upload_dir = self.package_build.getUploadDir(upload_leaf)
52
os.path.join(config.builddmaster.root, 'incoming', upload_leaf),
56
class TestBuildBase(TestCase, TestBuildBaseMixin):
59
"""Create the package build for testing."""
60
super(TestBuildBase, self).setUp()
61
self.package_build = BuildBase()
64
class TestGetUploadMethodsMixin:
65
"""Tests for `IBuildBase` that need objects from the rest of Launchpad."""
67
layer = LaunchpadZopelessLayer
70
"""Allow classes to override the build with which the test runs.
72
XXX michaeln 2010-06-03 bug=567922
73
Until buildbase is removed, we need to ensure these tests
74
run against new IPackageBuild builds (BinaryPackageBuild)
75
and the IBuildBase builds (SPRecipeBuild). They assume the build
76
is successfully built and check that incorrect upload paths will
77
set the status to FAILEDTOUPLOAD.
82
super(TestGetUploadMethodsMixin, self).setUp()
83
self.build = self.makeBuild()
85
def test_getUploadLogContent_nolog(self):
86
"""If there is no log file there, a string explanation is returned.
89
self.assertEquals('Could not find upload log file',
90
self.build.getUploadLogContent(os.getcwd(), "myleaf"))
92
def test_getUploadLogContent_only_dir(self):
93
"""If there is a directory but no log file, expect the error string,
96
os.makedirs("accepted/myleaf")
97
self.assertEquals('Could not find upload log file',
98
self.build.getUploadLogContent(os.getcwd(), "myleaf"))
100
def test_getUploadLogContent_readsfile(self):
101
"""If there is a log file, return its contents."""
103
os.makedirs("accepted/myleaf")
104
with open('accepted/myleaf/uploader.log', 'w') as f:
106
self.assertEquals('foo',
107
self.build.getUploadLogContent(os.getcwd(), "myleaf"))
109
def test_getUploaderCommand(self):
110
upload_leaf = self.factory.getUniqueString('upload-leaf')
111
config_args = list(config.builddmaster.uploader.split())
112
log_file = self.factory.getUniqueString('logfile')
114
['--log-file', log_file,
115
'-d', self.build.distribution.name,
116
'-s', (self.build.distro_series.name
117
+ pocketsuffix[self.build.pocket]),
118
'-b', str(self.build.id),
120
'--context=%s' % self.build.policy_name,
121
os.path.abspath(config.builddmaster.root),
123
uploader_command = self.build.getUploaderCommand(
124
self.build, upload_leaf, log_file)
125
self.assertEqual(config_args, uploader_command)
128
class TestHandleStatusMixin:
129
"""Tests for `IBuildBase`s handleStatus method.
131
Note: these tests do *not* test the updating of the build
132
status to FULLYBUILT as this happens during the upload which
133
is stubbed out by a mock function.
136
layer = LaunchpadZopelessLayer
139
"""Allow classes to override the build with which the test runs.
141
XXX michaeln 2010-06-03 bug=567922
142
Until buildbase is removed, we need to ensure these tests
143
run against new IPackageBuild builds (BinaryPackageBuild)
144
and the IBuildBase builds (SPRecipeBuild). They assume the build
145
is successfully built and check that incorrect upload paths will
146
set the status to FAILEDTOUPLOAD.
148
raise NotImplementedError
151
super(TestHandleStatusMixin, self).setUp()
152
self.build = self.makeBuild()
153
# For the moment, we require a builder for the build so that
154
# handleStatus_OK can get a reference to the slave.
155
builder = self.factory.makeBuilder()
156
self.build.buildqueue_record.builder = builder
157
self.build.buildqueue_record.setDateStarted(UTC_NOW)
158
self.slave = WaitingSlave('BuildStatus.OK')
159
self.slave.valid_file_hashes.append('test_file_hash')
160
builder.setSlaveForTesting(self.slave)
162
# We overwrite the buildmaster root to use a temp directory.
163
tmp_dir = self.makeTemporaryDirectory()
164
tmp_builddmaster_root = """
168
config.push('tmp_builddmaster_root', tmp_builddmaster_root)
170
# We stub out our builds getUploaderCommand() method so
171
# we can check whether it was called as well as
172
# verifySuccessfulUpload().
173
self.fake_getUploaderCommand = FakeMethod(
174
result=['echo', 'noop'])
175
removeSecurityProxy(self.build).getUploaderCommand = (
176
self.fake_getUploaderCommand)
177
removeSecurityProxy(self.build).verifySuccessfulUpload = FakeMethod(
180
def test_handleStatus_OK_normal_file(self):
181
# A filemap with plain filenames should not cause a problem.
182
# The call to handleStatus will attempt to get the file from
183
# the slave resulting in a URL error in this test case.
184
self.build.handleStatus('OK', None, {
185
'filemap': {'myfile.py': 'test_file_hash'},
188
self.assertEqual(BuildStatus.FULLYBUILT, self.build.status)
189
self.assertEqual(1, self.fake_getUploaderCommand.call_count)
191
def test_handleStatus_OK_absolute_filepath(self):
192
# A filemap that tries to write to files outside of
193
# the upload directory will result in a failed upload.
194
self.build.handleStatus('OK', None, {
195
'filemap': {'/tmp/myfile.py': 'test_file_hash'},
197
self.assertEqual(BuildStatus.FAILEDTOUPLOAD, self.build.status)
198
self.assertEqual(0, self.fake_getUploaderCommand.call_count)
200
def test_handleStatus_OK_relative_filepath(self):
201
# A filemap that tries to write to files outside of
202
# the upload directory will result in a failed upload.
203
self.build.handleStatus('OK', None, {
204
'filemap': {'../myfile.py': 'test_file_hash'},
206
self.assertEqual(BuildStatus.FAILEDTOUPLOAD, self.build.status)
207
self.assertEqual(0, self.fake_getUploaderCommand.call_count)
209
def test_handleStatus_OK_sets_build_log(self):
210
# The build log is set during handleStatus.
211
removeSecurityProxy(self.build).log = None
212
self.assertEqual(None, self.build.log)
213
self.build.handleStatus('OK', None, {
214
'filemap': {'myfile.py': 'test_file_hash'},
216
self.assertNotEqual(None, self.build.log)
218
def test_date_finished_set(self):
219
# The date finished is updated during handleStatus_OK.
220
removeSecurityProxy(self.build).date_finished = None
221
self.assertEqual(None, self.build.date_finished)
222
self.build.handleStatus('OK', None, {
223
'filemap': {'myfile.py': 'test_file_hash'},
225
self.assertNotEqual(None, self.build.date_finished)