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