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