1cdf0c1d5Smjnelson#! /usr/bin/python 2cdf0c1d5Smjnelson# 3cdf0c1d5Smjnelson# CDDL HEADER START 4cdf0c1d5Smjnelson# 5cdf0c1d5Smjnelson# The contents of this file are subject to the terms of the 6cdf0c1d5Smjnelson# Common Development and Distribution License (the "License"). 7cdf0c1d5Smjnelson# You may not use this file except in compliance with the License. 8cdf0c1d5Smjnelson# 9cdf0c1d5Smjnelson# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10cdf0c1d5Smjnelson# or http://www.opensolaris.org/os/licensing. 11cdf0c1d5Smjnelson# See the License for the specific language governing permissions 12cdf0c1d5Smjnelson# and limitations under the License. 13cdf0c1d5Smjnelson# 14cdf0c1d5Smjnelson# When distributing Covered Code, include this CDDL HEADER in each 15cdf0c1d5Smjnelson# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16cdf0c1d5Smjnelson# If applicable, add the following below this CDDL HEADER, with the 17cdf0c1d5Smjnelson# fields enclosed by brackets "[]" replaced with your own identifying 18cdf0c1d5Smjnelson# information: Portions Copyright [yyyy] [name of copyright owner] 19cdf0c1d5Smjnelson# 20cdf0c1d5Smjnelson# CDDL HEADER END 21cdf0c1d5Smjnelson# 22cdf0c1d5Smjnelson 23cdf0c1d5Smjnelson# 24cdf0c1d5Smjnelson# Copyright 2008 Sun Microsystems, Inc. All rights reserved. 25cdf0c1d5Smjnelson# Use is subject to license terms. 26cdf0c1d5Smjnelson# 27cdf0c1d5Smjnelson 28cdf0c1d5Smjnelson# 29cdf0c1d5Smjnelson# Check delta comments: 30cdf0c1d5Smjnelson# - Have the correct form. 31cdf0c1d5Smjnelson# - Have a synopsis matching that of the CR or ARC case. 32cdf0c1d5Smjnelson# - Appear only once. 33cdf0c1d5Smjnelson# 34cdf0c1d5Smjnelson 35cdf0c1d5Smjnelsonimport re, sys 36cdf0c1d5Smjnelsonfrom onbld.Checks.DbLookups import BugDB, ARC 37cdf0c1d5Smjnelson 38cdf0c1d5Smjnelsonarcre = re.compile(r'^([A-Z][A-Z]*ARC[/ \t][12]\d{3}/\d{3}) (.*)$') 39cdf0c1d5Smjnelsonbugre = re.compile(r'^(\d{7}) (.*)$') 40cdf0c1d5Smjnelsondef isARC(comment): 41cdf0c1d5Smjnelson return arcre.match(comment) 42cdf0c1d5Smjnelson 43cdf0c1d5Smjnelsondef isBug(comment): 44cdf0c1d5Smjnelson return bugre.match(comment) 45cdf0c1d5Smjnelson 46cdf0c1d5Smjnelson# 47cdf0c1d5Smjnelson# Translate any acceptable case number format into "<ARC> <YEAR>/<NUM>" 48cdf0c1d5Smjnelson# format. 49cdf0c1d5Smjnelson# 50cdf0c1d5Smjnelsondef normalize_arc(caseid): 51cdf0c1d5Smjnelson return re.sub(r'^([A-Z][A-Z]*ARC)[/ \t]', '\\1 ', caseid) 52cdf0c1d5Smjnelson 53cdf0c1d5Smjnelsondef comchk(comments, check_db=True, output=sys.stderr): 54cdf0c1d5Smjnelson bugnospcre = re.compile(r'^(\d{7})([^ ].*)') 55*aa46c263SJohn Beck ignorere = re.compile(r'^(Portions contributed by |Contributed by |back[ -]?out )') 56cdf0c1d5Smjnelson 57cdf0c1d5Smjnelson errors = { 'bugnospc': [], 58cdf0c1d5Smjnelson 'mutant': [], 59cdf0c1d5Smjnelson 'dup': [], 60cdf0c1d5Smjnelson 'nomatch': [], 61cdf0c1d5Smjnelson 'nonexistent': [] } 62cdf0c1d5Smjnelson bugs = {} 63cdf0c1d5Smjnelson arcs = {} 64cdf0c1d5Smjnelson ret = blanks = 0 65cdf0c1d5Smjnelson 66cdf0c1d5Smjnelson for com in comments: 67cdf0c1d5Smjnelson # Ignore valid comments we can't check 68cdf0c1d5Smjnelson if ignorere.search(com): 69cdf0c1d5Smjnelson continue 70cdf0c1d5Smjnelson 71cdf0c1d5Smjnelson if not com or com.isspace(): 72cdf0c1d5Smjnelson blanks += 1 73cdf0c1d5Smjnelson continue 74cdf0c1d5Smjnelson 75cdf0c1d5Smjnelson match = bugre.search(com) 76cdf0c1d5Smjnelson if match: 77cdf0c1d5Smjnelson if match.group(1) not in bugs: 78cdf0c1d5Smjnelson bugs[match.group(1)] = [] 79cdf0c1d5Smjnelson bugs[match.group(1)].append(match.group(2)) 80cdf0c1d5Smjnelson continue 81cdf0c1d5Smjnelson 82cdf0c1d5Smjnelson # 83cdf0c1d5Smjnelson # Bugs missing a space after the ID are still bugs 84cdf0c1d5Smjnelson # for the purposes of the duplicate ID and synopsis 85cdf0c1d5Smjnelson # checks. 86cdf0c1d5Smjnelson # 87cdf0c1d5Smjnelson match = bugnospcre.search(com) 88cdf0c1d5Smjnelson if match: 89cdf0c1d5Smjnelson if match.group(1) not in bugs: 90cdf0c1d5Smjnelson bugs[match.group(1)] = [] 91cdf0c1d5Smjnelson bugs[match.group(1)].append(match.group(2)) 92cdf0c1d5Smjnelson errors['bugnospc'].append(com) 93cdf0c1d5Smjnelson continue 94cdf0c1d5Smjnelson 95cdf0c1d5Smjnelson # ARC case 96cdf0c1d5Smjnelson match = arcre.search(com) 97cdf0c1d5Smjnelson if match: 98cdf0c1d5Smjnelson case = normalize_arc(match.group(1)) 99cdf0c1d5Smjnelson if case not in arcs: arcs[case] = [] 100cdf0c1d5Smjnelson arcs[case].append(match.group(2)) 101cdf0c1d5Smjnelson continue 102cdf0c1d5Smjnelson 103cdf0c1d5Smjnelson # Anything else is bogus 104cdf0c1d5Smjnelson errors['mutant'].append(com) 105cdf0c1d5Smjnelson 106cdf0c1d5Smjnelson if len(bugs) > 0 and check_db: 107cdf0c1d5Smjnelson bugdb = BugDB() 108cdf0c1d5Smjnelson results = bugdb.lookup(bugs.keys()) 109cdf0c1d5Smjnelson 110cdf0c1d5Smjnelson for crid, insts in bugs.iteritems(): 111cdf0c1d5Smjnelson if len(insts) > 1: 112cdf0c1d5Smjnelson errors['dup'].append(crid) 113cdf0c1d5Smjnelson 114cdf0c1d5Smjnelson if not check_db: 115cdf0c1d5Smjnelson continue 116cdf0c1d5Smjnelson 117cdf0c1d5Smjnelson if crid not in results: 118cdf0c1d5Smjnelson errors['nonexistent'].append(crid) 119cdf0c1d5Smjnelson continue 120cdf0c1d5Smjnelson 121cdf0c1d5Smjnelson for entered in insts: 122cdf0c1d5Smjnelson synopsis = results[crid]["synopsis"] 123cdf0c1d5Smjnelson if not re.search(re.escape(synopsis) + 124cdf0c1d5Smjnelson r'( \([^)]+\))?$', entered): 125cdf0c1d5Smjnelson errors['nomatch'].append([crid, synopsis, 126cdf0c1d5Smjnelson entered]) 127cdf0c1d5Smjnelson 128cdf0c1d5Smjnelson for case, insts in arcs.iteritems(): 129cdf0c1d5Smjnelson if len(insts) > 1: 130cdf0c1d5Smjnelson errors['dup'].append(case) 131cdf0c1d5Smjnelson 132cdf0c1d5Smjnelson if not check_db: 133cdf0c1d5Smjnelson continue 134cdf0c1d5Smjnelson 135cdf0c1d5Smjnelson com, id = case.split(' ') 136cdf0c1d5Smjnelson arc = ARC(com, id) 137cdf0c1d5Smjnelson 138cdf0c1d5Smjnelson if not arc.valid(): 139cdf0c1d5Smjnelson errors['nonexistent'].append(case) 140cdf0c1d5Smjnelson continue 141cdf0c1d5Smjnelson 142cdf0c1d5Smjnelson # 143cdf0c1d5Smjnelson # The opensolaris.org ARC interfaces only give us the 144cdf0c1d5Smjnelson # first 40 characters of the case name, so we must limit 145cdf0c1d5Smjnelson # our checking similarly. 146cdf0c1d5Smjnelson # 147cdf0c1d5Smjnelson # We first try a direct match between the actual case name 148cdf0c1d5Smjnelson # and the entered comment. If that fails we remove a possible 149cdf0c1d5Smjnelson # trailing (fix nit)-type comment, and re-try. 150cdf0c1d5Smjnelson # 151cdf0c1d5Smjnelson for entered in insts: 152cdf0c1d5Smjnelson if entered[0:40] == arc.name(): 153cdf0c1d5Smjnelson continue 154cdf0c1d5Smjnelson else: 155cdf0c1d5Smjnelson dbcom = re.sub(r' \([^)]+\)$', '', entered) 156cdf0c1d5Smjnelson if dbcom[0:40] != arc.name(): 157cdf0c1d5Smjnelson errors['nomatch'].append([case, 158cdf0c1d5Smjnelson arc.name(), 159cdf0c1d5Smjnelson entered]) 160cdf0c1d5Smjnelson 161cdf0c1d5Smjnelson if blanks: 162cdf0c1d5Smjnelson output.write("WARNING: Blank line(s) in comments\n") 163cdf0c1d5Smjnelson ret = 1 164cdf0c1d5Smjnelson 165cdf0c1d5Smjnelson if errors['dup']: 166cdf0c1d5Smjnelson ret = 1 167cdf0c1d5Smjnelson output.write("These IDs appear more than once in your " 168cdf0c1d5Smjnelson "comments:\n") 169cdf0c1d5Smjnelson for err in errors['dup']: 170cdf0c1d5Smjnelson output.write(" %s\n" % err) 171cdf0c1d5Smjnelson 172cdf0c1d5Smjnelson if errors['bugnospc']: 173cdf0c1d5Smjnelson ret = 1 174cdf0c1d5Smjnelson output.write("These bugs are missing a single space following " 175cdf0c1d5Smjnelson "the ID:\n") 176cdf0c1d5Smjnelson for com in errors['bugnospc']: 177cdf0c1d5Smjnelson output.write(" %s\n" % com) 178cdf0c1d5Smjnelson 179cdf0c1d5Smjnelson if errors['mutant']: 180cdf0c1d5Smjnelson ret = 1 181cdf0c1d5Smjnelson output.write("These comments are neither bug nor ARC case:\n") 182cdf0c1d5Smjnelson for com in errors['mutant']: 183cdf0c1d5Smjnelson output.write(" %s\n" % com) 184cdf0c1d5Smjnelson 185cdf0c1d5Smjnelson if errors['nonexistent']: 186cdf0c1d5Smjnelson ret = 1 187cdf0c1d5Smjnelson output.write("These bugs/ARC cases were not found in the " 188cdf0c1d5Smjnelson "databases:\n") 189cdf0c1d5Smjnelson for id in errors['nonexistent']: 190cdf0c1d5Smjnelson output.write(" %s\n" % id) 191cdf0c1d5Smjnelson 192cdf0c1d5Smjnelson if errors['nomatch']: 193cdf0c1d5Smjnelson ret = 1 194cdf0c1d5Smjnelson output.write("These bugs/ARC case synopsis/names don't match " 195cdf0c1d5Smjnelson "the database entries:\n") 196cdf0c1d5Smjnelson for err in errors['nomatch']: 197cdf0c1d5Smjnelson output.write("Synopsis/name of %s is wrong:\n" % err[0]) 198cdf0c1d5Smjnelson output.write(" should be: '%s'\n" % err[1]) 199cdf0c1d5Smjnelson output.write(" is: '%s'\n" % err[2]) 200cdf0c1d5Smjnelson 201cdf0c1d5Smjnelson return ret 202