~andrewjbeach/juju-ci-tools/make-local-patcher

« back to all changes in this revision

Viewing changes to tests/test_upload_jenkins_job.py

  • Committer: Aaron Bentley
  • Date: 2015-01-19 15:32:33 UTC
  • mto: This revision was merged to the branch mainline in revision 804.
  • Revision ID: aaron.bentley@canonical.com-20150119153233-jjcvikwiw1dx2lak
Print error on missing environment.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
from argparse import Namespace
2
 
from ConfigParser import NoOptionError
3
 
import json
4
 
from time import sleep
5
 
from unittest import TestCase
6
 
 
7
 
from mock import patch, MagicMock, call
8
 
from tempfile import NamedTemporaryFile
9
 
 
10
 
from jujuci import (
11
 
    Credentials,
12
 
    JENKINS_URL,
13
 
)
14
 
from upload_jenkins_job import (
15
 
    get_args,
16
 
    get_s3_access,
17
 
    S3Uploader,
18
 
    JenkinsBuild,
19
 
    S3,
20
 
)
21
 
 
22
 
 
23
 
__metaclass__ = type
24
 
 
25
 
 
26
 
JOB_NAME = 'compatibility-control'
27
 
BUILD_NUM = 1277
28
 
BUCKET = 'juju-qa'
29
 
DIRECTORY = 'foo'
30
 
 
31
 
BUILD_INFO = json.loads(
32
 
    json.dumps(
33
 
        {'building': False,
34
 
         'artifacts': [{"relativePath": "logs/all-machines.log.gz",
35
 
                        "displayPath": "all-machines.log.gz",
36
 
                        "fileName": "all-machines.log.gz"
37
 
                        }],
38
 
         'timestamp': 1411053288000,
39
 
         'number': BUILD_NUM,
40
 
         'result': 'SUCCESS',
41
 
         'duration': 176239,
42
 
         "build_number": 1024,
43
 
         "new_to_old": False,
44
 
         "candidate": "1.21",
45
 
         "old_version": "1.20.5",
46
 
         "url": 'http://juju-ci.vapour.ws:8080/job/compatibility-control/1277/'
47
 
         }))
48
 
 
49
 
 
50
 
class TestJenkinsBuild(TestCase):
51
 
 
52
 
    def test_factory(self):
53
 
        credentials = fake_credentials()
54
 
        with patch('upload_jenkins_job.get_build_data',
55
 
                   autospec=True) as gbd_mock:
56
 
            j = JenkinsBuild.factory(credentials, JOB_NAME)
57
 
        self.assertIs(type(j), JenkinsBuild)
58
 
        self.assertEqual(j.job_name, JOB_NAME)
59
 
        self.assertEqual(j.credentials, credentials)
60
 
        self.assertEqual(j.build_info, None)
61
 
        self.assertEqual(j.jenkins_url, JENKINS_URL)
62
 
        self.assertEqual(gbd_mock.call_count, 0)
63
 
 
64
 
    def test_factory_with_build_number(self):
65
 
        credentials = fake_credentials()
66
 
        with patch('upload_jenkins_job.get_build_data',
67
 
                   autospec=True, return_value=BUILD_INFO) as gbd_mock:
68
 
            j = JenkinsBuild.factory(credentials, JOB_NAME, BUILD_NUM)
69
 
        self.assertIs(type(j), JenkinsBuild)
70
 
        self.assertEqual(j.build_info, BUILD_INFO)
71
 
        gbd_mock.assert_called_once_with(
72
 
            JENKINS_URL, credentials, JOB_NAME, BUILD_NUM)
73
 
 
74
 
    def test_get_build_info(self):
75
 
        credentials = fake_credentials()
76
 
        j = JenkinsBuild(credentials, JOB_NAME, JENKINS_URL, None)
77
 
        with patch('upload_jenkins_job.get_build_data', autospec=True,
78
 
                   return_value=BUILD_INFO) as gbd_mock:
79
 
            build_info = j.get_build_info(BUILD_NUM)
80
 
        self.assertEqual(build_info, BUILD_INFO)
81
 
        gbd_mock.assert_called_once_with(
82
 
            JENKINS_URL, credentials, JOB_NAME, BUILD_NUM)
83
 
 
84
 
    def test_result(self):
85
 
        credentials = fake_credentials()
86
 
        j = JenkinsBuild(credentials, JOB_NAME, None, BUILD_INFO)
87
 
        self.assertEqual(j.result, BUILD_INFO['result'])
88
 
 
89
 
    def test_console_text(self):
90
 
        class Response:
91
 
            text = "console content"
92
 
 
93
 
        credentials = fake_credentials()
94
 
        j = JenkinsBuild(credentials, "fake", None, BUILD_INFO)
95
 
        with patch('upload_jenkins_job.requests.get',
96
 
                   return_value=Response, autospec=True) as u_mock:
97
 
            with patch('upload_jenkins_job.HTTPBasicAuth',
98
 
                       autospec=True) as h_mock:
99
 
                text = j.get_console_text()
100
 
                self.assertEqual(text, 'console content')
101
 
        u_mock.assert_called_once_with(
102
 
            BUILD_INFO['url'] + 'consoleText', auth=h_mock.return_value)
103
 
        h_mock.assert_called_once_with(credentials[0], credentials[1])
104
 
 
105
 
    def test_get_last_completed_build_number(self):
106
 
        last_build = {"lastCompletedBuild": {"number": BUILD_NUM}}
107
 
        credentials = fake_credentials()
108
 
        with patch("upload_jenkins_job.get_job_data", autospec=True,
109
 
                   return_value=last_build) as gjd_mock:
110
 
            j = JenkinsBuild(credentials, JOB_NAME, None, BUILD_INFO)
111
 
            last_build_number = j.get_last_completed_build_number()
112
 
        self.assertEqual(last_build_number, BUILD_NUM)
113
 
        gjd_mock.assert_called_once_with(None, credentials, JOB_NAME)
114
 
 
115
 
    def test_artifacts(self):
116
 
        class Response:
117
 
            content = "artifact content"
118
 
 
119
 
        credentials = fake_credentials()
120
 
        j = JenkinsBuild(credentials, "fake", None, BUILD_INFO)
121
 
        expected = BUILD_INFO['url'] + 'artifact/' + 'logs/all-machines.log.gz'
122
 
        with patch('upload_jenkins_job.requests.get',
123
 
                   return_value=Response, autospec=True) as u_mock:
124
 
            with patch('upload_jenkins_job.HTTPBasicAuth',
125
 
                       return_value=None, autospec=True) as h_mock:
126
 
                    for filename, content in j.artifacts():
127
 
                        self.assertEqual(content, 'artifact content')
128
 
        u_mock.assert_called_once_with(
129
 
            expected, auth=h_mock.return_value)
130
 
        h_mock.assert_called_once_with(credentials.user, credentials.password)
131
 
 
132
 
    def test_get_build_number(self):
133
 
        credentials = fake_credentials()
134
 
        j = JenkinsBuild(credentials, "fake", None, BUILD_INFO)
135
 
        self.assertEqual(j.get_build_number(), BUILD_NUM)
136
 
 
137
 
    def test_set_build_number(self):
138
 
        credentials = fake_credentials()
139
 
        j = JenkinsBuild(credentials, JOB_NAME, JENKINS_URL, None)
140
 
        with patch('upload_jenkins_job.get_build_data', autospec=True,
141
 
                   return_value=BUILD_INFO) as gbd_mock:
142
 
            j.set_build_number(BUILD_NUM)
143
 
            build_info = j.get_build_info(BUILD_NUM)
144
 
        self.assertEqual(build_info, BUILD_INFO)
145
 
        gbd_mock.assert_called_with(
146
 
            JENKINS_URL, credentials, JOB_NAME, BUILD_NUM)
147
 
        self.assertEqual(2, gbd_mock.call_count)
148
 
 
149
 
    def test_is_build_completed(self):
150
 
        credentials = fake_credentials()
151
 
        j = JenkinsBuild(credentials, JOB_NAME, JENKINS_URL, BUILD_INFO)
152
 
        with patch('upload_jenkins_job.get_build_data', autospec=True,
153
 
                   return_value=BUILD_INFO) as gbd_mock:
154
 
            build_status = j.is_build_completed()
155
 
        self.assertIs(build_status, True)
156
 
        self.assertEqual(gbd_mock.mock_calls, create_build_data_calls())
157
 
 
158
 
    def test_is_build_completed_return_false(self):
159
 
        credentials = fake_credentials()
160
 
        build_info = json.loads('{"building": true}')
161
 
        j = JenkinsBuild(credentials, JOB_NAME, JENKINS_URL, BUILD_INFO)
162
 
        with patch('upload_jenkins_job.get_build_data', autospec=True,
163
 
                   return_value=build_info) as gbd_mock:
164
 
            build_status = j.is_build_completed()
165
 
        self.assertIs(build_status, False)
166
 
        self.assertEqual(gbd_mock.mock_calls, create_build_data_calls())
167
 
 
168
 
 
169
 
class TestS3(TestCase):
170
 
    def test_factory(self):
171
 
        cred = ('fake_user', 'fake_pass')
172
 
        s3conn_cxt = patch(
173
 
            'upload_jenkins_job.S3Connection', autospec=True)
174
 
        with s3conn_cxt as j_mock:
175
 
            with patch('upload_jenkins_job.get_s3_access',
176
 
                       return_value=cred, autospec=True) as g_mock:
177
 
                s3 = S3.factory('buck', 'dir')
178
 
                self.assertIs(type(s3), S3)
179
 
                self.assertEqual(s3.dir, 'dir')
180
 
                self.assertEqual(('buck',), j_mock.mock_calls[1][1])
181
 
        g_mock.assert_called_once_with()
182
 
        j_mock.assert_called_once_with(cred[0], cred[1])
183
 
 
184
 
    def test_store(self):
185
 
        b_mock = MagicMock()
186
 
        s3 = S3('/comp-test', 'fake', 'fake', None, b_mock)
187
 
        status = s3.store('fake filename', 'fake data')
188
 
        self.assertTrue(status, True)
189
 
        (b_mock.new_key.return_value.set_contents_from_string.
190
 
            assert_called_once_with('fake data', headers=None))
191
 
 
192
 
 
193
 
class TestS3Uploader(TestCase):
194
 
 
195
 
    def test_factory(self):
196
 
        credentials = fake_credentials()
197
 
        with patch('upload_jenkins_job.S3', autospec=True) as s_mock:
198
 
            with patch('upload_jenkins_job.JenkinsBuild',
199
 
                       autospec=True) as j_mock:
200
 
                h = S3Uploader.factory(credentials, JOB_NAME, BUILD_NUM,
201
 
                                       BUCKET, DIRECTORY)
202
 
                self.assertIs(type(h), S3Uploader)
203
 
                self.assertEqual((BUCKET, DIRECTORY), s_mock.mock_calls[0][1])
204
 
                self.assertEqual(credentials,
205
 
                                 j_mock.mock_calls[0][2]['credentials'])
206
 
                self.assertEqual(JOB_NAME, j_mock.mock_calls[0][2]['job_name'])
207
 
                self.assertEqual(BUILD_NUM,
208
 
                                 j_mock.mock_calls[0][2]['build_number'])
209
 
 
210
 
    def test_upload(self):
211
 
        filename, s3_mock, jenkins_mock = (
212
 
            self._make_upload(file_prefix=BUILD_NUM))
213
 
        h = S3Uploader(s3_mock, jenkins_mock)
214
 
        h.upload()
215
 
        self.assertEqual(s3_mock.store.mock_calls, [
216
 
            call(filename, json.dumps(
217
 
                {"build_info": BUILD_NUM, "number": "2222"}, indent=4),
218
 
                headers={"Content-Type": "application/json"}),
219
 
            call('{}-console-consoleText.txt'.format(BUILD_NUM),
220
 
                 'console text',
221
 
                 headers={"Content-Type": "text/plain; charset=utf8"}),
222
 
            call('{}-log-filename'.format(BUILD_NUM), 'artifact data 1',
223
 
                 headers={"Content-Type": "application/octet-stream"})])
224
 
 
225
 
    def test_upload_unique_id(self):
226
 
        filename, s3_mock, jenkins_mock = self._make_upload(file_prefix='9999')
227
 
        h = S3Uploader(s3_mock, jenkins_mock, unique_id='9999')
228
 
        h.upload()
229
 
        self.assertEqual(s3_mock.store.mock_calls, [
230
 
            call(filename,
231
 
                 ('{\n    "origin_number": 2222, \n    "build_info": 1277, \n '
232
 
                  '   "number": 9999\n}'),
233
 
                 headers={"Content-Type": "application/json"}),
234
 
            call('9999-console-consoleText.txt', 'console text',
235
 
                 headers={"Content-Type": "text/plain; charset=utf8"}),
236
 
            call('9999-log-filename', 'artifact data 1',
237
 
                 headers={"Content-Type": "application/octet-stream"})])
238
 
 
239
 
    def _make_upload(self, file_prefix):
240
 
        filename = '{}-result-results.json'.format(file_prefix)
241
 
        s3_mock = MagicMock()
242
 
        jenkins_mock = MagicMock()
243
 
        jenkins_mock.get_last_completed_build_number.return_value = BUILD_NUM
244
 
        jenkins_mock.get_build_number.return_value = BUILD_NUM
245
 
        jenkins_mock.get_build_info.return_value = {"build_info": BUILD_NUM,
246
 
                                                    "number": "2222"}
247
 
        jenkins_mock.get_console_text.return_value = "console text"
248
 
        jenkins_mock._create_filename.return_value = filename
249
 
        jenkins_mock.artifacts.return_value = fake_artifacts(2)
250
 
        return filename, s3_mock, jenkins_mock
251
 
 
252
 
    def test_upload_all_test_results(self):
253
 
        s3_mock = MagicMock()
254
 
        jenkins_mock = MagicMock()
255
 
        jenkins_mock.get_last_completed_build_number.return_value = 3
256
 
        jenkins_mock.get_build_info.return_value = BUILD_INFO
257
 
        h = S3Uploader(s3_mock, jenkins_mock)
258
 
        h.upload_all_test_results()
259
 
        self.assertEqual(jenkins_mock.set_build_number.mock_calls,
260
 
                         [call(1), call(2), call(3)])
261
 
 
262
 
    def test_upload_test_results(self):
263
 
        filename, headers, s3_mock, jenkins_mock = (
264
 
            self._make_upload_test_results(file_prefix=BUILD_NUM))
265
 
        h = S3Uploader(s3_mock, jenkins_mock)
266
 
        h.upload_test_results()
267
 
        s3_mock.store.assert_called_once_with(
268
 
            filename, json.dumps(jenkins_mock.get_build_info.return_value,
269
 
                                 indent=4), headers=headers)
270
 
 
271
 
    def test_upload_test_results_unique_id(self):
272
 
        filename, headers, s3_mock, jenkins_mock = (
273
 
            self._make_upload_test_results(file_prefix='9999'))
274
 
        h = S3Uploader(s3_mock, jenkins_mock, unique_id='9999')
275
 
        h.upload_test_results()
276
 
        s3_mock.store.assert_called_once_with(
277
 
            filename, json.dumps(jenkins_mock.get_build_info.return_value,
278
 
                                 indent=4), headers=headers)
279
 
 
280
 
    def _make_upload_test_results(self, file_prefix):
281
 
        filename = '{}-result-results.json'.format(file_prefix)
282
 
        headers = {"Content-Type": "application/json"}
283
 
        s3_mock = MagicMock()
284
 
        jenkins_mock = MagicMock()
285
 
        jenkins_mock.get_build_info.return_value = BUILD_INFO
286
 
        jenkins_mock.get_build_number.return_value = BUILD_NUM
287
 
        return filename, headers, s3_mock, jenkins_mock
288
 
 
289
 
    def test_upload_console_log_444444(self):
290
 
        filename, headers, s3_mock, jenkins_mock = (
291
 
            self._make_upload_console_log(file_prefix=BUILD_NUM))
292
 
        h = S3Uploader(s3_mock, jenkins_mock)
293
 
        h.upload_console_log()
294
 
        s3_mock.store.assert_called_once_with(
295
 
            filename, 'log text', headers=headers)
296
 
        jenkins_mock.get_console_text.assert_called_once_with()
297
 
 
298
 
    def test_upload_console_log_unique_id(self):
299
 
        filename, headers, s3_mock, jenkins_mock = (
300
 
            self._make_upload_console_log(file_prefix='9999'))
301
 
        h = S3Uploader(s3_mock, jenkins_mock, unique_id='9999')
302
 
        h.upload_console_log()
303
 
        s3_mock.store.assert_called_once_with(
304
 
            filename, 'log text', headers=headers)
305
 
        jenkins_mock.get_console_text.assert_called_once_with()
306
 
 
307
 
    def _make_upload_console_log(self, file_prefix):
308
 
        filename = '{}-console-consoleText.txt'.format(file_prefix)
309
 
        headers = {"Content-Type": "text/plain; charset=utf8"}
310
 
        s3_mock = MagicMock()
311
 
        jenkins_mock = MagicMock()
312
 
        jenkins_mock.get_build_number.return_value = BUILD_NUM
313
 
        jenkins_mock.get_console_text.return_value = "log text"
314
 
        return filename, headers, s3_mock, jenkins_mock
315
 
 
316
 
    def test_make_headers_svg(self):
317
 
        headers = S3Uploader.make_headers('/file/path.svg')
318
 
        expected = {'Content-Type': 'image/svg+xml'}
319
 
        self.assertEqual(headers, expected)
320
 
 
321
 
    def test_make_headers_txt_gz(self):
322
 
        headers = S3Uploader.make_headers('/file/path.txt.gz')
323
 
        expected = {'Content-Type': 'text/plain',
324
 
                    'Content-Encoding': 'gzip'}
325
 
        self.assertEqual(headers, expected)
326
 
 
327
 
    def test_make_headers_log_gz(self):
328
 
        headers = S3Uploader.make_headers('path.log.gz')
329
 
        expected = {'Content-Type': 'text/plain', 'Content-Encoding': 'gzip'}
330
 
        self.assertEqual(headers, expected)
331
 
 
332
 
    def test_make_headers_json(self):
333
 
        headers = S3Uploader.make_headers('path.json')
334
 
        expected = {'Content-Type': 'application/json'}
335
 
        self.assertEqual(headers, expected)
336
 
 
337
 
    def test_make_headers_yaml(self):
338
 
        headers = S3Uploader.make_headers('path.yaml')
339
 
        expected = {'Content-Type': 'text/x-yaml'}
340
 
        self.assertEqual(headers, expected)
341
 
 
342
 
    def test_make_headers_unknown(self):
343
 
        headers = S3Uploader.make_headers('path.ab123')
344
 
        expected = {'Content-Type': 'application/octet-stream'}
345
 
        self.assertEqual(headers, expected)
346
 
 
347
 
    def test_upload_artifacts(self):
348
 
        filename, headers, s3_mock, jenkins_mock = (
349
 
            self._make_upload_artifacts(BUILD_NUM))
350
 
        h = S3Uploader(s3_mock, jenkins_mock)
351
 
        h.upload_artifacts()
352
 
        calls = [call(filename, 'artifact data 1', headers=headers),
353
 
                 call(filename, 'artifact data 2', headers=headers),
354
 
                 call(filename, 'artifact data 3', headers=headers)]
355
 
        self.assertEqual(s3_mock.store.mock_calls, calls)
356
 
        jenkins_mock.artifacts.assert_called_once_with()
357
 
 
358
 
    def test_upload_artifacts_unique_id(self):
359
 
        filename, headers, s3_mock, jenkins_mock = (
360
 
            self._make_upload_artifacts('9999'))
361
 
        h = S3Uploader(s3_mock, jenkins_mock, unique_id='9999')
362
 
        h.upload_artifacts()
363
 
        calls = [call(filename, 'artifact data 1', headers=headers),
364
 
                 call(filename, 'artifact data 2', headers=headers),
365
 
                 call(filename, 'artifact data 3', headers=headers)]
366
 
        self.assertEqual(s3_mock.store.mock_calls, calls)
367
 
        jenkins_mock.artifacts.assert_called_once_with()
368
 
 
369
 
    def test_upload_artifacts_content_type(self):
370
 
 
371
 
        def artifacts_fake():
372
 
            for filename, i in zip(['foo.log.gz', 'foo.svg'], xrange(1, 3)):
373
 
                yield filename, "artifact data {}".format(i)
374
 
 
375
 
        _, _, s3_mock, jenkins_mock = self._make_upload_artifacts(BUILD_NUM)
376
 
        jenkins_mock.artifacts.return_value = artifacts_fake()
377
 
        h = S3Uploader(s3_mock, jenkins_mock)
378
 
        h.upload_artifacts()
379
 
        calls = [call('1277-log-foo.log.gz', 'artifact data 1',
380
 
                      headers={'Content-Type': 'text/plain',
381
 
                               'Content-Encoding': 'gzip'}),
382
 
                 call('1277-log-foo.svg', 'artifact data 2',
383
 
                      headers={'Content-Type': 'image/svg+xml'})]
384
 
        self.assertEqual(s3_mock.store.mock_calls, calls)
385
 
        jenkins_mock.artifacts.assert_called_once_with()
386
 
 
387
 
    def test_upload_artifacts_file_ext(self):
388
 
 
389
 
        def artifacts_fake():
390
 
            for filename, i in zip(['foo.log', 'bar.svg', 'result.json'],
391
 
                                   xrange(1, 4)):
392
 
                yield filename, "artifact data {}".format(i)
393
 
        _, _, s3_mock, jenkins_mock = self._make_upload_artifacts(BUILD_NUM)
394
 
        jenkins_mock.artifacts.return_value = artifacts_fake()
395
 
        h = S3Uploader(s3_mock, jenkins_mock,
396
 
                       artifact_file_ext=['.json', '.svg'])
397
 
        h.upload_artifacts()
398
 
        calls = [
399
 
            call('1277-log-bar.svg', 'artifact data 2',
400
 
                 headers={'Content-Type': 'image/svg+xml'}),
401
 
            call('1277-log-result.json', 'artifact data 3',
402
 
                 headers={'Content-Type': 'application/json'})]
403
 
        self.assertEqual(s3_mock.store.mock_calls, calls)
404
 
        jenkins_mock.artifacts.assert_called_once_with()
405
 
 
406
 
    def _make_upload_artifacts(self, file_prefix):
407
 
        filename = '{}-log-filename'.format(file_prefix)
408
 
        headers = {"Content-Type": "application/octet-stream"}
409
 
        s3_mock = MagicMock()
410
 
        jenkins_mock = MagicMock()
411
 
        jenkins_mock.get_build_number.return_value = BUILD_NUM
412
 
        jenkins_mock.artifacts.return_value = fake_artifacts(4)
413
 
        return filename, headers, s3_mock, jenkins_mock
414
 
 
415
 
    def test_upload_by_build_number(self):
416
 
        credentials = fake_credentials()
417
 
        build_info = {"number": 9988, 'building': False}
418
 
        j = JenkinsBuild(credentials, JOB_NAME, JENKINS_URL, BUILD_INFO)
419
 
        uploader = S3Uploader(None, j)
420
 
        with patch('upload_jenkins_job.os.getenv',
421
 
                   return_value=9988, autospec=True) as g_mock:
422
 
            with patch('upload_jenkins_job.get_build_data', autospec=True,
423
 
                       return_value=build_info) as gbd_mock:
424
 
                with patch.object(uploader, 'upload', autospec=True) as u_mock:
425
 
                    uploader.upload_by_build_number()
426
 
        g_mock.assert_called_once_with('BUILD_NUMBER')
427
 
        u_mock.assert_called_once_with()
428
 
        self.assertEqual(
429
 
            gbd_mock.mock_calls,
430
 
            create_build_data_calls(build_num=9988, calls=2))
431
 
 
432
 
    def test_upload_by_build_number_no_build_number(self):
433
 
        jenkins_mock = MagicMock()
434
 
        h = S3Uploader(None, jenkins_mock)
435
 
        with patch('upload_jenkins_job.os.getenv',
436
 
                   return_value=None, autospec=True):
437
 
            with self.assertRaisesRegexp(
438
 
                    ValueError, 'Build number is not set'):
439
 
                h.upload_by_build_number()
440
 
 
441
 
    def test_upload_by_build_number_timeout(self):
442
 
        credentials = fake_credentials()
443
 
        build_info = {"number": 9988, 'building': True}
444
 
        j = JenkinsBuild(credentials, JOB_NAME, JENKINS_URL, BUILD_INFO)
445
 
        uploader = S3Uploader(None, j)
446
 
        with patch('upload_jenkins_job.get_build_data', autospec=True,
447
 
                   return_value=build_info) as gbd_mock:
448
 
            with self.assertRaisesRegexp(
449
 
                    Exception, "Build fails to complete: 9988"):
450
 
                uploader.upload_by_build_number(
451
 
                    build_number=9988, pause_time=.1, timeout=.1)
452
 
        self.assertEqual(
453
 
            gbd_mock.mock_calls,
454
 
            create_build_data_calls(build_num=9988, calls=2))
455
 
 
456
 
    def test_upload_by_build_number_waits(self):
457
 
        credentials = fake_credentials()
458
 
        build_info = {"number": BUILD_NUM, 'building': True}
459
 
        build_info_done = {"number": BUILD_NUM, 'building': False}
460
 
        jb = JenkinsBuild(credentials, JOB_NAME, JENKINS_URL, BUILD_INFO)
461
 
        uploader = S3Uploader(None, jb)
462
 
        with patch('upload_jenkins_job.get_build_data', autospec=True,
463
 
                   side_effect=[build_info, build_info, build_info_done]) as m:
464
 
            with patch.object(uploader, 'upload', autospec=True) as u_mock:
465
 
                with patch('upload_jenkins_job.sleep', autospec=True,
466
 
                           side_effect=sleep(.1)) as s_mock:
467
 
                    uploader.upload_by_build_number(
468
 
                        build_number=BUILD_NUM, pause_time=.1, timeout=1)
469
 
        self.assertEqual(m.mock_calls, create_build_data_calls(calls=3))
470
 
        u_mock.assert_called_once_with()
471
 
        s_mock.assert_called_once_with(.1)
472
 
 
473
 
    def test_last_completed_test_results(self):
474
 
        class Response:
475
 
            text = "console content"
476
 
        build_info = {"artifacts": [], 'url': 'fake', "number": BUILD_NUM}
477
 
        last_build = {"lastCompletedBuild": {"number": BUILD_NUM}}
478
 
        cred = Credentials('joe', 'password')
479
 
        jenkins_build = JenkinsBuild(cred, None, None, build_info)
480
 
        s3_mock = MagicMock()
481
 
        h = S3Uploader(s3_mock, jenkins_build)
482
 
        with patch("upload_jenkins_job.get_job_data", autospec=True,
483
 
                   return_value=last_build) as gjd_mock:
484
 
            with patch("upload_jenkins_job.get_build_data", autospec=True,
485
 
                       return_value=build_info) as gbd_mock:
486
 
                with patch('upload_jenkins_job.requests.get', autospec=True,
487
 
                           return_value=Response):
488
 
                    h.upload_last_completed_test_result()
489
 
                    self.assertEqual(
490
 
                        h.jenkins_build.get_last_completed_build_number(),
491
 
                        BUILD_NUM)
492
 
        self.assertEqual(s3_mock.store.mock_calls, [
493
 
            call('1277-result-results.json', json.dumps(build_info, indent=4),
494
 
                 headers={"Content-Type": "application/json"}),
495
 
            call('1277-console-consoleText.txt', Response.text,
496
 
                 headers={"Content-Type": "text/plain; charset=utf8"})
497
 
        ])
498
 
        self.assertEqual(gjd_mock.mock_calls, [
499
 
            call(None, cred, None),
500
 
            call(None, cred, None)
501
 
        ])
502
 
        self.assertEqual(gbd_mock.mock_calls, [
503
 
            call(None, cred, None, BUILD_NUM),
504
 
            call(None, cred, None, BUILD_NUM)
505
 
        ])
506
 
 
507
 
    def test_create_file(self):
508
 
        filename, s3_mock, jenkins_mock = (
509
 
            self._make_upload(file_prefix=BUILD_NUM))
510
 
        h = S3Uploader(s3_mock, jenkins_mock)
511
 
        filename = h._create_filename("myfile")
512
 
        self.assertEqual(filename, "{}-log-myfile".format(BUILD_NUM))
513
 
 
514
 
    def test_create_file_console_text(self):
515
 
        filename, s3_mock, jenkins_mock = (
516
 
            self._make_upload(file_prefix=BUILD_NUM))
517
 
        h = S3Uploader(s3_mock, jenkins_mock)
518
 
        filename = h._create_filename("consoleText")
519
 
        self.assertEqual(
520
 
            filename, "{}-console-consoleText.txt".format(BUILD_NUM))
521
 
 
522
 
    def test_create_file_result_results(self):
523
 
        filename, s3_mock, jenkins_mock = (
524
 
            self._make_upload(file_prefix=BUILD_NUM))
525
 
        h = S3Uploader(s3_mock, jenkins_mock)
526
 
        filename = h._create_filename("result-results.json")
527
 
        self.assertEqual(
528
 
            filename, "{}-result-results.json".format(BUILD_NUM))
529
 
 
530
 
    def test_create_file_no_prefixes(self):
531
 
        filename, s3_mock, jenkins_mock = (
532
 
            self._make_upload(file_prefix=BUILD_NUM))
533
 
        h = S3Uploader(s3_mock, jenkins_mock, no_prefixes=True)
534
 
        filename = h._create_filename("myfile")
535
 
        self.assertEqual(filename, "myfile")
536
 
 
537
 
    def test_create_file_unique_id(self):
538
 
        filename, s3_mock, jenkins_mock = (
539
 
            self._make_upload(file_prefix=BUILD_NUM))
540
 
        h = S3Uploader(s3_mock, jenkins_mock, unique_id='9999')
541
 
        filename = h._create_filename("myfile")
542
 
        self.assertEqual(filename, "9999-log-myfile")
543
 
 
544
 
 
545
 
class OtherTests(TestCase):
546
 
 
547
 
    def test_get_args(self):
548
 
        args = get_args([JOB_NAME, str(BUILD_NUM), BUCKET, DIRECTORY])
549
 
        self.assertEqual(JOB_NAME, args.jenkins_job)
550
 
        self.assertEqual(BUILD_NUM, args.build_number)
551
 
        self.assertEqual(BUCKET, args.s3_bucket)
552
 
        self.assertEqual(DIRECTORY, args.s3_directory)
553
 
        self.assertFalse(args.all)
554
 
        self.assertFalse(args.latest)
555
 
        self.assertIsNone(args.user)
556
 
        self.assertIsNone(args.password)
557
 
 
558
 
    def test_get_args_all(self):
559
 
        args = get_args([JOB_NAME, 'all', BUCKET, DIRECTORY])
560
 
        self.assertEqual(JOB_NAME, args.jenkins_job)
561
 
        self.assertIsNone(args.build_number)
562
 
        self.assertEqual(BUCKET, args.s3_bucket)
563
 
        self.assertEqual(DIRECTORY, args.s3_directory)
564
 
        self.assertTrue(args.all)
565
 
        self.assertFalse(args.latest)
566
 
        self.assertIsNone(args.user)
567
 
        self.assertIsNone(args.password)
568
 
 
569
 
    def test_get_args_latest(self):
570
 
        args = get_args([JOB_NAME, 'latest', BUCKET, DIRECTORY])
571
 
        self.assertEqual(JOB_NAME, args.jenkins_job)
572
 
        self.assertIsNone(args.build_number)
573
 
        self.assertEqual(BUCKET, args.s3_bucket)
574
 
        self.assertEqual(DIRECTORY, args.s3_directory)
575
 
        self.assertFalse(args.all)
576
 
        self.assertTrue(args.latest)
577
 
        self.assertIsNone(args.user)
578
 
        self.assertIsNone(args.password)
579
 
 
580
 
    def test_get_args_with_credentials(self):
581
 
        args = get_args(['--user', 'me', '--password', 'passwd', JOB_NAME,
582
 
                        str(BUILD_NUM), BUCKET, DIRECTORY])
583
 
        self.assertEqual(JOB_NAME, args.jenkins_job)
584
 
        self.assertEqual(BUILD_NUM, args.build_number)
585
 
        self.assertEqual(BUCKET, args.s3_bucket)
586
 
        self.assertEqual(DIRECTORY, args.s3_directory)
587
 
        self.assertFalse(args.all)
588
 
        self.assertFalse(args.latest)
589
 
        self.assertEqual(args.user, 'me')
590
 
        self.assertEqual(args.password, 'passwd')
591
 
 
592
 
    def test_get_args_default(self):
593
 
        args = get_args([JOB_NAME, str(BUILD_NUM), BUCKET, DIRECTORY])
594
 
        self.assertEqual(args, Namespace(
595
 
            all=False, artifact_file_ext=None, build_number=1277,
596
 
            jenkins_job=JOB_NAME, latest=False, password=None,
597
 
            s3_bucket=BUCKET, s3_directory=DIRECTORY, unique_id=None,
598
 
            user=None, no_prefixes=False))
599
 
 
600
 
    def test_get_args_artifact_file_ext(self):
601
 
        args = get_args([JOB_NAME, str(BUILD_NUM), BUCKET, DIRECTORY,
602
 
                         '--artifact-file-ext', '.svg', '.json',
603
 
                         '--unique-id', '1234'])
604
 
        self.assertEqual(args.artifact_file_ext, ['.svg', '.json'])
605
 
        self.assertEqual(args.unique_id, '1234')
606
 
 
607
 
    def test_get_s3_access(self):
608
 
        path = '/u/home'
609
 
        relative_path = 'cloud-city/juju-qa.s3cfg'
610
 
        with NamedTemporaryFile() as temp_file:
611
 
                temp_file.write(s3cfg())
612
 
                temp_file.flush()
613
 
                with patch(
614
 
                        'upload_jenkins_job.os.path.join', autospec=True,
615
 
                        return_value=temp_file.name) as j_mock:
616
 
                    with patch(
617
 
                            'upload_jenkins_job.os.getenv', autospec=True,
618
 
                            return_value=path) as g_mock:
619
 
                        access_key, secret_key = get_s3_access()
620
 
                        self.assertEqual(access_key, "fake_username")
621
 
                        self.assertEqual(secret_key, "fake_pass")
622
 
        j_mock.assert_called_once_with(path, relative_path)
623
 
        g_mock.assert_called_once_with('HOME')
624
 
 
625
 
    def test_get_s3_access_no_access_key(self):
626
 
        path = '/u/home'
627
 
        relative_path = 'cloud-city/juju-qa.s3cfg'
628
 
        with NamedTemporaryFile() as temp_file:
629
 
                temp_file.write(s3cfg_no_access_key())
630
 
                temp_file.flush()
631
 
                with patch('upload_jenkins_job.os.path.join', autospec=True,
632
 
                           return_value=temp_file.name) as j_mock:
633
 
                    with patch(
634
 
                            'upload_jenkins_job.os.getenv', autospec=True,
635
 
                            return_value=path) as g_mock:
636
 
                        with self.assertRaisesRegexp(
637
 
                                NoOptionError,
638
 
                                "No option 'access_key' in section: "
639
 
                                "'default'"):
640
 
                            get_s3_access()
641
 
        j_mock.assert_called_once_with(path, relative_path)
642
 
        g_mock.assert_called_once_with('HOME')
643
 
 
644
 
    def test_get_s3_access_no_secret_key(self):
645
 
        path = '/u/home'
646
 
        relative_path = 'cloud-city/juju-qa.s3cfg'
647
 
        with NamedTemporaryFile() as temp_file:
648
 
                temp_file.write(s3cfg_no_secret_key())
649
 
                temp_file.flush()
650
 
                with patch(
651
 
                        'upload_jenkins_job.os.path.join', autospec=True,
652
 
                        return_value=temp_file.name) as j_mock:
653
 
                    with patch(
654
 
                            'upload_jenkins_job.os.getenv', autospec=True,
655
 
                            return_value=path) as g_mock:
656
 
                        with self.assertRaisesRegexp(
657
 
                                NoOptionError,
658
 
                                "No option 'secret_key' in section: "
659
 
                                "'default'"):
660
 
                            get_s3_access()
661
 
        j_mock.assert_called_once_with(path, relative_path)
662
 
        g_mock.assert_called_once_with('HOME')
663
 
 
664
 
 
665
 
def create_build_data_calls(
666
 
        url=JENKINS_URL, cred=None, job_name=JOB_NAME,
667
 
        build_num=BUILD_NUM, calls=1):
668
 
    cred = Credentials('fake_username', 'fake_pass') if not cred else cred
669
 
    return [call(url, cred, job_name, build_num) for _ in xrange(calls)]
670
 
 
671
 
 
672
 
def fake_credentials():
673
 
    return Credentials('fake_username', 'fake_pass')
674
 
 
675
 
 
676
 
def s3cfg():
677
 
    return """[default]
678
 
access_key = fake_username
679
 
secret_key = fake_pass
680
 
"""
681
 
 
682
 
 
683
 
def s3cfg_no_access_key():
684
 
    return """
685
 
[default]
686
 
secret_key = fake_pass
687
 
"""
688
 
 
689
 
 
690
 
def s3cfg_no_secret_key():
691
 
    return """
692
 
[default]
693
 
access_key = fake_username
694
 
"""
695
 
 
696
 
 
697
 
def fake_artifacts(max=4):
698
 
    for x in range(1, max):
699
 
        yield "filename", "artifact data %s" % x