diff options
Diffstat (limited to 'bin/check-missing-unittests.py')
-rwxr-xr-x | bin/check-missing-unittests.py | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/bin/check-missing-unittests.py b/bin/check-missing-unittests.py new file mode 100755 index 0000000000..0ee36ef76a --- /dev/null +++ b/bin/check-missing-unittests.py @@ -0,0 +1,240 @@ +#!/usr/bin/env python3 + +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Use this script to update +# https://wiki.documentfoundation.org/MissingUnitTests + +import os +import datetime +import subprocess +import sys +import re +import json +import requests + +def splitList(lst, n): + for i in range(0, len(lst), n): + yield lst[i:i + n] + +def whiteboardNotes(whiteboard): + if not whiteboard: + return '' + if ' ' in whiteboard: + whiteboardList = reversed(whiteboard.split(' ')) + for w in whiteboardList: + if w.startswith("unitTestNotes"): + return w.split(':')[1] + elif whiteboard.startswith("unitTestNotes"): + return whiteboard.split(':')[1] + + return '' + +def main(ignoredBugs): + results = { + 'export': { + 'docx': {}, + 'doc': {}, + 'pptx': {}, + 'xlsx': {}, + 'xhtml': {}, + 'html': {}, + }, + 'writer': { + 'undo': {}, + 'autoformat': {}, + 'autocorrect': {}, + 'others': {}, + }, + 'calc': { + 'import': {}, + 'format': {}, + 'others': {}, + }, + 'impress': { + 'drawingml': {}, + 'slidesorter': {}, + 'others': {}, + }, + + } + hasTestSet = set() + + repoPath = os.path.dirname(os.path.abspath(__file__)) + '/..' + branch = subprocess.check_output( + ['git', '-C', repoPath, 'rev-parse', '--abbrev-ref', 'HEAD'], + stderr=subprocess.DEVNULL) + last_hash = subprocess.check_output( + ['git', '-C', repoPath, 'rev-parse', 'HEAD'], + stderr=subprocess.DEVNULL) + output = subprocess.check_output( + ['git', '-C', repoPath, 'log', '--since="2012-01-01', '--name-only' ,'--pretty=format:"%s%n%ad"', '--date=format:"%Y/%m/%d"'], + stderr=subprocess.DEVNULL) + commits = output.decode('utf-8', 'ignore').split('\n\n') + + for commit in reversed(commits): + + commitInfo = commit.split('\n') + + summary = commitInfo[0].strip('"').lower() + + # Check for bugIds in the summary. Ignore those with a '-' after the digits. + # Those are used for file names ( e.g. tdf129410-1.ods ) + bugIds = re.findall("\\b(?:bug|fdo|tdf|lo)[#:]?(\\d+)(?!-)\\b", summary) + if bugIds is None or len(bugIds) == 0: + continue + + for bugId in bugIds: + + isIgnored = False + for i in ignoredBugs: + if i in summary: + isIgnored = True + if isIgnored: + continue + + if bugId in hasTestSet: + continue + + date = commitInfo[1].strip('"') + infoList = [date, summary] + + changedFiles = "".join(commitInfo[2:]) + if 'qa' in changedFiles: + hasTestSet.add(bugId) + continue + + elif 'sw/source/filter/ww8/docx' in changedFiles or \ + 'writerfilter/source/dmapper' in changedFiles or \ + 'starmath/source/ooxmlimport' in changedFiles: + results['export']['docx'][bugId] = infoList + + elif 'sw/source/filter/ww8/ww8' in changedFiles: + results['export']['doc'][bugId] = infoList + + elif 'sc/source/filter/excel/xe' in changedFiles: + results['export']['xlsx'][bugId] = infoList + + elif 'oox/source/export/' in changedFiles: + results['export']['pptx'][bugId] = infoList + + elif 'filter/source/xslt/odf2xhtml/export' in changedFiles: + results['export']['xhtml'][bugId] = infoList + + elif 'sw/source/filter/html/' in changedFiles: + results['export']['html'][bugId] = infoList + + elif 'sw/source/core/undo/' in changedFiles: + results['writer']['undo'][bugId] = infoList + + elif 'sw/source/core/edit/autofmt' in changedFiles: + results['writer']['autoformat'][bugId] = infoList + + elif 'sw/source/core/edit/acorrect' in changedFiles: + results['writer']['autocorrect'][bugId] = infoList + + elif 'drawingml' in changedFiles: + results['impress']['drawingml'][bugId] = infoList + + elif 'sd/source/ui/slidesorter/' in changedFiles: + results['impress']['slidesorter'][bugId] = infoList + + elif 'sc/source/core/tool/interpr' in changedFiles: + results['calc']['import'][bugId] = infoList + + elif 'svl/source/numbers/' in changedFiles: + results['calc']['format'][bugId] = infoList + + # Keep the following if statements at the end + + elif 'sc/source/core/' in changedFiles: + results['calc']['others'][bugId] = infoList + + elif 'sw/source/core/' in changedFiles: + results['writer']['others'][bugId] = infoList + + elif 'sd/source/core/' in changedFiles: + results['impress']['others'][bugId] = infoList + + listOfBugIdsWithoutTest = [] + for k,v in results.items(): + for k1, v1 in v.items(): + for bugId, info in v1.items(): + if bugId not in hasTestSet: + listOfBugIdsWithoutTest.append(bugId) + + + bugzillaJson = [] + resultList = [] + fixList = [] + #Split the list into different chunks for the requests, otherwise it fails + for chunk in splitList(listOfBugIdsWithoutTest, 50): + urlGet = 'https://bugs.documentfoundation.org/rest/bug?id=' + ','.join(chunk) + rGet = requests.get(urlGet) + rawData = json.loads(rGet.text) + rGet.close() + bugzillaJson.extend(rawData['bugs']) + + for k,v in results.items(): + for k1, v1 in v.items(): + for bugId, info in v1.items(): + + resolution = '' + keywords = [] + priority = '' + notes = '' + for bug in bugzillaJson: + if str(bug['id']) == str(bugId): + resolution = bug['resolution'] + keywords = bug['keywords'] + priority = bug['priority'] + notes = whiteboardNotes(bug['whiteboard']) + break + + # Only care about FIXED bugs + # Ignore performance bugs and accessibility bugs + if resolution and resolution == 'FIXED' and 'perf' not in keywords \ + and 'accessibility' not in keywords: + fixList.append({ + "id": bugId, + "date": info[0], + "priority": priority.upper(), + "summary": info[1], + "maintopic":k, + "subtopic":k1, + "notes": notes + }) + + resultList.append([{ + "Generator": os.path.basename(sys.argv[0]), + "Date": str(datetime.datetime.now()), + "Commits": str(len(commits)), + "Branch": branch.decode().strip(), + "Hash": str(last_hash.decode().strip()), + }]) + resultList.append(fixList) + print(json.dumps(resultList)) + +def usage(): + message = """usage: {program} [bugs to ignore (each one is one argument)] + +Sample: {program} 10000 10001 10002""" + print(message.format(program = os.path.basename(sys.argv[0]))) + +if __name__ == '__main__': + + args = set() + if len(sys.argv) > 1: + arg1 = sys.argv[1] + if arg1 == '-h' or arg1 == "--help": + usage() + sys.exit(1) + for i in sys.argv: + if i.isdigit(): + args.add(i) + + main(sorted(args)) |