| #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<int64_t> Integer; |
| |
| explicit TestLog(const char *fileName, uint32_t flags = 0); |
| ~TestLog(void); |
| |
| void writeSessionInfo(std::string additionalInfo = ""); |
| |
| 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 §ion); |
| 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, int64_t 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(int64_t value); |
| void endSample(void); |
| void endSampleList(void); |
| |
| void writeRaw(const char *rawContents); |
| |
| bool isShaderLoggingEnabled(void); |
| |
| void supressLogging(bool value); |
| bool isSupressLogging(void); |
| |
| private: |
| TestLog(const TestLog &other); // Not allowed! |
| TestLog &operator=(const TestLog &other); // Not allowed! |
| |
| qpTestLog *m_log; |
| bool m_logSupressed; |
| bool m_skipAdditionalDataInLog; |
| }; |
| |
| 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((int64_t)v)); |
| return *this; |
| } |
| SampleBuilder &operator<<(int64_t 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 |
| { |
| int64_t int64; |
| double float64; |
| } value; |
| |
| Value(void) : type(TYPE_LAST) |
| { |
| value.int64 = 0; |
| } |
| Value(double v) : type(TYPE_FLOAT64) |
| { |
| value.float64 = v; |
| } |
| Value(int64_t 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 §ion) |
| { |
| 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<int64_t>::write(TestLog &log) const |
| { |
| log.writeInteger(m_name.c_str(), m_desc.c_str(), m_unit.c_str(), m_tag, m_value); |
| } |
| |
| } // namespace tcu |
| |
| #endif // _TCUTESTLOG_HPP |