Exemple #1
0
    def test_commit_with_noexport_is_not_exportable(self):
        # Patch is not tested if the commit is ignored based on the message, hence empty MockLocalWPT.

        commit = MockChromiumCommit(MockHost(),
                                    body='Message\nNo-Export: true')
        github = MockWPTGitHub(pull_requests=[])
        self.assertEqual(
            get_commit_export_state(commit, MockLocalWPT(), github),
            (CommitExportState.IGNORED, ''))

        # The older NOEXPORT tag also makes it non-exportable.
        old_commit = MockChromiumCommit(MockHost(),
                                        body='Message\nNOEXPORT=true')
        self.assertEqual(
            get_commit_export_state(old_commit, MockLocalWPT(), github),
            (CommitExportState.IGNORED, ''))

        # No-Export/NOEXPORT in a revert CL also makes it non-exportable.
        revert = MockChromiumCommit(
            MockHost(), body='Revert of Message\n> No-Export: true')
        self.assertEqual(
            get_commit_export_state(revert, MockLocalWPT(), github),
            (CommitExportState.IGNORED, ''))
        old_revert = MockChromiumCommit(
            MockHost(), body='Revert of Message\n> NOEXPORT=true')
        self.assertEqual(
            get_commit_export_state(old_revert, MockLocalWPT(), github),
            (CommitExportState.IGNORED, ''))
    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_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': '*****@*****.**'},
            },
            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_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': '*****@*****.**'},
            },
            api=test_exporter.gerrit,
            chromium_commit=MockChromiumCommit(self.host, subject='subject', body='fake body', change_id='I001')
        )]
        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"',
        ])
        self.assertEqual(test_exporter.wpt_github.pull_requests_created, [
            ('chromium-export-cl-1234',
             'subject',
             'fake body\n\nChange-Id: I001\nReviewed-on: https://chromium-review.googlesource.com/1234\nWPT-Export-Revision: 1'),
        ])
        self.assertEqual(test_exporter.wpt_github.pull_requests_merged, [])
Exemple #5
0
    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(self.host, 'gerrit-username',
                                             'gerrit-token')
        test_exporter.gerrit.query_exportable_open_cls = lambda: []
        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_pull_request',
            'delete_remote_branch',
        ])
        self.assertEqual(test_exporter.wpt_github.pull_requests_created, [])
        self.assertEqual(test_exporter.wpt_github.pull_requests_merged, [1234])
Exemple #6
0
    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, [])
Exemple #7
0
 def test_commit_that_produces_errors(self):
     commit = MockChromiumCommit(MockHost())
     github = MockWPTGitHub(pull_requests=[])
     self.assertEqual(
         get_commit_export_state(
             commit, MockLocalWPT(test_patch=[(False, 'error')]), github),
         (CommitExportState.EXPORTABLE_DIRTY, 'error'))
Exemple #8
0
 def test_apply_exportable_commits_locally(self):
     host = MockHost()
     importer = TestImporter(host, wpt_github=MockWPTGitHub(pull_requests=[]))
     fake_commit = MockChromiumCommit(
         host, subject='My fake commit',
         patch=(
             'Fake patch contents...\n'
             '--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-ui-3/outline-004.html\n'
             '+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-ui-3/outline-004.html\n'
             '@@ -20,7 +20,7 @@\n'
             '...'))
     importer.exportable_but_not_exported_commits = lambda _: [fake_commit]
     applied = importer.apply_exportable_commits_locally(LocalWPT(host))
     self.assertEqual(applied, [fake_commit])
     self.assertEqual(host.executive.full_calls, [
         MockCall(
             ['git', 'apply', '-'],
             {
                 'input': (
                     'Fake patch contents...\n'
                     '--- a/css/css-ui-3/outline-004.html\n'
                     '+++ b/css/css-ui-3/outline-004.html\n'
                     '@@ -20,7 +20,7 @@\n'
                     '...'),
                 'cwd': '/tmp/wpt',
                 'env': None
             }),
         MockCall(
             ['git', 'add', '.'],
             kwargs={'input': None, 'cwd': '/tmp/wpt', 'env': None}),
         MockCall(
             ['git', 'commit', '--all', '-F', '-'],
             kwargs={'cwd': '/tmp/wpt', 'env': None})
     ])
 def test_commit_that_has_closed_pr_is_not_exportable(self):
     commit = MockChromiumCommit(MockHost(), change_id='I00decade')
     github = MockWPTGitHub(pull_requests=[
         PullRequest('PR1', 1, 'body\nChange-Id: I00c0ffee', 'closed', []),
         PullRequest('PR2', 2, 'body\nChange-Id: I00decade', 'closed', []),
     ])
     self.assertEqual(get_commit_export_state(commit, MockLocalWPT(), github), (CommitExportState.EXPORTED, ''))
    def test_pr_for_chromium_commit_multiple_commit_positions(self):
        self.wpt_github.all_pull_requests = lambda: [
            PullRequest(
                'PR1', 1, 'body\nCr-Commit-Position: refs/heads/master@{#10}\n'
                'Cr-Commit-Position: refs/heads/master@{#33}', 'open', []),
        ]

        chromium_commit = MockChromiumCommit(
            MockHost(), position='refs/heads/master@{#10}')
        pull_request = self.wpt_github.pr_for_chromium_commit(chromium_commit)
        self.assertEqual(pull_request.number, 1)

        chromium_commit = MockChromiumCommit(
            MockHost(), position='refs/heads/master@{#33}')
        pull_request = self.wpt_github.pr_for_chromium_commit(chromium_commit)
        self.assertEqual(pull_request.number, 1)
Exemple #11
0
 def test_main_abort_on_exportable_commit_if_open_pr_found(self):
     host = MockHost()
     host.filesystem.write_text_file(
         '/tmp/creds.json', '{"GH_USER": "******", "GH_TOKEN": "y"}')
     wpt_github = MockWPTGitHub(pull_requests=[
         PullRequest('Title', 5, 'Commit body\nChange-Id: Iba5eba11', 'open', []),
     ])
     importer = TestImporter(host, wpt_github=wpt_github)
     importer.exportable_but_not_exported_commits = lambda _: [
         MockChromiumCommit(host, subject='Fake PR subject', change_id='Iba5eba11')
     ]
     importer.checkout_is_okay = lambda: True
     return_code = importer.main(['--credentials-json=/tmp/creds.json'])
     self.assertEqual(return_code, 0)
     self.assertLog([
         'INFO: Cloning GitHub w3c/web-platform-tests into /tmp/wpt\n',
         'INFO: There were exportable but not-yet-exported commits:\n',
         'INFO: Commit: https://fake-chromium-commit-viewer.org/+/14fd77e88e\n',
         'INFO: Subject: Fake PR subject\n',
         'INFO: PR: https://github.com/w3c/web-platform-tests/pull/5\n',
         'INFO: Modified files in wpt directory in this commit:\n',
         'INFO:   third_party/WebKit/LayoutTests/external/wpt/one.html\n',
         'INFO:   third_party/WebKit/LayoutTests/external/wpt/two.html\n',
         'INFO: Aborting import to prevent clobbering commits.\n',
     ])
    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': '*****@*****.**'},
            },
            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, [])
Exemple #13
0
 def test_get_commit_export_state(self):
     commit = MockChromiumCommit(MockHost())
     github = MockWPTGitHub(pull_requests=[])
     self.assertEqual(
         get_commit_export_state(commit,
                                 MockLocalWPT(test_patch=[(True, '')]),
                                 github),
         (CommitExportState.EXPORTABLE_CLEAN, ''))
Exemple #14
0
 def test_pr_for_chromium_commit_falls_back_to_commit_position(self):
     self.wpt_github.all_pull_requests = lambda: [
         PullRequest('PR1', 1, 'body\nChange-Id: I00c0ffee\nCr-Commit-Position: refs/heads/master@{#10}', 'open', []),
         PullRequest('PR2', 2, 'body\nChange-Id: I00decade\nCr-Commit-Position: refs/heads/master@{#33}', 'open', []),
     ]
     chromium_commit = MockChromiumCommit(
         MockHost(), position='refs/heads/master@{#10}')
     pull_request = self.wpt_github.pr_for_chromium_commit(chromium_commit)
     self.assertEqual(pull_request.number, 1)
 def test_apply_exportable_commits_locally_returns_none_on_failure(self):
     host = MockHost()
     wpt_github = MockWPTGitHub(pull_requests=[])
     importer = TestImporter(host, wpt_github=wpt_github)
     commit = MockChromiumCommit(host, subject='My fake commit')
     importer.exportable_but_not_exported_commits = lambda _: [commit]
     local_wpt = MockLocalWPT(apply_patch=['Failed'])    # Failure to apply patch.
     applied = importer.apply_exportable_commits_locally(local_wpt)
     self.assertIsNone(applied)
Exemple #16
0
 def test_commit_that_has_open_pr_is_exportable(self):
     commit = MockChromiumCommit(MockHost(), change_id='I00decade')
     github = MockWPTGitHub(pull_requests=[
         PullRequest('PR2', 2, 'body\nChange-Id: I00decade', 'open', []),
     ])
     self.assertEqual(
         get_commit_export_state(commit,
                                 MockLocalWPT(test_patch=[(True, '')]),
                                 github),
         (CommitExportState.EXPORTABLE_CLEAN, ''))
    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.get_exportable_commits = lambda: ([
            MockChromiumCommit(self.host, position='refs/heads/master@{#458475}'),
            MockChromiumCommit(self.host, position='refs/heads/master@{#458476}'),
            MockChromiumCommit(self.host, position='refs/heads/master@{#458477}'),
        ], [])
        success = test_exporter.main(['--credentials-json', '/tmp/credentials.json', '--dry-run'])

        self.assertTrue(success)
        self.assertEqual(test_exporter.wpt_github.calls, [
            'pr_for_chromium_commit',
            'pr_for_chromium_commit',
            'pr_for_chromium_commit',
        ])
    def test_pr_for_chromium_commit_multiple_change_ids(self):
        self.wpt_github.all_pull_requests = lambda: [
            PullRequest('PR1', 1,
                        'body\nChange-Id: I00c0ffee\nChange-Id: I00decade',
                        'open', []),
        ]

        chromium_commit = MockChromiumCommit(
            MockHost(),
            change_id='I00c0ffee',
            position='refs/heads/master@{#10}')
        pull_request = self.wpt_github.pr_for_chromium_commit(chromium_commit)
        self.assertEqual(pull_request.number, 1)

        chromium_commit = MockChromiumCommit(
            MockHost(),
            change_id='I00decade',
            position='refs/heads/master@{#33}')
        pull_request = self.wpt_github.pr_for_chromium_commit(chromium_commit)
        self.assertEqual(pull_request.number, 1)
Exemple #19
0
 def test_commit_that_has_merged_pr_but_not_found_locally(self):
     commit = MockChromiumCommit(MockHost(), change_id='I00decade')
     github = MockWPTGitHub(pull_requests=[
         PullRequest('PR2', 2, 'body\nChange-Id: I00decade', 'closed', []),
     ],
                            merged_index=0)
     # verify_merged_pr should be False by default.
     self.assertEqual(
         get_commit_export_state(commit, MockLocalWPT(), github),
         (CommitExportState.EXPORTED, ''))
     self.assertEqual(
         get_commit_export_state(commit,
                                 MockLocalWPT(test_patch=[(True, '')]),
                                 github,
                                 verify_merged_pr=True),
         (CommitExportState.EXPORTABLE_CLEAN, ''))
Exemple #20
0
 def test_commit_that_has_closed_but_not_merged_pr(self):
     commit = MockChromiumCommit(MockHost(), change_id='I00decade')
     github = MockWPTGitHub(pull_requests=[
         PullRequest('PR2', 2, 'body\nChange-Id: I00decade', 'closed', []),
     ])
     # Regardless of verify_merged_pr, abandoned PRs are always exported.
     self.assertEqual(
         get_commit_export_state(commit,
                                 MockLocalWPT(),
                                 github,
                                 verify_merged_pr=False),
         (CommitExportState.EXPORTED, ''))
     self.assertEqual(
         get_commit_export_state(commit,
                                 MockLocalWPT(),
                                 github,
                                 verify_merged_pr=True),
         (CommitExportState.EXPORTED, ''))
Exemple #21
0
 def test_commit_that_has_merged_pr_and_found_locally(self):
     commit = MockChromiumCommit(MockHost(), change_id='I00decade')
     github = MockWPTGitHub(pull_requests=[
         PullRequest('PR2', 2, 'body\nChange-Id: I00decade', 'closed', []),
     ],
                            merged_index=0)
     self.assertEqual(
         get_commit_export_state(commit,
                                 MockLocalWPT(change_ids=['I00decade']),
                                 github,
                                 verify_merged_pr=False),
         (CommitExportState.EXPORTED, ''))
     self.assertEqual(
         get_commit_export_state(commit,
                                 MockLocalWPT(change_ids=['I00decade']),
                                 github,
                                 verify_merged_pr=True),
         (CommitExportState.EXPORTED, ''))
 def test_apply_exportable_commits_locally(self):
     # TODO(robertma): Consider using MockLocalWPT.
     host = MockHost()
     importer = TestImporter(host,
                             wpt_github=MockWPTGitHub(pull_requests=[]))
     importer.wpt_git = MockGit(cwd='/tmp/wpt', executive=host.executive)
     fake_commit = MockChromiumCommit(
         host,
         subject='My fake commit',
         patch=
         ('Fake patch contents...\n'
          '--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-ui-3/outline-004.html\n'
          '+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-ui-3/outline-004.html\n'
          '@@ -20,7 +20,7 @@\n'
          '...'))
     importer.exportable_but_not_exported_commits = lambda _: [fake_commit]
     applied = importer.apply_exportable_commits_locally(LocalWPT(host))
     self.assertEqual(applied, [fake_commit])
     # This assertion is implementation details of LocalWPT.apply_patch.
     # TODO(robertma): Move this to local_wpt_unittest.py.
     self.assertEqual(host.executive.full_calls, [
         MockCall(
             ['git', 'apply', '-'], {
                 'input': ('Fake patch contents...\n'
                           '--- a/css/css-ui-3/outline-004.html\n'
                           '+++ b/css/css-ui-3/outline-004.html\n'
                           '@@ -20,7 +20,7 @@\n'
                           '...'),
                 'cwd':
                 '/tmp/wpt',
                 'env':
                 None
             }),
         MockCall(['git', 'add', '.'],
                  kwargs={
                      'input': None,
                      'cwd': '/tmp/wpt',
                      'env': None
                  })
     ])
     self.assertEqual(
         importer.wpt_git.local_commits(),
         [['Applying patch 14fd77e88e42147c57935c49d9e3b2412b8491b7']])
Exemple #23
0
 def test_main_abort_on_exportable_commit_if_no_pr_found(self):
     host = MockHost()
     host.filesystem.write_text_file(
         '/tmp/creds.json', '{"GH_USER": "******", "GH_TOKEN": "y"}')
     wpt_github = MockWPTGitHub(pull_requests=[])
     importer = TestImporter(host, wpt_github=wpt_github)
     importer.exportable_but_not_exported_commits = lambda _: [
         MockChromiumCommit(host, subject='Fake PR subject', position='refs/heads/master@{#431}')
     ]
     importer.checkout_is_okay = lambda: True
     return_code = importer.main(['--credentials-json=/tmp/creds.json'])
     self.assertEqual(return_code, 0)
     self.assertLog([
         'INFO: Cloning GitHub w3c/web-platform-tests into /tmp/wpt\n',
         'INFO: There were exportable but not-yet-exported commits:\n',
         'INFO: Commit: https://fake-chromium-commit-viewer.org/+/fa2de685c0\n',
         'INFO: Subject: Fake PR subject\n',
         'WARNING: No pull request found.\n',
         'INFO: Modified files in wpt directory in this commit:\n',
         'INFO:   third_party/WebKit/LayoutTests/external/wpt/one.html\n',
         'INFO:   third_party/WebKit/LayoutTests/external/wpt/two.html\n',
         'INFO: Aborting import to prevent clobbering commits.\n',
     ])
 def test_commit_that_starts_with_import_is_not_exportable(self):
     commit = MockChromiumCommit(MockHost(), subject='Import message')
     github = MockWPTGitHub(pull_requests=[])
     self.assertEqual(get_commit_export_state(commit, MockLocalWPT(), github), (CommitExportState.IGNORED, ''))
Exemple #25
0
    def test_creates_and_merges_pull_requests(self):
        # This tests 4 exportable commits:
        # 1. #458475 has an in-flight PR associated with it but cannot be 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.
        host = MockHost()
        host.executive = mock_git_commands({
            'show': 'git show text\nCr-Commit-Position: refs/heads/master@{#458476}\nChange-Id: I0476',
            'crrev-parse': 'c2087acb00eee7960339a0be34ea27d6b20e1131',

        })
        test_exporter = TestExporter(host, 'gh-username', 'gh-token', gerrit_user=None, gerrit_token=None)
        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.
            ),
        ], unsuccessful_merge_index=0)
        test_exporter.gerrit = MockGerritAPI(host, 'gerrit-username', 'gerrit-token')
        test_exporter.get_exportable_commits = lambda: [
            MockChromiumCommit(host, position='refs/heads/master@{#458475}', change_id='I0005'),
            MockChromiumCommit(host, position='refs/heads/master@{#458476}', change_id='I0476'),
            MockChromiumCommit(host, position='refs/heads/master@{#458477}', change_id='Idead'),
            MockChromiumCommit(host, position='refs/heads/master@{#458478}', change_id='I0118'),
        ]
        test_exporter.run()
        self.assertEqual(test_exporter.wpt_github.calls, [
            'pr_for_chromium_commit',
            'remove_label "do not merge yet"',
            'get_pr_branch',
            'merge_pull_request',
            'pr_for_chromium_commit',
            'create_pr',
            'add_label "chromium-export"',
            'pr_for_chromium_commit',
            '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_pull_request',
            'delete_remote_branch',
        ])
        self.assertEqual(test_exporter.wpt_github.pull_requests_created, [
            ('chromium-export-52c3178508', 'Fake subject', 'Fake body\n\nChange-Id: I0476'),
        ])
    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',
            'delete_remote_branch',
            # 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])