1 #ifndef _TCUTESTLOG_HPP
2 #define _TCUTESTLOG_HPP
3 /*-------------------------------------------------------------------------
4 * drawElements Quality Program Tester Core
5 * ----------------------------------------
6 *
7 * Copyright 2014 The Android Open Source Project
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Test Log C++ Wrapper.
24 *//*--------------------------------------------------------------------*/
25
26 #include "tcuDefs.hpp"
27 #include "qpTestLog.h"
28 #include "tcuTexture.hpp"
29
30 #include <sstream>
31
32 namespace tcu
33 {
34
35 class Surface;
36 class MessageBuilder;
37 class LogImageSet;
38 class LogImage;
39 class LogSection;
40 class LogShaderProgram;
41 class LogShader;
42 class LogSpirVAssemblySource;
43 class LogKernelSource;
44 class LogSampleList;
45 class LogValueInfo;
46 class SampleBuilder;
47 template<typename T> class LogNumber;
48
49 /*--------------------------------------------------------------------*//*!
50 * \brief Test log
51 *
52 * TestLog provides convinient C++ API for logging. The API has been designed
53 * around stream operators much like STL iostream library. The following
54 * examples demonstrate how to use TestLog.
55 *
56 * \code
57 * TestLog& log = m_testCtx.getLog();
58 *
59 * // Write message to log.
60 * log << TestLog::Message << "Hello, World!" << TestLog::EndMessage;
61 * int myNumber = 3;
62 * log << TestLog::Message << "Diff is " << myNumber << TestLog::EndMessage;
63 *
64 * // Write image
65 * Surface myImage(256, 256);
66 * log << TestLog::Image("TestImage", "My test image", myImage);
67 *
68 * // Multiple commands can be combined:
69 * log << TestLog::Section("Details", "Test case details")
70 * << TestLog::Message << "Here be dragons" << TestLog::EndMessage
71 * << TestLog::ImageSet("Result", "Result images")
72 * << TestLog::Image("ImageA", "Image A", imageA)
73 * << TestLog::Image("ImageB", "Image B", imageB)
74 * << TestLog::EndImageSet << TestLog::EndSection;
75 * \endcode
76 *//*--------------------------------------------------------------------*/
77 class TestLog
78 {
79 public:
80 // Tokens
81 static const class BeginMessageToken {} Message;
82 static const class EndMessageToken {} EndMessage;
83 static const class EndImageSetToken {} EndImageSet;
84 static const class EndSectionToken {} EndSection;
85 static const class EndShaderProgramToken {} EndShaderProgram;
86 static const class SampleInfoToken {} SampleInfo;
87 static const class EndSampleInfoToken {} EndSampleInfo;
88 static const class BeginSampleToken {} Sample;
89 static const class EndSampleToken {} EndSample;
90 static const class EndSampleListToken {} EndSampleList;
91
92 // Typedefs.
93 typedef LogImageSet ImageSet;
94 typedef LogImage Image;
95 typedef LogSection Section;
96 typedef LogShaderProgram ShaderProgram;
97 typedef LogShader Shader;
98 typedef LogSpirVAssemblySource SpirVAssemblySource;
99 typedef LogKernelSource KernelSource;
100 typedef LogSampleList SampleList;
101 typedef LogValueInfo ValueInfo;
102 typedef LogNumber<float> Float;
103 typedef LogNumber<deInt64> Integer;
104
105 explicit TestLog (const char* fileName, deUint32 flags = 0);
106 ~TestLog (void);
107
108 void writeSessionInfo (std::string additionalInfo = "");
109
110 MessageBuilder operator<< (const BeginMessageToken&);
111 MessageBuilder message (void);
112
113 TestLog& operator<< (const ImageSet& imageSet);
114 TestLog& operator<< (const Image& image);
115 TestLog& operator<< (const EndImageSetToken&);
116
117 TestLog& operator<< (const Section& section);
118 TestLog& operator<< (const EndSectionToken&);
119
120 TestLog& operator<< (const ShaderProgram& shaderProgram);
121 TestLog& operator<< (const EndShaderProgramToken&);
122 TestLog& operator<< (const Shader& shader);
123 TestLog& operator<< (const SpirVAssemblySource& module);
124
125 TestLog& operator<< (const KernelSource& kernelSrc);
126
127 template<typename T>
128 TestLog& operator<< (const LogNumber<T>& number);
129
130 TestLog& operator<< (const SampleList& sampleList);
131 TestLog& operator<< (const SampleInfoToken&);
132 TestLog& operator<< (const ValueInfo& valueInfo);
133 TestLog& operator<< (const EndSampleInfoToken&);
134 SampleBuilder operator<< (const BeginSampleToken&);
135 TestLog& operator<< (const EndSampleListToken&);
136
137 // Raw api
138 void writeMessage (const char* message);
139
140 void startImageSet (const char* name, const char* description);
141 void endImageSet (void);
142 void writeImage (const char* name, const char* description, const ConstPixelBufferAccess& surface, const Vec4& scale, const Vec4& bias, qpImageCompressionMode compressionMode = QP_IMAGE_COMPRESSION_MODE_BEST);
143 void writeImage (const char* name, const char* description, qpImageCompressionMode compressionMode, qpImageFormat format, int width, int height, int stride, const void* data);
144
145 void startSection (const char* name, const char* description);
146 void endSection (void);
147
148 void startShaderProgram (bool linkOk, const char* linkInfoLog);
149 void endShaderProgram (void);
150 void writeShader (qpShaderType type, const char* source, bool compileOk, const char* infoLog);
151 void writeSpirVAssemblySource(const char* source);
152 void writeKernelSource (const char* source);
153 void writeCompileInfo (const char* name, const char* description, bool compileOk, const char* infoLog);
154
155 void writeFloat (const char* name, const char* description, const char* unit, qpKeyValueTag tag, float value);
156 void writeInteger (const char* name, const char* description, const char* unit, qpKeyValueTag tag, deInt64 value);
157
158 void startEglConfigSet (const char* name, const char* description);
159 void writeEglConfig (const qpEglConfigInfo* config);
160 void endEglConfigSet (void);
161
162 void startCase (const char* testCasePath, qpTestCaseType testCaseType);
163 void endCase (qpTestResult result, const char* description);
164 void terminateCase (qpTestResult result);
165
166 void startTestsCasesTime (void);
167 void endTestsCasesTime (void);
168
169 void startSampleList (const std::string& name, const std::string& description);
170 void startSampleInfo (void);
171 void writeValueInfo (const std::string& name, const std::string& description, const std::string& unit, qpSampleValueTag tag);
172 void endSampleInfo (void);
173 void startSample (void);
174 void writeSampleValue (double value);
175 void writeSampleValue (deInt64 value);
176 void endSample (void);
177 void endSampleList (void);
178
179 void writeRaw (const char* rawContents);
180
181 bool isShaderLoggingEnabled (void);
182
183 void supressLogging (bool value);
184 bool isSupressLogging (void);
185 private:
186 TestLog (const TestLog& other); // Not allowed!
187 TestLog& operator= (const TestLog& other); // Not allowed!
188
189 qpTestLog* m_log;
190 bool m_logSupressed;
191 bool m_skipAdditionalDataInLog;
192 };
193
194 class MessageBuilder
195 {
196 public:
MessageBuilder(TestLog* log)197 explicit MessageBuilder (TestLog* log) : m_log(log) {}
~MessageBuilder(void)198 ~MessageBuilder (void) {}
199
toString(void) const200 std::string toString (void) const { return m_str.str(); }
201
202 TestLog& operator<< (const TestLog::EndMessageToken&);
203
204 template <typename T>
205 MessageBuilder& operator<< (const T& value);
206
207 MessageBuilder (const MessageBuilder& other);
208 MessageBuilder& operator= (const MessageBuilder& other);
209
210 private:
211 TestLog* m_log;
212 std::ostringstream m_str;
213 };
214
215 class SampleBuilder
216 {
217 public:
SampleBuilder(TestLog* log)218 SampleBuilder (TestLog* log) : m_log(log) {}
219
operator <<(int v)220 SampleBuilder& operator<< (int v) { m_values.push_back(Value((deInt64)v)); return *this; }
operator <<(deInt64 v)221 SampleBuilder& operator<< (deInt64 v) { m_values.push_back(Value(v)); return *this; }
operator <<(float v)222 SampleBuilder& operator<< (float v) { m_values.push_back(Value((double)v)); return *this; }
operator <<(double v)223 SampleBuilder& operator<< (double v) { m_values.push_back(Value(v)); return *this; }
224
225 TestLog& operator<< (const TestLog::EndSampleToken&);
226
227 private:
228 struct Value
229 {
230 enum Type { TYPE_INT64 = 0, TYPE_FLOAT64, TYPE_LAST };
231
232 Type type;
233 union
234 {
235 deInt64 int64;
236 double float64;
237 } value;
238
Valuetcu::SampleBuilder::Value239 Value (void) : type(TYPE_LAST) { value.int64 = 0; }
Valuetcu::SampleBuilder::Value240 Value (double v) : type(TYPE_FLOAT64) { value.float64 = v; }
Valuetcu::SampleBuilder::Value241 Value (deInt64 v) : type(TYPE_INT64) { value.int64 = v; }
242 };
243
244 TestLog* m_log;
245 std::vector<Value> m_values;
246 };
247
248 class LogImageSet
249 {
250 public:
LogImageSet(const std::string& name, const std::string& description)251 LogImageSet (const std::string& name, const std::string& description)
252 : m_name (name)
253 , m_description (description)
254 {
255 }
256
257 void write (TestLog& log) const;
258
259 private:
260 std::string m_name;
261 std::string m_description;
262 };
263
264 // \note Doesn't take copy of surface contents
265 class LogImage
266 {
267 public:
268 LogImage (const std::string& name, const std::string& description, const Surface& surface, qpImageCompressionMode compression = QP_IMAGE_COMPRESSION_MODE_BEST);
269
270 LogImage (const std::string& name, const std::string& description, const ConstPixelBufferAccess& access, qpImageCompressionMode compression = QP_IMAGE_COMPRESSION_MODE_BEST);
271
272 LogImage (const std::string& name, const std::string& description, const ConstPixelBufferAccess& access, const Vec4& scale, const Vec4& bias, qpImageCompressionMode compression = QP_IMAGE_COMPRESSION_MODE_BEST);
273
274 void write (TestLog& log) const;
275
276 private:
277 std::string m_name;
278 std::string m_description;
279 ConstPixelBufferAccess m_access;
280 Vec4 m_scale;
281 Vec4 m_bias;
282 qpImageCompressionMode m_compression;
283 };
284
285 class LogSection
286 {
287 public:
LogSection(const std::string& name, const std::string& description)288 LogSection (const std::string& name, const std::string& description)
289 : m_name (name)
290 , m_description (description)
291 {
292 }
293
294 void write (TestLog& log) const;
295
296 private:
297 std::string m_name;
298 std::string m_description;
299 };
300
301 class LogShaderProgram
302 {
303 public:
LogShaderProgram(bool linkOk, const std::string& linkInfoLog)304 LogShaderProgram (bool linkOk, const std::string& linkInfoLog)
305 : m_linkOk (linkOk)
306 , m_linkInfoLog (linkInfoLog)
307 {
308 }
309
310 void write (TestLog& log) const;
311
312 private:
313 bool m_linkOk;
314 std::string m_linkInfoLog;
315 };
316
317 class LogShader
318 {
319 public:
LogShader(qpShaderType type, const std::string& source, bool compileOk, const std::string& infoLog)320 LogShader (qpShaderType type, const std::string& source, bool compileOk, const std::string& infoLog)
321 : m_type (type)
322 , m_source (source)
323 , m_compileOk (compileOk)
324 , m_infoLog (infoLog)
325 {
326 }
327
328 void write (TestLog& log) const;
329
330 private:
331 qpShaderType m_type;
332 std::string m_source;
333 bool m_compileOk;
334 std::string m_infoLog;
335 };
336
337 class LogSpirVAssemblySource
338 {
339 public:
LogSpirVAssemblySource(const std::string& source)340 LogSpirVAssemblySource (const std::string& source)
341 : m_source (source)
342 {
343 }
344
345 void write (TestLog& log) const;
346
347 private:
348 std::string m_source;
349 };
350
351 class LogKernelSource
352 {
353 public:
LogKernelSource(const std::string& source)354 explicit LogKernelSource (const std::string& source)
355 : m_source(source)
356 {
357 }
358
359 void write (TestLog& log) const;
360
361 private:
362 std::string m_source;
363 };
364
365 class LogSampleList
366 {
367 public:
LogSampleList(const std::string& name, const std::string& description)368 LogSampleList (const std::string& name, const std::string& description)
369 : m_name (name)
370 , m_description (description)
371 {
372 }
373
374 void write (TestLog& log) const;
375
376 private:
377 std::string m_name;
378 std::string m_description;
379 };
380
381 class LogValueInfo
382 {
383 public:
LogValueInfo(const std::string& name, const std::string& description, const std::string& unit, qpSampleValueTag tag)384 LogValueInfo (const std::string& name, const std::string& description, const std::string& unit, qpSampleValueTag tag)
385 : m_name (name)
386 , m_description (description)
387 , m_unit (unit)
388 , m_tag (tag)
389 {
390 }
391
392 void write (TestLog& log) const;
393
394 private:
395 std::string m_name;
396 std::string m_description;
397 std::string m_unit;
398 qpSampleValueTag m_tag;
399 };
400
401 template<typename T>
402 class LogNumber
403 {
404 public:
LogNumber(const std::string& name, const std::string& desc, const std::string& unit, qpKeyValueTag tag, T value)405 LogNumber (const std::string& name, const std::string& desc, const std::string& unit, qpKeyValueTag tag, T value)
406 : m_name (name)
407 , m_desc (desc)
408 , m_unit (unit)
409 , m_tag (tag)
410 , m_value (value)
411 {
412 }
413
414 void write (TestLog& log) const;
415
416 private:
417 std::string m_name;
418 std::string m_desc;
419 std::string m_unit;
420 qpKeyValueTag m_tag;
421 T m_value;
422 };
423
424 // Section helper that closes section when leaving scope.
425 class ScopedLogSection
426 {
427 public:
ScopedLogSection(TestLog& log, const std::string& name, const std::string& description)428 ScopedLogSection (TestLog& log, const std::string& name, const std::string& description)
429 : m_log(log)
430 {
431 m_log << TestLog::Section(name, description);
432 }
433
~ScopedLogSection(void)434 ~ScopedLogSection (void)
435 {
436 m_log << TestLog::EndSection;
437 }
438
439 private:
440 TestLog& m_log;
441 };
442
443 // TestLog stream operators.
444
operator <<(const ImageSet& imageSet)445 inline TestLog& TestLog::operator<< (const ImageSet& imageSet) { imageSet.write(*this); return *this; }
operator <<(const Image& image)446 inline TestLog& TestLog::operator<< (const Image& image) { image.write(*this); return *this; }
operator <<(const EndImageSetToken&)447 inline TestLog& TestLog::operator<< (const EndImageSetToken&) { endImageSet(); return *this; }
operator <<(const Section& section)448 inline TestLog& TestLog::operator<< (const Section& section) { section.write(*this); return *this; }
operator <<(const EndSectionToken&)449 inline TestLog& TestLog::operator<< (const EndSectionToken&) { endSection(); return *this; }
operator <<(const ShaderProgram& shaderProg)450 inline TestLog& TestLog::operator<< (const ShaderProgram& shaderProg) { shaderProg.write(*this); return *this; }
operator <<(const EndShaderProgramToken&)451 inline TestLog& TestLog::operator<< (const EndShaderProgramToken&) { endShaderProgram(); return *this; }
operator <<(const Shader& shader)452 inline TestLog& TestLog::operator<< (const Shader& shader) { shader.write(*this); return *this; }
operator <<(const SpirVAssemblySource& module)453 inline TestLog& TestLog::operator<< (const SpirVAssemblySource& module) { module.write(*this); return *this; }
operator <<(const KernelSource& kernelSrc)454 inline TestLog& TestLog::operator<< (const KernelSource& kernelSrc) { kernelSrc.write(*this); return *this; }
operator <<(const SampleList& sampleList)455 inline TestLog& TestLog::operator<< (const SampleList& sampleList) { sampleList.write(*this); return *this; }
operator <<(const SampleInfoToken&)456 inline TestLog& TestLog::operator<< (const SampleInfoToken&) { startSampleInfo(); return *this; }
operator <<(const ValueInfo& valueInfo)457 inline TestLog& TestLog::operator<< (const ValueInfo& valueInfo) { valueInfo.write(*this); return *this; }
operator <<(const EndSampleInfoToken&)458 inline TestLog& TestLog::operator<< (const EndSampleInfoToken&) { endSampleInfo(); return *this; }
operator <<(const EndSampleListToken&)459 inline TestLog& TestLog::operator<< (const EndSampleListToken&) { endSampleList(); return *this; }
460
461 template<typename T>
operator <<(const LogNumber<T>& number)462 inline TestLog& TestLog::operator<< (const LogNumber<T>& number)
463 {
464 number.write(*this);
465 return *this;
466 }
467
operator <<(TestLog& log, const std::exception& e)468 inline TestLog& operator<< (TestLog& log, const std::exception& e)
469 {
470 // \todo [2012-10-18 pyry] Print type info?
471 return log << TestLog::Message << e.what() << TestLog::EndMessage;
472 }
473
474 // Utility class inline implementations.
475
476 template <typename T>
operator <<(const T& value)477 inline MessageBuilder& MessageBuilder::operator<< (const T& value)
478 {
479 // Overload stream operator to implement custom format
480 m_str << value;
481 return *this;
482 }
483
operator <<(const BeginMessageToken&)484 inline MessageBuilder TestLog::operator<< (const BeginMessageToken&)
485 {
486 return MessageBuilder(this);
487 }
488
message(void)489 inline MessageBuilder TestLog::message (void)
490 {
491 return MessageBuilder(this);
492 }
493
operator <<(const BeginSampleToken&)494 inline SampleBuilder TestLog::operator<< (const BeginSampleToken&)
495 {
496 return SampleBuilder(this);
497 }
498
write(TestLog& log) const499 inline void LogImageSet::write (TestLog& log) const
500 {
501 log.startImageSet(m_name.c_str(), m_description.c_str());
502 }
503
write(TestLog& log) const504 inline void LogSection::write (TestLog& log) const
505 {
506 log.startSection(m_name.c_str(), m_description.c_str());
507 }
508
write(TestLog& log) const509 inline void LogShaderProgram::write (TestLog& log) const
510 {
511 log.startShaderProgram(m_linkOk, m_linkInfoLog.c_str());
512 }
513
write(TestLog& log) const514 inline void LogShader::write (TestLog& log) const
515 {
516 log.writeShader(m_type, m_source.c_str(), m_compileOk, m_infoLog.c_str());
517 }
518
write(TestLog& log) const519 inline void LogSpirVAssemblySource::write (TestLog& log) const
520 {
521 log.writeSpirVAssemblySource(m_source.c_str());
522 }
523
write(TestLog& log) const524 inline void LogKernelSource::write (TestLog& log) const
525 {
526 log.writeKernelSource(m_source.c_str());
527 }
528
write(TestLog& log) const529 inline void LogSampleList::write (TestLog& log) const
530 {
531 log.startSampleList(m_name, m_description);
532 }
533
write(TestLog& log) const534 inline void LogValueInfo::write (TestLog& log) const
535 {
536 log.writeValueInfo(m_name, m_description, m_unit, m_tag);
537 }
538
539 template<>
write(TestLog& log) const540 inline void LogNumber<float>::write (TestLog& log) const
541 {
542 log.writeFloat(m_name.c_str(), m_desc.c_str(), m_unit.c_str(), m_tag, m_value);
543 }
544
545 template<>
write(TestLog& log) const546 inline void LogNumber<deInt64>::write (TestLog& log) const
547 {
548 log.writeInteger(m_name.c_str(), m_desc.c_str(), m_unit.c_str(), m_tag, m_value);
549 }
550
551 } // tcu
552
553 #endif // _TCUTESTLOG_HPP
554