blob: cf581c1e148127e29bc11cad1f9df8d8197a3dd6 [file] [log] [blame]
#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 &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, 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 &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<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