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 startSampleList (const std::string& name, const std::string& description);
165 void startSampleInfo (void);
166 void writeValueInfo (const std::string& name, const std::string& description, const std::string& unit, qpSampleValueTag tag);
167 void endSampleInfo (void);
168 void startSample (void);
169 void writeSampleValue (double value);
170 void writeSampleValue (deInt64 value);
171 void endSample (void);
172 void endSampleList (void);
173
174 private:
175 TestLog (const TestLog& other); // Not allowed!
176 TestLog& operator= (const TestLog& other); // Not allowed!
177
178 qpTestLog* m_log;
179 };
180
181 class MessageBuilder
182 {
183 public:
MessageBuilder(TestLog * log)184 explicit MessageBuilder (TestLog* log) : m_log(log) {}
~MessageBuilder(void)185 ~MessageBuilder (void) {}
186
toString(void) const187 std::string toString (void) const { return m_str.str(); }
188
189 TestLog& operator<< (const TestLog::EndMessageToken&);
190
191 template <typename T>
192 MessageBuilder& operator<< (const T& value);
193
194 MessageBuilder (const MessageBuilder& other);
195 MessageBuilder& operator= (const MessageBuilder& other);
196
197 private:
198 TestLog* m_log;
199 std::ostringstream m_str;
200 };
201
202 class SampleBuilder
203 {
204 public:
SampleBuilder(TestLog * log)205 SampleBuilder (TestLog* log) : m_log(log) {}
206
operator <<(int v)207 SampleBuilder& operator<< (int v) { m_values.push_back(Value((deInt64)v)); return *this; }
operator <<(deInt64 v)208 SampleBuilder& operator<< (deInt64 v) { m_values.push_back(Value(v)); return *this; }
operator <<(float v)209 SampleBuilder& operator<< (float v) { m_values.push_back(Value((double)v)); return *this; }
operator <<(double v)210 SampleBuilder& operator<< (double v) { m_values.push_back(Value(v)); return *this; }
211
212 TestLog& operator<< (const TestLog::EndSampleToken&);
213
214 private:
215 struct Value
216 {
217 enum Type { TYPE_INT64 = 0, TYPE_FLOAT64, TYPE_LAST };
218
219 Type type;
220 union
221 {
222 deInt64 int64;
223 double float64;
224 } value;
225
Valuetcu::SampleBuilder::Value226 Value (void) : type(TYPE_LAST) { value.int64 = 0; }
Valuetcu::SampleBuilder::Value227 Value (double v) : type(TYPE_FLOAT64) { value.float64 = v; }
Valuetcu::SampleBuilder::Value228 Value (deInt64 v) : type(TYPE_INT64) { value.int64 = v; }
229 };
230
231 TestLog* m_log;
232 std::vector<Value> m_values;
233 };
234
235 class LogImageSet
236 {
237 public:
LogImageSet(const std::string & name,const std::string & description)238 LogImageSet (const std::string& name, const std::string& description)
239 : m_name (name)
240 , m_description (description)
241 {
242 }
243
244 void write (TestLog& log) const;
245
246 private:
247 std::string m_name;
248 std::string m_description;
249 };
250
251 // \note Doesn't take copy of surface contents
252 class LogImage
253 {
254 public:
255 LogImage (const std::string& name, const std::string& description, const Surface& surface, qpImageCompressionMode compression = QP_IMAGE_COMPRESSION_MODE_BEST);
256
257 LogImage (const std::string& name, const std::string& description, const ConstPixelBufferAccess& access, qpImageCompressionMode compression = QP_IMAGE_COMPRESSION_MODE_BEST);
258
259 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);
260
261 void write (TestLog& log) const;
262
263 private:
264 std::string m_name;
265 std::string m_description;
266 ConstPixelBufferAccess m_access;
267 Vec4 m_scale;
268 Vec4 m_bias;
269 qpImageCompressionMode m_compression;
270 };
271
272 class LogSection
273 {
274 public:
LogSection(const std::string & name,const std::string & description)275 LogSection (const std::string& name, const std::string& description)
276 : m_name (name)
277 , m_description (description)
278 {
279 }
280
281 void write (TestLog& log) const;
282
283 private:
284 std::string m_name;
285 std::string m_description;
286 };
287
288 class LogShaderProgram
289 {
290 public:
LogShaderProgram(bool linkOk,const std::string & linkInfoLog)291 LogShaderProgram (bool linkOk, const std::string& linkInfoLog)
292 : m_linkOk (linkOk)
293 , m_linkInfoLog (linkInfoLog)
294 {
295 }
296
297 void write (TestLog& log) const;
298
299 private:
300 bool m_linkOk;
301 std::string m_linkInfoLog;
302 };
303
304 class LogShader
305 {
306 public:
LogShader(qpShaderType type,const std::string & source,bool compileOk,const std::string & infoLog)307 LogShader (qpShaderType type, const std::string& source, bool compileOk, const std::string& infoLog)
308 : m_type (type)
309 , m_source (source)
310 , m_compileOk (compileOk)
311 , m_infoLog (infoLog)
312 {
313 }
314
315 void write (TestLog& log) const;
316
317 private:
318 qpShaderType m_type;
319 std::string m_source;
320 bool m_compileOk;
321 std::string m_infoLog;
322 };
323
324 class LogSpirVAssemblySource
325 {
326 public:
LogSpirVAssemblySource(const std::string & source)327 LogSpirVAssemblySource (const std::string& source)
328 : m_source (source)
329 {
330 }
331
332 void write (TestLog& log) const;
333
334 private:
335 std::string m_source;
336 };
337
338 class LogKernelSource
339 {
340 public:
LogKernelSource(const std::string & source)341 explicit LogKernelSource (const std::string& source)
342 : m_source(source)
343 {
344 }
345
346 void write (TestLog& log) const;
347
348 private:
349 std::string m_source;
350 };
351
352 class LogSampleList
353 {
354 public:
LogSampleList(const std::string & name,const std::string & description)355 LogSampleList (const std::string& name, const std::string& description)
356 : m_name (name)
357 , m_description (description)
358 {
359 }
360
361 void write (TestLog& log) const;
362
363 private:
364 std::string m_name;
365 std::string m_description;
366 };
367
368 class LogValueInfo
369 {
370 public:
LogValueInfo(const std::string & name,const std::string & description,const std::string & unit,qpSampleValueTag tag)371 LogValueInfo (const std::string& name, const std::string& description, const std::string& unit, qpSampleValueTag tag)
372 : m_name (name)
373 , m_description (description)
374 , m_unit (unit)
375 , m_tag (tag)
376 {
377 }
378
379 void write (TestLog& log) const;
380
381 private:
382 std::string m_name;
383 std::string m_description;
384 std::string m_unit;
385 qpSampleValueTag m_tag;
386 };
387
388 template<typename T>
389 class LogNumber
390 {
391 public:
LogNumber(const std::string & name,const std::string & desc,const std::string & unit,qpKeyValueTag tag,T value)392 LogNumber (const std::string& name, const std::string& desc, const std::string& unit, qpKeyValueTag tag, T value)
393 : m_name (name)
394 , m_desc (desc)
395 , m_unit (unit)
396 , m_tag (tag)
397 , m_value (value)
398 {
399 }
400
401 void write (TestLog& log) const;
402
403 private:
404 std::string m_name;
405 std::string m_desc;
406 std::string m_unit;
407 qpKeyValueTag m_tag;
408 T m_value;
409 };
410
411 // Section helper that closes section when leaving scope.
412 class ScopedLogSection
413 {
414 public:
ScopedLogSection(TestLog & log,const std::string & name,const std::string & description)415 ScopedLogSection (TestLog& log, const std::string& name, const std::string& description)
416 : m_log(log)
417 {
418 m_log << TestLog::Section(name, description);
419 }
420
~ScopedLogSection(void)421 ~ScopedLogSection (void)
422 {
423 m_log << TestLog::EndSection;
424 }
425
426 private:
427 TestLog& m_log;
428 };
429
430 // TestLog stream operators.
431
operator <<(const ImageSet & imageSet)432 inline TestLog& TestLog::operator<< (const ImageSet& imageSet) { imageSet.write(*this); return *this; }
operator <<(const Image & image)433 inline TestLog& TestLog::operator<< (const Image& image) { image.write(*this); return *this; }
operator <<(const EndImageSetToken &)434 inline TestLog& TestLog::operator<< (const EndImageSetToken&) { endImageSet(); return *this; }
operator <<(const Section & section)435 inline TestLog& TestLog::operator<< (const Section& section) { section.write(*this); return *this; }
operator <<(const EndSectionToken &)436 inline TestLog& TestLog::operator<< (const EndSectionToken&) { endSection(); return *this; }
operator <<(const ShaderProgram & shaderProg)437 inline TestLog& TestLog::operator<< (const ShaderProgram& shaderProg) { shaderProg.write(*this); return *this; }
operator <<(const EndShaderProgramToken &)438 inline TestLog& TestLog::operator<< (const EndShaderProgramToken&) { endShaderProgram(); return *this; }
operator <<(const Shader & shader)439 inline TestLog& TestLog::operator<< (const Shader& shader) { shader.write(*this); return *this; }
operator <<(const SpirVAssemblySource & module)440 inline TestLog& TestLog::operator<< (const SpirVAssemblySource& module) { module.write(*this); return *this; }
operator <<(const KernelSource & kernelSrc)441 inline TestLog& TestLog::operator<< (const KernelSource& kernelSrc) { kernelSrc.write(*this); return *this; }
operator <<(const SampleList & sampleList)442 inline TestLog& TestLog::operator<< (const SampleList& sampleList) { sampleList.write(*this); return *this; }
operator <<(const SampleInfoToken &)443 inline TestLog& TestLog::operator<< (const SampleInfoToken&) { startSampleInfo(); return *this; }
operator <<(const ValueInfo & valueInfo)444 inline TestLog& TestLog::operator<< (const ValueInfo& valueInfo) { valueInfo.write(*this); return *this; }
operator <<(const EndSampleInfoToken &)445 inline TestLog& TestLog::operator<< (const EndSampleInfoToken&) { endSampleInfo(); return *this; }
operator <<(const EndSampleListToken &)446 inline TestLog& TestLog::operator<< (const EndSampleListToken&) { endSampleList(); return *this; }
447
448 template<typename T>
operator <<(const LogNumber<T> & number)449 inline TestLog& TestLog::operator<< (const LogNumber<T>& number)
450 {
451 number.write(*this);
452 return *this;
453 }
454
operator <<(TestLog & log,const std::exception & e)455 inline TestLog& operator<< (TestLog& log, const std::exception& e)
456 {
457 // \todo [2012-10-18 pyry] Print type info?
458 return log << TestLog::Message << e.what() << TestLog::EndMessage;
459 }
460
461 // Utility class inline implementations.
462
463 template <typename T>
operator <<(const T & value)464 inline MessageBuilder& MessageBuilder::operator<< (const T& value)
465 {
466 // Overload stream operator to implement custom format
467 m_str << value;
468 return *this;
469 }
470
operator <<(const BeginMessageToken &)471 inline MessageBuilder TestLog::operator<< (const BeginMessageToken&)
472 {
473 return MessageBuilder(this);
474 }
475
message(void)476 inline MessageBuilder TestLog::message (void)
477 {
478 return MessageBuilder(this);
479 }
480
operator <<(const BeginSampleToken &)481 inline SampleBuilder TestLog::operator<< (const BeginSampleToken&)
482 {
483 return SampleBuilder(this);
484 }
485
write(TestLog & log) const486 inline void LogImageSet::write (TestLog& log) const
487 {
488 log.startImageSet(m_name.c_str(), m_description.c_str());
489 }
490
write(TestLog & log) const491 inline void LogSection::write (TestLog& log) const
492 {
493 log.startSection(m_name.c_str(), m_description.c_str());
494 }
495
write(TestLog & log) const496 inline void LogShaderProgram::write (TestLog& log) const
497 {
498 log.startShaderProgram(m_linkOk, m_linkInfoLog.c_str());
499 }
500
write(TestLog & log) const501 inline void LogShader::write (TestLog& log) const
502 {
503 log.writeShader(m_type, m_source.c_str(), m_compileOk, m_infoLog.c_str());
504 }
505
write(TestLog & log) const506 inline void LogSpirVAssemblySource::write (TestLog& log) const
507 {
508 log.writeSpirVAssemblySource(m_source.c_str());
509 }
510
write(TestLog & log) const511 inline void LogKernelSource::write (TestLog& log) const
512 {
513 log.writeKernelSource(m_source.c_str());
514 }
515
write(TestLog & log) const516 inline void LogSampleList::write (TestLog& log) const
517 {
518 log.startSampleList(m_name, m_description);
519 }
520
write(TestLog & log) const521 inline void LogValueInfo::write (TestLog& log) const
522 {
523 log.writeValueInfo(m_name, m_description, m_unit, m_tag);
524 }
525
526 template<>
write(TestLog & log) const527 inline void LogNumber<float>::write (TestLog& log) const
528 {
529 log.writeFloat(m_name.c_str(), m_desc.c_str(), m_unit.c_str(), m_tag, m_value);
530 }
531
532 template<>
write(TestLog & log) const533 inline void LogNumber<deInt64>::write (TestLog& log) const
534 {
535 log.writeInteger(m_name.c_str(), m_desc.c_str(), m_unit.c_str(), m_tag, m_value);
536 }
537
538 } // tcu
539
540 #endif // _TCUTESTLOG_HPP
541