Updates from BitShares FC #22
4 changed files with 86 additions and 74 deletions
|
|
@ -28,6 +28,8 @@
|
|||
#include <vector>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
namespace fc { namespace detail {
|
||||
|
||||
/** Errors thrown by the bignum class */
|
||||
class bignum_error : public std::runtime_error
|
||||
{
|
||||
|
|
@ -605,11 +607,10 @@ inline bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vch
|
|||
return DecodeBase58(str.c_str(), vchRet);
|
||||
}
|
||||
|
||||
|
||||
namespace fc {
|
||||
} // detail
|
||||
|
||||
std::string to_base58( const char* d, size_t s ) {
|
||||
return EncodeBase58( (const unsigned char*)d, (const unsigned char*)d+s ).c_str();
|
||||
return fc::detail::EncodeBase58( (const unsigned char*)d, (const unsigned char*)d+s ).c_str();
|
||||
}
|
||||
|
||||
std::string to_base58( const std::vector<char>& d )
|
||||
|
|
@ -620,8 +621,9 @@ std::string to_base58( const std::vector<char>& d )
|
|||
}
|
||||
std::vector<char> from_base58( const std::string& base58_str ) {
|
||||
std::vector<unsigned char> out;
|
||||
if( !DecodeBase58( base58_str.c_str(), out ) ) {
|
||||
FC_THROW_EXCEPTION( parse_error_exception, "Unable to decode base58 string ${base58_str}", ("base58_str",base58_str) );
|
||||
if( !fc::detail::DecodeBase58( base58_str.c_str(), out ) ) {
|
||||
FC_THROW_EXCEPTION( parse_error_exception, "Unable to decode base58 string ${base58_str}",
|
||||
("base58_str",base58_str) );
|
||||
}
|
||||
return std::vector<char>((const char*)out.data(), ((const char*)out.data())+out.size() );
|
||||
}
|
||||
|
|
@ -629,10 +631,10 @@ std::vector<char> from_base58( const std::string& base58_str ) {
|
|||
* @return the number of bytes decoded
|
||||
*/
|
||||
size_t from_base58( const std::string& base58_str, char* out_data, size_t out_data_len ) {
|
||||
//slog( "%s", base58_str.c_str() );
|
||||
std::vector<unsigned char> out;
|
||||
if( !DecodeBase58( base58_str.c_str(), out ) ) {
|
||||
FC_THROW_EXCEPTION( parse_error_exception, "Unable to decode base58 string ${base58_str}", ("base58_str",base58_str) );
|
||||
if( !fc::detail::DecodeBase58( base58_str.c_str(), out ) ) {
|
||||
FC_THROW_EXCEPTION( parse_error_exception, "Unable to decode base58 string ${base58_str}",
|
||||
("base58_str",base58_str) );
|
||||
}
|
||||
FC_ASSERT( out.size() <= out_data_len );
|
||||
if (!out.empty()) {
|
||||
|
|
@ -640,6 +642,7 @@ size_t from_base58( const std::string& base58_str, char* out_data, size_t out_da
|
|||
}
|
||||
return out.size();
|
||||
}
|
||||
}
|
||||
|
||||
} // fc
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
#include <fc/rpc/api_connection.hpp>
|
||||
#include <fc/rpc/websocket_api.hpp>
|
||||
|
||||
namespace fc { namespace test {
|
||||
|
||||
class calculator
|
||||
{
|
||||
public:
|
||||
|
|
@ -15,9 +17,6 @@ class calculator
|
|||
void on_result2( const std::function<void(int32_t)>& cb, int test );
|
||||
};
|
||||
|
||||
FC_API( calculator, (add)(sub)(on_result)(on_result2) )
|
||||
|
||||
|
||||
class login_api
|
||||
{
|
||||
public:
|
||||
|
|
@ -29,8 +28,6 @@ class login_api
|
|||
fc::optional<fc::api<calculator>> calc;
|
||||
std::set<std::string> test( const std::string&, const std::string& ) { return std::set<std::string>(); }
|
||||
};
|
||||
FC_API( login_api, (get_calc)(test) );
|
||||
|
||||
|
||||
class optionals_api
|
||||
{
|
||||
|
|
@ -44,9 +41,6 @@ public:
|
|||
return fc::json::to_string(fc::variants{{first,2}, {second, 2}, {third, 2}});
|
||||
}
|
||||
};
|
||||
FC_API( optionals_api, (foo)(bar) );
|
||||
|
||||
using namespace fc;
|
||||
|
||||
class some_calculator
|
||||
{
|
||||
|
|
@ -58,6 +52,12 @@ class some_calculator
|
|||
std::function<void(int32_t)> _cb;
|
||||
};
|
||||
|
||||
}} // fc::test
|
||||
|
||||
FC_API( fc::test::calculator, (add)(sub)(on_result)(on_result2) )
|
||||
FC_API( fc::test::login_api, (get_calc)(test) );
|
||||
FC_API( fc::test::optionals_api, (foo)(bar) );
|
||||
|
||||
using namespace fc::http;
|
||||
using namespace fc::rpc;
|
||||
|
||||
|
|
@ -67,14 +67,14 @@ BOOST_AUTO_TEST_SUITE(api_tests)
|
|||
|
||||
BOOST_AUTO_TEST_CASE(login_test) {
|
||||
try {
|
||||
fc::api<calculator> calc_api( std::make_shared<some_calculator>() );
|
||||
fc::api<fc::test::calculator> calc_api( std::make_shared<fc::test::some_calculator>() );
|
||||
|
||||
auto server = std::make_shared<fc::http::websocket_server>();
|
||||
server->on_connection([&]( const websocket_connection_ptr& c ){
|
||||
auto wsc = std::make_shared<websocket_api_connection>(c, MAX_DEPTH);
|
||||
auto login = std::make_shared<login_api>();
|
||||
auto login = std::make_shared<fc::test::login_api>();
|
||||
login->calc = calc_api;
|
||||
wsc->register_api(fc::api<login_api>(login));
|
||||
wsc->register_api(fc::api<fc::test::login_api>(login));
|
||||
c->set_session_data( wsc );
|
||||
});
|
||||
|
||||
|
|
@ -86,7 +86,7 @@ BOOST_AUTO_TEST_CASE(login_test) {
|
|||
auto con = client->connect( "ws://localhost:" + std::to_string(listen_port) );
|
||||
server->stop_listening();
|
||||
auto apic = std::make_shared<websocket_api_connection>(con, MAX_DEPTH);
|
||||
auto remote_login_api = apic->get_remote_api<login_api>();
|
||||
auto remote_login_api = apic->get_remote_api<fc::test::login_api>();
|
||||
auto remote_calc = remote_login_api->get_calc();
|
||||
bool remote_triggered = false;
|
||||
remote_calc->on_result( [&remote_triggered]( uint32_t r ) { remote_triggered = true; } );
|
||||
|
|
@ -103,8 +103,8 @@ BOOST_AUTO_TEST_CASE(login_test) {
|
|||
|
||||
BOOST_AUTO_TEST_CASE(optionals_test) {
|
||||
try {
|
||||
auto optionals = std::make_shared<optionals_api>();
|
||||
fc::api<optionals_api> oapi(optionals);
|
||||
auto optionals = std::make_shared<fc::test::optionals_api>();
|
||||
fc::api<fc::test::optionals_api> oapi(optionals);
|
||||
BOOST_CHECK_EQUAL(oapi->foo("a"), "[\"a\",null,null]");
|
||||
BOOST_CHECK_EQUAL(oapi->foo("a", "b"), "[\"a\",\"b\",null]");
|
||||
BOOST_CHECK_EQUAL(oapi->foo("a", "b", "c"), "[\"a\",\"b\",\"c\"]");
|
||||
|
|
@ -119,7 +119,7 @@ BOOST_AUTO_TEST_CASE(optionals_test) {
|
|||
auto server = std::make_shared<fc::http::websocket_server>();
|
||||
server->on_connection([&]( const websocket_connection_ptr& c ){
|
||||
auto wsc = std::make_shared<websocket_api_connection>(c, MAX_DEPTH);
|
||||
wsc->register_api(fc::api<optionals_api>(optionals));
|
||||
wsc->register_api(fc::api<fc::test::optionals_api>(optionals));
|
||||
c->set_session_data( wsc );
|
||||
});
|
||||
|
||||
|
|
@ -130,7 +130,7 @@ BOOST_AUTO_TEST_CASE(optionals_test) {
|
|||
auto client = std::make_shared<fc::http::websocket_client>();
|
||||
auto con = client->connect( "ws://localhost:" + std::to_string(listen_port) );
|
||||
auto apic = std::make_shared<websocket_api_connection>(con, MAX_DEPTH);
|
||||
auto remote_optionals = apic->get_remote_api<optionals_api>();
|
||||
auto remote_optionals = apic->get_remote_api<fc::test::optionals_api>();
|
||||
|
||||
BOOST_CHECK_EQUAL(remote_optionals->foo("a"), "[\"a\",null,null]");
|
||||
BOOST_CHECK_EQUAL(remote_optionals->foo("a", "b"), "[\"a\",\"b\",null]");
|
||||
|
|
@ -145,8 +145,8 @@ BOOST_AUTO_TEST_CASE(optionals_test) {
|
|||
|
||||
auto client2 = std::make_shared<fc::http::websocket_client>();
|
||||
auto con2 = client2->connect( "ws://localhost:" + std::to_string(listen_port) );
|
||||
string response;
|
||||
con2->on_message_handler([&](const std::string& s){
|
||||
std::string response;
|
||||
con2->on_message_handler([&response](const std::string& s){
|
||||
response = s;
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,16 @@
|
|||
#include <fc/network/tcp_socket.hpp>
|
||||
#include <fc/asio.hpp>
|
||||
|
||||
namespace fc { namespace test {
|
||||
|
||||
class my_io_class : public fc::asio::default_io_service_scope
|
||||
{
|
||||
public:
|
||||
static void reset_num_threads() { fc::asio::default_io_service_scope::num_io_threads = 0; }
|
||||
};
|
||||
|
||||
}} // fc::test
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(tcp_tests)
|
||||
|
||||
/***
|
||||
|
|
@ -15,23 +25,17 @@ BOOST_AUTO_TEST_CASE(tcpconstructor_test)
|
|||
fc::tcp_socket socket;
|
||||
}
|
||||
|
||||
class my_io_class : public fc::asio::default_io_service_scope
|
||||
{
|
||||
public:
|
||||
static void reset_num_threads() { fc::asio::default_io_service_scope::num_io_threads = 0; }
|
||||
};
|
||||
|
||||
/***
|
||||
* Test the control of number of threads from outside
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE( number_threads_test )
|
||||
{
|
||||
// to erase leftovers from previous tests
|
||||
my_io_class::reset_num_threads();
|
||||
fc::test::my_io_class::reset_num_threads();
|
||||
|
||||
fc::asio::default_io_service_scope::set_num_threads(12);
|
||||
|
||||
my_io_class my_class;
|
||||
fc::test::my_io_class my_class;
|
||||
|
||||
BOOST_CHECK_EQUAL( 12, my_class.get_num_threads() );
|
||||
}
|
||||
|
|
@ -42,9 +46,9 @@ BOOST_AUTO_TEST_CASE( number_threads_test )
|
|||
BOOST_AUTO_TEST_CASE( default_number_threads_test )
|
||||
{
|
||||
// to erase leftovers from previous tests
|
||||
my_io_class::reset_num_threads();
|
||||
fc::test::my_io_class::reset_num_threads();
|
||||
|
||||
my_io_class my_class;
|
||||
fc::test::my_io_class my_class;
|
||||
|
||||
fc::asio::default_io_service();
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
namespace fc { namespace test {
|
||||
|
||||
struct thread_config {
|
||||
thread_config() {
|
||||
for( int i = 0; i < boost::unit_test::framework::master_test_suite().argc - 1; ++i )
|
||||
|
|
@ -42,13 +44,51 @@ struct thread_config {
|
|||
{
|
||||
uint16_t threads = atoi(boost::unit_test::framework::master_test_suite().argv[++i]);
|
||||
std::cout << "Using " << threads << " pool threads\n";
|
||||
fc::asio::default_io_service_scope::set_num_threads(threads);
|
||||
asio::default_io_service_scope::set_num_threads(threads);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_GLOBAL_FIXTURE( thread_config );
|
||||
const std::string TEXT = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"$%&/()=?,.-#+´{[]}`*'_:;<>|";
|
||||
|
||||
template<typename Hash>
|
||||
class hash_test {
|
||||
public:
|
||||
std::string _hashname = get_typename<Hash>::name();
|
||||
|
||||
void run_single_threaded() {
|
||||
const std::string first = Hash::hash(TEXT).str();
|
||||
time_point start = time_point::now();
|
||||
for( int i = 0; i < 1000; i++ )
|
||||
BOOST_CHECK_EQUAL( first, Hash::hash(TEXT).str() );
|
||||
time_point end = time_point::now();
|
||||
ilog( "${c} single-threaded ${h}'s in ${t}µs", ("c",1000)("h",_hashname)("t",end-start) );
|
||||
}
|
||||
|
||||
void run_multi_threaded() {
|
||||
const std::string first = Hash::hash(TEXT).str();
|
||||
std::vector<future<std::string>> results;
|
||||
results.reserve( 10000 );
|
||||
time_point start = time_point::now();
|
||||
for( int i = 0; i < 10000; i++ )
|
||||
results.push_back( do_parallel( [] () { return Hash::hash(TEXT).str(); } ) );
|
||||
for( auto& result: results )
|
||||
BOOST_CHECK_EQUAL( first, result.wait() );
|
||||
time_point end = time_point::now();
|
||||
ilog( "${c} multi-threaded ${h}'s in ${t}µs", ("c",10000)("h",_hashname)("t",end-start) );
|
||||
}
|
||||
|
||||
void run() {
|
||||
run_single_threaded();
|
||||
run_multi_threaded();
|
||||
}
|
||||
};
|
||||
|
||||
}} // fc::test
|
||||
|
||||
using namespace fc::test;
|
||||
|
||||
BOOST_GLOBAL_FIXTURE( thread_config );
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(parallel_tests)
|
||||
|
||||
|
|
@ -96,41 +136,6 @@ BOOST_AUTO_TEST_CASE( do_something_parallel )
|
|||
}
|
||||
}
|
||||
|
||||
const std::string TEXT = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"$%&/()=?,.-#+´{[]}`*'_:;<>|";
|
||||
|
||||
template<typename Hash>
|
||||
class hash_test {
|
||||
public:
|
||||
std::string _hashname = fc::get_typename<Hash>::name();
|
||||
|
||||
void run_single_threaded() {
|
||||
const std::string first = Hash::hash(TEXT).str();
|
||||
fc::time_point start = fc::time_point::now();
|
||||
for( int i = 0; i < 1000; i++ )
|
||||
BOOST_CHECK_EQUAL( first, Hash::hash(TEXT).str() );
|
||||
fc::time_point end = fc::time_point::now();
|
||||
ilog( "${c} single-threaded ${h}'s in ${t}µs", ("c",1000)("h",_hashname)("t",end-start) );
|
||||
}
|
||||
|
||||
void run_multi_threaded() {
|
||||
const std::string first = Hash::hash(TEXT).str();
|
||||
std::vector<fc::future<std::string>> results;
|
||||
results.reserve( 10000 );
|
||||
fc::time_point start = fc::time_point::now();
|
||||
for( int i = 0; i < 10000; i++ )
|
||||
results.push_back( fc::do_parallel( [] () { return Hash::hash(TEXT).str(); } ) );
|
||||
for( auto& result: results )
|
||||
BOOST_CHECK_EQUAL( first, result.wait() );
|
||||
fc::time_point end = fc::time_point::now();
|
||||
ilog( "${c} multi-threaded ${h}'s in ${t}µs", ("c",10000)("h",_hashname)("t",end-start) );
|
||||
}
|
||||
|
||||
void run() {
|
||||
run_single_threaded();
|
||||
run_multi_threaded();
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_CASE( hash_parallel )
|
||||
{
|
||||
hash_test<fc::ripemd160>().run();
|
||||
|
|
|
|||
Loading…
Reference in a new issue