未验证 提交 05bac683 编写于 作者: K Kevin Heifner 提交者: GitHub

Merge pull request #1650 from EOSIO/DAWN-379

DAWN 379 - Restore block_tests
......@@ -3,6 +3,7 @@ file(GLOB HEADERS "include/eosio/testing/*.hpp")
## SORT .cpp by most likely to change / break compile
add_library( eosio_testing
tester.cpp
tester_network.cpp
${HEADERS}
)
......
......@@ -18,15 +18,17 @@ namespace eosio { namespace testing {
typedef string action_result;
base_tester(chain_controller::runtime_limits limits = chain_controller::runtime_limits());
explicit base_tester(chain_controller::controller_config config);
void close();
void open();
signed_block produce_block( fc::microseconds skip_time = fc::milliseconds(config::block_interval_ms) );
signed_block produce_block( fc::microseconds skip_time = fc::milliseconds(config::block_interval_ms), uint32_t skip_flag = skip_missed_block_penalty );
void produce_blocks( uint32_t n = 1 );
void produce_blocks_until_end_of_round();
transaction_trace push_transaction( packed_transaction& trx );
transaction_trace push_transaction( signed_transaction& trx );
transaction_trace push_transaction( packed_transaction& trx, uint32_t skip_flag = skip_nothing );
transaction_trace push_transaction( signed_transaction& trx, uint32_t skip_flag = skip_nothing );
action_result push_action(action&& cert_act, uint64_t authorizer);
transaction_trace push_action( const account_name& code, const action_name& act, const account_name& signer, const variant_object &data );
......@@ -112,6 +114,7 @@ namespace eosio { namespace testing {
};
}
void sync_with(base_tester& other);
private:
fc::temp_directory tempdir;
......@@ -123,8 +126,10 @@ namespace eosio { namespace testing {
class tester : public base_tester {
public:
tester(chain_controller::runtime_limits limits = chain_controller::runtime_limits());
tester(chain_controller::controller_config config);
void push_genesis_block();
void set_producers(const vector<account_name>& producer_names);
};
/**
......
#pragma once
#include "tester.hpp"
#include <boost/signals2/signal.hpp>
#include <boost/signals2/shared_connection_block.hpp>
namespace eosio { namespace testing {
using namespace boost::signals2;
/**
* @brief The tester_network class provides a simplistic virtual P2P network connecting testing_blockchains together.
*
* A tester may be connected to zero or more tester_networks at any given time. When a new
* tester joins the network, it will be synced with all other blockchains already in the network (blocks
* known only to the new chain will be pushed to the prior network members and vice versa, ignoring blocks not on the
* main fork). After this, whenever any blockchain in the network gets a new block, that block will be pushed to all
* other blockchains in the network as well.
*/
class tester_network {
public:
/**
* @brief Add a new blockchain to the network
* @param new_blockchain The blockchain to add
*/
void connect_blockchain(tester &new_blockchain);
/**
* @brief Remove a blockchain from the network
* @param leaving_blockchain The blockchain to remove
*/
void disconnect_blockchain(tester &leaving_blockchain);
/**
* @brief Disconnect all blockchains from the network
*/
void disconnect_all();
/**
* @brief Send a block to all blockchains in this network
* @param block The block to send
*/
void propagate_block(const signed_block &block, const tester &skip_db);
protected:
std::map<tester *, scoped_connection> blockchains;
};
} } /// eosio::testing
\ No newline at end of file
......@@ -30,6 +30,11 @@ namespace eosio { namespace testing {
open();
}
base_tester::base_tester(chain_controller::controller_config config) {
cfg = config;
open();
}
public_key_type base_tester::get_public_key( name keyname, string role ) const {
return get_private_key( keyname, role ).get_public_key();
}
......@@ -59,14 +64,14 @@ namespace eosio { namespace testing {
});
}
signed_block base_tester::produce_block( fc::microseconds skip_time ) {
signed_block base_tester::produce_block( fc::microseconds skip_time, uint32_t skip_flag) {
auto head_time = control->head_block_time();
auto next_time = head_time + skip_time;
uint32_t slot = control->get_slot_at_time( next_time );
auto sch_pro = control->get_scheduled_producer(slot);
auto priv_key = get_private_key( sch_pro, "active" );
return control->generate_block( next_time, sch_pro, priv_key, skip_missed_block_penalty );
return control->generate_block( next_time, sch_pro, priv_key, skip_flag );
}
void base_tester::produce_blocks( uint32_t n ) {
......@@ -74,6 +79,15 @@ namespace eosio { namespace testing {
produce_block();
}
void base_tester::produce_blocks_until_end_of_round() {
uint64_t blocks_per_round;
while(true) {
blocks_per_round = control->get_global_properties().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::set_tapos( signed_transaction& trx ) const {
trx.set_reference_block( control->head_block_id() );
}
......@@ -104,13 +118,13 @@ namespace eosio { namespace testing {
push_transaction( trx );
}
transaction_trace base_tester::push_transaction( packed_transaction& trx ) {
return control->push_transaction( trx );
transaction_trace base_tester::push_transaction( packed_transaction& trx, uint32_t skip_flag ) {
return control->push_transaction( trx, skip_flag );
}
transaction_trace base_tester::push_transaction( signed_transaction& trx ) {
transaction_trace base_tester::push_transaction( signed_transaction& trx, uint32_t skip_flag ) {
auto ptrx = packed_transaction(trx);
return push_transaction( ptrx );
return push_transaction( ptrx, skip_flag );
}
base_tester::action_result base_tester::push_action(action&& cert_act, uint64_t authorizer) {
......@@ -421,14 +435,58 @@ namespace eosio { namespace testing {
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 (int 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())) {
b.control->push_block(*block, eosio::chain::validation_steps::created_block);
}
}
};
sync_dbs(*this, other);
sync_dbs(other, *this);
}
tester::tester(chain_controller::runtime_limits limits)
: base_tester(limits) {
push_genesis_block();
}
tester::tester(chain_controller::controller_config config): base_tester(config) {};
void tester::push_genesis_block() {
set_code(config::system_account_name, test_system_wast);
set_abi(config::system_account_name, test_system_abi);
}
void tester::set_producers(const vector<account_name>& producer_names) {
// Create producer accounts, if it does not exist yet
for (auto& producer_name: producer_names) {
create_account(producer_name);
}
// Construct the param for setprods action
vector<fc::mutable_variant_object> producer_keys;
for (auto& producer_name: producer_names) {
producer_keys.emplace_back( fc::mutable_variant_object()
("producer_name", producer_name)
("signing_key", get_public_key( producer_name, "active" )));
}
// Send setprods action
static uint32_t version = 1;
push_action(N(eosio), N(setprods), N(eosio), fc::mutable_variant_object()
("version", version++)
("producers", producer_keys));
}
} } /// eosio::test
#include <eosio/testing/tester_network.hpp>
namespace eosio { namespace testing {
void tester_network::connect_blockchain(tester &new_blockchain) {
if (blockchains.count(&new_blockchain))
return;
// If the network isn't empty, sync the new blockchain with one of the old ones. The old ones are already in sync with
// each other, so just grab one arbitrarily. The old blockchains are connected to the propagation signals, so when one
// of them gets synced, it will propagate blocks to the others as well.
if (!blockchains.empty()) {
blockchains.begin()->first->sync_with(new_blockchain);
}
// The new blockchain is now in sync with any old ones; go ahead and connect the propagation signal.
blockchains[&new_blockchain] = new_blockchain.control->applied_block.connect(
[this, &new_blockchain](const chain::block_trace& bt) {
propagate_block(bt.block, new_blockchain);
});
}
void tester_network::disconnect_blockchain(tester &leaving_blockchain) {
blockchains.erase(&leaving_blockchain);
}
void tester_network::disconnect_all() {
blockchains.clear();
}
void tester_network::propagate_block(const signed_block &block, const tester &skip_blockchain) {
for (const auto &pair : blockchains) {
if (pair.first == &skip_blockchain) continue;
boost::signals2::shared_connection_block blocker(pair.second);
pair.first->control->push_block(block, eosio::chain::validation_steps::created_block);
}
}
} } /// eosio::testing
\ No newline at end of file
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册