aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/core_proxy/core_proxy.h2
-rw-r--r--tests/core_tests/chaingen_main.cpp1
-rw-r--r--tests/core_tests/tx_pool.cpp52
-rw-r--r--tests/core_tests/tx_pool.h11
-rw-r--r--tests/functional_tests/make_test_signature.cc22
-rwxr-xr-xtests/functional_tests/rpc_payment.py40
-rwxr-xr-xtests/functional_tests/transfer.py3
-rw-r--r--tests/unit_tests/CMakeLists.txt5
-rw-r--r--tests/unit_tests/bootstrap_node_selector.cpp172
-rw-r--r--tests/unit_tests/epee_utils.cpp46
-rw-r--r--tests/unit_tests/hmac_keccak.cpp2
-rw-r--r--tests/unit_tests/keccak.cpp4
-rw-r--r--tests/unit_tests/levin.cpp20
-rw-r--r--tests/unit_tests/mul_div.cpp2
-rw-r--r--tests/unit_tests/net.cpp4
-rw-r--r--tests/unit_tests/node_server.cpp2
-rw-r--r--tests/unit_tests/test_tx_utils.cpp2
-rw-r--r--tests/unit_tests/wipeable_string.cpp1
-rw-r--r--tests/unit_tests/zmq_rpc.cpp55
19 files changed, 417 insertions, 29 deletions
diff --git a/tests/core_proxy/core_proxy.h b/tests/core_proxy/core_proxy.h
index aa99699de..aad1bc962 100644
--- a/tests/core_proxy/core_proxy.h
+++ b/tests/core_proxy/core_proxy.h
@@ -109,5 +109,7 @@ namespace tests
bool pad_transactions() const { return false; }
uint32_t get_blockchain_pruning_seed() const { return 0; }
bool prune_blockchain(uint32_t pruning_seed) const { return true; }
+ bool get_txpool_complement(const std::vector<crypto::hash> &hashes, std::vector<cryptonote::blobdata> &txes) { return false; }
+ bool get_pool_transaction_hashes(std::vector<crypto::hash>& txs, bool include_unrelayed_txes = true) const { return false; }
};
}
diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp
index 23f3170b8..014c7475b 100644
--- a/tests/core_tests/chaingen_main.cpp
+++ b/tests/core_tests/chaingen_main.cpp
@@ -161,6 +161,7 @@ int main(int argc, char* argv[])
GENERATE_AND_PLAY(txpool_spend_key_all);
GENERATE_AND_PLAY(txpool_double_spend_norelay);
GENERATE_AND_PLAY(txpool_double_spend_local);
+ GENERATE_AND_PLAY(txpool_double_spend_keyimage);
// Double spend
GENERATE_AND_PLAY(gen_double_spend_in_tx<false>);
diff --git a/tests/core_tests/tx_pool.cpp b/tests/core_tests/tx_pool.cpp
index 537015dca..cc738c4ba 100644
--- a/tests/core_tests/tx_pool.cpp
+++ b/tests/core_tests/tx_pool.cpp
@@ -125,10 +125,12 @@ txpool_double_spend_base::txpool_double_spend_base()
, m_no_relay_hashes()
, m_all_hashes()
, m_no_new_index(0)
+ , m_failed_index(0)
, m_new_timestamp_index(0)
, m_last_tx(crypto::hash{})
{
REGISTER_CALLBACK_METHOD(txpool_double_spend_base, mark_no_new);
+ REGISTER_CALLBACK_METHOD(txpool_double_spend_base, mark_failed);
REGISTER_CALLBACK_METHOD(txpool_double_spend_base, mark_timestamp_change);
REGISTER_CALLBACK_METHOD(txpool_double_spend_base, timestamp_change_pause);
REGISTER_CALLBACK_METHOD(txpool_double_spend_base, check_unchanged);
@@ -143,6 +145,12 @@ bool txpool_double_spend_base::mark_no_new(cryptonote::core& /*c*/, size_t ev_in
return true;
}
+bool txpool_double_spend_base::mark_failed(cryptonote::core& /*c*/, size_t ev_index, const std::vector<test_event_entry>& /*events*/)
+{
+ m_failed_index = ev_index + 1;
+ return true;
+}
+
bool txpool_double_spend_base::mark_timestamp_change(cryptonote::core& /*c*/, size_t ev_index, const std::vector<test_event_entry>& /*events*/)
{
m_new_timestamp_index = ev_index + 1;
@@ -483,6 +491,8 @@ bool txpool_double_spend_base::check_tx_verification_context(const cryptonote::t
m_last_tx = cryptonote::get_transaction_hash(tx);
if (m_no_new_index == event_idx)
return !tvc.m_verifivation_failed && !tx_added;
+ else if (m_failed_index == event_idx)
+ return tvc.m_verifivation_failed;// && !tx_added;
else
return !tvc.m_verifivation_failed && tx_added;
}
@@ -559,3 +569,45 @@ bool txpool_double_spend_local::generate(std::vector<test_event_entry>& events)
return true;
}
+bool txpool_double_spend_keyimage::generate(std::vector<test_event_entry>& events) const
+{
+ INIT_MEMPOOL_TEST();
+
+ DO_CALLBACK(events, "check_txpool_spent_keys");
+ SET_EVENT_VISITOR_SETT(events, event_visitor_settings::set_local_relay);
+ DO_CALLBACK(events, "mark_no_new");
+
+ const std::size_t tx_index1 = events.size();
+ MAKE_TX(events, tx_0, miner_account, bob_account, send_amount, blk_0);
+
+ DO_CALLBACK(events, "increase_all_tx_count");
+ DO_CALLBACK(events, "check_txpool_spent_keys");
+ DO_CALLBACK(events, "mark_timestamp_change");
+ DO_CALLBACK(events, "check_new_hidden");
+ DO_CALLBACK(events, "timestamp_change_pause");
+ DO_CALLBACK(events, "mark_no_new");
+ const std::size_t tx_index2 = events.size();
+ events.push_back(tx_0);
+ DO_CALLBACK(events, "check_txpool_spent_keys");
+ DO_CALLBACK(events, "mark_timestamp_change");
+ DO_CALLBACK(events, "check_unchanged");
+
+ // use same key image with different id
+ cryptonote::transaction tx_1;
+ {
+ auto events_copy = events;
+ events_copy.erase(events_copy.begin() + tx_index1);
+ events_copy.erase(events_copy.begin() + tx_index2 - 1);
+ MAKE_TX(events_copy, tx_temp, miner_account, bob_account, send_amount, blk_0);
+ tx_1 = tx_temp;
+ }
+
+ // same key image
+ DO_CALLBACK(events, "timestamp_change_pause");
+ DO_CALLBACK(events, "mark_failed");
+ events.push_back(tx_1);
+ DO_CALLBACK(events, "check_unchanged");
+
+ return true;
+}
+
diff --git a/tests/core_tests/tx_pool.h b/tests/core_tests/tx_pool.h
index 996c76698..eb71dcf79 100644
--- a/tests/core_tests/tx_pool.h
+++ b/tests/core_tests/tx_pool.h
@@ -77,6 +77,7 @@ class txpool_double_spend_base : public txpool_base
std::unordered_set<crypto::hash> m_no_relay_hashes;
std::unordered_map<crypto::hash, uint64_t> m_all_hashes;
size_t m_no_new_index;
+ size_t m_failed_index;
size_t m_new_timestamp_index;
crypto::hash m_last_tx;
@@ -86,6 +87,7 @@ public:
txpool_double_spend_base();
bool mark_no_new(cryptonote::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
+ bool mark_failed(cryptonote::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
bool mark_timestamp_change(cryptonote::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
//! Pause for 1 second, so that `receive_time` for tx meta changes (tx hidden from public rpc being updated)
@@ -116,3 +118,12 @@ struct txpool_double_spend_local : txpool_double_spend_base
bool generate(std::vector<test_event_entry>& events) const;
};
+
+struct txpool_double_spend_keyimage : txpool_double_spend_base
+{
+ txpool_double_spend_keyimage()
+ : txpool_double_spend_base()
+ {}
+
+ bool generate(std::vector<test_event_entry>& events) const;
+};
diff --git a/tests/functional_tests/make_test_signature.cc b/tests/functional_tests/make_test_signature.cc
index 789523de5..6ac1a6a86 100644
--- a/tests/functional_tests/make_test_signature.cc
+++ b/tests/functional_tests/make_test_signature.cc
@@ -33,9 +33,9 @@
int main(int argc, const char **argv)
{
TRY_ENTRY();
- if (argc > 2)
+ if (argc > 3)
{
- fprintf(stderr, "usage: %s <secret_key>\n", argv[0]);
+ fprintf(stderr, "usage: %s [<secret_key> [N]]\n", argv[0]);
return 1;
}
@@ -55,8 +55,22 @@ int main(int argc, const char **argv)
fprintf(stderr, "invalid secret key\n");
return 1;
}
- std::string signature = cryptonote::make_rpc_payment_signature(skey);
- printf("%s\n", signature.c_str());
+ uint32_t count = 1;
+ if (argc == 3)
+ {
+ int i = atoi(argv[2]);
+ if (i <= 0)
+ {
+ fprintf(stderr, "invalid count\n");
+ return 1;
+ }
+ count = (uint32_t)i;
+ }
+ while (count--)
+ {
+ std::string signature = cryptonote::make_rpc_payment_signature(skey);
+ printf("%s\n", signature.c_str());
+ }
return 0;
CATCH_ENTRY_L0("main()", 1);
}
diff --git a/tests/functional_tests/rpc_payment.py b/tests/functional_tests/rpc_payment.py
index 4c777ccd7..3bf995f0c 100755
--- a/tests/functional_tests/rpc_payment.py
+++ b/tests/functional_tests/rpc_payment.py
@@ -31,6 +31,7 @@
from __future__ import print_function
import subprocess
import os
+import time
"""Test daemon RPC payment calls
"""
@@ -43,6 +44,7 @@ class RPCPaymentTest():
self.make_test_signature = os.environ['MAKE_TEST_SIGNATURE']
assert len(self.make_test_signature) > 0
self.secret_key, self.public_key = self.get_keys()
+ self.signatures = []
self.reset()
self.test_access_tracking()
self.test_access_mining()
@@ -56,8 +58,17 @@ class RPCPaymentTest():
assert len(fields) == 2
return fields
+ def refill_signatures(self):
+ signatures = subprocess.check_output([self.make_test_signature, self.secret_key, '256']).decode('utf-8')
+ for line in signatures.split():
+ self.signatures.append(line.rstrip())
+
def get_signature(self):
- return subprocess.check_output([self.make_test_signature, self.secret_key]).decode('utf-8').rstrip()
+ if len(self.signatures) == 0:
+ self.refill_signatures()
+ s = self.signatures[0]
+ self.signatures = self.signatures[1:]
+ return s
def reset(self):
print('Resetting blockchain')
@@ -143,6 +154,7 @@ class RPCPaymentTest():
found_valid = 0
found_invalid = 0
last_credits = 0
+ loop_time = time.time()
while found_valid == 0 or found_invalid == 0:
nonce += 1
try:
@@ -152,10 +164,17 @@ class RPCPaymentTest():
except Exception as e:
found_invalid += 1
res = daemon.rpc_access_info(client = self.get_signature())
+ cookie = res.cookie
+ loop_time = time.time()
assert res.credits < last_credits or res.credits == 0
assert nonce < 1000 # can't find both valid and invalid -> the RPC probably fails
last_credits = res.credits
+ if time.time() >= loop_time + 10:
+ res = daemon.rpc_access_info(client = self.get_signature())
+ cookie = res.cookie
+ loop_time = time.time()
+
# we should now have 1 valid nonce, and a number of bad ones
res = daemon.rpc_access_info(client = self.get_signature())
assert len(res.hashing_blob) > 39
@@ -176,6 +195,7 @@ class RPCPaymentTest():
assert e.nonces_dupe == 0
# Try random nonces till we find one that's valid so we get a load of credits
+ loop_time = time.time()
while last_credits == 0:
nonce += 1
try:
@@ -186,6 +206,10 @@ class RPCPaymentTest():
except:
found_invalid += 1
assert nonce < 1000 # can't find a valid none -> the RPC probably fails
+ if time.time() >= loop_time + 10:
+ res = daemon.rpc_access_info(client = self.get_signature())
+ cookie = res.cookie
+ loop_time = time.time()
# we should now have at least 5000
res = daemon.rpc_access_info(client = self.get_signature())
@@ -208,6 +232,7 @@ class RPCPaymentTest():
res = daemon.rpc_access_info(client = self.get_signature())
cookie = res.cookie
old_cookie = cookie # we keep that so can submit a stale later
+ loop_time = time.time()
while True:
nonce += 1
try:
@@ -218,6 +243,11 @@ class RPCPaymentTest():
found_invalid += 1
assert nonce < 1000 # can't find both valid and invalid -> the RPC probably fails
+ if time.time() >= loop_time + 10:
+ res = daemon.rpc_access_info(client = self.get_signature())
+ cookie = res.cookie
+ loop_time = time.time()
+
res = daemon.rpc_access_data()
assert len(res.entries) > 0
e = [x for x in res.entries if x['client'] == self.public_key]
@@ -247,14 +277,17 @@ class RPCPaymentTest():
# find stales without updating cookie, one within 5 seconds (accepted), one later (rejected)
res = daemon.rpc_access_info(client = self.get_signature())
+ cookie = res.cookie # let the daemon update its timestamp, but use old cookie
found_close_stale = 0
found_late_stale = 0
+ loop_time = time.time()
while found_close_stale == 0 or found_late_stale == 0:
nonce += 1
try:
res = daemon.rpc_access_submit_nonce(nonce = nonce, cookie = cookie, client = self.get_signature())
found_close_stale += 1
found_valid += 1
+ time.sleep(15) # now we've got an early stale, wait till they become late stales
except Exception as e:
#if e[0]['error']['code'] == -18: # stale
if "'code': -18" in str(e): # stale (ugly version, but also works with python 3)
@@ -263,6 +296,11 @@ class RPCPaymentTest():
found_invalid += 1
assert nonce < 1000 # can't find both valid and invalid -> the RPC probably fails
+ if time.time() >= loop_time + 10:
+ res = daemon.rpc_access_info(client = self.get_signature())
+ # cookie = res.cookie # let the daemon update its timestamp, but use old cookie
+ loop_time = time.time()
+
res = daemon.rpc_access_data()
assert len(res.entries) > 0
e = [x for x in res.entries if x['client'] == self.public_key]
diff --git a/tests/functional_tests/transfer.py b/tests/functional_tests/transfer.py
index 3bed69b98..c3d71aa9c 100755
--- a/tests/functional_tests/transfer.py
+++ b/tests/functional_tests/transfer.py
@@ -256,7 +256,6 @@ class TransferTest():
assert res.too_big == False
assert res.overspend == False
assert res.fee_too_low == False
- assert res.not_rct == False
self.wallet[0].refresh()
@@ -598,7 +597,6 @@ class TransferTest():
assert res.too_big == False
assert res.overspend == False
assert res.fee_too_low == False
- assert res.not_rct == False
res = daemon.get_transactions([txes[0][0]])
assert len(res.txs) >= 1
@@ -615,7 +613,6 @@ class TransferTest():
assert res.too_big == False
assert res.overspend == False
assert res.fee_too_low == False
- assert res.not_rct == False
assert res.too_few_outputs == False
res = daemon.get_transactions([txes[0][0]])
diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt
index cda25dfc9..9c24a5ec7 100644
--- a/tests/unit_tests/CMakeLists.txt
+++ b/tests/unit_tests/CMakeLists.txt
@@ -34,6 +34,7 @@ set(unit_tests_sources
blockchain_db.cpp
block_queue.cpp
block_reward.cpp
+ bootstrap_node_selector.cpp
bulletproofs.cpp
canonical_amounts.cpp
chacha.cpp
@@ -93,7 +94,8 @@ set(unit_tests_sources
wipeable_string.cpp
is_hdd.cpp
aligned.cpp
- rpc_version_str.cpp)
+ rpc_version_str.cpp
+ zmq_rpc.cpp)
set(unit_tests_headers
unit_tests_utils.h)
@@ -106,6 +108,7 @@ target_link_libraries(unit_tests
ringct
cryptonote_protocol
cryptonote_core
+ daemon_messages
blockchain_db
lmdb_lib
rpc
diff --git a/tests/unit_tests/bootstrap_node_selector.cpp b/tests/unit_tests/bootstrap_node_selector.cpp
new file mode 100644
index 000000000..c609d1223
--- /dev/null
+++ b/tests/unit_tests/bootstrap_node_selector.cpp
@@ -0,0 +1,172 @@
+// Copyright (c) 2020, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. 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.
+//
+// 3. Neither the name of the copyright holder 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 HOLDER OR CONTRIBUTORS 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.
+
+#include <gtest/gtest.h>
+
+#include "rpc/bootstrap_node_selector.h"
+
+class bootstrap_node_selector : public ::testing::Test
+{
+protected:
+ void SetUp() override
+ {
+ nodes.insert(white_nodes.begin(), white_nodes.end());
+ nodes.insert(gray_nodes.begin(), gray_nodes.end());
+ }
+
+ const std::map<std::string, bool> white_nodes = {
+ {
+ "white_node_1:18089", true
+ },
+ {
+ "white_node_2:18081", true
+ }
+ };
+ const std::map<std::string, bool> gray_nodes = {
+ {
+ "gray_node_1:18081", false
+ },
+ {
+ "gray_node_2:18089", false
+ }
+ };
+
+ std::map<std::string, bool> nodes;
+};
+
+TEST_F(bootstrap_node_selector, selector_auto_empty)
+{
+ cryptonote::bootstrap_node::selector_auto selector([]() {
+ return std::map<std::string, bool>();
+ });
+
+ EXPECT_FALSE(selector.next_node());
+}
+
+TEST_F(bootstrap_node_selector, selector_auto_no_credentials)
+{
+ cryptonote::bootstrap_node::selector_auto selector([this]() {
+ return nodes;
+ });
+
+ for (size_t fails = 0; fails < nodes.size(); ++fails)
+ {
+ const auto current = selector.next_node();
+ EXPECT_FALSE(current->credentials);
+
+ selector.handle_result(current->address, false);
+ }
+}
+
+TEST_F(bootstrap_node_selector, selector_auto_success)
+{
+ cryptonote::bootstrap_node::selector_auto selector([this]() {
+ return nodes;
+ });
+
+ auto current = selector.next_node();
+ for (size_t fails = 0; fails < nodes.size(); ++fails)
+ {
+ selector.handle_result(current->address, true);
+
+ current = selector.next_node();
+ EXPECT_TRUE(white_nodes.count(current->address) > 0);
+ }
+}
+
+TEST_F(bootstrap_node_selector, selector_auto_failure)
+{
+ cryptonote::bootstrap_node::selector_auto selector([this]() {
+ return nodes;
+ });
+
+ auto current = selector.next_node();
+ for (size_t fails = 0; fails < nodes.size(); ++fails)
+ {
+ const auto previous = current;
+
+ selector.handle_result(current->address, false);
+
+ current = selector.next_node();
+ EXPECT_NE(current->address, previous->address);
+ }
+}
+
+TEST_F(bootstrap_node_selector, selector_auto_white_nodes_first)
+{
+ cryptonote::bootstrap_node::selector_auto selector([this]() {
+ return nodes;
+ });
+
+ for (size_t iterations = 0; iterations < 2; ++iterations)
+ {
+ for (size_t fails = 0; fails < white_nodes.size(); ++fails)
+ {
+ const auto current = selector.next_node();
+ EXPECT_TRUE(white_nodes.count(current->address) > 0);
+
+ selector.handle_result(current->address, false);
+ }
+
+ for (size_t fails = 0; fails < gray_nodes.size(); ++fails)
+ {
+ const auto current = selector.next_node();
+ EXPECT_TRUE(gray_nodes.count(current->address) > 0);
+
+ selector.handle_result(current->address, false);
+ }
+ }
+}
+
+TEST_F(bootstrap_node_selector, selector_auto_max_nodes)
+{
+ const size_t max_nodes = nodes.size() / 2;
+
+ bool populated_once = false;
+ cryptonote::bootstrap_node::selector_auto selector([this, &populated_once]() {
+ if (!populated_once)
+ {
+ populated_once = true;
+ return nodes;
+ }
+
+ return std::map<std::string, bool>();
+ }, max_nodes);
+
+ std::set<std::string> unique_nodes;
+
+ for (size_t fails = 0; fails < nodes.size(); ++fails)
+ {
+ const auto current = selector.next_node();
+ unique_nodes.insert(current->address);
+
+ selector.handle_result(current->address, false);
+ }
+
+ EXPECT_EQ(unique_nodes.size(), max_nodes);
+}
diff --git a/tests/unit_tests/epee_utils.cpp b/tests/unit_tests/epee_utils.cpp
index 513c2227c..42bbb26bb 100644
--- a/tests/unit_tests/epee_utils.cpp
+++ b/tests/unit_tests/epee_utils.cpp
@@ -824,14 +824,14 @@ TEST(ToHex, String)
}
-TEST(FromHex, String)
+TEST(HexLocale, String)
{
// the source data to encode and decode
std::vector<uint8_t> source{{ 0x00, 0xFF, 0x0F, 0xF0 }};
// encode and decode the data
auto hex = epee::to_hex::string({ source.data(), source.size() });
- auto decoded = epee::from_hex::vector(hex);
+ auto decoded = epee::from_hex_locale::to_vector(hex);
// encoded should be twice the size and should decode to the exact same data
EXPECT_EQ(source.size() * 2, hex.size());
@@ -840,7 +840,7 @@ TEST(FromHex, String)
// we will now create a padded hex string, we want to explicitly allow
// decoding it this way also, ignoring spaces and colons between the numbers
hex.assign("00:ff 0f:f0");
- EXPECT_EQ(source, epee::from_hex::vector(hex));
+ EXPECT_EQ(source, epee::from_hex_locale::to_vector(hex));
}
TEST(ToHex, Array)
@@ -902,6 +902,46 @@ TEST(ToHex, Formatted)
EXPECT_EQ(expected, out.str());
}
+TEST(FromHex, ToString)
+{
+ static constexpr const char hex[] = u8"deadbeeffY";
+ static constexpr const char binary[] = {
+ char(0xde), char(0xad), char(0xbe), char(0xef), 0x00
+ };
+
+ std::string out{};
+ EXPECT_FALSE(epee::from_hex::to_string(out, hex));
+
+ boost::string_ref portion{hex};
+ portion.remove_suffix(1);
+ EXPECT_FALSE(epee::from_hex::to_string(out, portion));
+
+ portion.remove_suffix(1);
+ EXPECT_TRUE(epee::from_hex::to_string(out, portion));
+ EXPECT_EQ(std::string{binary}, out);
+}
+
+TEST(FromHex, ToBuffer)
+{
+ static constexpr const char hex[] = u8"deadbeeffY";
+ static constexpr const std::uint8_t binary[] = {0xde, 0xad, 0xbe, 0xef};
+
+ std::vector<std::uint8_t> out{};
+ out.resize(sizeof(binary));
+ EXPECT_FALSE(epee::from_hex::to_buffer(epee::to_mut_span(out), hex));
+
+ boost::string_ref portion{hex};
+ portion.remove_suffix(1);
+ EXPECT_FALSE(epee::from_hex::to_buffer(epee::to_mut_span(out), portion));
+
+ portion.remove_suffix(1);
+ EXPECT_FALSE(epee::from_hex::to_buffer({out.data(), out.size() - 1}, portion));
+
+ EXPECT_TRUE(epee::from_hex::to_buffer(epee::to_mut_span(out), portion));
+ const std::vector<std::uint8_t> expected{std::begin(binary), std::end(binary)};
+ EXPECT_EQ(expected, out);
+}
+
TEST(StringTools, BuffToHex)
{
const std::vector<unsigned char> all_bytes = get_all_bytes();
diff --git a/tests/unit_tests/hmac_keccak.cpp b/tests/unit_tests/hmac_keccak.cpp
index 3898d4a7a..ec7c90dbe 100644
--- a/tests/unit_tests/hmac_keccak.cpp
+++ b/tests/unit_tests/hmac_keccak.cpp
@@ -123,7 +123,7 @@ static void test_keccak_hmac(const size_t * chunks)
}
-TEST(keccak_hmac, )
+TEST(keccak_hmac, nullptr)
{
test_keccak_hmac(nullptr);
}
diff --git a/tests/unit_tests/keccak.cpp b/tests/unit_tests/keccak.cpp
index f4d41a8fa..a869fbaec 100644
--- a/tests/unit_tests/keccak.cpp
+++ b/tests/unit_tests/keccak.cpp
@@ -54,10 +54,6 @@ extern "C" {
keccak_finish(&ctx, md1); \
ASSERT_EQ(memcmp(md0, md1, 32), 0);
-TEST(keccak, )
-{
-}
-
TEST(keccak, 0_and_0)
{
static const size_t chunks[] = {0};
diff --git a/tests/unit_tests/levin.cpp b/tests/unit_tests/levin.cpp
index 38707f075..720103e5a 100644
--- a/tests/unit_tests/levin.cpp
+++ b/tests/unit_tests/levin.cpp
@@ -462,8 +462,8 @@ TEST_F(levin_notify, fluff_without_padding)
}
std::vector<cryptonote::blobdata> txs(2);
- txs[0].resize(100, 'e');
- txs[1].resize(200, 'f');
+ txs[0].resize(100, 'f');
+ txs[1].resize(200, 'e');
ASSERT_EQ(10u, contexts_.size());
{
@@ -479,6 +479,7 @@ TEST_F(levin_notify, fluff_without_padding)
for (++context; context != contexts_.end(); ++context)
EXPECT_EQ(1u, context->process_send_queue());
+ std::sort(txs.begin(), txs.end());
ASSERT_EQ(9u, receiver_.notified_size());
for (unsigned count = 0; count < 9; ++count)
{
@@ -510,8 +511,8 @@ TEST_F(levin_notify, fluff_with_padding)
}
std::vector<cryptonote::blobdata> txs(2);
- txs[0].resize(100, 'e');
- txs[1].resize(200, 'f');
+ txs[0].resize(100, 'f');
+ txs[1].resize(200, 'e');
ASSERT_EQ(10u, contexts_.size());
{
@@ -527,6 +528,7 @@ TEST_F(levin_notify, fluff_with_padding)
for (++context; context != contexts_.end(); ++context)
EXPECT_EQ(1u, context->process_send_queue());
+ std::sort(txs.begin(), txs.end());
ASSERT_EQ(9u, receiver_.notified_size());
for (unsigned count = 0; count < 9; ++count)
{
@@ -558,8 +560,8 @@ TEST_F(levin_notify, private_fluff_without_padding)
}
std::vector<cryptonote::blobdata> txs(2);
- txs[0].resize(100, 'e');
- txs[1].resize(200, 'f');
+ txs[0].resize(100, 'f');
+ txs[1].resize(200, 'e');
ASSERT_EQ(10u, contexts_.size());
{
@@ -572,6 +574,7 @@ TEST_F(levin_notify, private_fluff_without_padding)
io_service_.reset();
ASSERT_LT(0u, io_service_.poll());
+ std::sort(txs.begin(), txs.end());
EXPECT_EQ(0u, context->process_send_queue());
for (++context; context != contexts_.end(); ++context)
{
@@ -610,8 +613,8 @@ TEST_F(levin_notify, private_fluff_with_padding)
}
std::vector<cryptonote::blobdata> txs(2);
- txs[0].resize(100, 'e');
- txs[1].resize(200, 'f');
+ txs[0].resize(100, 'f');
+ txs[1].resize(200, 'e');
ASSERT_EQ(10u, contexts_.size());
{
@@ -624,6 +627,7 @@ TEST_F(levin_notify, private_fluff_with_padding)
io_service_.reset();
ASSERT_LT(0u, io_service_.poll());
+ std::sort(txs.begin(), txs.end());
EXPECT_EQ(0u, context->process_send_queue());
for (++context; context != contexts_.end(); ++context)
{
diff --git a/tests/unit_tests/mul_div.cpp b/tests/unit_tests/mul_div.cpp
index e3f7c34f3..c1a72ce51 100644
--- a/tests/unit_tests/mul_div.cpp
+++ b/tests/unit_tests/mul_div.cpp
@@ -82,7 +82,7 @@ namespace
lo = mul128(0x1111111111111111, 0x1111111111111111, &hi);
ASSERT_EQ(lo, 0x0fedcba987654321);
- ASSERT_EQ(hi, 0x0123456789abcdf0);;
+ ASSERT_EQ(hi, 0x0123456789abcdf0);
}
TEST(mul128_with_carry_1_only, multiplies_correctly)
diff --git a/tests/unit_tests/net.cpp b/tests/unit_tests/net.cpp
index 250dc35f5..36cb28ae0 100644
--- a/tests/unit_tests/net.cpp
+++ b/tests/unit_tests/net.cpp
@@ -739,7 +739,7 @@ TEST(i2p_address, epee_serializev_b32)
EXPECT_EQ(std::strlen(b32_i2p), host.size());
host.push_back('k');
- EXPECT_TRUE(stg.set_value("host", host, stg.open_section("i2p", nullptr, false)));
+ EXPECT_TRUE(stg.set_value("host", std::string{host}, stg.open_section("i2p", nullptr, false)));
EXPECT_TRUE(command.load(stg)); // poor error reporting from `KV_SERIALIZE`
}
@@ -790,7 +790,7 @@ TEST(i2p_address, epee_serialize_unknown)
EXPECT_EQ(std::strlen(net::i2p_address::unknown_str()), host.size());
host.push_back('k');
- EXPECT_TRUE(stg.set_value("host", host, stg.open_section("i2p", nullptr, false)));
+ EXPECT_TRUE(stg.set_value("host", std::string{host}, stg.open_section("i2p", nullptr, false)));
EXPECT_TRUE(command.load(stg)); // poor error reporting from `KV_SERIALIZE`
}
diff --git a/tests/unit_tests/node_server.cpp b/tests/unit_tests/node_server.cpp
index bda606e1a..b656c4858 100644
--- a/tests/unit_tests/node_server.cpp
+++ b/tests/unit_tests/node_server.cpp
@@ -90,6 +90,8 @@ public:
bool prune_blockchain(uint32_t pruning_seed = 0) { return true; }
bool is_within_compiled_block_hash_area(uint64_t height) const { return false; }
bool has_block_weights(uint64_t height, uint64_t nblocks) const { return false; }
+ bool get_txpool_complement(const std::vector<crypto::hash> &hashes, std::vector<cryptonote::blobdata> &txes) { return false; }
+ bool get_pool_transaction_hashes(std::vector<crypto::hash>& txs, bool include_unrelayed_txes = true) const { return false; }
void stop() {}
};
diff --git a/tests/unit_tests/test_tx_utils.cpp b/tests/unit_tests/test_tx_utils.cpp
index d8d760b07..deb45594d 100644
--- a/tests/unit_tests/test_tx_utils.cpp
+++ b/tests/unit_tests/test_tx_utils.cpp
@@ -44,7 +44,7 @@ namespace
TEST(parse_tx_extra, handles_empty_extra)
{
- std::vector<uint8_t> extra;;
+ std::vector<uint8_t> extra;
std::vector<cryptonote::tx_extra_field> tx_extra_fields;
ASSERT_TRUE(cryptonote::parse_tx_extra(extra, tx_extra_fields));
ASSERT_TRUE(tx_extra_fields.empty());
diff --git a/tests/unit_tests/wipeable_string.cpp b/tests/unit_tests/wipeable_string.cpp
index 44e050c5c..9911bd6f4 100644
--- a/tests/unit_tests/wipeable_string.cpp
+++ b/tests/unit_tests/wipeable_string.cpp
@@ -182,6 +182,7 @@ TEST(wipeable_string, split)
ASSERT_TRUE(check_split(" foo bar baz ", {"foo", "bar", "baz"}));
ASSERT_TRUE(check_split(" foo bar baz", {"foo", "bar", "baz"}));
ASSERT_TRUE(check_split("foo bar baz ", {"foo", "bar", "baz"}));
+ ASSERT_TRUE(check_split("\tfoo\n bar\r\nbaz", {"foo", "bar", "baz"}));
}
TEST(wipeable_string, parse_hexstr)
diff --git a/tests/unit_tests/zmq_rpc.cpp b/tests/unit_tests/zmq_rpc.cpp
new file mode 100644
index 000000000..af1f1608b
--- /dev/null
+++ b/tests/unit_tests/zmq_rpc.cpp
@@ -0,0 +1,55 @@
+// Copyright (c) 2020, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. 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.
+//
+// 3. Neither the name of the copyright holder 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 HOLDER OR CONTRIBUTORS 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.
+
+#include <gtest/gtest.h>
+
+#include "rpc/message.h"
+#include "serialization/json_object.h"
+
+TEST(ZmqFullMessage, InvalidRequest)
+{
+ EXPECT_THROW(
+ (cryptonote::rpc::FullMessage{"{\"jsonrpc\":\"2.0\",\"id\":0,\"params\":[]}", true}),
+ cryptonote::json::MISSING_KEY
+ );
+ EXPECT_THROW(
+ (cryptonote::rpc::FullMessage{"{\"jsonrpc\":\"2.0\",\"id\":0,\"method\":3,\"params\":[]}", true}),
+ cryptonote::json::WRONG_TYPE
+ );
+}
+
+TEST(ZmqFullMessage, Request)
+{
+ static constexpr const char request[] = "{\"jsonrpc\":\"2.0\",\"id\":0,\"method\":\"foo\",\"params\":[]}";
+ EXPECT_NO_THROW(
+ (cryptonote::rpc::FullMessage{request, true})
+ );
+
+ cryptonote::rpc::FullMessage parsed{request, true};
+ EXPECT_STREQ("foo", parsed.getRequestType().c_str());
+}