xref: /illumos-gate/usr/src/tools/onbld/Checks/Comments_test.py (revision c093b3ec6d35e1fe023174ed7f6ca6b90690d526)
1#
2# This file and its contents are supplied under the terms of the
3# Common Development and Distribution License ("CDDL"), version 1.0.
4# You may only use this file in accordance with the terms of version
5# 1.0 of the CDDL.
6#
7# A full copy of the text of the CDDL should have accompanied this
8# source.  A copy of the CDDL is also available via the Internet at
9# http://www.illumos.org/license/CDDL.
10#
11
12#
13# Copyright 2024 Bill Sommerfeld <sommerfeld@hamachi.org>
14#
15
16#
17# Unit test for onbld comment checker
18#
19# To run this as a simple unit test:
20#     python3 Comments_test.py
21#
22# To use this to measure coverage:
23#     coverage3 erase
24#     coverage3 run --branch Comments_test.py
25#     coverage3 report -m --include Comments.py
26
27
28import io
29import os
30import sys
31import unittest
32from unittest.mock import patch
33
34sys.path.insert(2, os.path.join(os.path.dirname(__file__), "../.."))
35
36import onbld.Checks.Comments as Comments
37
38class fake_bug_db:
39
40    db = {
41        '10': { 'cr_number': '10',
42                'synopsis': 'this is a bug',
43                'status': 'New'
44               }
45    }
46
47    def lookup(self, buglist):
48        return { bug: self.db[bug] for bug in buglist if bug in self.db }
49
50class comchk_helper_test(unittest.TestCase):
51
52    def test_isBug(self):
53        self.assertTrue(Comments.isBug('10 this is a bug'))
54        self.assertTrue(Comments.isBug('12345 this is a bug'))
55        self.assertFalse(Comments.isBug('this is not a bug (no id)'))
56        self.assertFalse(Comments.isBug('10000000 this is too big to be a bug'))
57
58    def test_changeid_present(self):
59        self.assertTrue(Comments.changeid_present(
60            ['10 this is a bug',
61             '',
62             'Change-Id: Ideadbeef']))
63        self.assertTrue(Comments.changeid_present(
64            ['10 this is a bug',
65             '20 this is another bug',
66             '',
67             'Change-Id: Ideadbeef']))
68
69        self.assertFalse(Comments.changeid_present([]))
70        self.assertFalse(Comments.changeid_present(['10 this is a bug']))
71        self.assertFalse(Comments.changeid_present(
72            ['10 this is a bug',
73             '']))
74
75        # Not a valid Change-Id
76        self.assertFalse(Comments.changeid_present(
77            ['10 this is a bug',
78             '',
79             'this is not a changeid']))
80        self.assertFalse(Comments.changeid_present(
81            ['10 this is a bug',
82             '',
83             'Change-Id: this is not a changeid']))
84
85        # more than one Change-Id
86        self.assertFalse(Comments.changeid_present(
87            ['10 this is a bug',
88             '',
89             'Change-Id: Ideadbeef',
90             'Change-Id: Ifeedface']))
91
92class comchk_test(unittest.TestCase):
93
94    def setUp(self):
95        self.bugs = {}
96        self.bugdb = fake_bug_db()
97
98    def split_input(self, str):
99        return [ line.strip() for line in str.splitlines() ]
100
101    def expect_pass(self, input, *, check_db=False):
102
103        with patch('onbld.Checks.Comments.BugDB') as mockdb:
104            mockdb.configure_mock(return_value=self.bugdb)
105
106            out = io.StringIO()
107            self.assertEqual(0, Comments.comchk(self.split_input(input),
108                                                check_db, out, bugs=self.bugs))
109            self.assertEqual(out.getvalue(), '')
110
111    def expect_fail(self, input, output, *, check_db=False):
112        with patch('onbld.Checks.Comments.BugDB') as mockdb:
113            mockdb.configure_mock(return_value=self.bugdb)
114
115            out = io.StringIO()
116            self.assertEqual(1, Comments.comchk(self.split_input(input),
117                                                check_db, out, bugs=self.bugs))
118            self.assertEqual(out.getvalue(), output)
119
120    def test_comchk_newline(self):
121        out = io.StringIO()
122        with self.assertRaises(ValueError):
123            Comments.comchk(['\n'], False, out)
124
125    def test_comchk_basic(self):
126        self.expect_pass('10 this is a bug\n')
127
128    def test_comchk_reviewer(self):
129        self.expect_pass('10 this is a bug\nReviewed by: alice\n')
130
131    def test_comchk_approver(self):
132        self.expect_pass('10 this is a bug\nReviewed by: alice\n'
133                         'Approved by: bob\n')
134
135    def test_comchk_changeid(self):
136        self.expect_fail('10 this is a bug\n\nChange-Id: Ideadbeef',
137                         'NOTE: Change-Id present in comment\n')
138
139    def test_comchk_fail_spelling(self):
140
141        self.expect_fail('10 this is the the bug\n',
142                         'Spellcheck:\ncomment line 1 - '
143                         'contains "the the", a common misspelling of "the"\n')
144
145    def test_comchk_fail_not_bug(self):
146        self.expect_fail('XX this is a bug\n',
147                         'These comments are not valid bugs:\n'
148                         '  XX this is a bug\n')
149
150    def test_comchk_fail_blank_lines(self):
151        self.expect_fail('10 this is a bug\n\n',
152                         'WARNING: Blank line(s) in comments\n')
153
154    def test_comchk_fail_bug_no_space(self):
155        self.expect_fail('10this is a bug\n',
156                         'These bugs are missing a single space '
157                         'following the ID:\n'
158                         '  10this is a bug\n')
159
160    def test_comchk_fail_bug_dup(self):
161        self.expect_fail('10 this is a bug\n10 this is another bug\n',
162                         'These IDs appear more than once in your comments:\n'
163                         '  10\n')
164
165    def test_comchk_fail_bug_dup_no_space(self):
166        self.expect_fail('10 this is a bug\n10this is another bug\n',
167                         'These IDs appear more than once in your comments:\n'
168                         '  10\n'
169                         'These bugs are missing a single space '
170                         'following the ID:\n'
171                         '  10this is another bug\n')
172
173    def test_comchk_multi_commit_dup(self):
174        self.expect_pass('10 this is a bug\nReviewed-by: bob')
175        self.expect_fail('10 this is a bug\nReviewed-by: bob',
176                         'These IDs appear more than once in your comments:\n'
177                         '  10\n')
178        self.expect_pass('20 this is another bug\nReviewed-by: alice')
179
180    def test_comchk_multi_changeid(self):
181        self.expect_fail('10 this is a bug\n\nChange-Id: Ideadbeef',
182                         'NOTE: Change-Id present in comment\n')
183        self.expect_fail('20 this is a another bug\n\nChange-Id: Ifeedface',
184                         'NOTE: Change-Id present in comment\n')
185
186    def test_comchk_bugdb_pass(self):
187        self.expect_pass('10 this is a bug\n', check_db=True)
188
189    def test_comchk_bugdb_fail_synopsis(self):
190        self.expect_fail('10 this is the wrong synopsis\n',
191                         "These bug synopses don't match "
192                         "the database entries:\n"
193                         "Synopsis of 10 is wrong:\n"
194                         "  should be: 'this is a bug'\n"
195                         "         is: 'this is the wrong synopsis'\n",
196                         check_db=True)
197
198    def test_comchk_bugdb_wrong_bugid(self):
199        self.expect_fail('20 this is the wrong bugid\n',
200                         'These bugs were not found in the databases:\n'
201                         '  20\n',
202                         check_db=True)
203
204
205
206if __name__ == '__main__':
207    unittest.main()
208