diff options
Diffstat (limited to 'meta/lib/patchtest/tests/test_mbox.py')
-rw-r--r-- | meta/lib/patchtest/tests/test_mbox.py | 114 |
1 files changed, 67 insertions, 47 deletions
diff --git a/meta/lib/patchtest/tests/test_mbox.py b/meta/lib/patchtest/tests/test_mbox.py index 0b623b7d17..dab733ea77 100644 --- a/meta/lib/patchtest/tests/test_mbox.py +++ b/meta/lib/patchtest/tests/test_mbox.py | |||
@@ -6,15 +6,15 @@ | |||
6 | 6 | ||
7 | import base | 7 | import base |
8 | import collections | 8 | import collections |
9 | import parse_shortlog | 9 | import patchtest_patterns |
10 | import parse_signed_off_by | ||
11 | import pyparsing | 10 | import pyparsing |
11 | import re | ||
12 | import subprocess | 12 | import subprocess |
13 | from data import PatchTestInput | 13 | from patchtest_parser import PatchtestParser |
14 | 14 | ||
15 | def headlog(): | 15 | def headlog(): |
16 | output = subprocess.check_output( | 16 | output = subprocess.check_output( |
17 | "cd %s; git log --pretty='%%h#%%aN#%%cD:#%%s' -1" % PatchTestInput.repodir, | 17 | "cd %s; git log --pretty='%%h#%%aN#%%cD:#%%s' -1" % PatchtestParser.repodir, |
18 | universal_newlines=True, | 18 | universal_newlines=True, |
19 | shell=True | 19 | shell=True |
20 | ) | 20 | ) |
@@ -22,20 +22,6 @@ def headlog(): | |||
22 | 22 | ||
23 | class TestMbox(base.Base): | 23 | class TestMbox(base.Base): |
24 | 24 | ||
25 | auh_email = 'auh@auh.yoctoproject.org' | ||
26 | |||
27 | invalids = [pyparsing.Regex("^Upgrade Helper.+"), | ||
28 | pyparsing.Regex(auh_email), | ||
29 | pyparsing.Regex("uh@not\.set"), | ||
30 | pyparsing.Regex("\S+@example\.com")] | ||
31 | |||
32 | rexp_detect = pyparsing.Regex('\[\s?YOCTO.*\]') | ||
33 | rexp_validation = pyparsing.Regex('\[(\s?YOCTO\s?#\s?(\d+)\s?,?)+\]') | ||
34 | revert_shortlog_regex = pyparsing.Regex('Revert\s+".*"') | ||
35 | signoff_prog = parse_signed_off_by.signed_off_by | ||
36 | revert_shortlog_regex = pyparsing.Regex('Revert\s+".*"') | ||
37 | maxlength = 90 | ||
38 | |||
39 | # base paths of main yocto project sub-projects | 25 | # base paths of main yocto project sub-projects |
40 | paths = { | 26 | paths = { |
41 | 'oe-core': ['meta-selftest', 'meta-skeleton', 'meta', 'scripts'], | 27 | 'oe-core': ['meta-selftest', 'meta-skeleton', 'meta', 'scripts'], |
@@ -57,16 +43,18 @@ class TestMbox(base.Base): | |||
57 | 43 | ||
58 | 44 | ||
59 | def test_signed_off_by_presence(self): | 45 | def test_signed_off_by_presence(self): |
60 | for commit in TestMbox.commits: | 46 | for commit in self.commits: |
61 | # skip those patches that revert older commits, these do not required the tag presence | 47 | # skip those patches that revert older commits, these do not required the tag presence |
62 | if self.revert_shortlog_regex.search_string(commit.shortlog): | 48 | if patchtest_patterns.mbox_revert_shortlog_regex.search_string(commit.shortlog): |
63 | continue | 49 | continue |
64 | if not self.signoff_prog.search_string(commit.payload): | 50 | if not patchtest_patterns.signed_off_by.search_string(commit.payload): |
65 | self.fail('Mbox is missing Signed-off-by. Add it manually or with "git commit --amend -s"', | 51 | self.fail( |
66 | commit=commit) | 52 | 'Mbox is missing Signed-off-by. Add it manually or with "git commit --amend -s"', |
53 | commit=commit, | ||
54 | ) | ||
67 | 55 | ||
68 | def test_shortlog_format(self): | 56 | def test_shortlog_format(self): |
69 | for commit in TestMbox.commits: | 57 | for commit in self.commits: |
70 | shortlog = commit.shortlog | 58 | shortlog = commit.shortlog |
71 | if not shortlog.strip(): | 59 | if not shortlog.strip(): |
72 | self.skip('Empty shortlog, no reason to execute shortlog format test') | 60 | self.skip('Empty shortlog, no reason to execute shortlog format test') |
@@ -75,40 +63,54 @@ class TestMbox(base.Base): | |||
75 | if shortlog.startswith('Revert "'): | 63 | if shortlog.startswith('Revert "'): |
76 | continue | 64 | continue |
77 | try: | 65 | try: |
78 | parse_shortlog.shortlog.parseString(shortlog) | 66 | patchtest_patterns.shortlog.parseString(shortlog) |
79 | except pyparsing.ParseException as pe: | 67 | except pyparsing.ParseException as pe: |
80 | self.fail('Commit shortlog (first line of commit message) should follow the format "<target>: <summary>"', | 68 | self.fail('Commit shortlog (first line of commit message) should follow the format "<target>: <summary>"', |
81 | commit=commit) | 69 | commit=commit) |
82 | 70 | ||
83 | def test_shortlog_length(self): | 71 | def test_shortlog_length(self): |
84 | for commit in TestMbox.commits: | 72 | for commit in self.commits: |
85 | # no reason to re-check on revert shortlogs | 73 | # no reason to re-check on revert shortlogs |
86 | shortlog = commit.shortlog | 74 | shortlog = re.sub('^(\[.*?\])+ ', '', commit.shortlog) |
87 | if shortlog.startswith('Revert "'): | 75 | if shortlog.startswith('Revert "'): |
88 | continue | 76 | continue |
89 | l = len(shortlog) | 77 | l = len(shortlog) |
90 | if l > self.maxlength: | 78 | if l > patchtest_patterns.mbox_shortlog_maxlength: |
91 | self.fail('Edit shortlog so that it is %d characters or less (currently %d characters)' % (self.maxlength, l), | 79 | self.fail( |
92 | commit=commit) | 80 | "Edit shortlog so that it is %d characters or less (currently %d characters)" |
81 | % (patchtest_patterns.mbox_shortlog_maxlength, l), | ||
82 | commit=commit, | ||
83 | ) | ||
93 | 84 | ||
94 | def test_series_merge_on_head(self): | 85 | def test_series_merge_on_head(self): |
95 | self.skip("Merge test is disabled for now") | 86 | self.skip("Merge test is disabled for now") |
96 | if PatchTestInput.repo.branch != "master": | 87 | if PatchtestParser.repo.patch.branch != "master": |
97 | self.skip("Skipping merge test since patch is not intended for master branch. Target detected is %s" % PatchTestInput.repo.branch) | 88 | self.skip( |
98 | if not PatchTestInput.repo.ismerged: | 89 | "Skipping merge test since patch is not intended" |
90 | " for master branch. Target detected is %s" | ||
91 | % PatchtestParser.repo.patch.branch | ||
92 | ) | ||
93 | if not PatchtestParser.repo.canbemerged: | ||
99 | commithash, author, date, shortlog = headlog() | 94 | commithash, author, date, shortlog = headlog() |
100 | self.fail('Series does not apply on top of target branch %s' % PatchTestInput.repo.branch, | 95 | self.fail( |
101 | data=[('Targeted branch', '%s (currently at %s)' % (PatchTestInput.repo.branch, commithash))]) | 96 | "Series does not apply on top of target branch %s" |
97 | % PatchtestParser.repo.patch.branch, | ||
98 | data=[ | ||
99 | ( | ||
100 | "Targeted branch", | ||
101 | "%s (currently at %s)" | ||
102 | % (PatchtestParser.repo.patch.branch, commithash), | ||
103 | ) | ||
104 | ], | ||
105 | ) | ||
102 | 106 | ||
103 | def test_target_mailing_list(self): | 107 | def test_target_mailing_list(self): |
104 | """In case of merge failure, check for other targeted projects""" | 108 | """Check for other targeted projects""" |
105 | if PatchTestInput.repo.ismerged: | ||
106 | self.skip('Series merged, no reason to check other mailing lists') | ||
107 | 109 | ||
108 | # a meta project may be indicted in the message subject, if this is the case, just fail | 110 | # a meta project may be indicted in the message subject, if this is the case, just fail |
109 | # TODO: there may be other project with no-meta prefix, we also need to detect these | 111 | # TODO: there may be other project with no-meta prefix, we also need to detect these |
110 | project_regex = pyparsing.Regex("\[(?P<project>meta-.+)\]") | 112 | project_regex = pyparsing.Regex("\[(?P<project>meta-.+)\]") |
111 | for commit in TestMbox.commits: | 113 | for commit in self.commits: |
112 | match = project_regex.search_string(commit.subject) | 114 | match = project_regex.search_string(commit.subject) |
113 | if match: | 115 | if match: |
114 | self.fail('Series sent to the wrong mailing list or some patches from the series correspond to different mailing lists', | 116 | self.fail('Series sent to the wrong mailing list or some patches from the series correspond to different mailing lists', |
@@ -136,24 +138,42 @@ class TestMbox(base.Base): | |||
136 | data=[('Diff line',self.unidiff_parse_error)]) | 138 | data=[('Diff line',self.unidiff_parse_error)]) |
137 | 139 | ||
138 | def test_commit_message_presence(self): | 140 | def test_commit_message_presence(self): |
139 | for commit in TestMbox.commits: | 141 | for commit in self.commits: |
140 | if not commit.commit_message.strip(): | 142 | if not commit.commit_message.strip(): |
141 | self.fail('Please include a commit message on your patch explaining the change', commit=commit) | 143 | self.fail('Please include a commit message on your patch explaining the change', commit=commit) |
142 | 144 | ||
145 | # This may incorrectly report a failure if something such as a | ||
146 | # Python decorator is included in the commit message, but this | ||
147 | # scenario is much less common than the username case it is written | ||
148 | # to protect against | ||
149 | def test_commit_message_user_tags(self): | ||
150 | for commit in self.commits: | ||
151 | if patchtest_patterns.mbox_github_username.search_string(commit.commit_message): | ||
152 | self.fail('Mbox includes one or more GitHub-style username tags. Ensure that any "@" symbols are stripped out of usernames', commit=commit) | ||
153 | |||
143 | def test_bugzilla_entry_format(self): | 154 | def test_bugzilla_entry_format(self): |
144 | for commit in TestMbox.commits: | 155 | for commit in self.commits: |
145 | if not self.rexp_detect.search_string(commit.commit_message): | 156 | if not patchtest_patterns.mbox_bugzilla.search_string(commit.commit_message): |
146 | self.skip("No bug ID found") | 157 | self.skip("No bug ID found") |
147 | elif not self.rexp_validation.search_string(commit.commit_message): | 158 | elif not patchtest_patterns.mbox_bugzilla_validation.search_string( |
148 | self.fail('Bugzilla issue ID is not correctly formatted - specify it with format: "[YOCTO #<bugzilla ID>]"', commit=commit) | 159 | commit.commit_message |
160 | ): | ||
161 | self.fail( | ||
162 | 'Bugzilla issue ID is not correctly formatted - specify it with format: "[YOCTO #<bugzilla ID>]"', | ||
163 | commit=commit, | ||
164 | ) | ||
149 | 165 | ||
150 | def test_author_valid(self): | 166 | def test_author_valid(self): |
151 | for commit in self.commits: | 167 | for commit in self.commits: |
152 | for invalid in self.invalids: | 168 | for invalid in patchtest_patterns.invalid_submitters: |
153 | if invalid.search_string(commit.author): | 169 | if invalid.search_string(commit.author): |
154 | self.fail('Invalid author %s. Resend the series with a valid patch author' % commit.author, commit=commit) | 170 | self.fail('Invalid author %s. Resend the series with a valid patch author' % commit.author, commit=commit) |
155 | 171 | ||
156 | def test_non_auh_upgrade(self): | 172 | def test_non_auh_upgrade(self): |
157 | for commit in self.commits: | 173 | for commit in self.commits: |
158 | if self.auh_email in commit.payload: | 174 | if patchtest_patterns.auh_email in commit.commit_message: |
159 | self.fail('Invalid author %s. Resend the series with a valid patch author' % self.auh_email, commit=commit) | 175 | self.fail( |
176 | "Invalid author %s. Resend the series with a valid patch author" | ||
177 | % patchtest_patterns.auh_email, | ||
178 | commit=commit, | ||
179 | ) | ||