102 {
103 boost::filesystem::path temp = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
104
105 try {
106 std::promise<std::tuple<producer_plugin*, chain_plugin*>> plugin_promise;
107 std::future<std::tuple<producer_plugin*, chain_plugin*>> plugin_fut = plugin_promise.get_future();
108 std::thread app_thread( [&]() {
110 std::vector<const char*>
argv =
111 {"test", "--data-dir", temp.c_str(), "--config-dir", temp.c_str(),
112 "-p", "sysio", "-e", "--max-transaction-time", "475", "--disable-subjective-billing=true" };
115 plugin_promise.set_value(
118 } );
119
120 auto[prod_plug, chain_plug] = plugin_fut.get();
121 auto chain_id = chain_plug->get_chain_id();
122
123 std::deque<block_state_ptr> all_blocks;
124 std::promise<void> empty_blocks_promise;
125 std::future<void> empty_blocks_fut = empty_blocks_promise.get_future();
126 auto ab = chain_plug->chain().accepted_block.connect( [&](
const block_state_ptr& bsp) {
127 static int num_empty = std::numeric_limits<int>::max();
128 all_blocks.push_back( bsp );
129 if( bsp->block->transactions.empty() ) {
130 --num_empty;
131 if( num_empty == 0 ) empty_blocks_promise.set_value();
132 } else {
133 num_empty = 10;
134 }
135 } );
136 auto bs = chain_plug->chain().block_start.connect( [&](
uint32_t bn ) {
137 } );
138
139 std::deque<packed_transaction_ptr> trxs;
140 std::atomic<size_t> next_calls = 0;
141 std::atomic<size_t> num_posts = 0;
142 std::atomic<size_t> trace_with_except = 0;
143 std::atomic<bool> trx_match = true;
144 const size_t num_pushes = 4242;
145 for( size_t i = 1; i <= num_pushes; ++i ) {
146 auto ptrx = make_unique_trx( chain_id );
147 dlog(
"posting ${id}", (
"id", ptrx->id()) );
148 app().
post(
priority::low, [ptrx, &next_calls, &num_posts, &trace_with_except, &trx_match, &trxs]() {
149 ++num_posts;
150 bool return_failure_traces = false;
152 false,
153 false,
154 false,
155 [ptrx, &next_calls, &trace_with_except, &trx_match, &trxs, return_failure_traces]
156 (const std::variant<fc::exception_ptr, transaction_trace_ptr>& result) {
157 if( !std::holds_alternative<fc::exception_ptr>( result ) && !std::get<chain::transaction_trace_ptr>( result )->except ) {
158 if( std::get<chain::transaction_trace_ptr>( result )->id == ptrx->id() ) {
159 trxs.push_back( ptrx );
160 } else {
161 elog(
"trace not for trx ${id}: ${t}",
163 trx_match = false;
164 }
165 } else if( !return_failure_traces && !std::holds_alternative<fc::exception_ptr>( result ) && std::get<chain::transaction_trace_ptr>( result )->except ) {
166 elog(
"trace with except ${e}",
168 ++trace_with_except;
169 }
170 ++next_calls;
171 });
172 });
173 if( i % (num_pushes/3) == 0 ) {
174
175 usleep( config::block_interval_us / 2 );
176 }
177 if( i % 200 == 0 ) {
178
179
182 });
183 }
184 }
185
186 empty_blocks_fut.wait_for(std::chrono::seconds(15));
187
188 BOOST_CHECK_EQUAL( trace_with_except, 0 );
189 BOOST_CHECK( all_blocks.size() > 3 );
190 BOOST_CHECK_EQUAL( num_pushes, num_posts );
191 BOOST_CHECK_EQUAL( num_pushes, next_calls );
192 BOOST_CHECK( trx_match.load() );
193
195 app_thread.join();
196
197 BOOST_REQUIRE( verify_equal(trxs, all_blocks ) );
198
199 } catch ( ... ) {
200 bfs::remove_all( temp );
201 throw;
202 }
203 bfs::remove_all( temp );
204}
abstract_plugin * find_plugin(const string &name) const
bool initialize(int argc, char **argv)
Looks for the –plugin commandline / config option and calls initialize on those plugins.
auto post(int priority, Func &&func)
auto get_method() -> std::enable_if_t< is_method_decl< MethodDecl >::value, typename MethodDecl::method_type & >
static string to_pretty_string(const variant &v, const yield_function_t &yield, const output_formatting format=output_formatting::stringify_large_ints_and_doubles)
logger & set_log_level(log_level e)
static logger get(const fc::string &name=DEFAULT_LOGGER)
std::shared_ptr< block_state > block_state_ptr
static constexpr int high