| #ifndef _TCUTESTLOG_HPP |
| #define _TCUTESTLOG_HPP |
| /*------------------------------------------------------------------------- |
| * drawElements Quality Program Tester Core |
| * ---------------------------------------- |
| * |
| * Copyright 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief Test Log C++ Wrapper. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "tcuDefs.hpp" |
| #include "qpTestLog.h" |
| #include "tcuTexture.hpp" |
| |
| #include <sstream> |
| |
| namespace tcu |
| { |
| |
| class Surface; |
| class MessageBuilder; |
| class LogImageSet; |
| class LogImage; |
| class LogSection; |
| class LogShaderProgram; |
| class LogShader; |
| class LogSpirVAssemblySource; |
| class LogKernelSource; |
| class LogSampleList; |
| class LogValueInfo; |
| class SampleBuilder; |
| template<typename T> class LogNumber; |
| |
| /*--------------------------------------------------------------------*//*! |
| * \brief Test log |
| * |
| * TestLog provides convinient C++ API for logging. The API has been designed |
| * around stream operators much like STL iostream library. The following |
| * examples demonstrate how to use TestLog. |
| * |
| * \code |
| * TestLog& log = m_testCtx.getLog(); |
| * |
| * // Write message to log. |
| * log << TestLog::Message << "Hello, World!" << TestLog::EndMessage; |
| * int myNumber = 3; |
| * log << TestLog::Message << "Diff is " << myNumber << TestLog::EndMessage; |
| * |
| * // Write image |
| * Surface myImage(256, 256); |
| * log << TestLog::Image("TestImage", "My test image", myImage); |
| * |
| * // Multiple commands can be combined: |
| * log << TestLog::Section("Details", "Test case details") |
| * << TestLog::Message << "Here be dragons" << TestLog::EndMessage |
| * << TestLog::ImageSet("Result", "Result images") |
| * << TestLog::Image("ImageA", "Image A", imageA) |
| * << TestLog::Image("ImageB", "Image B", imageB) |
| * << TestLog::EndImageSet << TestLog::EndSection; |
| * \endcode |
| *//*--------------------------------------------------------------------*/ |
| class TestLog |
| { |
| public: |
| // Tokens |
| static const class BeginMessageToken {} Message; |
| static const class EndMessageToken {} EndMessage; |
| static const class EndImageSetToken {} EndImageSet; |
| static const class EndSectionToken {} EndSection; |
| static const class EndShaderProgramToken {} EndShaderProgram; |
| static const class SampleInfoToken {} SampleInfo; |
| static const class EndSampleInfoToken {} EndSampleInfo; |
| static const class BeginSampleToken {} Sample; |
| static const class EndSampleToken {} EndSample; |
| static const class EndSampleListToken {} EndSampleList; |
| |
| // Typedefs. |
| typedef LogImageSet ImageSet; |
| typedef LogImage Image; |
| typedef LogSection Section; |
| typedef LogShaderProgram ShaderProgram; |
| typedef LogShader Shader; |
| typedef LogSpirVAssemblySource SpirVAssemblySource; |
| typedef LogKernelSource KernelSource; |
| typedef LogSampleList SampleList; |
| typedef LogValueInfo ValueInfo; |
| typedef LogNumber<float> Float; |
| typedef LogNumber<deInt64> Integer; |
| |
| explicit TestLog (const char* fileName, deUint32 flags = 0); |
| ~TestLog (void); |
| |
| MessageBuilder operator<< (const BeginMessageToken&); |
| MessageBuilder message (void); |
| |
| TestLog& operator<< (const ImageSet& imageSet); |
| TestLog& operator<< (const Image& image); |
| TestLog& operator<< (const EndImageSetToken&); |
| |
| TestLog& operator<< (const Section& section); |
| TestLog& operator<< (const EndSectionToken&); |
| |
| TestLog& operator<< (const ShaderProgram& shaderProgram); |
| TestLog& operator<< (const EndShaderProgramToken&); |
| TestLog& operator<< (const Shader& shader); |
| TestLog& operator<< (const SpirVAssemblySource& module); |
| |
| TestLog& operator<< (const KernelSource& kernelSrc); |
| |
| template<typename T> |
| TestLog& operator<< (const LogNumber<T>& number); |
| |
| TestLog& operator<< (const SampleList& sampleList); |
| TestLog& operator<< (const SampleInfoToken&); |
| TestLog& operator<< (const ValueInfo& valueInfo); |
| TestLog& operator<< (const EndSampleInfoToken&); |
| SampleBuilder operator<< (const BeginSampleToken&); |
| TestLog& operator<< (const EndSampleListToken&); |
| |
| // Raw api |
| void writeMessage (const char* message); |
| |
| void startImageSet (const char* name, const char* description); |
| void endImageSet (void); |
| void writeImage (const char* name, const char* description, const ConstPixelBufferAccess& surface, const Vec4& scale, const Vec4& bias, qpImageCompressionMode compressionMode = QP_IMAGE_COMPRESSION_MODE_BEST); |
| void writeImage (const char* name, const char* description, qpImageCompressionMode compressionMode, qpImageFormat format, int width, int height, int stride, const void* data); |
| |
| void startSection (const char* name, const char* description); |
| void endSection (void); |
| |
| void startShaderProgram (bool linkOk, const char* linkInfoLog); |
| void endShaderProgram (void); |
| void writeShader (qpShaderType type, const char* source, bool compileOk, const char* infoLog); |
| void writeSpirVAssemblySource(const char* source); |
| void writeKernelSource (const char* source); |
| void writeCompileInfo (const char* name, const char* description, bool compileOk, const char* infoLog); |
| |
| void writeFloat (const char* name, const char* description, const char* unit, qpKeyValueTag tag, float value); |
| void writeInteger (const char* name, const char* description, const char* unit, qpKeyValueTag tag, deInt64 value); |
| |
| void startEglConfigSet (const char* name, const char* description); |
| void writeEglConfig (const qpEglConfigInfo* config); |
| void endEglConfigSet (void); |
| |
| void startCase (const char* testCasePath, qpTestCaseType testCaseType); |
| void endCase (qpTestResult result, const char* description); |
| void terminateCase (qpTestResult result); |
| |
| void startTestsCasesTime (void); |
| void endTestsCasesTime (void); |
| |
| void startSampleList (const std::string& name, const std::string& description); |
| void startSampleInfo (void); |
| void writeValueInfo (const std::string& name, const std::string& description, const std::string& unit, qpSampleValueTag tag); |
| void endSampleInfo (void); |
| void startSample (void); |
| void writeSampleValue (double value); |
| void writeSampleValue (deInt64 value); |
| void endSample (void); |
| void endSampleList (void); |
| |
| bool isShaderLoggingEnabled (void); |
| private: |
| TestLog (const TestLog& other); // Not allowed! |
| TestLog& operator= (const TestLog& other); // Not allowed! |
| |
| qpTestLog* m_log; |
| }; |
| |
| class MessageBuilder |
| { |
| public: |
| explicit MessageBuilder (TestLog* log) : m_log(log) {} |
| ~MessageBuilder (void) {} |
| |
| std::string toString (void) const { return m_str.str(); } |
| |
| TestLog& operator<< (const TestLog::EndMessageToken&); |
| |
| template <typename T> |
| MessageBuilder& operator<< (const T& value); |
| |
| MessageBuilder (const MessageBuilder& other); |
| MessageBuilder& operator= (const MessageBuilder& other); |
| |
| private: |
| TestLog* m_log; |
| std::ostringstream m_str; |
| }; |
| |
| class SampleBuilder |
| { |
| public: |
| SampleBuilder (TestLog* log) : m_log(log) {} |
| |
| SampleBuilder& operator<< (int v) { m_values.push_back(Value((deInt64)v)); return *this; } |
| SampleBuilder& operator<< (deInt64 v) { m_values.push_back(Value(v)); return *this; } |
| SampleBuilder& operator<< (float v) { m_values.push_back(Value((double)v)); return *this; } |
| SampleBuilder& operator<< (double v) { m_values.push_back(Value(v)); return *this; } |
| |
| TestLog& operator<< (const TestLog::EndSampleToken&); |
| |
| private: |
| struct Value |
| { |
| enum Type { TYPE_INT64 = 0, TYPE_FLOAT64, TYPE_LAST }; |
| |
| Type type; |
| union |
| { |
| deInt64 int64; |
| double float64; |
| } value; |
| |
| Value (void) : type(TYPE_LAST) { value.int64 = 0; } |
| Value (double v) : type(TYPE_FLOAT64) { value.float64 = v; } |
| Value (deInt64 v) : type(TYPE_INT64) { value.int64 = v; } |
| }; |
| |
| TestLog* m_log; |
| std::vector<Value> m_values; |
| }; |
| |
| class LogImageSet |
| { |
| public: |
| LogImageSet (const std::string& name, const std::string& description) |
| : m_name (name) |
| , m_description (description) |
| { |
| } |
| |
| void write (TestLog& log) const; |
| |
| private: |
| std::string m_name; |
| std::string m_description; |
| }; |
| |
| // \note Doesn't take copy of surface contents |
| class LogImage |
| { |
| public: |
| LogImage (const std::string& name, const std::string& description, const Surface& surface, qpImageCompressionMode compression = QP_IMAGE_COMPRESSION_MODE_BEST); |
| |
| LogImage (const std::string& name, const std::string& description, const ConstPixelBufferAccess& access, qpImageCompressionMode compression = QP_IMAGE_COMPRESSION_MODE_BEST); |
| |
| 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); |
| |
| void write (TestLog& log) const; |
| |
| private: |
| std::string m_name; |
| std::string m_description; |
| ConstPixelBufferAccess m_access; |
| Vec4 m_scale; |
| Vec4 m_bias; |
| qpImageCompressionMode m_compression; |
| }; |
| |
| class LogSection |
| { |
| public: |
| LogSection (const std::string& name, const std::string& description) |
| : m_name (name) |
| , m_description (description) |
| { |
| } |
| |
| void write (TestLog& log) const; |
| |
| private: |
| std::string m_name; |
| std::string m_description; |
| }; |
| |
| class LogShaderProgram |
| { |
| public: |
| LogShaderProgram (bool linkOk, const std::string& linkInfoLog) |
| : m_linkOk (linkOk) |
| , m_linkInfoLog (linkInfoLog) |
| { |
| } |
| |
| void write (TestLog& log) const; |
| |
| private: |
| bool m_linkOk; |
| std::string m_linkInfoLog; |
| }; |
| |
| class LogShader |
| { |
| public: |
| LogShader (qpShaderType type, const std::string& source, bool compileOk, const std::string& infoLog) |
| : m_type (type) |
| , m_source (source) |
| , m_compileOk (compileOk) |
| , m_infoLog (infoLog) |
| { |
| } |
| |
| void write (TestLog& log) const; |
| |
| private: |
| qpShaderType m_type; |
| std::string m_source; |
| bool m_compileOk; |
| std::string m_infoLog; |
| }; |
| |
| class LogSpirVAssemblySource |
| { |
| public: |
| LogSpirVAssemblySource (const std::string& source) |
| : m_source (source) |
| { |
| } |
| |
| void write (TestLog& log) const; |
| |
| private: |
| std::string m_source; |
| }; |
| |
| class LogKernelSource |
| { |
| public: |
| explicit LogKernelSource (const std::string& source) |
| : m_source(source) |
| { |
| } |
| |
| void write (TestLog& log) const; |
| |
| private: |
| std::string m_source; |
| }; |
| |
| class LogSampleList |
| { |
| public: |
| LogSampleList (const std::string& name, const std::string& description) |
| : m_name (name) |
| , m_description (description) |
| { |
| } |
| |
| void write (TestLog& log) const; |
| |
| private: |
| std::string m_name; |
| std::string m_description; |
| }; |
| |
| class LogValueInfo |
| { |
| public: |
| LogValueInfo (const std::string& name, const std::string& description, const std::string& unit, qpSampleValueTag tag) |
| : m_name (name) |
| , m_description (description) |
| , m_unit (unit) |
| , m_tag (tag) |
| { |
| } |
| |
| void write (TestLog& log) const; |
| |
| private: |
| std::string m_name; |
| std::string m_description; |
| std::string m_unit; |
| qpSampleValueTag m_tag; |
| }; |
| |
| template<typename T> |
| class LogNumber |
| { |
| public: |
| LogNumber (const std::string& name, const std::string& desc, const std::string& unit, qpKeyValueTag tag, T value) |
| : m_name (name) |
| , m_desc (desc) |
| , m_unit (unit) |
| , m_tag (tag) |
| , m_value (value) |
| { |
| } |
| |
| void write (TestLog& log) const; |
| |
| private: |
| std::string m_name; |
| std::string m_desc; |
| std::string m_unit; |
| qpKeyValueTag m_tag; |
| T m_value; |
| }; |
| |
| // Section helper that closes section when leaving scope. |
| class ScopedLogSection |
| { |
| public: |
| ScopedLogSection (TestLog& log, const std::string& name, const std::string& description) |
| : m_log(log) |
| { |
| m_log << TestLog::Section(name, description); |
| } |
| |
| ~ScopedLogSection (void) |
| { |
| m_log << TestLog::EndSection; |
| } |
| |
| private: |
| TestLog& m_log; |
| }; |
| |
| // TestLog stream operators. |
| |
| inline TestLog& TestLog::operator<< (const ImageSet& imageSet) { imageSet.write(*this); return *this; } |
| inline TestLog& TestLog::operator<< (const Image& image) { image.write(*this); return *this; } |
| inline TestLog& TestLog::operator<< (const EndImageSetToken&) { endImageSet(); return *this; } |
| inline TestLog& TestLog::operator<< (const Section& section) { section.write(*this); return *this; } |
| inline TestLog& TestLog::operator<< (const EndSectionToken&) { endSection(); return *this; } |
| inline TestLog& TestLog::operator<< (const ShaderProgram& shaderProg) { shaderProg.write(*this); return *this; } |
| inline TestLog& TestLog::operator<< (const EndShaderProgramToken&) { endShaderProgram(); return *this; } |
| inline TestLog& TestLog::operator<< (const Shader& shader) { shader.write(*this); return *this; } |
| inline TestLog& TestLog::operator<< (const SpirVAssemblySource& module) { module.write(*this); return *this; } |
| inline TestLog& TestLog::operator<< (const KernelSource& kernelSrc) { kernelSrc.write(*this); return *this; } |
| inline TestLog& TestLog::operator<< (const SampleList& sampleList) { sampleList.write(*this); return *this; } |
| inline TestLog& TestLog::operator<< (const SampleInfoToken&) { startSampleInfo(); return *this; } |
| inline TestLog& TestLog::operator<< (const ValueInfo& valueInfo) { valueInfo.write(*this); return *this; } |
| inline TestLog& TestLog::operator<< (const EndSampleInfoToken&) { endSampleInfo(); return *this; } |
| inline TestLog& TestLog::operator<< (const EndSampleListToken&) { endSampleList(); return *this; } |
| |
| template<typename T> |
| inline TestLog& TestLog::operator<< (const LogNumber<T>& number) |
| { |
| number.write(*this); |
| return *this; |
| } |
| |
| inline TestLog& operator<< (TestLog& log, const std::exception& e) |
| { |
| // \todo [2012-10-18 pyry] Print type info? |
| return log << TestLog::Message << e.what() << TestLog::EndMessage; |
| } |
| |
| // Utility class inline implementations. |
| |
| template <typename T> |
| inline MessageBuilder& MessageBuilder::operator<< (const T& value) |
| { |
| // Overload stream operator to implement custom format |
| m_str << value; |
| return *this; |
| } |
| |
| inline MessageBuilder TestLog::operator<< (const BeginMessageToken&) |
| { |
| return MessageBuilder(this); |
| } |
| |
| inline MessageBuilder TestLog::message (void) |
| { |
| return MessageBuilder(this); |
| } |
| |
| inline SampleBuilder TestLog::operator<< (const BeginSampleToken&) |
| { |
| return SampleBuilder(this); |
| } |
| |
| inline void LogImageSet::write (TestLog& log) const |
| { |
| log.startImageSet(m_name.c_str(), m_description.c_str()); |
| } |
| |
| inline void LogSection::write (TestLog& log) const |
| { |
| log.startSection(m_name.c_str(), m_description.c_str()); |
| } |
| |
| inline void LogShaderProgram::write (TestLog& log) const |
| { |
| log.startShaderProgram(m_linkOk, m_linkInfoLog.c_str()); |
| } |
| |
| inline void LogShader::write (TestLog& log) const |
| { |
| log.writeShader(m_type, m_source.c_str(), m_compileOk, m_infoLog.c_str()); |
| } |
| |
| inline void LogSpirVAssemblySource::write (TestLog& log) const |
| { |
| log.writeSpirVAssemblySource(m_source.c_str()); |
| } |
| |
| inline void LogKernelSource::write (TestLog& log) const |
| { |
| log.writeKernelSource(m_source.c_str()); |
| } |
| |
| inline void LogSampleList::write (TestLog& log) const |
| { |
| log.startSampleList(m_name, m_description); |
| } |
| |
| inline void LogValueInfo::write (TestLog& log) const |
| { |
| log.writeValueInfo(m_name, m_description, m_unit, m_tag); |
| } |
| |
| template<> |
| inline void LogNumber<float>::write (TestLog& log) const |
| { |
| log.writeFloat(m_name.c_str(), m_desc.c_str(), m_unit.c_str(), m_tag, m_value); |
| } |
| |
| template<> |
| inline void LogNumber<deInt64>::write (TestLog& log) const |
| { |
| log.writeInteger(m_name.c_str(), m_desc.c_str(), m_unit.c_str(), m_tag, m_value); |
| } |
| |
| } // tcu |
| |
| #endif // _TCUTESTLOG_HPP |