xref: /aosp_15_r20/external/deqp/framework/common/tcuWaiverUtil.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * Vulkan CTS Framework
3*35238bceSAndroid Build Coastguard Worker  * --------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright (c) 2020 The Khronos Group Inc.
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief Waiver mechanism implementation.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "tcuWaiverUtil.hpp"
25*35238bceSAndroid Build Coastguard Worker #include <fstream>
26*35238bceSAndroid Build Coastguard Worker #include <iostream>
27*35238bceSAndroid Build Coastguard Worker #include <sstream>
28*35238bceSAndroid Build Coastguard Worker #include <iomanip>
29*35238bceSAndroid Build Coastguard Worker #include "deString.h"
30*35238bceSAndroid Build Coastguard Worker #include "deStringUtil.hpp"
31*35238bceSAndroid Build Coastguard Worker #include "xeXMLParser.hpp"
32*35238bceSAndroid Build Coastguard Worker #include "tcuCommandLine.hpp"
33*35238bceSAndroid Build Coastguard Worker 
34*35238bceSAndroid Build Coastguard Worker namespace tcu
35*35238bceSAndroid Build Coastguard Worker {
36*35238bceSAndroid Build Coastguard Worker 
SessionInfo(uint32_t vendorId,uint32_t deviceId,const std::string & deviceName,const std::string & cmdLine)37*35238bceSAndroid Build Coastguard Worker SessionInfo::SessionInfo(uint32_t vendorId, uint32_t deviceId, const std::string &deviceName,
38*35238bceSAndroid Build Coastguard Worker                          const std::string &cmdLine)
39*35238bceSAndroid Build Coastguard Worker     : m_cmdLine(cmdLine)
40*35238bceSAndroid Build Coastguard Worker {
41*35238bceSAndroid Build Coastguard Worker     m_info << std::hex << "#sessionInfo vendorID 0x" << vendorId << "\n"
42*35238bceSAndroid Build Coastguard Worker            << "#sessionInfo deviceID 0x" << deviceId << "\n"
43*35238bceSAndroid Build Coastguard Worker            << "#sessionInfo deviceName " << deviceName << "\n";
44*35238bceSAndroid Build Coastguard Worker }
45*35238bceSAndroid Build Coastguard Worker 
SessionInfo(std::string vendor,std::string renderer,const std::string & cmdLine)46*35238bceSAndroid Build Coastguard Worker SessionInfo::SessionInfo(std::string vendor, std::string renderer, const std::string &cmdLine) : m_cmdLine(cmdLine)
47*35238bceSAndroid Build Coastguard Worker {
48*35238bceSAndroid Build Coastguard Worker     m_info << "#sessionInfo vendor \"" << vendor << "\"\n"
49*35238bceSAndroid Build Coastguard Worker            << "#sessionInfo renderer \"" << renderer << "\"\n";
50*35238bceSAndroid Build Coastguard Worker }
51*35238bceSAndroid Build Coastguard Worker 
get()52*35238bceSAndroid Build Coastguard Worker std::string SessionInfo::get()
53*35238bceSAndroid Build Coastguard Worker {
54*35238bceSAndroid Build Coastguard Worker     if (!m_waiverUrls.empty())
55*35238bceSAndroid Build Coastguard Worker     {
56*35238bceSAndroid Build Coastguard Worker         m_info << "#sessionInfo waiverUrls \"" << m_waiverUrls << "\"\n";
57*35238bceSAndroid Build Coastguard Worker         m_waiverUrls.clear();
58*35238bceSAndroid Build Coastguard Worker     }
59*35238bceSAndroid Build Coastguard Worker     if (!m_cmdLine.empty())
60*35238bceSAndroid Build Coastguard Worker     {
61*35238bceSAndroid Build Coastguard Worker         m_info << "#sessionInfo commandLineParameters \"" << m_cmdLine << "\"\n";
62*35238bceSAndroid Build Coastguard Worker         m_cmdLine.clear();
63*35238bceSAndroid Build Coastguard Worker     }
64*35238bceSAndroid Build Coastguard Worker     return m_info.str();
65*35238bceSAndroid Build Coastguard Worker }
66*35238bceSAndroid Build Coastguard Worker 
67*35238bceSAndroid Build Coastguard Worker // Base class for GL and VK waiver tree builders
68*35238bceSAndroid Build Coastguard Worker class WaiverTreeBuilder
69*35238bceSAndroid Build Coastguard Worker {
70*35238bceSAndroid Build Coastguard Worker public:
71*35238bceSAndroid Build Coastguard Worker     typedef WaiverUtil::WaiverComponent WaiverComponent;
72*35238bceSAndroid Build Coastguard Worker 
73*35238bceSAndroid Build Coastguard Worker public:
74*35238bceSAndroid Build Coastguard Worker     WaiverTreeBuilder(const std::string &waiverFile, const std::string &packageName, const char *vendorTag,
75*35238bceSAndroid Build Coastguard Worker                       const char *deviceTag, SessionInfo &sessionInfo, std::vector<WaiverComponent> &waiverTree);
76*35238bceSAndroid Build Coastguard Worker 
77*35238bceSAndroid Build Coastguard Worker     virtual ~WaiverTreeBuilder();
78*35238bceSAndroid Build Coastguard Worker 
79*35238bceSAndroid Build Coastguard Worker     void build(void);
80*35238bceSAndroid Build Coastguard Worker 
81*35238bceSAndroid Build Coastguard Worker protected:
82*35238bceSAndroid Build Coastguard Worker     // structure representing component during tree construction
83*35238bceSAndroid Build Coastguard Worker     struct BuilComponent
84*35238bceSAndroid Build Coastguard Worker     {
85*35238bceSAndroid Build Coastguard Worker         std::string name;
86*35238bceSAndroid Build Coastguard Worker         uint32_t parentIndex;                // index in allComponents vector
87*35238bceSAndroid Build Coastguard Worker         std::vector<uint32_t> childrenIndex; // index in allComponents vector
88*35238bceSAndroid Build Coastguard Worker 
BuilComponenttcu::WaiverTreeBuilder::BuilComponent89*35238bceSAndroid Build Coastguard Worker         BuilComponent(std::string n, uint32_t p) : name(std::move(n)), parentIndex(p)
90*35238bceSAndroid Build Coastguard Worker         {
91*35238bceSAndroid Build Coastguard Worker         }
92*35238bceSAndroid Build Coastguard Worker     };
93*35238bceSAndroid Build Coastguard Worker 
94*35238bceSAndroid Build Coastguard Worker     // parse waiver.xml and read list of waived tests defined
95*35238bceSAndroid Build Coastguard Worker     // specificly for current device id and current vendor id
96*35238bceSAndroid Build Coastguard Worker     void readWaivedTestsFromXML(void);
97*35238bceSAndroid Build Coastguard Worker 
98*35238bceSAndroid Build Coastguard Worker     // use list of paths to build a temporary tree which
99*35238bceSAndroid Build Coastguard Worker     // consists of BuilComponents that help with tree construction
100*35238bceSAndroid Build Coastguard Worker     void buildTreeFromPathList(void);
101*35238bceSAndroid Build Coastguard Worker 
102*35238bceSAndroid Build Coastguard Worker     // use temporary tree to create final tree containing
103*35238bceSAndroid Build Coastguard Worker     // only things that are needed during searches
104*35238bceSAndroid Build Coastguard Worker     void constructFinalTree(void);
105*35238bceSAndroid Build Coastguard Worker 
106*35238bceSAndroid Build Coastguard Worker     // helper methods used to identify if proper waiver for vendor was found
107*35238bceSAndroid Build Coastguard Worker     virtual bool matchVendor(const std::string &vendor) const = 0;
108*35238bceSAndroid Build Coastguard Worker 
109*35238bceSAndroid Build Coastguard Worker     // helper methods used after waiver for current vendor was found to check
110*35238bceSAndroid Build Coastguard Worker     // if it is defined also for currend deviceId/renderer
111*35238bceSAndroid Build Coastguard Worker     virtual bool matchDevice(const std::string &device) const = 0;
112*35238bceSAndroid Build Coastguard Worker 
113*35238bceSAndroid Build Coastguard Worker     // helper method used in buildTreeFromPathList; returns index
114*35238bceSAndroid Build Coastguard Worker     // of component having same ancestors as the component specified
115*35238bceSAndroid Build Coastguard Worker     // in the argument or 0 when build tree does not include this component
116*35238bceSAndroid Build Coastguard Worker     uint32_t findComponentInBuildTree(const std::vector<std::string> &pathComponents, uint32_t index) const;
117*35238bceSAndroid Build Coastguard Worker 
118*35238bceSAndroid Build Coastguard Worker private:
119*35238bceSAndroid Build Coastguard Worker     const std::string &m_waiverFile;
120*35238bceSAndroid Build Coastguard Worker     const std::string &m_packageName;
121*35238bceSAndroid Build Coastguard Worker 
122*35238bceSAndroid Build Coastguard Worker     const char *m_vendorTag;
123*35238bceSAndroid Build Coastguard Worker     const char *m_deviceTag;
124*35238bceSAndroid Build Coastguard Worker 
125*35238bceSAndroid Build Coastguard Worker     // helper attributes used during construction
126*35238bceSAndroid Build Coastguard Worker     std::vector<std::string> m_testList;
127*35238bceSAndroid Build Coastguard Worker     std::vector<BuilComponent> m_buildTree;
128*35238bceSAndroid Build Coastguard Worker 
129*35238bceSAndroid Build Coastguard Worker     // reference to object containing information about used waivers
130*35238bceSAndroid Build Coastguard Worker     SessionInfo &m_sessionInfo;
131*35238bceSAndroid Build Coastguard Worker 
132*35238bceSAndroid Build Coastguard Worker     // reference to vector containing final tree
133*35238bceSAndroid Build Coastguard Worker     std::vector<WaiverComponent> &m_finalTree;
134*35238bceSAndroid Build Coastguard Worker };
135*35238bceSAndroid Build Coastguard Worker 
WaiverTreeBuilder(const std::string & waiverFile,const std::string & packageName,const char * vendorTag,const char * deviceTag,SessionInfo & sessionInfo,std::vector<WaiverComponent> & waiverTree)136*35238bceSAndroid Build Coastguard Worker WaiverTreeBuilder::WaiverTreeBuilder(const std::string &waiverFile, const std::string &packageName,
137*35238bceSAndroid Build Coastguard Worker                                      const char *vendorTag, const char *deviceTag, SessionInfo &sessionInfo,
138*35238bceSAndroid Build Coastguard Worker                                      std::vector<WaiverComponent> &waiverTree)
139*35238bceSAndroid Build Coastguard Worker     : m_waiverFile(waiverFile)
140*35238bceSAndroid Build Coastguard Worker     , m_packageName(packageName)
141*35238bceSAndroid Build Coastguard Worker     , m_vendorTag(vendorTag)
142*35238bceSAndroid Build Coastguard Worker     , m_deviceTag(deviceTag)
143*35238bceSAndroid Build Coastguard Worker     , m_sessionInfo(sessionInfo)
144*35238bceSAndroid Build Coastguard Worker     , m_finalTree(waiverTree)
145*35238bceSAndroid Build Coastguard Worker {
146*35238bceSAndroid Build Coastguard Worker }
147*35238bceSAndroid Build Coastguard Worker 
~WaiverTreeBuilder()148*35238bceSAndroid Build Coastguard Worker WaiverTreeBuilder::~WaiverTreeBuilder()
149*35238bceSAndroid Build Coastguard Worker {
150*35238bceSAndroid Build Coastguard Worker }
151*35238bceSAndroid Build Coastguard Worker 
build(void)152*35238bceSAndroid Build Coastguard Worker void WaiverTreeBuilder::build(void)
153*35238bceSAndroid Build Coastguard Worker {
154*35238bceSAndroid Build Coastguard Worker     readWaivedTestsFromXML();
155*35238bceSAndroid Build Coastguard Worker     buildTreeFromPathList();
156*35238bceSAndroid Build Coastguard Worker     constructFinalTree();
157*35238bceSAndroid Build Coastguard Worker }
158*35238bceSAndroid Build Coastguard Worker 
readWaivedTestsFromXML()159*35238bceSAndroid Build Coastguard Worker void WaiverTreeBuilder::readWaivedTestsFromXML()
160*35238bceSAndroid Build Coastguard Worker {
161*35238bceSAndroid Build Coastguard Worker     std::ifstream iStream(m_waiverFile);
162*35238bceSAndroid Build Coastguard Worker     if (!iStream.is_open())
163*35238bceSAndroid Build Coastguard Worker         return;
164*35238bceSAndroid Build Coastguard Worker 
165*35238bceSAndroid Build Coastguard Worker     // get whole waiver file content
166*35238bceSAndroid Build Coastguard Worker     std::stringstream buffer;
167*35238bceSAndroid Build Coastguard Worker     buffer << iStream.rdbuf();
168*35238bceSAndroid Build Coastguard Worker     std::string wholeContent = buffer.str();
169*35238bceSAndroid Build Coastguard Worker 
170*35238bceSAndroid Build Coastguard Worker     // feed parser with xml content
171*35238bceSAndroid Build Coastguard Worker     xe::xml::Parser xmlParser;
172*35238bceSAndroid Build Coastguard Worker     xmlParser.feed(reinterpret_cast<const uint8_t *>(wholeContent.c_str()), static_cast<int>(wholeContent.size()));
173*35238bceSAndroid Build Coastguard Worker     xmlParser.advance();
174*35238bceSAndroid Build Coastguard Worker 
175*35238bceSAndroid Build Coastguard Worker     // first we find matching vendor, then search for matching device/renderer and then memorize cases
176*35238bceSAndroid Build Coastguard Worker     bool vendorFound  = false;
177*35238bceSAndroid Build Coastguard Worker     bool deviceFound  = false;
178*35238bceSAndroid Build Coastguard Worker     bool scanDevice   = false;
179*35238bceSAndroid Build Coastguard Worker     bool memorizeCase = false;
180*35238bceSAndroid Build Coastguard Worker     std::string waiverUrl;
181*35238bceSAndroid Build Coastguard Worker     std::vector<std::string> waiverTestList;
182*35238bceSAndroid Build Coastguard Worker 
183*35238bceSAndroid Build Coastguard Worker     while (true)
184*35238bceSAndroid Build Coastguard Worker     {
185*35238bceSAndroid Build Coastguard Worker         // we are grabing elements one by one - depth-first traversal in pre-order
186*35238bceSAndroid Build Coastguard Worker         xe::xml::Element currElement = xmlParser.getElement();
187*35238bceSAndroid Build Coastguard Worker 
188*35238bceSAndroid Build Coastguard Worker         // stop if there is parsing error or we didnt found
189*35238bceSAndroid Build Coastguard Worker         // waiver for current vendor id and device id/renderer
190*35238bceSAndroid Build Coastguard Worker         if (currElement == xe::xml::ELEMENT_INCOMPLETE || currElement == xe::xml::ELEMENT_END_OF_STRING)
191*35238bceSAndroid Build Coastguard Worker             break;
192*35238bceSAndroid Build Coastguard Worker 
193*35238bceSAndroid Build Coastguard Worker         const char *elemName = xmlParser.getElementName();
194*35238bceSAndroid Build Coastguard Worker         switch (currElement)
195*35238bceSAndroid Build Coastguard Worker         {
196*35238bceSAndroid Build Coastguard Worker         case xe::xml::ELEMENT_START:
197*35238bceSAndroid Build Coastguard Worker             if (vendorFound)
198*35238bceSAndroid Build Coastguard Worker             {
199*35238bceSAndroid Build Coastguard Worker                 if (!deviceFound)
200*35238bceSAndroid Build Coastguard Worker                 {
201*35238bceSAndroid Build Coastguard Worker                     // if we found proper vendor and are reading deviceIds/rendererers list then allow it
202*35238bceSAndroid Build Coastguard Worker                     scanDevice = deStringEqual(elemName, m_deviceTag); // e.g. "d"
203*35238bceSAndroid Build Coastguard Worker                     if (scanDevice)
204*35238bceSAndroid Build Coastguard Worker                         break;
205*35238bceSAndroid Build Coastguard Worker                 }
206*35238bceSAndroid Build Coastguard Worker 
207*35238bceSAndroid Build Coastguard Worker                 // if we found waiver for current vendor and are reading test case names then allow it
208*35238bceSAndroid Build Coastguard Worker                 memorizeCase = deStringEqual(elemName, "t");
209*35238bceSAndroid Build Coastguard Worker                 break;
210*35238bceSAndroid Build Coastguard Worker             }
211*35238bceSAndroid Build Coastguard Worker 
212*35238bceSAndroid Build Coastguard Worker             // we are searching for waiver definition for current vendor, till we find
213*35238bceSAndroid Build Coastguard Worker             // it we skip everythingh; we also skip tags that we don't need eg. description
214*35238bceSAndroid Build Coastguard Worker             if (!deStringEqual(elemName, "waiver"))
215*35238bceSAndroid Build Coastguard Worker                 break;
216*35238bceSAndroid Build Coastguard Worker 
217*35238bceSAndroid Build Coastguard Worker             // we found waiver tag, check if it is deffined for current vendor
218*35238bceSAndroid Build Coastguard Worker             waiverTestList.clear();
219*35238bceSAndroid Build Coastguard Worker             if (xmlParser.hasAttribute(m_vendorTag))
220*35238bceSAndroid Build Coastguard Worker             {
221*35238bceSAndroid Build Coastguard Worker                 vendorFound = matchVendor(xmlParser.getAttribute(m_vendorTag));
222*35238bceSAndroid Build Coastguard Worker                 // if waiver vendor matches current one then memorize waiver url
223*35238bceSAndroid Build Coastguard Worker                 // it will be needed when deviceId/renderer will match current one
224*35238bceSAndroid Build Coastguard Worker                 if (vendorFound)
225*35238bceSAndroid Build Coastguard Worker                     waiverUrl = xmlParser.getAttribute("url");
226*35238bceSAndroid Build Coastguard Worker             }
227*35238bceSAndroid Build Coastguard Worker             break;
228*35238bceSAndroid Build Coastguard Worker 
229*35238bceSAndroid Build Coastguard Worker         case xe::xml::ELEMENT_DATA:
230*35238bceSAndroid Build Coastguard Worker             if (scanDevice)
231*35238bceSAndroid Build Coastguard Worker             {
232*35238bceSAndroid Build Coastguard Worker                 // check if device read from xml matches current device/renderer
233*35238bceSAndroid Build Coastguard Worker                 std::string waivedDevice;
234*35238bceSAndroid Build Coastguard Worker                 xmlParser.getDataStr(waivedDevice);
235*35238bceSAndroid Build Coastguard Worker                 deviceFound = matchDevice(waivedDevice);
236*35238bceSAndroid Build Coastguard Worker             }
237*35238bceSAndroid Build Coastguard Worker             else if (memorizeCase)
238*35238bceSAndroid Build Coastguard Worker             {
239*35238bceSAndroid Build Coastguard Worker                 // memorize whats betwean <t></t> tags when case name starts with current package name
240*35238bceSAndroid Build Coastguard Worker                 // note: waiver tree is constructed per package
241*35238bceSAndroid Build Coastguard Worker                 std::string waivedCaseName;
242*35238bceSAndroid Build Coastguard Worker                 xmlParser.getDataStr(waivedCaseName);
243*35238bceSAndroid Build Coastguard Worker                 if (waivedCaseName.find(m_packageName) == 0)
244*35238bceSAndroid Build Coastguard Worker                     waiverTestList.push_back(waivedCaseName);
245*35238bceSAndroid Build Coastguard Worker             }
246*35238bceSAndroid Build Coastguard Worker             break;
247*35238bceSAndroid Build Coastguard Worker 
248*35238bceSAndroid Build Coastguard Worker         case xe::xml::ELEMENT_END:
249*35238bceSAndroid Build Coastguard Worker             memorizeCase = false;
250*35238bceSAndroid Build Coastguard Worker             scanDevice   = false;
251*35238bceSAndroid Build Coastguard Worker             if (deStringEqual(elemName, "waiver"))
252*35238bceSAndroid Build Coastguard Worker             {
253*35238bceSAndroid Build Coastguard Worker                 // when we found proper waiver we can copy memorized cases and update waiver info
254*35238bceSAndroid Build Coastguard Worker                 if (vendorFound && deviceFound)
255*35238bceSAndroid Build Coastguard Worker                 {
256*35238bceSAndroid Build Coastguard Worker                     DE_ASSERT(m_testList.empty() || waiverUrl.empty());
257*35238bceSAndroid Build Coastguard Worker 
258*35238bceSAndroid Build Coastguard Worker                     std::string &urls = m_sessionInfo.m_waiverUrls;
259*35238bceSAndroid Build Coastguard Worker                     m_testList.insert(m_testList.end(), waiverTestList.begin(), waiverTestList.end());
260*35238bceSAndroid Build Coastguard Worker 
261*35238bceSAndroid Build Coastguard Worker                     // if m_waiverUrls is not empty then we found another waiver
262*35238bceSAndroid Build Coastguard Worker                     // definition that should be applyed for this device; we need to
263*35238bceSAndroid Build Coastguard Worker                     // add space to urls attribute to separate new url from previous one
264*35238bceSAndroid Build Coastguard Worker                     if (!urls.empty())
265*35238bceSAndroid Build Coastguard Worker                         urls.append(" ");
266*35238bceSAndroid Build Coastguard Worker                     urls.append(waiverUrl);
267*35238bceSAndroid Build Coastguard Worker                 }
268*35238bceSAndroid Build Coastguard Worker                 vendorFound = false;
269*35238bceSAndroid Build Coastguard Worker                 deviceFound = false;
270*35238bceSAndroid Build Coastguard Worker             }
271*35238bceSAndroid Build Coastguard Worker             break;
272*35238bceSAndroid Build Coastguard Worker 
273*35238bceSAndroid Build Coastguard Worker         default:
274*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
275*35238bceSAndroid Build Coastguard Worker         }
276*35238bceSAndroid Build Coastguard Worker 
277*35238bceSAndroid Build Coastguard Worker         xmlParser.advance();
278*35238bceSAndroid Build Coastguard Worker     }
279*35238bceSAndroid Build Coastguard Worker }
280*35238bceSAndroid Build Coastguard Worker 
findComponentInBuildTree(const std::vector<std::string> & pathComponents,uint32_t index) const281*35238bceSAndroid Build Coastguard Worker uint32_t WaiverTreeBuilder::findComponentInBuildTree(const std::vector<std::string> &pathComponents,
282*35238bceSAndroid Build Coastguard Worker                                                      uint32_t index) const
283*35238bceSAndroid Build Coastguard Worker {
284*35238bceSAndroid Build Coastguard Worker     const std::string &checkedName = pathComponents[index];
285*35238bceSAndroid Build Coastguard Worker 
286*35238bceSAndroid Build Coastguard Worker     // check if same component is already in the build tree; we start from 1 - skiping root
287*35238bceSAndroid Build Coastguard Worker     for (uint32_t componentIndex = 1; componentIndex < m_buildTree.size(); ++componentIndex)
288*35238bceSAndroid Build Coastguard Worker     {
289*35238bceSAndroid Build Coastguard Worker         const BuilComponent &componentInTree = m_buildTree[componentIndex];
290*35238bceSAndroid Build Coastguard Worker         if (componentInTree.name != checkedName)
291*35238bceSAndroid Build Coastguard Worker             continue;
292*35238bceSAndroid Build Coastguard Worker 
293*35238bceSAndroid Build Coastguard Worker         // names match so we need to make sure that all their ancestors match too;
294*35238bceSAndroid Build Coastguard Worker         uint32_t reverseLevel        = index;
295*35238bceSAndroid Build Coastguard Worker         uint32_t ancestorInTreeIndex = componentInTree.parentIndex;
296*35238bceSAndroid Build Coastguard Worker 
297*35238bceSAndroid Build Coastguard Worker         // if this component is the next after root then there is no ancestors to check
298*35238bceSAndroid Build Coastguard Worker         if (reverseLevel == 1)
299*35238bceSAndroid Build Coastguard Worker             return componentIndex;
300*35238bceSAndroid Build Coastguard Worker 
301*35238bceSAndroid Build Coastguard Worker         while (--reverseLevel > 0)
302*35238bceSAndroid Build Coastguard Worker         {
303*35238bceSAndroid Build Coastguard Worker             // names dont match - we can move to searching other build tree items
304*35238bceSAndroid Build Coastguard Worker             if (pathComponents[reverseLevel] != m_buildTree[ancestorInTreeIndex].name)
305*35238bceSAndroid Build Coastguard Worker                 break;
306*35238bceSAndroid Build Coastguard Worker 
307*35238bceSAndroid Build Coastguard Worker             // when previous path component matches ancestor name then we need do check earlier path component
308*35238bceSAndroid Build Coastguard Worker             ancestorInTreeIndex = m_buildTree[ancestorInTreeIndex].parentIndex;
309*35238bceSAndroid Build Coastguard Worker 
310*35238bceSAndroid Build Coastguard Worker             // we reached root
311*35238bceSAndroid Build Coastguard Worker             if (ancestorInTreeIndex == 0)
312*35238bceSAndroid Build Coastguard Worker             {
313*35238bceSAndroid Build Coastguard Worker                 // if next level would be root then ancestors match
314*35238bceSAndroid Build Coastguard Worker                 if (reverseLevel == 1)
315*35238bceSAndroid Build Coastguard Worker                     return componentIndex;
316*35238bceSAndroid Build Coastguard Worker                 // if next level is not root then ancestors dont match
317*35238bceSAndroid Build Coastguard Worker                 break;
318*35238bceSAndroid Build Coastguard Worker             }
319*35238bceSAndroid Build Coastguard Worker         }
320*35238bceSAndroid Build Coastguard Worker     }
321*35238bceSAndroid Build Coastguard Worker 
322*35238bceSAndroid Build Coastguard Worker     // searched path component is not in the tree
323*35238bceSAndroid Build Coastguard Worker     return 0;
324*35238bceSAndroid Build Coastguard Worker }
325*35238bceSAndroid Build Coastguard Worker 
buildTreeFromPathList(void)326*35238bceSAndroid Build Coastguard Worker void WaiverTreeBuilder::buildTreeFromPathList(void)
327*35238bceSAndroid Build Coastguard Worker {
328*35238bceSAndroid Build Coastguard Worker     if (m_testList.empty())
329*35238bceSAndroid Build Coastguard Worker         return;
330*35238bceSAndroid Build Coastguard Worker 
331*35238bceSAndroid Build Coastguard Worker     uint32_t parentIndex = 0;
332*35238bceSAndroid Build Coastguard Worker 
333*35238bceSAndroid Build Coastguard Worker     // construct root node
334*35238bceSAndroid Build Coastguard Worker     m_buildTree.emplace_back("root", 0);
335*35238bceSAndroid Build Coastguard Worker 
336*35238bceSAndroid Build Coastguard Worker     for (const auto &path : m_testList)
337*35238bceSAndroid Build Coastguard Worker     {
338*35238bceSAndroid Build Coastguard Worker         const std::vector<std::string> pathComponents = de::splitString(path, '.');
339*35238bceSAndroid Build Coastguard Worker 
340*35238bceSAndroid Build Coastguard Worker         // first component is parented to root
341*35238bceSAndroid Build Coastguard Worker         parentIndex = 0;
342*35238bceSAndroid Build Coastguard Worker 
343*35238bceSAndroid Build Coastguard Worker         // iterate over all components of current path, but skip first one (e.g. "dEQP-VK", "KHR-GLES31")
344*35238bceSAndroid Build Coastguard Worker         for (uint32_t level = 1; level < pathComponents.size(); ++level)
345*35238bceSAndroid Build Coastguard Worker         {
346*35238bceSAndroid Build Coastguard Worker             // check if same component is already in the tree and we dont need to add it
347*35238bceSAndroid Build Coastguard Worker             uint32_t componentIndex = findComponentInBuildTree(pathComponents, level);
348*35238bceSAndroid Build Coastguard Worker             if (componentIndex)
349*35238bceSAndroid Build Coastguard Worker             {
350*35238bceSAndroid Build Coastguard Worker                 parentIndex = componentIndex;
351*35238bceSAndroid Build Coastguard Worker                 continue;
352*35238bceSAndroid Build Coastguard Worker             }
353*35238bceSAndroid Build Coastguard Worker 
354*35238bceSAndroid Build Coastguard Worker             // component is not in the tree, add it
355*35238bceSAndroid Build Coastguard Worker             const std::string componentName = pathComponents[level];
356*35238bceSAndroid Build Coastguard Worker             m_buildTree.emplace_back(componentName, parentIndex);
357*35238bceSAndroid Build Coastguard Worker 
358*35238bceSAndroid Build Coastguard Worker             // add current component as a child to its parent and assume
359*35238bceSAndroid Build Coastguard Worker             // that this component will be parent of next component
360*35238bceSAndroid Build Coastguard Worker             componentIndex = static_cast<uint32_t>(m_buildTree.size() - 1);
361*35238bceSAndroid Build Coastguard Worker             m_buildTree[parentIndex].childrenIndex.push_back(componentIndex);
362*35238bceSAndroid Build Coastguard Worker             parentIndex = componentIndex;
363*35238bceSAndroid Build Coastguard Worker         }
364*35238bceSAndroid Build Coastguard Worker     }
365*35238bceSAndroid Build Coastguard Worker }
366*35238bceSAndroid Build Coastguard Worker 
constructFinalTree(void)367*35238bceSAndroid Build Coastguard Worker void WaiverTreeBuilder::constructFinalTree(void)
368*35238bceSAndroid Build Coastguard Worker {
369*35238bceSAndroid Build Coastguard Worker     if (m_buildTree.empty())
370*35238bceSAndroid Build Coastguard Worker         return;
371*35238bceSAndroid Build Coastguard Worker 
372*35238bceSAndroid Build Coastguard Worker     // translate vector of BuilComponents to vector of WaiverComponents
373*35238bceSAndroid Build Coastguard Worker     m_finalTree.resize(m_buildTree.size());
374*35238bceSAndroid Build Coastguard Worker     for (uint32_t i = 0; i < m_finalTree.size(); ++i)
375*35238bceSAndroid Build Coastguard Worker     {
376*35238bceSAndroid Build Coastguard Worker         BuilComponent &buildCmponent     = m_buildTree[i];
377*35238bceSAndroid Build Coastguard Worker         WaiverComponent &waiverComponent = m_finalTree[i];
378*35238bceSAndroid Build Coastguard Worker 
379*35238bceSAndroid Build Coastguard Worker         waiverComponent.name = std::move(buildCmponent.name);
380*35238bceSAndroid Build Coastguard Worker         waiverComponent.children.resize(buildCmponent.childrenIndex.size());
381*35238bceSAndroid Build Coastguard Worker 
382*35238bceSAndroid Build Coastguard Worker         // set pointers for children
383*35238bceSAndroid Build Coastguard Worker         for (uint32_t j = 0; j < buildCmponent.childrenIndex.size(); ++j)
384*35238bceSAndroid Build Coastguard Worker         {
385*35238bceSAndroid Build Coastguard Worker             uint32_t childIndexInTree   = buildCmponent.childrenIndex[j];
386*35238bceSAndroid Build Coastguard Worker             waiverComponent.children[j] = &m_finalTree[childIndexInTree];
387*35238bceSAndroid Build Coastguard Worker         }
388*35238bceSAndroid Build Coastguard Worker     }
389*35238bceSAndroid Build Coastguard Worker }
390*35238bceSAndroid Build Coastguard Worker 
391*35238bceSAndroid Build Coastguard Worker // Class that builds a tree out of waiver definitions for OpenGL tests.
392*35238bceSAndroid Build Coastguard Worker // Most of functionalities are shared betwean VK and GL builders and they
393*35238bceSAndroid Build Coastguard Worker // were extracted to WaiverTreeBuilder base class.
394*35238bceSAndroid Build Coastguard Worker class GLWaiverTreeBuilder : public WaiverTreeBuilder
395*35238bceSAndroid Build Coastguard Worker {
396*35238bceSAndroid Build Coastguard Worker public:
397*35238bceSAndroid Build Coastguard Worker     GLWaiverTreeBuilder(const std::string &waiverFile, const std::string &packageName, const std::string &currentVendor,
398*35238bceSAndroid Build Coastguard Worker                         const std::string &currentRenderer, SessionInfo &sessionInfo,
399*35238bceSAndroid Build Coastguard Worker                         std::vector<WaiverComponent> &waiverTree);
400*35238bceSAndroid Build Coastguard Worker 
401*35238bceSAndroid Build Coastguard Worker     bool matchVendor(const std::string &vendor) const override;
402*35238bceSAndroid Build Coastguard Worker     bool matchDevice(const std::string &device) const override;
403*35238bceSAndroid Build Coastguard Worker 
404*35238bceSAndroid Build Coastguard Worker private:
405*35238bceSAndroid Build Coastguard Worker     const std::string m_currentVendor;
406*35238bceSAndroid Build Coastguard Worker     const std::string m_currentRenderer;
407*35238bceSAndroid Build Coastguard Worker };
408*35238bceSAndroid Build Coastguard Worker 
GLWaiverTreeBuilder(const std::string & waiverFile,const std::string & packageName,const std::string & currentVendor,const std::string & currentRenderer,SessionInfo & sessionInfo,std::vector<WaiverComponent> & waiverTree)409*35238bceSAndroid Build Coastguard Worker GLWaiverTreeBuilder::GLWaiverTreeBuilder(const std::string &waiverFile, const std::string &packageName,
410*35238bceSAndroid Build Coastguard Worker                                          const std::string &currentVendor, const std::string &currentRenderer,
411*35238bceSAndroid Build Coastguard Worker                                          SessionInfo &sessionInfo, std::vector<WaiverComponent> &waiverTree)
412*35238bceSAndroid Build Coastguard Worker     : WaiverTreeBuilder(waiverFile, packageName, "vendor", "r", sessionInfo, waiverTree)
413*35238bceSAndroid Build Coastguard Worker     , m_currentVendor(currentVendor)
414*35238bceSAndroid Build Coastguard Worker     , m_currentRenderer(currentRenderer)
415*35238bceSAndroid Build Coastguard Worker {
416*35238bceSAndroid Build Coastguard Worker }
417*35238bceSAndroid Build Coastguard Worker 
matchVendor(const std::string & vendor) const418*35238bceSAndroid Build Coastguard Worker bool GLWaiverTreeBuilder::matchVendor(const std::string &vendor) const
419*35238bceSAndroid Build Coastguard Worker {
420*35238bceSAndroid Build Coastguard Worker     return tcu::matchWildcards(vendor.cbegin(), vendor.cend(), m_currentVendor.cbegin(), m_currentVendor.cend(), false);
421*35238bceSAndroid Build Coastguard Worker }
422*35238bceSAndroid Build Coastguard Worker 
matchDevice(const std::string & device) const423*35238bceSAndroid Build Coastguard Worker bool GLWaiverTreeBuilder::matchDevice(const std::string &device) const
424*35238bceSAndroid Build Coastguard Worker {
425*35238bceSAndroid Build Coastguard Worker     // make sure that renderer name in .xml is not within "", those extra characters should be removed
426*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(device[0] != '\"');
427*35238bceSAndroid Build Coastguard Worker 
428*35238bceSAndroid Build Coastguard Worker     return tcu::matchWildcards(device.cbegin(), device.cend(), m_currentRenderer.cbegin(), m_currentRenderer.cend(),
429*35238bceSAndroid Build Coastguard Worker                                false);
430*35238bceSAndroid Build Coastguard Worker }
431*35238bceSAndroid Build Coastguard Worker 
432*35238bceSAndroid Build Coastguard Worker // Class that builds a tree out of waiver definitions for Vulkan tests.
433*35238bceSAndroid Build Coastguard Worker // Most of functionalities are shared betwean VK and GL builders and they
434*35238bceSAndroid Build Coastguard Worker // were extracted to WaiverTreeBuilder base class.
435*35238bceSAndroid Build Coastguard Worker class VKWaiverTreeBuilder : public WaiverTreeBuilder
436*35238bceSAndroid Build Coastguard Worker {
437*35238bceSAndroid Build Coastguard Worker public:
438*35238bceSAndroid Build Coastguard Worker     VKWaiverTreeBuilder(const std::string &waiverFile, const std::string &packageName, const uint32_t currentVendor,
439*35238bceSAndroid Build Coastguard Worker                         const uint32_t currentRenderer, SessionInfo &sessionInfo,
440*35238bceSAndroid Build Coastguard Worker                         std::vector<WaiverComponent> &waiverTree);
441*35238bceSAndroid Build Coastguard Worker 
442*35238bceSAndroid Build Coastguard Worker     bool matchVendor(const std::string &vendor) const override;
443*35238bceSAndroid Build Coastguard Worker     bool matchDevice(const std::string &device) const override;
444*35238bceSAndroid Build Coastguard Worker 
445*35238bceSAndroid Build Coastguard Worker private:
446*35238bceSAndroid Build Coastguard Worker     const uint32_t m_currentVendorId;
447*35238bceSAndroid Build Coastguard Worker     const uint32_t m_currentDeviceId;
448*35238bceSAndroid Build Coastguard Worker };
449*35238bceSAndroid Build Coastguard Worker 
VKWaiverTreeBuilder(const std::string & waiverFile,const std::string & packageName,const uint32_t currentVendor,const uint32_t currentRenderer,SessionInfo & sessionInfo,std::vector<WaiverComponent> & waiverTree)450*35238bceSAndroid Build Coastguard Worker VKWaiverTreeBuilder::VKWaiverTreeBuilder(const std::string &waiverFile, const std::string &packageName,
451*35238bceSAndroid Build Coastguard Worker                                          const uint32_t currentVendor, const uint32_t currentRenderer,
452*35238bceSAndroid Build Coastguard Worker                                          SessionInfo &sessionInfo, std::vector<WaiverComponent> &waiverTree)
453*35238bceSAndroid Build Coastguard Worker     : WaiverTreeBuilder(waiverFile, packageName, "vendorId", "d", sessionInfo, waiverTree)
454*35238bceSAndroid Build Coastguard Worker     , m_currentVendorId(currentVendor)
455*35238bceSAndroid Build Coastguard Worker     , m_currentDeviceId(currentRenderer)
456*35238bceSAndroid Build Coastguard Worker {
457*35238bceSAndroid Build Coastguard Worker }
458*35238bceSAndroid Build Coastguard Worker 
matchVendor(const std::string & vendor) const459*35238bceSAndroid Build Coastguard Worker bool VKWaiverTreeBuilder::matchVendor(const std::string &vendor) const
460*35238bceSAndroid Build Coastguard Worker {
461*35238bceSAndroid Build Coastguard Worker     return (m_currentVendorId == static_cast<uint32_t>(std::stoul(vendor, 0, 0)));
462*35238bceSAndroid Build Coastguard Worker }
463*35238bceSAndroid Build Coastguard Worker 
matchDevice(const std::string & device) const464*35238bceSAndroid Build Coastguard Worker bool VKWaiverTreeBuilder::matchDevice(const std::string &device) const
465*35238bceSAndroid Build Coastguard Worker {
466*35238bceSAndroid Build Coastguard Worker     return (m_currentDeviceId == static_cast<uint32_t>(std::stoul(device, 0, 0)));
467*35238bceSAndroid Build Coastguard Worker }
468*35238bceSAndroid Build Coastguard Worker 
setup(const std::string waiverFile,std::string packageName,uint32_t vendorId,uint32_t deviceId,SessionInfo & sessionInfo)469*35238bceSAndroid Build Coastguard Worker void WaiverUtil::setup(const std::string waiverFile, std::string packageName, uint32_t vendorId, uint32_t deviceId,
470*35238bceSAndroid Build Coastguard Worker                        SessionInfo &sessionInfo)
471*35238bceSAndroid Build Coastguard Worker {
472*35238bceSAndroid Build Coastguard Worker     VKWaiverTreeBuilder(waiverFile, packageName, vendorId, deviceId, sessionInfo, m_waiverTree).build();
473*35238bceSAndroid Build Coastguard Worker }
474*35238bceSAndroid Build Coastguard Worker 
setup(const std::string waiverFile,std::string packageName,std::string vendor,std::string renderer,SessionInfo & sessionInfo)475*35238bceSAndroid Build Coastguard Worker void WaiverUtil::setup(const std::string waiverFile, std::string packageName, std::string vendor, std::string renderer,
476*35238bceSAndroid Build Coastguard Worker                        SessionInfo &sessionInfo)
477*35238bceSAndroid Build Coastguard Worker {
478*35238bceSAndroid Build Coastguard Worker     GLWaiverTreeBuilder(waiverFile, packageName, vendor, renderer, sessionInfo, m_waiverTree).build();
479*35238bceSAndroid Build Coastguard Worker }
480*35238bceSAndroid Build Coastguard Worker 
isOnWaiverList(const std::string & casePath) const481*35238bceSAndroid Build Coastguard Worker bool WaiverUtil::isOnWaiverList(const std::string &casePath) const
482*35238bceSAndroid Build Coastguard Worker {
483*35238bceSAndroid Build Coastguard Worker     if (m_waiverTree.empty())
484*35238bceSAndroid Build Coastguard Worker         return false;
485*35238bceSAndroid Build Coastguard Worker 
486*35238bceSAndroid Build Coastguard Worker     // skip root e.g. "dEQP-VK"
487*35238bceSAndroid Build Coastguard Worker     size_t firstDotPos                         = casePath.find('.');
488*35238bceSAndroid Build Coastguard Worker     std::string::const_iterator componentStart = casePath.cbegin() + firstDotPos + 1;
489*35238bceSAndroid Build Coastguard Worker     std::string::const_iterator componentEnd   = componentStart;
490*35238bceSAndroid Build Coastguard Worker     std::string::const_iterator pathEnd        = casePath.cend();
491*35238bceSAndroid Build Coastguard Worker     const WaiverComponent *waiverComponent     = m_waiverTree.data();
492*35238bceSAndroid Build Coastguard Worker 
493*35238bceSAndroid Build Coastguard Worker     // check path component by component
494*35238bceSAndroid Build Coastguard Worker     while (true)
495*35238bceSAndroid Build Coastguard Worker     {
496*35238bceSAndroid Build Coastguard Worker         // find the last character of next component
497*35238bceSAndroid Build Coastguard Worker         ++componentEnd;
498*35238bceSAndroid Build Coastguard Worker         for (; componentEnd < pathEnd; ++componentEnd)
499*35238bceSAndroid Build Coastguard Worker         {
500*35238bceSAndroid Build Coastguard Worker             if (*componentEnd == '.')
501*35238bceSAndroid Build Coastguard Worker                 break;
502*35238bceSAndroid Build Coastguard Worker         }
503*35238bceSAndroid Build Coastguard Worker 
504*35238bceSAndroid Build Coastguard Worker         // check if one of children has the same component name
505*35238bceSAndroid Build Coastguard Worker         for (const auto &c : waiverComponent->children)
506*35238bceSAndroid Build Coastguard Worker         {
507*35238bceSAndroid Build Coastguard Worker             bool matchFound =
508*35238bceSAndroid Build Coastguard Worker                 tcu::matchWildcards(c->name.cbegin(), c->name.cend(), componentStart, componentEnd, false);
509*35238bceSAndroid Build Coastguard Worker 
510*35238bceSAndroid Build Coastguard Worker             // current waiver component matches curent path component - go to next component
511*35238bceSAndroid Build Coastguard Worker             if (matchFound)
512*35238bceSAndroid Build Coastguard Worker             {
513*35238bceSAndroid Build Coastguard Worker                 waiverComponent = c;
514*35238bceSAndroid Build Coastguard Worker                 break;
515*35238bceSAndroid Build Coastguard Worker             }
516*35238bceSAndroid Build Coastguard Worker         }
517*35238bceSAndroid Build Coastguard Worker 
518*35238bceSAndroid Build Coastguard Worker         // we checked all components - if our pattern was a leaf then this test should be waived
519*35238bceSAndroid Build Coastguard Worker         if (componentEnd == pathEnd)
520*35238bceSAndroid Build Coastguard Worker             return waiverComponent->children.empty();
521*35238bceSAndroid Build Coastguard Worker 
522*35238bceSAndroid Build Coastguard Worker         // go to next test path component
523*35238bceSAndroid Build Coastguard Worker         componentStart = componentEnd + 1;
524*35238bceSAndroid Build Coastguard Worker     }
525*35238bceSAndroid Build Coastguard Worker     return false;
526*35238bceSAndroid Build Coastguard Worker }
527*35238bceSAndroid Build Coastguard Worker 
528*35238bceSAndroid Build Coastguard Worker } // namespace tcu
529