xref: /aosp_15_r20/external/deqp/scripts/mustpass.py (revision 35238bce31c2a825756842865a792f8cf7f89930)
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