1 # -*- coding: utf-8 -*-
7 from optparse import OptionParser
9 def all (results, predicate):
10 for result in results:
11 if not predicate(result):
15 def any (results, predicate):
16 for result in results:
22 def __init__ (self, name, description, filters):
24 self.description = description
25 self.filters = filters
28 def __init__ (self, name, results):
30 self.results = results
33 def __init__ (self, name):
37 def readCaseList (filename):
38 f = open(filename, 'rb')
41 if line[:6] == "TEST: ":
42 case = line[6:].strip()
47 def toResultList (caselist):
50 results.append(TestCaseResult(case, []))
53 def addResultsToCaseList (caselist, results):
55 caseListRes = toResultList(caselist)
57 for res in caseListRes:
58 resultMap[res.name] = res
60 for result in results:
61 if result.name in resultMap:
62 resultMap[result.name].results += result.results
66 def readTestResults (filename):
67 f = open(filename, 'rb')
69 csvLines = csvData.splitlines()
74 for line in csvLines[1:]:
75 args = line.split(',')
79 results.append(TestCaseResult(args[0], args[1:]))
82 raise Exception("Empty result list")
84 # Sanity check for results
85 numResultItems = len(results[0].results)
87 for result in results:
88 if result.name in seenResults:
89 raise Exception("Duplicate result row for test case '%s'" % result.name)
90 if len(result.results) != numResultItems:
91 raise Exception("Found %d results for test case '%s', expected %d" % (len(result.results), result.name, numResultItems))
92 seenResults.add(result.name)
96 def readGroupList (filename):
97 f = open(filename, 'rb')
105 def createGroups (results, groupNames):
109 for groupName in groupNames:
110 group = Group(groupName)
113 prefix = groupName + "."
114 prefixLen = len(prefix)
116 if case.name[:prefixLen] == prefix:
118 die("Case '%s' matched by multiple groups (when processing '%s')" % (case.name, group.name))
119 group.cases.append(case)
124 def createLeafGroups (results):
129 parts = case.name.split('.')
130 groupName = string.join(parts[:-1], ".")
132 if not groupName in groupMap:
133 group = Group(groupName)
135 groupMap[groupName] = group
137 group = groupMap[groupName]
139 group.cases.append(case)
143 def filterList (results, condition):
146 if condition(case.results):
147 filtered.append(case)
150 def getFilter (list, name):
152 if filter.name == name:
156 def getNumCasesInGroups (groups):
159 numCases += len(group.cases)
162 def getCasesInSet (results, caseSet):
166 filtered.append(case)
169 def selectCasesInGroups (results, groups):
170 casesInGroups = set()
172 for case in group.cases:
173 casesInGroups.add(case)
174 return getCasesInSet(results, casesInGroups)
176 def selectRandomSubset (results, groups, limit, seed):
177 selectedCases = set()
178 numSelect = min(limit, getNumCasesInGroups(groups))
181 random.shuffle(groups)
184 while len(selectedCases) < numSelect:
185 group = groups[groupNdx]
186 if len(group.cases) == 0:
188 if groupNdx == len(groups):
192 selected = random.choice(group.cases)
193 selectedCases.add(selected)
194 group.cases.remove(selected)
196 groupNdx = (groupNdx + 1) % len(groups)
198 return getCasesInSet(results, selectedCases)
206 FilterRule("all", "No filtering", []),
207 FilterRule("all-pass", "All results must be 'Pass'", [lambda l: all(l, lambda r: r == 'Pass')]),
208 FilterRule("any-pass", "Any of results is 'Pass'", [lambda l: any(l, lambda r: r == 'Pass')]),
209 FilterRule("any-fail", "Any of results is not 'Pass' or 'NotSupported'", [lambda l: not all(l, lambda r: r == 'Pass' or r == 'NotSupported')]),
210 FilterRule("prev-failing", "Any except last result is failure", [lambda l: l[-1] == 'Pass' and not all(l[:-1], lambda r: r == 'Pass')]),
211 FilterRule("prev-passing", "Any except last result is 'Pass'", [lambda l: l[-1] != 'Pass' and any(l[:-1], lambda r: r == 'Pass')])
214 if __name__ == "__main__":
215 parser = OptionParser(usage = "usage: %prog [options] [caselist] [result csv file]")
216 parser.add_option("-f", "--filter", dest="filter", default="all", help="filter rule name")
217 parser.add_option("-l", "--list", action="store_true", dest="list", default=False, help="list available rules")
218 parser.add_option("-n", "--num", dest="limit", default=0, help="limit number of cases")
219 parser.add_option("-s", "--seed", dest="seed", default=0, help="use selected seed for random selection")
220 parser.add_option("-g", "--groups", dest="groups_file", default=None, help="select cases based on group list file")
222 (options, args) = parser.parse_args()
225 print "Available filter rules:"
226 for filter in FILTER_RULES:
227 print " %s: %s" % (filter.name, filter.description)
231 die("No input files specified")
233 die("Too many arguments")
236 filter = getFilter(FILTER_RULES, options.filter)
238 die("Unknown filter '%s'" % options.filter)
241 caselist = readCaseList(args[0])
243 results = readTestResults(args[1])
244 results = addResultsToCaseList(caselist, results)
246 results = toResultList(caselist)
248 # Execute filters for results
249 for rule in filter.filters:
250 results = filterList(results, rule)
252 if options.limit != 0:
253 if options.groups_file != None:
254 groups = createGroups(results, readGroupList(options.groups_file))
256 groups = createLeafGroups(results)
257 results = selectRandomSubset(results, groups, int(options.limit), int(options.seed))
258 elif options.groups_file != None:
259 groups = createGroups(results, readGroupList(options.groups_file))
260 results = selectCasesInGroups(results, groups)
263 for result in results: