• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# -*- 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
265