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 LogKernelSource;
43 class LogSampleList;
44 class LogValueInfo;
45 class SampleBuilder;
46 template<typename T> class LogNumber;
47
48 /*--------------------------------------------------------------------*//*!
49 * \brief Test log
50 *
51 * TestLog provides convinient C++ API for logging. The API has been designed
52 * around stream operators much like STL iostream library. The following
53 * examples demonstrate how to use TestLog.
54 *
55 * \code
56 * TestLog& log = m_testCtx.getLog();
57 *
58 * // Write message to log.
59 * log << TestLog::Message << "Hello, World!" << TestLog::EndMessage;
60 * int myNumber = 3;
61 * log << TestLog::Message << "Diff is " << myNumber << TestLog::EndMessage;
62 *
63 * // Write image
64 * Surface myImage(256, 256);
65 * log << TestLog::Image("TestImage", "My test image", myImage);
66 *
67 * // Multiple commands can be combined:
68 * log << TestLog::Section("Details", "Test case details")
69 * << TestLog::Message << "Here be dragons" << TestLog::EndMessage
70 * << TestLog::ImageSet("Result", "Result images")
71 * << TestLog::Image("ImageA", "Image A", imageA)
72 * << TestLog::Image("ImageB", "Image B", imageB)
73 * << TestLog::EndImageSet << TestLog::EndSection;
74 * \endcode
75 *//*--------------------------------------------------------------------*/
76 class TestLog
77 {
78 public:
79 // Tokens
80 static const class BeginMessageToken {} Message;
81 static const class EndMessageToken {} EndMessage;
82 static const class EndImageSetToken {} EndImageSet;
83 static const class EndSectionToken {} EndSection;
84 static const class EndShaderProgramToken {} EndShaderProgram;
85 static const class SampleInfoToken {} SampleInfo;
86 static const class EndSampleInfoToken {} EndSampleInfo;
87 static const class BeginSampleToken {} Sample;
88 static const class EndSampleToken {} EndSample;
89 static const class EndSampleListToken {} EndSampleList;
90
91 // Typedefs.
92 typedef LogImageSet ImageSet;
93 typedef LogImage Image;
94 typedef LogSection Section;
95 typedef LogShaderProgram ShaderProgram;
96 typedef LogShader Shader;
97 typedef LogKernelSource KernelSource;
98 typedef LogSampleList SampleList;
99 typedef LogValueInfo ValueInfo;
100 typedef LogNumber<float> Float;
101 typedef LogNumber<deInt64> Integer;
102
103 explicit TestLog (const char* fileName, deUint32 flags = 0);
104 ~TestLog (void);
105
106 MessageBuilder operator<< (const BeginMessageToken&);
107 MessageBuilder message (void);
108
109 TestLog& operator<< (const ImageSet& imageSet);
110 TestLog& operator<< (const Image& image);
111 TestLog& operator<< (const EndImageSetToken&);
112
113 TestLog& operator<< (const Section& section);
114 TestLog& operator<< (const EndSectionToken&);
115
116 TestLog& operator<< (const ShaderProgram& shaderProgram);
117 TestLog& operator<< (const EndShaderProgramToken&);
118 TestLog& operator<< (const Shader& shader);
119
120 TestLog& operator<< (const KernelSource& kernelSrc);
121
122 template<typename T>
123 TestLog& operator<< (const LogNumber<T>& number);
124
125 TestLog& operator<< (const SampleList& sampleList);
126 TestLog& operator<< (const SampleInfoToken&);
127 TestLog& operator<< (const ValueInfo& valueInfo);
128 TestLog& operator<< (const EndSampleInfoToken&);
129 SampleBuilder operator<< (const BeginSampleToken&);
130 TestLog& operator<< (const EndSampleListToken&);
131
132 // Raw api
133 void writeMessage (const char* message);
134
135 void startImageSet (const char* name, const char* description);
136 void endImageSet (void);
137 void writeImage (const char* name, const char* description, const ConstPixelBufferAccess& surface, const Vec4& scale, const Vec4& bias, qpImageCompressionMode compressionMode = QP_IMAGE_COMPRESSION_MODE_BEST);
138 void writeImage (const char* name, const char* description, qpImageCompressionMode compressionMode, qpImageFormat format, int width, int height, int stride, const void* data);
139
140 void startSection (const char* name, const char* description);
141 void endSection (void);
142
143 void startShaderProgram (bool linkOk, const char* linkInfoLog);
144 void endShaderProgram (void);
145 void writeShader (qpShaderType type, const char* source, bool compileOk, const char* infoLog);
146
147 void writeKernelSource (const char* source);
148 void writeCompileInfo (const char* name, const char* description, bool compileOk, const char* infoLog);
149
150 void writeFloat (const char* name, const char* description, const char* unit, qpKeyValueTag tag, float value);
151 void writeInteger (const char* name, const char* description, const char* unit, qpKeyValueTag tag, deInt64 value);
152
153 void startEglConfigSet (const char* name, const char* description);
154 void writeEglConfig (const qpEglConfigInfo* config);
155 void endEglConfigSet (void);
156
157 void startCase (const char* testCasePath, qpTestCaseType testCaseType);
158 void endCase (qpTestResult result, const char* description);
159 void terminateCase (qpTestResult result);
160
161 void startSampleList (const std::string& name, const std::string& description);
162 void startSampleInfo (void);
163 void writeValueInfo (const std::string& name, const std::string& description, const std::string& unit, qpSampleValueTag tag);
164 void endSampleInfo (void);
165 void startSample (void);
166 void writeSampleValue (double value);
167 void writeSampleValue (deInt64 value);
168 void endSample (void);
169 void endSampleList (void);
170
171 private:
172 TestLog (const TestLog& other); // Not allowed!
173 TestLog& operator= (const TestLog& other); // Not allowed!
174
175 qpTestLog* m_log;
176 };
177
178 class MessageBuilder
179 {
180 public:
MessageBuilder(TestLog * log)181 explicit MessageBuilder (TestLog* log) : m_log(log) {}
~MessageBuilder(void)182 ~MessageBuilder (void) {}
183
toString(void) const184 std::string toString (void) const { return m_str.str(); }
185
186 TestLog& operator<< (const TestLog::EndMessageToken&);
187
188 template <typename T>
189 MessageBuilder& operator<< (const T& value);
190
191 MessageBuilder (const MessageBuilder& other);
192 MessageBuilder& operator= (const MessageBuilder& other);
193
194 private:
195 TestLog* m_log;
196 std::ostringstream m_str;
197 };
198
199 class SampleBuilder
200 {
201 public:
SampleBuilder(TestLog * log)202 SampleBuilder (TestLog* log) : m_log(log) {}
203
operator <<(int v)204 SampleBuilder& operator<< (int v) { m_values.push_back(Value((deInt64)v)); return *this; }
operator <<(deInt64 v)205 SampleBuilder& operator<< (deInt64 v) { m_values.push_back(Value(v)); return *this; }
operator <<(float v)206 SampleBuilder& operator<< (float v) { m_values.push_back(Value((double)v)); return *this; }
operator <<(double v)207 SampleBuilder& operator<< (double v) { m_values.push_back(Value(v)); return *this; }
208
209 TestLog& operator<< (const TestLog::EndSampleToken&);
210
211 private:
212 struct Value
213 {
214 enum Type { TYPE_INT64 = 0, TYPE_FLOAT64, TYPE_LAST };
215
216 Type type;
217 union
218 {
219 deInt64 int64;
220 double float64;
221 } value;
222
Valuetcu::SampleBuilder::Value223 Value (void) : type(TYPE_LAST) { value.int64 = 0; }
Valuetcu::SampleBuilder::Value224 Value (double v) : type(TYPE_FLOAT64) { value.float64 = v; }
Valuetcu::SampleBuilder::Value225 Value (deInt64 v) : type(TYPE_INT64) { value.int64 = v; }
226 };
227
228 TestLog* m_log;
229 std::vector<Value> m_values;
230 };
231
232 class LogImageSet
233 {
234 public:
LogImageSet(const std::string & name,const std::string & description)235 LogImageSet (const std::string& name, const std::string& description)
236 : m_name (name)
237 , m_description (description)
238 {
239 }
240
241 void write (TestLog& log) const;
242
243 private:
244 std::string m_name;
245 std::string m_description;
246 };
247
248 // \note Doesn't take copy of surface contents
249 class LogImage
250 {
251 public:
252 LogImage (const std::string& name, const std::string& description, const Surface& surface, qpImageCompressionMode compression = QP_IMAGE_COMPRESSION_MODE_BEST);
253
254 LogImage (const std::string& name, const std::string& description, const ConstPixelBufferAccess& access, qpImageCompressionMode compression = QP_IMAGE_COMPRESSION_MODE_BEST);
255
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)256 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)
257 : m_name (name)
258 , m_description (description)
259 , m_access (access)
260 , m_scale (scale)
261 , m_bias (bias)
262 , m_compression (compression)
263 {
264 }
265
266 void write (TestLog& log) const;
267
268 private:
269 std::string m_name;
270 std::string m_description;
271 ConstPixelBufferAccess m_access;
272 Vec4 m_scale;
273 Vec4 m_bias;
274 qpImageCompressionMode m_compression;
275 };
276
277 class LogSection
278 {
279 public:
LogSection(const std::string & name,const std::string & description)280 LogSection (const std::string& name, const std::string& description)
281 : m_name (name)
282 , m_description (description)
283 {
284 }
285
286 void write (TestLog& log) const;
287
288 private:
289 std::string m_name;
290 std::string m_description;
291 };
292
293 class LogShaderProgram
294 {
295 public:
LogShaderProgram(bool linkOk,const std::string & linkInfoLog)296 LogShaderProgram (bool linkOk, const std::string& linkInfoLog)
297 : m_linkOk (linkOk)
298 , m_linkInfoLog (linkInfoLog)
299 {
300 }
301
302 void write (TestLog& log) const;
303
304 private:
305 bool m_linkOk;
306 std::string m_linkInfoLog;
307 };
308
309 class LogShader
310 {
311 public:
LogShader(qpShaderType type,const std::string & source,bool compileOk,const std::string & infoLog)312 LogShader (qpShaderType type, const std::string& source, bool compileOk, const std::string& infoLog)
313 : m_type (type)
314 , m_source (source)
315 , m_compileOk (compileOk)
316 , m_infoLog (infoLog)
317 {
318 }
319
320 void write (TestLog& log) const;
321
322 private:
323 qpShaderType m_type;
324 std::string m_source;
325 bool m_compileOk;
326 std::string m_infoLog;
327 };
328
329 class LogKernelSource
330 {
331 public:
LogKernelSource(const std::string & source)332 explicit LogKernelSource (const std::string& source)
333 : m_source(source)
334 {
335 }
336
337 void write (TestLog& log) const;
338
339 private:
340 std::string m_source;
341 };
342
343 class LogSampleList
344 {
345 public:
LogSampleList(const std::string & name,const std::string & description)346 LogSampleList (const std::string& name, const std::string& description)
347 : m_name (name)
348 , m_description (description)
349 {
350 }
351
352 void write (TestLog& log) const;
353
354 private:
355 std::string m_name;
356 std::string m_description;
357 };
358
359 class LogValueInfo
360 {
361 public:
LogValueInfo(const std::string & name,const std::string & description,const std::string & unit,qpSampleValueTag tag)362 LogValueInfo (const std::string& name, const std::string& description, const std::string& unit, qpSampleValueTag tag)
363 : m_name (name)
364 , m_description (description)
365 , m_unit (unit)
366 , m_tag (tag)
367 {
368 }
369
370 void write (TestLog& log) const;
371
372 private:
373 std::string m_name;
374 std::string m_description;
375 std::string m_unit;
376 qpSampleValueTag m_tag;
377 };
378
379 template<typename T>
380 class LogNumber
381 {
382 public:
LogNumber(const std::string & name,const std::string & desc,const std::string & unit,qpKeyValueTag tag,T value)383 LogNumber (const std::string& name, const std::string& desc, const std::string& unit, qpKeyValueTag tag, T value)
384 : m_name (name)
385 , m_desc (desc)
386 , m_unit (unit)
387 , m_tag (tag)
388 , m_value (value)
389 {
390 }
391
392 void write (TestLog& log) const;
393
394 private:
395 std::string m_name;
396 std::string m_desc;
397 std::string m_unit;
398 qpKeyValueTag m_tag;
399 T m_value;
400 };
401
402 // Section helper that closes section when leaving scope.
403 class ScopedLogSection
404 {
405 public:
ScopedLogSection(TestLog & log,const std::string & name,const std::string & description)406 ScopedLogSection (TestLog& log, const std::string& name, const std::string& description)
407 : m_log(log)
408 {
409 m_log << TestLog::Section(name, description);
410 }
411
~ScopedLogSection(void)412 ~ScopedLogSection (void)
413 {
414 m_log << TestLog::EndSection;
415 }
416
417 private:
418 TestLog& m_log;
419 };
420
421 // TestLog stream operators.
422
operator <<(const ImageSet & imageSet)423 inline TestLog& TestLog::operator<< (const ImageSet& imageSet) { imageSet.write(*this); return *this; }
operator <<(const Image & image)424 inline TestLog& TestLog::operator<< (const Image& image) { image.write(*this); return *this; }
operator <<(const EndImageSetToken &)425 inline TestLog& TestLog::operator<< (const EndImageSetToken&) { endImageSet(); return *this; }
operator <<(const Section & section)426 inline TestLog& TestLog::operator<< (const Section& section) { section.write(*this); return *this; }
operator <<(const EndSectionToken &)427 inline TestLog& TestLog::operator<< (const EndSectionToken&) { endSection(); return *this; }
operator <<(const ShaderProgram & shaderProg)428 inline TestLog& TestLog::operator<< (const ShaderProgram& shaderProg) { shaderProg.write(*this); return *this; }
operator <<(const EndShaderProgramToken &)429 inline TestLog& TestLog::operator<< (const EndShaderProgramToken&) { endShaderProgram(); return *this; }
operator <<(const Shader & shader)430 inline TestLog& TestLog::operator<< (const Shader& shader) { shader.write(*this); return *this; }
operator <<(const KernelSource & kernelSrc)431 inline TestLog& TestLog::operator<< (const KernelSource& kernelSrc) { kernelSrc.write(*this); return *this; }
operator <<(const SampleList & sampleList)432 inline TestLog& TestLog::operator<< (const SampleList& sampleList) { sampleList.write(*this); return *this; }
operator <<(const SampleInfoToken &)433 inline TestLog& TestLog::operator<< (const SampleInfoToken&) { startSampleInfo(); return *this; }
operator <<(const ValueInfo & valueInfo)434 inline TestLog& TestLog::operator<< (const ValueInfo& valueInfo) { valueInfo.write(*this); return *this; }
operator <<(const EndSampleInfoToken &)435 inline TestLog& TestLog::operator<< (const EndSampleInfoToken&) { endSampleInfo(); return *this; }
operator <<(const EndSampleListToken &)436 inline TestLog& TestLog::operator<< (const EndSampleListToken&) { endSampleList(); return *this; }
437
438 template<typename T>
operator <<(const LogNumber<T> & number)439 inline TestLog& TestLog::operator<< (const LogNumber<T>& number)
440 {
441 number.write(*this);
442 return *this;
443 }
444
operator <<(TestLog & log,const std::exception & e)445 inline TestLog& operator<< (TestLog& log, const std::exception& e)
446 {
447 // \todo [2012-10-18 pyry] Print type info?
448 return log << TestLog::Message << e.what() << TestLog::EndMessage;
449 }
450
451 // Utility class inline implementations.
452
453 template <typename T>
operator <<(const T & value)454 inline MessageBuilder& MessageBuilder::operator<< (const T& value)
455 {
456 // Overload stream operator to implement custom format
457 m_str << value;
458 return *this;
459 }
460
operator <<(const BeginMessageToken &)461 inline MessageBuilder TestLog::operator<< (const BeginMessageToken&)
462 {
463 return MessageBuilder(this);
464 }
465
message(void)466 inline MessageBuilder TestLog::message (void)
467 {
468 return MessageBuilder(this);
469 }
470
operator <<(const BeginSampleToken &)471 inline SampleBuilder TestLog::operator<< (const BeginSampleToken&)
472 {
473 return SampleBuilder(this);
474 }
475
write(TestLog & log) const476 inline void LogImageSet::write (TestLog& log) const
477 {
478 log.startImageSet(m_name.c_str(), m_description.c_str());
479 }
480
write(TestLog & log) const481 inline void LogImage::write (TestLog& log) const
482 {
483 log.writeImage(m_name.c_str(), m_description.c_str(), m_access, m_scale, m_bias, m_compression);
484 }
485
write(TestLog & log) const486 inline void LogSection::write (TestLog& log) const
487 {
488 log.startSection(m_name.c_str(), m_description.c_str());
489 }
490
write(TestLog & log) const491 inline void LogShaderProgram::write (TestLog& log) const
492 {
493 log.startShaderProgram(m_linkOk, m_linkInfoLog.c_str());
494 }
495
write(TestLog & log) const496 inline void LogShader::write (TestLog& log) const
497 {
498 log.writeShader(m_type, m_source.c_str(), m_compileOk, m_infoLog.c_str());
499 }
500
write(TestLog & log) const501 inline void LogKernelSource::write (TestLog& log) const
502 {
503 log.writeKernelSource(m_source.c_str());
504 }
505
write(TestLog & log) const506 inline void LogSampleList::write (TestLog& log) const
507 {
508 log.startSampleList(m_name, m_description);
509 }
510
write(TestLog & log) const511 inline void LogValueInfo::write (TestLog& log) const
512 {
513 log.writeValueInfo(m_name, m_description, m_unit, m_tag);
514 }
515
516 template<>
write(TestLog & log) const517 inline void LogNumber<float>::write (TestLog& log) const
518 {
519 log.writeFloat(m_name.c_str(), m_desc.c_str(), m_unit.c_str(), m_tag, m_value);
520 }
521
522 template<>
write(TestLog & log) const523 inline void LogNumber<deInt64>::write (TestLog& log) const
524 {
525 log.writeInteger(m_name.c_str(), m_desc.c_str(), m_unit.c_str(), m_tag, m_value);
526 }
527
528 } // tcu
529
530 #endif // _TCUTESTLOG_HPP
531