1# Copyright 2015 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import json
6import re
7import unittest
8
9import mock
10import webapp2
11import webtest
12
13from dashboard import buildbucket_job_status
14from dashboard import testing_common
15
16
17SAMPLE_RESPONSE = r"""{
18 "build": {
19  "status": "COMPLETED",
20  "created_ts": "1430771172999340",
21  "url": "http://build.chromium.org/p/tryserver.chromium.perf/builders\
22/linux_perf_bisector/builds/32",
23  "bucket": "master.tryserver.chromium.perf",
24  "result_details_json": "{\"properties\": {\
25\"got_nacl_revision\": \"660eb1e1c91349b53f0d60bbf9a92e31f4cf4e1d\", \
26\"got_swarming_client_revision\": \
27\"f222001cc23c7cdb574bf4cfb447f65c94bc6da3\", \
28\"got_revision\": \"d558f46c34085abfc9f59824fdc3466f45c40152\", \
29\"build_url\": \"gs://chrome-perf/Linux Bisector\", \
30\"recipe\": \"bisect\", \
31\"got_webrtc_revision_cp\": \"refs/heads/master@{#9128}\", \
32\"got_webkit_revision_git\": \"44bf01091874592828070dc26cbb5189da9b959b\", \
33\"append_deps_patch_sha\": true, \
34\"project\": \"\", \
35\"got_webkit_revision\": 194864, \
36\"slavename\": \"build74-m4\", \
37\"got_revision_cp\": \"refs/heads/master@{#328178}\", \
38\"blamelist\": [], \
39\"branch\": \"\", \
40\"revision\": \"\", \
41\"workdir\": \"/b/build/slave/linux_perf_bisector\", \
42\"repository\": \"\", \
43\"buildername\": \"linux_perf_bisector\", \
44\"got_webrtc_revision\": \"0d778c6af22767e9bcc92a278da08b5f82885977\", \
45\"mastername\": \"tryserver.chromium.perf\", \
46\"got_v8_revision\": \"a06f1b4e013812cc7ad1d52a0ea49206cafa7b67\", \
47\"got_v8_revision_cp\": \"refs/heads/4.4.50@{#1}\", \
48\"buildbotURL\": \"http://build.chromium.org/p/tryserver.chromium.perf/\", \
49\"bisect_config\": {\"good_revision\": \"328111\", \
50\"builder_host\": null, \
51\"metric\": \"record_time/record_time\", \
52\"max_time_minutes\": \"20\", \
53\"builder_port\": null, \
54\"bug_id\": null, \
55\"command\": \"src/tools/perf/run_benchmark -v --browser=release \
56rasterize_and_record_micro.key_mobile_sites_smooth\", \
57\"repeat_count\": \"20\", \
58\"test_type\": \"perf\", \
59\"gs_bucket\": \"chrome-perf\", \
60\"bad_revision\": \"328115\"}, \
61\"got_webkit_revision_cp\": \"refs/heads/master@{#194864}\", \
62\"buildnumber\": 32, \
63\"requestedAt\": 1430771180}}",
64  "status_changed_ts": "1430771433288620",
65  "created_by": "user:425761728072-pa1bs18esuhp2cp2qfa1u9vb6p1v6kfu\
66@developer.gserviceaccount.com",
67  "failure_reason": "BUILD_FAILURE",
68  "result": "FAILURE",
69  "utcnow_ts": "1430863009872910",
70  "id": "9046721402459257808",
71  "parameters_json": "{\"builder_name\": \"linux_perf_bisector\", \
72\"properties\": {\"bisect_config\": {\"bad_revision\": \"328115\", \
73\"bug_id\": null, \
74\"builder_host\": null, \
75\"builder_port\": null, \
76\"command\": \"src/tools/perf/run_benchmark -v --browser=release \
77rasterize_and_record_micro.key_mobile_sites_smooth\", \
78\"good_revision\": \"328111\", \
79\"gs_bucket\": \"chrome-perf\", \
80\"max_time_minutes\": \"20\", \
81\"metric\": \"record_time/record_time\", \
82\"repeat_count\": \"20\", \
83\"test_type\": \"perf\"}}}",
84  "completed_ts": "1430771433288680",
85  "updated_ts": "1430771433288850"
86 },
87 "kind": "buildbucket#resourcesItem",
88 "etag": "\"mWAxLWqIHM8gXvavjiTVUApk92U/AaU08KGmhFQcdRWOCVgNYJBBlgI\""
89}""".replace('\\\n', '')
90
91SAMPLE_RESPONSE_NOT_FOUND = r"""{
92 "error": {
93  "message": "",
94  "reason": "BUILD_NOT_FOUND"
95 },
96 "kind": "buildbucket#resourcesItem",
97 "etag": "\"mWAxLWqIHM8gXvavjiTVUApk92U/vcsTyxWNZoEnszG8qWqlQLOhpl8\""
98}"""
99
100
101class BuildbucketJobStatusTest(testing_common.TestCase):
102
103  def setUp(self):
104    super(BuildbucketJobStatusTest, self).setUp()
105    app = webapp2.WSGIApplication(
106        [(r'/buildbucket_job_status/(\d+)',
107          buildbucket_job_status.BuildbucketJobStatusHandler)])
108    self.testapp = webtest.TestApp(app)
109
110  @mock.patch.object(
111      buildbucket_job_status.buildbucket_service, 'GetJobStatus',
112      mock.MagicMock(return_value=json.loads(SAMPLE_RESPONSE)))
113  def testGet_ExistingJob(self):
114    response = self.testapp.get('/buildbucket_job_status/9046721402459257808')
115    # Verify that a human-readable creation time is presented. We check for the
116    # minute:second string to avoid localization from breaking this test.
117    self.assertIn('26:12', response.body)
118    # Verify that both the good and bad revisions are displayed somewhere.
119    self.assertIn('328115', response.body)
120    self.assertIn('328111', response.body)
121    # Verify that a link to buildbot is provided somewhere.
122    self.assertTrue(
123        re.search('href\\s*=\\s*[\'"]http://build.chromium.org/p/tryserver',
124                  response.body, re.IGNORECASE))
125
126  @mock.patch.object(
127      buildbucket_job_status.buildbucket_service, 'GetJobStatus',
128      mock.MagicMock(return_value=json.loads(SAMPLE_RESPONSE_NOT_FOUND)))
129  def testGet_JobNotFound(self):
130    response = self.testapp.get('/buildbucket_job_status/9046721402459257808')
131    # If the error code is shown somewhere in the page and no exception is
132    # raised, that's good enough.
133    self.assertIn('BUILD_NOT_FOUND', response)
134
135
136if __name__ == '__main__':
137  unittest.main()
138