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 LogKernelSource; 43 class LogSampleList; 44 class LogValueInfo; 45 class SampleBuilder; 46 template<typename T> class LogNumber; 47 48 /*--------------------------------------------------------------------*//*! 49 * \brief Test log 50 * 51 * TestLog provides convinient C++ API for logging. The API has been designed 52 * around stream operators much like STL iostream library. The following 53 * examples demonstrate how to use TestLog. 54 * 55 * \code 56 * TestLog& log = m_testCtx.getLog(); 57 * 58 * // Write message to log. 59 * log << TestLog::Message << "Hello, World!" << TestLog::EndMessage; 60 * int myNumber = 3; 61 * log << TestLog::Message << "Diff is " << myNumber << TestLog::EndMessage; 62 * 63 * // Write image 64 * Surface myImage(256, 256); 65 * log << TestLog::Image("TestImage", "My test image", myImage); 66 * 67 * // Multiple commands can be combined: 68 * log << TestLog::Section("Details", "Test case details") 69 * << TestLog::Message << "Here be dragons" << TestLog::EndMessage 70 * << TestLog::ImageSet("Result", "Result images") 71 * << TestLog::Image("ImageA", "Image A", imageA) 72 * << TestLog::Image("ImageB", "Image B", imageB) 73 * << TestLog::EndImageSet << TestLog::EndSection; 74 * \endcode 75 *//*--------------------------------------------------------------------*/ 76 class TestLog 77 { 78 public: 79 // Tokens 80 static const class BeginMessageToken {} Message; 81 static const class EndMessageToken {} EndMessage; 82 static const class EndImageSetToken {} EndImageSet; 83 static const class EndSectionToken {} EndSection; 84 static const class EndShaderProgramToken {} EndShaderProgram; 85 static const class SampleInfoToken {} SampleInfo; 86 static const class EndSampleInfoToken {} EndSampleInfo; 87 static const class BeginSampleToken {} Sample; 88 static const class EndSampleToken {} EndSample; 89 static const class EndSampleListToken {} EndSampleList; 90 91 // Typedefs. 92 typedef LogImageSet ImageSet; 93 typedef LogImage Image; 94 typedef LogSection Section; 95 typedef LogShaderProgram ShaderProgram; 96 typedef LogShader Shader; 97 typedef LogKernelSource KernelSource; 98 typedef LogSampleList SampleList; 99 typedef LogValueInfo ValueInfo; 100 typedef LogNumber<float> Float; 101 typedef LogNumber<deInt64> Integer; 102 103 explicit TestLog (const char* fileName, deUint32 flags = 0); 104 ~TestLog (void); 105 106 MessageBuilder operator<< (const BeginMessageToken&); 107 MessageBuilder message (void); 108 109 TestLog& operator<< (const ImageSet& imageSet); 110 TestLog& operator<< (const Image& image); 111 TestLog& operator<< (const EndImageSetToken&); 112 113 TestLog& operator<< (const Section& section); 114 TestLog& operator<< (const EndSectionToken&); 115 116 TestLog& operator<< (const ShaderProgram& shaderProgram); 117 TestLog& operator<< (const EndShaderProgramToken&); 118 TestLog& operator<< (const Shader& shader); 119 120 TestLog& operator<< (const KernelSource& kernelSrc); 121 122 template<typename T> 123 TestLog& operator<< (const LogNumber<T>& number); 124 125 TestLog& operator<< (const SampleList& sampleList); 126 TestLog& operator<< (const SampleInfoToken&); 127 TestLog& operator<< (const ValueInfo& valueInfo); 128 TestLog& operator<< (const EndSampleInfoToken&); 129 SampleBuilder operator<< (const BeginSampleToken&); 130 TestLog& operator<< (const EndSampleListToken&); 131 132 // Raw api 133 void writeMessage (const char* message); 134 135 void startImageSet (const char* name, const char* description); 136 void endImageSet (void); 137 void writeImage (const char* name, const char* description, const ConstPixelBufferAccess& surface, const Vec4& scale, const Vec4& bias, qpImageCompressionMode compressionMode = QP_IMAGE_COMPRESSION_MODE_BEST); 138 void writeImage (const char* name, const char* description, qpImageCompressionMode compressionMode, qpImageFormat format, int width, int height, int stride, const void* data); 139 140 void startSection (const char* name, const char* description); 141 void endSection (void); 142 143 void startShaderProgram (bool linkOk, const char* linkInfoLog); 144 void endShaderProgram (void); 145 void writeShader (qpShaderType type, const char* source, bool compileOk, const char* infoLog); 146 147 void writeKernelSource (const char* source); 148 void writeCompileInfo (const char* name, const char* description, bool compileOk, const char* infoLog); 149 150 void writeFloat (const char* name, const char* description, const char* unit, qpKeyValueTag tag, float value); 151 void writeInteger (const char* name, const char* description, const char* unit, qpKeyValueTag tag, deInt64 value); 152 153 void startEglConfigSet (const char* name, const char* description); 154 void writeEglConfig (const qpEglConfigInfo* config); 155 void endEglConfigSet (void); 156 157 void startCase (const char* testCasePath, qpTestCaseType testCaseType); 158 void endCase (qpTestResult result, const char* description); 159 void terminateCase (qpTestResult result); 160 161 void startSampleList (const std::string& name, const std::string& description); 162 void startSampleInfo (void); 163 void writeValueInfo (const std::string& name, const std::string& description, const std::string& unit, qpSampleValueTag tag); 164 void endSampleInfo (void); 165 void startSample (void); 166 void writeSampleValue (double value); 167 void writeSampleValue (deInt64 value); 168 void endSample (void); 169 void endSampleList (void); 170 171 private: 172 TestLog (const TestLog& other); // Not allowed! 173 TestLog& operator= (const TestLog& other); // Not allowed! 174 175 qpTestLog* m_log; 176 }; 177 178 class MessageBuilder 179 { 180 public: 181 explicit MessageBuilder (TestLog* log) : m_log(log) {} 182 ~MessageBuilder (void) {} 183 184 std::string toString (void) const { return m_str.str(); } 185 186 TestLog& operator<< (const TestLog::EndMessageToken&); 187 188 template <typename T> 189 MessageBuilder& operator<< (const T& value); 190 191 MessageBuilder (const MessageBuilder& other); 192 MessageBuilder& operator= (const MessageBuilder& other); 193 194 private: 195 TestLog* m_log; 196 std::ostringstream m_str; 197 }; 198 199 class SampleBuilder 200 { 201 public: 202 SampleBuilder (TestLog* log) : m_log(log) {} 203 204 SampleBuilder& operator<< (int v) { m_values.push_back(Value((deInt64)v)); return *this; } 205 SampleBuilder& operator<< (deInt64 v) { m_values.push_back(Value(v)); return *this; } 206 SampleBuilder& operator<< (float v) { m_values.push_back(Value((double)v)); return *this; } 207 SampleBuilder& operator<< (double v) { m_values.push_back(Value(v)); return *this; } 208 209 TestLog& operator<< (const TestLog::EndSampleToken&); 210 211 private: 212 struct Value 213 { 214 enum Type { TYPE_INT64 = 0, TYPE_FLOAT64, TYPE_LAST }; 215 216 Type type; 217 union 218 { 219 deInt64 int64; 220 double float64; 221 } value; 222 223 Value (void) : type(TYPE_LAST) { value.int64 = 0; } 224 Value (double v) : type(TYPE_FLOAT64) { value.float64 = v; } 225 Value (deInt64 v) : type(TYPE_INT64) { value.int64 = v; } 226 }; 227 228 TestLog* m_log; 229 std::vector<Value> m_values; 230 }; 231 232 class LogImageSet 233 { 234 public: 235 LogImageSet (const std::string& name, const std::string& description) 236 : m_name (name) 237 , m_description (description) 238 { 239 } 240 241 void write (TestLog& log) const; 242 243 private: 244 std::string m_name; 245 std::string m_description; 246 }; 247 248 // \note Doesn't take copy of surface contents 249 class LogImage 250 { 251 public: 252 LogImage (const std::string& name, const std::string& description, const Surface& surface, qpImageCompressionMode compression = QP_IMAGE_COMPRESSION_MODE_BEST); 253 254 LogImage (const std::string& name, const std::string& description, const ConstPixelBufferAccess& access, qpImageCompressionMode compression = QP_IMAGE_COMPRESSION_MODE_BEST); 255 256 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) 257 : m_name (name) 258 , m_description (description) 259 , m_access (access) 260 , m_scale (scale) 261 , m_bias (bias) 262 , m_compression (compression) 263 { 264 } 265 266 void write (TestLog& log) const; 267 268 private: 269 std::string m_name; 270 std::string m_description; 271 ConstPixelBufferAccess m_access; 272 Vec4 m_scale; 273 Vec4 m_bias; 274 qpImageCompressionMode m_compression; 275 }; 276 277 class LogSection 278 { 279 public: 280 LogSection (const std::string& name, const std::string& description) 281 : m_name (name) 282 , m_description (description) 283 { 284 } 285 286 void write (TestLog& log) const; 287 288 private: 289 std::string m_name; 290 std::string m_description; 291 }; 292 293 class LogShaderProgram 294 { 295 public: 296 LogShaderProgram (bool linkOk, const std::string& linkInfoLog) 297 : m_linkOk (linkOk) 298 , m_linkInfoLog (linkInfoLog) 299 { 300 } 301 302 void write (TestLog& log) const; 303 304 private: 305 bool m_linkOk; 306 std::string m_linkInfoLog; 307 }; 308 309 class LogShader 310 { 311 public: 312 LogShader (qpShaderType type, const std::string& source, bool compileOk, const std::string& infoLog) 313 : m_type (type) 314 , m_source (source) 315 , m_compileOk (compileOk) 316 , m_infoLog (infoLog) 317 { 318 } 319 320 void write (TestLog& log) const; 321 322 private: 323 qpShaderType m_type; 324 std::string m_source; 325 bool m_compileOk; 326 std::string m_infoLog; 327 }; 328 329 class LogKernelSource 330 { 331 public: 332 explicit LogKernelSource (const std::string& source) 333 : m_source(source) 334 { 335 } 336 337 void write (TestLog& log) const; 338 339 private: 340 std::string m_source; 341 }; 342 343 class LogSampleList 344 { 345 public: 346 LogSampleList (const std::string& name, const std::string& description) 347 : m_name (name) 348 , m_description (description) 349 { 350 } 351 352 void write (TestLog& log) const; 353 354 private: 355 std::string m_name; 356 std::string m_description; 357 }; 358 359 class LogValueInfo 360 { 361 public: 362 LogValueInfo (const std::string& name, const std::string& description, const std::string& unit, qpSampleValueTag tag) 363 : m_name (name) 364 , m_description (description) 365 , m_unit (unit) 366 , m_tag (tag) 367 { 368 } 369 370 void write (TestLog& log) const; 371 372 private: 373 std::string m_name; 374 std::string m_description; 375 std::string m_unit; 376 qpSampleValueTag m_tag; 377 }; 378 379 template<typename T> 380 class LogNumber 381 { 382 public: 383 LogNumber (const std::string& name, const std::string& desc, const std::string& unit, qpKeyValueTag tag, T value) 384 : m_name (name) 385 , m_desc (desc) 386 , m_unit (unit) 387 , m_tag (tag) 388 , m_value (value) 389 { 390 } 391 392 void write (TestLog& log) const; 393 394 private: 395 std::string m_name; 396 std::string m_desc; 397 std::string m_unit; 398 qpKeyValueTag m_tag; 399 T m_value; 400 }; 401 402 // Section helper that closes section when leaving scope. 403 class ScopedLogSection 404 { 405 public: 406 ScopedLogSection (TestLog& log, const std::string& name, const std::string& description) 407 : m_log(log) 408 { 409 m_log << TestLog::Section(name, description); 410 } 411 412 ~ScopedLogSection (void) 413 { 414 m_log << TestLog::EndSection; 415 } 416 417 private: 418 TestLog& m_log; 419 }; 420 421 // TestLog stream operators. 422 423 inline TestLog& TestLog::operator<< (const ImageSet& imageSet) { imageSet.write(*this); return *this; } 424 inline TestLog& TestLog::operator<< (const Image& image) { image.write(*this); return *this; } 425 inline TestLog& TestLog::operator<< (const EndImageSetToken&) { endImageSet(); return *this; } 426 inline TestLog& TestLog::operator<< (const Section& section) { section.write(*this); return *this; } 427 inline TestLog& TestLog::operator<< (const EndSectionToken&) { endSection(); return *this; } 428 inline TestLog& TestLog::operator<< (const ShaderProgram& shaderProg) { shaderProg.write(*this); return *this; } 429 inline TestLog& TestLog::operator<< (const EndShaderProgramToken&) { endShaderProgram(); return *this; } 430 inline TestLog& TestLog::operator<< (const Shader& shader) { shader.write(*this); return *this; } 431 inline TestLog& TestLog::operator<< (const KernelSource& kernelSrc) { kernelSrc.write(*this); return *this; } 432 inline TestLog& TestLog::operator<< (const SampleList& sampleList) { sampleList.write(*this); return *this; } 433 inline TestLog& TestLog::operator<< (const SampleInfoToken&) { startSampleInfo(); return *this; } 434 inline TestLog& TestLog::operator<< (const ValueInfo& valueInfo) { valueInfo.write(*this); return *this; } 435 inline TestLog& TestLog::operator<< (const EndSampleInfoToken&) { endSampleInfo(); return *this; } 436 inline TestLog& TestLog::operator<< (const EndSampleListToken&) { endSampleList(); return *this; } 437 438 template<typename T> 439 inline TestLog& TestLog::operator<< (const LogNumber<T>& number) 440 { 441 number.write(*this); 442 return *this; 443 } 444 445 inline TestLog& operator<< (TestLog& log, const std::exception& e) 446 { 447 // \todo [2012-10-18 pyry] Print type info? 448 return log << TestLog::Message << e.what() << TestLog::EndMessage; 449 } 450 451 // Utility class inline implementations. 452 453 template <typename T> 454 inline MessageBuilder& MessageBuilder::operator<< (const T& value) 455 { 456 // Overload stream operator to implement custom format 457 m_str << value; 458 return *this; 459 } 460 461 inline MessageBuilder TestLog::operator<< (const BeginMessageToken&) 462 { 463 return MessageBuilder(this); 464 } 465 466 inline MessageBuilder TestLog::message (void) 467 { 468 return MessageBuilder(this); 469 } 470 471 inline SampleBuilder TestLog::operator<< (const BeginSampleToken&) 472 { 473 return SampleBuilder(this); 474 } 475 476 inline void LogImageSet::write (TestLog& log) const 477 { 478 log.startImageSet(m_name.c_str(), m_description.c_str()); 479 } 480 481 inline void LogImage::write (TestLog& log) const 482 { 483 log.writeImage(m_name.c_str(), m_description.c_str(), m_access, m_scale, m_bias, m_compression); 484 } 485 486 inline void LogSection::write (TestLog& log) const 487 { 488 log.startSection(m_name.c_str(), m_description.c_str()); 489 } 490 491 inline void LogShaderProgram::write (TestLog& log) const 492 { 493 log.startShaderProgram(m_linkOk, m_linkInfoLog.c_str()); 494 } 495 496 inline void LogShader::write (TestLog& log) const 497 { 498 log.writeShader(m_type, m_source.c_str(), m_compileOk, m_infoLog.c_str()); 499 } 500 501 inline void LogKernelSource::write (TestLog& log) const 502 { 503 log.writeKernelSource(m_source.c_str()); 504 } 505 506 inline void LogSampleList::write (TestLog& log) const 507 { 508 log.startSampleList(m_name, m_description); 509 } 510 511 inline void LogValueInfo::write (TestLog& log) const 512 { 513 log.writeValueInfo(m_name, m_description, m_unit, m_tag); 514 } 515 516 template<> 517 inline void LogNumber<float>::write (TestLog& log) const 518 { 519 log.writeFloat(m_name.c_str(), m_desc.c_str(), m_unit.c_str(), m_tag, m_value); 520 } 521 522 template<> 523 inline void LogNumber<deInt64>::write (TestLog& log) const 524 { 525 log.writeInteger(m_name.c_str(), m_desc.c_str(), m_unit.c_str(), m_tag, m_value); 526 } 527 528 } // tcu 529 530 #endif // _TCUTESTLOG_HPP 531