You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openmonero/tests/mysql_tests.cpp

1633 lines
129 KiB

6 years ago
//
// Created by mwo on 15/06/18.
//
#include "src/MicroCore.h"
#include "../src/OpenMoneroRequests.h"
#include "../src/db/MysqlPing.h"
//#include "chaingen.h"
//#include "chaingen_tests_list.h"
#include "gmock/gmock.h"
6 years ago
#include "gtest/gtest.h"
#include "../src/ThreadRAII.h"
6 years ago
#include "helpers.h"
6 years ago
namespace
6 years ago
{
using json = nlohmann::json;
using namespace std;
using namespace mysqlpp;
using namespace cryptonote;
using namespace epee::string_tools;
using namespace std::chrono_literals;
using ::testing::AllOf;
using ::testing::Ge;
using ::testing::Le;
json
readin_config()
{
// read in confing json file and get test db info
std::string config_json_path{"../config/config.json"};
// check if config-file provided exist
if (!boost::filesystem::exists(config_json_path))
{
std::cerr << "Config file " << config_json_path
<< " does not exist\n";
return {};
}
json config_json;
try
{
// try reading and parsing json config file provided
std::ifstream i(config_json_path);
i >> config_json;
return config_json["database_test"];
}
catch (const std::exception &e)
{
std::cerr << "Error reading confing file "
<< config_json_path << ": "
<< e.what() << '\n';
return {};
}
return {};
}
shared_ptr<xmreg::MySqlConnector>
make_connection()
{
json db_config = readin_config();
if (db_config.empty())
{
cerr << "Cant readin_config()";
return nullptr;
}
xmreg::MySqlConnector::url = db_config["url"];
xmreg::MySqlConnector::port = db_config["port"];
xmreg::MySqlConnector::username = db_config["user"];
xmreg::MySqlConnector::password = db_config["password"];
xmreg::MySqlConnector::dbname = db_config["dbname"];
return make_shared<xmreg::MySqlConnector>();
}
TEST(MYSQL_CONNECTION, CantConnect)
{
// we did specify wrong mysql details so this should throw.
xmreg::MySqlConnector::url = "127.0.0.1";
xmreg::MySqlConnector::port = 3306;
xmreg::MySqlConnector::username = "wrong_user";
xmreg::MySqlConnector::password = "wrong_pass";
xmreg::MySqlConnector::dbname = "wrong_name";
try
{
auto xmr_accounts = std::make_shared<xmreg::MySqlAccounts>(nullptr);
}
catch(...) {
EXPECT_TRUE(true);
return;
}
FAIL() << "Should have thrown exception";
}
TEST(MYSQL_CONNECTION, CanConnect)
{
// we did specify wrong mysql details so this should throw.
json db_config = readin_config();
if (db_config.empty())
FAIL() << "Cant read in_config()";
xmreg::MySqlConnector::url = db_config["url"];
xmreg::MySqlConnector::port = db_config["port"];
xmreg::MySqlConnector::username = db_config["user"];
xmreg::MySqlConnector::password = db_config["password"];
xmreg::MySqlConnector::dbname = db_config["dbname"];
try
{
auto xmr_accounts = std::make_shared<xmreg::MySqlAccounts>(nullptr);
// try to connect again
// it should not perform the connection again, but just return true;
EXPECT_TRUE(xmr_accounts->get_connection()->connect());
}
catch(std::exception const& e)
{
FAIL();
}
EXPECT_TRUE(true);
}
/**
* Fixture that connects to openmonero_test database
* and repopulates it with known data for each test.
*/
class MYSQL_TEST : public ::testing::Test
{
public:
static void
SetUpTestCase()
{
db_config = readin_config();
if (db_config.empty())
FAIL() << "Cant read in_config()";
xmreg::MySqlConnector::url = db_config["url"];
xmreg::MySqlConnector::port = db_config["port"];
xmreg::MySqlConnector::username = db_config["user"];
xmreg::MySqlConnector::password = db_config["password"];
xmreg::MySqlConnector::dbname = db_config["dbname"];
db_data = xmreg::read("../sql/openmonero_test.sql");
}
protected:
virtual bool
connect(std::shared_ptr<xmreg::CurrentBlockchainStatus> _bc_status)
{
try
{
auto conn = std::make_shared<xmreg::MySqlConnector>(
new mysqlpp::MultiStatementsOption(true));
// MySqlAccounts will try connecting to the mysql database
xmr_accounts = std::make_shared<xmreg::MySqlAccounts>(_bc_status, conn);
}
catch (std::exception const &e)
{
std::cerr << e.what() << '\n';
return false;
}
return xmr_accounts->get_connection()->get_connection().connected();
}
virtual void
initDatabase()
{
mysqlpp::Query query = xmr_accounts
->get_connection()->get_connection().query(db_data);
query.parse();
try
{
ASSERT_TRUE(query.exec());
while(query.more_results())
query.store_next();
}
catch (std::exception &e)
{
std::cerr << e.what() << '\n';
throw e;
}
}
virtual void
SetUp()
{
current_bc_status = nullptr;
connect(current_bc_status);
initDatabase();
}
virtual void
TearDown()
{
xmr_accounts->disconnect();
}
static std::string db_data;
static json db_config;
std::shared_ptr<xmreg::MySqlAccounts> xmr_accounts;
std::shared_ptr<xmreg::CurrentBlockchainStatus> current_bc_status;
};
std::string MYSQL_TEST::db_data;
json MYSQL_TEST::db_config;
TEST_F(MYSQL_TEST, Connection)
{
EXPECT_TRUE(xmr_accounts != nullptr);
EXPECT_TRUE(xmr_accounts->get_connection()->get_connection().connected());
EXPECT_TRUE(xmr_accounts->get_connection()->ping());
}
TEST_F(MYSQL_TEST, Disconnection)
{
xmr_accounts->disconnect();
EXPECT_FALSE(xmr_accounts->get_connection()->get_connection().connected());
EXPECT_FALSE(xmr_accounts->get_connection()->ping());
}
string addr_57H_hex {"57Hx8QpLUSMjhgoCNkvJ2Ch91mVyxcffESCprnRPrtbphMCv8iGUEfCUJxrpUWUeWrS9vPWnFrnMmTwnFpSKJrSKNuaXc5q"};
// viewkey: 9595c2445cdd4c88d78f0af41ebdf52f68ae2e3597b9e7b99bc3d62e300df806
TEST_F(MYSQL_TEST, GetAccount)
{
ACC_FROM_HEX(addr_57H_hex);
EXPECT_EQ(acc.id.data, 129);
EXPECT_EQ(acc.scanned_block_height, 101610);
EXPECT_EQ(acc.viewkey_hash, "1acf92d12101afe2ce7392169a38d2d547bd042373148eaaab323a3b5185a9ba");
// try get data when disconnected
xmr_accounts->disconnect();
EXPECT_FALSE(xmr_accounts->select(addr_57H_hex, acc));
}
TEST_F(MYSQL_TEST, UpdateAccount)
{
ACC_FROM_HEX(addr_57H_hex);
// make copy of the orginal account so that we can update it easly
auto updated_account = acc;
updated_account.scanned_block_height = 555;
updated_account.scanned_block_timestamp
= DateTime(static_cast<time_t>(5555555));
EXPECT_TRUE(xmr_accounts->update(acc, updated_account));
// fetch the account data and check if it was updated
xmreg::XmrAccount account2;
ASSERT_TRUE(xmr_accounts->select(addr_57H_hex, account2));
EXPECT_EQ(account2.id.data, acc.id.data);
EXPECT_EQ(account2.scanned_block_height, 555);
EXPECT_EQ(account2.scanned_block_timestamp, 5555555);
// try ding same but when disconnected
xmr_accounts->disconnect();
EXPECT_FALSE(xmr_accounts->update(acc, updated_account));
}
TEST_F(MYSQL_TEST, InsertAndGetAccount)
{
uint64_t mock_current_blockchain_height = 452145;
uint64_t mock_current_blockchain_timestamp = 1529302789;
bool mock_generated_locally {true};
DateTime blk_timestamp_mysql_format
= mysqlpp::DateTime(static_cast<time_t>(
mock_current_blockchain_timestamp));
// address to insert
string xmr_addr {"4AKNvHrLG6KKtKYRaSPWtSZSnAcaBZ2UzeJg7guFNFK46EN93FnBDS5eiFgxH87Sb7ZcSFxMyBhhgKBJiG5kKBBmCY5tbgw"};
string view_key {"f359631075708155cc3d92a32b75a7d02a5dcf27756707b47a2b31b21c389501"};
string view_key_hash {"cdd3ae89cbdae1d14b178c7e7c6ba380630556cb9892bd24eb61a9a517e478cd"};
uint64_t expected_primary_id
= xmr_accounts->get_next_primary_id(xmreg::XmrAccount());
xmreg::XmrAccount new_account(mysqlpp::null,
xmr_addr,
view_key_hash,
mock_current_blockchain_height, /* for scanned_block_height */
blk_timestamp_mysql_format,
mock_generated_locally,
mock_current_blockchain_height);
int64_t acc_id = xmr_accounts->insert(new_account);
EXPECT_EQ(acc_id, expected_primary_id);
xmreg::XmrAccount acc;
bool is_success = xmr_accounts->select(xmr_addr, acc);
ASSERT_TRUE(is_success);
EXPECT_EQ(acc.id.data, expected_primary_id);
EXPECT_EQ(acc.scanned_block_height, mock_current_blockchain_height);
EXPECT_EQ(acc.scanned_block_timestamp, mock_current_blockchain_timestamp);
EXPECT_EQ(acc.viewkey_hash, view_key_hash);
// now try inserting same account. it should fail
acc_id = xmr_accounts->insert(new_account);
EXPECT_EQ(acc_id, 0);
// try doing same but when disconnected
xmr_accounts->disconnect();
acc_id = xmr_accounts->insert(new_account);
EXPECT_EQ(acc_id, 0);
}
TEST_F(MYSQL_TEST, GetNextPrimaryIdFailure)
{
xmr_accounts->disconnect();
EXPECT_EQ(xmr_accounts->get_next_primary_id(xmreg::XmrAccount()), 0);
}
// stagenet tx: 4b40cfb2fdce2cd57a834a380901d55d70aba29dad13ac6c4dc82a895f439ecf
const string tx_4b40_hex {"0200010200089832f68b01b2a601a21ec01da83ffe0139a71678019703665175d1e067d20c738a8634aeaad6a7bc493a4b5a641b4962fa020002fb1d79f31791c9553c6dc1c066cde2361385021a5c33e7101d69a557cc3c34a1000292b1073ac7c2fdd851955e7fb76cbc7de4e812db745b5e795445594ea1c7d2a721010a9e82db48149442ac50cff52a39fda95f90b9683098b02e413a52b4d1f05f1c0180f3a3f93aaac0d8887ce542c01e49afbaf1f5ac8e1e4c8882011dd83fa33d1c9efa5f210d39e17c153a6a5825da329dcb31cd1acae98961d55038fb22e78fb93b95e6820a6904ff5b7bbfcf0cd1f6b9e9dd56f41062c7f5f43d9e1b3d69724eeca4bc3404a41ff0669f7f8ae725da8bbc2f8d0411605d2c3e959e3099414ffce1654418020d6ee74bb25042045e955b966e060a9f65b9cfccfbdcb4ee3101019a51f3a41372414c90383c9b84fb4ac690047ea67d70c917192abeb1fdf6c618aeafc732ae9a3e6c6f7fb274240ca04d24035a1d55b3fd1060dc3f4e64f9816868f36d2a0aeb76b64169bc9525d7d70b077c8b998b1204c6108e2917af893b0de24f4adb043eee433b096db8ef730de6e339a84f966b80b239821f350e2a8b10817fc19508da4f82bcb90fcf84cd47929ab1ba90bde5d252767736a4b23d26063cc6b2120dc636b2d4e3e7b3f6d7448882e01c10cf7bdd2117710dc49a59b49cf99212800093da22a6ab5bf693a80d4a662f35259f088a91a26ac261980c537238daa7a40477871f7481973edbcc86fa4885a4061d5c889d0986b4c0cb394165d4039081069f61cff822c7a227474d1609dbf05909f738803834b9e1b5ee68dcb825fcd906d880684e5fa684c8cb02495530fcaeeb35a405345f352ef3c8cf276c096d4303ee14cc0a48533afd1bcdf32dcfb25db4c45a19b10926dff72ace2c2a1d0759090acff99ad06e3f81c4d759a9f74d47fff9cb61d3784aa0eb57a250eec8d14800b85026f5b112740e2e8c257541bdfa4ea1f166b9d930e9705fa1d3f3c2be1e0fb242394d9230c7c457fc8422a6f919a06df5c52d954fa1bfdb57a0a2778d35020ef07490fc3c4f6e99ceaef97fcb3da049898944f3291b96a4f9ce491654340414565db2e0c6bd13eab933194b32336c09c478689cc4a7160b63ecb59937b2028e1649744c6ea69db01aed72fb8b39519cb28d764f158789cc539e01fd5f8f098597c8977e6d2b22c37b289c95dca13bece9e28f741ae2384ead8f0d6df7c30f311210523cb0b7e8c1173aee311362282f3c7d06ae2153969d073bec14ff3605d193bfe829e110df39b894fc4a8eb462d357098688748d579c85f9dc9e9cd20229c9865bc54ae8338433247c28875249e37d4d9b9ccbad611ce5948f1c7ea00fccdc41a9fbe942539a44111f160c9b1dc2653ecae0e4c30bada58d9164fa4c021b60fc0e2068510ef8ec56f7c8e036f2eb31ae0871c9a6aff7b8ad6a86054a06daf06393871f41859f51165f09d22fedd8a2326099a803491dbff5027f72540ed6981f505d1162d86c1ec716758bfbf4e1bfdbbe628b9340942a328209c86b0ec71981c90b407b146cbf065cfd8b0a1c2528aaf007c505a83779dacf8cb7500577a1f8f4a2c9a833d08b254c0c5edbbe87c9eaf266627d23bf518373dceba4099c13c6c468b99c16d56ea5eec12620867fdeb01be66bb0248a7ab7dd6434aa042392c4482e8694292bfc638f1a344d35c9cbfe121a25d2302db4db9688285905fcef9a892593840fe2ddebf0e059e341b2e7f107ee6a19fe386e3f9ea0da2801c5e9fe1b9c4b21155f6f2194ef36f2383097f9cf7ee0994873cfd92d098a33006547ef67bbeb2c1386fcbeec6f0b974532f2ac6e474b26683a37ed3919ec3108b578d3a552c32a362c0bea8bfe35c481f014721af9503a0663d95f5aa91b8802c32f60dbaa65978ad114a2fd45901a07fb4dded61d19e30c8c11e4efbdc1180a02d08d05a646bd8a4d160203da8d490ae0a0b4e631280401d635eb78e0416408c208436dcd653c11a75f365e2d012e0e69f0d4fe2fb2997726dad29468109001ed7c65464ba734e4b35f2ac85a4437fcafe0cdb6128e634970ba420e2e3296080636520e9fbf453e07cdd215117a2eeffed5a0ea0003761f5eb4c35aebf87b063f59d0571e149dc9d0c143a59415a7fe950d34b5024087145969abdc7f7140079bc25119825dda1bf080150bd40142d9635fd87e5dc691899d2686ccf6c9d106c7cdbf783fbbc83fc0feebe8abee3b458e7417a385215f1f89a2a89bef3b870c7a30a6cf4920ddd6eb50439c95c1f38fec867a41e628415ed142b7014991fd0818e8cf725b7075498e773790ccc882db0eb22453f0c9931debfb8d3adb09370f30e62b5fe94ffa7e55ff053488ad48f6e244ed6f043fae8f2225a024800c690ce15dd8017457d23c834b276d079d4a141f22db8fed4ea8f1e378fb741a2da30c09abc817ef0ad589428f966b8bdf92fb32fefa67f425ef1c58a2d4c881e8cc0156519256b87736ed84691b585687971c01a23da37ab76726602a01e771d9820add53f62168d51c7ec12ede030b61155f12e7c8d5573985a9e0884bcc41e0b50aa066b3337f2ab8e3b1031a1c843700413ef03d3734536547fc636055f5d15b0f804b3d25f90e4aaf199ee666d90199d0781526bb2040144b5a638411c1067d0bc5e3ef1911c5223fb0f5d0ce6387702b6957f9466b1a8be6879b8c7190ec1e0662cda6005a363f5d3d4585e6d9d15349be797353179b0a713b925dddfbd05609430601339bf31226cce63c763d887364aa6f1d640892f2a074338b741b7c3303e62c6fc16f544ceeed251dbaed83
TEST_F(MYSQL_TEST, SelectSingleTx)
{
TX_AND_ACC_FROM_HEX(tx_4b40_hex, addr_57H_hex);
xmreg::XmrTransaction mysql_tx;
xmr_accounts->tx_exists(acc.id.data, tx_hash_str, mysql_tx);
EXPECT_EQ(mysql_tx.hash , tx_hash_str);
EXPECT_EQ(mysql_tx.prefix_hash, tx_prefix_hash_str);
EXPECT_EQ(mysql_tx.total_received, 0);
EXPECT_EQ(mysql_tx.total_sent, 100000000000000);
EXPECT_EQ(mysql_tx.blockchain_tx_id, 93830);
EXPECT_TRUE(static_cast<int>(mysql_tx.spendable) == 1);
EXPECT_TRUE(static_cast<int>(mysql_tx.coinbase) == 0);
EXPECT_TRUE(static_cast<int>(mysql_tx.is_rct) == 1);
EXPECT_TRUE(static_cast<int>(mysql_tx.rct_type) == 1);
EXPECT_EQ(mysql_tx.payment_id, string{});
EXPECT_EQ(mysql_tx.mixin, 8);
// try doing same but when disconnected
xmr_accounts->disconnect();
EXPECT_FALSE(xmr_accounts->tx_exists(acc.id.data, tx_hash_str, mysql_tx));
}
// existing address
string owner_addr_5Ajfk {"5AjfkEY7RFgNGDYvoRQkncfwHXT6Fh7oJBisqFUX5u96i3ZepxDPocQK29tmAwBDuvKRpskZnfA6N8Ra58qFzA4bSA3QZFp"};
// stagenet wallet: boxes smash cajun fences ouch hamburger heron pulp initiate hubcaps academy acumen weird pliers powder jive soil tissue skydive bygones nobody sifting novelty ounce sifting
// the list of txs containing our outputs and also when used in key images
// ./xmr2csv --stagenet -m -a 5AjfkEY7RFgNGDYvoRQkncfwHXT6Fh7oJBisqFUX5u96i3ZepxDPocQK29tmAwBDuvKRpskZnfA6N8Ra58qFzA4bSA3QZFp -v 3ee772709dcf834a881c432fc15625d84585e4462d7905c42460dd478a315008 -t 100000 -g 101610
// Txs associates with the stagenet address and viewkey are, based on the xmr2csv csv files
// Block_no Tx_hash
// 100938 efa653785fd536ec42283985666612eca961a0bf6a8d56c4c43b1027d173a32c
// 100939 00458128c40886b22d15cbf3c02fcbb1a0860cab654d81230dba216b50fe887d
// 100943 fc619eeccfa0626f4be78cb1002a232e0ae8c8be6826f800341977d23a5a8e1e
// 100943 9ba6fa1c6f0277651e38b9f076a2cf674d92d683beac42ad93db1f3cc429cffe
// 100948 da22b85e51644b7c5df30f65b33f4f00bb58278e8189f9073e0573eb6df1fc1f
// 100949 3fb5d474378431bfa1b01e61965dcd5a62e1753cb7b3064ba7adb98bcfd398cd
// 100964 ac715b386010bd95a506fde0ac0405aa8ad72080b1d7cef257b5b112d9ed84bb
// 100968 9bfe477f2df750dd31b2a3939b32a5017323586a11bad6cd81650cfd2d54113d
// 100985 380ff7683774c989c1fd7348b90cd37b76d68ee6f93bd5239ecc3bb3794030bf
// 100993 8901400e2cac9fa26a47a06d76c8c0ee499ff691df9d22bad2a0183943532040
// 101028 6e1368cd8c48636ee7a327c165fae95496a7098191398c950fe26031246287f1
// 101048 c3004a573547e5cd671c79a6f33f7907e2e6193d4abe47a3c5328f533b3d6cdc
// 101081 fc4b8d5956b30dc4a353b171b4d974697dfc32730778f138a8e7f16c11907691
// 101085 ad3f3d9ff1e2dd2145067950d68d24cbd53db6f9d771f0d275c33fd88e458cf0
// 101553 dcb792bba1da7a9872f9c36772ee8625282b1f144380288fbd8acb968f6de56a
// 101554 c8965d4f54de1e39033b07e88bb20cacaa725a0dc266444e2efde6f624b9245d
TEST_F(MYSQL_TEST, SelectAllTxsForAnAccount)
{
ACC_FROM_HEX(owner_addr_5Ajfk);
vector<xmreg::XmrTransaction> txs;
EXPECT_TRUE(xmr_accounts->select(acc.id.data, txs));
EXPECT_EQ(txs.size(), 16);
EXPECT_EQ(txs[0].hash , string{"efa653785fd536ec42283985666612eca961a0bf6a8d56c4c43b1027d173a32c"});
EXPECT_EQ(txs.back().hash, string{"c8965d4f54de1e39033b07e88bb20cacaa725a0dc266444e2efde6f624b9245d"});
// try ding same but when disconnected
xmr_accounts->disconnect();
EXPECT_FALSE(xmr_accounts->select(acc.id.data, txs));
}
// stagenet fc4b8d5956b30dc4a353b171b4d974697dfc32730778f138a8e7f16c11907691
string tx_fc4_hex {"020001020007ae8c01df25afec02bd15ba0bb405b20117d3a9c98911f1a4a400d141164449ec5355618c0f5e0daf110dff3ada0c819d02000229f2fd7ca2af272b850887ad29157dca35ff2453c7ea3f972a084de55cdb7fa50002ef172599c1758c46ebf2c79c770c8a54dddcd548b7d2753d6338d25747ae29862101011f34ac725f4832faa17b2a5232cee54ce97bd75b91e6622f4652d92b68c0140180e4abe5e701bcb1b544a76c414d1422b33fce35b4b71459922e1243b2fd0e4483e440486106491c2ecbaad46eb10e88657e8512cd8bd92531144aef6d53ee0d44946c4c0800e7b4486bce9d83d7544f7b41c91de608065ae2161d0711684bda35bfdc673305e32806113437b948f5a2675ef2b855023e318edf836cca8021dbdf8360204b036fda13a11780d40c6bc4539883151dc455bde739a676214ada553981880f22d8db1008d6fa3fca2181c0d4773b3048074f25dc925aa2d7f930b9cc09e38510fba12d161394113f12ac6c0445413d0165a13aa4cd6c55cc3a722d64cafcae6209fda513bc778ce07a2b263938866a1a8d50f44b70a4a1ca8bea6119f109744402c739bae72c3e61a1eb91e762bb89c35d3c61ce699177c047811511c97d80340532893a242d12771207e5a110a417dd13ac8d313c9777050d236f5ca69e70120f0b44bec7777ce71e2b6f9d8bf7df3cfe41610f923179b5d9609ad8cdafb05c0052e66336de3877209b02a50a4858d3019cf35739f71196938d544e81eaa05206f863386c6622f61fee4b24f8584923e0d2a93a0876d26fcfce792150214e570037e5965fdf76c6c6d9ded1197a483999c10eb99693ed2f80fcce3ee99593cc0aba40964b8533ff60214022e66f62905ba226013193a95bdca25358bf911f610da27a07eac4d06909d8e367bdc69a8da0106d13aed43bebaba5df4b35c6d9750210309523e1036fe255df408a8ba30a9a8780076b86371fb4ee65cdb491fe620fa7e57cb715b116ea18f16e5e240b6105e12ea5ee0fac73aeae97e1eb43455704a32fe4ca237f6c84ba78edcb1048c4daeefedb8a6e464fc790ce1bcf5fd654074e5ff5b36b2172e0bdf57a0c72d5bbf1a1bedb1ceb30f6a62adcdf399101cf0f41a85968972c1eb82e65a72d5f23348809f92fa4cff546ef1aaea0ca163fe20bd33e655de3ea6808c96883d40c8625989736a48f83cf873188a14bb17a8d2b0776c942297e6679fd43cdac69adc24ab14ff8612c528fc3ecccbf465953b0dd0fd59389d9c48ef22e2a71a3939fd377b41f6ef681c5cb0236e12927d2734f9808636e85ad5b79464b4ef62483bb25989b41a2b806934cf1f4c9a49b524084880d70e6f28f8815c8bc2391014628d261c77d5dcde5fe5eb874e759a21deb7526082b34351d6c100c17d3b165b7f370fc2f38426ccf039c37e0990949b451e0c3034a2a14009589a0e84a0aaf6479a754b2eae4a95fa4ef5a50b20ac03ec97ac00982ebe4b8e946618189441e0e25bcbf04e058e2906a7d39bb780b5459053a6406a3ffdf9295f1dd95754489ab6b3f2545679ac83c23bda77d79a6936de33f5c0117618ecfb6187ee19e36447575203e52a953cc27aa61c8e3f847de8cee11e802622832d19e1c10442118a7fbbac64b06bb0e582571b68a7300bb23d6bf51bc05e928f61665f231df8e5f52aaff541b528228e5952071e6de61aaf27220bcee036cd82158e84bf97102e8781fecb09c8631c8075366a508fd8f66226c1fae030d1411f7f460411690c3d045dd2e27d1ff018ffa8fb5ff60b8b48db7023fdba7069a9bdef6abc8dbac81ca43faa7ed0005644dbd5eccfe62112614d6e88fcadd0fd9974b96116e6806104587ab2525f19942a717053e29ddb061ad5de7c84ab3012e80ed108a07bc8043813dc344a1e7f3d51fdca76d264c5bb88e6677f8f528065b89edc7a60e42cdab99a0df7b02213a17d0b486b31a07eac84a8f137d575e012b3ffe78178968e62fad7f4ba1f0c9a4764ad2966f68853011f3654d33256102a6c07c96f6f24e2cd8ff9cee472d1a6a55f45b4f3447247b2e131eb86cc79f085a5372ccf515171cb896c2896dbb4492705eef30b7b59a5c655044840ea7d20737968d6e6d9753d911e6eff2bff6df2013d9834ee9948cb5bdc8abe440152b0b3c03383bbb0c079eeb00d263b96d6ea26fc03925e2aea829a07d454982d7a2017699ec3d8a905e0bf444d9696b33a2172485f2657d278aafafac4eee51f9bb00e9378d1e9bbc2267eb8522cd0aef3eb085c91caa80fe2a8f446119c28dd6dd088910952e6735af40a10906e3ff61e7104c854f0f39be2d285475a342dd433b038a239729113d823adc339eec733876525fc7f0b4cc86fe136e919c5e10167703c4191a4b45f014a0e381f5c062c9b813da5936e7168b7f8a6b42fdb9567c8103ee9f3b273ed386e6a3eac4a39fa14527d9868e38a60f9523f2ede898ff9c1302963bfafe769ad670fe83703375e5f79dd8a921f23d3781ada2c8c3bb8ea97c028d5d359c3f04f2c67b1b4edb39a27c5a99f60be1cee63c01a67bd6e46e6970099b25b9b5d02a398cf081adb6bfecac60d6f25d242028d3916f3c67d72ce9510a5a61c32fc7f1ceecab43c8dbb1b4915b85aeafc7f4fcd9f87b3cc8a584e1f70cb18bed117c292671af9979f9081dc067b1209ff24c35e6c6393eb6c404365b0980b94ccef498362d27c6d8eec2d3b7ada754006ab34eecab5dd8a3cb1dfcb1003263d2a77ba3a97c57a276d24327a0880dbdd9cb0e85e390acd6e487ea979c0b220da3dea14e114750bfd94f92e8e61f8d47d40828f84d1a4affbe1b21c129025697c06938038f90a9ca6995008ff45e5a0
// for different account we can have same tx in the Transaction table
string addres_of_different_acc {"57hGLsqr6eLjUDoqWwP3Ko9nCJ4GFN5AyezdxNXwpa1PMt6M4AbsBgcHH21hVe2MJrLGSM9C7UTqcEmyBepdhvFE4eyW3Kd"};
// seed: fall lava tudor nucleus hemlock afar tuition poaching waffle palace roped nifty wipeout fierce mystery thumbs hubcaps toffee maps etiquette jolted symptoms winter abyss fall
string addr_55Zb {"55ZbQdMnZHPFS8pmrhHN5jMpgJwnnTXpTDmmM5wkrBBx4xD6aEnpZq7dPkeDeWs67TV9HunDQtT3qF2UGYWzGGxq3zYWCBE"};
TEST_F(MYSQL_TEST, TryInsertingExistingTxToSameAccount)
{
// we should not be able to insert same tx twice for the same account
TX_AND_ACC_FROM_HEX(tx_fc4_hex, owner_addr_5Ajfk);
xmreg::XmrTransaction tx_data;
tx_data.hash = tx_hash_str;
tx_data.account_id = acc.id.data;
// rest of fields is not important
uint64_t tx_mysql_id = xmr_accounts->insert(tx_data);
// if zero than the insert failed
EXPECT_EQ(tx_mysql_id, 0);
}
TEST_F(MYSQL_TEST, TryInsertingExistingTxToDifferentAccount)
{
// we should be able to insert same tx to different account
// even though it exisits already for other account
TX_AND_ACC_FROM_HEX(tx_fc4_hex, addres_of_different_acc);
xmreg::XmrTransaction tx_data;
tx_data.id = mysqlpp::null;
tx_data.hash = tx_hash_str;
tx_data.account_id = acc.id.data;
// rest of fields is not important
uint64_t expected_primary_id = xmr_accounts->get_next_primary_id(tx_data);
uint64_t tx_mysql_id = xmr_accounts->insert(tx_data);
EXPECT_EQ(tx_mysql_id, expected_primary_id);
}
TEST_F(MYSQL_TEST, IfTxExistsForInOnwnerAccount)
{
TX_AND_ACC_FROM_HEX(tx_fc4_hex, owner_addr_5Ajfk);
xmreg::XmrTransaction tx_data;
EXPECT_TRUE(xmr_accounts->tx_exists(acc.id.data, tx_hash_str, tx_data));
}
TEST_F(MYSQL_TEST, IfTxExistsForInNoneOnwnerAccount)
{
TX_AND_ACC_FROM_HEX(tx_fc4_hex, addres_of_different_acc);
xmreg::XmrTransaction tx_data;
EXPECT_FALSE(xmr_accounts->tx_exists(acc.id.data, tx_hash_str, tx_data));
}
TEST_F(MYSQL_TEST, DeleteExistingTx)
{
// tx hash fc4b8d5956b30dc4a353b171b4d974697dfc32730778f138a8e7f16c11907691
TX_AND_ACC_FROM_HEX(tx_fc4_hex, owner_addr_5Ajfk);
xmreg::XmrTransaction tx_data;
ASSERT_TRUE(xmr_accounts->tx_exists(acc.id.data, tx_hash_str, tx_data));
uint64_t no_of_deleted_rows = xmr_accounts->delete_tx(tx_data.id.data);
EXPECT_EQ(no_of_deleted_rows, 1);
// try ding same but when disconnected
xmr_accounts->disconnect();
EXPECT_EQ(xmr_accounts->delete_tx(tx_data.id.data), 0);
}
string tx_1640_hex {"020002020007d08602b5019318990e8e469607ac6645d3cf7b4f5db9d614602e9e956c63c35cf3da6f7b93740c514e06c898fb0da2020007bb76e15af107934aa55f8156b6163ef54482411c54a280081a87fd35e542b3b8906b702123c55468e71dd620d3a402000254b5891ba8c1de2419bcc877383f004929e01a8ef8f9b5ae87549c5a5284d7710002a9d876b01eb972db944b78899b4c90c2b66a3c81fe04bf54ff61565f3db534194201cbfd2dec16b9cb35c8b5177e18615e7273b2bd43517dca8bd9ec9aaae6b7f67d01cbfd2dec16b9cb35c8b5177e18615e7273b2bd43517dca8bd9ec9aaae6b7f67d0280fa9b98fd01d82bde315b0324aa236d87c7dd34bee321eef33186febc0a38d0d57090027dfa03aa67466407567b7f8c1fa4587c003fe89426787b1a96f30e4a2a010fc685a095aa65eb5c3fac215aaab75565381a0721d50199fb902f58bf0dbc7a19f9ef086da5fd12a08dd89ab63e8becfffc1b2ad6510e4753b06191092e0ff159d18202a80d1e7a2ac0ff89f7151e1d8736b4a4b720464a262f52bba0c2ffa5355b3a0bbd5a5a87a2610c12d2edc410d2d26fc855c1ea3ce211e19881a4bc79b7ef28045951e126e8a05f6d69a9736691988eab8d711501f8b9098d9e4338c1da65da4fdadad568ed09dd2ce4f22b8375bc3c8fb7391af13ad24d34eed99cc61977a853d1f98016ed8610632bbcc6c31257359858afe724492953d2580973518efd1003e906f2c04ba82f9a758e2c79b9bf9741af8ad259357e31935fcd33c02167bf0bbebecf0529db992fd3634a165407ed6cabdfe53c794f0070ffc0a2f862ea720908986e1b8c458e8d3782b22ecfc230df2e10686b3c4ac2f801e308a248485e0d2d005cc47dfc92da9d5b57202e1a267784d98bcb2bc385fd8d6b119ee2ce7e0c14a7991413bc310871d53fcbe2d863c074d136ef4b912e1a93d00c92f777cd024bf4b84ba5688b84ef989a3cf56db681bf973dff7149610fc9c4f901f0b2bb0589cf064b9da57fc5506dbc058a76d7a960bd489c22dd58290b552359d53e6e0bbcc2443684d6410ce8f0c480f719532022a52cd0dbe87d8feb81a2180e45e90b30fa0ca3b81d6ad3940d78a181691c427c4211042b556a054388163b49ee4b0a188d4fa530af830ad5bacfc6333e33943af4b4b8d7c34293d52bb0e5a6259a06b2a31ee6529d55860ccb9b6b087bcde693afc82cb76eda4b981f8593e78bf703d2cdbcf3e2ac02b0ec66ce864ed5f00ca70acacaf87530b3d87289b45db3b007a080e9cff29bd7fd27d5ad5e978ab0eac1a4b789a942b8f37639cd8df0787a023e1d32610f6d775262974b398bfca302c6c43bbcf9b27b2796fd1cf7d135c801f55ca6595183f79d8ec32a1bcb5a61314952b73ed488fa77622cb3d3cb7b43049af38ce804cdfd5055c4368ffd8ddbf83ac71da0949079bae68ecd699216ea086b4e32de20a89284cee23058ecb2537719fd1c5d9979d88242a1473e58b91e016905d79511ab3ea90aca5722982099cac5e143ccea4d9cd0aba68d3196170c007a28fd08646dbb02c60e37a85e978e60dc5367322572c9af86f60a4e7893000d5c6acb5a1463bc3b114f14a00679b3bcda4d9f4ecbe12879c83f51debad5d6044905edef20946562bfc928e0dbc504b266dbeda3f8d7a4e1adf26019176626010a0e53a56cc387bae895f22d8dde4e4dc07a8cac57dfcb974c225e94462ae100b5fb06aa5f8829d9d8c318f0e60a609c9a5b0b5646471b939044458df98f33095e034929c8095cf28ea4fa2f515161e007b7f63ce164f7150ebe7df571ee1a0abe14e63260d891f8d800019fb32b6b421b683b9dcfe739bf3e85c1125a59890f6259f127ef8aa309f226506cbdc7e0362d327c01b24d4897c42fbc9c7b7fd101287dd6c1576e4db50eeaf9512902d880e05bace368d83cd0a3ed44fa9bfb0706a7429addc2491fb0325bb19c8996637c307851374e7d27dc09e779349c2c06043b5efd3a3cd045e5fad7e1735dceaadbac2e08189e2b1e2138fdf1ff783fb3093d0486430d62adc0687fbf8547765ce63ef4d637fda88836882bc6fbcf723000c84457bac63973793bce419d5a2f3b2b6b72c84e8dfdd8799a3c2d37f81b0607f8a09809afd99e51262b5e372278553504bb5862f7b2a57d05296c1bca79b407d1c88c875e7f7212c38b64826a83ac2fcce37888b86a870eeccfb35f4042470e3d0ef3a4fcf02c645644e33641de834ab3d37315dc3f508580f6734e1df9e10fd368a0cd8a4e58c5d259dce025ebb299478712e9ffde3ecbc67e71d3c9eaa20f898829cdc7bb2ffc041df360d14bc683ebbc62c6995fd2ae5b99b433dc18ca05dc05710159dfaf2b85f65c1949e9ba64efd068dc1626d7ac3899d0770d083f01818867a3d18b531cd7d46630e9f9582e30e6d8977cfe02ee48032b84f2bfc908cb21db8ddf71d64bff7a67f605801d5903fdf6c7bd76ed1a7842c2be672d6a0bc3f4b7aecab3203cfafff53b4647650db10c3af55521491c31b57e9581a7410d432303747fc20fd0d34b978450df1448a50f5a83a5b1598fdc0964e9501dff0cd345f2adedf34a0772970e5ea30c6c30671b49721dad3ef863beb92d89513b0b3c5190b4293c1f7a90f93f53cee4c4ed02b55d6c7c7450f04a81cc4f663ab80828a65d7342c17d17dd366c6db0b05d58a9be78ff2428ae878ba4ca7091b1910b120408bc946c2c0f6195e5a884b3399cec920d2117ebe56d759b51d5b4d838048a4322bfa22daaa42a5b7d9c2ec7682926e5e8473335905a440b50b4110f6a051a8709754281fec21f7a9252e989dc127c489fcef630d7d12c99b34e0fa10101
// tx hash 1640236fe817f83b0bd2082c655d152be390e4f78e41db5b935bb8a53249fe8c
TEST_F(MYSQL_TEST, DeleteExistingTxAndAssociatedOutputsAndInputs)
{
// removing a tx should automatically remove its outputs and inputs
// from mysql. we have constrans doing this, so we check here if
// they work as we think they do
TX_AND_ACC_FROM_HEX(tx_1640_hex, addr_57H_hex)
xmreg::XmrTransaction tx_data;
ASSERT_TRUE(xmr_accounts->tx_exists(acc.id.data, tx_hash_str, tx_data));
uint64_t no_of_deleted_rows = xmr_accounts->delete_tx(tx_data.id.data);
ASSERT_EQ(no_of_deleted_rows, 1);
// this tx has 1 output and two key images.
//
// output: a9d876b01eb972db944b78899b4c90c2b66a3c81fe04bf54ff61565f3db53419
// key1: 45d3cf7b4f5db9d614602e9e956c63c35cf3da6f7b93740c514e06c898fb0da2
// key2: 3ef54482411c54a280081a87fd35e542b3b8906b702123c55468e71dd620d3a4
// so we expect those to be also deleted after tx has been deleted
vector<xmreg::XmrOutput> outputs;
bool is_success = xmr_accounts->select_for_tx(tx_data.id.data, outputs);
// if no outputs found, we return false
EXPECT_FALSE(is_success);
EXPECT_EQ(outputs.size(), 0);
vector<xmreg::XmrInput> inputs;
is_success = xmr_accounts->select_for_tx(tx_data.id.data, inputs);
// if no inputs found, we return false
EXPECT_FALSE(is_success);
EXPECT_EQ(inputs.size(), 0);
}
TEST_F(MYSQL_TEST, DeleteNoNExistingTx)
{
uint64_t some_non_existing_tx_id = 7774748483;
uint64_t no_of_deleted_rows
= xmr_accounts->delete_tx(some_non_existing_tx_id);
EXPECT_EQ(no_of_deleted_rows, 0);
}
TEST_F(MYSQL_TEST, MarkTxSpendableAndNonSpendable)
{
TX_AND_ACC_FROM_HEX(tx_fc4_hex, owner_addr_5Ajfk);
xmreg::XmrTransaction tx_data;
ASSERT_TRUE(xmr_accounts->tx_exists(acc.id.data, tx_hash_str, tx_data));
// this particular tx is marked as spendable in mysql
EXPECT_TRUE(static_cast<bool>(tx_data.spendable));
uint64_t no_of_changed_rows
= xmr_accounts->mark_tx_nonspendable(tx_data.id.data);
EXPECT_EQ(no_of_changed_rows, 1);
// fetch tx_data again and check if its not-spendable now
ASSERT_TRUE(xmr_accounts->tx_exists(acc.id.data, tx_hash_str, tx_data));
EXPECT_FALSE(static_cast<bool>(tx_data.spendable));
// mark it as spendable
no_of_changed_rows = xmr_accounts->mark_tx_spendable(tx_data.id.data);
EXPECT_EQ(no_of_changed_rows, 1);
// fetch it again, and check if its spendable
ASSERT_TRUE(xmr_accounts->tx_exists(acc.id.data, tx_hash_str, tx_data));
EXPECT_TRUE(static_cast<bool>(tx_data.spendable));
// try ding same but when disconnected
xmr_accounts->disconnect();
EXPECT_EQ(xmr_accounts->mark_tx_spendable(tx_data.id.data), 0);
}
TEST_F(MYSQL_TEST, GetTotalRecievedByAnAddressWhenDisconnected)
{
ACC_FROM_HEX(owner_addr_5Ajfk);
uint64_t total_recieved;
xmr_accounts->disconnect();
EXPECT_FALSE(xmr_accounts->get_total_recieved(acc.id.data, total_recieved));
}
// now we can test total number of incoming xmr (only outputs)
// for serveral addresses. For this we can use
// parametrized fixture
// addr, expected recieved xmr
using address_incoming_balance = std::pair<string, uint64_t>;
class MYSQL_TEST_PARAM :
public MYSQL_TEST,
public ::testing::WithParamInterface<address_incoming_balance>
{};
TEST_P(MYSQL_TEST_PARAM, GetTotalRecievedByAnAddress)
{
auto const& own_addr = GetParam().first;
auto const& expected_recieved = GetParam().second;
ACC_FROM_HEX(own_addr);
uint64_t total_recieved;
EXPECT_TRUE(xmr_accounts->get_total_recieved(acc.id.data, total_recieved));
EXPECT_EQ(total_recieved, expected_recieved);
}
INSTANTIATE_TEST_CASE_P(
RecivedXmrTest, MYSQL_TEST_PARAM,
::testing::Values(
make_pair(owner_addr_5Ajfk, 697348926585540ull),
make_pair(addr_55Zb , 1046498996045077ull)
));
auto
make_mock_output_data(string last_char_pub_key = "4")
{
xmreg::XmrOutput mock_output_data ;
mock_output_data.id = mysqlpp::null;
// mock_output_data.account_id = acc.id; need to be set when used
mock_output_data.tx_id = 106086; // some tx id for this output
mock_output_data.out_pub_key = "18c6a80311d6f455ac1e5abdce7e86828d1ecf911f78da12a56ce8fdd5c716f"
+ last_char_pub_key; // out_pub_key is unique field, so to make
// few public keys, we just change its last char.
mock_output_data.tx_pub_key = "38ae1d790bce890c3750b20ba8d35b8edee439fc8fb4218d50cec39a0cb7844a";
mock_output_data.amount = 999916984840000ull;
mock_output_data.out_index = 1;
mock_output_data.rct_outpk = "e17cdc23fac1d92f2de196b567c8dd55ecd4cac52d6fef4eb446b6de4edb1d01";
mock_output_data.rct_mask = "03cea1ffc18193639f7432287432c058a70551ceebed0db2c9d18088b423a255";
mock_output_data.rct_amount = "f02e6d9dd504e6b428170d37b79344cad5538a4ad32f3f7dcebd5b96ac522e07";
mock_output_data.global_index = 64916;
mock_output_data.mixin = 7;
mock_output_data.timestamp = mysqlpp::DateTime(static_cast<time_t>(44434554));;
return mock_output_data;
}
TEST_F(MYSQL_TEST, SelectOutputsForAccount)
{
// select all outputs associated with the given account
ACC_FROM_HEX(owner_addr_5Ajfk);
vector<xmreg::XmrOutput> outputs;
ASSERT_TRUE(xmr_accounts->select(acc.id.data, outputs));
// can use this command to get list of outputs
// ./xmr2csv --stagenet -m -a 5AjfkEY7RFgNGDYvoRQkncfwHXT6Fh7oJBisqFUX5u96i3ZepxDPocQK29tmAwBDuvKRpskZnfA6N8Ra58qFzA4bSA3QZFp -v 3ee772709dcf834a881c432fc15625d84585e4462d7905c42460dd478a315008 -t 90000 -g 101610
EXPECT_EQ(outputs.size(), 9);
}
TEST_F(MYSQL_TEST, SelectOutputsForTransaction)
{
// select all outputs associated with given transaction
// tx hash 1640236fe817f83b0bd2082c655d152be390e4f78e41db5b935bb8a53249fe8c
TX_AND_ACC_FROM_HEX(tx_1640_hex, addr_57H_hex)
xmreg::XmrTransaction tx_data;
ASSERT_TRUE(xmr_accounts->tx_exists(acc.id.data, tx_hash_str, tx_data));
vector<xmreg::XmrOutput> outputs;
bool is_success = xmr_accounts->select_for_tx(tx_data.id.data, outputs);
ASSERT_TRUE(is_success);
EXPECT_EQ(outputs.size(), 1);
EXPECT_EQ(outputs[0].out_pub_key, "a9d876b01eb972db944b78899b4c90c2b66a3c81fe04bf54ff61565f3db53419");
// now use output_exists
xmreg::XmrOutput out;
EXPECT_TRUE(xmr_accounts->output_exists(outputs[0].out_pub_key, out));
EXPECT_EQ(outputs[0], out);
// use output_exists on non-exisiting output
string non_exist_key {"a9d876b01eb972db944b78899b4c90c2b66a3c81fe04bf54ff61565f3db53000"};
EXPECT_FALSE(xmr_accounts->output_exists(non_exist_key, out));
xmr_accounts->disconnect();
EXPECT_FALSE(xmr_accounts->output_exists(non_exist_key, out));
}
TEST_F(MYSQL_TEST, InsertOneOutput)
{
ACC_FROM_HEX(owner_addr_5Ajfk);
xmreg::XmrOutput mock_output_data = make_mock_output_data();
mock_output_data.account_id = acc.id.data;
uint64_t expected_primary_id
= xmr_accounts->get_next_primary_id(mock_output_data);
uint64_t inserted_output_id = xmr_accounts->insert(mock_output_data);
EXPECT_EQ(inserted_output_id, expected_primary_id);
// now we fetch the inserted output and compare its values
xmreg::XmrOutput out_data2;
EXPECT_TRUE(xmr_accounts
->select_by_primary_id(inserted_output_id, out_data2));
EXPECT_EQ(out_data2.tx_id, mock_output_data.tx_id);
EXPECT_EQ(out_data2.out_pub_key, mock_output_data.out_pub_key);
EXPECT_EQ(out_data2.tx_pub_key, mock_output_data.tx_pub_key);
EXPECT_EQ(out_data2.amount, mock_output_data.amount);
EXPECT_EQ(out_data2.out_index, mock_output_data.out_index);
EXPECT_EQ(out_data2.rct_outpk, mock_output_data.rct_outpk);
EXPECT_EQ(out_data2.rct_mask, mock_output_data.rct_mask);
EXPECT_EQ(out_data2.rct_amount, mock_output_data.rct_amount);
EXPECT_EQ(out_data2.global_index, mock_output_data.global_index);
EXPECT_EQ(out_data2.mixin, mock_output_data.mixin);
EXPECT_EQ(out_data2.timestamp, mock_output_data.timestamp);
xmr_accounts->disconnect();
EXPECT_FALSE(xmr_accounts->select_by_primary_id(inserted_output_id, out_data2));
}
TEST_F(MYSQL_TEST, TryToInsertSameOutputTwice)
{
ACC_FROM_HEX(owner_addr_5Ajfk);
xmreg::XmrOutput mock_output_data = make_mock_output_data();
mock_output_data.account_id = acc.id.data;
// first time insert should be fine
uint64_t inserted_output_id = xmr_accounts->insert(mock_output_data);
EXPECT_GT(inserted_output_id, 0);
// second insert should fail and result in 0
inserted_output_id = xmr_accounts->insert(mock_output_data);
EXPECT_EQ(inserted_output_id, 0);
}
TEST_F(MYSQL_TEST, TryToInsertSameOutputTwiceToDifferent)
{
ACC_FROM_HEX(owner_addr_5Ajfk);
xmreg::XmrOutput mock_output_data = make_mock_output_data();
mock_output_data.account_id = acc.id.data;
// first time insert should be fine
uint64_t inserted_output_id = xmr_accounts->insert(mock_output_data);
EXPECT_GT(inserted_output_id, 0);
xmreg::XmrAccount acc2; \
ASSERT_TRUE(xmr_accounts->select(addr_55Zb, acc2));
mock_output_data.account_id = acc2.id.data;
// second insert should fail and result in 0
inserted_output_id = xmr_accounts->insert(mock_output_data);
EXPECT_EQ(inserted_output_id, 0);
}
TEST_F(MYSQL_TEST, InsertSeverlOutputsAtOnce)
{
ACC_FROM_HEX(owner_addr_5Ajfk);
// create vector of several outputs to be written into database
vector<xmreg::XmrOutput> mock_outputs_data;
for (size_t i = 0; i < 10; ++i)
{
mock_outputs_data.push_back(make_mock_output_data(std::to_string(i)));
mock_outputs_data.back().account_id = acc.id.data;
}
uint64_t expected_primary_id
= xmr_accounts->get_next_primary_id(xmreg::XmrOutput());
// first time insert should be fine
uint64_t no_inserted_rows = xmr_accounts->insert(mock_outputs_data);
EXPECT_EQ(no_inserted_rows, mock_outputs_data.size());
// after inserting 10 rows, the expected ID should be before + 11
uint64_t expected_primary_id2
= xmr_accounts->get_next_primary_id(xmreg::XmrOutput());
EXPECT_EQ(expected_primary_id2, expected_primary_id + mock_outputs_data.size());
for (size_t i = 0; i < 10; ++i)
{
uint64_t output_id_to_get = expected_primary_id + i;
xmreg::XmrOutput out_data;
xmr_accounts->select_by_primary_id(output_id_to_get, out_data);
EXPECT_EQ(mock_outputs_data[i].out_pub_key, out_data.out_pub_key);
}
xmr_accounts->disconnect();
EXPECT_EQ(xmr_accounts->insert(mock_outputs_data), 0);
}
TEST_F(MYSQL_TEST, SelectInputsForAccount)
{
// select all inputs associated with the given account
ACC_FROM_HEX(owner_addr_5Ajfk);
vector<xmreg::XmrInput> inputs;
ASSERT_TRUE(xmr_accounts->select(acc.id.data, inputs));
// can use this command to get the list of ring members
// ./xmr2csv --stagenet -m -a 5AjfkEY7RFgNGDYvoRQkncfwHXT6Fh7oJBisqFUX5u96i3ZepxDPocQK29tmAwBDuvKRpskZnfA6N8Ra58qFzA4bSA3QZFp -v 3ee772709dcf834a881c432fc15625d84585e4462d7905c42460dd478a315008 -t 90000 -g 101610
EXPECT_EQ(inputs.size(), 12);
}
TEST_F(MYSQL_TEST, SelectInputsForTransaction)
{
// select all outputs associated with given transaction
// tx hash 1640236fe817f83b0bd2082c655d152be390e4f78e41db5b935bb8a53249fe8c
TX_AND_ACC_FROM_HEX(tx_1640_hex, addr_57H_hex)
xmreg::XmrTransaction tx_data;
ASSERT_TRUE(xmr_accounts->tx_exists(acc.id.data, tx_hash_str, tx_data));
vector<xmreg::XmrInput> inputs;
bool is_success = xmr_accounts->select_for_tx(tx_data.id.data, inputs);
ASSERT_TRUE(is_success);
EXPECT_EQ(inputs.size(), 2);
EXPECT_EQ(inputs[0].key_image, "45d3cf7b4f5db9d614602e9e956c63c35cf3da6f7b93740c514e06c898fb0da2");
EXPECT_EQ(inputs[1].key_image, "3ef54482411c54a280081a87fd35e542b3b8906b702123c55468e71dd620d3a4");
}
TEST_F(MYSQL_TEST, SelectInputsForOutput)
{
// select all inputs associated with given output
// i.e., where the output is used as a ring member
ACC_FROM_HEX(owner_addr_5Ajfk);
vector<xmreg::XmrOutput> outputs;
ASSERT_TRUE(xmr_accounts->select(acc.id.data, outputs));
// we check only for the first output
// for second output we should have three key images
// out pub key: 7f03cbcf4f9ddc763543959f0152bb5e66147359b6097bccf8fa0bbd748e1445
uint64_t output_id = outputs.at(1).id.data;
vector<xmreg::XmrInput> inputs;
ASSERT_TRUE(xmr_accounts->select_inputs_for_out(output_id, inputs));
EXPECT_EQ(inputs.size(), 3);
EXPECT_EQ(inputs.front().key_image, "00dd88b3a16b3616d342faec2bc47b24add433407ef79b9a00b55b75d96239a4");
EXPECT_EQ(inputs.back().key_image, "abc529357f90641d501d5108f822617049c19461569eafa45cb5400ee45bef33");
inputs.clear();
// for non exisitng output
ASSERT_FALSE(xmr_accounts->select_inputs_for_out(444444, inputs));
// try doing same when disconnected
xmr_accounts->disconnect();
EXPECT_FALSE(xmr_accounts->select_inputs_for_out(output_id, inputs));
}
auto
make_mock_input_data(string last_char_pub_key = "0")
{
xmreg::XmrInput mock_data;
mock_data.id = mysqlpp::null;
// mock_output_data.account_id = acc.id; need to be set when used
mock_data.tx_id = 106086; // some tx id for this output
mock_data.output_id = 428900; // some output id
mock_data.key_image = "18c6a80311d6f455ac1e5abdce7e86828d1ecf911f78da12a56ce8fdd5c716f"
+ last_char_pub_key; // out_pub_key is unique field, so to make
// few public keys, we just change its last char.
mock_data.amount = 999916984840000ull;
mock_data.timestamp = mysqlpp::DateTime(static_cast<time_t>(44434554));;
return mock_data;
}
TEST_F(MYSQL_TEST, InsertOneInput)
{
ACC_FROM_HEX(owner_addr_5Ajfk);
xmreg::XmrInput mock_input_data = make_mock_input_data();
mock_input_data.account_id = acc.id.data;
uint64_t expected_primary_id
= xmr_accounts->get_next_primary_id(mock_input_data);
uint64_t inserted_id = xmr_accounts->insert(mock_input_data);
EXPECT_EQ(expected_primary_id, inserted_id);
// now we fetch the inserted input and compare its values
xmreg::XmrInput in_data2;
EXPECT_TRUE(xmr_accounts->select_by_primary_id(inserted_id, in_data2));
EXPECT_EQ(in_data2.account_id, mock_input_data.account_id);
EXPECT_EQ(in_data2.tx_id, mock_input_data.tx_id);
EXPECT_EQ(in_data2.amount, mock_input_data.amount);
EXPECT_EQ(in_data2.key_image, mock_input_data.key_image);
EXPECT_EQ(in_data2.output_id, mock_input_data.output_id);
EXPECT_EQ(in_data2.timestamp, mock_input_data.timestamp);
}
TEST_F(MYSQL_TEST, InsertSeverlInputsAtOnce)
{
ACC_FROM_HEX(owner_addr_5Ajfk);
// create vector of several inputs to be written into database
vector<xmreg::XmrInput> mock_data;
for (size_t i = 0; i < 10; ++i)
{
mock_data.push_back(make_mock_input_data(std::to_string(i)));
mock_data.back().account_id = acc.id.data;
}
uint64_t expected_primary_id
= xmr_accounts->get_next_primary_id(xmreg::XmrInput());
// first time insert should be fine
uint64_t no_inserted_rows = xmr_accounts->insert(mock_data);
EXPECT_EQ(no_inserted_rows, mock_data.size());
// after inserting 10 rows, the expected ID should be before + 11
uint64_t expected_primary_id2
= xmr_accounts->get_next_primary_id(xmreg::XmrInput());
EXPECT_EQ(expected_primary_id2, expected_primary_id + mock_data.size());
for (size_t i = 0; i < 10; ++i)
{
uint64_t id_to_get = expected_primary_id + i;
xmreg::XmrInput out_data;
xmr_accounts->select_by_primary_id(id_to_get, out_data);
EXPECT_EQ(mock_data[i].key_image, out_data.key_image);
}
}
TEST_F(MYSQL_TEST, TryToInsertSameInputTwice)
{
// the input table requires a row to be unique for pair
// of key_image + output_id
ACC_FROM_HEX(owner_addr_5Ajfk);
xmreg::XmrInput mock_data = make_mock_input_data();
mock_data.account_id = acc.id.data;
// first time insert should be fine
uint64_t inserted_id = xmr_accounts->insert(mock_data);
EXPECT_GT(inserted_id, 0);
// second insert should fail and result in 0
inserted_id = xmr_accounts->insert(mock_data);
EXPECT_EQ(inserted_id, 0);
}
TEST_F(MYSQL_TEST, SelectPaymentForAccount)
{
ACC_FROM_HEX(owner_addr_5Ajfk);
vector<xmreg::XmrPayment> payments;
ASSERT_TRUE(xmr_accounts->select(acc.id.data, payments));
EXPECT_EQ(payments.size(), 1);
EXPECT_EQ(payments[0].payment_id, "74854c1cd490e148");
EXPECT_EQ(payments[0].payment_address, "5DUWE29P72Eb8inMa41HuNJG4tj9CcaNKGr6EVSbvhWGJdpDQCiNNYBUNF1oDb8BczU5aD68d3HNKXaEsPq8cvbQLK4Tiiy");
EXPECT_FALSE(static_cast<bool>(payments[0].request_fulfilled));
//check if there is no payment for the given account id
EXPECT_FALSE(xmr_accounts->select(5555, payments));
}
TEST_F(MYSQL_TEST, SelectPaymentUsingPaymentID)
{
string exising_id {"e410eb43e14a28fb"};
vector<xmreg::XmrPayment> payments;
EXPECT_TRUE(xmr_accounts->select_payment_by_id(exising_id, payments));
EXPECT_EQ(payments.size(), 1);
string non_exising_id {"e410eb43e140000"};
EXPECT_FALSE(xmr_accounts->select_payment_by_id(non_exising_id, payments));
EXPECT_EQ(payments.size(), 0);
xmr_accounts->disconnect();
EXPECT_FALSE(xmr_accounts->select_payment_by_id(exising_id, payments));
}
auto
make_mock_payment_data(string last_char_pub_key = "0")
{
xmreg::XmrPayment mock_data;
mock_data.id = mysqlpp::null;
// mock_output_data.account_id = acc.id; need to be set when used
mock_data.payment_id = pod_to_hex(crypto::rand<crypto::hash8>());
mock_data.import_fee = 10000000010ull; // xmr
mock_data.request_fulfilled = false;
mock_data.tx_hash = ""; // no tx_hash yet with the payment
mock_data.payment_address = "5DUWE29P72Eb8inMa41HuNJG4tj9CcaNKGr6EVSbvhWGJdpDQCiNNYBUNF1oDb8BczU5aD68d3HNKXaEsPq8cvbQLGi6vcb2zkW7mhsWor";
return mock_data;
}
TEST_F(MYSQL_TEST, InsertOnePayment)
{
ACC_FROM_HEX(addr_55Zb);
xmreg::XmrPayment mock_data = make_mock_payment_data();
mock_data.account_id = acc.id.data;
uint64_t expected_primary_id = xmr_accounts->get_next_primary_id(mock_data);
uint64_t inserted_id = xmr_accounts->insert(mock_data);
EXPECT_EQ(expected_primary_id, inserted_id);
// now we fetch the inserted input and compare its values
xmreg::XmrPayment in_data2;
EXPECT_TRUE(xmr_accounts->select_by_primary_id(inserted_id, in_data2));
EXPECT_EQ(in_data2.account_id, mock_data.account_id);
EXPECT_EQ(in_data2.payment_id, mock_data.payment_id);
EXPECT_EQ(in_data2.import_fee, mock_data.import_fee);
EXPECT_EQ(in_data2.payment_address, mock_data.payment_address);
EXPECT_EQ(in_data2.request_fulfilled, mock_data.request_fulfilled);
}
TEST_F(MYSQL_TEST, TryToInsertSamePaymentTwice)
{
// the input table requires a row to be unique for pair
// of key_image + output_id
ACC_FROM_HEX(addr_55Zb);
xmreg::XmrPayment mock_data = make_mock_payment_data();
mock_data.account_id = acc.id.data;
uint64_t inserted_id = xmr_accounts->insert(mock_data);
EXPECT_GT(inserted_id, 0);
// second insert should fail and result in 0
inserted_id = xmr_accounts->insert(mock_data);
EXPECT_EQ(inserted_id, 0);
}
TEST_F(MYSQL_TEST, UpdatePayment)
{
ACC_FROM_HEX(owner_addr_5Ajfk);
vector<xmreg::XmrPayment> payments;
ASSERT_TRUE(xmr_accounts->select(acc.id.data, payments));
// make copy of the orginal payment so that we can update it easly
auto updated_payment = payments.at(0);
ASSERT_FALSE(static_cast<bool>(updated_payment.request_fulfilled));
ASSERT_EQ(updated_payment.tx_hash, "");
updated_payment.request_fulfilled = 1;
updated_payment.tx_hash = "7456e8f14cc327ac653fa680e20d53e43b61be238302ea4589bb5a73932e921c";
EXPECT_TRUE(xmr_accounts->update( payments.at(0), updated_payment));
// fetch the payment data and check if it was updated
vector<xmreg::XmrPayment> payments2;
ASSERT_TRUE(xmr_accounts->select(acc.id.data, payments2));
EXPECT_EQ(payments2.at(0).id.data, payments.at(0).id.data);
EXPECT_TRUE(static_cast<bool>(payments2.at(0).request_fulfilled));
EXPECT_EQ(payments2.at(0).tx_hash, updated_payment.tx_hash);
}
/*
* Dont want to use real blockchain data, so we are going to
* mock xmreg::CurrentBlockchainStatus
*/
class MockCurrentBlockchainStatus1 : public xmreg::CurrentBlockchainStatus
{
public:
MockCurrentBlockchainStatus1()
6 years ago
: xmreg::CurrentBlockchainStatus(
xmreg::BlockchainSetup(),
nullptr, nullptr, nullptr)
6 years ago
{}
bool tx_unlock_state {true};
bool tx_exist_state {true};
std::map<string, uint64_t> tx_exist_mock_data;
// all txs in the blockchain are unlocked
virtual bool
is_tx_unlocked(uint64_t unlock_time,
uint64_t block_height,
xmreg::TxUnlockChecker const& tx_unlock_checker
= xmreg::TxUnlockChecker()) override
{
return tx_unlock_state;
}
// all ts in the blockchain exists
virtual bool
tx_exist(const string& tx_hash_str, uint64_t& tx_index) override
{
if (tx_exist_mock_data.empty())
return tx_exist_state;
tx_index = tx_exist_mock_data[tx_hash_str];
return true;
}
};
TEST_F(MYSQL_TEST, SelectTxsIfAllAreSpendableAndExist)
{
// if all txs selected for the given account are spendable
// the select_txs_for_account_spendability_check method
// should not change anything
// use mock CurrentBlockchainStatus instead of real object
// which would access the real blockchain.
auto mock_bc_status = make_shared<MockCurrentBlockchainStatus1>();
xmr_accounts->set_bc_status_provider(mock_bc_status);
ACC_FROM_HEX(owner_addr_5Ajfk);
vector<xmreg::XmrTransaction> txs;
// we mark all txs for this account as spendable
// so that we have something to work with in this test
ASSERT_TRUE(this->xmr_accounts->select(acc.id.data, txs));
auto no_of_original_txs = txs.size();
for (size_t i = 0; i < txs.size(); ++i)
this->xmr_accounts->mark_tx_spendable(txs[i].id.data);
// reselect tx after they were marked as spendable
txs.clear();
ASSERT_TRUE(this->xmr_accounts->select(acc.id.data, txs));
EXPECT_TRUE(this->xmr_accounts
->select_txs_for_account_spendability_check(acc.id.data, txs));
// we check if non of the input txs got filtere out
EXPECT_EQ(txs.size(), no_of_original_txs);
// and we check if all of remained spendable
for (auto const& tx: txs)
EXPECT_TRUE(bool {tx.spendable});
}
TEST_F(MYSQL_TEST, SelectTxsIfAllAreNonspendableButUnlockedAndExist)
{
// if all txs selected for the given account are non-spendable
// the select_txs_for_account_spendability_check method
// will check their unlock time, and marked them spendable in
// they are unlocked.
// We are going to mock that all are unlocked
// use mock CurrentBlockchainStatus instead of real object
// which would access the real blockchain.
auto mock_bc_status = make_shared<MockCurrentBlockchainStatus1>();
xmr_accounts->set_bc_status_provider(mock_bc_status);
ACC_FROM_HEX(owner_addr_5Ajfk);
vector<xmreg::XmrTransaction> txs;
// we mark all txs for this account as spendable
// so that we have something to work with in this test
ASSERT_TRUE(this->xmr_accounts->select(acc.id.data, txs));
auto no_of_original_txs = txs.size();
for (size_t i = 0; i < txs.size(); ++i)
this->xmr_accounts->mark_tx_nonspendable(txs[i].id.data);
// reselect tx after they were marked as spendable
txs.clear();
ASSERT_TRUE(this->xmr_accounts->select(acc.id.data, txs));
// and we check if all non-spendable before we fetch them into
// select_txs_for_account_spendability_check
for (auto const& tx: txs)
ASSERT_FALSE(bool {tx.spendable});
EXPECT_TRUE(this->xmr_accounts
->select_txs_for_account_spendability_check(acc.id.data, txs));
// we check if non of the input txs got filtere out
EXPECT_EQ(txs.size(), no_of_original_txs);
// reselect tx after they were marked as spendable
txs.clear();
ASSERT_TRUE(this->xmr_accounts->select(acc.id.data, txs));
// and we check if all of remained spendable
for (auto const& tx: txs)
ASSERT_TRUE(bool {tx.spendable});
// and we check if all of remained spendable
for (auto const& tx: txs)
EXPECT_TRUE(bool {tx.spendable});
}
TEST_F(MYSQL_TEST, SelectTxsIfAllAreNonspendableLockedButExist)
{
// if all txs selected for the given account are non-spendable
// the select_txs_for_account_spendability_check method
// will check if they are unlocked. In this thest all will be locked
// so new unlock_time for them is going to be set for them.
// all txs are set to exisit in the blockchain
ACC_FROM_HEX(owner_addr_5Ajfk);
vector<xmreg::XmrTransaction> txs;
// we mark all txs for this account as spendable
// so that we have something to work with in this test
ASSERT_TRUE(this->xmr_accounts->select(acc.id.data, txs));
// use mock CurrentBlockchainStatus instead of real object
// which would access the real blockchain.
auto mock_bc_status = make_shared<MockCurrentBlockchainStatus1>();
// we mock that all txs are still locked and cant be spent
mock_bc_status->tx_unlock_state = false;
// now we need to populate mock_bc_status->tx_exist_mock_data map
// so that tx_exist mock works as if all txs existed
// and it returns correct/expected blockchain_tx_id
for(auto const& tx: txs)
mock_bc_status->tx_exist_mock_data[tx.hash] = tx.blockchain_tx_id;
// now set the mock_bc_status to be used by xmr_accounts later on
xmr_accounts->set_bc_status_provider(mock_bc_status);
auto no_of_original_txs = txs.size();
for (size_t i = 0; i < txs.size(); ++i)
this->xmr_accounts->mark_tx_nonspendable(txs[i].id.data);
// reselect tx after they were marked as spendable
txs.clear();
ASSERT_TRUE(this->xmr_accounts->select(acc.id.data, txs));
// and we check if all non-spendable before we fetch them into
// select_txs_for_account_spendability_check
for (auto const& tx: txs)
{
ASSERT_FALSE(bool {tx.spendable});
if (!bool {tx.coinbase})
ASSERT_EQ(tx.unlock_time, 0);
}
EXPECT_TRUE(this->xmr_accounts
->select_txs_for_account_spendability_check(acc.id.data, txs));
// we check if non of the input txs got filtere out
EXPECT_EQ(txs.size(), no_of_original_txs);
// and we check if all of remained non-spendable and
// if their unlock time was modified as needed
for (auto const& tx: txs)
{
ASSERT_FALSE(bool {tx.spendable});
if (!bool {tx.coinbase})
ASSERT_EQ(tx.unlock_time,
tx.height + CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE);
}
}
TEST_F(MYSQL_TEST, SelectTxsIfAllAreNonspendableUnlockedAndDontExist)
{
// if all txs selected for the given account are non-spendable,
// locked and dont exist in blockchain
// they should be filtered and removed from the mysql
// use mock CurrentBlockchainStatus instead of real object
// which would access the real blockchain.
auto mock_bc_status = make_shared<MockCurrentBlockchainStatus1>();
// all txs are locked and dont exisit in blockchain
mock_bc_status->tx_unlock_state = false;
mock_bc_status->tx_exist_state = false;
xmr_accounts->set_bc_status_provider(mock_bc_status);
ACC_FROM_HEX(owner_addr_5Ajfk);
vector<xmreg::XmrTransaction> txs;
// we mark all txs for this account as nonspendable
// so that we have something to work with in this test
ASSERT_TRUE(this->xmr_accounts->select(acc.id.data, txs));
for (size_t i = 0; i < txs.size(); ++i)
this->xmr_accounts->mark_tx_nonspendable(txs[i].id.data);
// reselect tx after they were marked as spendable
txs.clear();
ASSERT_TRUE(this->xmr_accounts->select(acc.id.data, txs));
// and we check if all non-spendable before we fetch them into
// select_txs_for_account_spendability_check
for (auto const& tx: txs)
ASSERT_FALSE(bool {tx.spendable});
EXPECT_TRUE(this->xmr_accounts->select_txs_for_account_spendability_check(acc.id.data, txs));
// after the call to select_txs_for_account_spendability_check
// all txs should be filted out
EXPECT_EQ(txs.size(), 0);
// all these txs should also be deleted from the mysql
txs.clear();
ASSERT_FALSE(this->xmr_accounts->select(acc.id.data, txs));
EXPECT_EQ(txs.size(), 0);
}
TEST_F(MYSQL_TEST, SelectTxsFailureDueToSpendabilityAndTxDeletion)
{
// if all txs selected for the given account are non-spendable,
// locked and dont exist in blockchain
// they should be filtered and removed from the mysql
// however, the mark_tx_spendable and delete_tx can
// fail. We simulate the failure by providing tx.id which does not
// exisit in the mysql
// use mock CurrentBlockchainStatus instead of real object
// which would access the real blockchain.
auto mock_bc_status = make_shared<MockCurrentBlockchainStatus1>();
// all txs are unlocked and dont exisit in blockchain
mock_bc_status->tx_unlock_state = true;
mock_bc_status->tx_exist_state = false;
xmr_accounts->set_bc_status_provider(mock_bc_status);
ACC_FROM_HEX(owner_addr_5Ajfk);
vector<xmreg::XmrTransaction> txs;
// we mark all txs for this account as nonspendable
// so that we have something to work with in this test
ASSERT_TRUE(this->xmr_accounts->select(acc.id.data, txs));
auto no_of_original_txs = txs.size();
for (size_t i = 0; i < txs.size(); ++i)
{
txs[i].id = 5555555555 /*some non-existing id*/;
txs[i].spendable = false;
}
// the non-exisiting ids should result in failure
EXPECT_FALSE(this->xmr_accounts->select_txs_for_account_spendability_check(acc.id.data, txs));
// now repeat if all txs are locked and dont exisit in blockchain
mock_bc_status->tx_unlock_state = false;
// also should lead to false
EXPECT_FALSE(this->xmr_accounts->select_txs_for_account_spendability_check(acc.id.data, txs));
}
TEST_F(MYSQL_TEST, MysqlPingThreadStopsOnPingFailure)
{
// we test creation of the mysql ping thread
// and its stop due to ping failure, for example,
// when connection to mysql is lost
auto conn = xmr_accounts->get_connection();
// create ping functor that will be pinging mysql every 1 second
xmreg::MysqlPing mysql_ping {conn, 1s};
{
// create ping thread and start pinging
// we put it in this local scope so that
// we exit the scope only when the thread is fully finished
// i.e., it was joined.
xmreg::ThreadRAII mysql_ping_thread(
std::thread(std::ref(mysql_ping)),
xmreg::ThreadRAII::DtorAction::join);
// wait few seconds so that several pings are done
std::this_thread::sleep_for(4s);
// disconnecting from mysql should result in the thread to stop
conn->get_connection().disconnect();
}
// since we waiting 4s, we expect that there were at about 3-4 pings
EXPECT_EQ(mysql_ping.get_stop_reason(),
xmreg::MysqlPing::StopReason::PingFailed);
EXPECT_THAT(mysql_ping.get_counter(), AllOf(Ge(3), Le(5)));
}
TEST_F(MYSQL_TEST, MysqlPingThreadStopsOnPointerExpiry)
{
// we test creation of the mysql ping thread
// and weak pointer in the ping object expires.
// to simulate the pointer expiry, we are going to create new connection here
// i.e., so we dont use the one from the fixture, as its shared pointer
// will be keeping the weak pointer in the functor alive
// we did specify wrong mysql details so this should throw.
auto new_conn = make_connection();
ASSERT_TRUE(new_conn->get_connection().connected());
// create ping functor that will be pinging mysql every 1 second
xmreg::MysqlPing mysql_ping {new_conn, 1s};
{
// create ping thread and start pinging
// we put it in this local scope so that
// we exit the scope only when the thread is fully finished
// i.e., it was joined.
xmreg::ThreadRAII mysql_ping_thread(
std::thread(std::ref(mysql_ping)),
xmreg::ThreadRAII::DtorAction::join);
// wait few seconds so that several pings are done
std::this_thread::sleep_for(4s);
// reset new_conn pointer. this should lead to expiry of
// weak pointer in mysql_ping function
new_conn.reset();
}
// since we waiting 4s, we expect that there were at about 3-4 pings
EXPECT_EQ(mysql_ping.get_stop_reason(),
xmreg::MysqlPing::StopReason::PointerExpired);
EXPECT_THAT(mysql_ping.get_counter(), AllOf(Ge(3), Le(5)));
}
//class MYSQL_TEST2 : public MYSQL_TEST
//{
//
//};
//TEST(TEST_CHAIN, GenerateTestChain)
//{
// uint64_t ts_start = 1338224400;
//
// std::vector<test_event_entry> events;
//
// GENERATE_ACCOUNT(miner);
// GENERATE_ACCOUNT(alice);
//
// MAKE_GENESIS_BLOCK(events, blk_0, miner, ts_start);
// MAKE_NEXT_BLOCK(events, blk_1, blk_0, miner);
// MAKE_NEXT_BLOCK(events, blk_1_side, blk_0, miner);
// MAKE_NEXT_BLOCK(events, blk_2, blk_1, miner);
//
// std::vector<cryptonote::block> chain;
// map_hash2tx_t mtx;
//
//
// REWIND_BLOCKS(events, blk_2r, blk_2, miner);
// MAKE_TX_LIST_START(events, txlist_0, miner, alice, MK_COINS(1), blk_2);
// MAKE_TX_LIST(events, txlist_0, miner, alice, MK_COINS(2), blk_2);
// MAKE_TX_LIST(events, txlist_0, miner, alice, MK_COINS(4), blk_2);
// MAKE_NEXT_BLOCK_TX_LIST(events, blk_3, blk_2r, miner, txlist_0);
// REWIND_BLOCKS(events, blk_3r, blk_3, miner);
// MAKE_TX(events, tx_1, miner, alice, MK_COINS(50), blk_3);
// MAKE_NEXT_BLOCK_TX1(events, blk_4, blk_3r, miner, tx_1);
// REWIND_BLOCKS(events, blk_4r, blk_4, miner);
// MAKE_TX(events, tx_2, miner, alice, MK_COINS(50), blk_4);
// MAKE_NEXT_BLOCK_TX1(events, blk_5, blk_4r, miner, tx_2);
// REWIND_BLOCKS(events, blk_5r, blk_5, miner);
// MAKE_TX(events, tx_3, miner, alice, MK_COINS(50), blk_5);
// MAKE_NEXT_BLOCK_TX1(events, blk_6, blk_5r, miner, tx_3);
// REWIND_BLOCKS(events, blk_6r, blk_6, miner);
// MAKE_TX(events, tx_4, alice, miner, MK_COINS(20), blk_6);
// MAKE_NEXT_BLOCK_TX1(events, blk_7, blk_6r, miner, tx_4);
//
// find_block_chain(events, chain, mtx, get_block_hash(blk_7));
//
//
// std::cout << "Alice BALANCE = " << get_balance(alice, chain, mtx) << std::endl;
//
// cout << get_account_address_as_str(network_type::MAINNET, false, alice.get_keys().m_account_address) << endl;
// cout << pod_to_hex(alice.get_keys().m_view_secret_key) << endl;
// cout << pod_to_hex(alice.get_keys().m_spend_secret_key) << endl;
//
// cout << '\n\n' << xmreg::tx_to_hex(tx_4) << '\n';
//
//}
}