blob: 2b5f8ac2912586f986110cb943f71ce9c770c43f [file] [log] [blame]
# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import json
from blinkpy.common.host_mock import MockHost
from blinkpy.common.system.log_testing import LoggingTestCase
from blinkpy.w3c.chromium_commit_mock import MockChromiumCommit
from blinkpy.w3c.gerrit import GerritError
from blinkpy.w3c.gerrit_mock import MockGerritAPI, MockGerritCL
from blinkpy.w3c.test_exporter import TestExporter
from blinkpy.w3c.wpt_github import PullRequest
from blinkpy.w3c.wpt_github_mock import MockWPTGitHub
class TestExporterTest(LoggingTestCase):
def setUp(self):
super(TestExporterTest, self).setUp()
host = MockHost()
host.filesystem.write_text_file(
'/tmp/credentials.json',
json.dumps({
'GH_USER': 'github-username',
'GH_TOKEN': 'github-token',
'GERRIT_USER': 'gerrit-username',
'GERRIT_TOKEN': 'gerrit-token',
}))
self.host = host
def test_dry_run_stops_before_creating_pr(self):
test_exporter = TestExporter(self.host)
test_exporter.wpt_github = MockWPTGitHub(pull_requests=[
PullRequest(
title='title1', number=1234, body='', state='open', labels=[]),
])
test_exporter.gerrit = MockGerritAPI()
test_exporter.gerrit.exportable_open_cls = [
MockGerritCL(
data={
'change_id': 'I001',
'subject': 'subject',
'_number': 1234,
'current_revision': '1',
'has_review_started': True,
'revisions': {
'1': {
'commit_with_footers': 'a commit with footers'
}
},
'owner': {
'email': 'test@chromium.org'
},
},
api=test_exporter.gerrit,
chromium_commit=MockChromiumCommit(
self.host,
subject='subject',
body='fake body',
change_id='I001'))
]
test_exporter.get_exportable_commits = lambda: ([
MockChromiumCommit(
self.host, position='refs/heads/master@{#458475}'),
MockChromiumCommit(
self.host, position='refs/heads/master@{#458476}'),
], [])
success = test_exporter.main(
['--credentials-json', '/tmp/credentials.json', '--dry-run'])
self.assertTrue(success)
self.assertEqual(test_exporter.wpt_github.calls, [
'pr_with_change_id',
'pr_for_chromium_commit',
'pr_for_chromium_commit',
])
self.assertEqual(len(test_exporter.gerrit.request_posted), 0)
def test_creates_pull_request_for_all_exportable_commits(self):
test_exporter = TestExporter(self.host)
test_exporter.wpt_github = MockWPTGitHub(
pull_requests=[], create_pr_fail_index=1)
test_exporter.gerrit = MockGerritAPI()
test_exporter.get_exportable_commits = lambda: ([
MockChromiumCommit(
self.host, position='refs/heads/master@{#1}', change_id='I001', subject='subject 1', body='body 1'),
MockChromiumCommit(
self.host, position='refs/heads/master@{#2}', change_id='I002', subject='subject 2', body='body 2'),
MockChromiumCommit(
self.host, position='refs/heads/master@{#3}', change_id='I003', subject='subject 3', body='body 3'),
], [])
success = test_exporter.main(
['--credentials-json', '/tmp/credentials.json'])
self.assertTrue(success)
self.assertEqual(
test_exporter.wpt_github.calls,
[
# 1
'pr_for_chromium_commit',
'create_pr',
'add_label "chromium-export"',
# 2
'pr_for_chromium_commit',
'create_pr',
'add_label "chromium-export"',
# 3
'pr_for_chromium_commit',
'create_pr',
'add_label "chromium-export"',
])
self.assertEqual(test_exporter.wpt_github.pull_requests_created, [
('chromium-export-96862edfc1', 'subject 1',
'body 1\n\nChange-Id: I001\n'),
('chromium-export-ce0e78bf18', 'subject 3',
'body 3\n\nChange-Id: I003\n'),
])
def test_creates_and_merges_pull_requests(self):
# This tests 4 exportable commits:
# 1. #458475 has a provisional in-flight PR associated with it. The PR needs to be updated but not merged.
# 2. #458476 has no PR associated with it and should have one created.
# 3. #458477 has a closed PR associated with it and should be skipped.
# 4. #458478 has an in-flight PR associated with it and should be merged successfully.
# 5. #458479 has an in-flight PR associated with it but can not be merged.
test_exporter = TestExporter(self.host)
test_exporter.wpt_github = MockWPTGitHub(
pull_requests=[
PullRequest(
title='Open PR',
number=1234,
body=
'rutabaga\nCr-Commit-Position: refs/heads/master@{#458475}\nChange-Id: I0005',
state='open',
labels=['do not merge yet']),
PullRequest(
title='Merged PR',
number=2345,
body=
'rutabaga\nCr-Commit-Position: refs/heads/master@{#458477}\nChange-Id: Idead',
state='closed',
labels=[]),
PullRequest(
title='Open PR',
number=3456,
body=
'rutabaga\nCr-Commit-Position: refs/heads/master@{#458478}\nChange-Id: I0118',
state='open',
labels=[] # It's important that this is empty.
),
PullRequest(
title='Open PR',
number=4747,
body=
'rutabaga\nCr-Commit-Position: refs/heads/master@{#458479}\nChange-Id: I0147',
state='open',
labels=[] # It's important that this is empty.
),
],
unsuccessful_merge_index=3) # Mark the last PR as unmergable.
test_exporter.gerrit = MockGerritAPI()
test_exporter.get_exportable_commits = lambda: ([
MockChromiumCommit(
self.host, position='refs/heads/master@{#458475}', change_id='I0005'),
MockChromiumCommit(
self.host, position='refs/heads/master@{#458476}', change_id='I0476'),
MockChromiumCommit(
self.host, position='refs/heads/master@{#458477}', change_id='Idead'),
MockChromiumCommit(
self.host, position='refs/heads/master@{#458478}', change_id='I0118'),
MockChromiumCommit(
self.host, position='refs/heads/master@{#458479}', change_id='I0147'),
], [])
success = test_exporter.main(
['--credentials-json', '/tmp/credentials.json'])
self.assertTrue(success)
self.assertEqual(
test_exporter.wpt_github.calls,
[
# 1. #458475
'pr_for_chromium_commit',
'get_pr_branch',
'update_pr',
'remove_label "do not merge yet"',
# 2. #458476
'pr_for_chromium_commit',
'create_pr',
'add_label "chromium-export"',
# 3. #458477
'pr_for_chromium_commit',
# 4. #458478
'pr_for_chromium_commit',
# Testing the lack of remove_label here. The exporter should not
# try to remove the provisional label from PRs it has already
# removed it from.
'get_pr_branch',
'merge_pr',
# 5. #458479
'pr_for_chromium_commit',
'get_pr_branch',
'merge_pr',
])
self.assertEqual(test_exporter.wpt_github.pull_requests_created, [
('chromium-export-52c3178508', 'Fake subject',
'Fake body\n\nChange-Id: I0476\n'),
])
self.assertEqual(test_exporter.wpt_github.pull_requests_merged, [3456])
def test_new_gerrit_cl(self):
test_exporter = TestExporter(self.host)
test_exporter.wpt_github = MockWPTGitHub(pull_requests=[])
test_exporter.get_exportable_commits = lambda: ([], [])
test_exporter.gerrit = MockGerritAPI()
test_exporter.gerrit.exportable_open_cls = [
MockGerritCL(
data={
'change_id': 'I001',
'subject': 'subject',
'_number': 1234,
'current_revision': '1',
'has_review_started': True,
'revisions': {
'1': {
'commit_with_footers': 'a commit with footers'
}
},
'owner': {
'email': 'test@chromium.org'
},
},
api=test_exporter.gerrit,
chromium_commit=MockChromiumCommit(
self.host,
subject='subject',
body='fake body <html>',
change_id='I001')),
MockGerritCL(
data={
'change_id': 'I002',
'subject': 'subject',
'_number': 1235,
'current_revision': '1',
'has_review_started': True,
'revisions': {
'1': {
'commit_with_footers': 'a commit with footers'
}
},
'owner': {
'email': 'test@chromium.org'
},
},
api=test_exporter.gerrit,
chromium_commit=MockChromiumCommit(
self.host, subject='subject', body='body',
change_id=None)),
]
test_exporter.main(['--credentials-json', '/tmp/credentials.json'])
self.assertEqual(test_exporter.wpt_github.calls, [
'pr_with_change_id',
'create_pr',
'add_label "chromium-export"',
'add_label "do not merge yet"',
'pr_with_change_id',
'create_pr',
'add_label "chromium-export"',
'add_label "do not merge yet"',
])
self.assertEqual(test_exporter.wpt_github.pull_requests_created, [
('chromium-export-cl-1234', 'subject',
'fake body \\<html>\n\nChange-Id: I001\nReviewed-on: '
'https://chromium-review.googlesource.com/1234\n'
'WPT-Export-Revision: 1'),
('chromium-export-cl-1235', 'subject',
'body\nChange-Id: I002\nReviewed-on: '
'https://chromium-review.googlesource.com/1235\n'
'WPT-Export-Revision: 1'),
])
self.assertEqual(test_exporter.wpt_github.pull_requests_merged, [])
def test_gerrit_cl_no_update_if_pr_with_same_revision(self):
test_exporter = TestExporter(self.host)
test_exporter.wpt_github = MockWPTGitHub(pull_requests=[
PullRequest(
title='title1',
number=1234,
body='description\nWPT-Export-Revision: 1',
state='open',
labels=[]),
])
test_exporter.get_exportable_commits = lambda: ([], [])
test_exporter.gerrit = MockGerritAPI()
test_exporter.gerrit.exportable_open_cls = [
MockGerritCL(
data={
'change_id': '1',
'subject': 'subject',
'_number': 1,
'current_revision': '1',
'has_review_started': True,
'revisions': {
'1': {
'commit_with_footers': 'a commit with footers'
}
},
'owner': {
'email': 'test@chromium.org'
},
},
api=test_exporter.gerrit,
chromium_commit=MockChromiumCommit(self.host))
]
success = test_exporter.main(
['--credentials-json', '/tmp/credentials.json'])
self.assertTrue(success)
self.assertEqual(test_exporter.wpt_github.calls, [
'pr_with_change_id',
])
self.assertEqual(test_exporter.wpt_github.pull_requests_created, [])
self.assertEqual(test_exporter.wpt_github.pull_requests_merged, [])
def test_gerrit_cl_updates_if_cl_has_new_revision(self):
test_exporter = TestExporter(self.host)
test_exporter.wpt_github = MockWPTGitHub(pull_requests=[
PullRequest(
title='title1',
number=1234,
body='description\nWPT-Export-Revision: 1',
state='open',
labels=[]),
])
test_exporter.get_exportable_commits = lambda: ([], [])
test_exporter.gerrit = MockGerritAPI()
test_exporter.gerrit.exportable_open_cls = [
MockGerritCL(
data={
'change_id': '1',
'subject': 'subject',
'_number': 1,
'current_revision': '2',
'has_review_started': True,
'revisions': {
'1': {
'commit_with_footers': 'a commit with footers 1',
'description': 'subject 1',
},
'2': {
'commit_with_footers': 'a commit with footers 2',
'description': 'subject 2',
},
},
'owner': {
'email': 'test@chromium.org'
},
},
api=test_exporter.gerrit,
chromium_commit=MockChromiumCommit(self.host))
]
test_exporter.main(['--credentials-json', '/tmp/credentials.json'])
self.assertEqual(test_exporter.wpt_github.calls, [
'pr_with_change_id',
'get_pr_branch',
'update_pr',
])
self.assertEqual(test_exporter.wpt_github.pull_requests_created, [])
self.assertEqual(test_exporter.wpt_github.pull_requests_merged, [])
def test_attempts_to_merge_landed_gerrit_cl(self):
test_exporter = TestExporter(self.host)
test_exporter.wpt_github = MockWPTGitHub(pull_requests=[
PullRequest(
title='title1',
number=1234,
body='description\nWPT-Export-Revision: 9\nChange-Id: decafbad',
state='open',
labels=['do not merge yet']),
])
test_exporter.get_exportable_commits = lambda: ([
MockChromiumCommit(self.host, change_id='decafbad'), ], [])
test_exporter.gerrit = MockGerritAPI()
success = test_exporter.main(
['--credentials-json', '/tmp/credentials.json'])
self.assertTrue(success)
self.assertEqual(test_exporter.wpt_github.calls, [
'pr_for_chromium_commit',
'get_pr_branch',
'update_pr',
'remove_label "do not merge yet"',
])
self.assertEqual(test_exporter.wpt_github.pull_requests_created, [])
self.assertEqual(test_exporter.wpt_github.pull_requests_merged, [])
def test_merges_non_provisional_pr(self):
test_exporter = TestExporter(self.host)
test_exporter.wpt_github = MockWPTGitHub(pull_requests=[
PullRequest(
title='title1',
number=1234,
body='description\nWPT-Export-Revision: 9\nChange-Id: decafbad',
state='open',
labels=['']),
])
test_exporter.get_exportable_commits = lambda: ([
MockChromiumCommit(self.host, change_id='decafbad'), ], [])
test_exporter.gerrit = MockGerritAPI()
success = test_exporter.main(
['--credentials-json', '/tmp/credentials.json'])
self.assertTrue(success)
self.assertEqual(test_exporter.wpt_github.calls, [
'pr_for_chromium_commit',
'get_pr_branch',
'merge_pr',
])
self.assertEqual(test_exporter.wpt_github.pull_requests_created, [])
self.assertEqual(test_exporter.wpt_github.pull_requests_merged, [1234])
def test_does_not_create_pr_if_cl_review_has_not_started(self):
test_exporter = TestExporter(self.host)
test_exporter.wpt_github = MockWPTGitHub(pull_requests=[])
test_exporter.get_exportable_commits = lambda: ([], [])
test_exporter.gerrit = MockGerritAPI()
test_exporter.gerrit.exportable_open_cls = [
MockGerritCL(
data={
'change_id': '1',
'subject': 'subject',
'_number': 1,
'current_revision': '2',
'has_review_started': False,
'revisions': {
'1': {
'commit_with_footers': 'a commit with footers 1',
'description': 'subject 1',
},
'2': {
'commit_with_footers': 'a commit with footers 2',
'description': 'subject 2',
},
},
'owner': {
'email': 'test@chromium.org'
},
},
api=test_exporter.gerrit,
chromium_commit=MockChromiumCommit(self.host))
]
success = test_exporter.main(
['--credentials-json', '/tmp/credentials.json'])
self.assertTrue(success)
self.assertEqual(test_exporter.wpt_github.calls, [])
self.assertEqual(test_exporter.wpt_github.pull_requests_created, [])
self.assertEqual(test_exporter.wpt_github.pull_requests_merged, [])
def test_run_returns_false_on_gerrit_search_error(self):
def raise_gerrit_error():
raise GerritError('Gerrit API fails.')
test_exporter = TestExporter(self.host)
test_exporter.wpt_github = MockWPTGitHub(pull_requests=[])
test_exporter.get_exportable_commits = lambda: ([], [])
test_exporter.gerrit = MockGerritAPI()
test_exporter.gerrit.query_exportable_open_cls = raise_gerrit_error
success = test_exporter.main(
['--credentials-json', '/tmp/credentials.json'])
self.assertFalse(success)
self.assertLog([
'INFO: Cloning GitHub web-platform-tests/wpt into /tmp/wpt\n',
'INFO: Setting git user name & email in /tmp/wpt\n',
'INFO: Searching for exportable in-flight CLs.\n',
'INFO: In-flight CLs cannot be exported due to the following error:\n',
'ERROR: Gerrit API fails.\n',
'INFO: Searching for exportable Chromium commits.\n'
])
def test_run_returns_false_on_patch_failure(self):
test_exporter = TestExporter(self.host)
test_exporter.wpt_github = MockWPTGitHub(pull_requests=[])
test_exporter.get_exportable_commits = lambda: (
[], ['There was an error with the rutabaga.'])
test_exporter.gerrit = MockGerritAPI()
success = test_exporter.main(
['--credentials-json', '/tmp/credentials.json'])
self.assertFalse(success)
self.assertLog([
'INFO: Cloning GitHub web-platform-tests/wpt into /tmp/wpt\n',
'INFO: Setting git user name & email in /tmp/wpt\n',
'INFO: Searching for exportable in-flight CLs.\n',
'INFO: Searching for exportable Chromium commits.\n',
'INFO: Attention: The following errors have prevented some commits from being exported:\n',
'ERROR: There was an error with the rutabaga.\n'
])