text: /*
   *  Created by Phil on 31/12/2010.
   *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
   *
   *  Distributed under the Boost Software License, Version 1.0. (See accompanying
   *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
   */
  #ifndef TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
  #define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
  
  #include "catch_section_info.h"
  #include "catch_common.h"
  #include "catch_totals.hpp"
  #include "catch_ptr.hpp"
  #include "catch_config.hpp"
  #include "catch_test_case_info.h"
  #include "catch_assertionresult.h"
  #include "catch_message.h"
  #include "catch_option.hpp"
  
  #include <string>
  #include <ostream>
  #include <map>
  #include <assert.h>
  
  namespace Catch
  {
      struct ReporterConfig {
          explicit ReporterConfig( Ptr<IConfig const> const& _fullConfig )
          :   m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
  
          ReporterConfig( Ptr<IConfig const> const& _fullConfig, std::ostream& _stream )
          :   m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
  
          std::ostream& stream() const    { return *m_stream; }
          Ptr<IConfig const> fullConfig() const { return m_fullConfig; }
  
      private:
          std::ostream* m_stream;
          Ptr<IConfig const> m_fullConfig;
      };
  
      struct ReporterPreferences {
          ReporterPreferences()
          : shouldRedirectStdOut( false )
          {}
  
          bool shouldRedirectStdOut;
      };
  
      template<typename T>
      struct LazyStat : Option<T> {
          LazyStat() : used( false ) {}
          LazyStat& operator=( T const& _value ) {
              Option<T>::operator=( _value );
              used = false;
              return *this;
          }
          void reset() {
              Option<T>::reset();
              used = false;
          }
          bool used;
      };
  
      struct TestRunInfo {
          TestRunInfo( std::string const& _name ) : name( _name ) {}
          std::string name;
      };
      struct GroupInfo {
          GroupInfo(  std::string const& _name,
                      std::size_t _groupIndex,
                      std::size_t _groupsCount )
          :   name( _name ),
              groupIndex( _groupIndex ),
              groupsCounts( _groupsCount )
          {}
  
          std::string name;
          std::size_t groupIndex;
          std::size_t groupsCounts;
      };
  
      struct AssertionStats {
          AssertionStats( AssertionResult const& _assertionResult,
                          std::vector<MessageInfo> const& _infoMessages,
                          Totals const& _totals )
          :   assertionResult( _assertionResult ),
              infoMessages( _infoMessages ),
              totals( _totals )
          {
              if( assertionResult.hasMessage() ) {
                  // Copy message into messages list.
                  // !TBD This should have been done earlier, somewhere
                  MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
                  builder << assertionResult.getMessage();
                  builder.m_info.message = builder.m_stream.str();
  
                  infoMessages.push_back( builder.m_info );
              }
          }
          virtual ~AssertionStats();
  
  #  ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
          AssertionStats( AssertionStats const& )              = default;
          AssertionStats( AssertionStats && )                  = default;
          AssertionStats& operator = ( AssertionStats const& ) = default;
          AssertionStats& operator = ( AssertionStats && )     = default;
  #  endif
  
          AssertionResult assertionResult;
          std::vector<MessageInfo> infoMessages;
          Totals totals;
      };
  
      struct SectionStats {
          SectionStats(   SectionInfo const& _sectionInfo,
                          Counts const& _assertions,
                          double _durationInSeconds,
                          bool _missingAssertions )
          :   sectionInfo( _sectionInfo ),
              assertions( _assertions ),
              durationInSeconds( _durationInSeconds ),
              missingAssertions( _missingAssertions )
          {}
          virtual ~SectionStats();
  #  ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
          SectionStats( SectionStats const& )              = default;
          SectionStats( SectionStats && )                  = default;
          SectionStats& operator = ( SectionStats const& ) = default;
          SectionStats& operator = ( SectionStats && )     = default;
  #  endif
  
          SectionInfo sectionInfo;
          Counts assertions;
          double durationInSeconds;
          bool missingAssertions;
      };
  
      struct TestCaseStats {
          TestCaseStats(  TestCaseInfo const& _testInfo,
                          Totals const& _totals,
                          std::string const& _stdOut,
                          std::string const& _stdErr,
                          bool _aborting )
          : testInfo( _testInfo ),
              totals( _totals ),
              stdOut( _stdOut ),
              stdErr( _stdErr ),
              aborting( _aborting )
          {}
          virtual ~TestCaseStats();
  
  #  ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
          TestCaseStats( TestCaseStats const& )              = default;
          TestCaseStats( TestCaseStats && )                  = default;
          TestCaseStats& operator = ( TestCaseStats const& ) = default;
          TestCaseStats& operator = ( TestCaseStats && )     = default;
  #  endif
  
          TestCaseInfo testInfo;
          Totals totals;
          std::string stdOut;
          std::string stdErr;
          bool aborting;
      };
  
      struct TestGroupStats {
          TestGroupStats( GroupInfo const& _groupInfo,
                          Totals const& _totals,
                          bool _aborting )
          :   groupInfo( _groupInfo ),
              totals( _totals ),
              aborting( _aborting )
          {}
          TestGroupStats( GroupInfo const& _groupInfo )
          :   groupInfo( _groupInfo ),
              aborting( false )
          {}
          virtual ~TestGroupStats();
  
  #  ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
          TestGroupStats( TestGroupStats const& )              = default;
          TestGroupStats( TestGroupStats && )                  = default;
          TestGroupStats& operator = ( TestGroupStats const& ) = default;
          TestGroupStats& operator = ( TestGroupStats && )     = default;
  #  endif
  
          GroupInfo groupInfo;
          Totals totals;
          bool aborting;
      };
  
      struct TestRunStats {
          TestRunStats(   TestRunInfo const& _runInfo,
                          Totals const& _totals,
                          bool _aborting )
          :   runInfo( _runInfo ),
              totals( _totals ),
              aborting( _aborting )
          {}
          virtual ~TestRunStats();
  
  #  ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
          TestRunStats( TestRunStats const& _other )
          :   runInfo( _other.runInfo ),
              totals( _other.totals ),
              aborting( _other.aborting )
          {}
  #  else
          TestRunStats( TestRunStats const& )              = default;
          TestRunStats( TestRunStats && )                  = default;
          TestRunStats& operator = ( TestRunStats const& ) = default;
          TestRunStats& operator = ( TestRunStats && )     = default;
  #  endif
  
          TestRunInfo runInfo;
          Totals totals;
          bool aborting;
      };
  
  
      struct IStreamingReporter : IShared {
          virtual ~IStreamingReporter();
  
          // Implementing class must also provide the following static method:
          // static std::string getDescription();
  
          virtual ReporterPreferences getPreferences() const = 0;
  
          virtual void noMatchingTestCases( std::string const& spec ) = 0;
  
          virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
          virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
  
          virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
          virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
  
          virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
  
          // The return value indicates if the messages buffer should be cleared:
          virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
  
          virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
          virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
          virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
          virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
  
          virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
      };
  
  
      struct IReporterFactory : IShared {
          virtual ~IReporterFactory();
          virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
          virtual std::string getDescription() const = 0;
      };
  
      struct IReporterRegistry {
          typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap;
          typedef std::vector<Ptr<IReporterFactory> > Listeners;
  
          virtual ~IReporterRegistry();
          virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const = 0;
          virtual FactoryMap const& getFactories() const = 0;
          virtual Listeners const& getListeners() const = 0;
      };
  
      Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter );
  
  }
  
  #endif // TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
  