Home | History | Annotate | Download | only in checkout
      1 # Copyright (C) 2010 Google Inc. All rights reserved.
      2 #
      3 # Redistribution and use in source and binary forms, with or without
      4 # modification, are permitted provided that the following conditions are
      5 # met:
      6 #
      7 #    * Redistributions of source code must retain the above copyright
      8 # notice, this list of conditions and the following disclaimer.
      9 #    * Redistributions in binary form must reproduce the above
     10 # copyright notice, this list of conditions and the following disclaimer
     11 # in the documentation and/or other materials provided with the
     12 # distribution.
     13 #    * Neither the name of Google Inc. nor the names of its
     14 # contributors may be used to endorse or promote products derived from
     15 # this software without specific prior written permission.
     16 #
     17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 
     29 from __future__ import with_statement
     30 
     31 import codecs
     32 import os
     33 import shutil
     34 import tempfile
     35 import unittest
     36 
     37 from webkitpy.common.checkout.api import Checkout
     38 from webkitpy.common.checkout.changelog import ChangeLogEntry
     39 from webkitpy.common.checkout.scm import detect_scm_system, CommitMessage
     40 from webkitpy.common.system.outputcapture import OutputCapture
     41 from webkitpy.common.system.executive import ScriptError
     42 from webkitpy.thirdparty.mock import Mock
     43 
     44 
     45 # FIXME: Copied from scm_unittest.py
     46 def write_into_file_at_path(file_path, contents, encoding="utf-8"):
     47     with codecs.open(file_path, "w", encoding) as file:
     48         file.write(contents)
     49 
     50 
     51 _changelog1entry1 = u"""2010-03-25  Tor Arne Vestb\u00f8  <vestbo (at] webkit.org>
     52 
     53         Unreviewed build fix to un-break webkit-patch land.
     54 
     55         Move commit_message_for_this_commit from scm to checkout
     56         https://bugs.webkit.org/show_bug.cgi?id=36629
     57 
     58         * Scripts/webkitpy/common/checkout/api.py: import scm.CommitMessage
     59 """
     60 _changelog1entry2 = u"""2010-03-25  Adam Barth  <abarth (at] webkit.org>
     61 
     62         Reviewed by Eric Seidel.
     63 
     64         Move commit_message_for_this_commit from scm to checkout
     65         https://bugs.webkit.org/show_bug.cgi?id=36629
     66 
     67         * Scripts/webkitpy/common/checkout/api.py:
     68 """
     69 _changelog1 = u"\n".join([_changelog1entry1, _changelog1entry2])
     70 _changelog2 = u"""2010-03-25  Tor Arne Vestb\u00f8  <vestbo (at] webkit.org>
     71 
     72         Unreviewed build fix to un-break webkit-patch land.
     73 
     74         Second part of this complicated change.
     75 
     76         * Path/To/Complicated/File: Added.
     77 
     78 2010-03-25  Adam Barth  <abarth (at] webkit.org>
     79 
     80         Reviewed by Eric Seidel.
     81 
     82         Filler change.
     83 """
     84 
     85 class CommitMessageForThisCommitTest(unittest.TestCase):
     86     expected_commit_message = u"""2010-03-25  Tor Arne Vestb\u00f8  <vestbo (at] webkit.org>
     87 
     88         Unreviewed build fix to un-break webkit-patch land.
     89 
     90         Move commit_message_for_this_commit from scm to checkout
     91         https://bugs.webkit.org/show_bug.cgi?id=36629
     92 
     93         * Scripts/webkitpy/common/checkout/api.py: import scm.CommitMessage
     94 2010-03-25  Tor Arne Vestb\u00f8  <vestbo (at] webkit.org>
     95 
     96         Unreviewed build fix to un-break webkit-patch land.
     97 
     98         Second part of this complicated change.
     99 
    100         * Path/To/Complicated/File: Added.
    101 """
    102 
    103     def setUp(self):
    104         self.temp_dir = tempfile.mkdtemp(suffix="changelogs")
    105         self.old_cwd = os.getcwd()
    106         os.chdir(self.temp_dir)
    107         write_into_file_at_path("ChangeLog1", _changelog1)
    108         write_into_file_at_path("ChangeLog2", _changelog2)
    109 
    110     def tearDown(self):
    111         shutil.rmtree(self.temp_dir, ignore_errors=True)
    112         os.chdir(self.old_cwd)
    113 
    114     # FIXME: This should not need to touch the file system, however
    115     # ChangeLog is difficult to mock at current.
    116     def test_commit_message_for_this_commit(self):
    117         checkout = Checkout(None)
    118         checkout.modified_changelogs = lambda git_commit, changed_files=None: ["ChangeLog1", "ChangeLog2"]
    119         output = OutputCapture()
    120         expected_stderr = "Parsing ChangeLog: ChangeLog1\nParsing ChangeLog: ChangeLog2\n"
    121         commit_message = output.assert_outputs(self, checkout.commit_message_for_this_commit,
    122             kwargs={"git_commit": None}, expected_stderr=expected_stderr)
    123         self.assertEqual(commit_message.message(), self.expected_commit_message)
    124 
    125 
    126 class CheckoutTest(unittest.TestCase):
    127     def test_latest_entry_for_changelog_at_revision(self):
    128         scm = Mock()
    129         def mock_contents_at_revision(changelog_path, revision):
    130             self.assertEqual(changelog_path, "foo")
    131             self.assertEqual(revision, "bar")
    132             # contents_at_revision is expected to return a byte array (str)
    133             # so we encode our unicode ChangeLog down to a utf-8 stream.
    134             # The ChangeLog utf-8 decoding should ignore invalid codepoints.
    135             invalid_utf8 = "\255"
    136             return _changelog1.encode("utf-8") + invalid_utf8
    137         scm.contents_at_revision = mock_contents_at_revision
    138         checkout = Checkout(scm)
    139         entry = checkout._latest_entry_for_changelog_at_revision("foo", "bar")
    140         self.assertEqual(entry.contents(), _changelog1entry1)
    141 
    142     # FIXME: This tests a hack around our current changed_files handling.
    143     # Right now changelog_entries_for_revision tries to fetch deleted files
    144     # from revisions, resulting in a ScriptError exception.  Test that we
    145     # recover from those and still return the other ChangeLog entries.
    146     def test_changelog_entries_for_revision(self):
    147         scm = Mock()
    148         scm.changed_files_for_revision = lambda revision: ['foo/ChangeLog', 'bar/ChangeLog']
    149         checkout = Checkout(scm)
    150 
    151         def mock_latest_entry_for_changelog_at_revision(path, revision):
    152             if path == "foo/ChangeLog":
    153                 return 'foo'
    154             raise ScriptError()
    155 
    156         checkout._latest_entry_for_changelog_at_revision = mock_latest_entry_for_changelog_at_revision
    157 
    158         # Even though fetching one of the entries failed, the other should succeed.
    159         entries = checkout.changelog_entries_for_revision(1)
    160         self.assertEqual(len(entries), 1)
    161         self.assertEqual(entries[0], 'foo')
    162 
    163     def test_commit_info_for_revision(self):
    164         scm = Mock()
    165         scm.committer_email_for_revision = lambda revision: "committer (at] example.com"
    166         checkout = Checkout(scm)
    167         checkout.changelog_entries_for_revision = lambda revision: [ChangeLogEntry(_changelog1entry1)]
    168         commitinfo = checkout.commit_info_for_revision(4)
    169         self.assertEqual(commitinfo.bug_id(), 36629)
    170         self.assertEqual(commitinfo.author_name(), u"Tor Arne Vestb\u00f8")
    171         self.assertEqual(commitinfo.author_email(), "vestbo (at] webkit.org")
    172         self.assertEqual(commitinfo.reviewer_text(), None)
    173         self.assertEqual(commitinfo.reviewer(), None)
    174         self.assertEqual(commitinfo.committer_email(), "committer (at] example.com")
    175         self.assertEqual(commitinfo.committer(), None)
    176 
    177         checkout.changelog_entries_for_revision = lambda revision: []
    178         self.assertEqual(checkout.commit_info_for_revision(1), None)
    179 
    180     def test_bug_id_for_revision(self):
    181         scm = Mock()
    182         scm.committer_email_for_revision = lambda revision: "committer (at] example.com"
    183         checkout = Checkout(scm)
    184         checkout.changelog_entries_for_revision = lambda revision: [ChangeLogEntry(_changelog1entry1)]
    185         self.assertEqual(checkout.bug_id_for_revision(4), 36629)
    186 
    187     def test_bug_id_for_this_commit(self):
    188         scm = Mock()
    189         checkout = Checkout(scm)
    190         checkout.commit_message_for_this_commit = lambda git_commit, changed_files=None: CommitMessage(ChangeLogEntry(_changelog1entry1).contents().splitlines())
    191         self.assertEqual(checkout.bug_id_for_this_commit(git_commit=None), 36629)
    192 
    193     def test_modified_changelogs(self):
    194         scm = Mock()
    195         scm.checkout_root = "/foo/bar"
    196         scm.changed_files = lambda git_commit: ["file1", "ChangeLog", "relative/path/ChangeLog"]
    197         checkout = Checkout(scm)
    198         expected_changlogs = ["/foo/bar/ChangeLog", "/foo/bar/relative/path/ChangeLog"]
    199         self.assertEqual(checkout.modified_changelogs(git_commit=None), expected_changlogs)
    200 
    201     def test_suggested_reviewers(self):
    202         def mock_changelog_entries_for_revision(revision):
    203             if revision % 2 == 0:
    204                 return [ChangeLogEntry(_changelog1entry1)]
    205             return [ChangeLogEntry(_changelog1entry2)]
    206 
    207         def mock_revisions_changing_file(path, limit=5):
    208             if path.endswith("ChangeLog"):
    209                 return [3]
    210             return [4, 8]
    211 
    212         scm = Mock()
    213         scm.checkout_root = "/foo/bar"
    214         scm.changed_files = lambda git_commit: ["file1", "file2", "relative/path/ChangeLog"]
    215         scm.revisions_changing_file = mock_revisions_changing_file
    216         checkout = Checkout(scm)
    217         checkout.changelog_entries_for_revision = mock_changelog_entries_for_revision
    218         reviewers = checkout.suggested_reviewers(git_commit=None)
    219         reviewer_names = [reviewer.full_name for reviewer in reviewers]
    220         self.assertEqual(reviewer_names, [u'Tor Arne Vestb\xf8'])
    221