xref: /aosp_15_r20/external/deqp/framework/qphelper/qpTestLog.c (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements TestLog Library
3*35238bceSAndroid Build Coastguard Worker  * ----------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
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 Test case result logging
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "qpTestLog.h"
25*35238bceSAndroid Build Coastguard Worker #include "qpXmlWriter.h"
26*35238bceSAndroid Build Coastguard Worker #include "qpInfo.h"
27*35238bceSAndroid Build Coastguard Worker #include "qpDebugOut.h"
28*35238bceSAndroid Build Coastguard Worker 
29*35238bceSAndroid Build Coastguard Worker #include "deMemory.h"
30*35238bceSAndroid Build Coastguard Worker #include "deInt32.h"
31*35238bceSAndroid Build Coastguard Worker #include "deString.h"
32*35238bceSAndroid Build Coastguard Worker 
33*35238bceSAndroid Build Coastguard Worker #include "deMutex.h"
34*35238bceSAndroid Build Coastguard Worker 
35*35238bceSAndroid Build Coastguard Worker #include "deClock.h"
36*35238bceSAndroid Build Coastguard Worker 
37*35238bceSAndroid Build Coastguard Worker #if defined(QP_SUPPORT_PNG)
38*35238bceSAndroid Build Coastguard Worker #include <png.h>
39*35238bceSAndroid Build Coastguard Worker #endif
40*35238bceSAndroid Build Coastguard Worker 
41*35238bceSAndroid Build Coastguard Worker #include <stdio.h>
42*35238bceSAndroid Build Coastguard Worker #include <stdlib.h>
43*35238bceSAndroid Build Coastguard Worker #include <stdarg.h>
44*35238bceSAndroid Build Coastguard Worker 
45*35238bceSAndroid Build Coastguard Worker #if (DE_OS == DE_OS_WIN32)
46*35238bceSAndroid Build Coastguard Worker #include <windows.h>
47*35238bceSAndroid Build Coastguard Worker #include <io.h>
48*35238bceSAndroid Build Coastguard Worker #endif
49*35238bceSAndroid Build Coastguard Worker 
50*35238bceSAndroid Build Coastguard Worker static uint64_t sessionStartTime;
51*35238bceSAndroid Build Coastguard Worker 
52*35238bceSAndroid Build Coastguard Worker #if defined(DE_DEBUG)
53*35238bceSAndroid Build Coastguard Worker 
54*35238bceSAndroid Build Coastguard Worker /* Utils for verifying container (Section, ImageSet, EglConfigSet) usage in debug builds. */
55*35238bceSAndroid Build Coastguard Worker 
56*35238bceSAndroid Build Coastguard Worker typedef enum ContainerType_e
57*35238bceSAndroid Build Coastguard Worker {
58*35238bceSAndroid Build Coastguard Worker     CONTAINERTYPE_SECTION = 0,
59*35238bceSAndroid Build Coastguard Worker     CONTAINERTYPE_IMAGESET,
60*35238bceSAndroid Build Coastguard Worker     CONTAINERTYPE_EGLCONFIGSET,
61*35238bceSAndroid Build Coastguard Worker     CONTAINERTYPE_SHADERPROGRAM,
62*35238bceSAndroid Build Coastguard Worker     CONTAINERTYPE_SAMPLELIST,
63*35238bceSAndroid Build Coastguard Worker     CONTAINERTYPE_SAMPLEINFO,
64*35238bceSAndroid Build Coastguard Worker     CONTAINERTYPE_SAMPLE,
65*35238bceSAndroid Build Coastguard Worker 
66*35238bceSAndroid Build Coastguard Worker     CONTAINERTYPE_LAST
67*35238bceSAndroid Build Coastguard Worker } ContainerType;
68*35238bceSAndroid Build Coastguard Worker 
childContainersOk(ContainerType type)69*35238bceSAndroid Build Coastguard Worker DE_INLINE bool childContainersOk(ContainerType type)
70*35238bceSAndroid Build Coastguard Worker {
71*35238bceSAndroid Build Coastguard Worker     return type == CONTAINERTYPE_SECTION || type == CONTAINERTYPE_SAMPLELIST;
72*35238bceSAndroid Build Coastguard Worker }
73*35238bceSAndroid Build Coastguard Worker 
74*35238bceSAndroid Build Coastguard Worker enum
75*35238bceSAndroid Build Coastguard Worker {
76*35238bceSAndroid Build Coastguard Worker     MAX_CONTAINER_STACK_DEPTH = 32
77*35238bceSAndroid Build Coastguard Worker };
78*35238bceSAndroid Build Coastguard Worker 
79*35238bceSAndroid Build Coastguard Worker typedef struct ContainerStack_s
80*35238bceSAndroid Build Coastguard Worker {
81*35238bceSAndroid Build Coastguard Worker     int numElements;
82*35238bceSAndroid Build Coastguard Worker     ContainerType elements[MAX_CONTAINER_STACK_DEPTH];
83*35238bceSAndroid Build Coastguard Worker } ContainerStack;
84*35238bceSAndroid Build Coastguard Worker 
ContainerStack_reset(ContainerStack * stack)85*35238bceSAndroid Build Coastguard Worker DE_INLINE void ContainerStack_reset(ContainerStack *stack)
86*35238bceSAndroid Build Coastguard Worker {
87*35238bceSAndroid Build Coastguard Worker     deMemset(stack, 0, sizeof(ContainerStack));
88*35238bceSAndroid Build Coastguard Worker }
89*35238bceSAndroid Build Coastguard Worker 
ContainerStack_isEmpty(const ContainerStack * stack)90*35238bceSAndroid Build Coastguard Worker DE_INLINE bool ContainerStack_isEmpty(const ContainerStack *stack)
91*35238bceSAndroid Build Coastguard Worker {
92*35238bceSAndroid Build Coastguard Worker     return stack->numElements == 0;
93*35238bceSAndroid Build Coastguard Worker }
94*35238bceSAndroid Build Coastguard Worker 
ContainerStack_push(ContainerStack * stack,ContainerType type)95*35238bceSAndroid Build Coastguard Worker DE_INLINE bool ContainerStack_push(ContainerStack *stack, ContainerType type)
96*35238bceSAndroid Build Coastguard Worker {
97*35238bceSAndroid Build Coastguard Worker     if (stack->numElements == MAX_CONTAINER_STACK_DEPTH)
98*35238bceSAndroid Build Coastguard Worker         return false;
99*35238bceSAndroid Build Coastguard Worker 
100*35238bceSAndroid Build Coastguard Worker     if (stack->numElements > 0 && !childContainersOk(stack->elements[stack->numElements - 1]))
101*35238bceSAndroid Build Coastguard Worker         return false;
102*35238bceSAndroid Build Coastguard Worker 
103*35238bceSAndroid Build Coastguard Worker     stack->elements[stack->numElements] = type;
104*35238bceSAndroid Build Coastguard Worker     stack->numElements += 1;
105*35238bceSAndroid Build Coastguard Worker 
106*35238bceSAndroid Build Coastguard Worker     return true;
107*35238bceSAndroid Build Coastguard Worker }
108*35238bceSAndroid Build Coastguard Worker 
ContainerStack_pop(ContainerStack * stack)109*35238bceSAndroid Build Coastguard Worker DE_INLINE ContainerType ContainerStack_pop(ContainerStack *stack)
110*35238bceSAndroid Build Coastguard Worker {
111*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(stack->numElements > 0);
112*35238bceSAndroid Build Coastguard Worker     stack->numElements -= 1;
113*35238bceSAndroid Build Coastguard Worker     return stack->elements[stack->numElements];
114*35238bceSAndroid Build Coastguard Worker }
115*35238bceSAndroid Build Coastguard Worker 
ContainerStack_getTop(const ContainerStack * stack)116*35238bceSAndroid Build Coastguard Worker DE_INLINE ContainerType ContainerStack_getTop(const ContainerStack *stack)
117*35238bceSAndroid Build Coastguard Worker {
118*35238bceSAndroid Build Coastguard Worker     if (stack->numElements > 0)
119*35238bceSAndroid Build Coastguard Worker         return stack->elements[stack->numElements - 1];
120*35238bceSAndroid Build Coastguard Worker     else
121*35238bceSAndroid Build Coastguard Worker         return CONTAINERTYPE_LAST;
122*35238bceSAndroid Build Coastguard Worker }
123*35238bceSAndroid Build Coastguard Worker 
124*35238bceSAndroid Build Coastguard Worker #endif
125*35238bceSAndroid Build Coastguard Worker 
126*35238bceSAndroid Build Coastguard Worker /* qpTestLog instance */
127*35238bceSAndroid Build Coastguard Worker struct qpTestLog_s
128*35238bceSAndroid Build Coastguard Worker {
129*35238bceSAndroid Build Coastguard Worker     uint32_t flags; /*!< Logging flags.                        */
130*35238bceSAndroid Build Coastguard Worker 
131*35238bceSAndroid Build Coastguard Worker     deMutex lock; /*!< Lock for mutable state below.        */
132*35238bceSAndroid Build Coastguard Worker 
133*35238bceSAndroid Build Coastguard Worker     /* State protected by lock. */
134*35238bceSAndroid Build Coastguard Worker     FILE *outputFile;
135*35238bceSAndroid Build Coastguard Worker     qpXmlWriter *writer;
136*35238bceSAndroid Build Coastguard Worker     bool isSessionOpen;
137*35238bceSAndroid Build Coastguard Worker     bool isCaseOpen;
138*35238bceSAndroid Build Coastguard Worker 
139*35238bceSAndroid Build Coastguard Worker #if defined(DE_DEBUG)
140*35238bceSAndroid Build Coastguard Worker     ContainerStack containerStack; /*!< For container usage verification.    */
141*35238bceSAndroid Build Coastguard Worker #endif
142*35238bceSAndroid Build Coastguard Worker };
143*35238bceSAndroid Build Coastguard Worker 
144*35238bceSAndroid Build Coastguard Worker /* Maps integer to string. */
145*35238bceSAndroid Build Coastguard Worker typedef struct qpKeyStringMap_s
146*35238bceSAndroid Build Coastguard Worker {
147*35238bceSAndroid Build Coastguard Worker     int key;
148*35238bceSAndroid Build Coastguard Worker     char *string;
149*35238bceSAndroid Build Coastguard Worker } qpKeyStringMap;
150*35238bceSAndroid Build Coastguard Worker 
151*35238bceSAndroid Build Coastguard Worker static const char *LOG_FORMAT_VERSION = "0.3.4";
152*35238bceSAndroid Build Coastguard Worker 
153*35238bceSAndroid Build Coastguard Worker /* Mapping enum to above strings... */
154*35238bceSAndroid Build Coastguard Worker static const qpKeyStringMap s_qpTestTypeMap[] = {{QP_TEST_CASE_TYPE_SELF_VALIDATE, "SelfValidate"},
155*35238bceSAndroid Build Coastguard Worker                                                  {QP_TEST_CASE_TYPE_PERFORMANCE, "Performance"},
156*35238bceSAndroid Build Coastguard Worker                                                  {QP_TEST_CASE_TYPE_CAPABILITY, "Capability"},
157*35238bceSAndroid Build Coastguard Worker                                                  {QP_TEST_CASE_TYPE_ACCURACY, "Accuracy"},
158*35238bceSAndroid Build Coastguard Worker 
159*35238bceSAndroid Build Coastguard Worker                                                  {QP_TEST_CASE_TYPE_LAST, DE_NULL}};
160*35238bceSAndroid Build Coastguard Worker 
161*35238bceSAndroid Build Coastguard Worker DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qpTestTypeMap) == QP_TEST_CASE_TYPE_LAST + 1);
162*35238bceSAndroid Build Coastguard Worker 
163*35238bceSAndroid Build Coastguard Worker static const qpKeyStringMap s_qpTestResultMap[] = {
164*35238bceSAndroid Build Coastguard Worker     {QP_TEST_RESULT_PASS, "Pass"},
165*35238bceSAndroid Build Coastguard Worker     {QP_TEST_RESULT_FAIL, "Fail"},
166*35238bceSAndroid Build Coastguard Worker     {QP_TEST_RESULT_QUALITY_WARNING, "QualityWarning"},
167*35238bceSAndroid Build Coastguard Worker     {QP_TEST_RESULT_COMPATIBILITY_WARNING, "CompatibilityWarning"},
168*35238bceSAndroid Build Coastguard Worker     {QP_TEST_RESULT_PENDING, "Pending"}, /* should not be needed here */
169*35238bceSAndroid Build Coastguard Worker     {QP_TEST_RESULT_NOT_SUPPORTED, "NotSupported"},
170*35238bceSAndroid Build Coastguard Worker     {QP_TEST_RESULT_RESOURCE_ERROR, "ResourceError"},
171*35238bceSAndroid Build Coastguard Worker     {QP_TEST_RESULT_INTERNAL_ERROR, "InternalError"},
172*35238bceSAndroid Build Coastguard Worker     {QP_TEST_RESULT_CRASH, "Crash"},
173*35238bceSAndroid Build Coastguard Worker     {QP_TEST_RESULT_TIMEOUT, "Timeout"},
174*35238bceSAndroid Build Coastguard Worker     {QP_TEST_RESULT_WAIVER, "Waiver"},
175*35238bceSAndroid Build Coastguard Worker     {QP_TEST_RESULT_DEVICE_LOST, "DeviceLost"},
176*35238bceSAndroid Build Coastguard Worker 
177*35238bceSAndroid Build Coastguard Worker     /* Add new values here if needed, remember to update qpTestResult enumeration. */
178*35238bceSAndroid Build Coastguard Worker 
179*35238bceSAndroid Build Coastguard Worker     {QP_TEST_RESULT_LAST, DE_NULL}};
180*35238bceSAndroid Build Coastguard Worker 
181*35238bceSAndroid Build Coastguard Worker DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qpTestResultMap) == QP_TEST_RESULT_LAST + 1);
182*35238bceSAndroid Build Coastguard Worker 
183*35238bceSAndroid Build Coastguard Worker /* Key tag to string mapping. */
184*35238bceSAndroid Build Coastguard Worker 
185*35238bceSAndroid Build Coastguard Worker static const qpKeyStringMap s_qpTagMap[] = {{QP_KEY_TAG_NONE, DE_NULL},      {QP_KEY_TAG_PERFORMANCE, "Performance"},
186*35238bceSAndroid Build Coastguard Worker                                             {QP_KEY_TAG_QUALITY, "Quality"}, {QP_KEY_TAG_PRECISION, "Precision"},
187*35238bceSAndroid Build Coastguard Worker                                             {QP_KEY_TAG_TIME, "Time"},
188*35238bceSAndroid Build Coastguard Worker 
189*35238bceSAndroid Build Coastguard Worker                                             {QP_KEY_TAG_LAST, DE_NULL}};
190*35238bceSAndroid Build Coastguard Worker 
191*35238bceSAndroid Build Coastguard Worker DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qpTagMap) == QP_KEY_TAG_LAST + 1);
192*35238bceSAndroid Build Coastguard Worker 
193*35238bceSAndroid Build Coastguard Worker /* Sample value tag to string mapping. */
194*35238bceSAndroid Build Coastguard Worker 
195*35238bceSAndroid Build Coastguard Worker static const qpKeyStringMap s_qpSampleValueTagMap[] = {{QP_SAMPLE_VALUE_TAG_PREDICTOR, "Predictor"},
196*35238bceSAndroid Build Coastguard Worker                                                        {QP_SAMPLE_VALUE_TAG_RESPONSE, "Response"},
197*35238bceSAndroid Build Coastguard Worker 
198*35238bceSAndroid Build Coastguard Worker                                                        {QP_SAMPLE_VALUE_TAG_LAST, DE_NULL}};
199*35238bceSAndroid Build Coastguard Worker 
200*35238bceSAndroid Build Coastguard Worker DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qpSampleValueTagMap) == QP_SAMPLE_VALUE_TAG_LAST + 1);
201*35238bceSAndroid Build Coastguard Worker 
202*35238bceSAndroid Build Coastguard Worker /* Image compression mode to string mapping. */
203*35238bceSAndroid Build Coastguard Worker 
204*35238bceSAndroid Build Coastguard Worker static const qpKeyStringMap s_qpImageCompressionModeMap[] = {
205*35238bceSAndroid Build Coastguard Worker     {QP_IMAGE_COMPRESSION_MODE_NONE, "None"},
206*35238bceSAndroid Build Coastguard Worker     {QP_IMAGE_COMPRESSION_MODE_PNG, "PNG"},
207*35238bceSAndroid Build Coastguard Worker 
208*35238bceSAndroid Build Coastguard Worker     {QP_IMAGE_COMPRESSION_MODE_BEST, DE_NULL}, /* not allowed to be written! */
209*35238bceSAndroid Build Coastguard Worker 
210*35238bceSAndroid Build Coastguard Worker     {QP_IMAGE_COMPRESSION_MODE_LAST, DE_NULL}};
211*35238bceSAndroid Build Coastguard Worker 
212*35238bceSAndroid Build Coastguard Worker DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qpImageCompressionModeMap) == QP_IMAGE_COMPRESSION_MODE_LAST + 1);
213*35238bceSAndroid Build Coastguard Worker 
214*35238bceSAndroid Build Coastguard Worker /* Image format to string mapping. */
215*35238bceSAndroid Build Coastguard Worker 
216*35238bceSAndroid Build Coastguard Worker static const qpKeyStringMap s_qpImageFormatMap[] = {{QP_IMAGE_FORMAT_RGB888, "RGB888"},
217*35238bceSAndroid Build Coastguard Worker                                                     {QP_IMAGE_FORMAT_RGBA8888, "RGBA8888"},
218*35238bceSAndroid Build Coastguard Worker 
219*35238bceSAndroid Build Coastguard Worker                                                     {QP_IMAGE_FORMAT_LAST, DE_NULL}};
220*35238bceSAndroid Build Coastguard Worker 
221*35238bceSAndroid Build Coastguard Worker DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qpImageFormatMap) == QP_IMAGE_FORMAT_LAST + 1);
222*35238bceSAndroid Build Coastguard Worker 
223*35238bceSAndroid Build Coastguard Worker /* Shader type to string mapping. */
224*35238bceSAndroid Build Coastguard Worker 
225*35238bceSAndroid Build Coastguard Worker static const qpKeyStringMap s_qpShaderTypeMap[] = {{QP_SHADER_TYPE_VERTEX, "VertexShader"},
226*35238bceSAndroid Build Coastguard Worker                                                    {QP_SHADER_TYPE_FRAGMENT, "FragmentShader"},
227*35238bceSAndroid Build Coastguard Worker                                                    {QP_SHADER_TYPE_GEOMETRY, "GeometryShader"},
228*35238bceSAndroid Build Coastguard Worker                                                    {QP_SHADER_TYPE_TESS_CONTROL, "TessControlShader"},
229*35238bceSAndroid Build Coastguard Worker                                                    {QP_SHADER_TYPE_TESS_EVALUATION, "TessEvaluationShader"},
230*35238bceSAndroid Build Coastguard Worker                                                    {QP_SHADER_TYPE_COMPUTE, "ComputeShader"},
231*35238bceSAndroid Build Coastguard Worker                                                    {QP_SHADER_TYPE_RAYGEN, "RaygenShader"},
232*35238bceSAndroid Build Coastguard Worker                                                    {QP_SHADER_TYPE_ANY_HIT, "AnyHitShader"},
233*35238bceSAndroid Build Coastguard Worker                                                    {QP_SHADER_TYPE_CLOSEST_HIT, "ClosestHitShader"},
234*35238bceSAndroid Build Coastguard Worker                                                    {QP_SHADER_TYPE_MISS, "MissShader"},
235*35238bceSAndroid Build Coastguard Worker                                                    {QP_SHADER_TYPE_INTERSECTION, "IntersectionShader"},
236*35238bceSAndroid Build Coastguard Worker                                                    {QP_SHADER_TYPE_CALLABLE, "CallableShader"},
237*35238bceSAndroid Build Coastguard Worker                                                    {QP_SHADER_TYPE_TASK, "TaskShader"},
238*35238bceSAndroid Build Coastguard Worker                                                    {QP_SHADER_TYPE_MESH, "MeshShader"},
239*35238bceSAndroid Build Coastguard Worker 
240*35238bceSAndroid Build Coastguard Worker                                                    {QP_SHADER_TYPE_LAST, DE_NULL}};
241*35238bceSAndroid Build Coastguard Worker 
242*35238bceSAndroid Build Coastguard Worker DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qpShaderTypeMap) == QP_SHADER_TYPE_LAST + 1);
243*35238bceSAndroid Build Coastguard Worker 
qpTestLog_flushFile(qpTestLog * log)244*35238bceSAndroid Build Coastguard Worker static void qpTestLog_flushFile(qpTestLog *log)
245*35238bceSAndroid Build Coastguard Worker {
246*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log && log->outputFile);
247*35238bceSAndroid Build Coastguard Worker     fflush(log->outputFile);
248*35238bceSAndroid Build Coastguard Worker #if (DE_OS == DE_OS_WIN32) && (DE_COMPILER == DE_COMPILER_MSC)
249*35238bceSAndroid Build Coastguard Worker     /* \todo [petri] Is this really necessary? */
250*35238bceSAndroid Build Coastguard Worker     FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(log->outputFile)));
251*35238bceSAndroid Build Coastguard Worker #endif
252*35238bceSAndroid Build Coastguard Worker }
253*35238bceSAndroid Build Coastguard Worker 
254*35238bceSAndroid Build Coastguard Worker #define QP_LOOKUP_STRING(KEYMAP, KEY) qpLookupString(KEYMAP, DE_LENGTH_OF_ARRAY(KEYMAP), (int)(KEY))
255*35238bceSAndroid Build Coastguard Worker 
qpLookupString(const qpKeyStringMap * keyMap,int keyMapSize,int key)256*35238bceSAndroid Build Coastguard Worker static const char *qpLookupString(const qpKeyStringMap *keyMap, int keyMapSize, int key)
257*35238bceSAndroid Build Coastguard Worker {
258*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(keyMap);
259*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(deInBounds32(key, 0, keyMapSize - 1)); /* Last element in map is assumed to be terminator */
260*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(keyMap[keyMapSize - 1].string ==
261*35238bceSAndroid Build Coastguard Worker               DE_NULL); /* Ensure map is properly completed, *_LAST element is not missing */
262*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(keyMap[key].key == key);
263*35238bceSAndroid Build Coastguard Worker     DE_UNREF(keyMapSize); /* for asserting only */
264*35238bceSAndroid Build Coastguard Worker     return keyMap[key].string;
265*35238bceSAndroid Build Coastguard Worker }
266*35238bceSAndroid Build Coastguard Worker 
int32ToString(int val,char buf[32])267*35238bceSAndroid Build Coastguard Worker DE_INLINE void int32ToString(int val, char buf[32])
268*35238bceSAndroid Build Coastguard Worker {
269*35238bceSAndroid Build Coastguard Worker     deSprintf(&buf[0], 32, "%d", val);
270*35238bceSAndroid Build Coastguard Worker }
271*35238bceSAndroid Build Coastguard Worker 
int64ToString(int64_t val,char buf[32])272*35238bceSAndroid Build Coastguard Worker DE_INLINE void int64ToString(int64_t val, char buf[32])
273*35238bceSAndroid Build Coastguard Worker {
274*35238bceSAndroid Build Coastguard Worker     deSprintf(&buf[0], 32, "%lld", (long long int)val);
275*35238bceSAndroid Build Coastguard Worker }
276*35238bceSAndroid Build Coastguard Worker 
floatToString(float value,char * buf,size_t bufSize)277*35238bceSAndroid Build Coastguard Worker DE_INLINE void floatToString(float value, char *buf, size_t bufSize)
278*35238bceSAndroid Build Coastguard Worker {
279*35238bceSAndroid Build Coastguard Worker     deSprintf(buf, bufSize, "%f", value);
280*35238bceSAndroid Build Coastguard Worker }
281*35238bceSAndroid Build Coastguard Worker 
doubleToString(double value,char * buf,size_t bufSize)282*35238bceSAndroid Build Coastguard Worker DE_INLINE void doubleToString(double value, char *buf, size_t bufSize)
283*35238bceSAndroid Build Coastguard Worker {
284*35238bceSAndroid Build Coastguard Worker     deSprintf(buf, bufSize, "%f", value);
285*35238bceSAndroid Build Coastguard Worker }
286*35238bceSAndroid Build Coastguard Worker 
endSession(qpTestLog * log)287*35238bceSAndroid Build Coastguard Worker static bool endSession(qpTestLog *log)
288*35238bceSAndroid Build Coastguard Worker {
289*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log && log->isSessionOpen);
290*35238bceSAndroid Build Coastguard Worker 
291*35238bceSAndroid Build Coastguard Worker     /* Make sure xml is flushed. */
292*35238bceSAndroid Build Coastguard Worker     qpXmlWriter_flush(log->writer);
293*35238bceSAndroid Build Coastguard Worker 
294*35238bceSAndroid Build Coastguard Worker     uint64_t duration = deGetMicroseconds() - sessionStartTime;
295*35238bceSAndroid Build Coastguard Worker 
296*35238bceSAndroid Build Coastguard Worker     fprintf(log->outputFile, "\nRun took %.2f seconds\n", (float)duration / 1000000.0f);
297*35238bceSAndroid Build Coastguard Worker 
298*35238bceSAndroid Build Coastguard Worker     /* Write out #endSession. */
299*35238bceSAndroid Build Coastguard Worker     fprintf(log->outputFile, "\n#endSession\n");
300*35238bceSAndroid Build Coastguard Worker     qpTestLog_flushFile(log);
301*35238bceSAndroid Build Coastguard Worker 
302*35238bceSAndroid Build Coastguard Worker     log->isSessionOpen = false;
303*35238bceSAndroid Build Coastguard Worker 
304*35238bceSAndroid Build Coastguard Worker     return true;
305*35238bceSAndroid Build Coastguard Worker }
306*35238bceSAndroid Build Coastguard Worker 
307*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
308*35238bceSAndroid Build Coastguard Worker  * \brief Create a file based logger instance
309*35238bceSAndroid Build Coastguard Worker  * \param fileName Name of the file where to put logs
310*35238bceSAndroid Build Coastguard Worker  * \return qpTestLog instance, or DE_NULL if cannot create file
311*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_createFileLog(const char * fileName,uint32_t flags)312*35238bceSAndroid Build Coastguard Worker qpTestLog *qpTestLog_createFileLog(const char *fileName, uint32_t flags)
313*35238bceSAndroid Build Coastguard Worker {
314*35238bceSAndroid Build Coastguard Worker     qpTestLog *log = (qpTestLog *)deCalloc(sizeof(qpTestLog));
315*35238bceSAndroid Build Coastguard Worker     if (!log)
316*35238bceSAndroid Build Coastguard Worker         return DE_NULL;
317*35238bceSAndroid Build Coastguard Worker 
318*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(fileName && fileName[0]); /* must have filename. */
319*35238bceSAndroid Build Coastguard Worker 
320*35238bceSAndroid Build Coastguard Worker #if defined(DE_DEBUG)
321*35238bceSAndroid Build Coastguard Worker     ContainerStack_reset(&log->containerStack);
322*35238bceSAndroid Build Coastguard Worker #endif
323*35238bceSAndroid Build Coastguard Worker 
324*35238bceSAndroid Build Coastguard Worker     if (!(flags & QP_TEST_LOG_NO_INITIAL_OUTPUT))
325*35238bceSAndroid Build Coastguard Worker         qpPrintf("Writing test log into %s\n", fileName);
326*35238bceSAndroid Build Coastguard Worker 
327*35238bceSAndroid Build Coastguard Worker     /* Create output file. */
328*35238bceSAndroid Build Coastguard Worker     log->outputFile = fopen(fileName, "wb");
329*35238bceSAndroid Build Coastguard Worker     if (!log->outputFile)
330*35238bceSAndroid Build Coastguard Worker     {
331*35238bceSAndroid Build Coastguard Worker         qpPrintf("ERROR: Unable to open test log output file '%s'.\n", fileName);
332*35238bceSAndroid Build Coastguard Worker         qpTestLog_destroy(log);
333*35238bceSAndroid Build Coastguard Worker         return DE_NULL;
334*35238bceSAndroid Build Coastguard Worker     }
335*35238bceSAndroid Build Coastguard Worker 
336*35238bceSAndroid Build Coastguard Worker     log->flags         = flags;
337*35238bceSAndroid Build Coastguard Worker     log->writer        = qpXmlWriter_createFileWriter(log->outputFile, 0, !(flags & QP_TEST_LOG_NO_FLUSH));
338*35238bceSAndroid Build Coastguard Worker     log->lock          = deMutex_create(DE_NULL);
339*35238bceSAndroid Build Coastguard Worker     log->isSessionOpen = false;
340*35238bceSAndroid Build Coastguard Worker     log->isCaseOpen    = false;
341*35238bceSAndroid Build Coastguard Worker 
342*35238bceSAndroid Build Coastguard Worker     if (!log->writer)
343*35238bceSAndroid Build Coastguard Worker     {
344*35238bceSAndroid Build Coastguard Worker         qpPrintf("ERROR: Unable to create output XML writer to file '%s'.\n", fileName);
345*35238bceSAndroid Build Coastguard Worker         qpTestLog_destroy(log);
346*35238bceSAndroid Build Coastguard Worker         return DE_NULL;
347*35238bceSAndroid Build Coastguard Worker     }
348*35238bceSAndroid Build Coastguard Worker 
349*35238bceSAndroid Build Coastguard Worker     if (!log->lock)
350*35238bceSAndroid Build Coastguard Worker     {
351*35238bceSAndroid Build Coastguard Worker         qpPrintf("ERROR: Unable to create mutex.\n");
352*35238bceSAndroid Build Coastguard Worker         qpTestLog_destroy(log);
353*35238bceSAndroid Build Coastguard Worker         return DE_NULL;
354*35238bceSAndroid Build Coastguard Worker     }
355*35238bceSAndroid Build Coastguard Worker 
356*35238bceSAndroid Build Coastguard Worker     return log;
357*35238bceSAndroid Build Coastguard Worker }
358*35238bceSAndroid Build Coastguard Worker 
359*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
360*35238bceSAndroid Build Coastguard Worker  * \brief Log information about test session
361*35238bceSAndroid Build Coastguard Worker  * \param log qpTestLog instance
362*35238bceSAndroid Build Coastguard Worker  * \param additionalSessionInfo string contatining additional sessionInfo data
363*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_beginSession(qpTestLog * log,const char * additionalSessionInfo)364*35238bceSAndroid Build Coastguard Worker bool qpTestLog_beginSession(qpTestLog *log, const char *additionalSessionInfo)
365*35238bceSAndroid Build Coastguard Worker {
366*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log);
367*35238bceSAndroid Build Coastguard Worker 
368*35238bceSAndroid Build Coastguard Worker     /* Make sure this function is called once*/
369*35238bceSAndroid Build Coastguard Worker     if (log->isSessionOpen)
370*35238bceSAndroid Build Coastguard Worker         return true;
371*35238bceSAndroid Build Coastguard Worker 
372*35238bceSAndroid Build Coastguard Worker     /* Write session info. */
373*35238bceSAndroid Build Coastguard Worker     fprintf(log->outputFile, "#sessionInfo releaseName %s\n", qpGetReleaseName());
374*35238bceSAndroid Build Coastguard Worker     fprintf(log->outputFile, "#sessionInfo releaseId 0x%08x\n", qpGetReleaseId());
375*35238bceSAndroid Build Coastguard Worker     fprintf(log->outputFile, "#sessionInfo targetName \"%s\"\n", qpGetTargetName());
376*35238bceSAndroid Build Coastguard Worker     char *compactStr = "";
377*35238bceSAndroid Build Coastguard Worker     if (qpTestLog_isCompact(log))
378*35238bceSAndroid Build Coastguard Worker     {
379*35238bceSAndroid Build Coastguard Worker         compactStr = "-compact";
380*35238bceSAndroid Build Coastguard Worker     }
381*35238bceSAndroid Build Coastguard Worker     fprintf(log->outputFile, "#sessionInfo logFormatVersion \"%s%s\"\n", LOG_FORMAT_VERSION, compactStr);
382*35238bceSAndroid Build Coastguard Worker 
383*35238bceSAndroid Build Coastguard Worker     if (strlen(additionalSessionInfo) > 1)
384*35238bceSAndroid Build Coastguard Worker         fprintf(log->outputFile, "%s\n", additionalSessionInfo);
385*35238bceSAndroid Build Coastguard Worker 
386*35238bceSAndroid Build Coastguard Worker     /* Write out #beginSession. */
387*35238bceSAndroid Build Coastguard Worker     fprintf(log->outputFile, "#beginSession\n");
388*35238bceSAndroid Build Coastguard Worker     qpTestLog_flushFile(log);
389*35238bceSAndroid Build Coastguard Worker     sessionStartTime = deGetMicroseconds();
390*35238bceSAndroid Build Coastguard Worker 
391*35238bceSAndroid Build Coastguard Worker     log->isSessionOpen = true;
392*35238bceSAndroid Build Coastguard Worker 
393*35238bceSAndroid Build Coastguard Worker     return true;
394*35238bceSAndroid Build Coastguard Worker }
395*35238bceSAndroid Build Coastguard Worker 
396*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
397*35238bceSAndroid Build Coastguard Worker  * \brief Destroy a logger instance
398*35238bceSAndroid Build Coastguard Worker  * \param log qpTestLog instance
399*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_destroy(qpTestLog * log)400*35238bceSAndroid Build Coastguard Worker void qpTestLog_destroy(qpTestLog *log)
401*35238bceSAndroid Build Coastguard Worker {
402*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log);
403*35238bceSAndroid Build Coastguard Worker 
404*35238bceSAndroid Build Coastguard Worker     if (log->isSessionOpen)
405*35238bceSAndroid Build Coastguard Worker         endSession(log);
406*35238bceSAndroid Build Coastguard Worker 
407*35238bceSAndroid Build Coastguard Worker     if (log->writer)
408*35238bceSAndroid Build Coastguard Worker         qpXmlWriter_destroy(log->writer);
409*35238bceSAndroid Build Coastguard Worker 
410*35238bceSAndroid Build Coastguard Worker     if (log->outputFile)
411*35238bceSAndroid Build Coastguard Worker         fclose(log->outputFile);
412*35238bceSAndroid Build Coastguard Worker 
413*35238bceSAndroid Build Coastguard Worker     if (log->lock)
414*35238bceSAndroid Build Coastguard Worker         deMutex_destroy(log->lock);
415*35238bceSAndroid Build Coastguard Worker 
416*35238bceSAndroid Build Coastguard Worker     deFree(log);
417*35238bceSAndroid Build Coastguard Worker }
418*35238bceSAndroid Build Coastguard Worker 
419*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
420*35238bceSAndroid Build Coastguard Worker  * \brief Log start of test case
421*35238bceSAndroid Build Coastguard Worker  * \param log qpTestLog instance
422*35238bceSAndroid Build Coastguard Worker  * \param testCasePath    Full test case path (as seen in Candy).
423*35238bceSAndroid Build Coastguard Worker  * \param testCaseType    Test case type
424*35238bceSAndroid Build Coastguard Worker  * \return true if ok, false otherwise
425*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_startCase(qpTestLog * log,const char * testCasePath,qpTestCaseType testCaseType)426*35238bceSAndroid Build Coastguard Worker bool qpTestLog_startCase(qpTestLog *log, const char *testCasePath, qpTestCaseType testCaseType)
427*35238bceSAndroid Build Coastguard Worker {
428*35238bceSAndroid Build Coastguard Worker     const char *typeStr  = QP_LOOKUP_STRING(s_qpTestTypeMap, testCaseType);
429*35238bceSAndroid Build Coastguard Worker     int numResultAttribs = 0;
430*35238bceSAndroid Build Coastguard Worker     qpXmlAttribute resultAttribs[8];
431*35238bceSAndroid Build Coastguard Worker 
432*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log && testCasePath && (testCasePath[0] != 0));
433*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
434*35238bceSAndroid Build Coastguard Worker 
435*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!log->isCaseOpen);
436*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(ContainerStack_isEmpty(&log->containerStack));
437*35238bceSAndroid Build Coastguard Worker 
438*35238bceSAndroid Build Coastguard Worker     /* Flush XML and write out #beginTestCaseResult. */
439*35238bceSAndroid Build Coastguard Worker     qpXmlWriter_flush(log->writer);
440*35238bceSAndroid Build Coastguard Worker     if (!qpTestLog_isCompact(log))
441*35238bceSAndroid Build Coastguard Worker     {
442*35238bceSAndroid Build Coastguard Worker         fprintf(log->outputFile, "\n#beginTestCaseResult %s\n", testCasePath);
443*35238bceSAndroid Build Coastguard Worker     }
444*35238bceSAndroid Build Coastguard Worker     if (!(log->flags & QP_TEST_LOG_NO_FLUSH))
445*35238bceSAndroid Build Coastguard Worker         qpTestLog_flushFile(log);
446*35238bceSAndroid Build Coastguard Worker 
447*35238bceSAndroid Build Coastguard Worker     log->isCaseOpen = true;
448*35238bceSAndroid Build Coastguard Worker 
449*35238bceSAndroid Build Coastguard Worker     /* Fill in attributes. */
450*35238bceSAndroid Build Coastguard Worker     resultAttribs[numResultAttribs++] = qpSetStringAttrib("CasePath", testCasePath);
451*35238bceSAndroid Build Coastguard Worker     if (!qpTestLog_isCompact(log))
452*35238bceSAndroid Build Coastguard Worker     {
453*35238bceSAndroid Build Coastguard Worker         resultAttribs[numResultAttribs++] = qpSetStringAttrib("Version", LOG_FORMAT_VERSION);
454*35238bceSAndroid Build Coastguard Worker         resultAttribs[numResultAttribs++] = qpSetStringAttrib("CaseType", typeStr);
455*35238bceSAndroid Build Coastguard Worker     }
456*35238bceSAndroid Build Coastguard Worker 
457*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_startDocument(log->writer, !qpTestLog_isCompact(log)) ||
458*35238bceSAndroid Build Coastguard Worker         !qpXmlWriter_startElement(log->writer, "TestCaseResult", numResultAttribs, resultAttribs))
459*35238bceSAndroid Build Coastguard Worker     {
460*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_startCase(): Writing XML failed\n");
461*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
462*35238bceSAndroid Build Coastguard Worker         return false;
463*35238bceSAndroid Build Coastguard Worker     }
464*35238bceSAndroid Build Coastguard Worker 
465*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
466*35238bceSAndroid Build Coastguard Worker     return true;
467*35238bceSAndroid Build Coastguard Worker }
468*35238bceSAndroid Build Coastguard Worker 
469*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
470*35238bceSAndroid Build Coastguard Worker  * \brief Log end of test case
471*35238bceSAndroid Build Coastguard Worker  * \param log qpTestLog instance
472*35238bceSAndroid Build Coastguard Worker  * \param result Test result
473*35238bceSAndroid Build Coastguard Worker  * \param description Description of a problem in case of error
474*35238bceSAndroid Build Coastguard Worker  * \return true if ok, false otherwise
475*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_endCase(qpTestLog * log,qpTestResult result,const char * resultDetails)476*35238bceSAndroid Build Coastguard Worker bool qpTestLog_endCase(qpTestLog *log, qpTestResult result, const char *resultDetails)
477*35238bceSAndroid Build Coastguard Worker {
478*35238bceSAndroid Build Coastguard Worker     const char *statusStr       = QP_LOOKUP_STRING(s_qpTestResultMap, result);
479*35238bceSAndroid Build Coastguard Worker     qpXmlAttribute statusAttrib = qpSetStringAttrib("StatusCode", statusStr);
480*35238bceSAndroid Build Coastguard Worker 
481*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
482*35238bceSAndroid Build Coastguard Worker 
483*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log->isCaseOpen);
484*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(ContainerStack_isEmpty(&log->containerStack));
485*35238bceSAndroid Build Coastguard Worker 
486*35238bceSAndroid Build Coastguard Worker     /* <Result StatusCode="Pass">Result details</Result>
487*35238bceSAndroid Build Coastguard Worker      * </TestCaseResult>
488*35238bceSAndroid Build Coastguard Worker      */
489*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_startElement(log->writer, "Result", 1, &statusAttrib) ||
490*35238bceSAndroid Build Coastguard Worker         (resultDetails && !qpXmlWriter_writeString(log->writer, resultDetails)) ||
491*35238bceSAndroid Build Coastguard Worker         !qpXmlWriter_endElement(log->writer, "Result") || !qpXmlWriter_endElement(log->writer, "TestCaseResult") ||
492*35238bceSAndroid Build Coastguard Worker         !qpXmlWriter_endDocument(log->writer)) /* Close any XML elements still open */
493*35238bceSAndroid Build Coastguard Worker     {
494*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_endCase(): Writing XML failed\n");
495*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
496*35238bceSAndroid Build Coastguard Worker         return false;
497*35238bceSAndroid Build Coastguard Worker     }
498*35238bceSAndroid Build Coastguard Worker 
499*35238bceSAndroid Build Coastguard Worker     /* Flush XML and write #endTestCaseResult. */
500*35238bceSAndroid Build Coastguard Worker     qpXmlWriter_flush(log->writer);
501*35238bceSAndroid Build Coastguard Worker     if (!qpTestLog_isCompact(log))
502*35238bceSAndroid Build Coastguard Worker     {
503*35238bceSAndroid Build Coastguard Worker         fprintf(log->outputFile, "\n#endTestCaseResult\n");
504*35238bceSAndroid Build Coastguard Worker     }
505*35238bceSAndroid Build Coastguard Worker     if (!(log->flags & QP_TEST_LOG_NO_FLUSH))
506*35238bceSAndroid Build Coastguard Worker         qpTestLog_flushFile(log);
507*35238bceSAndroid Build Coastguard Worker 
508*35238bceSAndroid Build Coastguard Worker     log->isCaseOpen = false;
509*35238bceSAndroid Build Coastguard Worker 
510*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
511*35238bceSAndroid Build Coastguard Worker     return true;
512*35238bceSAndroid Build Coastguard Worker }
513*35238bceSAndroid Build Coastguard Worker 
qpTestLog_startTestsCasesTime(qpTestLog * log)514*35238bceSAndroid Build Coastguard Worker bool qpTestLog_startTestsCasesTime(qpTestLog *log)
515*35238bceSAndroid Build Coastguard Worker {
516*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log);
517*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
518*35238bceSAndroid Build Coastguard Worker 
519*35238bceSAndroid Build Coastguard Worker     /* Flush XML and write out #beginTestCaseResult. */
520*35238bceSAndroid Build Coastguard Worker     qpXmlWriter_flush(log->writer);
521*35238bceSAndroid Build Coastguard Worker     fprintf(log->outputFile, "\n#beginTestsCasesTime\n");
522*35238bceSAndroid Build Coastguard Worker 
523*35238bceSAndroid Build Coastguard Worker     log->isCaseOpen = true;
524*35238bceSAndroid Build Coastguard Worker 
525*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_startDocument(log->writer, !qpTestLog_isCompact(log)) ||
526*35238bceSAndroid Build Coastguard Worker         !qpXmlWriter_startElement(log->writer, "TestsCasesTime", 0, (const qpXmlAttribute *)DE_NULL))
527*35238bceSAndroid Build Coastguard Worker     {
528*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_startTestsCasesTime(): Writing XML failed\n");
529*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
530*35238bceSAndroid Build Coastguard Worker         return false;
531*35238bceSAndroid Build Coastguard Worker     }
532*35238bceSAndroid Build Coastguard Worker 
533*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
534*35238bceSAndroid Build Coastguard Worker     return true;
535*35238bceSAndroid Build Coastguard Worker }
536*35238bceSAndroid Build Coastguard Worker 
qpTestLog_endTestsCasesTime(qpTestLog * log)537*35238bceSAndroid Build Coastguard Worker bool qpTestLog_endTestsCasesTime(qpTestLog *log)
538*35238bceSAndroid Build Coastguard Worker {
539*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log);
540*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
541*35238bceSAndroid Build Coastguard Worker 
542*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log->isCaseOpen);
543*35238bceSAndroid Build Coastguard Worker 
544*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_endElement(log->writer, "TestsCasesTime") || !qpXmlWriter_endDocument(log->writer))
545*35238bceSAndroid Build Coastguard Worker     {
546*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_endTestsCasesTime(): Writing XML failed\n");
547*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
548*35238bceSAndroid Build Coastguard Worker         return false;
549*35238bceSAndroid Build Coastguard Worker     }
550*35238bceSAndroid Build Coastguard Worker 
551*35238bceSAndroid Build Coastguard Worker     qpXmlWriter_flush(log->writer);
552*35238bceSAndroid Build Coastguard Worker 
553*35238bceSAndroid Build Coastguard Worker     fprintf(log->outputFile, "\n#endTestsCasesTime\n");
554*35238bceSAndroid Build Coastguard Worker 
555*35238bceSAndroid Build Coastguard Worker     log->isCaseOpen = false;
556*35238bceSAndroid Build Coastguard Worker 
557*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
558*35238bceSAndroid Build Coastguard Worker     return true;
559*35238bceSAndroid Build Coastguard Worker }
560*35238bceSAndroid Build Coastguard Worker 
561*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
562*35238bceSAndroid Build Coastguard Worker  * \brief Abrupt termination of logging.
563*35238bceSAndroid Build Coastguard Worker  * \param log        qpTestLog instance
564*35238bceSAndroid Build Coastguard Worker  * \param result    Result code, only Crash and Timeout are allowed.
565*35238bceSAndroid Build Coastguard Worker  * \return true if ok, false otherwise
566*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_terminateCase(qpTestLog * log,qpTestResult result)567*35238bceSAndroid Build Coastguard Worker bool qpTestLog_terminateCase(qpTestLog *log, qpTestResult result)
568*35238bceSAndroid Build Coastguard Worker {
569*35238bceSAndroid Build Coastguard Worker     const char *resultStr = QP_LOOKUP_STRING(s_qpTestResultMap, result);
570*35238bceSAndroid Build Coastguard Worker 
571*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log);
572*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(result == QP_TEST_RESULT_CRASH || result == QP_TEST_RESULT_TIMEOUT);
573*35238bceSAndroid Build Coastguard Worker 
574*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
575*35238bceSAndroid Build Coastguard Worker 
576*35238bceSAndroid Build Coastguard Worker     if (!log->isCaseOpen)
577*35238bceSAndroid Build Coastguard Worker     {
578*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
579*35238bceSAndroid Build Coastguard Worker         return false; /* Soft error. This is called from error handler. */
580*35238bceSAndroid Build Coastguard Worker     }
581*35238bceSAndroid Build Coastguard Worker 
582*35238bceSAndroid Build Coastguard Worker     /* Flush XML and write #terminateTestCaseResult. */
583*35238bceSAndroid Build Coastguard Worker     qpXmlWriter_flush(log->writer);
584*35238bceSAndroid Build Coastguard Worker     fprintf(log->outputFile, "\n#terminateTestCaseResult %s\n", resultStr);
585*35238bceSAndroid Build Coastguard Worker     qpTestLog_flushFile(log);
586*35238bceSAndroid Build Coastguard Worker 
587*35238bceSAndroid Build Coastguard Worker     log->isCaseOpen = false;
588*35238bceSAndroid Build Coastguard Worker 
589*35238bceSAndroid Build Coastguard Worker #if defined(DE_DEBUG)
590*35238bceSAndroid Build Coastguard Worker     ContainerStack_reset(&log->containerStack);
591*35238bceSAndroid Build Coastguard Worker #endif
592*35238bceSAndroid Build Coastguard Worker 
593*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
594*35238bceSAndroid Build Coastguard Worker     return true;
595*35238bceSAndroid Build Coastguard Worker }
596*35238bceSAndroid Build Coastguard Worker 
qpTestLog_writeKeyValuePair(qpTestLog * log,const char * elementName,const char * name,const char * description,const char * unit,qpKeyValueTag tag,const char * text)597*35238bceSAndroid Build Coastguard Worker static bool qpTestLog_writeKeyValuePair(qpTestLog *log, const char *elementName, const char *name,
598*35238bceSAndroid Build Coastguard Worker                                         const char *description, const char *unit, qpKeyValueTag tag, const char *text)
599*35238bceSAndroid Build Coastguard Worker {
600*35238bceSAndroid Build Coastguard Worker     const char *tagString = QP_LOOKUP_STRING(s_qpTagMap, tag);
601*35238bceSAndroid Build Coastguard Worker     qpXmlAttribute attribs[8];
602*35238bceSAndroid Build Coastguard Worker     int numAttribs = 0;
603*35238bceSAndroid Build Coastguard Worker 
604*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log && elementName && text);
605*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
606*35238bceSAndroid Build Coastguard Worker 
607*35238bceSAndroid Build Coastguard Worker     /* Fill in attributes. */
608*35238bceSAndroid Build Coastguard Worker     if (name)
609*35238bceSAndroid Build Coastguard Worker         attribs[numAttribs++] = qpSetStringAttrib("Name", name);
610*35238bceSAndroid Build Coastguard Worker     if (description)
611*35238bceSAndroid Build Coastguard Worker         attribs[numAttribs++] = qpSetStringAttrib("Description", description);
612*35238bceSAndroid Build Coastguard Worker     if (tagString)
613*35238bceSAndroid Build Coastguard Worker         attribs[numAttribs++] = qpSetStringAttrib("Tag", tagString);
614*35238bceSAndroid Build Coastguard Worker     if (unit)
615*35238bceSAndroid Build Coastguard Worker         attribs[numAttribs++] = qpSetStringAttrib("Unit", unit);
616*35238bceSAndroid Build Coastguard Worker 
617*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_startElement(log->writer, elementName, numAttribs, attribs) ||
618*35238bceSAndroid Build Coastguard Worker         !qpXmlWriter_writeString(log->writer, text) || !qpXmlWriter_endElement(log->writer, elementName))
619*35238bceSAndroid Build Coastguard Worker     {
620*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_writeKeyValuePair(): Writing XML failed\n");
621*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
622*35238bceSAndroid Build Coastguard Worker         return false;
623*35238bceSAndroid Build Coastguard Worker     }
624*35238bceSAndroid Build Coastguard Worker 
625*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
626*35238bceSAndroid Build Coastguard Worker     return true;
627*35238bceSAndroid Build Coastguard Worker }
628*35238bceSAndroid Build Coastguard Worker 
629*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
630*35238bceSAndroid Build Coastguard Worker  * \brief Write key-value-pair into log
631*35238bceSAndroid Build Coastguard Worker  * \param log            qpTestLog instance
632*35238bceSAndroid Build Coastguard Worker  * \param name            Unique identifier for entry
633*35238bceSAndroid Build Coastguard Worker  * \param description    Human readable description
634*35238bceSAndroid Build Coastguard Worker  * \param tag            Optional tag
635*35238bceSAndroid Build Coastguard Worker  * \param value            Value of the key-value-pair
636*35238bceSAndroid Build Coastguard Worker  * \return true if ok, false otherwise
637*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_writeText(qpTestLog * log,const char * name,const char * description,qpKeyValueTag tag,const char * text)638*35238bceSAndroid Build Coastguard Worker bool qpTestLog_writeText(qpTestLog *log, const char *name, const char *description, qpKeyValueTag tag, const char *text)
639*35238bceSAndroid Build Coastguard Worker {
640*35238bceSAndroid Build Coastguard Worker     /* <Text Name="name" Description="description" Tag="tag">text</Text> */
641*35238bceSAndroid Build Coastguard Worker     return qpTestLog_writeKeyValuePair(log, "Text", name, description, DE_NULL, tag, text);
642*35238bceSAndroid Build Coastguard Worker }
643*35238bceSAndroid Build Coastguard Worker 
644*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
645*35238bceSAndroid Build Coastguard Worker  * \brief Write key-value-pair into log
646*35238bceSAndroid Build Coastguard Worker  * \param log            qpTestLog instance
647*35238bceSAndroid Build Coastguard Worker  * \param name            Unique identifier for entry
648*35238bceSAndroid Build Coastguard Worker  * \param description    Human readable description
649*35238bceSAndroid Build Coastguard Worker  * \param tag            Optional tag
650*35238bceSAndroid Build Coastguard Worker  * \param value            Value of the key-value-pair
651*35238bceSAndroid Build Coastguard Worker  * \return true if ok, false otherwise
652*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_writeInteger(qpTestLog * log,const char * name,const char * description,const char * unit,qpKeyValueTag tag,int64_t value)653*35238bceSAndroid Build Coastguard Worker bool qpTestLog_writeInteger(qpTestLog *log, const char *name, const char *description, const char *unit,
654*35238bceSAndroid Build Coastguard Worker                             qpKeyValueTag tag, int64_t value)
655*35238bceSAndroid Build Coastguard Worker {
656*35238bceSAndroid Build Coastguard Worker     char tmpString[64];
657*35238bceSAndroid Build Coastguard Worker     int64ToString(value, tmpString);
658*35238bceSAndroid Build Coastguard Worker 
659*35238bceSAndroid Build Coastguard Worker     /* <Number Name="name" Description="description" Tag="Performance">15</Number> */
660*35238bceSAndroid Build Coastguard Worker     return qpTestLog_writeKeyValuePair(log, "Number", name, description, unit, tag, tmpString);
661*35238bceSAndroid Build Coastguard Worker }
662*35238bceSAndroid Build Coastguard Worker 
663*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
664*35238bceSAndroid Build Coastguard Worker  * \brief Write key-value-pair into log
665*35238bceSAndroid Build Coastguard Worker  * \param log            qpTestLog instance
666*35238bceSAndroid Build Coastguard Worker  * \param name            Unique identifier for entry
667*35238bceSAndroid Build Coastguard Worker  * \param description    Human readable description
668*35238bceSAndroid Build Coastguard Worker  * \param tag            Optional tag
669*35238bceSAndroid Build Coastguard Worker  * \param value            Value of the key-value-pair
670*35238bceSAndroid Build Coastguard Worker  * \return true if ok, false otherwise
671*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_writeFloat(qpTestLog * log,const char * name,const char * description,const char * unit,qpKeyValueTag tag,float value)672*35238bceSAndroid Build Coastguard Worker bool qpTestLog_writeFloat(qpTestLog *log, const char *name, const char *description, const char *unit,
673*35238bceSAndroid Build Coastguard Worker                           qpKeyValueTag tag, float value)
674*35238bceSAndroid Build Coastguard Worker {
675*35238bceSAndroid Build Coastguard Worker     char tmpString[64];
676*35238bceSAndroid Build Coastguard Worker     floatToString(value, tmpString, sizeof(tmpString));
677*35238bceSAndroid Build Coastguard Worker 
678*35238bceSAndroid Build Coastguard Worker     /* <Number Name="name" Description="description" Tag="Performance">15</Number> */
679*35238bceSAndroid Build Coastguard Worker     return qpTestLog_writeKeyValuePair(log, "Number", name, description, unit, tag, tmpString);
680*35238bceSAndroid Build Coastguard Worker }
681*35238bceSAndroid Build Coastguard Worker 
682*35238bceSAndroid Build Coastguard Worker typedef struct Buffer_s
683*35238bceSAndroid Build Coastguard Worker {
684*35238bceSAndroid Build Coastguard Worker     size_t capacity;
685*35238bceSAndroid Build Coastguard Worker     size_t size;
686*35238bceSAndroid Build Coastguard Worker     uint8_t *data;
687*35238bceSAndroid Build Coastguard Worker } Buffer;
688*35238bceSAndroid Build Coastguard Worker 
Buffer_init(Buffer * buffer)689*35238bceSAndroid Build Coastguard Worker void Buffer_init(Buffer *buffer)
690*35238bceSAndroid Build Coastguard Worker {
691*35238bceSAndroid Build Coastguard Worker     buffer->capacity = 0;
692*35238bceSAndroid Build Coastguard Worker     buffer->size     = 0;
693*35238bceSAndroid Build Coastguard Worker     buffer->data     = DE_NULL;
694*35238bceSAndroid Build Coastguard Worker }
695*35238bceSAndroid Build Coastguard Worker 
Buffer_deinit(Buffer * buffer)696*35238bceSAndroid Build Coastguard Worker void Buffer_deinit(Buffer *buffer)
697*35238bceSAndroid Build Coastguard Worker {
698*35238bceSAndroid Build Coastguard Worker     deFree(buffer->data);
699*35238bceSAndroid Build Coastguard Worker     Buffer_init(buffer);
700*35238bceSAndroid Build Coastguard Worker }
701*35238bceSAndroid Build Coastguard Worker 
Buffer_resize(Buffer * buffer,size_t newSize)702*35238bceSAndroid Build Coastguard Worker bool Buffer_resize(Buffer *buffer, size_t newSize)
703*35238bceSAndroid Build Coastguard Worker {
704*35238bceSAndroid Build Coastguard Worker     /* Grow buffer if necessary. */
705*35238bceSAndroid Build Coastguard Worker     if (newSize > buffer->capacity)
706*35238bceSAndroid Build Coastguard Worker     {
707*35238bceSAndroid Build Coastguard Worker         size_t newCapacity = (size_t)deAlign32(deMax32(2 * (int)buffer->capacity, (int)newSize), 512);
708*35238bceSAndroid Build Coastguard Worker         uint8_t *newData   = (uint8_t *)deMalloc(newCapacity);
709*35238bceSAndroid Build Coastguard Worker         if (!newData)
710*35238bceSAndroid Build Coastguard Worker             return false;
711*35238bceSAndroid Build Coastguard Worker 
712*35238bceSAndroid Build Coastguard Worker         if (buffer->data)
713*35238bceSAndroid Build Coastguard Worker             memcpy(newData, buffer->data, buffer->size);
714*35238bceSAndroid Build Coastguard Worker 
715*35238bceSAndroid Build Coastguard Worker         deFree(buffer->data);
716*35238bceSAndroid Build Coastguard Worker         buffer->data     = newData;
717*35238bceSAndroid Build Coastguard Worker         buffer->capacity = newCapacity;
718*35238bceSAndroid Build Coastguard Worker     }
719*35238bceSAndroid Build Coastguard Worker 
720*35238bceSAndroid Build Coastguard Worker     buffer->size = newSize;
721*35238bceSAndroid Build Coastguard Worker     return true;
722*35238bceSAndroid Build Coastguard Worker }
723*35238bceSAndroid Build Coastguard Worker 
Buffer_append(Buffer * buffer,const uint8_t * data,size_t numBytes)724*35238bceSAndroid Build Coastguard Worker bool Buffer_append(Buffer *buffer, const uint8_t *data, size_t numBytes)
725*35238bceSAndroid Build Coastguard Worker {
726*35238bceSAndroid Build Coastguard Worker     size_t offset = buffer->size;
727*35238bceSAndroid Build Coastguard Worker 
728*35238bceSAndroid Build Coastguard Worker     if (!Buffer_resize(buffer, buffer->size + numBytes))
729*35238bceSAndroid Build Coastguard Worker         return false;
730*35238bceSAndroid Build Coastguard Worker 
731*35238bceSAndroid Build Coastguard Worker     /* Append bytes. */
732*35238bceSAndroid Build Coastguard Worker     memcpy(&buffer->data[offset], data, numBytes);
733*35238bceSAndroid Build Coastguard Worker     return true;
734*35238bceSAndroid Build Coastguard Worker }
735*35238bceSAndroid Build Coastguard Worker 
736*35238bceSAndroid Build Coastguard Worker #if defined(QP_SUPPORT_PNG)
pngWriteData(png_structp png,png_bytep dataPtr,png_size_t numBytes)737*35238bceSAndroid Build Coastguard Worker void pngWriteData(png_structp png, png_bytep dataPtr, png_size_t numBytes)
738*35238bceSAndroid Build Coastguard Worker {
739*35238bceSAndroid Build Coastguard Worker     Buffer *buffer = (Buffer *)png_get_io_ptr(png);
740*35238bceSAndroid Build Coastguard Worker     if (!Buffer_append(buffer, (const uint8_t *)dataPtr, numBytes))
741*35238bceSAndroid Build Coastguard Worker         png_error(png, "unable to resize PNG write buffer!");
742*35238bceSAndroid Build Coastguard Worker }
743*35238bceSAndroid Build Coastguard Worker 
pngFlushData(png_structp png)744*35238bceSAndroid Build Coastguard Worker void pngFlushData(png_structp png)
745*35238bceSAndroid Build Coastguard Worker {
746*35238bceSAndroid Build Coastguard Worker     DE_UNREF(png);
747*35238bceSAndroid Build Coastguard Worker     /* nada */
748*35238bceSAndroid Build Coastguard Worker }
749*35238bceSAndroid Build Coastguard Worker 
writeCompressedPNG(png_structp png,png_infop info,png_byte ** rowPointers,int width,int height,int colorFormat)750*35238bceSAndroid Build Coastguard Worker static bool writeCompressedPNG(png_structp png, png_infop info, png_byte **rowPointers, int width, int height,
751*35238bceSAndroid Build Coastguard Worker                                int colorFormat)
752*35238bceSAndroid Build Coastguard Worker {
753*35238bceSAndroid Build Coastguard Worker     if (setjmp(png_jmpbuf(png)) == 0)
754*35238bceSAndroid Build Coastguard Worker     {
755*35238bceSAndroid Build Coastguard Worker         /* Write data. */
756*35238bceSAndroid Build Coastguard Worker         png_set_IHDR(png, info, (png_uint_32)width, (png_uint_32)height, 8, colorFormat, PNG_INTERLACE_NONE,
757*35238bceSAndroid Build Coastguard Worker                      PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
758*35238bceSAndroid Build Coastguard Worker         png_write_info(png, info);
759*35238bceSAndroid Build Coastguard Worker         png_write_image(png, rowPointers);
760*35238bceSAndroid Build Coastguard Worker         png_write_end(png, NULL);
761*35238bceSAndroid Build Coastguard Worker 
762*35238bceSAndroid Build Coastguard Worker         return true;
763*35238bceSAndroid Build Coastguard Worker     }
764*35238bceSAndroid Build Coastguard Worker     else
765*35238bceSAndroid Build Coastguard Worker         return false;
766*35238bceSAndroid Build Coastguard Worker }
767*35238bceSAndroid Build Coastguard Worker 
compressImagePNG(Buffer * buffer,qpImageFormat imageFormat,int width,int height,int rowStride,const void * data)768*35238bceSAndroid Build Coastguard Worker static bool compressImagePNG(Buffer *buffer, qpImageFormat imageFormat, int width, int height, int rowStride,
769*35238bceSAndroid Build Coastguard Worker                              const void *data)
770*35238bceSAndroid Build Coastguard Worker {
771*35238bceSAndroid Build Coastguard Worker     bool compressOk        = false;
772*35238bceSAndroid Build Coastguard Worker     png_structp png        = DE_NULL;
773*35238bceSAndroid Build Coastguard Worker     png_infop info         = DE_NULL;
774*35238bceSAndroid Build Coastguard Worker     png_byte **rowPointers = DE_NULL;
775*35238bceSAndroid Build Coastguard Worker     bool hasAlpha          = imageFormat == QP_IMAGE_FORMAT_RGBA8888;
776*35238bceSAndroid Build Coastguard Worker     int ndx;
777*35238bceSAndroid Build Coastguard Worker 
778*35238bceSAndroid Build Coastguard Worker     /* Handle format. */
779*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(imageFormat == QP_IMAGE_FORMAT_RGB888 || imageFormat == QP_IMAGE_FORMAT_RGBA8888);
780*35238bceSAndroid Build Coastguard Worker 
781*35238bceSAndroid Build Coastguard Worker     /* Allocate & set row pointers. */
782*35238bceSAndroid Build Coastguard Worker     rowPointers = (png_byte **)deMalloc((size_t)height * sizeof(png_byte *));
783*35238bceSAndroid Build Coastguard Worker     if (!rowPointers)
784*35238bceSAndroid Build Coastguard Worker         return false;
785*35238bceSAndroid Build Coastguard Worker 
786*35238bceSAndroid Build Coastguard Worker     for (ndx = 0; ndx < height; ndx++)
787*35238bceSAndroid Build Coastguard Worker         rowPointers[ndx] = (png_byte *)((const uint8_t *)data + ndx * rowStride);
788*35238bceSAndroid Build Coastguard Worker 
789*35238bceSAndroid Build Coastguard Worker     /* Initialize PNG compressor. */
790*35238bceSAndroid Build Coastguard Worker     png  = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
791*35238bceSAndroid Build Coastguard Worker     info = png ? png_create_info_struct(png) : DE_NULL;
792*35238bceSAndroid Build Coastguard Worker     if (png && info)
793*35238bceSAndroid Build Coastguard Worker     {
794*35238bceSAndroid Build Coastguard Worker         /* Set our own write function. */
795*35238bceSAndroid Build Coastguard Worker         png_set_write_fn(png, buffer, pngWriteData, pngFlushData);
796*35238bceSAndroid Build Coastguard Worker 
797*35238bceSAndroid Build Coastguard Worker         compressOk = writeCompressedPNG(png, info, rowPointers, width, height,
798*35238bceSAndroid Build Coastguard Worker                                         hasAlpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB);
799*35238bceSAndroid Build Coastguard Worker     }
800*35238bceSAndroid Build Coastguard Worker 
801*35238bceSAndroid Build Coastguard Worker     /* Cleanup & return. */
802*35238bceSAndroid Build Coastguard Worker     if (png && info)
803*35238bceSAndroid Build Coastguard Worker     {
804*35238bceSAndroid Build Coastguard Worker         png_destroy_info_struct(png, &info);
805*35238bceSAndroid Build Coastguard Worker         png_destroy_write_struct(&png, DE_NULL);
806*35238bceSAndroid Build Coastguard Worker     }
807*35238bceSAndroid Build Coastguard Worker     else if (png)
808*35238bceSAndroid Build Coastguard Worker         png_destroy_write_struct(&png, &info);
809*35238bceSAndroid Build Coastguard Worker 
810*35238bceSAndroid Build Coastguard Worker     deFree(rowPointers);
811*35238bceSAndroid Build Coastguard Worker     return compressOk;
812*35238bceSAndroid Build Coastguard Worker }
813*35238bceSAndroid Build Coastguard Worker #endif /* QP_SUPPORT_PNG */
814*35238bceSAndroid Build Coastguard Worker 
815*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
816*35238bceSAndroid Build Coastguard Worker  * \brief Start image set
817*35238bceSAndroid Build Coastguard Worker  * \param log            qpTestLog instance
818*35238bceSAndroid Build Coastguard Worker  * \param name            Unique identifier for the set
819*35238bceSAndroid Build Coastguard Worker  * \param description    Human readable description
820*35238bceSAndroid Build Coastguard Worker  * \return true if ok, false otherwise
821*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_startImageSet(qpTestLog * log,const char * name,const char * description)822*35238bceSAndroid Build Coastguard Worker bool qpTestLog_startImageSet(qpTestLog *log, const char *name, const char *description)
823*35238bceSAndroid Build Coastguard Worker {
824*35238bceSAndroid Build Coastguard Worker     qpXmlAttribute attribs[4];
825*35238bceSAndroid Build Coastguard Worker     int numAttribs = 0;
826*35238bceSAndroid Build Coastguard Worker 
827*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log && name);
828*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
829*35238bceSAndroid Build Coastguard Worker 
830*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetStringAttrib("Name", name);
831*35238bceSAndroid Build Coastguard Worker     if (description)
832*35238bceSAndroid Build Coastguard Worker         attribs[numAttribs++] = qpSetStringAttrib("Description", description);
833*35238bceSAndroid Build Coastguard Worker 
834*35238bceSAndroid Build Coastguard Worker     /* <ImageSet Name="<name>"> */
835*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_startElement(log->writer, "ImageSet", numAttribs, attribs))
836*35238bceSAndroid Build Coastguard Worker     {
837*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_startImageSet(): Writing XML failed\n");
838*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
839*35238bceSAndroid Build Coastguard Worker         return false;
840*35238bceSAndroid Build Coastguard Worker     }
841*35238bceSAndroid Build Coastguard Worker 
842*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_IMAGESET));
843*35238bceSAndroid Build Coastguard Worker 
844*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
845*35238bceSAndroid Build Coastguard Worker     return true;
846*35238bceSAndroid Build Coastguard Worker }
847*35238bceSAndroid Build Coastguard Worker 
848*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
849*35238bceSAndroid Build Coastguard Worker  * \brief End image set
850*35238bceSAndroid Build Coastguard Worker  * \param log            qpTestLog instance
851*35238bceSAndroid Build Coastguard Worker  * \return true if ok, false otherwise
852*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_endImageSet(qpTestLog * log)853*35238bceSAndroid Build Coastguard Worker bool qpTestLog_endImageSet(qpTestLog *log)
854*35238bceSAndroid Build Coastguard Worker {
855*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log);
856*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
857*35238bceSAndroid Build Coastguard Worker 
858*35238bceSAndroid Build Coastguard Worker     /* <ImageSet Name="<name>"> */
859*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_endElement(log->writer, "ImageSet"))
860*35238bceSAndroid Build Coastguard Worker     {
861*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_endImageSet(): Writing XML failed\n");
862*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
863*35238bceSAndroid Build Coastguard Worker         return false;
864*35238bceSAndroid Build Coastguard Worker     }
865*35238bceSAndroid Build Coastguard Worker 
866*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(ContainerStack_pop(&log->containerStack) == CONTAINERTYPE_IMAGESET);
867*35238bceSAndroid Build Coastguard Worker 
868*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
869*35238bceSAndroid Build Coastguard Worker     return true;
870*35238bceSAndroid Build Coastguard Worker }
871*35238bceSAndroid Build Coastguard Worker 
872*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
873*35238bceSAndroid Build Coastguard Worker  * \brief Write base64 encoded raw image data into log
874*35238bceSAndroid Build Coastguard Worker  * \param log                qpTestLog instance
875*35238bceSAndroid Build Coastguard Worker  * \param name                Unique name (matching names can be compared across BatchResults).
876*35238bceSAndroid Build Coastguard Worker  * \param description        Textual description (shown in Candy).
877*35238bceSAndroid Build Coastguard Worker  * \param compressionMode    Compression mode
878*35238bceSAndroid Build Coastguard Worker  * \param imageFormat        Color format
879*35238bceSAndroid Build Coastguard Worker  * \param width                Width in pixels
880*35238bceSAndroid Build Coastguard Worker  * \param height            Height in pixels
881*35238bceSAndroid Build Coastguard Worker  * \param stride            Data stride (offset between rows)
882*35238bceSAndroid Build Coastguard Worker  * \param data                Pointer to pixel data
883*35238bceSAndroid Build Coastguard Worker  * \return 0 if OK, otherwise <0
884*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_writeImage(qpTestLog * log,const char * name,const char * description,qpImageCompressionMode compressionMode,qpImageFormat imageFormat,int width,int height,int stride,const void * data)885*35238bceSAndroid Build Coastguard Worker bool qpTestLog_writeImage(qpTestLog *log, const char *name, const char *description,
886*35238bceSAndroid Build Coastguard Worker                           qpImageCompressionMode compressionMode, qpImageFormat imageFormat, int width, int height,
887*35238bceSAndroid Build Coastguard Worker                           int stride, const void *data)
888*35238bceSAndroid Build Coastguard Worker {
889*35238bceSAndroid Build Coastguard Worker     char widthStr[32];
890*35238bceSAndroid Build Coastguard Worker     char heightStr[32];
891*35238bceSAndroid Build Coastguard Worker     qpXmlAttribute attribs[8];
892*35238bceSAndroid Build Coastguard Worker     int numAttribs = 0;
893*35238bceSAndroid Build Coastguard Worker     Buffer compressedBuffer;
894*35238bceSAndroid Build Coastguard Worker     const void *writeDataPtr = DE_NULL;
895*35238bceSAndroid Build Coastguard Worker     size_t writeDataBytes    = ~(size_t)0;
896*35238bceSAndroid Build Coastguard Worker 
897*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log && name);
898*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(deInRange32(width, 1, 32768));
899*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(deInRange32(height, 1, 32768));
900*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(data);
901*35238bceSAndroid Build Coastguard Worker 
902*35238bceSAndroid Build Coastguard Worker     if (log->flags & QP_TEST_LOG_EXCLUDE_IMAGES)
903*35238bceSAndroid Build Coastguard Worker         return true; /* Image not logged. */
904*35238bceSAndroid Build Coastguard Worker 
905*35238bceSAndroid Build Coastguard Worker     Buffer_init(&compressedBuffer);
906*35238bceSAndroid Build Coastguard Worker 
907*35238bceSAndroid Build Coastguard Worker     /* BEST compression mode defaults to PNG. */
908*35238bceSAndroid Build Coastguard Worker     if (compressionMode == QP_IMAGE_COMPRESSION_MODE_BEST)
909*35238bceSAndroid Build Coastguard Worker     {
910*35238bceSAndroid Build Coastguard Worker #if defined(QP_SUPPORT_PNG)
911*35238bceSAndroid Build Coastguard Worker         compressionMode = QP_IMAGE_COMPRESSION_MODE_PNG;
912*35238bceSAndroid Build Coastguard Worker #else
913*35238bceSAndroid Build Coastguard Worker         compressionMode = QP_IMAGE_COMPRESSION_MODE_NONE;
914*35238bceSAndroid Build Coastguard Worker #endif
915*35238bceSAndroid Build Coastguard Worker     }
916*35238bceSAndroid Build Coastguard Worker 
917*35238bceSAndroid Build Coastguard Worker #if defined(QP_SUPPORT_PNG)
918*35238bceSAndroid Build Coastguard Worker     /* Try storing with PNG compression. */
919*35238bceSAndroid Build Coastguard Worker     if (compressionMode == QP_IMAGE_COMPRESSION_MODE_PNG)
920*35238bceSAndroid Build Coastguard Worker     {
921*35238bceSAndroid Build Coastguard Worker         bool compressOk = compressImagePNG(&compressedBuffer, imageFormat, width, height, stride, data);
922*35238bceSAndroid Build Coastguard Worker         if (compressOk)
923*35238bceSAndroid Build Coastguard Worker         {
924*35238bceSAndroid Build Coastguard Worker             writeDataPtr   = compressedBuffer.data;
925*35238bceSAndroid Build Coastguard Worker             writeDataBytes = compressedBuffer.size;
926*35238bceSAndroid Build Coastguard Worker         }
927*35238bceSAndroid Build Coastguard Worker         else
928*35238bceSAndroid Build Coastguard Worker         {
929*35238bceSAndroid Build Coastguard Worker             /* Fall-back to default compression. */
930*35238bceSAndroid Build Coastguard Worker             qpPrintf("WARNING: PNG compression failed -- storing image uncompressed.\n");
931*35238bceSAndroid Build Coastguard Worker             compressionMode = QP_IMAGE_COMPRESSION_MODE_NONE;
932*35238bceSAndroid Build Coastguard Worker         }
933*35238bceSAndroid Build Coastguard Worker     }
934*35238bceSAndroid Build Coastguard Worker #endif
935*35238bceSAndroid Build Coastguard Worker 
936*35238bceSAndroid Build Coastguard Worker     /* Handle image compression. */
937*35238bceSAndroid Build Coastguard Worker     switch (compressionMode)
938*35238bceSAndroid Build Coastguard Worker     {
939*35238bceSAndroid Build Coastguard Worker     case QP_IMAGE_COMPRESSION_MODE_NONE:
940*35238bceSAndroid Build Coastguard Worker     {
941*35238bceSAndroid Build Coastguard Worker         int pixelSize    = imageFormat == QP_IMAGE_FORMAT_RGB888 ? 3 : 4;
942*35238bceSAndroid Build Coastguard Worker         int packedStride = pixelSize * width;
943*35238bceSAndroid Build Coastguard Worker 
944*35238bceSAndroid Build Coastguard Worker         if (packedStride == stride)
945*35238bceSAndroid Build Coastguard Worker             writeDataPtr = data;
946*35238bceSAndroid Build Coastguard Worker         else
947*35238bceSAndroid Build Coastguard Worker         {
948*35238bceSAndroid Build Coastguard Worker             /* Need to re-pack pixels. */
949*35238bceSAndroid Build Coastguard Worker             if (Buffer_resize(&compressedBuffer, (size_t)(packedStride * height)))
950*35238bceSAndroid Build Coastguard Worker             {
951*35238bceSAndroid Build Coastguard Worker                 int row;
952*35238bceSAndroid Build Coastguard Worker                 for (row = 0; row < height; row++)
953*35238bceSAndroid Build Coastguard Worker                     memcpy(&compressedBuffer.data[packedStride * row], &((const uint8_t *)data)[row * stride],
954*35238bceSAndroid Build Coastguard Worker                            (size_t)(pixelSize * width));
955*35238bceSAndroid Build Coastguard Worker             }
956*35238bceSAndroid Build Coastguard Worker             else
957*35238bceSAndroid Build Coastguard Worker             {
958*35238bceSAndroid Build Coastguard Worker                 qpPrintf("ERROR: Failed to pack pixels for writing.\n");
959*35238bceSAndroid Build Coastguard Worker                 Buffer_deinit(&compressedBuffer);
960*35238bceSAndroid Build Coastguard Worker                 return false;
961*35238bceSAndroid Build Coastguard Worker             }
962*35238bceSAndroid Build Coastguard Worker         }
963*35238bceSAndroid Build Coastguard Worker 
964*35238bceSAndroid Build Coastguard Worker         writeDataBytes = (size_t)(packedStride * height);
965*35238bceSAndroid Build Coastguard Worker         break;
966*35238bceSAndroid Build Coastguard Worker     }
967*35238bceSAndroid Build Coastguard Worker 
968*35238bceSAndroid Build Coastguard Worker #if defined(QP_SUPPORT_PNG)
969*35238bceSAndroid Build Coastguard Worker     case QP_IMAGE_COMPRESSION_MODE_PNG:
970*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(writeDataPtr); /* Already handled. */
971*35238bceSAndroid Build Coastguard Worker         break;
972*35238bceSAndroid Build Coastguard Worker #endif
973*35238bceSAndroid Build Coastguard Worker 
974*35238bceSAndroid Build Coastguard Worker     default:
975*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_writeImage(): Unknown compression mode: %s\n",
976*35238bceSAndroid Build Coastguard Worker                  QP_LOOKUP_STRING(s_qpImageCompressionModeMap, compressionMode));
977*35238bceSAndroid Build Coastguard Worker         Buffer_deinit(&compressedBuffer);
978*35238bceSAndroid Build Coastguard Worker         return false;
979*35238bceSAndroid Build Coastguard Worker     }
980*35238bceSAndroid Build Coastguard Worker 
981*35238bceSAndroid Build Coastguard Worker     /* Fill in attributes. */
982*35238bceSAndroid Build Coastguard Worker     int32ToString(width, widthStr);
983*35238bceSAndroid Build Coastguard Worker     int32ToString(height, heightStr);
984*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetStringAttrib("Name", name);
985*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetStringAttrib("Width", widthStr);
986*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetStringAttrib("Height", heightStr);
987*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetStringAttrib("Format", QP_LOOKUP_STRING(s_qpImageFormatMap, imageFormat));
988*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] =
989*35238bceSAndroid Build Coastguard Worker         qpSetStringAttrib("CompressionMode", QP_LOOKUP_STRING(s_qpImageCompressionModeMap, compressionMode));
990*35238bceSAndroid Build Coastguard Worker     if (description)
991*35238bceSAndroid Build Coastguard Worker         attribs[numAttribs++] = qpSetStringAttrib("Description", description);
992*35238bceSAndroid Build Coastguard Worker 
993*35238bceSAndroid Build Coastguard Worker     /* \note Log lock is acquired after compression! */
994*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
995*35238bceSAndroid Build Coastguard Worker 
996*35238bceSAndroid Build Coastguard Worker     /* <Image ID="result" Name="Foobar" Width="640" Height="480" Format="RGB888" CompressionMode="None">base64 data</Image> */
997*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_startElement(log->writer, "Image", numAttribs, attribs) ||
998*35238bceSAndroid Build Coastguard Worker         !qpXmlWriter_writeBase64(log->writer, (const uint8_t *)writeDataPtr, writeDataBytes) ||
999*35238bceSAndroid Build Coastguard Worker         !qpXmlWriter_endElement(log->writer, "Image"))
1000*35238bceSAndroid Build Coastguard Worker     {
1001*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_writeImage(): Writing XML failed\n");
1002*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
1003*35238bceSAndroid Build Coastguard Worker         Buffer_deinit(&compressedBuffer);
1004*35238bceSAndroid Build Coastguard Worker         return false;
1005*35238bceSAndroid Build Coastguard Worker     }
1006*35238bceSAndroid Build Coastguard Worker 
1007*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
1008*35238bceSAndroid Build Coastguard Worker 
1009*35238bceSAndroid Build Coastguard Worker     /* Free compressed data if allocated. */
1010*35238bceSAndroid Build Coastguard Worker     Buffer_deinit(&compressedBuffer);
1011*35238bceSAndroid Build Coastguard Worker 
1012*35238bceSAndroid Build Coastguard Worker     return true;
1013*35238bceSAndroid Build Coastguard Worker }
1014*35238bceSAndroid Build Coastguard Worker 
1015*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
1016*35238bceSAndroid Build Coastguard Worker  * \brief Writes infoLog into log. Might filter out empty infoLog.
1017*35238bceSAndroid Build Coastguard Worker  * \param log            qpTestLog instance
1018*35238bceSAndroid Build Coastguard Worker  * \param infoLog        Implementation provided shader compilation or linkage log
1019*35238bceSAndroid Build Coastguard Worker  * \return true if ok, false otherwise
1020*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_writeInfoLog(qpTestLog * log,const char * infoLog)1021*35238bceSAndroid Build Coastguard Worker bool qpTestLog_writeInfoLog(qpTestLog *log, const char *infoLog)
1022*35238bceSAndroid Build Coastguard Worker {
1023*35238bceSAndroid Build Coastguard Worker     if (infoLog == DE_NULL)
1024*35238bceSAndroid Build Coastguard Worker         return false;
1025*35238bceSAndroid Build Coastguard Worker 
1026*35238bceSAndroid Build Coastguard Worker     if (infoLog[0] == '\0' && (log->flags & QP_TEST_LOG_EXCLUDE_EMPTY_LOGINFO) != 0)
1027*35238bceSAndroid Build Coastguard Worker         return true;
1028*35238bceSAndroid Build Coastguard Worker 
1029*35238bceSAndroid Build Coastguard Worker     return qpXmlWriter_writeStringElement(log->writer, "InfoLog", infoLog);
1030*35238bceSAndroid Build Coastguard Worker }
1031*35238bceSAndroid Build Coastguard Worker 
1032*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
1033*35238bceSAndroid Build Coastguard Worker  * \brief Write a OpenGL ES shader program into the log.
1034*35238bceSAndroid Build Coastguard Worker  * \param linkOk            Shader program link result, false on failure
1035*35238bceSAndroid Build Coastguard Worker  * \param linkInfoLog        Implementation provided linkage log
1036*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_startShaderProgram(qpTestLog * log,bool linkOk,const char * linkInfoLog)1037*35238bceSAndroid Build Coastguard Worker bool qpTestLog_startShaderProgram(qpTestLog *log, bool linkOk, const char *linkInfoLog)
1038*35238bceSAndroid Build Coastguard Worker {
1039*35238bceSAndroid Build Coastguard Worker     qpXmlAttribute programAttribs[4];
1040*35238bceSAndroid Build Coastguard Worker     int numProgramAttribs = 0;
1041*35238bceSAndroid Build Coastguard Worker 
1042*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log);
1043*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
1044*35238bceSAndroid Build Coastguard Worker 
1045*35238bceSAndroid Build Coastguard Worker     programAttribs[numProgramAttribs++] = qpSetStringAttrib("LinkStatus", linkOk ? "OK" : "Fail");
1046*35238bceSAndroid Build Coastguard Worker 
1047*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_startElement(log->writer, "ShaderProgram", numProgramAttribs, programAttribs) ||
1048*35238bceSAndroid Build Coastguard Worker         !qpTestLog_writeInfoLog(log, linkInfoLog))
1049*35238bceSAndroid Build Coastguard Worker     {
1050*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_startShaderProgram(): Writing XML failed\n");
1051*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
1052*35238bceSAndroid Build Coastguard Worker         return false;
1053*35238bceSAndroid Build Coastguard Worker     }
1054*35238bceSAndroid Build Coastguard Worker 
1055*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_SHADERPROGRAM));
1056*35238bceSAndroid Build Coastguard Worker 
1057*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
1058*35238bceSAndroid Build Coastguard Worker     return true;
1059*35238bceSAndroid Build Coastguard Worker }
1060*35238bceSAndroid Build Coastguard Worker 
1061*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
1062*35238bceSAndroid Build Coastguard Worker  * \brief End shader program
1063*35238bceSAndroid Build Coastguard Worker  * \param log            qpTestLog instance
1064*35238bceSAndroid Build Coastguard Worker  * \return true if ok, false otherwise
1065*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_endShaderProgram(qpTestLog * log)1066*35238bceSAndroid Build Coastguard Worker bool qpTestLog_endShaderProgram(qpTestLog *log)
1067*35238bceSAndroid Build Coastguard Worker {
1068*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log);
1069*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
1070*35238bceSAndroid Build Coastguard Worker 
1071*35238bceSAndroid Build Coastguard Worker     /* </ShaderProgram> */
1072*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_endElement(log->writer, "ShaderProgram"))
1073*35238bceSAndroid Build Coastguard Worker     {
1074*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_endShaderProgram(): Writing XML failed\n");
1075*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
1076*35238bceSAndroid Build Coastguard Worker         return false;
1077*35238bceSAndroid Build Coastguard Worker     }
1078*35238bceSAndroid Build Coastguard Worker 
1079*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(ContainerStack_pop(&log->containerStack) == CONTAINERTYPE_SHADERPROGRAM);
1080*35238bceSAndroid Build Coastguard Worker 
1081*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
1082*35238bceSAndroid Build Coastguard Worker     return true;
1083*35238bceSAndroid Build Coastguard Worker }
1084*35238bceSAndroid Build Coastguard Worker 
1085*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
1086*35238bceSAndroid Build Coastguard Worker  * \brief Write a OpenGL ES shader into the log.
1087*35238bceSAndroid Build Coastguard Worker  * \param type                Shader type
1088*35238bceSAndroid Build Coastguard Worker  * \param source            Shader source
1089*35238bceSAndroid Build Coastguard Worker  * \param compileOk            Shader compilation result, false on failure
1090*35238bceSAndroid Build Coastguard Worker  * \param infoLog            Implementation provided shader compilation log
1091*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_writeShader(qpTestLog * log,qpShaderType type,const char * source,bool compileOk,const char * infoLog)1092*35238bceSAndroid Build Coastguard Worker bool qpTestLog_writeShader(qpTestLog *log, qpShaderType type, const char *source, bool compileOk, const char *infoLog)
1093*35238bceSAndroid Build Coastguard Worker {
1094*35238bceSAndroid Build Coastguard Worker     const char *tagName   = QP_LOOKUP_STRING(s_qpShaderTypeMap, type);
1095*35238bceSAndroid Build Coastguard Worker     const char *sourceStr = ((log->flags & QP_TEST_LOG_EXCLUDE_SHADER_SOURCES) == 0 || !compileOk) ? source : "";
1096*35238bceSAndroid Build Coastguard Worker     int numShaderAttribs  = 0;
1097*35238bceSAndroid Build Coastguard Worker     qpXmlAttribute shaderAttribs[4];
1098*35238bceSAndroid Build Coastguard Worker 
1099*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
1100*35238bceSAndroid Build Coastguard Worker 
1101*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(source);
1102*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(ContainerStack_getTop(&log->containerStack) == CONTAINERTYPE_SHADERPROGRAM);
1103*35238bceSAndroid Build Coastguard Worker 
1104*35238bceSAndroid Build Coastguard Worker     shaderAttribs[numShaderAttribs++] = qpSetStringAttrib("CompileStatus", compileOk ? "OK" : "Fail");
1105*35238bceSAndroid Build Coastguard Worker 
1106*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_startElement(log->writer, tagName, numShaderAttribs, shaderAttribs) ||
1107*35238bceSAndroid Build Coastguard Worker         !qpXmlWriter_writeStringElement(log->writer, "ShaderSource", sourceStr) ||
1108*35238bceSAndroid Build Coastguard Worker         !qpTestLog_writeInfoLog(log, infoLog) || !qpXmlWriter_endElement(log->writer, tagName))
1109*35238bceSAndroid Build Coastguard Worker     {
1110*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_writeShader(): Writing XML failed\n");
1111*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
1112*35238bceSAndroid Build Coastguard Worker         return false;
1113*35238bceSAndroid Build Coastguard Worker     }
1114*35238bceSAndroid Build Coastguard Worker 
1115*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
1116*35238bceSAndroid Build Coastguard Worker     return true;
1117*35238bceSAndroid Build Coastguard Worker }
1118*35238bceSAndroid Build Coastguard Worker 
1119*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
1120*35238bceSAndroid Build Coastguard Worker  * \brief Start writing a set of EGL configurations into the log.
1121*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_startEglConfigSet(qpTestLog * log,const char * name,const char * description)1122*35238bceSAndroid Build Coastguard Worker bool qpTestLog_startEglConfigSet(qpTestLog *log, const char *name, const char *description)
1123*35238bceSAndroid Build Coastguard Worker {
1124*35238bceSAndroid Build Coastguard Worker     qpXmlAttribute attribs[4];
1125*35238bceSAndroid Build Coastguard Worker     int numAttribs = 0;
1126*35238bceSAndroid Build Coastguard Worker 
1127*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log && name);
1128*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
1129*35238bceSAndroid Build Coastguard Worker 
1130*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetStringAttrib("Name", name);
1131*35238bceSAndroid Build Coastguard Worker     if (description)
1132*35238bceSAndroid Build Coastguard Worker         attribs[numAttribs++] = qpSetStringAttrib("Description", description);
1133*35238bceSAndroid Build Coastguard Worker 
1134*35238bceSAndroid Build Coastguard Worker     /* <EglConfigSet Name="<name>"> */
1135*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_startElement(log->writer, "EglConfigSet", numAttribs, attribs))
1136*35238bceSAndroid Build Coastguard Worker     {
1137*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_startEglImageSet(): Writing XML failed\n");
1138*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
1139*35238bceSAndroid Build Coastguard Worker         return false;
1140*35238bceSAndroid Build Coastguard Worker     }
1141*35238bceSAndroid Build Coastguard Worker 
1142*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_EGLCONFIGSET));
1143*35238bceSAndroid Build Coastguard Worker 
1144*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
1145*35238bceSAndroid Build Coastguard Worker     return true;
1146*35238bceSAndroid Build Coastguard Worker }
1147*35238bceSAndroid Build Coastguard Worker 
1148*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
1149*35238bceSAndroid Build Coastguard Worker  * \brief End an EGL config set
1150*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_endEglConfigSet(qpTestLog * log)1151*35238bceSAndroid Build Coastguard Worker bool qpTestLog_endEglConfigSet(qpTestLog *log)
1152*35238bceSAndroid Build Coastguard Worker {
1153*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log);
1154*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
1155*35238bceSAndroid Build Coastguard Worker 
1156*35238bceSAndroid Build Coastguard Worker     /* <EglConfigSet Name="<name>"> */
1157*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_endElement(log->writer, "EglConfigSet"))
1158*35238bceSAndroid Build Coastguard Worker     {
1159*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_endEglImageSet(): Writing XML failed\n");
1160*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
1161*35238bceSAndroid Build Coastguard Worker         return false;
1162*35238bceSAndroid Build Coastguard Worker     }
1163*35238bceSAndroid Build Coastguard Worker 
1164*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(ContainerStack_pop(&log->containerStack) == CONTAINERTYPE_EGLCONFIGSET);
1165*35238bceSAndroid Build Coastguard Worker 
1166*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
1167*35238bceSAndroid Build Coastguard Worker     return true;
1168*35238bceSAndroid Build Coastguard Worker }
1169*35238bceSAndroid Build Coastguard Worker 
1170*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
1171*35238bceSAndroid Build Coastguard Worker  * \brief Write an EGL config inside an EGL config set
1172*35238bceSAndroid Build Coastguard Worker  * \see   qpElgConfigInfo for details
1173*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_writeEglConfig(qpTestLog * log,const qpEglConfigInfo * config)1174*35238bceSAndroid Build Coastguard Worker bool qpTestLog_writeEglConfig(qpTestLog *log, const qpEglConfigInfo *config)
1175*35238bceSAndroid Build Coastguard Worker {
1176*35238bceSAndroid Build Coastguard Worker     qpXmlAttribute attribs[64];
1177*35238bceSAndroid Build Coastguard Worker     int numAttribs = 0;
1178*35238bceSAndroid Build Coastguard Worker 
1179*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log && config);
1180*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
1181*35238bceSAndroid Build Coastguard Worker 
1182*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetIntAttrib("BufferSize", config->bufferSize);
1183*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetIntAttrib("RedSize", config->redSize);
1184*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetIntAttrib("GreenSize", config->greenSize);
1185*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetIntAttrib("BlueSize", config->blueSize);
1186*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetIntAttrib("LuminanceSize", config->luminanceSize);
1187*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetIntAttrib("AlphaSize", config->alphaSize);
1188*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetIntAttrib("AlphaMaskSize", config->alphaMaskSize);
1189*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetBoolAttrib("BindToTextureRGB", config->bindToTextureRGB);
1190*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetBoolAttrib("BindToTextureRGBA", config->bindToTextureRGBA);
1191*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetStringAttrib("ColorBufferType", config->colorBufferType);
1192*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetStringAttrib("ConfigCaveat", config->configCaveat);
1193*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetIntAttrib("ConfigID", config->configID);
1194*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetStringAttrib("Conformant", config->conformant);
1195*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetIntAttrib("DepthSize", config->depthSize);
1196*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetIntAttrib("Level", config->level);
1197*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetIntAttrib("MaxPBufferWidth", config->maxPBufferWidth);
1198*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetIntAttrib("MaxPBufferHeight", config->maxPBufferHeight);
1199*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetIntAttrib("MaxPBufferPixels", config->maxPBufferPixels);
1200*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetIntAttrib("MaxSwapInterval", config->maxSwapInterval);
1201*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetIntAttrib("MinSwapInterval", config->minSwapInterval);
1202*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetBoolAttrib("NativeRenderable", config->nativeRenderable);
1203*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetStringAttrib("RenderableType", config->renderableType);
1204*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetIntAttrib("SampleBuffers", config->sampleBuffers);
1205*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetIntAttrib("Samples", config->samples);
1206*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetIntAttrib("StencilSize", config->stencilSize);
1207*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetStringAttrib("SurfaceTypes", config->surfaceTypes);
1208*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetStringAttrib("TransparentType", config->transparentType);
1209*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetIntAttrib("TransparentRedValue", config->transparentRedValue);
1210*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetIntAttrib("TransparentGreenValue", config->transparentGreenValue);
1211*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetIntAttrib("TransparentBlueValue", config->transparentBlueValue);
1212*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(numAttribs <= DE_LENGTH_OF_ARRAY(attribs));
1213*35238bceSAndroid Build Coastguard Worker 
1214*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_startElement(log->writer, "EglConfig", numAttribs, attribs) ||
1215*35238bceSAndroid Build Coastguard Worker         !qpXmlWriter_endElement(log->writer, "EglConfig"))
1216*35238bceSAndroid Build Coastguard Worker     {
1217*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_writeEglConfig(): Writing XML failed\n");
1218*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
1219*35238bceSAndroid Build Coastguard Worker         return false;
1220*35238bceSAndroid Build Coastguard Worker     }
1221*35238bceSAndroid Build Coastguard Worker 
1222*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
1223*35238bceSAndroid Build Coastguard Worker     return true;
1224*35238bceSAndroid Build Coastguard Worker }
1225*35238bceSAndroid Build Coastguard Worker 
1226*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
1227*35238bceSAndroid Build Coastguard Worker  * \brief Start section in log.
1228*35238bceSAndroid Build Coastguard Worker  * \param log            qpTestLog instance
1229*35238bceSAndroid Build Coastguard Worker  * \param name            Section name
1230*35238bceSAndroid Build Coastguard Worker  * \param description    Human readable description
1231*35238bceSAndroid Build Coastguard Worker  * \return true if ok, false otherwise
1232*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_startSection(qpTestLog * log,const char * name,const char * description)1233*35238bceSAndroid Build Coastguard Worker bool qpTestLog_startSection(qpTestLog *log, const char *name, const char *description)
1234*35238bceSAndroid Build Coastguard Worker {
1235*35238bceSAndroid Build Coastguard Worker     qpXmlAttribute attribs[2];
1236*35238bceSAndroid Build Coastguard Worker     int numAttribs = 0;
1237*35238bceSAndroid Build Coastguard Worker 
1238*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log && name);
1239*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
1240*35238bceSAndroid Build Coastguard Worker 
1241*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetStringAttrib("Name", name);
1242*35238bceSAndroid Build Coastguard Worker     if (description)
1243*35238bceSAndroid Build Coastguard Worker         attribs[numAttribs++] = qpSetStringAttrib("Description", description);
1244*35238bceSAndroid Build Coastguard Worker 
1245*35238bceSAndroid Build Coastguard Worker     /* <Section Name="<name>" Description="<description>"> */
1246*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_startElement(log->writer, "Section", numAttribs, attribs))
1247*35238bceSAndroid Build Coastguard Worker     {
1248*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_startSection(): Writing XML failed\n");
1249*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
1250*35238bceSAndroid Build Coastguard Worker         return false;
1251*35238bceSAndroid Build Coastguard Worker     }
1252*35238bceSAndroid Build Coastguard Worker 
1253*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_SECTION));
1254*35238bceSAndroid Build Coastguard Worker 
1255*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
1256*35238bceSAndroid Build Coastguard Worker     return true;
1257*35238bceSAndroid Build Coastguard Worker }
1258*35238bceSAndroid Build Coastguard Worker 
1259*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
1260*35238bceSAndroid Build Coastguard Worker  * \brief End section in log.
1261*35238bceSAndroid Build Coastguard Worker  * \param log            qpTestLog instance
1262*35238bceSAndroid Build Coastguard Worker  * \return true if ok, false otherwise
1263*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_endSection(qpTestLog * log)1264*35238bceSAndroid Build Coastguard Worker bool qpTestLog_endSection(qpTestLog *log)
1265*35238bceSAndroid Build Coastguard Worker {
1266*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log);
1267*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
1268*35238bceSAndroid Build Coastguard Worker 
1269*35238bceSAndroid Build Coastguard Worker     /* </Section> */
1270*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_endElement(log->writer, "Section"))
1271*35238bceSAndroid Build Coastguard Worker     {
1272*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_endSection(): Writing XML failed\n");
1273*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
1274*35238bceSAndroid Build Coastguard Worker         return false;
1275*35238bceSAndroid Build Coastguard Worker     }
1276*35238bceSAndroid Build Coastguard Worker 
1277*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(ContainerStack_pop(&log->containerStack) == CONTAINERTYPE_SECTION);
1278*35238bceSAndroid Build Coastguard Worker 
1279*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
1280*35238bceSAndroid Build Coastguard Worker     return true;
1281*35238bceSAndroid Build Coastguard Worker }
1282*35238bceSAndroid Build Coastguard Worker 
1283*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
1284*35238bceSAndroid Build Coastguard Worker  * \brief Write OpenCL compute kernel source into the log.
1285*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_writeKernelSource(qpTestLog * log,const char * source)1286*35238bceSAndroid Build Coastguard Worker bool qpTestLog_writeKernelSource(qpTestLog *log, const char *source)
1287*35238bceSAndroid Build Coastguard Worker {
1288*35238bceSAndroid Build Coastguard Worker     const char *sourceStr = (log->flags & QP_TEST_LOG_EXCLUDE_SHADER_SOURCES) != 0 ? "" : source;
1289*35238bceSAndroid Build Coastguard Worker 
1290*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log);
1291*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
1292*35238bceSAndroid Build Coastguard Worker 
1293*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_writeStringElement(log->writer, "KernelSource", sourceStr))
1294*35238bceSAndroid Build Coastguard Worker     {
1295*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_writeKernelSource(): Writing XML failed\n");
1296*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
1297*35238bceSAndroid Build Coastguard Worker         return false;
1298*35238bceSAndroid Build Coastguard Worker     }
1299*35238bceSAndroid Build Coastguard Worker 
1300*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
1301*35238bceSAndroid Build Coastguard Worker     return true;
1302*35238bceSAndroid Build Coastguard Worker }
1303*35238bceSAndroid Build Coastguard Worker 
1304*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
1305*35238bceSAndroid Build Coastguard Worker  * \brief Write a SPIR-V module assembly source into the log.
1306*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_writeSpirVAssemblySource(qpTestLog * log,const char * source)1307*35238bceSAndroid Build Coastguard Worker bool qpTestLog_writeSpirVAssemblySource(qpTestLog *log, const char *source)
1308*35238bceSAndroid Build Coastguard Worker {
1309*35238bceSAndroid Build Coastguard Worker     const char *const sourceStr = (log->flags & QP_TEST_LOG_EXCLUDE_SHADER_SOURCES) != 0 ? "" : source;
1310*35238bceSAndroid Build Coastguard Worker 
1311*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
1312*35238bceSAndroid Build Coastguard Worker 
1313*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(ContainerStack_getTop(&log->containerStack) == CONTAINERTYPE_SHADERPROGRAM);
1314*35238bceSAndroid Build Coastguard Worker 
1315*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_writeStringElement(log->writer, "SpirVAssemblySource", sourceStr))
1316*35238bceSAndroid Build Coastguard Worker     {
1317*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_writeSpirVAssemblySource(): Writing XML failed\n");
1318*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
1319*35238bceSAndroid Build Coastguard Worker         return false;
1320*35238bceSAndroid Build Coastguard Worker     }
1321*35238bceSAndroid Build Coastguard Worker 
1322*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
1323*35238bceSAndroid Build Coastguard Worker     return true;
1324*35238bceSAndroid Build Coastguard Worker }
1325*35238bceSAndroid Build Coastguard Worker 
1326*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
1327*35238bceSAndroid Build Coastguard Worker  * \brief Write OpenCL kernel compilation results into the log
1328*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
qpTestLog_writeCompileInfo(qpTestLog * log,const char * name,const char * description,bool compileOk,const char * infoLog)1329*35238bceSAndroid Build Coastguard Worker bool qpTestLog_writeCompileInfo(qpTestLog *log, const char *name, const char *description, bool compileOk,
1330*35238bceSAndroid Build Coastguard Worker                                 const char *infoLog)
1331*35238bceSAndroid Build Coastguard Worker {
1332*35238bceSAndroid Build Coastguard Worker     int numAttribs = 0;
1333*35238bceSAndroid Build Coastguard Worker     qpXmlAttribute attribs[3];
1334*35238bceSAndroid Build Coastguard Worker 
1335*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log && name && description && infoLog);
1336*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
1337*35238bceSAndroid Build Coastguard Worker 
1338*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetStringAttrib("Name", name);
1339*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetStringAttrib("Description", description);
1340*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetStringAttrib("CompileStatus", compileOk ? "OK" : "Fail");
1341*35238bceSAndroid Build Coastguard Worker 
1342*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_startElement(log->writer, "CompileInfo", numAttribs, attribs) ||
1343*35238bceSAndroid Build Coastguard Worker         !qpTestLog_writeInfoLog(log, infoLog) || !qpXmlWriter_endElement(log->writer, "CompileInfo"))
1344*35238bceSAndroid Build Coastguard Worker     {
1345*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_writeCompileInfo(): Writing XML failed\n");
1346*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
1347*35238bceSAndroid Build Coastguard Worker         return false;
1348*35238bceSAndroid Build Coastguard Worker     }
1349*35238bceSAndroid Build Coastguard Worker 
1350*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
1351*35238bceSAndroid Build Coastguard Worker     return true;
1352*35238bceSAndroid Build Coastguard Worker }
1353*35238bceSAndroid Build Coastguard Worker 
qpTestLog_startSampleList(qpTestLog * log,const char * name,const char * description)1354*35238bceSAndroid Build Coastguard Worker bool qpTestLog_startSampleList(qpTestLog *log, const char *name, const char *description)
1355*35238bceSAndroid Build Coastguard Worker {
1356*35238bceSAndroid Build Coastguard Worker     int numAttribs = 0;
1357*35238bceSAndroid Build Coastguard Worker     qpXmlAttribute attribs[2];
1358*35238bceSAndroid Build Coastguard Worker 
1359*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log && name && description);
1360*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
1361*35238bceSAndroid Build Coastguard Worker 
1362*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetStringAttrib("Name", name);
1363*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetStringAttrib("Description", description);
1364*35238bceSAndroid Build Coastguard Worker 
1365*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_startElement(log->writer, "SampleList", numAttribs, attribs))
1366*35238bceSAndroid Build Coastguard Worker     {
1367*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_startSampleList(): Writing XML failed\n");
1368*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
1369*35238bceSAndroid Build Coastguard Worker         return false;
1370*35238bceSAndroid Build Coastguard Worker     }
1371*35238bceSAndroid Build Coastguard Worker 
1372*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_SAMPLELIST));
1373*35238bceSAndroid Build Coastguard Worker 
1374*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
1375*35238bceSAndroid Build Coastguard Worker     return true;
1376*35238bceSAndroid Build Coastguard Worker }
1377*35238bceSAndroid Build Coastguard Worker 
qpTestLog_startSampleInfo(qpTestLog * log)1378*35238bceSAndroid Build Coastguard Worker bool qpTestLog_startSampleInfo(qpTestLog *log)
1379*35238bceSAndroid Build Coastguard Worker {
1380*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log);
1381*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
1382*35238bceSAndroid Build Coastguard Worker 
1383*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_startElement(log->writer, "SampleInfo", 0, DE_NULL))
1384*35238bceSAndroid Build Coastguard Worker     {
1385*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_startSampleInfo(): Writing XML failed\n");
1386*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
1387*35238bceSAndroid Build Coastguard Worker         return false;
1388*35238bceSAndroid Build Coastguard Worker     }
1389*35238bceSAndroid Build Coastguard Worker 
1390*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_SAMPLEINFO));
1391*35238bceSAndroid Build Coastguard Worker 
1392*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
1393*35238bceSAndroid Build Coastguard Worker     return true;
1394*35238bceSAndroid Build Coastguard Worker }
1395*35238bceSAndroid Build Coastguard Worker 
qpTestLog_writeValueInfo(qpTestLog * log,const char * name,const char * description,const char * unit,qpSampleValueTag tag)1396*35238bceSAndroid Build Coastguard Worker bool qpTestLog_writeValueInfo(qpTestLog *log, const char *name, const char *description, const char *unit,
1397*35238bceSAndroid Build Coastguard Worker                               qpSampleValueTag tag)
1398*35238bceSAndroid Build Coastguard Worker {
1399*35238bceSAndroid Build Coastguard Worker     const char *tagName = QP_LOOKUP_STRING(s_qpSampleValueTagMap, tag);
1400*35238bceSAndroid Build Coastguard Worker     int numAttribs      = 0;
1401*35238bceSAndroid Build Coastguard Worker     qpXmlAttribute attribs[4];
1402*35238bceSAndroid Build Coastguard Worker 
1403*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log && name && description && tagName);
1404*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
1405*35238bceSAndroid Build Coastguard Worker 
1406*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(ContainerStack_getTop(&log->containerStack) == CONTAINERTYPE_SAMPLEINFO);
1407*35238bceSAndroid Build Coastguard Worker 
1408*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetStringAttrib("Name", name);
1409*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetStringAttrib("Description", description);
1410*35238bceSAndroid Build Coastguard Worker     attribs[numAttribs++] = qpSetStringAttrib("Tag", tagName);
1411*35238bceSAndroid Build Coastguard Worker 
1412*35238bceSAndroid Build Coastguard Worker     if (unit)
1413*35238bceSAndroid Build Coastguard Worker         attribs[numAttribs++] = qpSetStringAttrib("Unit", unit);
1414*35238bceSAndroid Build Coastguard Worker 
1415*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_startElement(log->writer, "ValueInfo", numAttribs, attribs) ||
1416*35238bceSAndroid Build Coastguard Worker         !qpXmlWriter_endElement(log->writer, "ValueInfo"))
1417*35238bceSAndroid Build Coastguard Worker     {
1418*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_writeValueInfo(): Writing XML failed\n");
1419*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
1420*35238bceSAndroid Build Coastguard Worker         return false;
1421*35238bceSAndroid Build Coastguard Worker     }
1422*35238bceSAndroid Build Coastguard Worker 
1423*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
1424*35238bceSAndroid Build Coastguard Worker     return true;
1425*35238bceSAndroid Build Coastguard Worker }
1426*35238bceSAndroid Build Coastguard Worker 
qpTestLog_endSampleInfo(qpTestLog * log)1427*35238bceSAndroid Build Coastguard Worker bool qpTestLog_endSampleInfo(qpTestLog *log)
1428*35238bceSAndroid Build Coastguard Worker {
1429*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log);
1430*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
1431*35238bceSAndroid Build Coastguard Worker 
1432*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_endElement(log->writer, "SampleInfo"))
1433*35238bceSAndroid Build Coastguard Worker     {
1434*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_endSampleInfo(): Writing XML failed\n");
1435*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
1436*35238bceSAndroid Build Coastguard Worker         return false;
1437*35238bceSAndroid Build Coastguard Worker     }
1438*35238bceSAndroid Build Coastguard Worker 
1439*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(ContainerStack_pop(&log->containerStack) == CONTAINERTYPE_SAMPLEINFO);
1440*35238bceSAndroid Build Coastguard Worker 
1441*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
1442*35238bceSAndroid Build Coastguard Worker     return true;
1443*35238bceSAndroid Build Coastguard Worker }
1444*35238bceSAndroid Build Coastguard Worker 
qpTestLog_startSample(qpTestLog * log)1445*35238bceSAndroid Build Coastguard Worker bool qpTestLog_startSample(qpTestLog *log)
1446*35238bceSAndroid Build Coastguard Worker {
1447*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log);
1448*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
1449*35238bceSAndroid Build Coastguard Worker 
1450*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(ContainerStack_getTop(&log->containerStack) == CONTAINERTYPE_SAMPLELIST);
1451*35238bceSAndroid Build Coastguard Worker 
1452*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_startElement(log->writer, "Sample", 0, DE_NULL))
1453*35238bceSAndroid Build Coastguard Worker     {
1454*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_startSample(): Writing XML failed\n");
1455*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
1456*35238bceSAndroid Build Coastguard Worker         return false;
1457*35238bceSAndroid Build Coastguard Worker     }
1458*35238bceSAndroid Build Coastguard Worker 
1459*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_SAMPLE));
1460*35238bceSAndroid Build Coastguard Worker 
1461*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
1462*35238bceSAndroid Build Coastguard Worker     return true;
1463*35238bceSAndroid Build Coastguard Worker }
1464*35238bceSAndroid Build Coastguard Worker 
qpTestLog_writeValueFloat(qpTestLog * log,double value)1465*35238bceSAndroid Build Coastguard Worker bool qpTestLog_writeValueFloat(qpTestLog *log, double value)
1466*35238bceSAndroid Build Coastguard Worker {
1467*35238bceSAndroid Build Coastguard Worker     char tmpString[512];
1468*35238bceSAndroid Build Coastguard Worker     doubleToString(value, tmpString, (int)sizeof(tmpString));
1469*35238bceSAndroid Build Coastguard Worker 
1470*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
1471*35238bceSAndroid Build Coastguard Worker 
1472*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(ContainerStack_getTop(&log->containerStack) == CONTAINERTYPE_SAMPLE);
1473*35238bceSAndroid Build Coastguard Worker 
1474*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_writeStringElement(log->writer, "Value", &tmpString[0]))
1475*35238bceSAndroid Build Coastguard Worker     {
1476*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_writeSampleValue(): Writing XML failed\n");
1477*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
1478*35238bceSAndroid Build Coastguard Worker         return false;
1479*35238bceSAndroid Build Coastguard Worker     }
1480*35238bceSAndroid Build Coastguard Worker 
1481*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
1482*35238bceSAndroid Build Coastguard Worker     return true;
1483*35238bceSAndroid Build Coastguard Worker }
1484*35238bceSAndroid Build Coastguard Worker 
qpTestLog_writeValueInteger(qpTestLog * log,int64_t value)1485*35238bceSAndroid Build Coastguard Worker bool qpTestLog_writeValueInteger(qpTestLog *log, int64_t value)
1486*35238bceSAndroid Build Coastguard Worker {
1487*35238bceSAndroid Build Coastguard Worker     char tmpString[64];
1488*35238bceSAndroid Build Coastguard Worker     int64ToString(value, tmpString);
1489*35238bceSAndroid Build Coastguard Worker 
1490*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
1491*35238bceSAndroid Build Coastguard Worker 
1492*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(ContainerStack_getTop(&log->containerStack) == CONTAINERTYPE_SAMPLE);
1493*35238bceSAndroid Build Coastguard Worker 
1494*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_writeStringElement(log->writer, "Value", &tmpString[0]))
1495*35238bceSAndroid Build Coastguard Worker     {
1496*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_writeSampleValue(): Writing XML failed\n");
1497*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
1498*35238bceSAndroid Build Coastguard Worker         return false;
1499*35238bceSAndroid Build Coastguard Worker     }
1500*35238bceSAndroid Build Coastguard Worker 
1501*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
1502*35238bceSAndroid Build Coastguard Worker     return true;
1503*35238bceSAndroid Build Coastguard Worker }
1504*35238bceSAndroid Build Coastguard Worker 
qpTestLog_endSample(qpTestLog * log)1505*35238bceSAndroid Build Coastguard Worker bool qpTestLog_endSample(qpTestLog *log)
1506*35238bceSAndroid Build Coastguard Worker {
1507*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log);
1508*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
1509*35238bceSAndroid Build Coastguard Worker 
1510*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_endElement(log->writer, "Sample"))
1511*35238bceSAndroid Build Coastguard Worker     {
1512*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_endSample(): Writing XML failed\n");
1513*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
1514*35238bceSAndroid Build Coastguard Worker         return false;
1515*35238bceSAndroid Build Coastguard Worker     }
1516*35238bceSAndroid Build Coastguard Worker 
1517*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(ContainerStack_pop(&log->containerStack) == CONTAINERTYPE_SAMPLE);
1518*35238bceSAndroid Build Coastguard Worker 
1519*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
1520*35238bceSAndroid Build Coastguard Worker     return true;
1521*35238bceSAndroid Build Coastguard Worker }
1522*35238bceSAndroid Build Coastguard Worker 
qpTestLog_endSampleList(qpTestLog * log)1523*35238bceSAndroid Build Coastguard Worker bool qpTestLog_endSampleList(qpTestLog *log)
1524*35238bceSAndroid Build Coastguard Worker {
1525*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log);
1526*35238bceSAndroid Build Coastguard Worker     deMutex_lock(log->lock);
1527*35238bceSAndroid Build Coastguard Worker 
1528*35238bceSAndroid Build Coastguard Worker     if (!qpXmlWriter_endElement(log->writer, "SampleList"))
1529*35238bceSAndroid Build Coastguard Worker     {
1530*35238bceSAndroid Build Coastguard Worker         qpPrintf("qpTestLog_endSampleList(): Writing XML failed\n");
1531*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(log->lock);
1532*35238bceSAndroid Build Coastguard Worker         return false;
1533*35238bceSAndroid Build Coastguard Worker     }
1534*35238bceSAndroid Build Coastguard Worker 
1535*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(ContainerStack_pop(&log->containerStack) == CONTAINERTYPE_SAMPLELIST);
1536*35238bceSAndroid Build Coastguard Worker 
1537*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(log->lock);
1538*35238bceSAndroid Build Coastguard Worker     return true;
1539*35238bceSAndroid Build Coastguard Worker }
1540*35238bceSAndroid Build Coastguard Worker 
qpTestLog_writeRaw(qpTestLog * log,const char * rawContents)1541*35238bceSAndroid Build Coastguard Worker bool qpTestLog_writeRaw(qpTestLog *log, const char *rawContents)
1542*35238bceSAndroid Build Coastguard Worker {
1543*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log);
1544*35238bceSAndroid Build Coastguard Worker 
1545*35238bceSAndroid Build Coastguard Worker     fseek(log->outputFile, 0, SEEK_END);
1546*35238bceSAndroid Build Coastguard Worker     fprintf(log->outputFile, "%s", rawContents);
1547*35238bceSAndroid Build Coastguard Worker     if (!(log->flags & QP_TEST_LOG_NO_FLUSH))
1548*35238bceSAndroid Build Coastguard Worker         qpTestLog_flushFile(log);
1549*35238bceSAndroid Build Coastguard Worker 
1550*35238bceSAndroid Build Coastguard Worker     return true;
1551*35238bceSAndroid Build Coastguard Worker }
1552*35238bceSAndroid Build Coastguard Worker 
qpTestLog_getLogFlags(const qpTestLog * log)1553*35238bceSAndroid Build Coastguard Worker uint32_t qpTestLog_getLogFlags(const qpTestLog *log)
1554*35238bceSAndroid Build Coastguard Worker {
1555*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(log);
1556*35238bceSAndroid Build Coastguard Worker     return log->flags;
1557*35238bceSAndroid Build Coastguard Worker }
1558*35238bceSAndroid Build Coastguard Worker 
qpGetTestResultName(qpTestResult result)1559*35238bceSAndroid Build Coastguard Worker const char *qpGetTestResultName(qpTestResult result)
1560*35238bceSAndroid Build Coastguard Worker {
1561*35238bceSAndroid Build Coastguard Worker     return QP_LOOKUP_STRING(s_qpTestResultMap, result);
1562*35238bceSAndroid Build Coastguard Worker }
1563*35238bceSAndroid Build Coastguard Worker 
qpTestLog_isCompact(qpTestLog * log)1564*35238bceSAndroid Build Coastguard Worker bool qpTestLog_isCompact(qpTestLog *log)
1565*35238bceSAndroid Build Coastguard Worker {
1566*35238bceSAndroid Build Coastguard Worker     return (log->flags & QP_TEST_LOG_COMPACT) != 0;
1567*35238bceSAndroid Build Coastguard Worker }
1568