bump product version to 7.2.5.1
[LibreOffice.git] / bin / check-missing-unittests.py
blob50f329f6139d2ce1084e98563299a379f2a8a859
1 #!/usr/bin/env python3
3 # This file is part of the LibreOffice project.
5 # This Source Code Form is subject to the terms of the Mozilla Public
6 # License, v. 2.0. If a copy of the MPL was not distributed with this
7 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 import os
10 import datetime
11 import subprocess
12 import sys
13 import re
14 import json
15 import requests
17 def isOpen(status):
18 return status == 'NEW' or status == 'ASSIGNED' or status == 'REOPENED'
20 def splitList(lst, n):
21 for i in range(0, len(lst), n):
22 yield lst[i:i + n]
24 def main(ignoredBugs):
25 results = {
26 'export': {
27 'docx': {},
28 'doc': {},
29 'pptx': {},
30 'xlsx': {},
31 'xhtml': {},
32 'html': {},
34 'writer': {
35 'undo': {},
36 'autoformat': {},
37 'autocorrect': {},
38 'others': {},
40 'calc': {
41 'import': {},
42 'format': {},
43 'others': {},
45 'impress': {
46 'drawingml': {},
47 'slidesorter': {},
48 'others': {},
52 hasTestSet = set()
54 repoPath = os.path.dirname(os.path.abspath(__file__)) + '/..'
55 branch = subprocess.check_output(
56 ['git', '-C', repoPath, 'rev-parse', '--abbrev-ref', 'HEAD'],
57 stderr=subprocess.DEVNULL)
58 last_hash = subprocess.check_output(
59 ['git', '-C', repoPath, 'rev-parse', 'HEAD'],
60 stderr=subprocess.DEVNULL)
61 output = subprocess.check_output(
62 ['git', '-C', repoPath, 'log', '--since="2012-01-01', '--name-only' ,'--pretty=format:"%s%n%ad"', '--date=format:"%Y/%m/%d"'],
63 stderr=subprocess.DEVNULL)
64 commits = output.decode('utf-8', 'ignore').split('\n\n')
66 for commit in reversed(commits):
68 commitInfo = commit.split('\n')
70 summary = commitInfo[0].strip('"').lower()
72 # Check for bugIds in the summary. Ignore those with a '-' after the digits.
73 # Those are used for file names ( e.g. tdf129410-1.ods )
74 bugIds = re.findall("\\b(?:bug|fdo|tdf|lo)[#:]?(\\d+)(?!-)\\b", summary)
75 if bugIds is None or len(bugIds) == 0:
76 continue
78 for bugId in bugIds:
80 isIgnored = False
81 for i in ignoredBugs:
82 if i in summary:
83 isIgnored = True
84 if isIgnored:
85 continue
87 if bugId in hasTestSet:
88 continue
90 date = commitInfo[1].strip('"')
91 infoList = [date, summary]
93 changedFiles = "".join(commitInfo[2:])
94 if 'qa' in changedFiles:
95 hasTestSet.add(bugId)
96 continue
98 elif 'sw/source/filter/ww8/docx' in changedFiles or \
99 'writerfilter/source/dmapper' in changedFiles or \
100 'starmath/source/ooxmlimport' in changedFiles:
101 results['export']['docx'][bugId] = infoList
103 elif 'sw/source/filter/ww8/ww8' in changedFiles:
104 results['export']['doc'][bugId] = infoList
106 elif 'sc/source/filter/excel/xe' in changedFiles:
107 results['export']['xlsx'][bugId] = infoList
109 elif 'oox/source/export/' in changedFiles:
110 results['export']['pptx'][bugId] = infoList
112 elif 'filter/source/xslt/odf2xhtml/export' in changedFiles:
113 results['export']['xhtml'][bugId] = infoList
115 elif 'sw/source/filter/html/' in changedFiles:
116 results['export']['html'][bugId] = infoList
118 elif 'sw/source/core/undo/' in changedFiles:
119 results['writer']['undo'][bugId] = infoList
121 elif 'sw/source/core/edit/autofmt' in changedFiles:
122 results['writer']['autoformat'][bugId] = infoList
124 elif 'sw/source/core/edit/acorrect' in changedFiles:
125 results['writer']['autocorrect'][bugId] = infoList
127 elif 'drawingml' in changedFiles:
128 results['impress']['drawingml'][bugId] = infoList
130 elif 'sd/source/ui/slidesorter/' in changedFiles:
131 results['impress']['slidesorter'][bugId] = infoList
133 elif 'sc/source/core/tool/interpr' in changedFiles:
134 results['calc']['import'][bugId] = infoList
136 elif 'svl/source/numbers/' in changedFiles:
137 results['calc']['format'][bugId] = infoList
139 # Keep the following if statements at the end
141 elif 'sc/source/core/data/' in changedFiles:
142 results['calc']['others'][bugId] = infoList
144 elif 'sw/source/core/' in changedFiles:
145 results['writer']['others'][bugId] = infoList
147 elif 'sd/source/core/' in changedFiles:
148 results['impress']['others'][bugId] = infoList
150 listOfBugIdsWithoutTest = []
151 for k,v in results.items():
152 for k1, v1 in v.items():
153 for bugId, info in v1.items():
154 if bugId not in hasTestSet:
155 listOfBugIdsWithoutTest.append(bugId)
157 bugzillaJson = []
158 #Split the list into different chunks for the requests, otherwise it fails
159 for chunk in splitList(listOfBugIdsWithoutTest, 50):
160 urlGet = 'https://bugs.documentfoundation.org/rest/bug?id=' + ','.join(chunk)
161 rGet = requests.get(urlGet)
162 rawData = json.loads(rGet.text)
163 rGet.close()
164 bugzillaJson.extend(rawData['bugs'])
166 print()
167 print('{{TopMenu}}')
168 print('{{Menu}}')
169 print('{{Menu.Development}}')
170 print()
171 print('Date: ' + str(datetime.datetime.now()))
172 print()
173 print('Commits: ' + str(len(commits)))
174 print()
175 print('Branch: ' + branch.decode().strip())
176 print()
177 print('Hash: ' + str(last_hash.decode().strip()))
179 for k,v in results.items():
180 print('\n== ' + k + ' ==')
181 for k1, v1 in v.items():
182 print('\n=== ' + k1 + ' ===')
183 for bugId, info in v1.items():
185 status = ''
186 keywords = []
187 priority = ''
188 for bug in bugzillaJson:
189 if str(bug['id']) == str(bugId):
190 status = bug['status']
191 keywords = bug['keywords']
192 priority = bug['priority']
193 break
195 #Ignore open bugs, performance bugs and accessibility bugs
196 if status and not isOpen(status) and 'perf' not in keywords \
197 and 'accessibility' not in keywords:
198 print(
199 "# {} - [{}] {} - [https://bugs.documentfoundation.org/show_bug.cgi?id={} tdf#{}]".format(
200 info[0], priority.upper(), info[1], bugId, bugId))
202 print('\n== ignored bugs ==')
203 print(' '.join(ignoredBugs))
204 print()
205 print('[[Category:QA]][[Category:Development]]')
207 def usage():
208 message = """usage: {program} [bugs to ignore (each one is one argument)]
210 Sample: {program} 10000 10001 10002"""
211 print(message.format(program = os.path.basename(sys.argv[0])))
213 if __name__ == '__main__':
215 args = set()
216 if len(sys.argv) > 1:
217 arg1 = sys.argv[1]
218 if arg1 == '-h' or arg1 == "--help":
219 usage()
220 sys.exit(1)
221 for i in sys.argv:
222 if i.isdigit():
223 args.add(i)
225 main(sorted(args))