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>
48 class LogNumber;
49
50 /*--------------------------------------------------------------------*//*!
51 * \brief Test log
52 *
53 * TestLog provides convinient C++ API for logging. The API has been designed
54 * around stream operators much like STL iostream library. The following
55 * examples demonstrate how to use TestLog.
56 *
57 * \code
58 * TestLog& log = m_testCtx.getLog();
59 *
60 * // Write message to log.
61 * log << TestLog::Message << "Hello, World!" << TestLog::EndMessage;
62 * int myNumber = 3;
63 * log << TestLog::Message << "Diff is " << myNumber << TestLog::EndMessage;
64 *
65 * // Write image
66 * Surface myImage(256, 256);
67 * log << TestLog::Image("TestImage", "My test image", myImage);
68 *
69 * // Multiple commands can be combined:
70 * log << TestLog::Section("Details", "Test case details")
71 * << TestLog::Message << "Here be dragons" << TestLog::EndMessage
72 * << TestLog::ImageSet("Result", "Result images")
73 * << TestLog::Image("ImageA", "Image A", imageA)
74 * << TestLog::Image("ImageB", "Image B", imageB)
75 * << TestLog::EndImageSet << TestLog::EndSection;
76 * \endcode
77 *//*--------------------------------------------------------------------*/
78 class TestLog
79 {
80 public:
81 // Tokens
82 static const class BeginMessageToken
83 {
84 } Message;
85 static const class EndMessageToken
86 {
87 } EndMessage;
88 static const class EndImageSetToken
89 {
90 } EndImageSet;
91 static const class EndSectionToken
92 {
93 } EndSection;
94 static const class EndShaderProgramToken
95 {
96 } EndShaderProgram;
97 static const class SampleInfoToken
98 {
99 } SampleInfo;
100 static const class EndSampleInfoToken
101 {
102 } EndSampleInfo;
103 static const class BeginSampleToken
104 {
105 } Sample;
106 static const class EndSampleToken
107 {
108 } EndSample;
109 static const class EndSampleListToken
110 {
111 } EndSampleList;
112
113 // Typedefs.
114 typedef LogImageSet ImageSet;
115 typedef LogImage Image;
116 typedef LogSection Section;
117 typedef LogShaderProgram ShaderProgram;
118 typedef LogShader Shader;
119 typedef LogSpirVAssemblySource SpirVAssemblySource;
120 typedef LogKernelSource KernelSource;
121 typedef LogSampleList SampleList;
122 typedef LogValueInfo ValueInfo;
123 typedef LogNumber<float> Float;
124 typedef LogNumber<int64_t> Integer;
125
126 explicit TestLog(const char *fileName, uint32_t flags = 0);
127 ~TestLog(void);
128
129 void writeSessionInfo(std::string additionalInfo = "");
130
131 MessageBuilder operator<<(const BeginMessageToken &);
132 MessageBuilder message(void);
133
134 TestLog &operator<<(const ImageSet &imageSet);
135 TestLog &operator<<(const Image &image);
136 TestLog &operator<<(const EndImageSetToken &);
137
138 TestLog &operator<<(const Section §ion);
139 TestLog &operator<<(const EndSectionToken &);
140
141 TestLog &operator<<(const ShaderProgram &shaderProgram);
142 TestLog &operator<<(const EndShaderProgramToken &);
143 TestLog &operator<<(const Shader &shader);
144 TestLog &operator<<(const SpirVAssemblySource &module);
145
146 TestLog &operator<<(const KernelSource &kernelSrc);
147
148 template <typename T>
149 TestLog &operator<<(const LogNumber<T> &number);
150
151 TestLog &operator<<(const SampleList &sampleList);
152 TestLog &operator<<(const SampleInfoToken &);
153 TestLog &operator<<(const ValueInfo &valueInfo);
154 TestLog &operator<<(const EndSampleInfoToken &);
155 SampleBuilder operator<<(const BeginSampleToken &);
156 TestLog &operator<<(const EndSampleListToken &);
157
158 // Raw api
159 void writeMessage(const char *message);
160
161 void startImageSet(const char *name, const char *description);
162 void endImageSet(void);
163 void writeImage(const char *name, const char *description, const ConstPixelBufferAccess &surface, const Vec4 &scale,
164 const Vec4 &bias, qpImageCompressionMode compressionMode = QP_IMAGE_COMPRESSION_MODE_BEST);
165 void writeImage(const char *name, const char *description, qpImageCompressionMode compressionMode,
166 qpImageFormat format, int width, int height, int stride, const void *data);
167
168 void startSection(const char *name, const char *description);
169 void endSection(void);
170
171 void startShaderProgram(bool linkOk, const char *linkInfoLog);
172 void endShaderProgram(void);
173 void writeShader(qpShaderType type, const char *source, bool compileOk, const char *infoLog);
174 void writeSpirVAssemblySource(const char *source);
175 void writeKernelSource(const char *source);
176 void writeCompileInfo(const char *name, const char *description, bool compileOk, const char *infoLog);
177
178 void writeFloat(const char *name, const char *description, const char *unit, qpKeyValueTag tag, float value);
179 void writeInteger(const char *name, const char *description, const char *unit, qpKeyValueTag tag, int64_t value);
180
181 void startEglConfigSet(const char *name, const char *description);
182 void writeEglConfig(const qpEglConfigInfo *config);
183 void endEglConfigSet(void);
184
185 void startCase(const char *testCasePath, qpTestCaseType testCaseType);
186 void endCase(qpTestResult result, const char *description);
187 void terminateCase(qpTestResult result);
188
189 void startTestsCasesTime(void);
190 void endTestsCasesTime(void);
191
192 void startSampleList(const std::string &name, const std::string &description);
193 void startSampleInfo(void);
194 void writeValueInfo(const std::string &name, const std::string &description, const std::string &unit,
195 qpSampleValueTag tag);
196 void endSampleInfo(void);
197 void startSample(void);
198 void writeSampleValue(double value);
199 void writeSampleValue(int64_t value);
200 void endSample(void);
201 void endSampleList(void);
202
203 void writeRaw(const char *rawContents);
204
205 bool isShaderLoggingEnabled(void);
206
207 void supressLogging(bool value);
208 bool isSupressLogging(void);
209
210 private:
211 TestLog(const TestLog &other); // Not allowed!
212 TestLog &operator=(const TestLog &other); // Not allowed!
213
214 qpTestLog *m_log;
215 bool m_logSupressed;
216 bool m_skipAdditionalDataInLog;
217 };
218
219 class MessageBuilder
220 {
221 public:
MessageBuilder(TestLog * log)222 explicit MessageBuilder(TestLog *log) : m_log(log)
223 {
224 }
~MessageBuilder(void)225 ~MessageBuilder(void)
226 {
227 }
228
toString(void) const229 std::string toString(void) const
230 {
231 return m_str.str();
232 }
233
234 TestLog &operator<<(const TestLog::EndMessageToken &);
235
236 template <typename T>
237 MessageBuilder &operator<<(const T &value);
238
239 MessageBuilder(const MessageBuilder &other);
240 MessageBuilder &operator=(const MessageBuilder &other);
241
242 private:
243 TestLog *m_log;
244 std::ostringstream m_str;
245 };
246
247 class SampleBuilder
248 {
249 public:
SampleBuilder(TestLog * log)250 SampleBuilder(TestLog *log) : m_log(log)
251 {
252 }
253
operator <<(int v)254 SampleBuilder &operator<<(int v)
255 {
256 m_values.push_back(Value((int64_t)v));
257 return *this;
258 }
operator <<(int64_t v)259 SampleBuilder &operator<<(int64_t v)
260 {
261 m_values.push_back(Value(v));
262 return *this;
263 }
operator <<(float v)264 SampleBuilder &operator<<(float v)
265 {
266 m_values.push_back(Value((double)v));
267 return *this;
268 }
operator <<(double v)269 SampleBuilder &operator<<(double v)
270 {
271 m_values.push_back(Value(v));
272 return *this;
273 }
274
275 TestLog &operator<<(const TestLog::EndSampleToken &);
276
277 private:
278 struct Value
279 {
280 enum Type
281 {
282 TYPE_INT64 = 0,
283 TYPE_FLOAT64,
284 TYPE_LAST
285 };
286
287 Type type;
288 union
289 {
290 int64_t int64;
291 double float64;
292 } value;
293
Valuetcu::SampleBuilder::Value294 Value(void) : type(TYPE_LAST)
295 {
296 value.int64 = 0;
297 }
Valuetcu::SampleBuilder::Value298 Value(double v) : type(TYPE_FLOAT64)
299 {
300 value.float64 = v;
301 }
Valuetcu::SampleBuilder::Value302 Value(int64_t v) : type(TYPE_INT64)
303 {
304 value.int64 = v;
305 }
306 };
307
308 TestLog *m_log;
309 std::vector<Value> m_values;
310 };
311
312 class LogImageSet
313 {
314 public:
LogImageSet(const std::string & name,const std::string & description)315 LogImageSet(const std::string &name, const std::string &description) : m_name(name), m_description(description)
316 {
317 }
318
319 void write(TestLog &log) const;
320
321 private:
322 std::string m_name;
323 std::string m_description;
324 };
325
326 // \note Doesn't take copy of surface contents
327 class LogImage
328 {
329 public:
330 LogImage(const std::string &name, const std::string &description, const Surface &surface,
331 qpImageCompressionMode compression = QP_IMAGE_COMPRESSION_MODE_BEST);
332
333 LogImage(const std::string &name, const std::string &description, const ConstPixelBufferAccess &access,
334 qpImageCompressionMode compression = QP_IMAGE_COMPRESSION_MODE_BEST);
335
336 LogImage(const std::string &name, const std::string &description, const ConstPixelBufferAccess &access,
337 const Vec4 &scale, const Vec4 &bias, qpImageCompressionMode compression = QP_IMAGE_COMPRESSION_MODE_BEST);
338
339 void write(TestLog &log) const;
340
341 private:
342 std::string m_name;
343 std::string m_description;
344 ConstPixelBufferAccess m_access;
345 Vec4 m_scale;
346 Vec4 m_bias;
347 qpImageCompressionMode m_compression;
348 };
349
350 class LogSection
351 {
352 public:
LogSection(const std::string & name,const std::string & description)353 LogSection(const std::string &name, const std::string &description) : m_name(name), m_description(description)
354 {
355 }
356
357 void write(TestLog &log) const;
358
359 private:
360 std::string m_name;
361 std::string m_description;
362 };
363
364 class LogShaderProgram
365 {
366 public:
LogShaderProgram(bool linkOk,const std::string & linkInfoLog)367 LogShaderProgram(bool linkOk, const std::string &linkInfoLog) : m_linkOk(linkOk), m_linkInfoLog(linkInfoLog)
368 {
369 }
370
371 void write(TestLog &log) const;
372
373 private:
374 bool m_linkOk;
375 std::string m_linkInfoLog;
376 };
377
378 class LogShader
379 {
380 public:
LogShader(qpShaderType type,const std::string & source,bool compileOk,const std::string & infoLog)381 LogShader(qpShaderType type, const std::string &source, bool compileOk, const std::string &infoLog)
382 : m_type(type)
383 , m_source(source)
384 , m_compileOk(compileOk)
385 , m_infoLog(infoLog)
386 {
387 }
388
389 void write(TestLog &log) const;
390
391 private:
392 qpShaderType m_type;
393 std::string m_source;
394 bool m_compileOk;
395 std::string m_infoLog;
396 };
397
398 class LogSpirVAssemblySource
399 {
400 public:
LogSpirVAssemblySource(const std::string & source)401 LogSpirVAssemblySource(const std::string &source) : m_source(source)
402 {
403 }
404
405 void write(TestLog &log) const;
406
407 private:
408 std::string m_source;
409 };
410
411 class LogKernelSource
412 {
413 public:
LogKernelSource(const std::string & source)414 explicit LogKernelSource(const std::string &source) : m_source(source)
415 {
416 }
417
418 void write(TestLog &log) const;
419
420 private:
421 std::string m_source;
422 };
423
424 class LogSampleList
425 {
426 public:
LogSampleList(const std::string & name,const std::string & description)427 LogSampleList(const std::string &name, const std::string &description) : m_name(name), m_description(description)
428 {
429 }
430
431 void write(TestLog &log) const;
432
433 private:
434 std::string m_name;
435 std::string m_description;
436 };
437
438 class LogValueInfo
439 {
440 public:
LogValueInfo(const std::string & name,const std::string & description,const std::string & unit,qpSampleValueTag tag)441 LogValueInfo(const std::string &name, const std::string &description, const std::string &unit, qpSampleValueTag tag)
442 : m_name(name)
443 , m_description(description)
444 , m_unit(unit)
445 , m_tag(tag)
446 {
447 }
448
449 void write(TestLog &log) const;
450
451 private:
452 std::string m_name;
453 std::string m_description;
454 std::string m_unit;
455 qpSampleValueTag m_tag;
456 };
457
458 template <typename T>
459 class LogNumber
460 {
461 public:
LogNumber(const std::string & name,const std::string & desc,const std::string & unit,qpKeyValueTag tag,T value)462 LogNumber(const std::string &name, const std::string &desc, const std::string &unit, qpKeyValueTag tag, T value)
463 : m_name(name)
464 , m_desc(desc)
465 , m_unit(unit)
466 , m_tag(tag)
467 , m_value(value)
468 {
469 }
470
471 void write(TestLog &log) const;
472
473 private:
474 std::string m_name;
475 std::string m_desc;
476 std::string m_unit;
477 qpKeyValueTag m_tag;
478 T m_value;
479 };
480
481 // Section helper that closes section when leaving scope.
482 class ScopedLogSection
483 {
484 public:
ScopedLogSection(TestLog & log,const std::string & name,const std::string & description)485 ScopedLogSection(TestLog &log, const std::string &name, const std::string &description) : m_log(log)
486 {
487 m_log << TestLog::Section(name, description);
488 }
489
~ScopedLogSection(void)490 ~ScopedLogSection(void)
491 {
492 m_log << TestLog::EndSection;
493 }
494
495 private:
496 TestLog &m_log;
497 };
498
499 // TestLog stream operators.
500
operator <<(const ImageSet & imageSet)501 inline TestLog &TestLog::operator<<(const ImageSet &imageSet)
502 {
503 imageSet.write(*this);
504 return *this;
505 }
operator <<(const Image & image)506 inline TestLog &TestLog::operator<<(const Image &image)
507 {
508 image.write(*this);
509 return *this;
510 }
operator <<(const EndImageSetToken &)511 inline TestLog &TestLog::operator<<(const EndImageSetToken &)
512 {
513 endImageSet();
514 return *this;
515 }
operator <<(const Section & section)516 inline TestLog &TestLog::operator<<(const Section §ion)
517 {
518 section.write(*this);
519 return *this;
520 }
operator <<(const EndSectionToken &)521 inline TestLog &TestLog::operator<<(const EndSectionToken &)
522 {
523 endSection();
524 return *this;
525 }
operator <<(const ShaderProgram & shaderProg)526 inline TestLog &TestLog::operator<<(const ShaderProgram &shaderProg)
527 {
528 shaderProg.write(*this);
529 return *this;
530 }
operator <<(const EndShaderProgramToken &)531 inline TestLog &TestLog::operator<<(const EndShaderProgramToken &)
532 {
533 endShaderProgram();
534 return *this;
535 }
operator <<(const Shader & shader)536 inline TestLog &TestLog::operator<<(const Shader &shader)
537 {
538 shader.write(*this);
539 return *this;
540 }
operator <<(const SpirVAssemblySource & module)541 inline TestLog &TestLog::operator<<(const SpirVAssemblySource &module)
542 {
543 module.write(*this);
544 return *this;
545 }
operator <<(const KernelSource & kernelSrc)546 inline TestLog &TestLog::operator<<(const KernelSource &kernelSrc)
547 {
548 kernelSrc.write(*this);
549 return *this;
550 }
operator <<(const SampleList & sampleList)551 inline TestLog &TestLog::operator<<(const SampleList &sampleList)
552 {
553 sampleList.write(*this);
554 return *this;
555 }
operator <<(const SampleInfoToken &)556 inline TestLog &TestLog::operator<<(const SampleInfoToken &)
557 {
558 startSampleInfo();
559 return *this;
560 }
operator <<(const ValueInfo & valueInfo)561 inline TestLog &TestLog::operator<<(const ValueInfo &valueInfo)
562 {
563 valueInfo.write(*this);
564 return *this;
565 }
operator <<(const EndSampleInfoToken &)566 inline TestLog &TestLog::operator<<(const EndSampleInfoToken &)
567 {
568 endSampleInfo();
569 return *this;
570 }
operator <<(const EndSampleListToken &)571 inline TestLog &TestLog::operator<<(const EndSampleListToken &)
572 {
573 endSampleList();
574 return *this;
575 }
576
577 template <typename T>
operator <<(const LogNumber<T> & number)578 inline TestLog &TestLog::operator<<(const LogNumber<T> &number)
579 {
580 number.write(*this);
581 return *this;
582 }
583
operator <<(TestLog & log,const std::exception & e)584 inline TestLog &operator<<(TestLog &log, const std::exception &e)
585 {
586 // \todo [2012-10-18 pyry] Print type info?
587 return log << TestLog::Message << e.what() << TestLog::EndMessage;
588 }
589
590 // Utility class inline implementations.
591
592 template <typename T>
operator <<(const T & value)593 inline MessageBuilder &MessageBuilder::operator<<(const T &value)
594 {
595 // Overload stream operator to implement custom format
596 m_str << value;
597 return *this;
598 }
599
operator <<(const BeginMessageToken &)600 inline MessageBuilder TestLog::operator<<(const BeginMessageToken &)
601 {
602 return MessageBuilder(this);
603 }
604
message(void)605 inline MessageBuilder TestLog::message(void)
606 {
607 return MessageBuilder(this);
608 }
609
operator <<(const BeginSampleToken &)610 inline SampleBuilder TestLog::operator<<(const BeginSampleToken &)
611 {
612 return SampleBuilder(this);
613 }
614
write(TestLog & log) const615 inline void LogImageSet::write(TestLog &log) const
616 {
617 log.startImageSet(m_name.c_str(), m_description.c_str());
618 }
619
write(TestLog & log) const620 inline void LogSection::write(TestLog &log) const
621 {
622 log.startSection(m_name.c_str(), m_description.c_str());
623 }
624
write(TestLog & log) const625 inline void LogShaderProgram::write(TestLog &log) const
626 {
627 log.startShaderProgram(m_linkOk, m_linkInfoLog.c_str());
628 }
629
write(TestLog & log) const630 inline void LogShader::write(TestLog &log) const
631 {
632 log.writeShader(m_type, m_source.c_str(), m_compileOk, m_infoLog.c_str());
633 }
634
write(TestLog & log) const635 inline void LogSpirVAssemblySource::write(TestLog &log) const
636 {
637 log.writeSpirVAssemblySource(m_source.c_str());
638 }
639
write(TestLog & log) const640 inline void LogKernelSource::write(TestLog &log) const
641 {
642 log.writeKernelSource(m_source.c_str());
643 }
644
write(TestLog & log) const645 inline void LogSampleList::write(TestLog &log) const
646 {
647 log.startSampleList(m_name, m_description);
648 }
649
write(TestLog & log) const650 inline void LogValueInfo::write(TestLog &log) const
651 {
652 log.writeValueInfo(m_name, m_description, m_unit, m_tag);
653 }
654
655 template <>
write(TestLog & log) const656 inline void LogNumber<float>::write(TestLog &log) const
657 {
658 log.writeFloat(m_name.c_str(), m_desc.c_str(), m_unit.c_str(), m_tag, m_value);
659 }
660
661 template <>
write(TestLog & log) const662 inline void LogNumber<int64_t>::write(TestLog &log) const
663 {
664 log.writeInteger(m_name.c_str(), m_desc.c_str(), m_unit.c_str(), m_tag, m_value);
665 }
666
667 } // namespace tcu
668
669 #endif // _TCUTESTLOG_HPP
670