Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test for node connectivity #1715

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 32 additions & 33 deletions libraries/app/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ void application_impl::reset_p2p_node(const fc::path& data_dir)
for( const string& endpoint_string : seeds )
{
try {
std::vector<fc::ip::endpoint> endpoints = resolve_string_to_ip_endpoints(endpoint_string);
std::vector<fc::ip::endpoint> endpoints = application::resolve_string_to_ip_endpoints(endpoint_string);
for (const fc::ip::endpoint& endpoint : endpoints)
{
ilog("Adding seed node ${endpoint}", ("endpoint", endpoint));
Expand All @@ -149,7 +149,7 @@ void application_impl::reset_p2p_node(const fc::path& data_dir)
for( const string& endpoint_string : seeds )
{
try {
std::vector<fc::ip::endpoint> endpoints = resolve_string_to_ip_endpoints(endpoint_string);
std::vector<fc::ip::endpoint> endpoints = application::resolve_string_to_ip_endpoints(endpoint_string);
for (const fc::ip::endpoint& endpoint : endpoints)
{
ilog("Adding seed node ${endpoint}", ("endpoint", endpoint));
Expand Down Expand Up @@ -188,7 +188,7 @@ void application_impl::reset_p2p_node(const fc::path& data_dir)
for( const string& endpoint_string : seeds )
{
try {
std::vector<fc::ip::endpoint> endpoints = resolve_string_to_ip_endpoints(endpoint_string);
std::vector<fc::ip::endpoint> endpoints = application::resolve_string_to_ip_endpoints(endpoint_string);
for (const fc::ip::endpoint& endpoint : endpoints)
{
ilog("Adding seed node ${endpoint}", ("endpoint", endpoint));
Expand All @@ -214,36 +214,6 @@ void application_impl::reset_p2p_node(const fc::path& data_dir)
std::vector<uint32_t>());
} FC_CAPTURE_AND_RETHROW() }

std::vector<fc::ip::endpoint> application_impl::resolve_string_to_ip_endpoints(const std::string& endpoint_string)
{
try
{
string::size_type colon_pos = endpoint_string.find(':');
if (colon_pos == std::string::npos)
FC_THROW("Missing required port number in endpoint string \"${endpoint_string}\"",
("endpoint_string", endpoint_string));
std::string port_string = endpoint_string.substr(colon_pos + 1);
try
{
uint16_t port = boost::lexical_cast<uint16_t>(port_string);

std::string hostname = endpoint_string.substr(0, colon_pos);
std::vector<fc::ip::endpoint> endpoints = fc::resolve(hostname, port);
if (endpoints.empty())
FC_THROW_EXCEPTION( fc::unknown_host_exception,
"The host name can not be resolved: ${hostname}",
("hostname", hostname) );
return endpoints;
}
catch (const boost::bad_lexical_cast&)
{
FC_THROW("Bad port: ${port}", ("port", port_string));
}
}
FC_CAPTURE_AND_RETHROW((endpoint_string))
}


void application_impl::new_connection( const fc::http::websocket_connection_ptr& c )
{
auto wsc = std::make_shared<fc::rpc::websocket_api_connection>(*c, GRAPHENE_NET_MAX_NESTED_OBJECTS);
Expand Down Expand Up @@ -1100,5 +1070,34 @@ const application_options& application::get_options()
return my->_app_options;
}

std::vector<fc::ip::endpoint> application::resolve_string_to_ip_endpoints(const std::string& endpoint_string)
{
try
{
string::size_type colon_pos = endpoint_string.find(':');
if (colon_pos == std::string::npos)
FC_THROW("Missing required port number in endpoint string \"${endpoint_string}\"",
("endpoint_string", endpoint_string));
std::string port_string = endpoint_string.substr(colon_pos + 1);
try
{
uint16_t port = boost::lexical_cast<uint16_t>(port_string);

std::string hostname = endpoint_string.substr(0, colon_pos);
std::vector<fc::ip::endpoint> endpoints = fc::resolve(hostname, port);
if (endpoints.empty())
FC_THROW_EXCEPTION( fc::unknown_host_exception,
"The host name can not be resolved: ${hostname}",
("hostname", hostname) );
return endpoints;
}
catch (const boost::bad_lexical_cast&)
{
FC_THROW("Bad port: ${port}", ("port", port_string));
}
}
FC_CAPTURE_AND_RETHROW((endpoint_string))
}

// namespace detail
} }
2 changes: 0 additions & 2 deletions libraries/app/application_impl.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ class application_impl : public net::node_delegate

void reset_p2p_node(const fc::path& data_dir);

std::vector<fc::ip::endpoint> resolve_string_to_ip_endpoints(const std::string& endpoint_string);

void new_connection( const fc::http::websocket_connection_ptr& c );

void reset_websocket_server();
Expand Down
1 change: 1 addition & 0 deletions libraries/app/include/graphene/app/application.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ namespace graphene { namespace app {
void shutdown();
void startup_plugins();
void shutdown_plugins();
static std::vector<fc::ip::endpoint> resolve_string_to_ip_endpoints(const std::string& endpoint_string);

template<typename PluginType>
std::shared_ptr<PluginType> register_plugin(bool auto_load = false) {
Expand Down
6 changes: 3 additions & 3 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ endif(MSVC)

file(GLOB PERFORMANCE_TESTS "performance/*.cpp")
add_executable( performance_test ${COMMON_SOURCES} ${PERFORMANCE_TESTS} )
target_link_libraries( performance_test graphene_chain graphene_app graphene_account_history graphene_elasticsearch graphene_es_objects graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
target_link_libraries( performance_test graphene_chain graphene_app graphene_witness graphene_account_history graphene_elasticsearch graphene_es_objects graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )

file(GLOB BENCH_MARKS "benchmarks/*.cpp")
add_executable( chain_bench ${COMMON_SOURCES} ${BENCH_MARKS} )
target_link_libraries( chain_bench graphene_chain graphene_app graphene_account_history graphene_elasticsearch graphene_es_objects graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
target_link_libraries( chain_bench graphene_chain graphene_witness graphene_app graphene_account_history graphene_elasticsearch graphene_es_objects graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )

file(GLOB APP_SOURCES "app/*.cpp")
add_executable( app_test ${APP_SOURCES} )
Expand All @@ -38,6 +38,6 @@ endif(MSVC)

file(GLOB ES_SOURCES "elasticsearch/*.cpp")
add_executable( es_test ${COMMON_SOURCES} ${ES_SOURCES} )
target_link_libraries( es_test graphene_chain graphene_app graphene_account_history graphene_elasticsearch graphene_es_objects graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
target_link_libraries( es_test graphene_chain graphene_app graphene_witness graphene_account_history graphene_elasticsearch graphene_es_objects graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )

add_subdirectory( generate_empty_blocks )
138 changes: 138 additions & 0 deletions tests/common/application_helper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#include "application_helper.hpp"
#include "genesis_file_util.hpp"
#include <graphene/account_history/account_history_plugin.hpp>
#include <graphene/market_history/market_history_plugin.hpp>
#include <graphene/witness/witness.hpp>
#include <graphene/grouped_orders/grouped_orders_plugin.hpp>
#include <boost/filesystem.hpp>

#ifdef _WIN32
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif
#include <winsock2.h>
#include <WS2tcpip.h>
int sockInit(void)
{
WSADATA wsa_data;
return WSAStartup(MAKEWORD(1,1), &wsa_data);
}
int sockQuit(void)
{
return WSACleanup();
}
#else
#include <sys/socket.h>
#include <netinet/ip.h>
#include <sys/types.h>
#endif

#include <boost/filesystem/path.hpp>

namespace graphene { namespace test {

application_runner::application_runner()
{
_app = std::make_shared<graphene::app::application>();

_app->register_plugin< graphene::account_history::account_history_plugin >(true);
_app->register_plugin< graphene::market_history::market_history_plugin >(true);
_app->register_plugin< graphene::witness_plugin::witness_plugin >(true);
_app->register_plugin< graphene::grouped_orders::grouped_orders_plugin >(true);
_app->startup_plugins();
#ifdef _WIN32
sockInit();
#endif
rpc_port_number = get_available_port();
p2p_port_number = get_available_port();
}

void application_runner::start()
{
boost::program_options::variables_map cfg;
cfg.emplace(
"rpc-endpoint",
boost::program_options::variable_value(std::string("127.0.0.1:" + std::to_string(rpc_port_number)), false)
);
cfg.emplace( "p2p-endpoint",
boost::program_options::variable_value(std::string("127.0.0.1:" + std::to_string(p2p_port_number)), false));
cfg.emplace("genesis-json", boost::program_options::variable_value(create_genesis_file(_dir), false));
std::string seed_node_string = "[";
bool needs_comma = false;
for(auto url : seed_nodes)
{
if (needs_comma)
seed_node_string += ", ";
seed_node_string += "\"" + url + "\"";
needs_comma = true;
}
seed_node_string += "]";
cfg.emplace("seed-nodes", boost::program_options::variable_value(seed_node_string, false));
_app->initialize(_dir.path(), cfg);

_app->initialize_plugins(cfg);
_app->startup_plugins();

_app->startup();
fc::usleep(fc::milliseconds(500));
}

std::shared_ptr<graphene::app::application> application_runner::get_app()
{
return _app;
}

void application_runner::add_seed_node(std::string addr)
{
/*
std::vector<fc::ip::endpoint> endpoints = graphene::app::application::resolve_string_to_ip_endpoints(addr);
for(const auto& ep : endpoints)
_app->p2p_node()->add_node(ep);
*/
seed_nodes.push_back(addr);
}

uint32_t application_runner::get_connection_count()
{
return _app->p2p_node()->get_connection_count();
}

bool application_runner::is_connected( std::string addr )
{
auto peer_statuses = _app->p2p_node()->get_connected_peers();
for (auto status : peer_statuses )
{
std::string host = status.host;
if ( host == addr )
return true;
}
return false;
}

//////
/// @brief attempt to find an available port on localhost
/// @returns an available port number, or -1 on error
/////
int application_runner::get_available_port()
{
struct sockaddr_in sin;
int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (socket_fd == -1)
return -1;
sin.sin_family = AF_INET;
sin.sin_port = 0;
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (::bind(socket_fd, (struct sockaddr*)&sin, sizeof(struct sockaddr_in)) == -1)
return -1;
socklen_t len = sizeof(sin);
if (getsockname(socket_fd, (struct sockaddr *)&sin, &len) == -1)
return -1;
#ifdef _WIN32
closesocket(socket_fd);
#else
close(socket_fd);
#endif
return ntohs(sin.sin_port);
}

}}
99 changes: 99 additions & 0 deletions tests/common/application_helper.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#pragma once
#include <memory>
#include <graphene/app/application.hpp>
#include <graphene/wallet/wallet.hpp>

#include <fc/thread/thread.hpp>
#include <fc/network/http/websocket.hpp>
#include <fc/rpc/websocket_api.hpp>
#include <fc/rpc/cli.hpp>

namespace graphene { namespace test {

/**
* Handles creating a running node
*/
class application_runner
{
public:
application_runner();
void start();
int rpc_port_number;
int p2p_port_number;
std::shared_ptr<graphene::app::application> get_app();
// networking
void add_seed_node(std::string addr);
bool is_connected( std::string addr );
uint32_t get_connection_count();
private:
std::shared_ptr<graphene::app::application> _app;
fc::temp_directory _dir;
static int get_available_port();
std::vector<std::string> seed_nodes;
};

///////////
/// @brief a class to make connecting to the application server easier
///////////
class client_connection
{
public:
/////////
// constructor
/////////
client_connection(
std::shared_ptr<graphene::app::application> app,
const int server_port_number,
const fc::temp_directory& data_dir = fc::temp_directory()
)
{
wallet_data.chain_id = app->chain_database()->get_chain_id();
wallet_data.ws_server = "ws://127.0.0.1:" + std::to_string(server_port_number);
wallet_data.ws_user = "";
wallet_data.ws_password = "";
websocket_connection = websocket_client.connect( wallet_data.ws_server );

api_connection = std::make_shared<fc::rpc::websocket_api_connection>(*websocket_connection, GRAPHENE_MAX_NESTED_OBJECTS);

remote_login_api = api_connection->get_remote_api< graphene::app::login_api >(1);
remote_login_api->login( wallet_data.ws_user, wallet_data.ws_password );


wallet_api_ptr = std::make_shared<graphene::wallet::wallet_api>(wallet_data, remote_login_api);
wallet_filename = data_dir.path().generic_string() + "/wallet.json";
wallet_api_ptr->set_wallet_filename(wallet_filename);
wallet_api_ptr->save_wallet_file();

wallet_api = fc::api<graphene::wallet::wallet_api>(wallet_api_ptr);

wallet_cli = std::make_shared<fc::rpc::cli>(GRAPHENE_MAX_NESTED_OBJECTS);
for( auto& name_formatter : wallet_api_ptr->get_result_formatters() )
wallet_cli->format_result( name_formatter.first, name_formatter.second );

boost::signals2::scoped_connection closed_connection(websocket_connection->closed.connect([=]{
std::cerr << "Server has disconnected us.\n";
wallet_cli->stop();
}));
(void)(closed_connection);
}
bool import_nathan_account()
{
std::string wif_key = "5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3";
std::vector<std::string> keys( { wif_key } );
bool ret_val = wallet_api_ptr->import_key("nathan", wif_key);
wallet_api_ptr->import_balance("nathan", keys, true);
return ret_val;
}
public:
fc::http::websocket_client websocket_client;
graphene::wallet::wallet_data wallet_data;
fc::http::websocket_connection_ptr websocket_connection;
std::shared_ptr<fc::rpc::websocket_api_connection> api_connection;
fc::api<login_api> remote_login_api;
std::shared_ptr<graphene::wallet::wallet_api> wallet_api_ptr;
fc::api<graphene::wallet::wallet_api> wallet_api;
std::shared_ptr<fc::rpc::cli> wallet_cli;
std::string wallet_filename;
};

}}
2 changes: 2 additions & 0 deletions tests/common/genesis_file_util.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include <boost/filesystem.hpp>

/////////
/// @brief forward declaration, using as a hack to generate a genesis.json file
/// for testing
Expand Down
Loading