1*35238bceSAndroid Build Coastguard Worker# -*- coding: utf-8 -*- 2*35238bceSAndroid Build Coastguard Worker#------------------------------------------------------------------------- 3*35238bceSAndroid Build Coastguard Worker# drawElements Quality Program utilities 4*35238bceSAndroid Build Coastguard Worker# -------------------------------------- 5*35238bceSAndroid Build Coastguard Worker# 6*35238bceSAndroid Build Coastguard Worker# Copyright 2016 The Android Open Source Project 7*35238bceSAndroid Build Coastguard Worker# 8*35238bceSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 9*35238bceSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 10*35238bceSAndroid Build Coastguard Worker# You may obtain a copy of the License at 11*35238bceSAndroid Build Coastguard Worker# 12*35238bceSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 13*35238bceSAndroid Build Coastguard Worker# 14*35238bceSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 15*35238bceSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 16*35238bceSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17*35238bceSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 18*35238bceSAndroid Build Coastguard Worker# limitations under the License. 19*35238bceSAndroid Build Coastguard Worker# 20*35238bceSAndroid Build Coastguard Worker#------------------------------------------------------------------------- 21*35238bceSAndroid Build Coastguard Worker 22*35238bceSAndroid Build Coastguard Workerfrom ctsbuild.common import * 23*35238bceSAndroid Build Coastguard Workerfrom ctsbuild.build import build 24*35238bceSAndroid Build Coastguard Workerfrom build_caselists import Module, getModuleByName, getBuildConfig, genCaseList, getCaseListPath, DEFAULT_BUILD_DIR, DEFAULT_TARGET 25*35238bceSAndroid Build Coastguard Workerfrom fnmatch import fnmatch 26*35238bceSAndroid Build Coastguard Workerfrom copy import copy 27*35238bceSAndroid Build Coastguard Workerfrom collections import defaultdict 28*35238bceSAndroid Build Coastguard Workerimport logging 29*35238bceSAndroid Build Coastguard Workerimport argparse 30*35238bceSAndroid Build Coastguard Workerimport re 31*35238bceSAndroid Build Coastguard Workerimport xml.etree.cElementTree as ElementTree 32*35238bceSAndroid Build Coastguard Workerimport xml.dom.minidom as minidom 33*35238bceSAndroid Build Coastguard Worker 34*35238bceSAndroid Build Coastguard WorkerGENERATED_FILE_WARNING = """ 35*35238bceSAndroid Build Coastguard Worker This file has been automatically generated. Edit with caution. 36*35238bceSAndroid Build Coastguard Worker """ 37*35238bceSAndroid Build Coastguard Worker 38*35238bceSAndroid Build Coastguard Workerclass Project: 39*35238bceSAndroid Build Coastguard Worker def __init__ (self, path, copyright = None): 40*35238bceSAndroid Build Coastguard Worker self.path = path 41*35238bceSAndroid Build Coastguard Worker self.copyright = copyright 42*35238bceSAndroid Build Coastguard Worker 43*35238bceSAndroid Build Coastguard Workerclass Configuration: 44*35238bceSAndroid Build Coastguard Worker def __init__ (self, name, filters, glconfig = None, rotation = None, surfacetype = None, required = False, runtime = None, runByDefault = True, listOfGroupsToSplit = []): 45*35238bceSAndroid Build Coastguard Worker self.name = name 46*35238bceSAndroid Build Coastguard Worker self.glconfig = glconfig 47*35238bceSAndroid Build Coastguard Worker self.rotation = rotation 48*35238bceSAndroid Build Coastguard Worker self.surfacetype = surfacetype 49*35238bceSAndroid Build Coastguard Worker self.required = required 50*35238bceSAndroid Build Coastguard Worker self.filters = filters 51*35238bceSAndroid Build Coastguard Worker self.expectedRuntime = runtime 52*35238bceSAndroid Build Coastguard Worker self.runByDefault = runByDefault 53*35238bceSAndroid Build Coastguard Worker self.listOfGroupsToSplit = listOfGroupsToSplit 54*35238bceSAndroid Build Coastguard Worker 55*35238bceSAndroid Build Coastguard Workerclass Package: 56*35238bceSAndroid Build Coastguard Worker def __init__ (self, module, configurations): 57*35238bceSAndroid Build Coastguard Worker self.module = module 58*35238bceSAndroid Build Coastguard Worker self.configurations = configurations 59*35238bceSAndroid Build Coastguard Worker 60*35238bceSAndroid Build Coastguard Workerclass Mustpass: 61*35238bceSAndroid Build Coastguard Worker def __init__ (self, project, version, packages): 62*35238bceSAndroid Build Coastguard Worker self.project = project 63*35238bceSAndroid Build Coastguard Worker self.version = version 64*35238bceSAndroid Build Coastguard Worker self.packages = packages 65*35238bceSAndroid Build Coastguard Worker 66*35238bceSAndroid Build Coastguard Workerclass Filter: 67*35238bceSAndroid Build Coastguard Worker TYPE_INCLUDE = 0 68*35238bceSAndroid Build Coastguard Worker TYPE_EXCLUDE = 1 69*35238bceSAndroid Build Coastguard Worker 70*35238bceSAndroid Build Coastguard Worker def __init__ (self, type, filenames): 71*35238bceSAndroid Build Coastguard Worker self.type = type 72*35238bceSAndroid Build Coastguard Worker self.filenames = filenames 73*35238bceSAndroid Build Coastguard Worker self.key = ",".join(filenames) 74*35238bceSAndroid Build Coastguard Worker 75*35238bceSAndroid Build Coastguard Workerclass TestRoot: 76*35238bceSAndroid Build Coastguard Worker def __init__ (self): 77*35238bceSAndroid Build Coastguard Worker self.children = [] 78*35238bceSAndroid Build Coastguard Worker 79*35238bceSAndroid Build Coastguard Workerclass TestGroup: 80*35238bceSAndroid Build Coastguard Worker def __init__ (self, name): 81*35238bceSAndroid Build Coastguard Worker self.name = name 82*35238bceSAndroid Build Coastguard Worker self.children = [] 83*35238bceSAndroid Build Coastguard Worker 84*35238bceSAndroid Build Coastguard Workerclass TestCase: 85*35238bceSAndroid Build Coastguard Worker def __init__ (self, name): 86*35238bceSAndroid Build Coastguard Worker self.name = name 87*35238bceSAndroid Build Coastguard Worker self.configurations = [] 88*35238bceSAndroid Build Coastguard Worker 89*35238bceSAndroid Build Coastguard Workerdef getSrcDir (mustpass): 90*35238bceSAndroid Build Coastguard Worker return os.path.join(mustpass.project.path, mustpass.version, "src") 91*35238bceSAndroid Build Coastguard Worker 92*35238bceSAndroid Build Coastguard Workerdef getModuleShorthand (module): 93*35238bceSAndroid Build Coastguard Worker assert module.name[:5] == "dEQP-" 94*35238bceSAndroid Build Coastguard Worker return module.name[5:].lower() 95*35238bceSAndroid Build Coastguard Worker 96*35238bceSAndroid Build Coastguard Workerdef getCaseListFileName (package, configuration): 97*35238bceSAndroid Build Coastguard Worker return "%s-%s.txt" % (getModuleShorthand(package.module), configuration.name) 98*35238bceSAndroid Build Coastguard Worker 99*35238bceSAndroid Build Coastguard Workerdef getDstCaseListPath (mustpass): 100*35238bceSAndroid Build Coastguard Worker return os.path.join(mustpass.project.path, mustpass.version) 101*35238bceSAndroid Build Coastguard Worker 102*35238bceSAndroid Build Coastguard Workerdef getCommandLine (config): 103*35238bceSAndroid Build Coastguard Worker cmdLine = "" 104*35238bceSAndroid Build Coastguard Worker 105*35238bceSAndroid Build Coastguard Worker if config.glconfig != None: 106*35238bceSAndroid Build Coastguard Worker cmdLine += "--deqp-gl-config-name=%s " % config.glconfig 107*35238bceSAndroid Build Coastguard Worker 108*35238bceSAndroid Build Coastguard Worker if config.rotation != None: 109*35238bceSAndroid Build Coastguard Worker cmdLine += "--deqp-screen-rotation=%s " % config.rotation 110*35238bceSAndroid Build Coastguard Worker 111*35238bceSAndroid Build Coastguard Worker if config.surfacetype != None: 112*35238bceSAndroid Build Coastguard Worker cmdLine += "--deqp-surface-type=%s " % config.surfacetype 113*35238bceSAndroid Build Coastguard Worker 114*35238bceSAndroid Build Coastguard Worker cmdLine += "--deqp-watchdog=enable" 115*35238bceSAndroid Build Coastguard Worker 116*35238bceSAndroid Build Coastguard Worker return cmdLine 117*35238bceSAndroid Build Coastguard Worker 118*35238bceSAndroid Build Coastguard Workerclass CaseList: 119*35238bceSAndroid Build Coastguard Worker def __init__(self, filePath, sortedLines): 120*35238bceSAndroid Build Coastguard Worker self.filePath = filePath 121*35238bceSAndroid Build Coastguard Worker self.sortedLines = sortedLines 122*35238bceSAndroid Build Coastguard Worker 123*35238bceSAndroid Build Coastguard Workerdef readAndSortCaseList (buildCfg, generator, module): 124*35238bceSAndroid Build Coastguard Worker build(buildCfg, generator, [module.binName]) 125*35238bceSAndroid Build Coastguard Worker genCaseList(buildCfg, generator, module, "txt") 126*35238bceSAndroid Build Coastguard Worker filePath = getCaseListPath(buildCfg, module, "txt") 127*35238bceSAndroid Build Coastguard Worker with open(filePath, 'r') as first_file: 128*35238bceSAndroid Build Coastguard Worker lines = first_file.readlines() 129*35238bceSAndroid Build Coastguard Worker lines.sort() 130*35238bceSAndroid Build Coastguard Worker caseList = CaseList(filePath, lines) 131*35238bceSAndroid Build Coastguard Worker return caseList 132*35238bceSAndroid Build Coastguard Worker 133*35238bceSAndroid Build Coastguard Workerdef readPatternList (filename, patternList): 134*35238bceSAndroid Build Coastguard Worker with open(filename, 'rt') as f: 135*35238bceSAndroid Build Coastguard Worker for line in f: 136*35238bceSAndroid Build Coastguard Worker line = line.strip() 137*35238bceSAndroid Build Coastguard Worker if len(line) > 0 and line[0] != '#': 138*35238bceSAndroid Build Coastguard Worker patternList.append(line) 139*35238bceSAndroid Build Coastguard Worker 140*35238bceSAndroid Build Coastguard Workerdef include (*filenames): 141*35238bceSAndroid Build Coastguard Worker return Filter(Filter.TYPE_INCLUDE, filenames) 142*35238bceSAndroid Build Coastguard Worker 143*35238bceSAndroid Build Coastguard Workerdef exclude (*filenames): 144*35238bceSAndroid Build Coastguard Worker return Filter(Filter.TYPE_EXCLUDE, filenames) 145*35238bceSAndroid Build Coastguard Worker 146*35238bceSAndroid Build Coastguard Workerdef insertXMLHeaders (mustpass, doc): 147*35238bceSAndroid Build Coastguard Worker if mustpass.project.copyright != None: 148*35238bceSAndroid Build Coastguard Worker doc.insert(0, ElementTree.Comment(mustpass.project.copyright)) 149*35238bceSAndroid Build Coastguard Worker doc.insert(1, ElementTree.Comment(GENERATED_FILE_WARNING)) 150*35238bceSAndroid Build Coastguard Worker 151*35238bceSAndroid Build Coastguard Workerdef prettifyXML (doc): 152*35238bceSAndroid Build Coastguard Worker uglyString = ElementTree.tostring(doc, 'utf-8') 153*35238bceSAndroid Build Coastguard Worker reparsed = minidom.parseString(uglyString) 154*35238bceSAndroid Build Coastguard Worker return reparsed.toprettyxml(indent='\t', encoding='utf-8') 155*35238bceSAndroid Build Coastguard Worker 156*35238bceSAndroid Build Coastguard Workerdef genSpecXML (mustpass): 157*35238bceSAndroid Build Coastguard Worker mustpassElem = ElementTree.Element("Mustpass", version = mustpass.version) 158*35238bceSAndroid Build Coastguard Worker insertXMLHeaders(mustpass, mustpassElem) 159*35238bceSAndroid Build Coastguard Worker 160*35238bceSAndroid Build Coastguard Worker for package in mustpass.packages: 161*35238bceSAndroid Build Coastguard Worker packageElem = ElementTree.SubElement(mustpassElem, "TestPackage", name = package.module.name) 162*35238bceSAndroid Build Coastguard Worker 163*35238bceSAndroid Build Coastguard Worker for config in package.configurations: 164*35238bceSAndroid Build Coastguard Worker configElem = ElementTree.SubElement(packageElem, "Configuration", 165*35238bceSAndroid Build Coastguard Worker caseListFile = getCaseListFileName(package, config), 166*35238bceSAndroid Build Coastguard Worker commandLine = getCommandLine(config), 167*35238bceSAndroid Build Coastguard Worker name = config.name) 168*35238bceSAndroid Build Coastguard Worker 169*35238bceSAndroid Build Coastguard Worker return mustpassElem 170*35238bceSAndroid Build Coastguard Worker 171*35238bceSAndroid Build Coastguard Workerdef addOptionElement (parent, optionName, optionValue): 172*35238bceSAndroid Build Coastguard Worker ElementTree.SubElement(parent, "option", name=optionName, value=optionValue) 173*35238bceSAndroid Build Coastguard Worker 174*35238bceSAndroid Build Coastguard Workerdef genAndroidTestXml (mustpass): 175*35238bceSAndroid Build Coastguard Worker RUNNER_CLASS = "com.drawelements.deqp.runner.DeqpTestRunner" 176*35238bceSAndroid Build Coastguard Worker configElement = ElementTree.Element("configuration") 177*35238bceSAndroid Build Coastguard Worker 178*35238bceSAndroid Build Coastguard Worker # have the deqp package installed on the device for us 179*35238bceSAndroid Build Coastguard Worker preparerElement = ElementTree.SubElement(configElement, "target_preparer") 180*35238bceSAndroid Build Coastguard Worker preparerElement.set("class", "com.android.tradefed.targetprep.suite.SuiteApkInstaller") 181*35238bceSAndroid Build Coastguard Worker addOptionElement(preparerElement, "cleanup-apks", "true") 182*35238bceSAndroid Build Coastguard Worker addOptionElement(preparerElement, "test-file-name", "com.drawelements.deqp.apk") 183*35238bceSAndroid Build Coastguard Worker 184*35238bceSAndroid Build Coastguard Worker # Target preparer for incremental dEQP 185*35238bceSAndroid Build Coastguard Worker preparerElement = ElementTree.SubElement(configElement, "target_preparer") 186*35238bceSAndroid Build Coastguard Worker preparerElement.set("class", "com.android.compatibility.common.tradefed.targetprep.FilePusher") 187*35238bceSAndroid Build Coastguard Worker addOptionElement(preparerElement, "cleanup", "true") 188*35238bceSAndroid Build Coastguard Worker addOptionElement(preparerElement, "disable", "true") 189*35238bceSAndroid Build Coastguard Worker addOptionElement(preparerElement, "push", "deqp-binary32->/data/local/tmp/deqp-binary32") 190*35238bceSAndroid Build Coastguard Worker addOptionElement(preparerElement, "push", "deqp-binary64->/data/local/tmp/deqp-binary64") 191*35238bceSAndroid Build Coastguard Worker addOptionElement(preparerElement, "push", "gles2->/data/local/tmp/gles2") 192*35238bceSAndroid Build Coastguard Worker addOptionElement(preparerElement, "push", "gles2-incremental-deqp-baseline.txt->/data/local/tmp/gles2-incremental-deqp-baseline.txt") 193*35238bceSAndroid Build Coastguard Worker addOptionElement(preparerElement, "push", "gles3->/data/local/tmp/gles3") 194*35238bceSAndroid Build Coastguard Worker addOptionElement(preparerElement, "push", "gles3-incremental-deqp-baseline.txt->/data/local/tmp/gles3-incremental-deqp-baseline.txt") 195*35238bceSAndroid Build Coastguard Worker addOptionElement(preparerElement, "push", "gles3-incremental-deqp.txt->/data/local/tmp/gles3-incremental-deqp.txt") 196*35238bceSAndroid Build Coastguard Worker addOptionElement(preparerElement, "push", "gles31->/data/local/tmp/gles31") 197*35238bceSAndroid Build Coastguard Worker addOptionElement(preparerElement, "push", "gles31-incremental-deqp-baseline.txt->/data/local/tmp/gles31-incremental-deqp-baseline.txt") 198*35238bceSAndroid Build Coastguard Worker addOptionElement(preparerElement, "push", "internal->/data/local/tmp/internal") 199*35238bceSAndroid Build Coastguard Worker addOptionElement(preparerElement, "push", "vk-incremental-deqp-baseline.txt->/data/local/tmp/vk-incremental-deqp-baseline.txt") 200*35238bceSAndroid Build Coastguard Worker addOptionElement(preparerElement, "push", "vk-incremental-deqp.txt->/data/local/tmp/vk-incremental-deqp.txt") 201*35238bceSAndroid Build Coastguard Worker addOptionElement(preparerElement, "push", "vulkan->/data/local/tmp/vulkan") 202*35238bceSAndroid Build Coastguard Worker preparerElement = ElementTree.SubElement(configElement, "target_preparer") 203*35238bceSAndroid Build Coastguard Worker preparerElement.set("class", "com.android.compatibility.common.tradefed.targetprep.IncrementalDeqpPreparer") 204*35238bceSAndroid Build Coastguard Worker addOptionElement(preparerElement, "disable", "true") 205*35238bceSAndroid Build Coastguard Worker 206*35238bceSAndroid Build Coastguard Worker # add in metadata option for component name 207*35238bceSAndroid Build Coastguard Worker ElementTree.SubElement(configElement, "option", name="test-suite-tag", value="cts") 208*35238bceSAndroid Build Coastguard Worker ElementTree.SubElement(configElement, "option", key="component", name="config-descriptor:metadata", value="deqp") 209*35238bceSAndroid Build Coastguard Worker ElementTree.SubElement(configElement, "option", key="parameter", name="config-descriptor:metadata", value="not_instant_app") 210*35238bceSAndroid Build Coastguard Worker ElementTree.SubElement(configElement, "option", key="parameter", name="config-descriptor:metadata", value="multi_abi") 211*35238bceSAndroid Build Coastguard Worker ElementTree.SubElement(configElement, "option", key="parameter", name="config-descriptor:metadata", value="secondary_user") 212*35238bceSAndroid Build Coastguard Worker ElementTree.SubElement(configElement, "option", key="parameter", name="config-descriptor:metadata", value="no_foldable_states") 213*35238bceSAndroid Build Coastguard Worker controllerElement = ElementTree.SubElement(configElement, "object") 214*35238bceSAndroid Build Coastguard Worker controllerElement.set("class", "com.android.tradefed.testtype.suite.module.TestFailureModuleController") 215*35238bceSAndroid Build Coastguard Worker controllerElement.set("type", "module_controller") 216*35238bceSAndroid Build Coastguard Worker addOptionElement(controllerElement, "screenshot-on-failure", "false") 217*35238bceSAndroid Build Coastguard Worker 218*35238bceSAndroid Build Coastguard Worker for package in mustpass.packages: 219*35238bceSAndroid Build Coastguard Worker for config in package.configurations: 220*35238bceSAndroid Build Coastguard Worker if not config.runByDefault: 221*35238bceSAndroid Build Coastguard Worker continue 222*35238bceSAndroid Build Coastguard Worker 223*35238bceSAndroid Build Coastguard Worker testElement = ElementTree.SubElement(configElement, "test") 224*35238bceSAndroid Build Coastguard Worker testElement.set("class", RUNNER_CLASS) 225*35238bceSAndroid Build Coastguard Worker addOptionElement(testElement, "deqp-package", package.module.name) 226*35238bceSAndroid Build Coastguard Worker caseListFile = getCaseListFileName(package,config) 227*35238bceSAndroid Build Coastguard Worker addOptionElement(testElement, "deqp-caselist-file", caseListFile) 228*35238bceSAndroid Build Coastguard Worker if caseListFile.startswith("gles3"): 229*35238bceSAndroid Build Coastguard Worker addOptionElement(testElement, "incremental-deqp-include-file", "gles3-incremental-deqp.txt") 230*35238bceSAndroid Build Coastguard Worker elif caseListFile.startswith("vk"): 231*35238bceSAndroid Build Coastguard Worker addOptionElement(testElement, "incremental-deqp-include-file", "vk-incremental-deqp.txt") 232*35238bceSAndroid Build Coastguard Worker # \todo [2015-10-16 kalle]: Replace with just command line? - requires simplifications in the runner/tests as well. 233*35238bceSAndroid Build Coastguard Worker if config.glconfig != None: 234*35238bceSAndroid Build Coastguard Worker addOptionElement(testElement, "deqp-gl-config-name", config.glconfig) 235*35238bceSAndroid Build Coastguard Worker 236*35238bceSAndroid Build Coastguard Worker if config.surfacetype != None: 237*35238bceSAndroid Build Coastguard Worker addOptionElement(testElement, "deqp-surface-type", config.surfacetype) 238*35238bceSAndroid Build Coastguard Worker 239*35238bceSAndroid Build Coastguard Worker if config.rotation != None: 240*35238bceSAndroid Build Coastguard Worker addOptionElement(testElement, "deqp-screen-rotation", config.rotation) 241*35238bceSAndroid Build Coastguard Worker 242*35238bceSAndroid Build Coastguard Worker if config.expectedRuntime != None: 243*35238bceSAndroid Build Coastguard Worker addOptionElement(testElement, "runtime-hint", config.expectedRuntime) 244*35238bceSAndroid Build Coastguard Worker 245*35238bceSAndroid Build Coastguard Worker if config.required: 246*35238bceSAndroid Build Coastguard Worker addOptionElement(testElement, "deqp-config-required", "true") 247*35238bceSAndroid Build Coastguard Worker 248*35238bceSAndroid Build Coastguard Worker insertXMLHeaders(mustpass, configElement) 249*35238bceSAndroid Build Coastguard Worker 250*35238bceSAndroid Build Coastguard Worker return configElement 251*35238bceSAndroid Build Coastguard Worker 252*35238bceSAndroid Build Coastguard Workerclass PatternSet: 253*35238bceSAndroid Build Coastguard Worker def __init__(self): 254*35238bceSAndroid Build Coastguard Worker self.namedPatternsTree = {} 255*35238bceSAndroid Build Coastguard Worker self.namedPatternsDict = {} 256*35238bceSAndroid Build Coastguard Worker self.wildcardPatternsDict = {} 257*35238bceSAndroid Build Coastguard Worker 258*35238bceSAndroid Build Coastguard Workerdef readPatternSets (mustpass): 259*35238bceSAndroid Build Coastguard Worker patternSets = {} 260*35238bceSAndroid Build Coastguard Worker for package in mustpass.packages: 261*35238bceSAndroid Build Coastguard Worker for cfg in package.configurations: 262*35238bceSAndroid Build Coastguard Worker for filter in cfg.filters: 263*35238bceSAndroid Build Coastguard Worker if not filter.key in patternSets: 264*35238bceSAndroid Build Coastguard Worker patternList = [] 265*35238bceSAndroid Build Coastguard Worker for filename in filter.filenames: 266*35238bceSAndroid Build Coastguard Worker readPatternList(os.path.join(getSrcDir(mustpass), filename), patternList) 267*35238bceSAndroid Build Coastguard Worker patternSet = PatternSet() 268*35238bceSAndroid Build Coastguard Worker for pattern in patternList: 269*35238bceSAndroid Build Coastguard Worker if pattern.find('*') == -1: 270*35238bceSAndroid Build Coastguard Worker patternSet.namedPatternsDict[pattern] = 0 271*35238bceSAndroid Build Coastguard Worker t = patternSet.namedPatternsTree 272*35238bceSAndroid Build Coastguard Worker parts = pattern.split('.') 273*35238bceSAndroid Build Coastguard Worker for part in parts: 274*35238bceSAndroid Build Coastguard Worker t = t.setdefault(part, {}) 275*35238bceSAndroid Build Coastguard Worker else: 276*35238bceSAndroid Build Coastguard Worker # We use regex instead of fnmatch because it's faster 277*35238bceSAndroid Build Coastguard Worker patternSet.wildcardPatternsDict[re.compile("^" + pattern.replace(".", r"\.").replace("*", ".*?") + "$")] = 0 278*35238bceSAndroid Build Coastguard Worker patternSets[filter.key] = patternSet 279*35238bceSAndroid Build Coastguard Worker return patternSets 280*35238bceSAndroid Build Coastguard Worker 281*35238bceSAndroid Build Coastguard Workerdef genMustpassFromLists (mustpass, moduleCaseLists): 282*35238bceSAndroid Build Coastguard Worker print("Generating mustpass '%s'" % mustpass.version) 283*35238bceSAndroid Build Coastguard Worker patternSets = readPatternSets(mustpass) 284*35238bceSAndroid Build Coastguard Worker 285*35238bceSAndroid Build Coastguard Worker for package in mustpass.packages: 286*35238bceSAndroid Build Coastguard Worker currentCaseList = moduleCaseLists[package.module] 287*35238bceSAndroid Build Coastguard Worker logging.debug("Reading " + currentCaseList.filePath) 288*35238bceSAndroid Build Coastguard Worker 289*35238bceSAndroid Build Coastguard Worker for config in package.configurations: 290*35238bceSAndroid Build Coastguard Worker # construct components of path to main destination file 291*35238bceSAndroid Build Coastguard Worker mainDstFileDir = getDstCaseListPath(mustpass) 292*35238bceSAndroid Build Coastguard Worker mainDstFileName = getCaseListFileName(package, config) 293*35238bceSAndroid Build Coastguard Worker mainDstFilePath = os.path.join(mainDstFileDir, mainDstFileName) 294*35238bceSAndroid Build Coastguard Worker mainGroupSubDir = mainDstFileName[:-4] 295*35238bceSAndroid Build Coastguard Worker 296*35238bceSAndroid Build Coastguard Worker if not os.path.exists(mainDstFileDir): 297*35238bceSAndroid Build Coastguard Worker os.makedirs(mainDstFileDir) 298*35238bceSAndroid Build Coastguard Worker mainDstFile = open(mainDstFilePath, 'w') 299*35238bceSAndroid Build Coastguard Worker print(mainDstFilePath) 300*35238bceSAndroid Build Coastguard Worker output_files = {} 301*35238bceSAndroid Build Coastguard Worker def openAndStoreFile(filePath, testFilePath, parentFile): 302*35238bceSAndroid Build Coastguard Worker if filePath not in output_files: 303*35238bceSAndroid Build Coastguard Worker try: 304*35238bceSAndroid Build Coastguard Worker print(" " + filePath) 305*35238bceSAndroid Build Coastguard Worker parentFile.write(mainGroupSubDir + "/" + testFilePath + "\n") 306*35238bceSAndroid Build Coastguard Worker currentDir = os.path.dirname(filePath) 307*35238bceSAndroid Build Coastguard Worker if not os.path.exists(currentDir): 308*35238bceSAndroid Build Coastguard Worker os.makedirs(currentDir) 309*35238bceSAndroid Build Coastguard Worker output_files[filePath] = open(filePath, 'w') 310*35238bceSAndroid Build Coastguard Worker 311*35238bceSAndroid Build Coastguard Worker except FileNotFoundError: 312*35238bceSAndroid Build Coastguard Worker print(f"File not found: {filePath}") 313*35238bceSAndroid Build Coastguard Worker return output_files[filePath] 314*35238bceSAndroid Build Coastguard Worker 315*35238bceSAndroid Build Coastguard Worker lastOutputFile = "" 316*35238bceSAndroid Build Coastguard Worker currentOutputFile = None 317*35238bceSAndroid Build Coastguard Worker for line in currentCaseList.sortedLines: 318*35238bceSAndroid Build Coastguard Worker if not line.startswith("TEST: "): 319*35238bceSAndroid Build Coastguard Worker continue 320*35238bceSAndroid Build Coastguard Worker caseName = line.replace("TEST: ", "").strip("\n") 321*35238bceSAndroid Build Coastguard Worker caseParts = caseName.split(".") 322*35238bceSAndroid Build Coastguard Worker keep = True 323*35238bceSAndroid Build Coastguard Worker # Do the includes with the complex patterns first 324*35238bceSAndroid Build Coastguard Worker for filter in config.filters: 325*35238bceSAndroid Build Coastguard Worker if filter.type == Filter.TYPE_INCLUDE: 326*35238bceSAndroid Build Coastguard Worker keep = False 327*35238bceSAndroid Build Coastguard Worker patterns = patternSets[filter.key].wildcardPatternsDict 328*35238bceSAndroid Build Coastguard Worker for pattern in patterns.keys(): 329*35238bceSAndroid Build Coastguard Worker keep = pattern.match(caseName) 330*35238bceSAndroid Build Coastguard Worker if keep: 331*35238bceSAndroid Build Coastguard Worker patterns[pattern] += 1 332*35238bceSAndroid Build Coastguard Worker break 333*35238bceSAndroid Build Coastguard Worker 334*35238bceSAndroid Build Coastguard Worker if not keep: 335*35238bceSAndroid Build Coastguard Worker t = patternSets[filter.key].namedPatternsTree 336*35238bceSAndroid Build Coastguard Worker if len(t.keys()) == 0: 337*35238bceSAndroid Build Coastguard Worker continue 338*35238bceSAndroid Build Coastguard Worker for part in caseParts: 339*35238bceSAndroid Build Coastguard Worker if part in t: 340*35238bceSAndroid Build Coastguard Worker t = t[part] 341*35238bceSAndroid Build Coastguard Worker else: 342*35238bceSAndroid Build Coastguard Worker t = None # Not found 343*35238bceSAndroid Build Coastguard Worker break 344*35238bceSAndroid Build Coastguard Worker keep = t == {} 345*35238bceSAndroid Build Coastguard Worker if keep: 346*35238bceSAndroid Build Coastguard Worker patternSets[filter.key].namedPatternsDict[caseName] += 1 347*35238bceSAndroid Build Coastguard Worker 348*35238bceSAndroid Build Coastguard Worker # Do the excludes 349*35238bceSAndroid Build Coastguard Worker if filter.type == Filter.TYPE_EXCLUDE: 350*35238bceSAndroid Build Coastguard Worker patterns = patternSets[filter.key].wildcardPatternsDict 351*35238bceSAndroid Build Coastguard Worker for pattern in patterns.keys(): 352*35238bceSAndroid Build Coastguard Worker discard = pattern.match(caseName) 353*35238bceSAndroid Build Coastguard Worker if discard: 354*35238bceSAndroid Build Coastguard Worker patterns[pattern] += 1 355*35238bceSAndroid Build Coastguard Worker keep = False 356*35238bceSAndroid Build Coastguard Worker break 357*35238bceSAndroid Build Coastguard Worker if keep: 358*35238bceSAndroid Build Coastguard Worker t = patternSets[filter.key].namedPatternsTree 359*35238bceSAndroid Build Coastguard Worker if len(t.keys()) == 0: 360*35238bceSAndroid Build Coastguard Worker continue 361*35238bceSAndroid Build Coastguard Worker for part in caseParts: 362*35238bceSAndroid Build Coastguard Worker if part in t: 363*35238bceSAndroid Build Coastguard Worker t = t[part] 364*35238bceSAndroid Build Coastguard Worker else: 365*35238bceSAndroid Build Coastguard Worker t = None # Not found 366*35238bceSAndroid Build Coastguard Worker break 367*35238bceSAndroid Build Coastguard Worker if t == {}: 368*35238bceSAndroid Build Coastguard Worker patternSets[filter.key].namedPatternsDict[caseName] += 1 369*35238bceSAndroid Build Coastguard Worker keep = False 370*35238bceSAndroid Build Coastguard Worker if not keep: 371*35238bceSAndroid Build Coastguard Worker break 372*35238bceSAndroid Build Coastguard Worker if not keep: 373*35238bceSAndroid Build Coastguard Worker continue 374*35238bceSAndroid Build Coastguard Worker 375*35238bceSAndroid Build Coastguard Worker parts = caseName.split('.') 376*35238bceSAndroid Build Coastguard Worker if len(config.listOfGroupsToSplit) > 0: 377*35238bceSAndroid Build Coastguard Worker if len(parts) > 2: 378*35238bceSAndroid Build Coastguard Worker groupName = parts[1].replace("_", "-") 379*35238bceSAndroid Build Coastguard Worker for splitPattern in config.listOfGroupsToSplit: 380*35238bceSAndroid Build Coastguard Worker splitParts = splitPattern.split(".") 381*35238bceSAndroid Build Coastguard Worker if len(splitParts) > 1 and caseName.startswith(splitPattern + "."): 382*35238bceSAndroid Build Coastguard Worker groupName = groupName + "/" + parts[2].replace("_", "-") 383*35238bceSAndroid Build Coastguard Worker filePath = os.path.join(mainDstFileDir, mainGroupSubDir, groupName + ".txt") 384*35238bceSAndroid Build Coastguard Worker if lastOutputFile != filePath: 385*35238bceSAndroid Build Coastguard Worker currentOutputFile = openAndStoreFile(filePath, groupName + ".txt", mainDstFile) 386*35238bceSAndroid Build Coastguard Worker lastOutputFile = filePath 387*35238bceSAndroid Build Coastguard Worker currentOutputFile.write(caseName + "\n") 388*35238bceSAndroid Build Coastguard Worker else: 389*35238bceSAndroid Build Coastguard Worker mainDstFile.write(caseName + "\n") 390*35238bceSAndroid Build Coastguard Worker 391*35238bceSAndroid Build Coastguard Worker # Check that all patterns have been used in the filters 392*35238bceSAndroid Build Coastguard Worker # This check will help identifying typos and patterns becoming stale 393*35238bceSAndroid Build Coastguard Worker for filter in config.filters: 394*35238bceSAndroid Build Coastguard Worker if filter.type == Filter.TYPE_INCLUDE: 395*35238bceSAndroid Build Coastguard Worker patternSet = patternSets[filter.key] 396*35238bceSAndroid Build Coastguard Worker for pattern, usage in patternSet.namedPatternsDict.items(): 397*35238bceSAndroid Build Coastguard Worker if usage == 0: 398*35238bceSAndroid Build Coastguard Worker logging.debug("Case %s in file %s for module %s was never used!" % (pattern, filter.key, config.name)) 399*35238bceSAndroid Build Coastguard Worker for pattern, usage in patternSet.wildcardPatternsDict.items(): 400*35238bceSAndroid Build Coastguard Worker if usage == 0: 401*35238bceSAndroid Build Coastguard Worker logging.debug("Pattern %s in file %s for module %s was never used!" % (pattern, filter.key, config.name)) 402*35238bceSAndroid Build Coastguard Worker 403*35238bceSAndroid Build Coastguard Worker # Generate XML 404*35238bceSAndroid Build Coastguard Worker specXML = genSpecXML(mustpass) 405*35238bceSAndroid Build Coastguard Worker specFilename = os.path.join(mustpass.project.path, mustpass.version, "mustpass.xml") 406*35238bceSAndroid Build Coastguard Worker 407*35238bceSAndroid Build Coastguard Worker print(" Writing spec: " + specFilename) 408*35238bceSAndroid Build Coastguard Worker writeFile(specFilename, prettifyXML(specXML).decode()) 409*35238bceSAndroid Build Coastguard Worker 410*35238bceSAndroid Build Coastguard Worker # TODO: Which is the best selector mechanism? 411*35238bceSAndroid Build Coastguard Worker if (mustpass.version == "main"): 412*35238bceSAndroid Build Coastguard Worker androidTestXML = genAndroidTestXml(mustpass) 413*35238bceSAndroid Build Coastguard Worker androidTestFilename = os.path.join(mustpass.project.path, "AndroidTest.xml") 414*35238bceSAndroid Build Coastguard Worker 415*35238bceSAndroid Build Coastguard Worker print(" Writing AndroidTest.xml: " + androidTestFilename) 416*35238bceSAndroid Build Coastguard Worker writeFile(androidTestFilename, prettifyXML(androidTestXML).decode()) 417*35238bceSAndroid Build Coastguard Worker 418*35238bceSAndroid Build Coastguard Worker print("Done!") 419*35238bceSAndroid Build Coastguard Worker 420*35238bceSAndroid Build Coastguard Worker 421*35238bceSAndroid Build Coastguard Workerdef genMustpassLists (mustpassLists, generator, buildCfg): 422*35238bceSAndroid Build Coastguard Worker moduleCaseLists = {} 423*35238bceSAndroid Build Coastguard Worker 424*35238bceSAndroid Build Coastguard Worker # Getting case lists involves invoking build, so we want to cache the results 425*35238bceSAndroid Build Coastguard Worker for mustpass in mustpassLists: 426*35238bceSAndroid Build Coastguard Worker for package in mustpass.packages: 427*35238bceSAndroid Build Coastguard Worker if not package.module in moduleCaseLists: 428*35238bceSAndroid Build Coastguard Worker moduleCaseLists[package.module] = readAndSortCaseList(buildCfg, generator, package.module) 429*35238bceSAndroid Build Coastguard Worker 430*35238bceSAndroid Build Coastguard Worker for mustpass in mustpassLists: 431*35238bceSAndroid Build Coastguard Worker genMustpassFromLists(mustpass, moduleCaseLists) 432*35238bceSAndroid Build Coastguard Worker 433*35238bceSAndroid Build Coastguard Workerdef parseCmdLineArgs (): 434*35238bceSAndroid Build Coastguard Worker parser = argparse.ArgumentParser(description = "Build Android CTS mustpass", 435*35238bceSAndroid Build Coastguard Worker formatter_class=argparse.ArgumentDefaultsHelpFormatter) 436*35238bceSAndroid Build Coastguard Worker parser.add_argument("-b", 437*35238bceSAndroid Build Coastguard Worker "--build-dir", 438*35238bceSAndroid Build Coastguard Worker dest="buildDir", 439*35238bceSAndroid Build Coastguard Worker default=DEFAULT_BUILD_DIR, 440*35238bceSAndroid Build Coastguard Worker help="Temporary build directory") 441*35238bceSAndroid Build Coastguard Worker parser.add_argument("-t", 442*35238bceSAndroid Build Coastguard Worker "--build-type", 443*35238bceSAndroid Build Coastguard Worker dest="buildType", 444*35238bceSAndroid Build Coastguard Worker default="Debug", 445*35238bceSAndroid Build Coastguard Worker help="Build type") 446*35238bceSAndroid Build Coastguard Worker parser.add_argument("-c", 447*35238bceSAndroid Build Coastguard Worker "--deqp-target", 448*35238bceSAndroid Build Coastguard Worker dest="targetName", 449*35238bceSAndroid Build Coastguard Worker default=DEFAULT_TARGET, 450*35238bceSAndroid Build Coastguard Worker help="dEQP build target") 451*35238bceSAndroid Build Coastguard Worker parser.add_argument("-v", "--verbose", 452*35238bceSAndroid Build Coastguard Worker dest="verbose", 453*35238bceSAndroid Build Coastguard Worker action="store_true", 454*35238bceSAndroid Build Coastguard Worker help="Enable verbose logging") 455*35238bceSAndroid Build Coastguard Worker return parser.parse_args() 456*35238bceSAndroid Build Coastguard Worker 457*35238bceSAndroid Build Coastguard Workerdef parseBuildConfigFromCmdLineArgs (): 458*35238bceSAndroid Build Coastguard Worker args = parseCmdLineArgs() 459*35238bceSAndroid Build Coastguard Worker initializeLogger(args.verbose) 460*35238bceSAndroid Build Coastguard Worker return getBuildConfig(args.buildDir, args.targetName, args.buildType) 461