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