1e5c31af7Sopenharmony_ci# -*- coding: utf-8 -*- 2e5c31af7Sopenharmony_ci 3e5c31af7Sopenharmony_ci#------------------------------------------------------------------------- 4e5c31af7Sopenharmony_ci# drawElements Quality Program utilities 5e5c31af7Sopenharmony_ci# -------------------------------------- 6e5c31af7Sopenharmony_ci# 7e5c31af7Sopenharmony_ci# Copyright 2015 The Android Open Source Project 8e5c31af7Sopenharmony_ci# 9e5c31af7Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 10e5c31af7Sopenharmony_ci# you may not use this file except in compliance with the License. 11e5c31af7Sopenharmony_ci# You may obtain a copy of the License at 12e5c31af7Sopenharmony_ci# 13e5c31af7Sopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 14e5c31af7Sopenharmony_ci# 15e5c31af7Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software 16e5c31af7Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 17e5c31af7Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18e5c31af7Sopenharmony_ci# See the License for the specific language governing permissions and 19e5c31af7Sopenharmony_ci# limitations under the License. 20e5c31af7Sopenharmony_ci# 21e5c31af7Sopenharmony_ci#------------------------------------------------------------------------- 22e5c31af7Sopenharmony_ci 23e5c31af7Sopenharmony_ciimport sys 24e5c31af7Sopenharmony_ciimport random 25e5c31af7Sopenharmony_ciimport string 26e5c31af7Sopenharmony_ciimport subprocess 27e5c31af7Sopenharmony_cifrom optparse import OptionParser 28e5c31af7Sopenharmony_ci 29e5c31af7Sopenharmony_cidef all (results, predicate): 30e5c31af7Sopenharmony_ci for result in results: 31e5c31af7Sopenharmony_ci if not predicate(result): 32e5c31af7Sopenharmony_ci return False 33e5c31af7Sopenharmony_ci return True 34e5c31af7Sopenharmony_ci 35e5c31af7Sopenharmony_cidef any (results, predicate): 36e5c31af7Sopenharmony_ci for result in results: 37e5c31af7Sopenharmony_ci if predicate(result): 38e5c31af7Sopenharmony_ci return True 39e5c31af7Sopenharmony_ci return False 40e5c31af7Sopenharmony_ci 41e5c31af7Sopenharmony_ciclass FilterRule: 42e5c31af7Sopenharmony_ci def __init__ (self, name, description, filters): 43e5c31af7Sopenharmony_ci self.name = name 44e5c31af7Sopenharmony_ci self.description = description 45e5c31af7Sopenharmony_ci self.filters = filters 46e5c31af7Sopenharmony_ci 47e5c31af7Sopenharmony_ciclass TestCaseResult: 48e5c31af7Sopenharmony_ci def __init__ (self, name, results): 49e5c31af7Sopenharmony_ci self.name = name 50e5c31af7Sopenharmony_ci self.results = results 51e5c31af7Sopenharmony_ci 52e5c31af7Sopenharmony_ciclass Group: 53e5c31af7Sopenharmony_ci def __init__ (self, name): 54e5c31af7Sopenharmony_ci self.name = name 55e5c31af7Sopenharmony_ci self.cases = [] 56e5c31af7Sopenharmony_ci 57e5c31af7Sopenharmony_cidef readCaseList (filename): 58e5c31af7Sopenharmony_ci f = open(filename, 'rb') 59e5c31af7Sopenharmony_ci cases = [] 60e5c31af7Sopenharmony_ci for line in f: 61e5c31af7Sopenharmony_ci if line[:6] == "TEST: ": 62e5c31af7Sopenharmony_ci case = line[6:].strip() 63e5c31af7Sopenharmony_ci if len(case) > 0: 64e5c31af7Sopenharmony_ci cases.append(case) 65e5c31af7Sopenharmony_ci return cases 66e5c31af7Sopenharmony_ci 67e5c31af7Sopenharmony_cidef toResultList (caselist): 68e5c31af7Sopenharmony_ci results = [] 69e5c31af7Sopenharmony_ci for case in caselist: 70e5c31af7Sopenharmony_ci results.append(TestCaseResult(case, [])) 71e5c31af7Sopenharmony_ci return results 72e5c31af7Sopenharmony_ci 73e5c31af7Sopenharmony_cidef addResultsToCaseList (caselist, results): 74e5c31af7Sopenharmony_ci resultMap = {} 75e5c31af7Sopenharmony_ci caseListRes = toResultList(caselist) 76e5c31af7Sopenharmony_ci 77e5c31af7Sopenharmony_ci for res in caseListRes: 78e5c31af7Sopenharmony_ci resultMap[res.name] = res 79e5c31af7Sopenharmony_ci 80e5c31af7Sopenharmony_ci for result in results: 81e5c31af7Sopenharmony_ci if result.name in resultMap: 82e5c31af7Sopenharmony_ci resultMap[result.name].results += result.results 83e5c31af7Sopenharmony_ci 84e5c31af7Sopenharmony_ci return caseListRes 85e5c31af7Sopenharmony_ci 86e5c31af7Sopenharmony_cidef readTestResults (filename): 87e5c31af7Sopenharmony_ci f = open(filename, 'rb') 88e5c31af7Sopenharmony_ci csvData = f.read() 89e5c31af7Sopenharmony_ci csvLines = csvData.splitlines() 90e5c31af7Sopenharmony_ci results = [] 91e5c31af7Sopenharmony_ci 92e5c31af7Sopenharmony_ci f.close() 93e5c31af7Sopenharmony_ci 94e5c31af7Sopenharmony_ci for line in csvLines[1:]: 95e5c31af7Sopenharmony_ci args = line.split(',') 96e5c31af7Sopenharmony_ci if len(args) == 1: 97e5c31af7Sopenharmony_ci continue # Ignore 98e5c31af7Sopenharmony_ci 99e5c31af7Sopenharmony_ci results.append(TestCaseResult(args[0], args[1:])) 100e5c31af7Sopenharmony_ci 101e5c31af7Sopenharmony_ci if len(results) == 0: 102e5c31af7Sopenharmony_ci raise Exception("Empty result list") 103e5c31af7Sopenharmony_ci 104e5c31af7Sopenharmony_ci # Quick check for results 105e5c31af7Sopenharmony_ci numResultItems = len(results[0].results) 106e5c31af7Sopenharmony_ci seenResults = set() 107e5c31af7Sopenharmony_ci for result in results: 108e5c31af7Sopenharmony_ci if result.name in seenResults: 109e5c31af7Sopenharmony_ci raise Exception("Duplicate result row for test case '%s'" % result.name) 110e5c31af7Sopenharmony_ci if len(result.results) != numResultItems: 111e5c31af7Sopenharmony_ci raise Exception("Found %d results for test case '%s', expected %d" % (len(result.results), result.name, numResultItems)) 112e5c31af7Sopenharmony_ci seenResults.add(result.name) 113e5c31af7Sopenharmony_ci 114e5c31af7Sopenharmony_ci return results 115e5c31af7Sopenharmony_ci 116e5c31af7Sopenharmony_cidef readGroupList (filename): 117e5c31af7Sopenharmony_ci f = open(filename, 'rb') 118e5c31af7Sopenharmony_ci groups = [] 119e5c31af7Sopenharmony_ci for line in f: 120e5c31af7Sopenharmony_ci group = line.strip() 121e5c31af7Sopenharmony_ci if group != "": 122e5c31af7Sopenharmony_ci groups.append(group) 123e5c31af7Sopenharmony_ci return groups 124e5c31af7Sopenharmony_ci 125e5c31af7Sopenharmony_cidef createGroups (results, groupNames): 126e5c31af7Sopenharmony_ci groups = [] 127e5c31af7Sopenharmony_ci matched = set() 128e5c31af7Sopenharmony_ci 129e5c31af7Sopenharmony_ci for groupName in groupNames: 130e5c31af7Sopenharmony_ci group = Group(groupName) 131e5c31af7Sopenharmony_ci groups.append(group) 132e5c31af7Sopenharmony_ci 133e5c31af7Sopenharmony_ci prefix = groupName + "." 134e5c31af7Sopenharmony_ci prefixLen = len(prefix) 135e5c31af7Sopenharmony_ci for case in results: 136e5c31af7Sopenharmony_ci if case.name[:prefixLen] == prefix: 137e5c31af7Sopenharmony_ci if case in matched: 138e5c31af7Sopenharmony_ci die("Case '%s' matched by multiple groups (when processing '%s')" % (case.name, group.name)) 139e5c31af7Sopenharmony_ci group.cases.append(case) 140e5c31af7Sopenharmony_ci matched.add(case) 141e5c31af7Sopenharmony_ci 142e5c31af7Sopenharmony_ci return groups 143e5c31af7Sopenharmony_ci 144e5c31af7Sopenharmony_cidef createLeafGroups (results): 145e5c31af7Sopenharmony_ci groups = [] 146e5c31af7Sopenharmony_ci groupMap = {} 147e5c31af7Sopenharmony_ci 148e5c31af7Sopenharmony_ci for case in results: 149e5c31af7Sopenharmony_ci parts = case.name.split('.') 150e5c31af7Sopenharmony_ci groupName = string.join(parts[:-1], ".") 151e5c31af7Sopenharmony_ci 152e5c31af7Sopenharmony_ci if not groupName in groupMap: 153e5c31af7Sopenharmony_ci group = Group(groupName) 154e5c31af7Sopenharmony_ci groups.append(group) 155e5c31af7Sopenharmony_ci groupMap[groupName] = group 156e5c31af7Sopenharmony_ci else: 157e5c31af7Sopenharmony_ci group = groupMap[groupName] 158e5c31af7Sopenharmony_ci 159e5c31af7Sopenharmony_ci group.cases.append(case) 160e5c31af7Sopenharmony_ci 161e5c31af7Sopenharmony_ci return groups 162e5c31af7Sopenharmony_ci 163e5c31af7Sopenharmony_cidef filterList (results, condition): 164e5c31af7Sopenharmony_ci filtered = [] 165e5c31af7Sopenharmony_ci for case in results: 166e5c31af7Sopenharmony_ci if condition(case.results): 167e5c31af7Sopenharmony_ci filtered.append(case) 168e5c31af7Sopenharmony_ci return filtered 169e5c31af7Sopenharmony_ci 170e5c31af7Sopenharmony_cidef getFilter (list, name): 171e5c31af7Sopenharmony_ci for filter in list: 172e5c31af7Sopenharmony_ci if filter.name == name: 173e5c31af7Sopenharmony_ci return filter 174e5c31af7Sopenharmony_ci return None 175e5c31af7Sopenharmony_ci 176e5c31af7Sopenharmony_cidef getNumCasesInGroups (groups): 177e5c31af7Sopenharmony_ci numCases = 0 178e5c31af7Sopenharmony_ci for group in groups: 179e5c31af7Sopenharmony_ci numCases += len(group.cases) 180e5c31af7Sopenharmony_ci return numCases 181e5c31af7Sopenharmony_ci 182e5c31af7Sopenharmony_cidef getCasesInSet (results, caseSet): 183e5c31af7Sopenharmony_ci filtered = [] 184e5c31af7Sopenharmony_ci for case in results: 185e5c31af7Sopenharmony_ci if case in caseSet: 186e5c31af7Sopenharmony_ci filtered.append(case) 187e5c31af7Sopenharmony_ci return filtered 188e5c31af7Sopenharmony_ci 189e5c31af7Sopenharmony_cidef selectCasesInGroups (results, groups): 190e5c31af7Sopenharmony_ci casesInGroups = set() 191e5c31af7Sopenharmony_ci for group in groups: 192e5c31af7Sopenharmony_ci for case in group.cases: 193e5c31af7Sopenharmony_ci casesInGroups.add(case) 194e5c31af7Sopenharmony_ci return getCasesInSet(results, casesInGroups) 195e5c31af7Sopenharmony_ci 196e5c31af7Sopenharmony_cidef selectRandomSubset (results, groups, limit, seed): 197e5c31af7Sopenharmony_ci selectedCases = set() 198e5c31af7Sopenharmony_ci numSelect = min(limit, getNumCasesInGroups(groups)) 199e5c31af7Sopenharmony_ci 200e5c31af7Sopenharmony_ci random.seed(seed) 201e5c31af7Sopenharmony_ci random.shuffle(groups) 202e5c31af7Sopenharmony_ci 203e5c31af7Sopenharmony_ci groupNdx = 0 204e5c31af7Sopenharmony_ci while len(selectedCases) < numSelect: 205e5c31af7Sopenharmony_ci group = groups[groupNdx] 206e5c31af7Sopenharmony_ci if len(group.cases) == 0: 207e5c31af7Sopenharmony_ci del groups[groupNdx] 208e5c31af7Sopenharmony_ci if groupNdx == len(groups): 209e5c31af7Sopenharmony_ci groupNdx -= 1 210e5c31af7Sopenharmony_ci continue # Try next 211e5c31af7Sopenharmony_ci 212e5c31af7Sopenharmony_ci selected = random.choice(group.cases) 213e5c31af7Sopenharmony_ci selectedCases.add(selected) 214e5c31af7Sopenharmony_ci group.cases.remove(selected) 215e5c31af7Sopenharmony_ci 216e5c31af7Sopenharmony_ci groupNdx = (groupNdx + 1) % len(groups) 217e5c31af7Sopenharmony_ci 218e5c31af7Sopenharmony_ci return getCasesInSet(results, selectedCases) 219e5c31af7Sopenharmony_ci 220e5c31af7Sopenharmony_cidef die (msg): 221e5c31af7Sopenharmony_ci print(msg) 222e5c31af7Sopenharmony_ci sys.exit(-1) 223e5c31af7Sopenharmony_ci 224e5c31af7Sopenharmony_ci# Named filter lists 225e5c31af7Sopenharmony_ciFILTER_RULES = [ 226e5c31af7Sopenharmony_ci FilterRule("all", "No filtering", []), 227e5c31af7Sopenharmony_ci FilterRule("all-pass", "All results must be 'Pass'", [lambda l: all(l, lambda r: r == 'Pass')]), 228e5c31af7Sopenharmony_ci FilterRule("any-pass", "Any of results is 'Pass'", [lambda l: any(l, lambda r: r == 'Pass')]), 229e5c31af7Sopenharmony_ci FilterRule("any-fail", "Any of results is not 'Pass' or 'NotSupported'", [lambda l: not all(l, lambda r: r == 'Pass' or r == 'NotSupported')]), 230e5c31af7Sopenharmony_ci FilterRule("prev-failing", "Any except last result is failure", [lambda l: l[-1] == 'Pass' and not all(l[:-1], lambda r: r == 'Pass')]), 231e5c31af7Sopenharmony_ci FilterRule("prev-passing", "Any except last result is 'Pass'", [lambda l: l[-1] != 'Pass' and any(l[:-1], lambda r: r == 'Pass')]) 232e5c31af7Sopenharmony_ci] 233e5c31af7Sopenharmony_ci 234e5c31af7Sopenharmony_ciif __name__ == "__main__": 235e5c31af7Sopenharmony_ci parser = OptionParser(usage = "usage: %prog [options] [caselist] [result csv file]") 236e5c31af7Sopenharmony_ci parser.add_option("-f", "--filter", dest="filter", default="all", help="filter rule name") 237e5c31af7Sopenharmony_ci parser.add_option("-l", "--list", action="store_true", dest="list", default=False, help="list available rules") 238e5c31af7Sopenharmony_ci parser.add_option("-n", "--num", dest="limit", default=0, help="limit number of cases") 239e5c31af7Sopenharmony_ci parser.add_option("-s", "--seed", dest="seed", default=0, help="use selected seed for random selection") 240e5c31af7Sopenharmony_ci parser.add_option("-g", "--groups", dest="groups_file", default=None, help="select cases based on group list file") 241e5c31af7Sopenharmony_ci 242e5c31af7Sopenharmony_ci (options, args) = parser.parse_args() 243e5c31af7Sopenharmony_ci 244e5c31af7Sopenharmony_ci if options.list: 245e5c31af7Sopenharmony_ci print("Available filter rules:") 246e5c31af7Sopenharmony_ci for filter in FILTER_RULES: 247e5c31af7Sopenharmony_ci print(" %s: %s" % (filter.name, filter.description)) 248e5c31af7Sopenharmony_ci sys.exit(0) 249e5c31af7Sopenharmony_ci 250e5c31af7Sopenharmony_ci if len(args) == 0: 251e5c31af7Sopenharmony_ci die("No input files specified") 252e5c31af7Sopenharmony_ci elif len(args) > 2: 253e5c31af7Sopenharmony_ci die("Too many arguments") 254e5c31af7Sopenharmony_ci 255e5c31af7Sopenharmony_ci # Fetch filter 256e5c31af7Sopenharmony_ci filter = getFilter(FILTER_RULES, options.filter) 257e5c31af7Sopenharmony_ci if filter == None: 258e5c31af7Sopenharmony_ci die("Unknown filter '%s'" % options.filter) 259e5c31af7Sopenharmony_ci 260e5c31af7Sopenharmony_ci # Read case list 261e5c31af7Sopenharmony_ci caselist = readCaseList(args[0]) 262e5c31af7Sopenharmony_ci if len(args) > 1: 263e5c31af7Sopenharmony_ci results = readTestResults(args[1]) 264e5c31af7Sopenharmony_ci results = addResultsToCaseList(caselist, results) 265e5c31af7Sopenharmony_ci else: 266e5c31af7Sopenharmony_ci results = toResultList(caselist) 267e5c31af7Sopenharmony_ci 268e5c31af7Sopenharmony_ci # Execute filters for results 269e5c31af7Sopenharmony_ci for rule in filter.filters: 270e5c31af7Sopenharmony_ci results = filterList(results, rule) 271e5c31af7Sopenharmony_ci 272e5c31af7Sopenharmony_ci if options.limit != 0: 273e5c31af7Sopenharmony_ci if options.groups_file != None: 274e5c31af7Sopenharmony_ci groups = createGroups(results, readGroupList(options.groups_file)) 275e5c31af7Sopenharmony_ci else: 276e5c31af7Sopenharmony_ci groups = createLeafGroups(results) 277e5c31af7Sopenharmony_ci results = selectRandomSubset(results, groups, int(options.limit), int(options.seed)) 278e5c31af7Sopenharmony_ci elif options.groups_file != None: 279e5c31af7Sopenharmony_ci groups = createGroups(results, readGroupList(options.groups_file)) 280e5c31af7Sopenharmony_ci results = selectCasesInGroups(results, groups) 281e5c31af7Sopenharmony_ci 282e5c31af7Sopenharmony_ci # Print test set 283e5c31af7Sopenharmony_ci for result in results: 284e5c31af7Sopenharmony_ci print(result.name) 285