1#!/usr/bin/env python
2# Copyright 2020 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5"""
6angle_presubmit_utils_unittest.py: Top-level unittest script for ANGLE presubmit checks.
7"""
8
9import imp
10import os
11import unittest
12from angle_presubmit_utils import *
13
14
15def SetCWDToAngleFolder():
16    angle_folder = "angle"
17    cwd = os.path.dirname(os.path.abspath(__file__))
18    cwd = cwd.split(angle_folder)[0] + angle_folder
19    os.chdir(cwd)
20
21
22SetCWDToAngleFolder()
23
24PRESUBMIT = imp.load_source('PRESUBMIT', 'PRESUBMIT.py')
25
26
27class CommitMessageFormattingCheckTest(unittest.TestCase):
28
29    def __init__(self, *args, **kwargs):
30        super(CommitMessageFormattingCheckTest, self).__init__(*args, **kwargs)
31        self.output_api = OutputAPI_mock()
32
33    def run_check_commit_message_formatting(self, commit_msg):
34        input_api = InputAPI_mock(commit_msg)
35        return PRESUBMIT._CheckCommitMessageFormatting(input_api, self.output_api)
36
37    def test_correct_commit_message(self):
38        commit_msg = """a
39
40b
41
42Bug: angleproject:4662
43Change-Id: I966c79d96175da9eee92ef6da20db50d488137b2
44"""
45        errors = self.run_check_commit_message_formatting(commit_msg)
46        self.assertEqual(len(errors), 0)
47
48    def test_missing_description_body_and_description_summary(self):
49        commit_msg = """Change-Id: I966c79d96175da9eee92ef6da20db50d488137b2"""
50        errors = self.run_check_commit_message_formatting(commit_msg)
51        self.assertEqual(len(errors), 1)
52        self.assertEqual(
53            errors[0],
54            self.output_api.PresubmitError(
55                "Commit 1:Please ensure that your" +
56                " description summary and description body are not blank."))
57
58    def test_missing_description_body(self):
59        commit_msg = """
60        a
61
62b: d
63c: e
64"""
65        errors = self.run_check_commit_message_formatting(commit_msg)
66        self.assertEqual(len(errors), 0)
67
68    def test_missing_tag_paragraph(self):
69        commit_msg = """a
70
71bd
72efgh"""
73        errors = self.run_check_commit_message_formatting(commit_msg)
74        self.assertEqual(len(errors), 1)
75        self.assertEqual(
76            errors[0],
77            self.output_api.PresubmitError(
78                "Commit 1:Please ensure that there are tags (e.g., Bug:, Test:) in your description."
79            ))
80
81    def test_missing_tag_paragraph_and_description_body(self):
82        commit_msg = "a"
83        errors = self.run_check_commit_message_formatting(commit_msg)
84        self.assertEqual(len(errors), 1)
85        self.assertEqual(
86            errors[0],
87            self.output_api.PresubmitError(
88                "Commit 1:Please ensure that there are tags (e.g., Bug:, Test:) in your description."
89            ))
90
91    def test_missing_blank_line_between_description_summary_and_description_body(self):
92        commit_msg = """a
93b
94
95Change-Id: I925cdb45779a9cdebe4e14f9e81e4211ade37c12"""
96        errors = self.run_check_commit_message_formatting(commit_msg)
97        self.assertEqual(len(errors), 1)
98        self.assertEqual(errors[0], self.output_api.PresubmitError(
99          "Commit 1:Please ensure the summary is only 1 line and there is 1 blank line" + \
100          " between the summary and description body."))
101
102    def test_missing_blank_line_between_description_body_and_tags_paragraph(self):
103        commit_msg = """a
104
105b
106Change-Id: I925cdb45779a9cdebe4e14f9e81e4211ade37c12"""
107        errors = self.run_check_commit_message_formatting(commit_msg)
108        self.assertEqual(len(errors), 0)
109
110    def test_multiple_blank_lines_before_and_after_commit_message(self):
111        commit_msg = """
112
113
114                a
115
116                  b
117
118Change-Id: I925cdb45779a9cdebe4e14f9e81e4211ade37c12
119"""
120        errors = self.run_check_commit_message_formatting(commit_msg)
121        self.assertEqual(len(errors), 0)
122
123    def test_newlines_within_description_body(self):
124        commit_msg = """a
125
126b
127
128d
129
130e
131
132for
133
134Change-Id: I443c36aaa8956c20da1abddf7aea613659e2cd5b"""
135        errors = self.run_check_commit_message_formatting(commit_msg)
136        self.assertEqual(len(errors), 0)
137
138    # Summary description in warning threshold(at 65 characters)
139    def test_summmary_description_in_warning_thresholds(self):
140        commit_msg = """aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
141
142b
143
144Change-Id: I925cdb45779a9cdebe4e14f9e81e4211ade37c12
145"""
146        errors = self.run_check_commit_message_formatting(commit_msg)
147        self.assertEqual(len(errors), 1)
148        self.assertEqual(
149            errors[0],
150            self.output_api.PresubmitPromptWarning(
151                "Commit 1:Your description summary should be on one line of 64 or less characters."
152            ))
153
154    # Summary description in error threshold(at 71 characters)
155    def test_summary_description_in_error_threshold(self):
156        commit_msg = """aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
157
158b
159
160Change-Id: I925cdb45779a9cdebe4e14f9e81e4211ade37c12"""
161        errors = self.run_check_commit_message_formatting(commit_msg)
162        self.assertEqual(len(errors), 1)
163        self.assertEqual(
164            errors[0],
165            self.output_api.PresubmitError(
166                "Commit 1:Please ensure that your description summary is on one line of 64 or less characters."
167            ))
168
169    def test_description_body_exceeds_line_count_limit(self):
170        commit_msg = """a
171
172bbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
173
174
175Change-Id: I443c36aaa8956c20da1abddf7aea613659e2cd5b"""
176        errors = self.run_check_commit_message_formatting(commit_msg)
177        self.assertEqual(len(errors), 2)
178        self.assertEqual(
179            errors[0],
180            self.output_api.PresubmitError(
181                "Commit 1:Please ensure that there exists only 1 blank line between tags and description body."
182            ))
183        self.assertEqual(
184            errors[1],
185            self.output_api.PresubmitError("""Commit 1:Line 3 is too long.
186"bbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
187Please wrap it to 72 characters. Lines without spaces or lines starting with 4 spaces are exempt."""
188                                          ))
189
190    def test_description_body_exceeds_line_count_limit_but_with_4_spaces_prefix(self):
191        commit_msg = """a
192
193cc
194
195dddd
196
197    bbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
198
199Change-Id: I443c36aaa8956c20da1abddf7aea613659e2cd5b"""
200        errors = self.run_check_commit_message_formatting(commit_msg)
201        self.assertEqual(len(errors), 0)
202
203    def test_description_body_exceeds_line_count_limit_but_without_space(self):
204        commit_msg = """a
205
206cc
207
208dddd
209
210bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
211
212a: d"""
213        errors = self.run_check_commit_message_formatting(commit_msg)
214        self.assertEqual(len(errors), 0)
215
216    def test_tabs_in_commit_message(self):
217        commit_msg = """																a
218
219bbbbbbbbbbbbbbbbbbbb
220
221Change-Id: I443c36aaa8956c20da1abddf7aea613659e2cd5b"""
222        errors = self.run_check_commit_message_formatting(commit_msg)
223        self.assertEqual(len(errors), 1)
224        self.assertEqual(
225            errors[0],
226            self.output_api.PresubmitError("Commit 1:Tabs are not allowed in commit message."))
227
228    def test_allowlist_revert(self):
229        commit_msg = """Revert "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssa
230
231bbbbbbbbbbbbbbbbbbbb
232
233Change-Id: I443c36aaa8956c20da1abddf7aea613659e2cd5b"""
234        errors = self.run_check_commit_message_formatting(commit_msg)
235        self.assertEqual(len(errors), 0)
236
237    def test_allowlist_roll(self):
238        commit_msg = """Roll sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssadd
239
240bbbbbbbbbbbbbbbbbbbb
241
242Change-Id: I443c36aaa8956c20da1abddf7aea613659e2cd5b"""
243        errors = self.run_check_commit_message_formatting(commit_msg)
244        self.assertEqual(len(errors), 0)
245
246    def test_allowlist_reland(self):
247        commit_msg = """Reland sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssadd
248
249bbbbbbbbbbbbbbbbbbbb
250
251Change-Id: I443c36aaa8956c20da1abddf7aea613659e2cd5b"""
252        errors = self.run_check_commit_message_formatting(commit_msg)
253        self.assertEqual(len(errors), 0)
254
255    def test_multiple_commits_with_errors_in_multiple_commits(self):
256        commit_msg = """a
257
258bbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
259
260Change-Id: I443c36aaa8956c20da1abddf7aea613659e2cd5b
261
262a
263
264cccccccccccccccccccccccccccccc cccccccccccccccccccccccccccccccccccccccccccc
265
266Change-Id: I443c36aaa8956c20da1abddf7aea613659e2cd5b"""
267        errors = self.run_check_commit_message_formatting(commit_msg)
268        self.assertEqual(len(errors), 2)
269        self.assertEqual(
270            errors[0],
271            self.output_api.PresubmitError("""Commit 2:Line 3 is too long.
272"bbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
273Please wrap it to 72 characters. Lines without spaces or lines starting with 4 spaces are exempt."""
274                                          ))
275        self.assertEqual(
276            errors[1],
277            self.output_api.PresubmitError("""Commit 1:Line 4 is too long.
278"cccccccccccccccccccccccccccccc cccccccccccccccccccccccccccccccccccccccccccc"
279Please wrap it to 72 characters. Lines without spaces or lines starting with 4 spaces are exempt."""
280                                          ))
281
282    def test_multiple_commits_with_error_in_one_commit(self):
283        commit_msg = """a
284
285bbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
286
287Change-Id: I443c36aaa8956c20da1abddf7aea613659e2cd5b
288
289Roll sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssadd
290
291bbbbbbbbbbbbbbbbbbbb
292
293Change-Id: I443c36aaa8956c20da1abddf7aea613659e2cd5b"""
294        errors = self.run_check_commit_message_formatting(commit_msg)
295        self.assertEqual(len(errors), 1)
296        self.assertEqual(
297            errors[0],
298            self.output_api.PresubmitError("""Commit 2:Line 3 is too long.
299"bbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
300Please wrap it to 72 characters. Lines without spaces or lines starting with 4 spaces are exempt."""
301                                          ))
302
303    def test_multiple_commits_with_no_error(self):
304        commit_msg = """Reland sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssadd
305
306bbbbbbbbbbbbbbbbbbbb
307
308Change-Id: I443c36aaa8956c20da1abddf7aea613659e2cd5b
309
310Roll sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssadd
311
312bbbbbbbbbbbbbbbbbbbb
313
314Change-Id: I443c36aaa8956c20da1abddf7aea613659e2cd5b"""
315        errors = self.run_check_commit_message_formatting(commit_msg)
316        self.assertEqual(len(errors), 0)
317
318
319if __name__ == '__main__':
320    unittest.main()
321