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 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:
    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 
    194 private:
    195 	TestLog*				m_log;
    196 	std::ostringstream		m_str;
    197 };
    198 
    199 class SampleBuilder
    200 {
    201 public:
    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 
    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 
    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 
    232 class LogImageSet
    233 {
    234 public:
    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 
    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:
    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:
    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:
    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:
    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:
    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:
    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:
    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:
    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 
    417 private:
    418 	TestLog& m_log;
    419 };
    420 
    421 // TestLog stream operators.
    422 
    423 inline TestLog& TestLog::operator<< (const ImageSet& imageSet)			{ imageSet.write(*this);	return *this;	}
    424 inline TestLog& TestLog::operator<< (const Image& image)				{ image.write(*this);		return *this;	}
    425 inline TestLog& TestLog::operator<< (const EndImageSetToken&)			{ endImageSet();			return *this;	}
    426 inline TestLog& TestLog::operator<< (const Section& section)			{ section.write(*this);		return *this;	}
    427 inline TestLog& TestLog::operator<< (const EndSectionToken&)			{ endSection();				return *this;	}
    428 inline TestLog& TestLog::operator<< (const ShaderProgram& shaderProg)	{ shaderProg.write(*this);	return *this;	}
    429 inline TestLog& TestLog::operator<< (const EndShaderProgramToken&)		{ endShaderProgram();		return *this;	}
    430 inline TestLog& TestLog::operator<< (const Shader& shader)				{ shader.write(*this);		return *this;	}
    431 inline TestLog& TestLog::operator<< (const KernelSource& kernelSrc)		{ kernelSrc.write(*this);	return *this;	}
    432 inline TestLog&	TestLog::operator<<	(const SampleList& sampleList)		{ sampleList.write(*this);	return *this;	}
    433 inline TestLog&	TestLog::operator<<	(const SampleInfoToken&)			{ startSampleInfo();		return *this;	}
    434 inline TestLog&	TestLog::operator<<	(const ValueInfo& valueInfo)		{ valueInfo.write(*this);	return *this;	}
    435 inline TestLog&	TestLog::operator<<	(const EndSampleInfoToken&)			{ endSampleInfo();			return *this;	}
    436 inline TestLog&	TestLog::operator<<	(const EndSampleListToken&)			{ endSampleList();			return *this;	}
    437 
    438 template<typename T>
    439 inline TestLog& TestLog::operator<< (const LogNumber<T>& number)
    440 {
    441 	number.write(*this);
    442 	return *this;
    443 }
    444 
    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>
    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 
    461 inline MessageBuilder TestLog::operator<< (const BeginMessageToken&)
    462 {
    463 	return MessageBuilder(this);
    464 }
    465 
    466 inline MessageBuilder TestLog::message (void)
    467 {
    468 	return MessageBuilder(this);
    469 }
    470 
    471 inline SampleBuilder TestLog::operator<< (const BeginSampleToken&)
    472 {
    473 	return SampleBuilder(this);
    474 }
    475 
    476 inline void LogImageSet::write (TestLog& log) const
    477 {
    478 	log.startImageSet(m_name.c_str(), m_description.c_str());
    479 }
    480 
    481 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 
    486 inline void LogSection::write (TestLog& log) const
    487 {
    488 	log.startSection(m_name.c_str(), m_description.c_str());
    489 }
    490 
    491 inline void LogShaderProgram::write (TestLog& log) const
    492 {
    493 	log.startShaderProgram(m_linkOk, m_linkInfoLog.c_str());
    494 }
    495 
    496 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 
    501 inline void LogKernelSource::write (TestLog& log) const
    502 {
    503 	log.writeKernelSource(m_source.c_str());
    504 }
    505 
    506 inline void LogSampleList::write (TestLog& log) const
    507 {
    508 	log.startSampleList(m_name, m_description);
    509 }
    510 
    511 inline void LogValueInfo::write (TestLog& log) const
    512 {
    513 	log.writeValueInfo(m_name, m_description, m_unit, m_tag);
    514 }
    515 
    516 template<>
    517 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<>
    523 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