diff --git a/master/buildbot/test/unit/test_reporter_bitbucketserver.py b/master/buildbot/test/unit/test_reporter_bitbucketserver.py index 6168773b5f3..2aa935ce3f1 100644 --- a/master/buildbot/test/unit/test_reporter_bitbucketserver.py +++ b/master/buildbot/test/unit/test_reporter_bitbucketserver.py @@ -15,6 +15,7 @@ from __future__ import absolute_import from __future__ import print_function + from future.utils import PY3 from mock import Mock @@ -27,12 +28,16 @@ from buildbot.process.results import SUCCESS from buildbot.reporters.bitbucketserver import BitbucketServerPRCommentPush from buildbot.reporters.bitbucketserver import BitbucketServerStatusPush +from buildbot.reporters.bitbucketserver import HTTP_PROCESSED +from buildbot.reporters.bitbucketserver import HTTP_CREATED from buildbot.test.fake import httpclientservice as fakehttpclientservice from buildbot.test.fake import fakemaster from buildbot.test.util.logging import LoggingMixin from buildbot.test.util.notifier import NotifierTestMixin from buildbot.test.util.reporter import ReporterTestMixin +from buildbot.util import unicode2NativeString +HTTP_NOT_FOUND = 404 class TestBitbucketServerStatusPush(unittest.TestCase, ReporterTestMixin, LoggingMixin): @@ -47,7 +52,8 @@ def setupReporter(self, **kwargs): self.master, self, 'serv', auth=('username', 'passwd'), debug=None, verify=None) - self.sp = sp = BitbucketServerStatusPush("serv", "username", "passwd", **kwargs) + self.sp = sp = BitbucketServerStatusPush( + "serv", "username", "passwd", **kwargs) yield sp.setServiceParent(self.master) yield self.master.startService() @@ -61,23 +67,22 @@ def setupBuildResults(self, buildResults): build = yield self.master.data.get(("builds", 20)) defer.returnValue(build) - @defer.inlineCallbacks - def test_basic(self): - self.setupReporter() - build = yield self.setupBuildResults(SUCCESS) + def _check_start_and_finish_build(self, build): # we make sure proper calls to txrequests have been made self._http.expect( 'post', u'/rest/build-status/1.0/commits/d34db33fd43db33f', json={'url': 'http://localhost:8080/#builders/79/builds/0', 'state': 'INPROGRESS', 'key': u'Builder0', - 'description': 'Build started.'}) + 'description': 'Build started.'}, + code=HTTP_PROCESSED) self._http.expect( 'post', u'/rest/build-status/1.0/commits/d34db33fd43db33f', json={'url': 'http://localhost:8080/#builders/79/builds/0', 'state': 'SUCCESSFUL', 'key': u'Builder0', - 'description': 'Build done.'}) + 'description': 'Build done.'}, + code=HTTP_PROCESSED) self._http.expect( 'post', u'/rest/build-status/1.0/commits/d34db33fd43db33f', @@ -91,6 +96,12 @@ def test_basic(self): build['results'] = FAILURE self.sp.buildFinished(("build", 20, "finished"), build) + @defer.inlineCallbacks + def test_basic(self): + self.setupReporter() + build = yield self.setupBuildResults(SUCCESS) + self._check_start_and_finish_build(build) + @defer.inlineCallbacks def test_setting_options(self): self.setupReporter(statusName='Build', startDescription='Build started.', @@ -102,19 +113,22 @@ def test_setting_options(self): u'/rest/build-status/1.0/commits/d34db33fd43db33f', json={'url': 'http://localhost:8080/#builders/79/builds/0', 'state': 'INPROGRESS', 'key': u'Builder0', - 'name': 'Build', 'description': 'Build started.'}) + 'name': 'Build', 'description': 'Build started.'}, + code=HTTP_PROCESSED) self._http.expect( 'post', u'/rest/build-status/1.0/commits/d34db33fd43db33f', json={'url': 'http://localhost:8080/#builders/79/builds/0', 'state': 'SUCCESSFUL', 'key': u'Builder0', - 'name': 'Build', 'description': 'Build finished.'}) + 'name': 'Build', 'description': 'Build finished.'}, + code=HTTP_PROCESSED) self._http.expect( 'post', u'/rest/build-status/1.0/commits/d34db33fd43db33f', json={'url': 'http://localhost:8080/#builders/79/builds/0', 'state': 'FAILED', 'key': u'Builder0', - 'name': 'Build', 'description': 'Build finished.'}) + 'name': 'Build', 'description': 'Build finished.'}, + code=HTTP_PROCESSED) build['complete'] = False self.sp.buildStarted(("build", 20, "started"), build) build['complete'] = True @@ -133,7 +147,7 @@ def test_error(self): json={'url': 'http://localhost:8080/#builders/79/builds/0', 'state': 'INPROGRESS', 'key': u'Builder0', 'description': 'Build started.'}, - code=404, + code=HTTP_NOT_FOUND, content_json={ "error_description": "This commit is unknown to us", "error": "invalid_commit"}) @@ -142,6 +156,48 @@ def test_error(self): self.sp.buildStarted(("build", 20, "started"), build) self.assertLogged('404: Unable to send Bitbucket Server status') + @defer.inlineCallbacks + def test_basic_with_no_revision(self): + yield self.setupReporter() + old_test_revision = self.TEST_REVISION + try: + self.TEST_REVISION = None + build = yield self.setupBuildResults(SUCCESS) + finally: + self.TEST_REVISION = old_test_revision + self._check_start_and_finish_build(build) + + @defer.inlineCallbacks + def test_basic_with_no_revision_and_dict_got_revision(self): + yield self.setupReporter() + old_test_revision = self.TEST_REVISION + old_got_revision = self.TEST_PROPS['got_revision'] + try: + self.TEST_REVISION = None + self.TEST_PROPS['got_revision'] = {'cbgerrit' : 'd34db33fd43db33f'} + build = yield self.setupBuildResults(SUCCESS) + finally: + self.TEST_REVISION = old_test_revision + self.TEST_PROPS['got_revision'] = old_got_revision + self._check_start_and_finish_build(build) + + @defer.inlineCallbacks + def test_basic_with_no_revision_and_no_got_revision(self): + yield self.setupReporter() + old_test_revision = self.TEST_REVISION + old_got_revision = self.TEST_PROPS['got_revision'] + try: + self.TEST_REVISION = None + self.TEST_PROPS['got_revision'] = None + build = yield self.setupBuildResults(SUCCESS) + finally: + self.TEST_REVISION = old_test_revision + self.TEST_PROPS['got_revision'] = old_got_revision + + self.setUpLogging() + self.sp.buildStarted(("build", 20, "started"), build) + self.assertLogged('Unable to get the commit hash') + UNICODE_BODY = u"body: \u00E5\u00E4\u00F6 text" EXPECTED_API = u'/rest/api/1.0/projects/PRO/repos/myrepo/pull-requests/20/comments' @@ -151,7 +207,7 @@ def test_error(self): class TestBitbucketServerPRCommentPush(unittest.TestCase, NotifierTestMixin, LoggingMixin): @defer.inlineCallbacks - def setupReporter(self, **kwargs): + def setupReporter(self, verbose=True, **kwargs): # ignore config error if txrequests is not installed self.patch(config, '_errors', Mock()) self.master = fakemaster.make_master( @@ -160,13 +216,13 @@ def setupReporter(self, **kwargs): self._http = yield fakehttpclientservice.HTTPClientService.getFakeService( self.master, self, 'serv', auth=('username', 'passwd'), debug=None, verify=None) - self.cp = BitbucketServerPRCommentPush("serv", "username", "passwd", **kwargs) + self.cp = BitbucketServerPRCommentPush( + "serv", "username", "passwd", verbose=verbose, **kwargs) yield self.cp.setServiceParent(self.master) yield self.master.startService() self.cp.messageFormatter = Mock(spec=self.cp.messageFormatter) self.cp.messageFormatter.formatMessageForBuildResults.return_value = \ - {"body": UNICODE_BODY, - "type": "text"} + {"body": UNICODE_BODY, "type": "text"} @defer.inlineCallbacks def tearDown(self): @@ -189,9 +245,29 @@ def test_reporter_basic(self): "post", EXPECTED_API, json={"text": UNICODE_BODY}, - code=201) + code=HTTP_CREATED) build["complete"] = True + self.setUpLogging() self.cp.buildComplete(("build", 20, "finished"), build) + self.assertLogged(unicode2NativeString( + u'{} sent to {}'.format(UNICODE_BODY, PR_URL))) + + @defer.inlineCallbacks + def test_reporter_basic_without_logging(self): + yield self.setupReporter(verbose=False) + _, builds = yield self.setupBuildResults(SUCCESS) + build = builds[0] + self._http.expect( + "post", + EXPECTED_API, + json={"text": UNICODE_BODY}, + code=HTTP_CREATED) + build["complete"] = True + self.setUpLogging() + self.cp.buildComplete(("build", 20, "finished"), build) + + self.assertNotLogged(unicode2NativeString( + u'{} sent to {}'.format(UNICODE_BODY, PR_URL))) @defer.inlineCallbacks def test_reporter_non_unicode(self): @@ -209,7 +285,7 @@ def test_reporter_non_unicode(self): "post", EXPECTED_API, json={"text": "body text"}, - code=201) + code=HTTP_CREATED) build["complete"] = True self.cp.buildComplete(("build", 20, "finished"), build) @@ -222,6 +298,11 @@ def test_reporter_without_pullrequest(self): # we don't expect any request self.cp.buildComplete(("builds", 20, "finished"), build) + @defer.inlineCallbacks + def test_missing_worker_does_nothing(self): + yield self.setupReporter() + self.cp.workerMissing(("workers", 13, "missing"), 13) + @defer.inlineCallbacks def test_reporter_with_buildset(self): yield self.setupReporter(buildSetSummary=True) @@ -230,21 +311,61 @@ def test_reporter_with_buildset(self): "post", EXPECTED_API, json={"text": UNICODE_BODY}, - code=201) + code=HTTP_CREATED) self.cp.buildsetComplete(("buildsets", 20, "complete"), buildset) @defer.inlineCallbacks - def test_reporter_on_invalid_return_code(self): + def test_reporter_logs_error_code_and_content_on_invalid_return_code(self): + yield self.setupReporter() + _, builds = yield self.setupBuildResults(SUCCESS) + build = builds[0] + + http_error_code = 500 + error_body = {u"errors": [{u"message": u"A dataXXXbase error has occurred."}]} + + self._http.expect( + "post", + EXPECTED_API, + json={"text": UNICODE_BODY}, + code=http_error_code, + content_json=error_body) + self.setUpLogging() + build['complete'] = True + self.cp.buildComplete(("builds", 20, "finished"), build) + + self.assertLogged("^{}: Unable to send a comment: ".format(http_error_code)) + self.assertLogged("A dataXXXbase error has occurred") + + @defer.inlineCallbacks + def test_reporter_logs_error_code_without_content_on_invalid_return_code(self): + yield self.setupReporter() + _, builds = yield self.setupBuildResults(SUCCESS) + build = builds[0] + http_error_code = 503 + self._http.expect( + "post", + EXPECTED_API, + json={"text": UNICODE_BODY}, + code=http_error_code) + self.setUpLogging() + build['complete'] = True + self.cp.buildComplete(("builds", 20, "finished"), build) + self.assertLogged("^{}: Unable to send a comment: ".format( + http_error_code)) + + @defer.inlineCallbacks + def test_reporter_does_not_log_return_code_on_valid_return_code( + self): yield self.setupReporter() _, builds = yield self.setupBuildResults(SUCCESS) build = builds[0] + http_code = 201 self._http.expect( "post", EXPECTED_API, json={"text": UNICODE_BODY}, - code=404, - content_json=None) + code=http_code) self.setUpLogging() build['complete'] = True self.cp.buildComplete(("builds", 20, "finished"), build) - self.assertLogged('404: Unable to send a comment: None') + self.assertNotLogged("^{}:".format(http_code)) \ No newline at end of file diff --git a/master/buildbot/test/unit/test_www_hooks_bitbucketserver.py b/master/buildbot/test/unit/test_www_hooks_bitbucketserver.py index 7b7002edf97..f112644f9a5 100644 --- a/master/buildbot/test/unit/test_www_hooks_bitbucketserver.py +++ b/master/buildbot/test/unit/test_www_hooks_bitbucketserver.py @@ -686,8 +686,7 @@ def _checkPush(self, change): def testHookWithChangeOnPushEvent(self): request = _prepare_request( - pushJsonPayload, - headers={_HEADER_EVENT: 'repo:push'}) + pushJsonPayload, headers={_HEADER_EVENT: 'repo:push'}) yield request.test_render(self.change_hook) @@ -697,6 +696,11 @@ def testHookWithChangeOnPushEvent(self): self.assertEqual(change['branch'], 'refs/heads/branch_1496411680') self.assertEqual(change['category'], 'push') + @defer.inlineCallbacks + def testHookWithNonDictOption(self): + self.change_hook.dialects = {'bitbucketserver': True} + yield self.testHookWithChangeOnPushEvent() + def _checkPullRequest(self, change): self.assertEqual( change['repository'], @@ -718,8 +722,8 @@ def _checkPullRequest(self, change): @defer.inlineCallbacks def testHookWithChangeOnPullRequestCreated(self): request = _prepare_request( - pullRequestCreatedJsonPayload, - headers={_HEADER_EVENT: 'pullrequest:created'}) + pullRequestCreatedJsonPayload, + headers={_HEADER_EVENT: 'pullrequest:created'}) yield request.test_render(self.change_hook) @@ -732,8 +736,8 @@ def testHookWithChangeOnPullRequestCreated(self): @defer.inlineCallbacks def testHookWithChangeOnPullRequestUpdated(self): request = _prepare_request( - pullRequestUpdatedJsonPayload, - headers={_HEADER_EVENT: 'pullrequest:updated'}) + pullRequestUpdatedJsonPayload, + headers={_HEADER_EVENT: 'pullrequest:updated'}) yield request.test_render(self.change_hook) @@ -746,8 +750,8 @@ def testHookWithChangeOnPullRequestUpdated(self): @defer.inlineCallbacks def testHookWithChangeOnPullRequestRejected(self): request = _prepare_request( - pullRequestRejectedJsonPayload, - headers={_HEADER_EVENT: 'pullrequest:rejected'}) + pullRequestRejectedJsonPayload, + headers={_HEADER_EVENT: 'pullrequest:rejected'}) yield request.test_render(self.change_hook) @@ -777,8 +781,7 @@ def _checkCodebase(self, event_type, expected_codebase): 'repo:push': pushJsonPayload, 'pullrequest:updated': pullRequestUpdatedJsonPayload} request = _prepare_request( - payloads[event_type], - headers={_HEADER_EVENT: event_type}) + payloads[event_type], headers={_HEADER_EVENT: event_type}) yield request.test_render(self.change_hook) self.assertEqual(len(self.change_hook.master.addedChanges), 1) change = self.change_hook.master.addedChanges[0] @@ -815,8 +818,7 @@ def testHookWithCodebaseFunctionOnPullEvent(self): @defer.inlineCallbacks def testHookWithUnhandledEvent(self): request = _prepare_request( - pushJsonPayload, - headers={_HEADER_EVENT: 'invented:event'}) + pushJsonPayload, headers={_HEADER_EVENT: 'invented:event'}) yield request.test_render(self.change_hook) self.assertEqual(len(self.change_hook.master.addedChanges), 0) self.assertEqual(request.written, "Unknown event: invented_event") @@ -824,8 +826,7 @@ def testHookWithUnhandledEvent(self): @defer.inlineCallbacks def testHookWithChangeOnCreateTag(self): request = _prepare_request( - newTagJsonPayload, - headers={_HEADER_EVENT: 'repo:push'}) + newTagJsonPayload, headers={_HEADER_EVENT: 'repo:push'}) yield request.test_render(self.change_hook) self.assertEqual(len(self.change_hook.master.addedChanges), 1) change = self.change_hook.master.addedChanges[0] @@ -836,8 +837,7 @@ def testHookWithChangeOnCreateTag(self): @defer.inlineCallbacks def testHookWithChangeOnDeleteTag(self): request = _prepare_request( - deleteTagJsonPayload, - headers={_HEADER_EVENT: 'repo:push'}) + deleteTagJsonPayload, headers={_HEADER_EVENT: 'repo:push'}) yield request.test_render(self.change_hook) self.assertEqual(len(self.change_hook.master.addedChanges), 1) change = self.change_hook.master.addedChanges[0] @@ -848,8 +848,7 @@ def testHookWithChangeOnDeleteTag(self): @defer.inlineCallbacks def testHookWithChangeOnDeleteBranch(self): request = _prepare_request( - deleteBranchJsonPayload, - headers={_HEADER_EVENT: 'repo:push'}) + deleteBranchJsonPayload, headers={_HEADER_EVENT: 'repo:push'}) yield request.test_render(self.change_hook) self.assertEqual(len(self.change_hook.master.addedChanges), 1) change = self.change_hook.master.addedChanges[0] @@ -860,8 +859,7 @@ def testHookWithChangeOnDeleteBranch(self): @defer.inlineCallbacks def testHookWithInvalidContentType(self): request = _prepare_request( - pushJsonPayload, - headers={_HEADER_EVENT: 'repo:push'}) + pushJsonPayload, headers={_HEADER_EVENT: 'repo:push'}) request.received_headers['Content-Type'] = 'invalid/content' yield request.test_render(self.change_hook) self.assertEqual(len(self.change_hook.master.addedChanges), 0) diff --git a/master/buildbot/test/util/reporter.py b/master/buildbot/test/util/reporter.py index 95995ed02a6..34455b6c164 100644 --- a/master/buildbot/test/util/reporter.py +++ b/master/buildbot/test/util/reporter.py @@ -26,6 +26,7 @@ class ReporterTestMixin(object): TEST_PROJECT = u'testProject' TEST_REPO = u'https://example.org/repo' TEST_REVISION = u'd34db33fd43db33f' + TEST_CODEBASE = u'cbgerrit' TEST_CHANGE_ID = u'I5bdc2e500d00607af53f0fa4df661aada17f81fc' TEST_BUILDER_NAME = u'Builder0' TEST_PROPS = { @@ -48,17 +49,19 @@ def insertTestData(self, buildResults, finalResult, insertSS=True): fakedb.Builder(id=80, name='Builder1'), fakedb.Buildset(id=98, results=finalResult, reason="testReason1"), fakedb.Change(changeid=13, branch=u'master', revision=u'9283', author='me@foo', - repository=self.TEST_REPO, codebase=u'cbgerrit', + repository=self.TEST_REPO, codebase=self.TEST_CODEBASE, project=u'world-domination', sourcestampid=234), ]) if insertSS: self.db.insertTestData([ fakedb.BuildsetSourceStamp(buildsetid=98, sourcestampid=234), - fakedb.SourceStamp(id=234, - project=self.TEST_PROJECT, - revision=self.TEST_REVISION, - repository=self.TEST_REPO) + fakedb.SourceStamp( + id=234, + project=self.TEST_PROJECT, + revision=self.TEST_REVISION, + repository=self.TEST_REPO, + codebase=self.TEST_CODEBASE) ]) for i, results in enumerate(buildResults):