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