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