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