mirror of
https://git.wownero.com/wownero/wownero.git
synced 2024-08-15 01:03:23 +00:00
moved all stuff to github
This commit is contained in:
parent
095fbeeb67
commit
296ae46ed8
388 changed files with 95937 additions and 469 deletions
1
contrib/epee/tests/.gitignore
vendored
Normal file
1
contrib/epee/tests/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/build/*
|
BIN
contrib/epee/tests/data/storages/invalid_storage_1.bin
Normal file
BIN
contrib/epee/tests/data/storages/invalid_storage_1.bin
Normal file
Binary file not shown.
BIN
contrib/epee/tests/data/storages/invalid_storage_2.bin
Normal file
BIN
contrib/epee/tests/data/storages/invalid_storage_2.bin
Normal file
Binary file not shown.
1
contrib/epee/tests/data/storages/invalid_storage_3.bin
Normal file
1
contrib/epee/tests/data/storages/invalid_storage_3.bin
Normal file
|
@ -0,0 +1 @@
|
|||
¢IMóÙŸˆm_bo
|
BIN
contrib/epee/tests/data/storages/invalid_storage_4.bin
Normal file
BIN
contrib/epee/tests/data/storages/invalid_storage_4.bin
Normal file
Binary file not shown.
BIN
contrib/epee/tests/data/storages/valid_storage.bin
Normal file
BIN
contrib/epee/tests/data/storages/valid_storage.bin
Normal file
Binary file not shown.
5
contrib/epee/tests/generate_vc_proj.bat
Normal file
5
contrib/epee/tests/generate_vc_proj.bat
Normal file
|
@ -0,0 +1,5 @@
|
|||
mkdir build
|
||||
cd build
|
||||
cmake "-DBoost_USE_STATIC_LIBS=TRUE" -G "Visual Studio 11 Win64" ../src
|
||||
cd ..
|
||||
pause
|
33
contrib/epee/tests/src/CMakeLists.txt
Normal file
33
contrib/epee/tests/src/CMakeLists.txt
Normal file
|
@ -0,0 +1,33 @@
|
|||
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(Boost_USE_MULTITHREADED ON)
|
||||
|
||||
include_directories(.)
|
||||
include_directories(../../include)
|
||||
|
||||
find_package(Boost COMPONENTS system filesystem thread date_time chrono regex)
|
||||
include_directories( ${Boost_INCLUDE_DIRS} )
|
||||
|
||||
IF (MSVC)
|
||||
add_definitions( "/W3 /D_CRT_SECURE_NO_WARNINGS /wd4996 /wd4345 /nologo /D_WIN32_WINNT=0x0600 /DWIN32_LEAN_AND_MEAN /bigobj" )
|
||||
include_directories(SYSTEM platform/msvc)
|
||||
ELSE()
|
||||
# set stuff for other systems
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -Wall -Werror")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Werror -Wno-reorder")
|
||||
ENDIF()
|
||||
|
||||
|
||||
# Add folders to filters
|
||||
file(GLOB_RECURSE SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.inl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.h)
|
||||
|
||||
source_group(general FILES ${SRC})
|
||||
|
||||
|
||||
add_executable(tests ${SRC} )
|
||||
target_link_libraries( tests ${Boost_LIBRARIES} )
|
||||
|
82
contrib/epee/tests/src/misc/test_math.h
Normal file
82
contrib/epee/tests/src/misc/test_math.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the Andrey N. Sabelnikov nor the
|
||||
// names of its contributors may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "misc_language.h"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace tests
|
||||
{
|
||||
bool test_median()
|
||||
{
|
||||
LOG_PRINT_L0("Testing median");
|
||||
std::vector<size_t> sz;
|
||||
size_t m = misc_utils::median(sz);
|
||||
CHECK_AND_ASSERT_MES(m == 0, false, "test failed");
|
||||
sz.push_back(1);
|
||||
m = misc_utils::median(sz);
|
||||
CHECK_AND_ASSERT_MES(m == 1, false, "test failed");
|
||||
sz.push_back(10);
|
||||
m = misc_utils::median(sz);
|
||||
CHECK_AND_ASSERT_MES(m == 5, false, "test failed");
|
||||
|
||||
sz.clear();
|
||||
sz.resize(3);
|
||||
sz[0] = 0;
|
||||
sz[1] = 9;
|
||||
sz[2] = 3;
|
||||
m = misc_utils::median(sz);
|
||||
CHECK_AND_ASSERT_MES(m == 3, false, "test failed");
|
||||
|
||||
sz.clear();
|
||||
sz.resize(4);
|
||||
sz[0] = 77;
|
||||
sz[1] = 9;
|
||||
sz[2] = 22;
|
||||
sz[3] = 60;
|
||||
m = misc_utils::median(sz);
|
||||
CHECK_AND_ASSERT_MES(m == 41, false, "test failed");
|
||||
|
||||
|
||||
|
||||
sz.clear();
|
||||
sz.resize(5);
|
||||
sz[0] = 77;
|
||||
sz[1] = 9;
|
||||
sz[2] = 22;
|
||||
sz[3] = 60;
|
||||
sz[4] = 11;
|
||||
m = misc_utils::median(sz);
|
||||
CHECK_AND_ASSERT_MES(m == 22, false, "test failed");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
403
contrib/epee/tests/src/net/test_net.h
Normal file
403
contrib/epee/tests/src/net/test_net.h
Normal file
|
@ -0,0 +1,403 @@
|
|||
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the Andrey N. Sabelnikov nor the
|
||||
// names of its contributors may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include "net/levin_server_cp2.h"
|
||||
#include "storages/abstract_invoke.h"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace StorageNamed
|
||||
{
|
||||
typedef CInMemStorage DefaultStorageType;
|
||||
}
|
||||
namespace tests
|
||||
{
|
||||
struct some_subdata
|
||||
{
|
||||
|
||||
std::string str1;
|
||||
std::list<boost::uint64_t> array_of_id;
|
||||
|
||||
BEGIN_NAMED_SERIALIZE_MAP()
|
||||
SERIALIZE_STL_ANSI_STRING(str1)
|
||||
SERIALIZE_STL_CONTAINER_POD(array_of_id)
|
||||
END_NAMED_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/************************************************************************/
|
||||
struct COMMAND_EXAMPLE_1
|
||||
{
|
||||
const static int ID = 1000;
|
||||
|
||||
struct request
|
||||
{
|
||||
|
||||
std::string example_string_data;
|
||||
boost::uint64_t example_id_data;
|
||||
some_subdata sub;
|
||||
|
||||
BEGIN_NAMED_SERIALIZE_MAP()
|
||||
SERIALIZE_STL_ANSI_STRING(example_string_data)
|
||||
SERIALIZE_POD(example_id_data)
|
||||
SERIALIZE_T(sub)
|
||||
END_NAMED_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
struct response
|
||||
{
|
||||
bool m_success;
|
||||
boost::uint64_t example_id_data;
|
||||
std::list<some_subdata> subs;
|
||||
|
||||
BEGIN_NAMED_SERIALIZE_MAP()
|
||||
SERIALIZE_POD(m_success)
|
||||
SERIALIZE_POD(example_id_data)
|
||||
SERIALIZE_STL_CONTAINER_T(subs)
|
||||
END_NAMED_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct COMMAND_EXAMPLE_2
|
||||
{
|
||||
const static int ID = 1001;
|
||||
|
||||
struct request
|
||||
{
|
||||
std::string example_string_data2;
|
||||
boost::uint64_t example_id_data;
|
||||
|
||||
BEGIN_NAMED_SERIALIZE_MAP()
|
||||
SERIALIZE_POD(example_id_data)
|
||||
SERIALIZE_STL_ANSI_STRING(example_string_data2)
|
||||
END_NAMED_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
bool m_success;
|
||||
boost::uint64_t example_id_data;
|
||||
|
||||
BEGIN_NAMED_SERIALIZE_MAP()
|
||||
SERIALIZE_POD(example_id_data)
|
||||
SERIALIZE_POD(m_success)
|
||||
END_NAMED_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
typedef boost::uuids::uuid uuid;
|
||||
|
||||
class test_levin_server: public levin::levin_commands_handler<>
|
||||
{
|
||||
test_levin_server(const test_levin_server&){}
|
||||
public:
|
||||
test_levin_server(){}
|
||||
void set_thread_prefix(const std::string& pref)
|
||||
{
|
||||
m_net_server.set_threads_prefix(pref);
|
||||
}
|
||||
template<class calback_t>
|
||||
bool connect_async(const std::string adr, const std::string& port, boost::uint32_t conn_timeot, calback_t cb, const std::string& bind_ip = "0.0.0.0")
|
||||
{
|
||||
return m_net_server.connect_async(adr, port, conn_timeot, cb, bind_ip);
|
||||
}
|
||||
|
||||
bool connect(const std::string adr, const std::string& port, boost::uint32_t conn_timeot, net_utils::connection_context_base& cn, const std::string& bind_ip = "0.0.0.0")
|
||||
{
|
||||
return m_net_server.connect(adr, port, conn_timeot, cn, bind_ip);
|
||||
}
|
||||
void close(net_utils::connection_context_base& cn)
|
||||
{
|
||||
m_net_server.get_config_object().close(cn.m_connection_id);
|
||||
}
|
||||
|
||||
template<class t_request, class t_response>
|
||||
bool invoke(uuid con_id, int command, t_request& req, t_response& resp)
|
||||
{
|
||||
return invoke_remote_command(con_id, command, req, resp, m_net_server.get_config_object());
|
||||
}
|
||||
|
||||
template< class t_response, class t_request, class callback_t>
|
||||
bool invoke_async(uuid con_id, int command, t_request& req, callback_t cb)
|
||||
{
|
||||
return async_invoke_remote_command<t_response>(con_id, command, req, m_net_server.get_config_object(), cb);
|
||||
}
|
||||
|
||||
bool init(const std::string& bind_port = "", const std::string& bind_ip = "0.0.0.0")
|
||||
{
|
||||
m_net_server.get_config_object().m_pcommands_handler = this;
|
||||
m_net_server.get_config_object().m_invoke_timeout = 1000;
|
||||
LOG_PRINT_L0("Binding on " << bind_ip << ":" << bind_port);
|
||||
return m_net_server.init_server(bind_port, bind_ip);
|
||||
}
|
||||
|
||||
bool run()
|
||||
{
|
||||
//here you can set worker threads count
|
||||
int thrds_count = 4;
|
||||
|
||||
//go to loop
|
||||
LOG_PRINT("Run net_service loop( " << thrds_count << " threads)...", LOG_LEVEL_0);
|
||||
if(!m_net_server.run_server(thrds_count))
|
||||
{
|
||||
LOG_ERROR("Failed to run net tcp server!");
|
||||
}
|
||||
|
||||
LOG_PRINT("net_service loop stopped.", LOG_LEVEL_0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool deinit()
|
||||
{
|
||||
return m_net_server.deinit_server();
|
||||
}
|
||||
|
||||
bool send_stop_signal()
|
||||
{
|
||||
m_net_server.send_stop_signal();
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t get_binded_port()
|
||||
{
|
||||
return m_net_server.get_binded_port();
|
||||
}
|
||||
private:
|
||||
|
||||
|
||||
CHAIN_LEVIN_INVOKE_TO_MAP(); //move levin_commands_handler interface invoke(...) callbacks into invoke map
|
||||
CHAIN_LEVIN_NOTIFY_TO_STUB(); //move levin_commands_handler interface notify(...) callbacks into nothing
|
||||
|
||||
BEGIN_INVOKE_MAP(test_levin_server)
|
||||
HANDLE_INVOKE_T(COMMAND_EXAMPLE_1, &test_levin_server::handle_1)
|
||||
HANDLE_INVOKE_T(COMMAND_EXAMPLE_2, &test_levin_server::handle_2)
|
||||
END_INVOKE_MAP()
|
||||
|
||||
//----------------- commands handlers ----------------------------------------------
|
||||
int handle_1(int command, COMMAND_EXAMPLE_1::request& arg, COMMAND_EXAMPLE_1::response& rsp, const net_utils::connection_context_base& context)
|
||||
{
|
||||
LOG_PRINT_L0("on_command_1: id " << arg.example_id_data << "---->>");
|
||||
COMMAND_EXAMPLE_2::request arg_ = AUTO_VAL_INIT(arg_);
|
||||
arg_.example_id_data = arg.example_id_data;
|
||||
COMMAND_EXAMPLE_2::response rsp_ = AUTO_VAL_INIT(rsp_);
|
||||
invoke_async<COMMAND_EXAMPLE_2::response>(context.m_connection_id, COMMAND_EXAMPLE_2::ID, arg_, [](int code, const COMMAND_EXAMPLE_2::response& rsp, const net_utils::connection_context_base& context)
|
||||
{
|
||||
if(code < 0)
|
||||
{LOG_PRINT_RED_L0("on_command_1: command_2 failed to invoke");}
|
||||
else
|
||||
{LOG_PRINT_L0("on_command_1: command_2 response " << rsp.example_id_data);}
|
||||
});
|
||||
rsp.example_id_data = arg.example_id_data;
|
||||
LOG_PRINT_L0("on_command_1: id " << arg.example_id_data << "<<----");
|
||||
return true;
|
||||
}
|
||||
int handle_2(int command, COMMAND_EXAMPLE_2::request& arg, COMMAND_EXAMPLE_2::response& rsp, const net_utils::connection_context_base& context)
|
||||
{
|
||||
LOG_PRINT_L0("on_command_2: id "<< arg.example_id_data);
|
||||
rsp.example_id_data = arg.example_id_data;
|
||||
//misc_utils::sleep_no_w(6000);
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
net_utils::boosted_levin_async_server m_net_server;
|
||||
};
|
||||
|
||||
|
||||
inline
|
||||
bool do_run_test_server()
|
||||
{
|
||||
|
||||
test_levin_server srv1, srv2;
|
||||
|
||||
|
||||
std::string bind_param = "0.0.0.0";
|
||||
std::string port = "";
|
||||
|
||||
if(!srv1.init(port, bind_param))
|
||||
{
|
||||
LOG_ERROR("Failed to initialize srv!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!srv2.init(port, bind_param))
|
||||
{
|
||||
LOG_ERROR("Failed to initialize srv!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
srv1.set_thread_prefix("SRV_A");
|
||||
srv2.set_thread_prefix("SRV_B");
|
||||
|
||||
boost::thread th1( boost::bind(&test_levin_server::run, &srv1));
|
||||
boost::thread th2( boost::bind(&test_levin_server::run, &srv2));
|
||||
|
||||
LOG_PRINT_L0("Initalized servers, waiting for worker threads started...");
|
||||
misc_utils::sleep_no_w(1000);
|
||||
|
||||
|
||||
LOG_PRINT_L0("Connecting to each other...");
|
||||
uint32_t port1 = srv1.get_binded_port();
|
||||
uint32_t port2 = srv2.get_binded_port();
|
||||
|
||||
COMMAND_EXAMPLE_1::request arg;
|
||||
COMMAND_EXAMPLE_1::request resp;
|
||||
|
||||
net_utils::connection_context_base cntxt_1;
|
||||
bool r = srv1.connect("127.0.0.1", string_tools::num_to_string_fast(port2), 5000, cntxt_1);
|
||||
CHECK_AND_ASSERT_MES(r, false, "connect to server failed");
|
||||
|
||||
net_utils::connection_context_base cntxt_2;
|
||||
r = srv2.connect("127.0.0.1", string_tools::num_to_string_fast(port1), 5000, cntxt_2);
|
||||
CHECK_AND_ASSERT_MES(r, false, "connect to server failed");
|
||||
|
||||
while(true)
|
||||
{
|
||||
LOG_PRINT_L0("Invoking from A to B...");
|
||||
int r = srv1.invoke(cntxt_1.m_connection_id, COMMAND_EXAMPLE_1::ID, arg, resp);
|
||||
if(r<=0)
|
||||
{
|
||||
LOG_ERROR("Failed tp invoke A to B");
|
||||
break;
|
||||
}
|
||||
|
||||
LOG_PRINT_L0("Invoking from B to A...");
|
||||
r = srv2.invoke(cntxt_2.m_connection_id, COMMAND_EXAMPLE_1::ID, arg, resp);
|
||||
if(r<=0)
|
||||
{
|
||||
LOG_ERROR("Failed tp invoke B to A");
|
||||
break;
|
||||
}
|
||||
}
|
||||
srv1.send_stop_signal();
|
||||
srv2.send_stop_signal();
|
||||
th1.join();
|
||||
th1.join();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline bool do_test2_work_with_srv(test_levin_server& srv, int port)
|
||||
{
|
||||
uint64_t i = 0;
|
||||
boost::mutex wait_event;
|
||||
wait_event.lock();
|
||||
while(true)
|
||||
{
|
||||
net_utils::connection_context_base cntxt_local = AUTO_VAL_INIT(cntxt_local);
|
||||
bool r = srv.connect_async("127.0.0.1", string_tools::num_to_string_fast(port), 5000, [&srv, &port, &wait_event, &i, &cntxt_local](const net_utils::connection_context_base& cntxt, const boost::system::error_code& ec)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(!ec, void(), "Some problems at connect, message: " << ec.message() );
|
||||
cntxt_local = cntxt;
|
||||
LOG_PRINT_L0("Invoking command 1 to " << port);
|
||||
COMMAND_EXAMPLE_1::request arg = AUTO_VAL_INIT(arg);
|
||||
arg.example_id_data = i;
|
||||
/*vc2010 workaround*/
|
||||
int port_ = port;
|
||||
boost::mutex& wait_event_ = wait_event;
|
||||
int r = srv.invoke_async<COMMAND_EXAMPLE_1::request>(cntxt.m_connection_id, COMMAND_EXAMPLE_1::ID, arg, [port_, &wait_event_](int code, const COMMAND_EXAMPLE_1::request& rsp, const net_utils::connection_context_base& cntxt)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(code > 0, void(), "Failed to invoke");
|
||||
LOG_PRINT_L0("command 1 invoke to " << port_ << " OK.");
|
||||
wait_event_.unlock();
|
||||
});
|
||||
});
|
||||
wait_event.lock();
|
||||
srv.close(cntxt_local);
|
||||
++i;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline
|
||||
bool do_run_test_server_async_connect()
|
||||
{
|
||||
test_levin_server srv1, srv2;
|
||||
|
||||
|
||||
std::string bind_param = "0.0.0.0";
|
||||
std::string port = "";
|
||||
|
||||
if(!srv1.init(port, bind_param))
|
||||
{
|
||||
LOG_ERROR("Failed to initialize srv!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!srv2.init(port, bind_param))
|
||||
{
|
||||
LOG_ERROR("Failed to initialize srv!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
srv1.set_thread_prefix("SRV_A");
|
||||
srv2.set_thread_prefix("SRV_B");
|
||||
|
||||
boost::thread thmain1( boost::bind(&test_levin_server::run, &srv1));
|
||||
boost::thread thmain2( boost::bind(&test_levin_server::run, &srv2));
|
||||
|
||||
LOG_PRINT_L0("Initalized servers, waiting for worker threads started...");
|
||||
misc_utils::sleep_no_w(1000);
|
||||
|
||||
|
||||
LOG_PRINT_L0("Connecting to each other...");
|
||||
uint32_t port1 = srv1.get_binded_port();
|
||||
uint32_t port2 = srv2.get_binded_port();
|
||||
|
||||
COMMAND_EXAMPLE_1::request arg;
|
||||
COMMAND_EXAMPLE_1::request resp;
|
||||
|
||||
|
||||
boost::thread work_1( boost::bind(do_test2_work_with_srv, boost::ref(srv1), port2));
|
||||
boost::thread work_2( boost::bind(do_test2_work_with_srv, boost::ref(srv2), port1));
|
||||
boost::thread work_3( boost::bind(do_test2_work_with_srv, boost::ref(srv1), port2));
|
||||
boost::thread work_4( boost::bind(do_test2_work_with_srv, boost::ref(srv2), port1));
|
||||
boost::thread work_5( boost::bind(do_test2_work_with_srv, boost::ref(srv1), port2));
|
||||
boost::thread work_6( boost::bind(do_test2_work_with_srv, boost::ref(srv2), port1));
|
||||
boost::thread work_7( boost::bind(do_test2_work_with_srv, boost::ref(srv1), port2));
|
||||
boost::thread work_8( boost::bind(do_test2_work_with_srv, boost::ref(srv2), port1));
|
||||
|
||||
|
||||
work_1.join();
|
||||
work_2.join();
|
||||
srv1.send_stop_signal();
|
||||
srv2.send_stop_signal();
|
||||
thmain1.join();
|
||||
thmain2.join();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
232
contrib/epee/tests/src/storages/portable_storages_test.h
Normal file
232
contrib/epee/tests/src/storages/portable_storages_test.h
Normal file
|
@ -0,0 +1,232 @@
|
|||
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the Andrey N. Sabelnikov nor the
|
||||
// names of its contributors may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include "storages/serializeble_struct_helper.h"
|
||||
#include "serialization/keyvalue_serialization.h"
|
||||
#include "storages/portable_storage.h"
|
||||
#include "storages/portable_storage_template_helper.h"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace tests
|
||||
{
|
||||
|
||||
struct port_test_struct_sub
|
||||
{
|
||||
std::string m_str;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_VAL(m_str)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
#pragma pack (push, 1)
|
||||
struct some_pod_struct
|
||||
{
|
||||
uint64_t a;
|
||||
int32_t b;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
struct port_test_struct
|
||||
{
|
||||
std::string m_str;
|
||||
uint64_t m_uint64;
|
||||
uint32_t m_uint32;
|
||||
uint16_t m_uint16;
|
||||
uint8_t m_uint8;
|
||||
int64_t m_int64;
|
||||
int32_t m_int32;
|
||||
int16_t m_int16;
|
||||
int8_t m_int8;
|
||||
double m_double;
|
||||
bool m_bool;
|
||||
some_pod_struct m_pod;
|
||||
std::list<std::string> m_list_of_str;
|
||||
std::list<uint64_t> m_list_of_uint64_t;
|
||||
std::list<uint32_t> m_list_of_uint32_t;
|
||||
std::list<uint16_t> m_list_of_uint16_t;
|
||||
std::list<uint8_t> m_list_of_uint8_t;
|
||||
std::list<int64_t> m_list_of_int64_t;
|
||||
std::list<int32_t> m_list_of_int32_t;
|
||||
std::list<int16_t> m_list_of_int16_t;
|
||||
std::list<int8_t> m_list_of_int8_t;
|
||||
std::list<double> m_list_of_double;
|
||||
std::list<bool> m_list_of_bool;
|
||||
port_test_struct_sub m_subobj;
|
||||
std::list<port_test_struct> m_list_of_self;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_VAL(m_str)
|
||||
KV_SERIALIZE_VAL(m_uint64)
|
||||
KV_SERIALIZE_VAL(m_uint32)
|
||||
KV_SERIALIZE_VAL(m_uint16)
|
||||
KV_SERIALIZE_VAL(m_uint8)
|
||||
KV_SERIALIZE_VAL(m_int64)
|
||||
KV_SERIALIZE_VAL(m_int32)
|
||||
KV_SERIALIZE_VAL(m_int16)
|
||||
KV_SERIALIZE_VAL(m_int8)
|
||||
KV_SERIALIZE_VAL(m_double)
|
||||
KV_SERIALIZE_VAL(m_bool)
|
||||
KV_SERIALIZE_VAL_POD_AS_BLOB(m_pod)
|
||||
KV_SERIALIZE_OBJ(m_subobj)
|
||||
KV_SERIALIZE_CONTAINER_VAL(m_list_of_str)
|
||||
KV_SERIALIZE_CONTAINER_VAL(m_list_of_uint64_t)
|
||||
KV_SERIALIZE_CONTAINER_VAL(m_list_of_uint32_t)
|
||||
KV_SERIALIZE_CONTAINER_VAL(m_list_of_uint16_t)
|
||||
KV_SERIALIZE_CONTAINER_VAL(m_list_of_uint8_t)
|
||||
KV_SERIALIZE_CONTAINER_VAL(m_list_of_int64_t)
|
||||
KV_SERIALIZE_CONTAINER_VAL(m_list_of_int32_t)
|
||||
KV_SERIALIZE_CONTAINER_VAL(m_list_of_int16_t)
|
||||
KV_SERIALIZE_CONTAINER_VAL(m_list_of_int8_t)
|
||||
KV_SERIALIZE_CONTAINER_VAL(m_list_of_double)
|
||||
KV_SERIALIZE_CONTAINER_VAL(m_list_of_bool)
|
||||
KV_SERIALIZE_CONTAINER_OBJ(m_list_of_self)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
bool operator != (const port_test_struct_sub& a, const port_test_struct_sub& b)
|
||||
{
|
||||
return b.m_str != a.m_str;
|
||||
}
|
||||
|
||||
bool operator == (const port_test_struct& a, const port_test_struct& b)
|
||||
{
|
||||
if( b.m_str != a.m_str
|
||||
|| b.m_uint64 != a.m_uint64
|
||||
|| b.m_uint32 != a.m_uint32
|
||||
|| b.m_uint16 != a.m_uint16
|
||||
|| b.m_uint8 != a.m_uint8
|
||||
|| b.m_int64 != a.m_int64
|
||||
|| b.m_int32 != a.m_int32
|
||||
|| b.m_int16 != a.m_int16
|
||||
|| b.m_int8 != a.m_int8
|
||||
|| b.m_double != a.m_double
|
||||
|| b.m_bool != a.m_bool
|
||||
|| b.m_pod.a != a.m_pod.a
|
||||
|| b.m_pod.b != a.m_pod.b
|
||||
|| b.m_list_of_str != a.m_list_of_str
|
||||
|| b.m_list_of_uint64_t != a.m_list_of_uint64_t
|
||||
|| b.m_list_of_uint32_t != a.m_list_of_uint32_t
|
||||
|| b.m_list_of_uint16_t != a.m_list_of_uint16_t
|
||||
|| b.m_list_of_uint8_t != a.m_list_of_uint8_t
|
||||
|| b.m_list_of_int64_t != a.m_list_of_int64_t
|
||||
|| b.m_list_of_int32_t != a.m_list_of_int32_t
|
||||
|| b.m_list_of_int16_t != a.m_list_of_int16_t
|
||||
|| b.m_list_of_int8_t != a.m_list_of_int8_t
|
||||
|| b.m_list_of_double != a.m_list_of_double
|
||||
|| b.m_list_of_bool != a.m_list_of_bool
|
||||
|| b.m_subobj != a.m_subobj
|
||||
|| b.m_list_of_self != a.m_list_of_self
|
||||
)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void fill_struct_with_test_values(port_test_struct& s)
|
||||
{
|
||||
s.m_str = "zuzuzuzuzuz";
|
||||
s.m_uint64 = 111111111111111;
|
||||
s.m_uint32 = 2222222;
|
||||
s.m_uint16 = 2222;
|
||||
s.m_uint8 = 22;
|
||||
s.m_int64 = -111111111111111;
|
||||
s.m_int32 = -2222222;
|
||||
s.m_int16 = -2222;
|
||||
s.m_int8 = -24;
|
||||
s.m_double = 0.11111;
|
||||
s.m_bool = true;
|
||||
s.m_pod.a = 32342342342342;
|
||||
s.m_pod.b = -342342;
|
||||
s.m_list_of_str.push_back("1112121");
|
||||
s.m_list_of_uint64_t.push_back(1111111111);
|
||||
s.m_list_of_uint64_t.push_back(2222222222);
|
||||
s.m_list_of_uint32_t.push_back(1111111);
|
||||
s.m_list_of_uint32_t.push_back(2222222);
|
||||
s.m_list_of_uint16_t.push_back(1111);
|
||||
s.m_list_of_uint16_t.push_back(2222);
|
||||
s.m_list_of_uint8_t.push_back(11);
|
||||
s.m_list_of_uint8_t.push_back(22);
|
||||
|
||||
|
||||
s.m_list_of_int64_t.push_back(-1111111111);
|
||||
s.m_list_of_int64_t.push_back(-222222222);
|
||||
s.m_list_of_int32_t.push_back(-1111111);
|
||||
s.m_list_of_int32_t.push_back(-2222222);
|
||||
s.m_list_of_int16_t.push_back(-1111);
|
||||
s.m_list_of_int16_t.push_back(-2222);
|
||||
s.m_list_of_int8_t.push_back(-11);
|
||||
s.m_list_of_int8_t.push_back(-22);
|
||||
|
||||
s.m_list_of_double.push_back(0.11111);
|
||||
s.m_list_of_double.push_back(0.22222);
|
||||
s.m_list_of_bool.push_back(true);
|
||||
s.m_list_of_bool.push_back(false);
|
||||
|
||||
s.m_subobj.m_str = "subszzzzzzzz";
|
||||
s.m_list_of_self.push_back(s);
|
||||
}
|
||||
|
||||
bool test_portable_storages(const std::string& tests_folder)
|
||||
{
|
||||
serialization::portable_storage ps, ps2;
|
||||
port_test_struct s1, s2;
|
||||
fill_struct_with_test_values(s1);
|
||||
|
||||
s1.store(ps);
|
||||
std::string binbuf;
|
||||
bool r = ps.store_to_binary(binbuf);
|
||||
|
||||
ps2.load_from_binary(binbuf);
|
||||
s2.load(ps2);
|
||||
if(!(s1 == s2))
|
||||
{
|
||||
LOG_ERROR("Portable storage test failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
port_test_struct ss1, ss2;
|
||||
fill_struct_with_test_values(ss1);
|
||||
std::string json_buff = epee::serialization::store_t_to_json(ss1);
|
||||
epee::serialization::load_t_from_json(ss2, json_buff);
|
||||
if(!(ss1 == ss2))
|
||||
{
|
||||
LOG_ERROR("Portable storage test failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
142
contrib/epee/tests/src/storages/storage_tests.h
Normal file
142
contrib/epee/tests/src/storages/storage_tests.h
Normal file
|
@ -0,0 +1,142 @@
|
|||
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the Andrey N. Sabelnikov nor the
|
||||
// names of its contributors may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "storages/serializeble_struct_helper.h"
|
||||
#include "storages/portable_storage.h"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace tests
|
||||
{
|
||||
|
||||
|
||||
struct test_struct
|
||||
{
|
||||
|
||||
std::string m_str;
|
||||
unsigned int m_uint;
|
||||
bool m_bool;
|
||||
std::list<std::string> m_list_of_str;
|
||||
std::list<int> m_list_of_int;
|
||||
std::list<test_struct> m_list_of_self;
|
||||
|
||||
|
||||
BEGIN_NAMED_SERIALIZE_MAP()
|
||||
SERIALIZE_STL_ANSI_STRING(m_str)
|
||||
SERIALIZE_POD(m_uint)
|
||||
SERIALIZE_POD(m_bool)
|
||||
SERIALIZE_STL_CONTAINER_ANSII_STRING(m_list_of_str)
|
||||
SERIALIZE_STL_CONTAINER_POD(m_list_of_int)
|
||||
SERIALIZE_STL_CONTAINER_T(m_list_of_self)
|
||||
END_NAMED_SERIALIZE_MAP()
|
||||
|
||||
};
|
||||
|
||||
|
||||
bool operator == (const test_struct& a, const test_struct& b)
|
||||
{
|
||||
if( b.m_str != a.m_str
|
||||
|| b.m_uint != a.m_uint
|
||||
|| b.m_bool != a.m_bool
|
||||
|| b.m_list_of_str != a.m_list_of_str
|
||||
|| b.m_list_of_int != a.m_list_of_int
|
||||
|| b.m_list_of_self != a.m_list_of_self
|
||||
)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline test_struct get_test_struct()
|
||||
{
|
||||
test_struct t = boost::value_initialized<test_struct>();
|
||||
t.m_bool = true;
|
||||
t.m_str = "ackamdc'kmecemcececmacmecmcm[aicm[oeicm[oeicm[qaicm[qoe";
|
||||
t.m_uint = 233242;
|
||||
for(int i = 0; i!=500; i++)
|
||||
t.m_list_of_int.push_back(i);
|
||||
|
||||
for(int i = 0; i!=500; i++)
|
||||
t.m_list_of_str.push_back("ssccd");
|
||||
|
||||
for(int i = 0; i!=5; i++)
|
||||
{
|
||||
t.m_list_of_self.push_back(t);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
bool test_storages(const std::string& tests_folder)
|
||||
{
|
||||
|
||||
epee::serialization::portable_storage ps;
|
||||
auto s = ps.open_section("zzz", nullptr);
|
||||
uint64_t i = 0;
|
||||
ps.get_value("afdsdf", i, s);
|
||||
|
||||
|
||||
LOG_PRINT_L0("Generating test struct...");
|
||||
boost::filesystem::path storage_folder = tests_folder;
|
||||
storage_folder /= "storages";
|
||||
|
||||
|
||||
test_struct t = get_test_struct();
|
||||
|
||||
LOG_PRINT_L0("Loading test struct from storage...");
|
||||
test_struct t2;
|
||||
bool res = epee::StorageNamed::load_struct_from_storage_file(t2, (storage_folder /+ "valid_storage.bin").string());
|
||||
CHECK_AND_ASSERT_MES(res, false, "Failed to load valid_storage.bin");
|
||||
|
||||
LOG_PRINT_L0("Comparing generated and loaded test struct...");
|
||||
if(!(t == t2))
|
||||
return false;
|
||||
|
||||
LOG_PRINT_L0("Loading broken archive 1...");
|
||||
test_struct t3;
|
||||
res = epee::StorageNamed::load_struct_from_storage_file(t3, (storage_folder /+ "invalid_storage_1.bin").string());
|
||||
CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_1.bin loaded, but should not ");
|
||||
|
||||
|
||||
LOG_PRINT_L0("Loading broken archive 2...");
|
||||
res = epee::StorageNamed::load_struct_from_storage_file(t3, (storage_folder /+ "invalid_storage_2.bin").string());
|
||||
CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_2.bin loaded, but should not ");
|
||||
|
||||
LOG_PRINT_L0("Loading broken archive 3...");
|
||||
res = epee::StorageNamed::load_struct_from_storage_file(t3, (storage_folder /+ "invalid_storage_3.bin").string());
|
||||
CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_3.bin loaded, but should not ");
|
||||
|
||||
LOG_PRINT_L0("Loading broken archive 4...");
|
||||
res = epee::StorageNamed::load_struct_from_storage_file(t3, (storage_folder /+ "invalid_storage_4.bin").string());
|
||||
CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_3.bin loaded, but should not ");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
59
contrib/epee/tests/src/tests.cpp
Normal file
59
contrib/epee/tests/src/tests.cpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
|
||||
#include "include_base_utils.h"
|
||||
#include "storages/storage_tests.h"
|
||||
#include "misc/test_math.h"
|
||||
#include "storages/portable_storages_test.h"
|
||||
#include "net/test_net.h"
|
||||
|
||||
using namespace epee;
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
|
||||
string_tools::set_module_name_and_folder(argv[0]);
|
||||
|
||||
//set up logging options
|
||||
log_space::get_set_log_detalisation_level(true, LOG_LEVEL_2);
|
||||
log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL);
|
||||
log_space::log_singletone::add_logger(LOGGER_FILE,
|
||||
log_space::log_singletone::get_default_log_file().c_str(),
|
||||
log_space::log_singletone::get_default_log_folder().c_str());
|
||||
|
||||
|
||||
string_tools::command_line_params_a start_params;
|
||||
string_tools::parse_commandline(start_params, argc, argv);
|
||||
std::string tests_data_path;
|
||||
string_tools::get_xparam_from_command_line(start_params, std::string("/tests_folder"), tests_data_path);
|
||||
|
||||
if(string_tools::have_in_command_line(start_params, std::string("/run_net_tests")))
|
||||
{
|
||||
if(!tests::do_run_test_server())
|
||||
{
|
||||
LOG_ERROR("net tests failed");
|
||||
return 1;
|
||||
}
|
||||
if(!tests::do_run_test_server_async_connect() )
|
||||
{
|
||||
LOG_ERROR("net tests failed");
|
||||
return 1;
|
||||
}
|
||||
}else if(string_tools::have_in_command_line(start_params, std::string("/run_unit_tests")))
|
||||
{
|
||||
if(!tests::test_median())
|
||||
{
|
||||
LOG_ERROR("median test failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
if(!tests::test_storages(tests_data_path))
|
||||
{
|
||||
LOG_ERROR("storage test failed");
|
||||
return 1;
|
||||
}
|
||||
}else if(string_tools::have_in_command_line(start_params, std::string("/run_portable_storage_test")))
|
||||
{
|
||||
tests::test_portable_storages(tests_data_path);
|
||||
}
|
||||
return 1;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue