Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/src/tests/deqp_support/tcuRandomOrderExecutor.cpp
1693 views
1
/*-------------------------------------------------------------------------
2
* drawElements Quality Program Tester Core
3
* ----------------------------------------
4
*
5
* Copyright 2014 The Android Open Source Project
6
*
7
* Licensed under the Apache License, Version 2.0 (the "License");
8
* you may not use this file except in compliance with the License.
9
* You may obtain a copy of the License at
10
*
11
* http://www.apache.org/licenses/LICENSE-2.0
12
*
13
* Unless required by applicable law or agreed to in writing, software
14
* distributed under the License is distributed on an "AS IS" BASIS,
15
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
* See the License for the specific language governing permissions and
17
* limitations under the License.
18
*
19
*//*!
20
* \file
21
* \brief Executor which can run randomly accessed tests.
22
*//*--------------------------------------------------------------------*/
23
24
#include "tcuRandomOrderExecutor.h"
25
26
#include "deClock.h"
27
#include "deStringUtil.hpp"
28
#include "tcuCommandLine.hpp"
29
#include "tcuTestLog.hpp"
30
31
#include <algorithm>
32
#include <cstdio>
33
#include <fstream>
34
35
using std::string;
36
using std::vector;
37
38
namespace tcu
39
{
40
41
RandomOrderExecutor::RandomOrderExecutor(TestPackageRoot &root,
42
TestContext &testCtx,
43
bool enableRenderDocCapture)
44
: m_testCtx(testCtx), m_inflater(testCtx)
45
{
46
m_nodeStack.push_back(NodeStackEntry(&root));
47
root.getChildren(m_nodeStack[0].children);
48
49
if (enableRenderDocCapture)
50
{
51
mRenderDoc.attach();
52
}
53
}
54
55
RandomOrderExecutor::~RandomOrderExecutor(void)
56
{
57
pruneStack(1);
58
}
59
60
void RandomOrderExecutor::pruneStack(size_t newStackSize)
61
{
62
// \note Root is not managed by us
63
DE_ASSERT(de::inRange(newStackSize, size_t(1), m_nodeStack.size()));
64
65
while (m_nodeStack.size() > newStackSize)
66
{
67
NodeStackEntry &curEntry = m_nodeStack.back();
68
const bool isPkg = curEntry.node->getNodeType() == NODETYPE_PACKAGE;
69
70
DE_ASSERT((m_nodeStack.size() == 2) == isPkg);
71
72
if (curEntry.node) // Just in case we are in
73
// cleanup path after partial
74
// prune
75
{
76
if (curEntry.node->getNodeType() == NODETYPE_GROUP)
77
m_inflater.leaveGroupNode(static_cast<TestCaseGroup *>(curEntry.node));
78
else if (curEntry.node->getNodeType() == NODETYPE_PACKAGE)
79
m_inflater.leaveTestPackage(static_cast<TestPackage *>(curEntry.node));
80
else
81
DE_ASSERT(curEntry.children.empty());
82
83
curEntry.node = DE_NULL;
84
curEntry.children.clear();
85
}
86
87
if (isPkg)
88
m_caseExecutor.clear();
89
90
m_nodeStack.pop_back();
91
}
92
}
93
94
static TestNode *findNodeByName(vector<TestNode *> &nodes, const std::string &name)
95
{
96
for (vector<TestNode *>::const_iterator node = nodes.begin(); node != nodes.end(); ++node)
97
{
98
if (name == (*node)->getName())
99
return *node;
100
}
101
102
return DE_NULL;
103
}
104
105
TestCase *RandomOrderExecutor::seekToCase(const string &path)
106
{
107
const vector<string> components = de::splitString(path, '.');
108
size_t compNdx;
109
110
DE_ASSERT(!m_nodeStack.empty() && m_nodeStack.front().node->getNodeType() == NODETYPE_ROOT);
111
112
for (compNdx = 0; compNdx < components.size(); compNdx++)
113
{
114
const size_t stackPos = compNdx + 1;
115
116
if (stackPos >= m_nodeStack.size())
117
break; // Stack end
118
else if (components[compNdx] != m_nodeStack[stackPos].node->getName())
119
{
120
// Current stack doesn't match any more, prune.
121
pruneStack(stackPos);
122
break;
123
}
124
}
125
126
DE_ASSERT(m_nodeStack.size() == compNdx + 1);
127
128
for (; compNdx < components.size(); compNdx++)
129
{
130
const size_t parentStackPos = compNdx;
131
TestNode *const curNode =
132
findNodeByName(m_nodeStack[parentStackPos].children, components[compNdx]);
133
134
if (!curNode)
135
throw Exception(string("Test hierarchy node not found: ") + path);
136
137
m_nodeStack.push_back(NodeStackEntry(curNode));
138
139
if (curNode->getNodeType() == NODETYPE_PACKAGE)
140
{
141
TestPackage *const testPackage = static_cast<TestPackage *>(curNode);
142
143
m_inflater.enterTestPackage(testPackage, m_nodeStack.back().children);
144
DE_ASSERT(!m_caseExecutor);
145
m_caseExecutor = de::MovePtr<TestCaseExecutor>(testPackage->createExecutor());
146
}
147
else if (curNode->getNodeType() == NODETYPE_GROUP)
148
m_inflater.enterGroupNode(static_cast<TestCaseGroup *>(curNode),
149
m_nodeStack.back().children);
150
else if (compNdx + 1 != components.size())
151
throw Exception(string("Invalid test hierarchy path: ") + path);
152
}
153
154
DE_ASSERT(m_nodeStack.size() == components.size() + 1);
155
156
if (isTestNodeTypeExecutable(m_nodeStack.back().node->getNodeType()))
157
return dynamic_cast<TestCase *>(m_nodeStack.back().node);
158
else
159
throw Exception(string("Not a test case: ") + path);
160
}
161
162
static qpTestCaseType nodeTypeToTestCaseType(TestNodeType nodeType)
163
{
164
switch (nodeType)
165
{
166
case NODETYPE_SELF_VALIDATE:
167
return QP_TEST_CASE_TYPE_SELF_VALIDATE;
168
case NODETYPE_PERFORMANCE:
169
return QP_TEST_CASE_TYPE_PERFORMANCE;
170
case NODETYPE_CAPABILITY:
171
return QP_TEST_CASE_TYPE_CAPABILITY;
172
case NODETYPE_ACCURACY:
173
return QP_TEST_CASE_TYPE_ACCURACY;
174
default:
175
DE_ASSERT(false);
176
return QP_TEST_CASE_TYPE_LAST;
177
}
178
}
179
180
TestStatus RandomOrderExecutor::execute(const std::string &casePath)
181
{
182
TestCase *const testCase = seekToCase(casePath);
183
TestLog &log = m_testCtx.getLog();
184
const qpTestCaseType caseType = nodeTypeToTestCaseType(testCase->getNodeType());
185
186
m_testCtx.setTerminateAfter(false);
187
log.startCase(casePath.c_str(), caseType);
188
189
{
190
const TestStatus result = executeInner(testCase, casePath);
191
log.endCase(result.getCode(), result.getDescription().c_str());
192
return result;
193
}
194
}
195
196
tcu::TestStatus RandomOrderExecutor::executeInner(TestCase *testCase, const std::string &casePath)
197
{
198
TestLog &log = m_testCtx.getLog();
199
const deUint64 testStartTime = deGetMicroseconds();
200
201
m_testCtx.setTestResult(QP_TEST_RESULT_LAST, "");
202
203
// Initialize, will return immediately if fails
204
try
205
{
206
mRenderDoc.startFrame();
207
m_caseExecutor->init(testCase, casePath);
208
}
209
catch (const std::bad_alloc &)
210
{
211
m_testCtx.setTerminateAfter(true);
212
return TestStatus(QP_TEST_RESULT_RESOURCE_ERROR,
213
"Failed to allocate memory in test case init");
214
}
215
catch (const TestException &e)
216
{
217
DE_ASSERT(e.getTestResult() != QP_TEST_RESULT_LAST);
218
m_testCtx.setTerminateAfter(e.isFatal());
219
log << e;
220
return TestStatus(e.getTestResult(), e.getMessage());
221
}
222
catch (const Exception &e)
223
{
224
log << e;
225
return TestStatus(QP_TEST_RESULT_FAIL, e.getMessage());
226
}
227
228
bool isFirstFrameBeingCaptured = true;
229
230
// Execute
231
for (;;)
232
{
233
TestCase::IterateResult iterateResult = TestCase::STOP;
234
235
m_testCtx.touchWatchdog();
236
237
try
238
{
239
// Make every iteration produce one renderdoc frame. Include the init code in the first
240
// frame, and the deinit code in the last frame.
241
if (!isFirstFrameBeingCaptured)
242
{
243
mRenderDoc.endFrame();
244
mRenderDoc.startFrame();
245
}
246
isFirstFrameBeingCaptured = false;
247
248
iterateResult = m_caseExecutor->iterate(testCase);
249
}
250
catch (const std::bad_alloc &)
251
{
252
m_testCtx.setTestResult(QP_TEST_RESULT_RESOURCE_ERROR,
253
"Failed to allocate memory during test "
254
"execution");
255
}
256
catch (const TestException &e)
257
{
258
log << e;
259
m_testCtx.setTestResult(e.getTestResult(), e.getMessage());
260
m_testCtx.setTerminateAfter(e.isFatal());
261
}
262
catch (const Exception &e)
263
{
264
log << e;
265
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, e.getMessage());
266
}
267
268
if (iterateResult == TestCase::STOP)
269
break;
270
}
271
272
DE_ASSERT(m_testCtx.getTestResult() != QP_TEST_RESULT_LAST);
273
274
if (m_testCtx.getTestResult() == QP_TEST_RESULT_RESOURCE_ERROR)
275
m_testCtx.setTerminateAfter(true);
276
277
// De-initialize
278
try
279
{
280
m_caseExecutor->deinit(testCase);
281
mRenderDoc.endFrame();
282
}
283
catch (const tcu::Exception &e)
284
{
285
log << e << TestLog::Message
286
<< "Error in test case deinit, test program "
287
"will terminate."
288
<< TestLog::EndMessage;
289
m_testCtx.setTerminateAfter(true);
290
}
291
292
if (m_testCtx.getWatchDog())
293
qpWatchDog_reset(m_testCtx.getWatchDog());
294
295
{
296
const TestStatus result =
297
TestStatus(m_testCtx.getTestResult(), m_testCtx.getTestResultDesc());
298
m_testCtx.setTestResult(QP_TEST_RESULT_LAST, "");
299
return result;
300
}
301
}
302
303
} // namespace tcu
304
305