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