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
32namespace tcu
33{
34
35class Surface;
36class MessageBuilder;
37class LogImageSet;
38class LogImage;
39class LogSection;
40class LogShaderProgram;
41class LogShader;
42class LogKernelSource;
43class LogSampleList;
44class LogValueInfo;
45class SampleBuilder;
46template<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 *//*--------------------------------------------------------------------*/
76class TestLog
77{
78public:
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
171private:
172						TestLog					(const TestLog& other); // Not allowed!
173	TestLog&			operator=				(const TestLog& other); // Not allowed!
174
175	qpTestLog*			m_log;
176};
177
178class MessageBuilder
179{
180public:
181	explicit				MessageBuilder		(TestLog* log) : m_log(log) {}
182							~MessageBuilder		(void) {}
183
184	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
194private:
195	TestLog*				m_log;
196	std::ostringstream		m_str;
197};
198
199class SampleBuilder
200{
201public:
202							SampleBuilder		(TestLog* log) : m_log(log) {}
203
204	SampleBuilder&			operator<<			(int v)		{ m_values.push_back(Value((deInt64)v));	return *this; }
205	SampleBuilder&			operator<<			(deInt64 v)	{ m_values.push_back(Value(v));				return *this; }
206	SampleBuilder&			operator<<			(float v)	{ m_values.push_back(Value((double)v));		return *this; }
207	SampleBuilder&			operator<<			(double v)	{ m_values.push_back(Value(v));				return *this; }
208
209	TestLog&				operator<<			(const TestLog::EndSampleToken&);
210
211private:
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
223		Value (void)		: type(TYPE_LAST)		{ value.int64 = 0;		}
224		Value (double v)	: type(TYPE_FLOAT64)	{ value.float64 = v;	}
225		Value (deInt64 v)	: type(TYPE_INT64)		{ value.int64 = v;		}
226	};
227
228	TestLog*				m_log;
229	std::vector<Value>		m_values;
230};
231
232class LogImageSet
233{
234public:
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
243private:
244	std::string		m_name;
245	std::string		m_description;
246};
247
248// \note Doesn't take copy of surface contents
249class LogImage
250{
251public:
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
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
268private:
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
277class LogSection
278{
279public:
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
288private:
289	std::string		m_name;
290	std::string		m_description;
291};
292
293class LogShaderProgram
294{
295public:
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
304private:
305	bool			m_linkOk;
306	std::string		m_linkInfoLog;
307};
308
309class LogShader
310{
311public:
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
322private:
323	qpShaderType	m_type;
324	std::string		m_source;
325	bool			m_compileOk;
326	std::string		m_infoLog;
327};
328
329class LogKernelSource
330{
331public:
332	explicit LogKernelSource (const std::string& source)
333		: m_source(source)
334	{
335	}
336
337	void write (TestLog& log) const;
338
339private:
340	std::string	m_source;
341};
342
343class LogSampleList
344{
345public:
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
354private:
355	std::string		m_name;
356	std::string		m_description;
357};
358
359class LogValueInfo
360{
361public:
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
372private:
373	std::string			m_name;
374	std::string			m_description;
375	std::string			m_unit;
376	qpSampleValueTag	m_tag;
377};
378
379template<typename T>
380class LogNumber
381{
382public:
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
394private:
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.
403class ScopedLogSection
404{
405public:
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
412	~ScopedLogSection (void)
413	{
414		m_log << TestLog::EndSection;
415	}
416
417private:
418	TestLog& m_log;
419};
420
421// TestLog stream operators.
422
423inline TestLog& TestLog::operator<< (const ImageSet& imageSet)			{ imageSet.write(*this);	return *this;	}
424inline TestLog& TestLog::operator<< (const Image& image)				{ image.write(*this);		return *this;	}
425inline TestLog& TestLog::operator<< (const EndImageSetToken&)			{ endImageSet();			return *this;	}
426inline TestLog& TestLog::operator<< (const Section& section)			{ section.write(*this);		return *this;	}
427inline TestLog& TestLog::operator<< (const EndSectionToken&)			{ endSection();				return *this;	}
428inline TestLog& TestLog::operator<< (const ShaderProgram& shaderProg)	{ shaderProg.write(*this);	return *this;	}
429inline TestLog& TestLog::operator<< (const EndShaderProgramToken&)		{ endShaderProgram();		return *this;	}
430inline TestLog& TestLog::operator<< (const Shader& shader)				{ shader.write(*this);		return *this;	}
431inline TestLog& TestLog::operator<< (const KernelSource& kernelSrc)		{ kernelSrc.write(*this);	return *this;	}
432inline TestLog&	TestLog::operator<<	(const SampleList& sampleList)		{ sampleList.write(*this);	return *this;	}
433inline TestLog&	TestLog::operator<<	(const SampleInfoToken&)			{ startSampleInfo();		return *this;	}
434inline TestLog&	TestLog::operator<<	(const ValueInfo& valueInfo)		{ valueInfo.write(*this);	return *this;	}
435inline TestLog&	TestLog::operator<<	(const EndSampleInfoToken&)			{ endSampleInfo();			return *this;	}
436inline TestLog&	TestLog::operator<<	(const EndSampleListToken&)			{ endSampleList();			return *this;	}
437
438template<typename T>
439inline TestLog& TestLog::operator<< (const LogNumber<T>& number)
440{
441	number.write(*this);
442	return *this;
443}
444
445inline 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
453template <typename T>
454inline MessageBuilder& MessageBuilder::operator<< (const T& value)
455{
456	// Overload stream operator to implement custom format
457	m_str << value;
458	return *this;
459}
460
461inline MessageBuilder TestLog::operator<< (const BeginMessageToken&)
462{
463	return MessageBuilder(this);
464}
465
466inline MessageBuilder TestLog::message (void)
467{
468	return MessageBuilder(this);
469}
470
471inline SampleBuilder TestLog::operator<< (const BeginSampleToken&)
472{
473	return SampleBuilder(this);
474}
475
476inline void LogImageSet::write (TestLog& log) const
477{
478	log.startImageSet(m_name.c_str(), m_description.c_str());
479}
480
481inline 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
486inline void LogSection::write (TestLog& log) const
487{
488	log.startSection(m_name.c_str(), m_description.c_str());
489}
490
491inline void LogShaderProgram::write (TestLog& log) const
492{
493	log.startShaderProgram(m_linkOk, m_linkInfoLog.c_str());
494}
495
496inline void LogShader::write (TestLog& log) const
497{
498	log.writeShader(m_type, m_source.c_str(), m_compileOk, m_infoLog.c_str());
499}
500
501inline void LogKernelSource::write (TestLog& log) const
502{
503	log.writeKernelSource(m_source.c_str());
504}
505
506inline void LogSampleList::write (TestLog& log) const
507{
508	log.startSampleList(m_name, m_description);
509}
510
511inline void LogValueInfo::write (TestLog& log) const
512{
513	log.writeValueInfo(m_name, m_description, m_unit, m_tag);
514}
515
516template<>
517inline 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
522template<>
523inline 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