text: /*
   * A simple test for getting count of registered cooperations
   * from run-time monitoring messages.
   */
  
  #include <iostream>
  #include <map>
  #include <exception>
  #include <stdexcept>
  #include <cstdlib>
  #include <thread>
  #include <chrono>
  
  #include <so_5/all.hpp>
  
  #include <test/3rd_party/various_helpers/time_limited_execution.hpp>
  
  class a_test_t : public so_5::agent_t
  	{
  	public :
  		a_test_t( context_t ctx )
  			:	so_5::agent_t( ctx )
  			{}
  
  		virtual void
  		so_define_agent() override
  			{
  				so_default_state().event(
  						so_environment().stats_controller().mbox(),
  						&a_test_t::evt_monitor_quantity );
  			}
  
  		virtual void
  		so_evt_start() override
  			{
  				create_child_coops();
  
  				// This big value can lead to test failure if there is an
  				// error in implementation of autoshutdown feature.
  				so_environment().stats_controller().
  					set_distribution_period(
  							std::chrono::seconds(30) );
  
  				so_environment().stats_controller().turn_on();
  			}
  
  	private :
  		unsigned int m_actual_values = { 0 };
  
  		void
  		evt_monitor_quantity(
  			const so_5::stats::messages::quantity< std::size_t > & evt )
  			{
  				namespace stats = so_5::stats;
  
  				std::cout << evt.m_prefix.c_str()
  						<< evt.m_suffix.c_str()
  						<< ": " << evt.m_value << std::endl;
  
  				if( stats::prefixes::coop_repository() == evt.m_prefix )
  					{
  						if( stats::suffixes::coop_count() == evt.m_suffix )
  							{
  								// Count of registered cooperations could be
  								// 12 or 11 (it depends of deregistration of
  								// the special autoshutdown-guard cooperation).
  								if( 12 != evt.m_value && 11 != evt.m_value )
  									throw std::runtime_error( "unexpected count of "
  											"registered cooperations: " +
  											std::to_string( evt.m_value ) );
  								else
  									++m_actual_values;
  							}
  						else if( stats::suffixes::agent_count() == evt.m_suffix )
  							{
  								// Count of registered agents could be
  								// 11 or 12 (it depends of deregistration of
  								// the special autoshutdown-guard cooperation).
  								if( 11 != evt.m_value && 12 != evt.m_value )
  									throw std::runtime_error( "unexpected count of "
  											"registered agents: " +
  											std::to_string( evt.m_value ) );
  								else
  									++m_actual_values;
  							}
  						else if( stats::suffixes::coop_final_dereg_count() == evt.m_suffix )
  							{
  								// Count of coops waiting for final dereg could be
  								// 0 or 1 (it depends of deregistration of
  								// the special autoshutdown-guard cooperation).
  								if( 0 != evt.m_value && 1 != evt.m_value )
  									throw std::runtime_error( "unexpected count of "
  											"coops in final dereg state: " +
  											std::to_string( evt.m_value ) );
  								else
  									++m_actual_values;
  							}
  					}
  
  				if( 3 == m_actual_values )
  					so_deregister_agent_coop_normally();
  			}
  
  		void
  		create_child_coops()
  			{
  				class empty_actor_t final : public so_5::agent_t
  				{
  				public :
  					using so_5::agent_t::agent_t;
  				};
  
  				for( int i = 0; i != 10; ++i )
  					{
  						auto coop = so_5::create_child_coop( *this );
  						coop->make_agent< empty_actor_t >();
  
  						so_environment().register_coop( std::move( coop ) );
  					}
  			}
  	};
  
  void
  init( so_5::environment_t & env )
  	{
  		env.register_agent_as_coop( env.make_agent< a_test_t >() );
  	}
  
  int
  main()
  {
  	try
  	{
  		run_with_time_limit(
  			[]()
  			{
  				so_5::launch( &init,
  					[]( so_5::environment_params_t & params ) {
  						params.infrastructure_factory(
  								so_5::env_infrastructures::simple_not_mtsafe::factory() );
  					} );
  			},
  			20,
  			"simple coop count monitoring test" );
  	}
  	catch( const std::exception & ex )
  	{
  		std::cerr << "Error: " << ex.what() << std::endl;
  		return 1;
  	}
  
  	return 0;
  }
  
  