OLD | NEW |
1 # Copyright (C) 2009 Google Inc. All rights reserved. | 1 # Copyright (C) 2009 Google Inc. All rights reserved. |
2 # | 2 # |
3 # Redistribution and use in source and binary forms, with or without | 3 # Redistribution and use in source and binary forms, with or without |
4 # modification, are permitted provided that the following conditions are | 4 # modification, are permitted provided that the following conditions are |
5 # met: | 5 # met: |
6 # | 6 # |
7 # * Redistributions of source code must retain the above copyright | 7 # * Redistributions of source code must retain the above copyright |
8 # notice, this list of conditions and the following disclaimer. | 8 # notice, this list of conditions and the following disclaimer. |
9 # * Redistributions in binary form must reproduce the above | 9 # * Redistributions in binary form must reproduce the above |
10 # copyright notice, this list of conditions and the following disclaimer | 10 # copyright notice, this list of conditions and the following disclaimer |
11 # in the documentation and/or other materials provided with the | 11 # in the documentation and/or other materials provided with the |
12 # distribution. | 12 # distribution. |
13 # * Neither the name of Google Inc. nor the names of its | 13 # * Neither the name of Google Inc. nor the names of its |
14 # contributors may be used to endorse or promote products derived from | 14 # contributors may be used to endorse or promote products derived from |
15 # this software without specific prior written permission. | 15 # this software without specific prior written permission. |
16 # | 16 # |
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | 28 |
29 import cStringIO as StringIO | |
30 import re | 29 import re |
31 import unittest | 30 import unittest |
32 | 31 |
33 from webkitpy.common.checkout import diff_parser | 32 from webkitpy.common.checkout.diff_parser import DiffParser |
34 from webkitpy.common.checkout.diff_test_data import DIFF_TEST_DATA | 33 from webkitpy.common.checkout.diff_test_data import DIFF_TEST_DATA |
35 | 34 |
36 | 35 |
37 class DiffParserTest(unittest.TestCase): | 36 class DiffParserTest(unittest.TestCase): |
38 maxDiff = None | |
39 | 37 |
40 def test_diff_parser(self, parser=None): | 38 def test_diff_parser(self, parser=None): |
41 if not parser: | 39 if not parser: |
42 parser = diff_parser.DiffParser(DIFF_TEST_DATA.splitlines()) | 40 parser = DiffParser(DIFF_TEST_DATA.splitlines()) |
43 self.assertEqual(3, len(parser.files)) | 41 self.assertEqual(3, len(parser.files)) |
44 | 42 |
45 self.assertIn('WebCore/style/StyleFlexibleBoxData.h', parser.files) | 43 self.assertIn('WebCore/style/StyleFlexibleBoxData.h', parser.files) |
46 diff = parser.files['WebCore/style/StyleFlexibleBoxData.h'] | 44 diff = parser.files['WebCore/style/StyleFlexibleBoxData.h'] |
47 self.assertEqual(7, len(diff.lines)) | 45 self.assertEqual(7, len(diff.lines)) |
| 46 |
48 # The first two unchanged lines. | 47 # The first two unchanged lines. |
49 self.assertEqual((47, 47), diff.lines[0][0:2]) | 48 self.assertEqual((47, 47), diff.lines[0][0:2]) |
50 self.assertEqual('', diff.lines[0][2]) | 49 self.assertEqual('', diff.lines[0][2]) |
51 self.assertEqual((48, 48), diff.lines[1][0:2]) | 50 self.assertEqual((48, 48), diff.lines[1][0:2]) |
52 self.assertEqual(' unsigned align : 3; // EBoxAlignment', diff.lines[
1][2]) | 51 self.assertEqual(' unsigned align : 3; // EBoxAlignment', diff.lines[
1][2]) |
53 # The deleted line | 52 |
| 53 # The deleted line. |
54 self.assertEqual((50, 0), diff.lines[3][0:2]) | 54 self.assertEqual((50, 0), diff.lines[3][0:2]) |
55 self.assertEqual(' unsigned orient: 1; // EBoxOrient', diff.lines[3][
2]) | 55 self.assertEqual(' unsigned orient: 1; // EBoxOrient', diff.lines[3][
2]) |
56 | 56 |
57 # The first file looks OK. Let's check the next, more complicated file. | 57 # The first file looks OK. Let's check the next, more complicated file. |
58 self.assertIn('WebCore/style/StyleRareInheritedData.cpp', parser.files) | 58 self.assertIn('WebCore/style/StyleRareInheritedData.cpp', parser.files) |
59 diff = parser.files['WebCore/style/StyleRareInheritedData.cpp'] | 59 diff = parser.files['WebCore/style/StyleRareInheritedData.cpp'] |
| 60 |
60 # There are 3 chunks. | 61 # There are 3 chunks. |
61 self.assertEqual(7 + 7 + 9, len(diff.lines)) | 62 self.assertEqual(7 + 7 + 9, len(diff.lines)) |
| 63 |
62 # Around an added line. | 64 # Around an added line. |
63 self.assertEqual((60, 61), diff.lines[9][0:2]) | 65 self.assertEqual((60, 61), diff.lines[9][0:2]) |
64 self.assertEqual((0, 62), diff.lines[10][0:2]) | 66 self.assertEqual((0, 62), diff.lines[10][0:2]) |
65 self.assertEqual((61, 63), diff.lines[11][0:2]) | 67 self.assertEqual((61, 63), diff.lines[11][0:2]) |
66 # Look through the last chunk, which contains both add's and delete's. | 68 |
| 69 # Look through the last chunk, which contains both adds and deletes. |
67 self.assertEqual((81, 83), diff.lines[14][0:2]) | 70 self.assertEqual((81, 83), diff.lines[14][0:2]) |
68 self.assertEqual((82, 84), diff.lines[15][0:2]) | 71 self.assertEqual((82, 84), diff.lines[15][0:2]) |
69 self.assertEqual((83, 85), diff.lines[16][0:2]) | 72 self.assertEqual((83, 85), diff.lines[16][0:2]) |
70 self.assertEqual((84, 0), diff.lines[17][0:2]) | 73 self.assertEqual((84, 0), diff.lines[17][0:2]) |
71 self.assertEqual((0, 86), diff.lines[18][0:2]) | 74 self.assertEqual((0, 86), diff.lines[18][0:2]) |
72 self.assertEqual((0, 87), diff.lines[19][0:2]) | 75 self.assertEqual((0, 87), diff.lines[19][0:2]) |
73 self.assertEqual((85, 88), diff.lines[20][0:2]) | 76 self.assertEqual((85, 88), diff.lines[20][0:2]) |
74 self.assertEqual((86, 89), diff.lines[21][0:2]) | 77 self.assertEqual((86, 89), diff.lines[21][0:2]) |
75 self.assertEqual((87, 90), diff.lines[22][0:2]) | 78 self.assertEqual((87, 90), diff.lines[22][0:2]) |
76 | 79 |
77 # Check if a newly added file is correctly handled. | 80 # Check if a newly added file is correctly handled. |
78 diff = parser.files['LayoutTests/platform/mac/fast/flexbox/box-orient-bu
tton-expected.checksum'] | 81 diff = parser.files['LayoutTests/platform/mac/fast/flexbox/box-orient-bu
tton-expected.checksum'] |
79 self.assertEqual(1, len(diff.lines)) | 82 self.assertEqual(1, len(diff.lines)) |
80 self.assertEqual((0, 1), diff.lines[0][0:2]) | 83 self.assertEqual((0, 1), diff.lines[0][0:2]) |
81 | 84 |
82 def test_diff_converter(self): | 85 def test_diff_parser_with_different_mnemonic_prefixes(self): |
83 comment_lines = [ | 86 # This repeats test_diff_parser but with different versions |
84 "Hey people,\n", | 87 # of DIFF_TEST_DATA that use other prefixes instead of a/b. |
85 "\n", | 88 prefixes = ( |
86 "See my awesome patch below!\n", | 89 ('i', 'w'), # git-diff (compares the (i)ndex and the (w)ork tree) |
87 "\n", | 90 ('c', 'w'), # git-diff HEAD (compares a (c)ommit and the (w)ork tre
e) |
88 " - Cool Hacker\n", | 91 ('c', 'i'), # git diff --cached (compares a (c)ommit and the (i)nde
x) |
89 "\n", | 92 ('o', 'w'), # git-diff HEAD:file1 file2 (compares an (o)bject and a
(w)ork tree entity) |
90 ] | 93 ('1', '2'), # git diff --no-index a b (compares two non-git things
(1) and (2)) |
| 94 ) |
| 95 for a_replacement, b_replacement in prefixes: |
| 96 patch = self._patch(a_replacement, b_replacement) |
| 97 self.test_diff_parser(DiffParser(patch.splitlines())) |
91 | 98 |
92 revision_lines = [ | 99 @staticmethod |
93 "Subversion Revision 289799\n", | 100 def _patch(a_replacement='a', b_replacement='b'): |
94 ] | 101 """Returns a version of the example patch with mnemonic prefixes a/b cha
nged.""" |
95 | 102 patch = re.sub(r' a/', ' %s/' % a_replacement, DIFF_TEST_DATA) |
96 svn_diff_lines = [ | 103 return re.sub(r' b/', ' %s/' % b_replacement, patch) |
97 "Index: Tools/Scripts/webkitpy/common/checkout/diff_parser.py\n", | |
98 "===================================================================
\n", | |
99 "--- Tools/Scripts/webkitpy/common/checkout/diff_parser.py\n", | |
100 "+++ Tools/Scripts/webkitpy/common/checkout/diff_parser.py\n", | |
101 "@@ -59,6 +59,7 @@ def git_diff_to_svn_diff(line):\n", | |
102 ] | |
103 self.assertEqual(diff_parser.get_diff_converter(svn_diff_lines), diff_pa
rser.svn_diff_to_svn_diff) | |
104 self.assertEqual(diff_parser.get_diff_converter(comment_lines + svn_diff
_lines), diff_parser.svn_diff_to_svn_diff) | |
105 self.assertEqual(diff_parser.get_diff_converter(revision_lines + svn_dif
f_lines), diff_parser.svn_diff_to_svn_diff) | |
106 | |
107 git_diff_lines = [ | |
108 ("diff --git a/Tools/Scripts/webkitpy/common/checkout/diff_parser.py
" | |
109 "b/Tools/Scripts/webkitpy/common/checkout/diff_parser.py\n"), | |
110 "index 3c5b45b..0197ead 100644\n", | |
111 "--- a/Tools/Scripts/webkitpy/common/checkout/diff_parser.py\n", | |
112 "+++ b/Tools/Scripts/webkitpy/common/checkout/diff_parser.py\n", | |
113 "@@ -59,6 +59,7 @@ def git_diff_to_svn_diff(line):\n", | |
114 ] | |
115 self.assertEqual(diff_parser.get_diff_converter(git_diff_lines), diff_pa
rser.git_diff_to_svn_diff) | |
116 self.assertEqual(diff_parser.get_diff_converter(comment_lines + git_diff
_lines), diff_parser.git_diff_to_svn_diff) | |
117 self.assertEqual(diff_parser.get_diff_converter(revision_lines + git_dif
f_lines), diff_parser.git_diff_to_svn_diff) | |
118 | |
119 def test_git_mnemonicprefix(self): | |
120 p = re.compile(r' ([a|b])/') | |
121 | |
122 prefixes = [ | |
123 {'a': 'i', 'b': 'w'}, # git-diff (compares the (i)ndex and the (w)o
rk tree) | |
124 {'a': 'c', 'b': 'w'}, # git-diff HEAD (compares a (c)ommit and the
(w)ork tree) | |
125 {'a': 'c', 'b': 'i'}, # git diff --cached (compares a (c)ommit and
the (i)ndex) | |
126 {'a': 'o', 'b': 'w'}, # git-diff HEAD:file1 file2 (compares an (o)b
ject and a (w)ork tree entity) | |
127 {'a': '1', 'b': '2'}, # git diff --no-index a b (compares two non-g
it things (1) and (2)) | |
128 ] | |
129 | |
130 for prefix in prefixes: | |
131 patch = p.sub(lambda x: " %s/" % prefix[x.group(1)], DIFF_TEST_DATA) | |
132 self.test_diff_parser(diff_parser.DiffParser(patch.splitlines())) | |
133 | |
134 def test_git_diff_to_svn_diff(self): | |
135 output = """\ | |
136 Index: Tools/Scripts/webkitpy/common/checkout/diff_parser.py | |
137 =================================================================== | |
138 --- Tools/Scripts/webkitpy/common/checkout/diff_parser.py | |
139 +++ Tools/Scripts/webkitpy/common/checkout/diff_parser.py | |
140 @@ -59,6 +59,7 @@ def git_diff_to_svn_diff(line): | |
141 A | |
142 B | |
143 C | |
144 +D | |
145 E | |
146 F | |
147 """ | |
148 | |
149 inputfmt = StringIO.StringIO("""\ | |
150 diff --git a/Tools/Scripts/webkitpy/common/checkout/diff_parser.py b/Tools/Scrip
ts/webkitpy/common/checkout/diff_parser.py | |
151 index 2ed552c4555db72df16b212547f2c125ae301a04..72870482000c0dba64ce4300ed782c03
ee79b74f 100644 | |
152 --- a/Tools/Scripts/webkitpy/common/checkout/diff_parser.py | |
153 +++ b/Tools/Scripts/webkitpy/common/checkout/diff_parser.py | |
154 @@ -59,6 +59,7 @@ def git_diff_to_svn_diff(line): | |
155 A | |
156 B | |
157 C | |
158 +D | |
159 E | |
160 F | |
161 """) | |
162 shortfmt = StringIO.StringIO("""\ | |
163 diff --git a/Tools/Scripts/webkitpy/common/checkout/diff_parser.py b/Tools/Scrip
ts/webkitpy/common/checkout/diff_parser.py | |
164 index b48b162..f300960 100644 | |
165 --- a/Tools/Scripts/webkitpy/common/checkout/diff_parser.py | |
166 +++ b/Tools/Scripts/webkitpy/common/checkout/diff_parser.py | |
167 @@ -59,6 +59,7 @@ def git_diff_to_svn_diff(line): | |
168 A | |
169 B | |
170 C | |
171 +D | |
172 E | |
173 F | |
174 """) | |
175 | |
176 self.assertMultiLineEqual(output, ''.join(diff_parser.git_diff_to_svn_di
ff(x) for x in shortfmt.readlines())) | |
177 self.assertMultiLineEqual(output, ''.join(diff_parser.git_diff_to_svn_di
ff(x) for x in inputfmt.readlines())) | |
OLD | NEW |