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 32namespace tcu 33{ 34 35class Surface; 36class MessageBuilder; 37class LogImageSet; 38class LogImage; 39class LogSection; 40class LogShaderProgram; 41class LogShader; 42class LogSpirVAssemblySource; 43class LogKernelSource; 44class LogSampleList; 45class LogValueInfo; 46class SampleBuilder; 47template<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 *//*--------------------------------------------------------------------*/ 77class TestLog 78{ 79public: 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 174private: 175 TestLog (const TestLog& other); // Not allowed! 176 TestLog& operator= (const TestLog& other); // Not allowed! 177 178 qpTestLog* m_log; 179}; 180 181class MessageBuilder 182{ 183public: 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 197private: 198 TestLog* m_log; 199 std::ostringstream m_str; 200}; 201 202class SampleBuilder 203{ 204public: 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 214private: 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 235class LogImageSet 236{ 237public: 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 246private: 247 std::string m_name; 248 std::string m_description; 249}; 250 251// \note Doesn't take copy of surface contents 252class LogImage 253{ 254public: 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 263private: 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 272class LogSection 273{ 274public: 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 283private: 284 std::string m_name; 285 std::string m_description; 286}; 287 288class LogShaderProgram 289{ 290public: 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 299private: 300 bool m_linkOk; 301 std::string m_linkInfoLog; 302}; 303 304class LogShader 305{ 306public: 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 317private: 318 qpShaderType m_type; 319 std::string m_source; 320 bool m_compileOk; 321 std::string m_infoLog; 322}; 323 324class LogSpirVAssemblySource 325{ 326public: 327 LogSpirVAssemblySource (const std::string& source) 328 : m_source (source) 329 { 330 } 331 332 void write (TestLog& log) const; 333 334private: 335 std::string m_source; 336}; 337 338class LogKernelSource 339{ 340public: 341 explicit LogKernelSource (const std::string& source) 342 : m_source(source) 343 { 344 } 345 346 void write (TestLog& log) const; 347 348private: 349 std::string m_source; 350}; 351 352class LogSampleList 353{ 354public: 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 363private: 364 std::string m_name; 365 std::string m_description; 366}; 367 368class LogValueInfo 369{ 370public: 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 381private: 382 std::string m_name; 383 std::string m_description; 384 std::string m_unit; 385 qpSampleValueTag m_tag; 386}; 387 388template<typename T> 389class LogNumber 390{ 391public: 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 403private: 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. 412class ScopedLogSection 413{ 414public: 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 426private: 427 TestLog& m_log; 428}; 429 430// TestLog stream operators. 431 432inline TestLog& TestLog::operator<< (const ImageSet& imageSet) { imageSet.write(*this); return *this; } 433inline TestLog& TestLog::operator<< (const Image& image) { image.write(*this); return *this; } 434inline TestLog& TestLog::operator<< (const EndImageSetToken&) { endImageSet(); return *this; } 435inline TestLog& TestLog::operator<< (const Section& section) { section.write(*this); return *this; } 436inline TestLog& TestLog::operator<< (const EndSectionToken&) { endSection(); return *this; } 437inline TestLog& TestLog::operator<< (const ShaderProgram& shaderProg) { shaderProg.write(*this); return *this; } 438inline TestLog& TestLog::operator<< (const EndShaderProgramToken&) { endShaderProgram(); return *this; } 439inline TestLog& TestLog::operator<< (const Shader& shader) { shader.write(*this); return *this; } 440inline TestLog& TestLog::operator<< (const SpirVAssemblySource& module) { module.write(*this); return *this; } 441inline TestLog& TestLog::operator<< (const KernelSource& kernelSrc) { kernelSrc.write(*this); return *this; } 442inline TestLog& TestLog::operator<< (const SampleList& sampleList) { sampleList.write(*this); return *this; } 443inline TestLog& TestLog::operator<< (const SampleInfoToken&) { startSampleInfo(); return *this; } 444inline TestLog& TestLog::operator<< (const ValueInfo& valueInfo) { valueInfo.write(*this); return *this; } 445inline TestLog& TestLog::operator<< (const EndSampleInfoToken&) { endSampleInfo(); return *this; } 446inline TestLog& TestLog::operator<< (const EndSampleListToken&) { endSampleList(); return *this; } 447 448template<typename T> 449inline TestLog& TestLog::operator<< (const LogNumber<T>& number) 450{ 451 number.write(*this); 452 return *this; 453} 454 455inline 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 463template <typename T> 464inline MessageBuilder& MessageBuilder::operator<< (const T& value) 465{ 466 // Overload stream operator to implement custom format 467 m_str << value; 468 return *this; 469} 470 471inline MessageBuilder TestLog::operator<< (const BeginMessageToken&) 472{ 473 return MessageBuilder(this); 474} 475 476inline MessageBuilder TestLog::message (void) 477{ 478 return MessageBuilder(this); 479} 480 481inline SampleBuilder TestLog::operator<< (const BeginSampleToken&) 482{ 483 return SampleBuilder(this); 484} 485 486inline void LogImageSet::write (TestLog& log) const 487{ 488 log.startImageSet(m_name.c_str(), m_description.c_str()); 489} 490 491inline void LogSection::write (TestLog& log) const 492{ 493 log.startSection(m_name.c_str(), m_description.c_str()); 494} 495 496inline void LogShaderProgram::write (TestLog& log) const 497{ 498 log.startShaderProgram(m_linkOk, m_linkInfoLog.c_str()); 499} 500 501inline void LogShader::write (TestLog& log) const 502{ 503 log.writeShader(m_type, m_source.c_str(), m_compileOk, m_infoLog.c_str()); 504} 505 506inline void LogSpirVAssemblySource::write (TestLog& log) const 507{ 508 log.writeSpirVAssemblySource(m_source.c_str()); 509} 510 511inline void LogKernelSource::write (TestLog& log) const 512{ 513 log.writeKernelSource(m_source.c_str()); 514} 515 516inline void LogSampleList::write (TestLog& log) const 517{ 518 log.startSampleList(m_name, m_description); 519} 520 521inline void LogValueInfo::write (TestLog& log) const 522{ 523 log.writeValueInfo(m_name, m_description, m_unit, m_tag); 524} 525 526template<> 527inline 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 532template<> 533inline 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