text:
#ifndef OSMIUM_OBJECT_POINTER_COLLECTION_HPP
#define OSMIUM_OBJECT_POINTER_COLLECTION_HPP

/*

This file is part of Osmium (http://osmcode.org/libosmium).

Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).

Boost Software License - Version 1.0 - August 17th, 2003

Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:

The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

*/

#include <algorithm>
#include <utility>
#include <vector>

#include <boost/iterator/indirect_iterator.hpp>

#include <osmium/handler.hpp>
#include <osmium/memory/item.hpp>
#include <osmium/osm/object.hpp>

// IWYU pragma: no_forward_declare osmium::OSMObject
// IWYU pragma: no_forward_declare osmium::memory::Item

namespace osmium {

    /**
     * A collection of pointers to OSM objects. The pointers can be easily
     * and quickly sorted or otherwise manipulated, while the objects
     * themselves or the buffers they are in, do not have to be changed.
     *
     * An iterator is provided that can iterate over the pointers but looks
     * like it is iterating over the underlying OSM objects.
     *
     * This class implements the visitor pattern which makes it easy to
     * populate the collection from a buffer of OSM objects:
     *
     *   osmium::ObjectPointerCollection objects;
     *   osmium::memory::Buffer buffer = reader.read();
     *   osmium::apply(buffer, objects);
     *
     */
    class ObjectPointerCollection : public osmium::handler::Handler {

        std::vector<osmium::OSMObject*> m_objects;

    public:

        using iterator       = boost::indirect_iterator<std::vector<osmium::OSMObject*>::iterator, osmium::OSMObject>;
        using const_iterator = boost::indirect_iterator<std::vector<osmium::OSMObject*>::const_iterator, const osmium::OSMObject>;

        ObjectPointerCollection() noexcept :
            m_objects() {
        }

        void osm_object(osmium::OSMObject& object) {
            m_objects.push_back(&object);
        }

        /**
         * Sort objects according to the given order functor.
         */
        template <typename TCompare>
        void sort(TCompare&& compare) {
            std::sort(m_objects.begin(), m_objects.end(), std::forward<TCompare>(compare));
        }

        iterator begin() {
            return iterator { m_objects.begin() };
        }

        iterator end() {
            return iterator { m_objects.end() };
        }

        const_iterator cbegin() const {
            return const_iterator { m_objects.cbegin() };
        }

        const_iterator cend() const {
            return const_iterator { m_objects.cend() };
        }

    }; // class ObjectPointerCollection

} // namespace osmium

#endif // OSMIUM_OBJECT_POINTER_COLLECTION_HPP

ext: hpp

max_stars_repo_name: tinloaf/libosmium

max_issues_repo_name: tinloaf/libosmium

max_forks_repo_name: tinloaf/libosmium


text:
/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/*
 * Copyright 2016 ScyllaDB
 */

#define BOOST_TEST_MODULE core

#include <boost/test/included/unit_test.hpp>
#include "core/weak_ptr.hh"

using namespace seastar;

class myclass : public weakly_referencable<myclass> {};

BOOST_AUTO_TEST_CASE(test_weak_ptr_is_empty_when_default_initialized) {
    weak_ptr<myclass> wp;
    BOOST_REQUIRE(!bool(wp));
}

BOOST_AUTO_TEST_CASE(test_weak_ptr_is_reset) {
    auto owning_ptr = std::make_unique<myclass>();
    weak_ptr<myclass> wp = owning_ptr->weak_from_this();
    BOOST_REQUIRE(bool(wp));
    BOOST_REQUIRE(&*wp == &*owning_ptr);
    owning_ptr = {};
    BOOST_REQUIRE(!bool(wp));
}

BOOST_AUTO_TEST_CASE(test_weak_ptr_can_be_moved) {
    auto owning_ptr = std::make_unique<myclass>();
    weak_ptr<myclass> wp1 = owning_ptr->weak_from_this();
    weak_ptr<myclass> wp2 = owning_ptr->weak_from_this();
    weak_ptr<myclass> wp3 = owning_ptr->weak_from_this();

    auto wp3_moved = std::move(wp3);
    auto wp1_moved = std::move(wp1);
    auto wp2_moved = std::move(wp2);
    BOOST_REQUIRE(!bool(wp1));
    BOOST_REQUIRE(!bool(wp2));
    BOOST_REQUIRE(!bool(wp3));
    BOOST_REQUIRE(bool(wp1_moved));
    BOOST_REQUIRE(bool(wp2_moved));
    BOOST_REQUIRE(bool(wp3_moved));

    owning_ptr = {};

    BOOST_REQUIRE(!bool(wp1_moved));
    BOOST_REQUIRE(!bool(wp2_moved));
    BOOST_REQUIRE(!bool(wp3_moved));
}

BOOST_AUTO_TEST_CASE(test_multipe_weak_ptrs) {
    auto owning_ptr = std::make_unique<myclass>();

    weak_ptr<myclass> wp1 = owning_ptr->weak_from_this();
    BOOST_REQUIRE(bool(wp1));
    BOOST_REQUIRE(&*wp1 == &*owning_ptr);

    weak_ptr<myclass> wp2 = owning_ptr->weak_from_this();
    BOOST_REQUIRE(bool(wp2));
    BOOST_REQUIRE(&*wp2 == &*owning_ptr);

    owning_ptr = {};

    BOOST_REQUIRE(!bool(wp1));
    BOOST_REQUIRE(!bool(wp2));
}

BOOST_AUTO_TEST_CASE(test_multipe_weak_ptrs_going_away_first) {
    auto owning_ptr = std::make_unique<myclass>();

    weak_ptr<myclass> wp1 = owning_ptr->weak_from_this();
    weak_ptr<myclass> wp2 = owning_ptr->weak_from_this();
    weak_ptr<myclass> wp3 = owning_ptr->weak_from_this();

    BOOST_REQUIRE(bool(wp1));
    BOOST_REQUIRE(bool(wp2));
    BOOST_REQUIRE(bool(wp3));

    wp2 = {};

    owning_ptr = std::make_unique<myclass>();

    BOOST_REQUIRE(!bool(wp1));
    BOOST_REQUIRE(!bool(wp2));
    BOOST_REQUIRE(!bool(wp3));

    wp1 = owning_ptr->weak_from_this();
    wp2 = owning_ptr->weak_from_this();
    wp3 = owning_ptr->weak_from_this();

    BOOST_REQUIRE(bool(wp1));
    BOOST_REQUIRE(bool(wp2));
    BOOST_REQUIRE(bool(wp3));

    wp3 = {};
    owning_ptr = std::make_unique<myclass>();

    BOOST_REQUIRE(!bool(wp1));
    BOOST_REQUIRE(!bool(wp2));
    BOOST_REQUIRE(!bool(wp3));

    wp1 = owning_ptr->weak_from_this();
    wp2 = owning_ptr->weak_from_this();
    wp3 = owning_ptr->weak_from_this();

    wp1 = {};
    wp3 = {};
    owning_ptr = std::make_unique<myclass>();

    BOOST_REQUIRE(!bool(wp1));
    BOOST_REQUIRE(!bool(wp2));
    BOOST_REQUIRE(!bool(wp3));
}

ext: cc

max_stars_repo_name: hitflame/x-deeplearning


text:
#include <boost/test/unit_test.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <eosio/testing/tester.hpp>
#include <eosio/chain/block_log.hpp>
#include <eosio/chain/wast_to_wasm.hpp>
#include <eosio/chain/eosio_contract.hpp>
#include <eosio/chain/generated_transaction_object.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/gzip.hpp>

#include <fstream>

#include <contracts.hpp>

namespace bio = boost::iostreams;

eosio::chain::asset core_from_string(const std::string& s) {
  return eosio::chain::asset::from_string(s + " " CORE_SYMBOL_NAME);
}

namespace eosio { namespace testing {
   std::string read_wast( const char* fn ) {
      std::ifstream wast_file(fn);
      FC_ASSERT( wast_file.is_open(), "wast file cannot be found" );
      wast_file.seekg(0, std::ios::end);
      std::vector<char> wast;
      int len = wast_file.tellg();
      FC_ASSERT( len >= 0, "wast file length is -1" );
      wast.resize(len+1);
      wast_file.seekg(0, std::ios::beg);
      wast_file.read(wast.data(), wast.size());
      wast[wast.size()-1] = '\0';
      wast_file.close();
      return {wast.data()};
   }

   std::vector<uint8_t> read_wasm( const char* fn ) {
      std::ifstream wasm_file(fn, std::ios::binary);
      FC_ASSERT( wasm_file.is_open(), "wasm file cannot be found" );
      wasm_file.seekg(0, std::ios::end);
      std::vector<uint8_t> wasm;
      int len = wasm_file.tellg();
      FC_ASSERT( len >= 0, "wasm file length is -1" );
      wasm.resize(len);
      wasm_file.seekg(0, std::ios::beg);
      wasm_file.read((char*)wasm.data(), wasm.size());
      wasm_file.close();
      return wasm;
   }

   std::vector<char> read_abi( const char* fn ) {
      std::ifstream abi_file(fn);
      FC_ASSERT( abi_file.is_open(), "abi file cannot be found" );
      abi_file.seekg(0, std::ios::end);
      std::vector<char> abi;
      int len = abi_file.tellg();
      FC_ASSERT( len >= 0, "abi file length is -1" );
      abi.resize(len+1);
      abi_file.seekg(0, std::ios::beg);
      abi_file.read(abi.data(), abi.size());
      abi[abi.size()-1] = '\0';
      abi_file.close();
      return abi;
   }

   namespace {
      std::string read_gzipped_snapshot( const char* fn ) {
         std::ifstream file(fn, std::ios_base::in | std::ios_base::binary);
         bio::filtering_streambuf<bio::input> in;

         in.push(bio::gzip_decompressor());
         in.push(file);

         std::stringstream decompressed;
         bio::copy(in, decompressed);
         return decompressed.str();
      }
   }

   std::string read_binary_snapshot( const char* fn ) {
      return read_gzipped_snapshot(fn);
   }

   fc::variant read_json_snapshot( const char* fn ) {
      return fc::json::from_string( read_gzipped_snapshot(fn) );
   }

   const fc::microseconds base_tester::abi_serializer_max_time{1000*1000}; // 1s for slow test machines

   bool expect_assert_message(const fc::exception& ex, string expected) {
      BOOST_TEST_MESSAGE("LOG : " << "expected: " << expected << ", actual: " << ex.get_log().at(0).get_message());
      return (ex.get_log().at(0).get_message().find(expected) != std::string::npos);
   }

   fc::variant_object filter_fields(const fc::variant_object& filter, const fc::variant_object& value) {
      fc::mutable_variant_object res;
      for( auto& entry : filter ) {
         auto it = value.find(entry.key());
         res( it->key(), it->value() );
      }
      return res;
   }

   void copy_row(const chain::key_value_object& obj, vector<char>& data) {
      data.resize( obj.value.size() );
      memcpy( data.data(), obj.value.data(), obj.value.size() );
   }

   protocol_feature_set make_protocol_feature_set(const subjective_restriction_map& custom_subjective_restrictions) {
      protocol_feature_set pfs;

      map< builtin_protocol_feature_t, std::optional<digest_type> > visited_builtins;

      std::function<digest_type(builtin_protocol_feature_t)> add_builtins =
      [&pfs, &visited_builtins, &add_builtins, &custom_subjective_restrictions]
      ( builtin_protocol_feature_t codename ) -> digest_type {
         auto res = visited_builtins.emplace( codename, std::optional<digest_type>() );
         if( !res.second ) {
            EOS_ASSERT( res.first->second, protocol_feature_exception,
                        "invariant failure: cycle found in builtin protocol feature dependencies"
            );
            return *res.first->second;
         }

         auto f = protocol_feature_set::make_default_builtin_protocol_feature( codename,
         [&add_builtins]( builtin_protocol_feature_t d ) {
            return add_builtins( d );
         } );

         const auto itr = custom_subjective_restrictions.find(codename);
         if( itr != custom_subjective_restrictions.end() ) {
            f.subjective_restrictions = itr->second;
         }

         const auto& pf = pfs.add_feature( f );
         res.first->second = pf.feature_digest;

         return pf.feature_digest;
      };

      for( const auto& p : builtin_protocol_feature_codenames ) {
         add_builtins( p.first );
      }

      return pfs;
   }

   bool base_tester::is_same_chain( base_tester& other ) {
     return control->head_block_id() == other.control->head_block_id();
   }

   void base_tester::init(const setup_policy policy, db_read_mode read_mode,
                          std::optional<uint32_t> genesis_max_inline_action_size,
                          std::optional<uint32_t> config_max_nonprivileged_inline_action_size,
                          std::optional<backing_store_type> config_backing_store) {
      auto def_conf = default_config(tempdir, genesis_max_inline_action_size,
                                     config_max_nonprivileged_inline_action_size, config_backing_store);
      def_conf.first.read_mode = read_mode;
      cfg = def_conf.first;

      open(def_conf.second);
      execute_setup_policy(policy);
   }

   void base_tester::init(controller::config config, const snapshot_reader_ptr& snapshot) {
      cfg = config;
      open(snapshot);
   }

   void base_tester::init(controller::config config, const genesis_state& genesis) {
      cfg = config;
      open(genesis);
   }

   void base_tester::init(controller::config config) {
      cfg = config;
      open(default_genesis().compute_chain_id());
   }

   void base_tester::init(controller::config config, protocol_feature_set&& pfs, const snapshot_reader_ptr& snapshot) {
      cfg = config;
      open(std::move(pfs), snapshot);
   }

   void base_tester::init(controller::config config, protocol_feature_set&& pfs, const genesis_state& genesis) {
      cfg = config;
      open(std::move(pfs), genesis);
   }

   void base_tester::init(controller::config config, protocol_feature_set&& pfs) {
      cfg = config;
      open(std::move(pfs), default_genesis().compute_chain_id());
   }

   void base_tester::execute_setup_policy(const setup_policy policy) {
      const auto& pfm = control->get_protocol_feature_manager();

      auto schedule_preactivate_protocol_feature = [&]() {
         auto preactivate_feature_digest = pfm.get_builtin_digest(builtin_protocol_feature_t::preactivate_feature);
         FC_ASSERT( preactivate_feature_digest, "PREACTIVATE_FEATURE not found" );
         schedule_protocol_features_wo_preactivation( { *preactivate_feature_digest } );
      };

      switch (policy) {
         case setup_policy::old_bios_only: {
            set_before_preactivate_bios_contract();
            break;
         }
         case setup_policy::preactivate_feature_only: {
            schedule_preactivate_protocol_feature();
            produce_block(); // block production is required to activate protocol feature
            break;
         }
         case setup_policy::preactivate_feature_and_new_bios: {
            schedule_preactivate_protocol_feature();
            produce_block();
            set_before_producer_authority_bios_contract();
            break;
         }
         case setup_policy::old_wasm_parser: {
            schedule_preactivate_protocol_feature();
            produce_block();
            set_before_producer_authority_bios_contract();
            preactivate_builtin_protocol_features({
               builtin_protocol_feature_t::only_link_to_existing_permission,
               builtin_protocol_feature_t::replace_deferred,
               builtin_protocol_feature_t::no_duplicate_deferred_id,
               builtin_protocol_feature_t::fix_linkauth_restriction,
               builtin_protocol_feature_t::disallow_empty_producer_schedule,
               builtin_protocol_feature_t::restrict_action_to_self,
               builtin_protocol_feature_t::only_bill_first_authorizer,
               builtin_protocol_feature_t::forward_setcode,
               builtin_protocol_feature_t::get_sender,
               builtin_protocol_feature_t::ram_restrictions,
               builtin_protocol_feature_t::webauthn_key,
               builtin_protocol_feature_t::wtmsig_block_signatures,
               builtin_protocol_feature_t::kv_database
            });
            produce_block();
            set_bios_contract();
            break;
         }
         case setup_policy::full: {
            schedule_preactivate_protocol_feature();
            produce_block();
            set_before_producer_authority_bios_contract();
            preactivate_all_builtin_protocol_features();
            produce_block();
            set_bios_contract();
            break;
         }
         case setup_policy::none:
         default:
            break;
      };
   }

   void base_tester::close() {
      control.reset();
      chain_transactions.clear();
   }

   void base_tester::open( const snapshot_reader_ptr& snapshot ) {
      open( make_protocol_feature_set(), snapshot );
   }

   void base_tester::open( const genesis_state& genesis ) {
      open( make_protocol_feature_set(), genesis );
   }

   void base_tester::open( std::optional<chain_id_type> expected_chain_id ) {
      open( make_protocol_feature_set(), expected_chain_id );
   }

   void base_tester::open( protocol_feature_set&& pfs, std::optional<chain_id_type> expected_chain_id, const std::function<void()>& lambda ) {
      if( !expected_chain_id ) {
         expected_chain_id = controller::extract_chain_id_from_db( cfg.state_dir );
         if( !expected_chain_id ) {
            if( fc::is_regular_file( cfg.blog.log_dir / "blocks.log" ) ) {
               expected_chain_id = block_log::extract_chain_id( cfg.blog.log_dir );
            } else {
               expected_chain_id = genesis_state().compute_chain_id();
            }
         }
      }

      control.reset( new controller(cfg, std::move(pfs), *expected_chain_id) );
      control->add_indices();
      if (lambda) lambda();
      chain_transactions.clear();
      control->accepted_block.connect([this]( const block_state_ptr& block_state ){
        FC_ASSERT( block_state->block );
          for( auto receipt : block_state->block->transactions ) {
              if( std::holds_alternative<packed_transaction>(receipt.trx) ) {
                  auto &pt = std::get<packed_transaction>(receipt.trx);
                  chain_transactions[pt.get_transaction().id()] = std::move(receipt);
              } else {
                  auto& id = std::get<transaction_id_type>(receipt.trx);
                  chain_transactions[id] = std::move(receipt);
              }
          }
      });
   }

   void base_tester::open( protocol_feature_set&& pfs, const snapshot_reader_ptr& snapshot ) {
      const auto& snapshot_chain_id = controller::extract_chain_id( *snapshot );
      snapshot->return_to_header();
      open(std::move(pfs), snapshot_chain_id, [&snapshot,&control=this->control]() {
         control->startup( [](){}, []() { return false; }, snapshot );
      });
   }

   void base_tester::open( protocol_feature_set&& pfs, const genesis_state& genesis ) {
      open(std::move(pfs), genesis.compute_chain_id(), [&genesis,&control=this->control]() {
         control->startup( [](){}, []() { return false; }, genesis );
      });
   }

   void base_tester::open( protocol_feature_set&& pfs, std::optional<chain_id_type> expected_chain_id ) {
      open(std::move(pfs), expected_chain_id, [&control=this->control]() {
         control->startup( [](){}, []() { return false; } );
      });
   }

   void base_tester::push_block(signed_block_ptr b) {
      auto bsf = control->create_block_state_future(b->calculate_id(), b);
      unapplied_transactions.add_aborted( control->abort_block() );
      control->push_block( bsf, [this]( const branch_type& forked_branch ) {
         unapplied_transactions.add_forked( forked_branch );
      }, [this]( const transaction_id_type& id ) {
         return unapplied_transactions.get_trx( id );
      } );

      auto itr = last_produced_block.find(b->producer);
      if (itr == last_produced_block.end() || b->block_num() > block_header::num_from_id(itr->second)) {
         last_produced_block[b->producer] = b->calculate_id();
      }
   }

   signed_block_ptr base_tester::_produce_block( fc::microseconds skip_time, bool skip_pending_trxs ) {
      std::vector<transaction_trace_ptr> traces;
      return _produce_block( skip_time, skip_pending_trxs, false, traces );
   }

   signed_block_ptr base_tester::_produce_block( fc::microseconds skip_time, bool skip_pending_trxs,
                                                 bool no_throw, std::vector<transaction_trace_ptr>& traces ) {
      auto head = control->head_block_state();
      auto head_time = control->head_block_time();
      auto next_time = head_time + skip_time;

      if( !control->is_building_block() || control->pending_block_time() != next_time ) {
         _start_block( next_time );
      }

      if( !skip_pending_trxs ) {
         for( auto itr = unapplied_transactions.begin(); itr != unapplied_transactions.end();  ) {
            auto trace = control->push_transaction( itr->trx_meta, fc::time_point::maximum(), DEFAULT_BILLED_CPU_TIME_US, true, 0 );
            traces.emplace_back( trace );
            if(!no_throw && trace->except) {
               // this always throws an fc::exception, since the original exception is copied into an fc::exception
               trace->except->dynamic_rethrow_exception();
            }
            itr = unapplied_transactions.erase( itr );
         }

         vector<transaction_id_type> scheduled_trxs;
         while ((scheduled_trxs = get_scheduled_transactions()).size() > 0 ) {
            for( const auto& trx : scheduled_trxs ) {
               auto trace = control->push_scheduled_transaction( trx, fc::time_point::maximum(), DEFAULT_BILLED_CPU_TIME_US, true );
               traces.emplace_back( trace );
               if( !no_throw && trace->except ) {
                  // this always throws an fc::exception, since the original exception is copied into an fc::exception
                  trace->except->dynamic_rethrow_exception();
               }
            }
         }
      }

      auto head_block = _finish_block();

      _start_block( next_time + fc::microseconds(config::block_interval_us));
      return head_block;
   }

   void base_tester::_start_block(fc::time_point block_time) {
      auto head_block_number = control->head_block_num();
      auto producer = control->head_block_state()->get_scheduled_producer(block_time);

      auto last_produced_block_num = control->last_irreversible_block_num();
      auto itr = last_produced_block.find(producer.producer_name);
      if (itr != last_produced_block.end()) {
         last_produced_block_num = std::max(control->last_irreversible_block_num(), block_header::num_from_id(itr->second));
      }

      unapplied_transactions.add_aborted( control->abort_block() );

      vector<digest_type> feature_to_be_activated;
      // First add protocol features to be activated WITHOUT preactivation
      feature_to_be_activated.insert(
         feature_to_be_activated.end(),
         protocol_features_to_be_activated_wo_preactivation.begin(),
         protocol_features_to_be_activated_wo_preactivation.end()
      );
      // Then add protocol features to be activated WITH preactivation
      const auto preactivated_protocol_features = control->get_preactivated_protocol_features();
      feature_to_be_activated.insert(
         feature_to_be_activated.end(),
         preactivated_protocol_features.begin(),
         preactivated_protocol_features.end()
      );

      control->start_block( block_time, head_block_number - last_produced_block_num, feature_to_be_activated );

      // Clear the list, if start block finishes successfuly, the protocol features should be assumed to be activated
      protocol_features_to_be_activated_wo_preactivation.clear();
   }

   signed_block_ptr base_tester::_finish_block() {
      FC_ASSERT( control->is_building_block(), "must first start a block before it can be finished" );

      auto producer = control->head_block_state()->get_scheduled_producer( control->pending_block_time() );
      vector<private_key_type> signing_keys;

      auto default_active_key = get_public_key( producer.producer_name, "active");
      producer.for_each_key([&](const public_key_type& key){
         const auto& iter = block_signing_private_keys.find(key);
         if(iter != block_signing_private_keys.end()) {
            signing_keys.push_back(iter->second);
         } else if (key == default_active_key) {
            signing_keys.emplace_back( get_private_key( producer.producer_name, "active") );
         }
      });

      control->finalize_block( [&]( digest_type d ) {
         std::vector<signature_type> result;
         result.reserve(signing_keys.size());
         for (const auto& k: signing_keys)
             result.emplace_back(k.sign(d));

         return result;
      } );

      control->commit_block();
      last_produced_block[control->head_block_state()->header.producer] = control->head_block_state()->id;

      return control->head_block_state()->block;
   }

   signed_block_ptr base_tester::produce_block( std::vector<transaction_trace_ptr>& traces ) {
      return _produce_block( fc::milliseconds(config::block_interval_ms), false, true, traces );
   }

   void base_tester::produce_blocks( uint32_t n, bool empty ) {
      if( empty ) {
         for( uint32_t i = 0; i < n; ++i )
            produce_empty_block();
      } else {
         for( uint32_t i = 0; i < n; ++i )
            produce_block();
      }
   }

   vector<transaction_id_type> base_tester::get_scheduled_transactions() const {
      const auto& idx = control->db().get_index<generated_transaction_multi_index,by_delay>();

      vector<transaction_id_type> result;

      auto itr = idx.begin();
      while( itr != idx.end() && itr->delay_until <= control->pending_block_time() ) {
         result.emplace_back(itr->trx_id);
         ++itr;
      }
      return result;
   }

   void base_tester::produce_blocks_until_end_of_round() {
      uint64_t blocks_per_round;
      while(true) {
         blocks_per_round = control->active_producers().producers.size() * config::producer_repetitions;
         produce_block();
         if (control->head_block_num() % blocks_per_round == (blocks_per_round - 1)) break;
      }
   }

   void base_tester::produce_blocks_for_n_rounds(const uint32_t num_of_rounds) {
      for(uint32_t i = 0; i < num_of_rounds; i++) {
         produce_blocks_until_end_of_round();
      }
   }

   void base_tester::produce_min_num_of_blocks_to_spend_time_wo_inactive_prod(const fc::microseconds target_elapsed_time) {
      fc::microseconds elapsed_time;
      while (elapsed_time < target_elapsed_time) {
         for(uint32_t i = 0; i < control->head_block_state()->active_schedule.producers.size(); i++) {
            const auto time_to_skip = fc::milliseconds(config::producer_repetitions * config::block_interval_ms);
            produce_block(time_to_skip);
            elapsed_time += time_to_skip;
         }
         // if it is more than 24 hours, producer will be marked as inactive
         const auto time_to_skip = fc::seconds(23 * 60 * 60);
         produce_block(time_to_skip);
         elapsed_time += time_to_skip;
      }

   }

  void base_tester::set_transaction_headers( transaction& trx, uint32_t expiration, uint32_t delay_sec ) const {
     trx.expiration = control->head_block_time() + fc::seconds(expiration);
     trx.set_reference_block( control->head_block_id() );

     trx.max_net_usage_words = 0; // No limit
     trx.max_cpu_usage_ms = 0; // No limit
     trx.delay_sec = delay_sec;
  }

   transaction_trace_ptr base_tester::create_account( account_name a, account_name creator, bool multisig, bool include_code ) {
      signed_transaction trx;
      set_transaction_headers(trx);

      authority owner_auth;
      if( multisig ) {
         // multisig between account's owner key and creators active permission
         owner_auth = authority(2, {key_weight{get_public_key( a, "owner" ), 1}}, {permission_level_weight{{creator, config::active_name}, 1}});
      } else {
         owner_auth =  authority( get_public_key( a, "owner" ) );
      }

      authority active_auth( get_public_key( a, "active" ) );

      auto sort_permissions = []( authority& auth ) {
         std::sort( auth.accounts.begin(), auth.accounts.end(),
                    []( const permission_level_weight& lhs, const permission_level_weight& rhs ) {
                        return lhs.permission < rhs.permission;
                    }
                  );
      };

      if( include_code ) {
         FC_ASSERT( owner_auth.threshold <= std::numeric_limits<weight_type>::max(), "threshold is too high" );
         FC_ASSERT( active_auth.threshold <= std::numeric_limits<weight_type>::max(), "threshold is too high" );
         owner_auth.accounts.push_back( permission_level_weight{ {a, config::eosio_code_name},
                                                                 static_cast<weight_type>(owner_auth.threshold) } );
         sort_permissions(owner_auth);
         active_auth.accounts.push_back( permission_level_weight{ {a, config::eosio_code_name},
                                                                  static_cast<weight_type>(active_auth.threshold) } );
         sort_permissions(active_auth);
      }

      trx.actions.emplace_back( vector<permission_level>{{creator,config::active_name}},
                                newaccount{
                                   .creator  = creator,
                                   .name     = a,
                                   .owner    = owner_auth,
                                   .active   = active_auth,
                                });

      set_transaction_headers(trx);
      trx.sign( get_private_key( creator, "active" ), control->get_chain_id()  );
      return push_transaction( trx );
   }

   transaction_trace_ptr base_tester::push_transaction( const packed_transaction& trx,
                                                        fc::time_point deadline,
                                                        uint32_t billed_cpu_time_us
                                                      )
   { try {
      if( !control->is_building_block() )
         _start_block(control->head_block_time() + fc::microseconds(config::block_interval_us));

      auto ptrx = std::make_shared<packed_transaction>(trx);
      auto time_limit = deadline == fc::time_point::maximum() ?
            fc::microseconds::maximum() :
            fc::microseconds( deadline - fc::time_point::now() );
      auto fut = transaction_metadata::start_recover_keys( ptrx, control->get_thread_pool(), control->get_chain_id(), time_limit );
      auto r = control->push_transaction( fut.get(), deadline, billed_cpu_time_us, billed_cpu_time_us > 0, 0 );
      if( r->except_ptr ) std::rethrow_exception( r->except_ptr );
      if( r->except ) throw *r->except;
      return r;
   } FC_RETHROW_EXCEPTIONS( warn, "transaction_header: ${header}", ("header", transaction_header(trx.get_transaction()) )) }

   transaction_trace_ptr base_tester::push_transaction( const signed_transaction& trx,
                                                        fc::time_point deadline,
                                                        uint32_t billed_cpu_time_us,
                                                        bool no_throw
                                                      )
   { try {
      if( !control->is_building_block() )
         _start_block(control->head_block_time() + fc::microseconds(config::block_interval_us));
      auto c = packed_transaction::compression_type::none;

      if( fc::raw::pack_size(trx) > 1000 ) {
         c = packed_transaction::compression_type::zlib;
      }

      auto time_limit = deadline == fc::time_point::maximum() ?
            fc::microseconds::maximum() :
            fc::microseconds( deadline - fc::time_point::now() );
      auto ptrx = std::make_shared<packed_transaction>( signed_transaction(trx), true, c );
      auto fut = transaction_metadata::start_recover_keys( std::move( ptrx ), control->get_thread_pool(), control->get_chain_id(), time_limit );
      auto r = control->push_transaction( fut.get(), deadline, billed_cpu_time_us, billed_cpu_time_us > 0, 0 );
      if (no_throw) return r;
      if( r->except_ptr ) std::rethrow_exception( r->except_ptr );
      if( r->except)  throw *r->except;
      return r;
   } FC_RETHROW_EXCEPTIONS( warn, "transaction_header: ${header}, billed_cpu_time_us: ${billed}",
                            ("header", transaction_header(trx) ) ("billed", billed_cpu_time_us))
   }

   typename base_tester::action_result base_tester::push_action(action&& act, uint64_t authorizer) {
      signed_transaction trx;
      if (authorizer) {
         act.authorization = vector<permission_level>{{account_name(authorizer), config::active_name}};
      }
      trx.actions.emplace_back(std::move(act));
      set_transaction_headers(trx);
      if (authorizer) {
         trx.sign(get_private_key(account_name(authorizer), "active"), control->get_chain_id());
      }
      try {
         push_transaction(trx);
      } catch (const fc::exception& ex) {
         edump((ex.to_detail_string()));
         return error(ex.top_message()); // top_message() is assumed by many tests; otherwise they fail
         //return error(ex.to_detail_string());
      }
      produce_block();
      BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
      return success();
   }

   transaction_trace_ptr base_tester::push_action( const account_name& code,
                                                   const action_name& acttype,
                                                   const account_name& actor,
                                                   const variant_object& data,
                                                   uint32_t expiration,
                                                   uint32_t delay_sec
                                                 )

   {
      vector<permission_level> auths;
      auths.push_back( permission_level{actor, config::active_name} );
      return push_action( code, acttype, auths, data, expiration, delay_sec );
   }

   transaction_trace_ptr base_tester::push_action( const account_name& code,
                                                   const action_name& acttype,
                                                   const vector<account_name>& actors,
                                                   const variant_object& data,
                                                   uint32_t expiration,
                                                   uint32_t delay_sec
                                                 )

   {
      vector<permission_level> auths;
      for (const auto& actor : actors) {
         auths.push_back( permission_level{actor, config::active_name} );
      }
      return push_action( code, acttype, auths, data, expiration, delay_sec );
   }

   transaction_trace_ptr base_tester::push_action( const account_name& code,
                                                   const action_name& acttype,
                                                   const vector<permission_level>& auths,
                                                   const variant_object& data,
                                                   uint32_t expiration,
                                                   uint32_t delay_sec
                                                 )

   { try {
      signed_transaction trx;
      trx.actions.emplace_back( get_action( code, acttype, auths, data ) );
      set_transaction_headers( trx, expiration, delay_sec );
      for (const auto& auth : auths) {
         trx.sign( get_private_key( auth.actor, auth.permission.to_string() ), control->get_chain_id() );
      }

      return push_transaction( trx );
   } FC_CAPTURE_AND_RETHROW( (code)(acttype)(auths)(data)(expiration)(delay_sec) ) }

   action base_tester::get_action( account_name code, action_name acttype, vector<permission_level> auths,
                                   const variant_object& data )const { try {
      const auto& acnt = control->get_account(code);
      auto abi = acnt.get_abi();
      chain::abi_serializer abis(abi, abi_serializer::create_yield_function( abi_serializer_max_time ));

      string action_type_name = abis.get_action_type(acttype);
      FC_ASSERT( action_type_name != string(), "unknown action type ${a}", ("a",acttype) );

      action act;
      act.account = code;
      act.name = acttype;
      act.authorization = auths;
      act.data = abis.variant_to_binary(action_type_name, data, abi_serializer::create_yield_function( abi_serializer_max_time ));
      return act;
   } FC_CAPTURE_AND_RETHROW() }

   transaction_trace_ptr base_tester::push_reqauth( account_name from, const vector<permission_level>& auths, const vector<private_key_type>& keys ) {
      fc::variant pretty_trx = fc::mutable_variant_object()
         ("actions", fc::variants({
            fc::mutable_variant_object()
               ("account", name(config::system_account_name))
               ("name", "reqauth")
               ("authorization", auths)
               ("data", fc::mutable_variant_object()
                  ("from", from)
               )
            })
        );

      signed_transaction trx;
      abi_serializer::from_variant(pretty_trx, trx, get_resolver(), abi_serializer::create_yield_function( abi_serializer_max_time ));
      set_transaction_headers(trx);
      for(auto iter = keys.begin(); iter != keys.end(); iter++)
         trx.sign( *iter, control->get_chain_id() );
      return push_transaction( trx );
   }

    transaction_trace_ptr base_tester::push_reqauth(account_name from, string role, bool multi_sig) {
        if (!multi_sig) {
            return push_reqauth(from, vector<permission_level>{{from, config::owner_name}},
                                        {get_private_key(from, role)});
        } else {
            return push_reqauth(from, vector<permission_level>{{from, config::owner_name}},
                                        {get_private_key(from, role), get_private_key( config::system_account_name, "active" )} );
        }
    }

   transaction_trace_ptr base_tester::push_dummy(account_name from, const string& v, uint32_t billed_cpu_time_us) {
      // use reqauth for a normal action, this could be anything
      fc::variant pretty_trx = fc::mutable_variant_object()
         ("actions", fc::variants({
            fc::mutable_variant_object()
               ("account", name(config::system_account_name))
               ("name", "reqauth")
               ("authorization", fc::variants({
                  fc::mutable_variant_object()
                     ("actor", from)
                     ("permission", name(config::active_name))
               }))
               ("data", fc::mutable_variant_object()
                  ("from", from)
               )
            })
        )
        // lets also push a context free action, the multi chain test will then also include a context free action
        ("context_free_actions", fc::variants({
            fc::mutable_variant_object()
               ("account", name(config::null_account_name))
               ("name", "nonce")
               ("data", fc::raw::pack(v))
            })
         );

      signed_transaction trx;
      abi_serializer::from_variant(pretty_trx, trx, get_resolver(), abi_serializer::create_yield_function( abi_serializer_max_time ));
      set_transaction_headers(trx);

      trx.sign( get_private_key( from, "active" ), control->get_chain_id() );
      return push_transaction( trx, fc::time_point::maximum(), billed_cpu_time_us );
   }

   transaction_trace_ptr base_tester::transfer( account_name from, account_name to, string amount, string memo, account_name currency ) {
      return transfer( from, to, asset::from_string(amount), memo, currency );
   }

   transaction_trace_ptr base_tester::transfer( account_name from, account_name to, asset amount, string memo, account_name currency ) {
      fc::variant pretty_trx = fc::mutable_variant_object()
         ("actions", fc::variants({
            fc::mutable_variant_object()
               ("account", currency)
               ("name", "transfer")
               ("authorization", fc::variants({
                  fc::mutable_variant_object()
                     ("actor", from)
                     ("permission", name(config::active_name))
               }))
               ("data", fc::mutable_variant_object()
                  ("from", from)
                  ("to", to)
                  ("quantity", amount)
                  ("memo", memo)
               )
            })
         );

      signed_transaction trx;
      abi_serializer::from_variant(pretty_trx, trx, get_resolver(), abi_serializer::create_yield_function( abi_serializer_max_time ));
      set_transaction_headers(trx);

      trx.sign( get_private_key( from, name(config::active_name).to_string() ), control->get_chain_id()  );
      return push_transaction( trx );
   }

   transaction_trace_ptr base_tester::issue( account_name to, string amount, account_name currency, string memo ) {
      fc::variant pretty_trx = fc::mutable_variant_object()
         ("actions", fc::variants({
            fc::mutable_variant_object()
               ("account", currency)
               ("name", "issue")
               ("authorization", fc::variants({
                  fc::mutable_variant_object()
                     ("actor", currency )
                     ("permission", name(config::active_name))
               }))
               ("data", fc::mutable_variant_object()
                  ("to", to)
                  ("quantity", amount)
                  ("memo", memo)
               )
            })
         );

      signed_transaction trx;
      abi_serializer::from_variant(pretty_trx, trx, get_resolver(), abi_serializer::create_yield_function( abi_serializer_max_time ));
      set_transaction_headers(trx);

      trx.sign( get_private_key( currency, name(config::active_name).to_string() ), control->get_chain_id()  );
      return push_transaction( trx );
   }

   void base_tester::link_authority( account_name account, account_name code, permission_name req, action_name type ) {
      signed_transaction trx;

      trx.actions.emplace_back( vector<permission_level>{{account, config::active_name}},
                                linkauth(account, code, type, req));
      set_transaction_headers(trx);
      trx.sign( get_private_key( account, "active" ), control->get_chain_id()  );

      push_transaction( trx );
   }

   void base_tester::unlink_authority( account_name account, account_name code, action_name type ) {
      signed_transaction trx;

      trx.actions.emplace_back( vector<permission_level>{{account, config::active_name}},
                                unlinkauth(account, code, type ));
      set_transaction_headers(trx);
      trx.sign( get_private_key( account, "active" ), control->get_chain_id()  );

      push_transaction( trx );
   }

   void base_tester::set_authority( account_name account,
                               permission_name perm,
                               authority auth,
                               permission_name parent,
                               const vector<permission_level>& auths,
                               const vector<private_key_type>& keys) { try {
      signed_transaction trx;

      trx.actions.emplace_back( auths,
                                updateauth{
                                   .account    = account,
                                   .permission = perm,
                                   .parent     = parent,
                                   .auth       = move(auth),
                                });

         set_transaction_headers(trx);
      for (const auto& key: keys) {
         trx.sign( key, control->get_chain_id()  );
      }

      push_transaction( trx );
   } FC_CAPTURE_AND_RETHROW( (account)(perm)(auth)(parent) ) }

   void base_tester::set_authority( account_name account,
                                    permission_name perm,
                                    authority auth,
                                    permission_name parent) {
      set_authority(account, perm, auth, parent, { { account, config::owner_name } }, { get_private_key( account, "owner" ) });
   }

   void base_tester::delete_authority( account_name account,
                                    permission_name perm,
                                    const vector<permission_level>& auths,
                                    const vector<private_key_type>& keys ) { try {
         signed_transaction trx;
         trx.actions.emplace_back( auths,
                                   deleteauth(account, perm) );

         set_transaction_headers(trx);
         for (const auto& key: keys) {
            trx.sign( key, control->get_chain_id()  );
         }

         push_transaction( trx );
      } FC_CAPTURE_AND_RETHROW( (account)(perm) ) }

   void base_tester::delete_authority( account_name account,
                                       permission_name perm ) {
      delete_authority(account, perm, { permission_level{ account, config::owner_name } }, { get_private_key( account, "owner" ) });
   }

   void base_tester::set_code( account_name account, const char* wast, const private_key_type* signer  ) try {
      set_code(account, wast_to_wasm(wast), signer);
   } FC_CAPTURE_AND_RETHROW( (account) )

   void base_tester::set_code( account_name account, const vector<uint8_t> wasm, const private_key_type* signer ) try {
      signed_transaction trx;
      trx.actions.emplace_back( vector<permission_level>{{account,config::active_name}},
                                setcode{
                                   .account    = account,
                                   .vmtype     = 0,
                                   .vmversion  = 0,
                                   .code       = bytes(wasm.begin(), wasm.end())
                                });

      set_transaction_headers(trx);
      if( signer ) {
         trx.sign( *signer, control->get_chain_id()  );
      } else {
         trx.sign( get_private_key( account, "active" ), control->get_chain_id()  );
      }
      push_transaction( trx );
   } FC_CAPTURE_AND_RETHROW( (account) )

   void base_tester::set_abi( account_name account, const char* abi_json, const private_key_type* signer ) {
      auto abi = fc::json::from_string(abi_json).template as<abi_def>();
      signed_transaction trx;
      trx.actions.emplace_back( vector<permission_level>{{account,config::active_name}},
                                setabi{
                                   .account    = account,
                                   .abi        = fc::raw::pack(abi)
                                });

      set_transaction_headers(trx);
      if( signer ) {
         trx.sign( *signer, control->get_chain_id()  );
      } else {
         trx.sign( get_private_key( account, "active" ), control->get_chain_id()  );
      }
      push_transaction( trx );
   }

   bool base_tester::chain_has_transaction( const transaction_id_type& txid ) const {
      return chain_transactions.count(txid) != 0;
   }

   const transaction_receipt& base_tester::get_transaction_receipt( const transaction_id_type& txid ) const {
      return chain_transactions.at(txid);
   }

   /**
    *  Reads balance as stored by generic_currency contract
    */

   asset base_tester::get_currency_balance( const account_name& code,
                                       const symbol&       asset_symbol,
                                       const account_name& account ) const {
      const auto& db  = control->db();
      const auto* tbl = db.template find<table_id_object, by_code_scope_table>(boost::make_tuple(code, account, "accounts"_n));
      share_type result = 0;

      // the balance is implied to be 0 if either the table or row does not exist
      if (tbl) {
         const auto *obj = db.template find<key_value_object, by_scope_primary>(boost::make_tuple(tbl->id, asset_symbol.to_symbol_code().value));
         if (obj) {
            //balance is the first field in the serialization
            fc::datastream<const char *> ds(obj->value.data(), obj->value.size());
            fc::raw::unpack(ds, result);
         }
      }
      return asset(result, asset_symbol);
   }

   vector<char> base_tester::get_row_by_account( name code, name scope, name table, const account_name& act ) const {
      vector<char> data;
      const auto& db = control->db();
      const auto* t_id = db.find<chain::table_id_object, chain::by_code_scope_table>( boost::make_tuple( code, scope, table ) );
      if ( !t_id ) {
         return data;
      }
      //FC_ASSERT( t_id != 0, "object not found" );

      const auto& idx = db.get_index<chain::key_value_index, chain::by_scope_primary>();

      auto itr = idx.lower_bound( boost::make_tuple( t_id->id, act.to_uint64_t() ) );
      if ( itr == idx.end() || itr->t_id != t_id->id || act.to_uint64_t() != itr->primary_key ) {
         return data;
      }

      data.resize( itr->value.size() );
      memcpy( data.data(), itr->value.data(), data.size() );
      return data;
   }

   vector<uint8_t> base_tester::to_uint8_vector(const string& s) {
      vector<uint8_t> v(s.size());
      copy(s.begin(), s.end(), v.begin());
      return v;
   };

   vector<uint8_t> base_tester::to_uint8_vector(uint64_t x) {
      vector<uint8_t> v(sizeof(x));
      *reinterpret_cast<uint64_t*>(v.data()) = x;
      return v;
   };

   uint64_t base_tester::to_uint64(fc::variant x) {
      vector<uint8_t> blob;
      fc::from_variant<uint8_t>(x, blob);
      FC_ASSERT(8 == blob.size());
      return *reinterpret_cast<uint64_t*>(blob.data());
   }

   string base_tester::to_string(fc::variant x) {
      vector<uint8_t> v;
      fc::from_variant<uint8_t>(x, v);
      string s(v.size(), 0);
      copy(v.begin(), v.end(), s.begin());
      return s;
   }

   void base_tester::sync_with(base_tester& other) {
      // Already in sync?
      if (control->head_block_id() == other.control->head_block_id())
         return;
      // If other has a longer chain than we do, sync it to us first
      if (control->head_block_num() < other.control->head_block_num())
         return other.sync_with(*this);

      auto sync_dbs = [](base_tester& a, base_tester& b) {
         for( uint32_t i = 1; i <= a.control->head_block_num(); ++i ) {

            auto block = a.control->fetch_block_by_number(i);
            if( block ) { //&& !b.control->is_known_block(block->id()) ) {
               auto bsf = b.control->create_block_state_future( block->calculate_id(), block );
               b.control->abort_block();
               b.control->push_block(bsf, forked_branch_callback{}, trx_meta_cache_lookup{}); //, eosio::chain::validation_steps::created_block);
            }
         }
      };

      sync_dbs(*this, other);
      sync_dbs(other, *this);
   }

   void base_tester::set_before_preactivate_bios_contract() {
      set_code(config::system_account_name, contracts::before_preactivate_eosio_bios_wasm());
      set_abi(config::system_account_name, contracts::before_preactivate_eosio_bios_abi().data());
   }

   void base_tester::set_before_producer_authority_bios_contract() {
      set_code(config::system_account_name, contracts::before_producer_authority_eosio_bios_wasm());
      set_abi(config::system_account_name, contracts::before_producer_authority_eosio_bios_abi().data());
   }

   void base_tester::set_bios_contract() {
      set_code(config::system_account_name, contracts::eosio_bios_wasm());
      set_abi(config::system_account_name, contracts::eosio_bios_abi().data());
   }

   vector<producer_authority> base_tester::get_producer_authorities( const vector<account_name>& producer_names )const {
       // Create producer schedule
       vector<producer_authority> schedule;
       for (auto& producer_name: producer_names) {
          schedule.emplace_back(producer_authority{ producer_name, block_signing_authority_v0{1, {{ get_public_key( producer_name, "active" ), 1}} } });
       }
       return schedule;
   }

   transaction_trace_ptr base_tester::set_producers(const vector<account_name>& producer_names) {
      auto schedule = get_producer_authorities( producer_names );

      return set_producer_schedule(schedule);
   }

   transaction_trace_ptr base_tester::set_producer_schedule(const vector<producer_authority>& schedule ) {
      // FC reflection does not create variants that are compatible with ABI 1.1 so we manually translate.
      fc::variants schedule_variant;
      schedule_variant.reserve(schedule.size());
      for( const auto& e: schedule ) {
         schedule_variant.emplace_back(e.get_abi_variant());
      }

      return push_action( config::system_account_name, "setprods"_n, config::system_account_name,
                          fc::mutable_variant_object()("schedule", schedule_variant));

   }

   transaction_trace_ptr base_tester::set_producers_legacy(const vector<account_name>& producer_names) {
      auto schedule = get_producer_authorities( producer_names );
      // down-rank to old version

      vector<legacy::producer_key> legacy_keys;
      legacy_keys.reserve(schedule.size());
      for (const auto &p : schedule) {
         std::visit([&legacy_keys, &p](const auto& auth){
            legacy_keys.emplace_back(legacy::producer_key{p.producer_name, auth.keys.front().key});
         }, p.authority);
      }

      return push_action( config::system_account_name, "setprods"_n, config::system_account_name,
                          fc::mutable_variant_object()("schedule", legacy_keys));

   }

   const table_id_object* base_tester::find_table( name code, name scope, name table ) {
      auto tid = control->db().find<table_id_object, by_code_scope_table>(boost::make_tuple(code, scope, table));
      return tid;
   }

   void base_tester::schedule_protocol_features_wo_preactivation(const vector<digest_type> feature_digests) {
      protocol_features_to_be_activated_wo_preactivation.insert(
         protocol_features_to_be_activated_wo_preactivation.end(),
         feature_digests.begin(),
         feature_digests.end()
      );
   }

   void base_tester::preactivate_protocol_features(const vector<digest_type> feature_digests) {
      for( const auto& feature_digest: feature_digests ) {
         push_action( config::system_account_name, "activate"_n, config::system_account_name,
                      fc::mutable_variant_object()("feature_digest", feature_digest) );
      }
   }

   void base_tester::preactivate_builtin_protocol_features(const std::vector<builtin_protocol_feature_t>& builtin_features) {
      const auto& pfs = control->get_protocol_feature_manager().get_protocol_feature_set();

      // This behavior is disabled by configurable_wasm_limits
      std::vector<digest_type> features;
      for(builtin_protocol_feature_t feature : builtin_features ) {
         if( auto digest = pfs.get_builtin_digest( feature ) ) {
            features.push_back( *digest );
         }
      }
      preactivate_protocol_features(features);
   }

   void base_tester::preactivate_all_builtin_protocol_features() {
      const auto& pfm = control->get_protocol_feature_manager();
      const auto& pfs = pfm.get_protocol_feature_set();
      const auto current_block_num  =  control->head_block_num() + (control->is_building_block() ? 1 : 0);
      const auto current_block_time = ( control->is_building_block() ? control->pending_block_time()
                                        : control->head_block_time() + fc::milliseconds(config::block_interval_ms) );

      set<digest_type>    preactivation_set;
      vector<digest_type> preactivations;

      std::function<void(const digest_type&)> add_digests =
      [&pfm, &pfs, current_block_num, current_block_time, &preactivation_set, &preactivations, &add_digests]
      ( const digest_type& feature_digest ) {
         const auto& pf = pfs.get_protocol_feature( feature_digest );
         FC_ASSERT( pf.builtin_feature, "called add_digests on a non-builtin protocol feature" );
         if( !pf.enabled || pf.earliest_allowed_activation_time > current_block_time
             || pfm.is_builtin_activated( *pf.builtin_feature, current_block_num ) ) return;

         auto res = preactivation_set.emplace( feature_digest );
         if( !res.second ) return;

         for( const auto& dependency : pf.dependencies ) {
            add_digests( dependency );
         }

         preactivations.emplace_back( feature_digest );
      };

      for( const auto& f : builtin_protocol_feature_codenames ) {
         auto digest = pfs.get_builtin_digest( f.first );
         if( !digest ) continue;
         add_digests( *digest );
      }

      preactivate_protocol_features( preactivations );
   }

   tester::tester(const std::function<void(controller&)>& control_setup, setup_policy policy, db_read_mode read_mode) {
      auto def_conf            = default_config(tempdir);
      def_conf.first.read_mode = read_mode;
      cfg                      = def_conf.first;

      base_tester::open(make_protocol_feature_set(), def_conf.second.compute_chain_id(),
                        [&genesis = def_conf.second, &control = this->control, &control_setup]() {
                           control_setup(*control);
                           control->startup([]() {}, []() { return false; }, genesis);
                        });

      execute_setup_policy(policy);
   }

   validating_tester::validating_tester(const flat_set<account_name>& trusted_producers,
                                        std::optional<backing_store_type> config_backing_store) {
      auto def_conf = default_config(tempdir, std::optional<uint32_t>{}, std::optional<uint32_t>{}, config_backing_store);
      init_with_trusted_producers(trusted_producers, def_conf, config_backing_store);
   }

   void validating_tester::init_with_trusted_producers(const flat_set<account_name>& trusted_producers,
                                                       std::pair<controller::config, genesis_state> config_state,
                                                       std::optional<backing_store_type> config_backing_store) {
      vcfg = config_state.first;
      if (config_backing_store) {
         // can only have one instance of RocksDB running in the test process
         vcfg.backing_store = alternate_type(*config_backing_store);
      }
      config_validator(vcfg);
      vcfg.trusted_producers = trusted_producers;

      validating_node = create_validating_node(vcfg, config_state.second, true);

      init(config_state.first, config_state.second);
      execute_setup_policy(setup_policy::full);
   }

   validating_tester::validating_tester(const fc::temp_directory& tempdir, bool use_genesis,
                     std::optional<backing_store_type> config_backing_store) {
      auto def_conf = default_config(tempdir, std::optional<uint32_t>{}, std::optional<uint32_t>{}, config_backing_store);
      vcfg = def_conf.first;
      if (config_backing_store) {
         // can only have one instance of RocksDB running in the test process
         vcfg.backing_store = alternate_type(*config_backing_store);
      }
      config_validator(vcfg);
      validating_node = create_validating_node(vcfg, def_conf.second, use_genesis);

      if (use_genesis) {
         init(def_conf.first, def_conf.second);
      }
      else {
         init(def_conf.first);
      }
   }

   backing_store_type validating_tester::alternate_type(backing_store_type type) {
      return type == backing_store_type::CHAINBASE ? backing_store_type::ROCKSDB : backing_store_type::CHAINBASE;
   }

   bool fc_exception_code_is::operator()( const fc::exception& ex ) {
      bool match = (ex.code() == expected);
      if( !match ) {
         auto message = ex.get_log().at( 0 ).get_message();
         BOOST_TEST_MESSAGE( "LOG: expected code: " << expected << ", actual code: " << ex.code() << ", message: " << message );
      }
      return match;
   }

   bool fc_exception_message_is::operator()( const fc::exception& ex ) {
      auto message = ex.get_log().at( 0 ).get_message();
      bool match = (message == expected);
      if( !match ) {
         BOOST_TEST_MESSAGE( "LOG: expected: " << expected << ", actual: " << message );
      }
      return match;
   }

   bool fc_exception_message_starts_with::operator()( const fc::exception& ex ) {
      auto message = ex.get_log().at( 0 ).get_message();
      bool match = boost::algorithm::starts_with( message, expected );
      if( !match ) {
         BOOST_TEST_MESSAGE( "LOG: expected: " << expected << ", actual: " << message );
      }
      return match;
   }

   bool fc_assert_exception_message_is::operator()( const fc::assert_exception& ex ) {
      auto message = ex.get_log().at( 0 ).get_message();
      bool match = false;
      auto pos = message.find( ": " );
      if( pos != std::string::npos ) {
         message = message.substr( pos + 2 );
         match = (message == expected);
      }
      if( !match ) {
         BOOST_TEST_MESSAGE( "LOG: expected: " << expected << ", actual: " << message );
      }
      return match;
   }

   bool fc_assert_exception_message_starts_with::operator()( const fc::assert_exception& ex ) {
      auto message = ex.get_log().at( 0 ).get_message();
      bool match = false;
      auto pos = message.find( ": " );
      if( pos != std::string::npos ) {
         message = message.substr( pos + 2 );
         match = boost::algorithm::starts_with( message, expected );
      }
      if( !match ) {
         BOOST_TEST_MESSAGE( "LOG: expected: " << expected << ", actual: " << message );
      }
      return match;
   }

   bool eosio_assert_message_is::operator()( const eosio_assert_message_exception& ex ) {
      auto message = ex.get_log().at( 0 ).get_message();
      bool match = (message == expected);
      if( !match ) {
         BOOST_TEST_MESSAGE( "LOG: expected: " << expected << ", actual: " << message );
      }
      return match;
   }

   bool eosio_assert_message_starts_with::operator()( const eosio_assert_message_exception& ex ) {
      auto message = ex.get_log().at( 0 ).get_message();
      bool match = boost::algorithm::starts_with( message, expected );
      if( !match ) {
         BOOST_TEST_MESSAGE( "LOG: expected: " << expected << ", actual: " << message );
      }
      return match;
   }

   bool eosio_assert_code_is::operator()( const eosio_assert_code_exception& ex ) {
      auto message = ex.get_log().at( 0 ).get_message();
      bool match = (message == expected);
      if( !match ) {
         BOOST_TEST_MESSAGE( "LOG: expected: " << expected << ", actual: " << message );
      }
      return match;
   }

   const std::string mock::webauthn_private_key::_origin = "mock.webauthn.invalid";
   const sha256 mock::webauthn_private_key::_origin_hash = fc::sha256::hash(mock::webauthn_private_key::_origin);
} }  /// eosio::testing

std::ostream& operator<<( std::ostream& osm, const fc::variant& v ) {
   //fc::json::to_stream( osm, v );
   osm << fc::json::to_pretty_string( v );
   return osm;
}

std::ostream& operator<<( std::ostream& osm, const fc::variant_object& v ) {
   osm << fc::variant(v);
   return osm;
}

std::ostream& operator<<( std::ostream& osm, const fc::variant_object::entry& e ) {
   osm << "{ " << e.key() << ": " << e.value() << " }";
   return osm;
}

ext: cpp

max_stars_repo_name: forfreeday/eos

max_issues_repo_name: forfreeday/eos

max_forks_repo_name: forfreeday/eos


text:
#include <gtest/gtest.h>
#include <common/network/NetworkModule.h>
#include <common/network/boost/BoostNetworkConnectionRepository.h>
#include "FakeUUIDFactory.h"
#include "FakeNetworkInterface.h"
#include "../command/FakeCommandsMap.h"
#include <boost/range/algorithm/copy.hpp>
#include <boost/range/adaptors.hpp>

class NetworkModuleTest : public ::testing::Test {
protected:
    int GAME_CLIENT_PORT = 1234;
    int AUTH_CLIENT_PORT = 5678;

    std::vector<int> LISTEN_PORTS = { GAME_CLIENT_PORT, AUTH_CLIENT_PORT };

    Endpoint GAME_SERVER_ENDPOINT = Endpoint("abc", 2345);
    Endpoint GAME_ROUTER_ENDPOINT = Endpoint("def", 6789);

    std::vector<Endpoint> CONNECT_ENDPOINTS = { GAME_SERVER_ENDPOINT, GAME_ROUTER_ENDPOINT };

    Settings EXPECTED_SETTINGS = Settings(
            { { NetworkConnectionType::GAME_CLIENT, GAME_CLIENT_PORT }, { NetworkConnectionType::AUTH_CLIENT, AUTH_CLIENT_PORT } },
            { { NetworkConnectionType::GAME_SERVER, GAME_SERVER_ENDPOINT }, { NetworkConnectionType::GAME_ROUTER, GAME_ROUTER_ENDPOINT } }
    );

    Bytes EXPECTED_BYTES = { 123, 210 };

    NetworkModule networkModule;
    FakeNetworkInterface networkInterface;

    FakeUUIDFactory uuidFactory;
    NetworkConnectionIdFactory connectionIdFactory;
    BoostNetworkConnectionRepository connections;

    FakeNetworkConnection connection;

    class : public Factory<NetworkConnectionEntry, NetworkConnectionId, NetworkConnection&, NetworkConnectionType> {
    public:
        NetworkConnectionEntry create(NetworkConnectionId id, NetworkConnection& connection, NetworkConnectionType type) override {
            ReceivedBytesQueue receivedBytesQueue;
            FakeCommandAdapter adapter;
            FakeCommandsMap commandsMap = FakeCommandsMap(adapter);
            CommandRouter<Bytes&> router = CommandRouter<Bytes&>(commandsMap);
            return NetworkConnectionEntry(id, connection, type, NetworkConnectionController(connection, router));
        }
    } connectionEntryFactory;

    NetworkModuleTest():    connectionIdFactory(uuidFactory),
                            networkModule(EXPECTED_SETTINGS, networkInterface, connectionIdFactory, connectionEntryFactory, connections) {
        networkModule.launch();
    }
};

TEST_F(NetworkModuleTest, ShouldListenOnSettingsPorts) {
    std::vector<int> listenPorts;
    boost::copy(networkInterface.listenPorts | boost::adaptors::map_keys, std::back_inserter(listenPorts));

    ASSERT_EQ(LISTEN_PORTS, listenPorts);
}

TEST_F(NetworkModuleTest, ShouldConnectToSettingsEndpoints) {
    std::vector<Endpoint> connectEndpoints;
    boost::copy(networkInterface.connectEndpoints | boost::adaptors::map_keys, std::back_inserter(connectEndpoints));

    ASSERT_EQ(CONNECT_ENDPOINTS, connectEndpoints);
}

TEST_F(NetworkModuleTest, ShouldStoreConnections) {
    networkInterface.simulateNewConnectionFromConnect(GAME_SERVER_ENDPOINT, connection);

    NetworkConnectionId id = NetworkConnectionId("1");
    NetworkConnectionEntry& entry = connections.getById(id);

    ASSERT_EQ(NetworkConnectionType::GAME_SERVER, entry.type);
    ASSERT_EQ(&connection, &entry.connection);
}

TEST_F(NetworkModuleTest, ShouldReadConnections) {
    networkInterface.simulateNewConnectionFromConnect(GAME_SERVER_ENDPOINT, connection);

    ASSERT_TRUE(connection.startedReading);
}

max_stars_repo_name: Toinouze/Arthos

max_issues_repo_name: Toinouze/Arthos

max_forks_repo_name: Toinouze/Arthos


text:
//---------------------------------------------------------------------------//
// Copyright (c) 2018-2020 Mikhail Komarov <nemo@nil.foundation>
//
// 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 CRYPTO3_BASIC_FUNCTIONS_HPP
#define CRYPTO3_BASIC_FUNCTIONS_HPP

#include <boost/integer.hpp>
#include <boost/static_assert.hpp>

#include <boost/crypto3/detail/make_uint_t.hpp>

namespace boost {
    namespace crypto3 {
        namespace detail {
            template<std::size_t WordBits>
            struct basic_functions {
                constexpr static const std::size_t byte_bits = CHAR_BIT;
                typedef typename boost::uint_t<byte_bits>::exact byte_type;

                constexpr static const std::size_t word_bits = WordBits;
                typedef typename boost::uint_t<word_bits>::exact word_type;

                static inline word_type shr(word_type x, std::size_t n) {
                    return x >> n;
                }

                template<std::size_t n>
                static inline word_type shr(word_type x) {
                    BOOST_STATIC_ASSERT(n < word_bits);
                    return x >> n;
                }

                static inline word_type shl(word_type x, std::size_t n) {
                    return x << n;
                }

                template<std::size_t n>
                static inline word_type shl(word_type x) {
                    BOOST_STATIC_ASSERT(n < word_bits);
                    return x << n;
                }

                static inline word_type rotr(word_type x, std::size_t n) {
                    return shr(x, n) | shl(x, word_bits - n);
                }

                template<std::size_t n>
                static inline word_type rotr(word_type x) {
                    return shr<n>(x) | shl<word_bits - n>(x);
                }

                static inline word_type rotl(word_type x, std::size_t n) {
                    return shl(x, n) | shr(x, word_bits - n);
                }

                template<std::size_t n>
                static inline word_type rotl(word_type x) {
                    return shl<n>(x) | shr<word_bits - n>(x);
                }
            };

            template<>
            struct basic_functions<32> {
                constexpr static const std::size_t byte_bits = CHAR_BIT;
                typedef typename boost::uint_t<byte_bits>::exact byte_type;

                constexpr static const std::size_t word_bits = 32;
                typedef typename boost::uint_t<word_bits>::exact word_type;

                static inline word_type shr(word_type x, std::size_t n) {
                    return x >> n;
                }

                template<std::size_t n>
                static inline word_type shr(word_type x) {
                    BOOST_STATIC_ASSERT(n < word_bits);
                    return x >> n;
                }

                static inline word_type shl(word_type x, std::size_t n) {
                    return x << n;
                }

                template<std::size_t n>
                static inline word_type shl(word_type x) {
                    BOOST_STATIC_ASSERT(n < word_bits);
                    return x << n;
                }

                static inline word_type rotr(word_type x, std::size_t n) {
#if defined(BOOST_ARCH_X86)
                    asm("rorl %1,%0" : "+r"(x) : "c"(static_cast<uint8_t>(n)));
                    return x;
#else
                    return shr(x, n) | shl(x, word_bits - n);
#endif
                }

                template<std::size_t n>
                static inline word_type rotr(word_type x) {
                    return shr<n>(x) | shl<word_bits - n>(x);
                }

                static inline word_type rotl(word_type x, std::size_t n) {
#if defined(BOOST_ARCH_X86)
                    asm("roll %1,%0" : "+r"(x) : "c"(static_cast<uint8_t>(n)));
                    return x;
#else
                    return shl(x, n) | shr(x, word_bits - n);
#endif
                }

                template<std::size_t n>
                static inline word_type rotl(word_type x) {
                    return shl<n>(x) | shr<word_bits - n>(x);
                }
            };
        }    // namespace detail
    }        // namespace crypto3
}    // namespace boost

#endif    // CRYPTO3_BASIC_FUNCTIONS_HPP

max_stars_repo_name: NilFoundation/boost-crypto

max_issues_repo_name: NilFoundation/boost-crypto

max_forks_repo_name: NilFoundation/boost-crypto