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 void writeSessionInfo (std::string additionalInfo = ""); 109 110 MessageBuilder operator<< (const BeginMessageToken&); 111 MessageBuilder message (void); 112 113 TestLog& operator<< (const ImageSet& imageSet); 114 TestLog& operator<< (const Image& image); 115 TestLog& operator<< (const EndImageSetToken&); 116 117 TestLog& operator<< (const Section& section); 118 TestLog& operator<< (const EndSectionToken&); 119 120 TestLog& operator<< (const ShaderProgram& shaderProgram); 121 TestLog& operator<< (const EndShaderProgramToken&); 122 TestLog& operator<< (const Shader& shader); 123 TestLog& operator<< (const SpirVAssemblySource& module); 124 125 TestLog& operator<< (const KernelSource& kernelSrc); 126 127 template<typename T> 128 TestLog& operator<< (const LogNumber<T>& number); 129 130 TestLog& operator<< (const SampleList& sampleList); 131 TestLog& operator<< (const SampleInfoToken&); 132 TestLog& operator<< (const ValueInfo& valueInfo); 133 TestLog& operator<< (const EndSampleInfoToken&); 134 SampleBuilder operator<< (const BeginSampleToken&); 135 TestLog& operator<< (const EndSampleListToken&); 136 137 // Raw api 138 void writeMessage (const char* message); 139 140 void startImageSet (const char* name, const char* description); 141 void endImageSet (void); 142 void writeImage (const char* name, const char* description, const ConstPixelBufferAccess& surface, const Vec4& scale, const Vec4& bias, qpImageCompressionMode compressionMode = QP_IMAGE_COMPRESSION_MODE_BEST); 143 void writeImage (const char* name, const char* description, qpImageCompressionMode compressionMode, qpImageFormat format, int width, int height, int stride, const void* data); 144 145 void startSection (const char* name, const char* description); 146 void endSection (void); 147 148 void startShaderProgram (bool linkOk, const char* linkInfoLog); 149 void endShaderProgram (void); 150 void writeShader (qpShaderType type, const char* source, bool compileOk, const char* infoLog); 151 void writeSpirVAssemblySource(const char* source); 152 void writeKernelSource (const char* source); 153 void writeCompileInfo (const char* name, const char* description, bool compileOk, const char* infoLog); 154 155 void writeFloat (const char* name, const char* description, const char* unit, qpKeyValueTag tag, float value); 156 void writeInteger (const char* name, const char* description, const char* unit, qpKeyValueTag tag, deInt64 value); 157 158 void startEglConfigSet (const char* name, const char* description); 159 void writeEglConfig (const qpEglConfigInfo* config); 160 void endEglConfigSet (void); 161 162 void startCase (const char* testCasePath, qpTestCaseType testCaseType); 163 void endCase (qpTestResult result, const char* description); 164 void terminateCase (qpTestResult result); 165 166 void startTestsCasesTime (void); 167 void endTestsCasesTime (void); 168 169 void startSampleList (const std::string& name, const std::string& description); 170 void startSampleInfo (void); 171 void writeValueInfo (const std::string& name, const std::string& description, const std::string& unit, qpSampleValueTag tag); 172 void endSampleInfo (void); 173 void startSample (void); 174 void writeSampleValue (double value); 175 void writeSampleValue (deInt64 value); 176 void endSample (void); 177 void endSampleList (void); 178 179 void writeRaw (const char* rawContents); 180 181 bool isShaderLoggingEnabled (void); 182 183 void supressLogging (bool value); 184 bool isSupressLogging (void); 185private: 186 TestLog (const TestLog& other); // Not allowed! 187 TestLog& operator= (const TestLog& other); // Not allowed! 188 189 qpTestLog* m_log; 190 bool m_logSupressed; 191 bool m_skipAdditionalDataInLog; 192}; 193 194class MessageBuilder 195{ 196public: 197 explicit MessageBuilder (TestLog* log) : m_log(log) {} 198 ~MessageBuilder (void) {} 199 200 std::string toString (void) const { return m_str.str(); } 201 202 TestLog& operator<< (const TestLog::EndMessageToken&); 203 204 template <typename T> 205 MessageBuilder& operator<< (const T& value); 206 207 MessageBuilder (const MessageBuilder& other); 208 MessageBuilder& operator= (const MessageBuilder& other); 209 210private: 211 TestLog* m_log; 212 std::ostringstream m_str; 213}; 214 215class SampleBuilder 216{ 217public: 218 SampleBuilder (TestLog* log) : m_log(log) {} 219 220 SampleBuilder& operator<< (int v) { m_values.push_back(Value((deInt64)v)); return *this; } 221 SampleBuilder& operator<< (deInt64 v) { m_values.push_back(Value(v)); return *this; } 222 SampleBuilder& operator<< (float v) { m_values.push_back(Value((double)v)); return *this; } 223 SampleBuilder& operator<< (double v) { m_values.push_back(Value(v)); return *this; } 224 225 TestLog& operator<< (const TestLog::EndSampleToken&); 226 227private: 228 struct Value 229 { 230 enum Type { TYPE_INT64 = 0, TYPE_FLOAT64, TYPE_LAST }; 231 232 Type type; 233 union 234 { 235 deInt64 int64; 236 double float64; 237 } value; 238 239 Value (void) : type(TYPE_LAST) { value.int64 = 0; } 240 Value (double v) : type(TYPE_FLOAT64) { value.float64 = v; } 241 Value (deInt64 v) : type(TYPE_INT64) { value.int64 = v; } 242 }; 243 244 TestLog* m_log; 245 std::vector<Value> m_values; 246}; 247 248class LogImageSet 249{ 250public: 251 LogImageSet (const std::string& name, const std::string& description) 252 : m_name (name) 253 , m_description (description) 254 { 255 } 256 257 void write (TestLog& log) const; 258 259private: 260 std::string m_name; 261 std::string m_description; 262}; 263 264// \note Doesn't take copy of surface contents 265class LogImage 266{ 267public: 268 LogImage (const std::string& name, const std::string& description, const Surface& surface, qpImageCompressionMode compression = QP_IMAGE_COMPRESSION_MODE_BEST); 269 270 LogImage (const std::string& name, const std::string& description, const ConstPixelBufferAccess& access, qpImageCompressionMode compression = QP_IMAGE_COMPRESSION_MODE_BEST); 271 272 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); 273 274 void write (TestLog& log) const; 275 276private: 277 std::string m_name; 278 std::string m_description; 279 ConstPixelBufferAccess m_access; 280 Vec4 m_scale; 281 Vec4 m_bias; 282 qpImageCompressionMode m_compression; 283}; 284 285class LogSection 286{ 287public: 288 LogSection (const std::string& name, const std::string& description) 289 : m_name (name) 290 , m_description (description) 291 { 292 } 293 294 void write (TestLog& log) const; 295 296private: 297 std::string m_name; 298 std::string m_description; 299}; 300 301class LogShaderProgram 302{ 303public: 304 LogShaderProgram (bool linkOk, const std::string& linkInfoLog) 305 : m_linkOk (linkOk) 306 , m_linkInfoLog (linkInfoLog) 307 { 308 } 309 310 void write (TestLog& log) const; 311 312private: 313 bool m_linkOk; 314 std::string m_linkInfoLog; 315}; 316 317class LogShader 318{ 319public: 320 LogShader (qpShaderType type, const std::string& source, bool compileOk, const std::string& infoLog) 321 : m_type (type) 322 , m_source (source) 323 , m_compileOk (compileOk) 324 , m_infoLog (infoLog) 325 { 326 } 327 328 void write (TestLog& log) const; 329 330private: 331 qpShaderType m_type; 332 std::string m_source; 333 bool m_compileOk; 334 std::string m_infoLog; 335}; 336 337class LogSpirVAssemblySource 338{ 339public: 340 LogSpirVAssemblySource (const std::string& source) 341 : m_source (source) 342 { 343 } 344 345 void write (TestLog& log) const; 346 347private: 348 std::string m_source; 349}; 350 351class LogKernelSource 352{ 353public: 354 explicit LogKernelSource (const std::string& source) 355 : m_source(source) 356 { 357 } 358 359 void write (TestLog& log) const; 360 361private: 362 std::string m_source; 363}; 364 365class LogSampleList 366{ 367public: 368 LogSampleList (const std::string& name, const std::string& description) 369 : m_name (name) 370 , m_description (description) 371 { 372 } 373 374 void write (TestLog& log) const; 375 376private: 377 std::string m_name; 378 std::string m_description; 379}; 380 381class LogValueInfo 382{ 383public: 384 LogValueInfo (const std::string& name, const std::string& description, const std::string& unit, qpSampleValueTag tag) 385 : m_name (name) 386 , m_description (description) 387 , m_unit (unit) 388 , m_tag (tag) 389 { 390 } 391 392 void write (TestLog& log) const; 393 394private: 395 std::string m_name; 396 std::string m_description; 397 std::string m_unit; 398 qpSampleValueTag m_tag; 399}; 400 401template<typename T> 402class LogNumber 403{ 404public: 405 LogNumber (const std::string& name, const std::string& desc, const std::string& unit, qpKeyValueTag tag, T value) 406 : m_name (name) 407 , m_desc (desc) 408 , m_unit (unit) 409 , m_tag (tag) 410 , m_value (value) 411 { 412 } 413 414 void write (TestLog& log) const; 415 416private: 417 std::string m_name; 418 std::string m_desc; 419 std::string m_unit; 420 qpKeyValueTag m_tag; 421 T m_value; 422}; 423 424// Section helper that closes section when leaving scope. 425class ScopedLogSection 426{ 427public: 428 ScopedLogSection (TestLog& log, const std::string& name, const std::string& description) 429 : m_log(log) 430 { 431 m_log << TestLog::Section(name, description); 432 } 433 434 ~ScopedLogSection (void) 435 { 436 m_log << TestLog::EndSection; 437 } 438 439private: 440 TestLog& m_log; 441}; 442 443// TestLog stream operators. 444 445inline TestLog& TestLog::operator<< (const ImageSet& imageSet) { imageSet.write(*this); return *this; } 446inline TestLog& TestLog::operator<< (const Image& image) { image.write(*this); return *this; } 447inline TestLog& TestLog::operator<< (const EndImageSetToken&) { endImageSet(); return *this; } 448inline TestLog& TestLog::operator<< (const Section& section) { section.write(*this); return *this; } 449inline TestLog& TestLog::operator<< (const EndSectionToken&) { endSection(); return *this; } 450inline TestLog& TestLog::operator<< (const ShaderProgram& shaderProg) { shaderProg.write(*this); return *this; } 451inline TestLog& TestLog::operator<< (const EndShaderProgramToken&) { endShaderProgram(); return *this; } 452inline TestLog& TestLog::operator<< (const Shader& shader) { shader.write(*this); return *this; } 453inline TestLog& TestLog::operator<< (const SpirVAssemblySource& module) { module.write(*this); return *this; } 454inline TestLog& TestLog::operator<< (const KernelSource& kernelSrc) { kernelSrc.write(*this); return *this; } 455inline TestLog& TestLog::operator<< (const SampleList& sampleList) { sampleList.write(*this); return *this; } 456inline TestLog& TestLog::operator<< (const SampleInfoToken&) { startSampleInfo(); return *this; } 457inline TestLog& TestLog::operator<< (const ValueInfo& valueInfo) { valueInfo.write(*this); return *this; } 458inline TestLog& TestLog::operator<< (const EndSampleInfoToken&) { endSampleInfo(); return *this; } 459inline TestLog& TestLog::operator<< (const EndSampleListToken&) { endSampleList(); return *this; } 460 461template<typename T> 462inline TestLog& TestLog::operator<< (const LogNumber<T>& number) 463{ 464 number.write(*this); 465 return *this; 466} 467 468inline TestLog& operator<< (TestLog& log, const std::exception& e) 469{ 470 // \todo [2012-10-18 pyry] Print type info? 471 return log << TestLog::Message << e.what() << TestLog::EndMessage; 472} 473 474// Utility class inline implementations. 475 476template <typename T> 477inline MessageBuilder& MessageBuilder::operator<< (const T& value) 478{ 479 // Overload stream operator to implement custom format 480 m_str << value; 481 return *this; 482} 483 484inline MessageBuilder TestLog::operator<< (const BeginMessageToken&) 485{ 486 return MessageBuilder(this); 487} 488 489inline MessageBuilder TestLog::message (void) 490{ 491 return MessageBuilder(this); 492} 493 494inline SampleBuilder TestLog::operator<< (const BeginSampleToken&) 495{ 496 return SampleBuilder(this); 497} 498 499inline void LogImageSet::write (TestLog& log) const 500{ 501 log.startImageSet(m_name.c_str(), m_description.c_str()); 502} 503 504inline void LogSection::write (TestLog& log) const 505{ 506 log.startSection(m_name.c_str(), m_description.c_str()); 507} 508 509inline void LogShaderProgram::write (TestLog& log) const 510{ 511 log.startShaderProgram(m_linkOk, m_linkInfoLog.c_str()); 512} 513 514inline void LogShader::write (TestLog& log) const 515{ 516 log.writeShader(m_type, m_source.c_str(), m_compileOk, m_infoLog.c_str()); 517} 518 519inline void LogSpirVAssemblySource::write (TestLog& log) const 520{ 521 log.writeSpirVAssemblySource(m_source.c_str()); 522} 523 524inline void LogKernelSource::write (TestLog& log) const 525{ 526 log.writeKernelSource(m_source.c_str()); 527} 528 529inline void LogSampleList::write (TestLog& log) const 530{ 531 log.startSampleList(m_name, m_description); 532} 533 534inline void LogValueInfo::write (TestLog& log) const 535{ 536 log.writeValueInfo(m_name, m_description, m_unit, m_tag); 537} 538 539template<> 540inline void LogNumber<float>::write (TestLog& log) const 541{ 542 log.writeFloat(m_name.c_str(), m_desc.c_str(), m_unit.c_str(), m_tag, m_value); 543} 544 545template<> 546inline void LogNumber<deInt64>::write (TestLog& log) const 547{ 548 log.writeInteger(m_name.c_str(), m_desc.c_str(), m_unit.c_str(), m_tag, m_value); 549} 550 551} // tcu 552 553#endif // _TCUTESTLOG_HPP 554