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 MessageBuilder operator<< (const BeginMessageToken&);
109 MessageBuilder message (void);
110
111 TestLog& operator<< (const ImageSet& imageSet);
112 TestLog& operator<< (const Image& image);
113 TestLog& operator<< (const EndImageSetToken&);
114
115 TestLog& operator<< (const Section& section);
116 TestLog& operator<< (const EndSectionToken&);
117
118 TestLog& operator<< (const ShaderProgram& shaderProgram);
119 TestLog& operator<< (const EndShaderProgramToken&);
120 TestLog& operator<< (const Shader& shader);
121 TestLog& operator<< (const SpirVAssemblySource& module);
122
123 TestLog& operator<< (const KernelSource& kernelSrc);
124
125 template<typename T>
126 TestLog& operator<< (const LogNumber<T>& number);
127
128 TestLog& operator<< (const SampleList& sampleList);
129 TestLog& operator<< (const SampleInfoToken&);
130 TestLog& operator<< (const ValueInfo& valueInfo);
131 TestLog& operator<< (const EndSampleInfoToken&);
132 SampleBuilder operator<< (const BeginSampleToken&);
133 TestLog& operator<< (const EndSampleListToken&);
134
135 // Raw api
136 void writeMessage (const char* message);
137
138 void startImageSet (const char* name, const char* description);
139 void endImageSet (void);
140 void writeImage (const char* name, const char* description, const ConstPixelBufferAccess& surface, const Vec4& scale, const Vec4& bias, qpImageCompressionMode compressionMode = QP_IMAGE_COMPRESSION_MODE_BEST);
141 void writeImage (const char* name, const char* description, qpImageCompressionMode compressionMode, qpImageFormat format, int width, int height, int stride, const void* data);
142
143 void startSection (const char* name, const char* description);
144 void endSection (void);
145
146 void startShaderProgram (bool linkOk, const char* linkInfoLog);
147 void endShaderProgram (void);
148 void writeShader (qpShaderType type, const char* source, bool compileOk, const char* infoLog);
149 void writeSpirVAssemblySource(const char* source);
150 void writeKernelSource (const char* source);
151 void writeCompileInfo (const char* name, const char* description, bool compileOk, const char* infoLog);
152
153 void writeFloat (const char* name, const char* description, const char* unit, qpKeyValueTag tag, float value);
154 void writeInteger (const char* name, const char* description, const char* unit, qpKeyValueTag tag, deInt64 value);
155
156 void startEglConfigSet (const char* name, const char* description);
157 void writeEglConfig (const qpEglConfigInfo* config);
158 void endEglConfigSet (void);
159
160 void startCase (const char* testCasePath, qpTestCaseType testCaseType);
161 void endCase (qpTestResult result, const char* description);
162 void terminateCase (qpTestResult result);
163
164 void startTestsCasesTime (void);
165 void endTestsCasesTime (void);
166
167 void startSampleList (const std::string& name, const std::string& description);
168 void startSampleInfo (void);
169 void writeValueInfo (const std::string& name, const std::string& description, const std::string& unit, qpSampleValueTag tag);
170 void endSampleInfo (void);
171 void startSample (void);
172 void writeSampleValue (double value);
173 void writeSampleValue (deInt64 value);
174 void endSample (void);
175 void endSampleList (void);
176
177 bool isShaderLoggingEnabled (void);
178 private:
179 TestLog (const TestLog& other); // Not allowed!
180 TestLog& operator= (const TestLog& other); // Not allowed!
181
182 qpTestLog* m_log;
183 };
184
185 class MessageBuilder
186 {
187 public:
MessageBuilder(TestLog * log)188 explicit MessageBuilder (TestLog* log) : m_log(log) {}
~MessageBuilder(void)189 ~MessageBuilder (void) {}
190
toString(void) const191 std::string toString (void) const { return m_str.str(); }
192
193 TestLog& operator<< (const TestLog::EndMessageToken&);
194
195 template <typename T>
196 MessageBuilder& operator<< (const T& value);
197
198 MessageBuilder (const MessageBuilder& other);
199 MessageBuilder& operator= (const MessageBuilder& other);
200
201 private:
202 TestLog* m_log;
203 std::ostringstream m_str;
204 };
205
206 class SampleBuilder
207 {
208 public:
SampleBuilder(TestLog * log)209 SampleBuilder (TestLog* log) : m_log(log) {}
210
operator <<(int v)211 SampleBuilder& operator<< (int v) { m_values.push_back(Value((deInt64)v)); return *this; }
operator <<(deInt64 v)212 SampleBuilder& operator<< (deInt64 v) { m_values.push_back(Value(v)); return *this; }
operator <<(float v)213 SampleBuilder& operator<< (float v) { m_values.push_back(Value((double)v)); return *this; }
operator <<(double v)214 SampleBuilder& operator<< (double v) { m_values.push_back(Value(v)); return *this; }
215
216 TestLog& operator<< (const TestLog::EndSampleToken&);
217
218 private:
219 struct Value
220 {
221 enum Type { TYPE_INT64 = 0, TYPE_FLOAT64, TYPE_LAST };
222
223 Type type;
224 union
225 {
226 deInt64 int64;
227 double float64;
228 } value;
229
Valuetcu::SampleBuilder::Value230 Value (void) : type(TYPE_LAST) { value.int64 = 0; }
Valuetcu::SampleBuilder::Value231 Value (double v) : type(TYPE_FLOAT64) { value.float64 = v; }
Valuetcu::SampleBuilder::Value232 Value (deInt64 v) : type(TYPE_INT64) { value.int64 = v; }
233 };
234
235 TestLog* m_log;
236 std::vector<Value> m_values;
237 };
238
239 class LogImageSet
240 {
241 public:
LogImageSet(const std::string & name,const std::string & description)242 LogImageSet (const std::string& name, const std::string& description)
243 : m_name (name)
244 , m_description (description)
245 {
246 }
247
248 void write (TestLog& log) const;
249
250 private:
251 std::string m_name;
252 std::string m_description;
253 };
254
255 // \note Doesn't take copy of surface contents
256 class LogImage
257 {
258 public:
259 LogImage (const std::string& name, const std::string& description, const Surface& surface, qpImageCompressionMode compression = QP_IMAGE_COMPRESSION_MODE_BEST);
260
261 LogImage (const std::string& name, const std::string& description, const ConstPixelBufferAccess& access, qpImageCompressionMode compression = QP_IMAGE_COMPRESSION_MODE_BEST);
262
263 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);
264
265 void write (TestLog& log) const;
266
267 private:
268 std::string m_name;
269 std::string m_description;
270 ConstPixelBufferAccess m_access;
271 Vec4 m_scale;
272 Vec4 m_bias;
273 qpImageCompressionMode m_compression;
274 };
275
276 class LogSection
277 {
278 public:
LogSection(const std::string & name,const std::string & description)279 LogSection (const std::string& name, const std::string& description)
280 : m_name (name)
281 , m_description (description)
282 {
283 }
284
285 void write (TestLog& log) const;
286
287 private:
288 std::string m_name;
289 std::string m_description;
290 };
291
292 class LogShaderProgram
293 {
294 public:
LogShaderProgram(bool linkOk,const std::string & linkInfoLog)295 LogShaderProgram (bool linkOk, const std::string& linkInfoLog)
296 : m_linkOk (linkOk)
297 , m_linkInfoLog (linkInfoLog)
298 {
299 }
300
301 void write (TestLog& log) const;
302
303 private:
304 bool m_linkOk;
305 std::string m_linkInfoLog;
306 };
307
308 class LogShader
309 {
310 public:
LogShader(qpShaderType type,const std::string & source,bool compileOk,const std::string & infoLog)311 LogShader (qpShaderType type, const std::string& source, bool compileOk, const std::string& infoLog)
312 : m_type (type)
313 , m_source (source)
314 , m_compileOk (compileOk)
315 , m_infoLog (infoLog)
316 {
317 }
318
319 void write (TestLog& log) const;
320
321 private:
322 qpShaderType m_type;
323 std::string m_source;
324 bool m_compileOk;
325 std::string m_infoLog;
326 };
327
328 class LogSpirVAssemblySource
329 {
330 public:
LogSpirVAssemblySource(const std::string & source)331 LogSpirVAssemblySource (const std::string& source)
332 : m_source (source)
333 {
334 }
335
336 void write (TestLog& log) const;
337
338 private:
339 std::string m_source;
340 };
341
342 class LogKernelSource
343 {
344 public:
LogKernelSource(const std::string & source)345 explicit LogKernelSource (const std::string& source)
346 : m_source(source)
347 {
348 }
349
350 void write (TestLog& log) const;
351
352 private:
353 std::string m_source;
354 };
355
356 class LogSampleList
357 {
358 public:
LogSampleList(const std::string & name,const std::string & description)359 LogSampleList (const std::string& name, const std::string& description)
360 : m_name (name)
361 , m_description (description)
362 {
363 }
364
365 void write (TestLog& log) const;
366
367 private:
368 std::string m_name;
369 std::string m_description;
370 };
371
372 class LogValueInfo
373 {
374 public:
LogValueInfo(const std::string & name,const std::string & description,const std::string & unit,qpSampleValueTag tag)375 LogValueInfo (const std::string& name, const std::string& description, const std::string& unit, qpSampleValueTag tag)
376 : m_name (name)
377 , m_description (description)
378 , m_unit (unit)
379 , m_tag (tag)
380 {
381 }
382
383 void write (TestLog& log) const;
384
385 private:
386 std::string m_name;
387 std::string m_description;
388 std::string m_unit;
389 qpSampleValueTag m_tag;
390 };
391
392 template<typename T>
393 class LogNumber
394 {
395 public:
LogNumber(const std::string & name,const std::string & desc,const std::string & unit,qpKeyValueTag tag,T value)396 LogNumber (const std::string& name, const std::string& desc, const std::string& unit, qpKeyValueTag tag, T value)
397 : m_name (name)
398 , m_desc (desc)
399 , m_unit (unit)
400 , m_tag (tag)
401 , m_value (value)
402 {
403 }
404
405 void write (TestLog& log) const;
406
407 private:
408 std::string m_name;
409 std::string m_desc;
410 std::string m_unit;
411 qpKeyValueTag m_tag;
412 T m_value;
413 };
414
415 // Section helper that closes section when leaving scope.
416 class ScopedLogSection
417 {
418 public:
ScopedLogSection(TestLog & log,const std::string & name,const std::string & description)419 ScopedLogSection (TestLog& log, const std::string& name, const std::string& description)
420 : m_log(log)
421 {
422 m_log << TestLog::Section(name, description);
423 }
424
~ScopedLogSection(void)425 ~ScopedLogSection (void)
426 {
427 m_log << TestLog::EndSection;
428 }
429
430 private:
431 TestLog& m_log;
432 };
433
434 // TestLog stream operators.
435
operator <<(const ImageSet & imageSet)436 inline TestLog& TestLog::operator<< (const ImageSet& imageSet) { imageSet.write(*this); return *this; }
operator <<(const Image & image)437 inline TestLog& TestLog::operator<< (const Image& image) { image.write(*this); return *this; }
operator <<(const EndImageSetToken &)438 inline TestLog& TestLog::operator<< (const EndImageSetToken&) { endImageSet(); return *this; }
operator <<(const Section & section)439 inline TestLog& TestLog::operator<< (const Section& section) { section.write(*this); return *this; }
operator <<(const EndSectionToken &)440 inline TestLog& TestLog::operator<< (const EndSectionToken&) { endSection(); return *this; }
operator <<(const ShaderProgram & shaderProg)441 inline TestLog& TestLog::operator<< (const ShaderProgram& shaderProg) { shaderProg.write(*this); return *this; }
operator <<(const EndShaderProgramToken &)442 inline TestLog& TestLog::operator<< (const EndShaderProgramToken&) { endShaderProgram(); return *this; }
operator <<(const Shader & shader)443 inline TestLog& TestLog::operator<< (const Shader& shader) { shader.write(*this); return *this; }
operator <<(const SpirVAssemblySource & module)444 inline TestLog& TestLog::operator<< (const SpirVAssemblySource& module) { module.write(*this); return *this; }
operator <<(const KernelSource & kernelSrc)445 inline TestLog& TestLog::operator<< (const KernelSource& kernelSrc) { kernelSrc.write(*this); return *this; }
operator <<(const SampleList & sampleList)446 inline TestLog& TestLog::operator<< (const SampleList& sampleList) { sampleList.write(*this); return *this; }
operator <<(const SampleInfoToken &)447 inline TestLog& TestLog::operator<< (const SampleInfoToken&) { startSampleInfo(); return *this; }
operator <<(const ValueInfo & valueInfo)448 inline TestLog& TestLog::operator<< (const ValueInfo& valueInfo) { valueInfo.write(*this); return *this; }
operator <<(const EndSampleInfoToken &)449 inline TestLog& TestLog::operator<< (const EndSampleInfoToken&) { endSampleInfo(); return *this; }
operator <<(const EndSampleListToken &)450 inline TestLog& TestLog::operator<< (const EndSampleListToken&) { endSampleList(); return *this; }
451
452 template<typename T>
operator <<(const LogNumber<T> & number)453 inline TestLog& TestLog::operator<< (const LogNumber<T>& number)
454 {
455 number.write(*this);
456 return *this;
457 }
458
operator <<(TestLog & log,const std::exception & e)459 inline TestLog& operator<< (TestLog& log, const std::exception& e)
460 {
461 // \todo [2012-10-18 pyry] Print type info?
462 return log << TestLog::Message << e.what() << TestLog::EndMessage;
463 }
464
465 // Utility class inline implementations.
466
467 template <typename T>
operator <<(const T & value)468 inline MessageBuilder& MessageBuilder::operator<< (const T& value)
469 {
470 // Overload stream operator to implement custom format
471 m_str << value;
472 return *this;
473 }
474
operator <<(const BeginMessageToken &)475 inline MessageBuilder TestLog::operator<< (const BeginMessageToken&)
476 {
477 return MessageBuilder(this);
478 }
479
message(void)480 inline MessageBuilder TestLog::message (void)
481 {
482 return MessageBuilder(this);
483 }
484
operator <<(const BeginSampleToken &)485 inline SampleBuilder TestLog::operator<< (const BeginSampleToken&)
486 {
487 return SampleBuilder(this);
488 }
489
write(TestLog & log) const490 inline void LogImageSet::write (TestLog& log) const
491 {
492 log.startImageSet(m_name.c_str(), m_description.c_str());
493 }
494
write(TestLog & log) const495 inline void LogSection::write (TestLog& log) const
496 {
497 log.startSection(m_name.c_str(), m_description.c_str());
498 }
499
write(TestLog & log) const500 inline void LogShaderProgram::write (TestLog& log) const
501 {
502 log.startShaderProgram(m_linkOk, m_linkInfoLog.c_str());
503 }
504
write(TestLog & log) const505 inline void LogShader::write (TestLog& log) const
506 {
507 log.writeShader(m_type, m_source.c_str(), m_compileOk, m_infoLog.c_str());
508 }
509
write(TestLog & log) const510 inline void LogSpirVAssemblySource::write (TestLog& log) const
511 {
512 log.writeSpirVAssemblySource(m_source.c_str());
513 }
514
write(TestLog & log) const515 inline void LogKernelSource::write (TestLog& log) const
516 {
517 log.writeKernelSource(m_source.c_str());
518 }
519
write(TestLog & log) const520 inline void LogSampleList::write (TestLog& log) const
521 {
522 log.startSampleList(m_name, m_description);
523 }
524
write(TestLog & log) const525 inline void LogValueInfo::write (TestLog& log) const
526 {
527 log.writeValueInfo(m_name, m_description, m_unit, m_tag);
528 }
529
530 template<>
write(TestLog & log) const531 inline void LogNumber<float>::write (TestLog& log) const
532 {
533 log.writeFloat(m_name.c_str(), m_desc.c_str(), m_unit.c_str(), m_tag, m_value);
534 }
535
536 template<>
write(TestLog & log) const537 inline void LogNumber<deInt64>::write (TestLog& log) const
538 {
539 log.writeInteger(m_name.c_str(), m_desc.c_str(), m_unit.c_str(), m_tag, m_value);
540 }
541
542 } // tcu
543
544 #endif // _TCUTESTLOG_HPP
545