blob: 5227a1229204592ac2d7493fdaa099ca3c1f468c [file] [log] [blame]
Jarkko Poyry3c827362014-09-02 11:48:52 +03001# -*- coding: utf-8 -*-
2
3import sys
4import random
5import string
6import subprocess
7from optparse import OptionParser
8
9def all (results, predicate):
10 for result in results:
11 if not predicate(result):
12 return False
13 return True
14
15def any (results, predicate):
16 for result in results:
17 if predicate(result):
18 return True
19 return False
20
21class FilterRule:
22 def __init__ (self, name, description, filters):
23 self.name = name
24 self.description = description
25 self.filters = filters
26
27class TestCaseResult:
28 def __init__ (self, name, results):
29 self.name = name
30 self.results = results
31
32class Group:
33 def __init__ (self, name):
34 self.name = name
35 self.cases = []
36
37def readCaseList (filename):
38 f = open(filename, 'rb')
39 cases = []
40 for line in f:
41 if line[:6] == "TEST: ":
42 case = line[6:].strip()
43 if len(case) > 0:
44 cases.append(case)
45 return cases
46
47def toResultList (caselist):
48 results = []
49 for case in caselist:
50 results.append(TestCaseResult(case, []))
51 return results
52
53def addResultsToCaseList (caselist, results):
54 resultMap = {}
55 caseListRes = toResultList(caselist)
56
57 for res in caseListRes:
58 resultMap[res.name] = res
59
60 for result in results:
61 if result.name in resultMap:
62 resultMap[result.name].results += result.results
63
64 return caseListRes
65
66def readTestResults (filename):
67 f = open(filename, 'rb')
68 csvData = f.read()
69 csvLines = csvData.splitlines()
70 results = []
71
72 f.close()
73
74 for line in csvLines[1:]:
75 args = line.split(',')
76 if len(args) == 1:
77 continue # Ignore
78
79 results.append(TestCaseResult(args[0], args[1:]))
80
81 if len(results) == 0:
82 raise Exception("Empty result list")
83
84 # Sanity check for results
85 numResultItems = len(results[0].results)
86 seenResults = set()
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)
93
94 return results
95
96def readGroupList (filename):
97 f = open(filename, 'rb')
98 groups = []
99 for line in f:
100 group = line.strip()
101 if group != "":
102 groups.append(group)
103 return groups
104
105def createGroups (results, groupNames):
106 groups = []
107 matched = set()
108
109 for groupName in groupNames:
110 group = Group(groupName)
111 groups.append(group)
112
113 prefix = groupName + "."
114 prefixLen = len(prefix)
115 for case in results:
116 if case.name[:prefixLen] == prefix:
117 if case in matched:
118 die("Case '%s' matched by multiple groups (when processing '%s')" % (case.name, group.name))
119 group.cases.append(case)
120 matched.add(case)
121
122 return groups
123
124def createLeafGroups (results):
125 groups = []
126 groupMap = {}
127
128 for case in results:
129 parts = case.name.split('.')
130 groupName = string.join(parts[:-1], ".")
131
132 if not groupName in groupMap:
133 group = Group(groupName)
134 groups.append(group)
135 groupMap[groupName] = group
136 else:
137 group = groupMap[groupName]
138
139 group.cases.append(case)
140
141 return groups
142
143def filterList (results, condition):
144 filtered = []
145 for case in results:
146 if condition(case.results):
147 filtered.append(case)
148 return filtered
149
150def getFilter (list, name):
151 for filter in list:
152 if filter.name == name:
153 return filter
154 return None
155
156def getNumCasesInGroups (groups):
157 numCases = 0
158 for group in groups:
159 numCases += len(group.cases)
160 return numCases
161
162def getCasesInSet (results, caseSet):
163 filtered = []
164 for case in results:
165 if case in caseSet:
166 filtered.append(case)
167 return filtered
168
169def selectCasesInGroups (results, groups):
170 casesInGroups = set()
171 for group in groups:
172 for case in group.cases:
173 casesInGroups.add(case)
174 return getCasesInSet(results, casesInGroups)
175
176def selectRandomSubset (results, groups, limit, seed):
177 selectedCases = set()
178 numSelect = min(limit, getNumCasesInGroups(groups))
179
180 random.seed(seed)
181 random.shuffle(groups)
182
183 groupNdx = 0
184 while len(selectedCases) < numSelect:
185 group = groups[groupNdx]
186 if len(group.cases) == 0:
187 del groups[groupNdx]
188 if groupNdx == len(groups):
189 groupNdx -= 1
190 continue # Try next
191
192 selected = random.choice(group.cases)
193 selectedCases.add(selected)
194 group.cases.remove(selected)
195
196 groupNdx = (groupNdx + 1) % len(groups)
197
198 return getCasesInSet(results, selectedCases)
199
200def die (msg):
201 print msg
202 sys.exit(-1)
203
204# Named filter lists
205FILTER_RULES = [
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')])
212]
213
214if __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")
221
222 (options, args) = parser.parse_args()
223
224 if options.list:
225 print "Available filter rules:"
226 for filter in FILTER_RULES:
227 print " %s: %s" % (filter.name, filter.description)
228 sys.exit(0)
229
230 if len(args) == 0:
231 die("No input files specified")
232 elif len(args) > 2:
233 die("Too many arguments")
234
235 # Fetch filter
236 filter = getFilter(FILTER_RULES, options.filter)
237 if filter == None:
238 die("Unknown filter '%s'" % options.filter)
239
240 # Read case list
241 caselist = readCaseList(args[0])
242 if len(args) > 1:
243 results = readTestResults(args[1])
244 results = addResultsToCaseList(caselist, results)
245 else:
246 results = toResultList(caselist)
247
248 # Execute filters for results
249 for rule in filter.filters:
250 results = filterList(results, rule)
251
252 if options.limit != 0:
253 if options.groups_file != None:
254 groups = createGroups(results, readGroupList(options.groups_file))
255 else:
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)
261
262 # Print test set
263 for result in results:
264 print result.name