aboutsummaryrefslogtreecommitdiff
path: root/tests/unit_tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests/unit_tests')
-rw-r--r--tests/unit_tests/CMakeLists.txt4
-rw-r--r--tests/unit_tests/difficulty.cpp68
-rw-r--r--tests/unit_tests/hmac_keccak.cpp152
-rw-r--r--tests/unit_tests/lmdb.cpp404
-rw-r--r--tests/unit_tests/long_term_block_weight.cpp12
-rw-r--r--tests/unit_tests/multisig.cpp2
-rw-r--r--tests/unit_tests/net.cpp90
-rw-r--r--tests/unit_tests/serialization.cpp23
8 files changed, 754 insertions, 1 deletions
diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt
index b355d566d..56a1f8c4d 100644
--- a/tests/unit_tests/CMakeLists.txt
+++ b/tests/unit_tests/CMakeLists.txt
@@ -43,6 +43,7 @@ set(unit_tests_sources
crypto.cpp
decompose_amount_into_digits.cpp
device.cpp
+ difficulty.cpp
dns_resolver.cpp
epee_boosted_tcp_server.cpp
epee_levin_protocol_handler_async.cpp
@@ -52,10 +53,12 @@ set(unit_tests_sources
json_serialization.cpp
get_xtype_from_string.cpp
hashchain.cpp
+ hmac_keccak.cpp
http.cpp
keccak.cpp
logging.cpp
long_term_block_weight.cpp
+ lmdb.cpp
main.cpp
memwipe.cpp
mlocker.cpp
@@ -101,6 +104,7 @@ target_link_libraries(unit_tests
cryptonote_protocol
cryptonote_core
blockchain_db
+ lmdb_lib
rpc
net
serialization
diff --git a/tests/unit_tests/difficulty.cpp b/tests/unit_tests/difficulty.cpp
new file mode 100644
index 000000000..090fecc84
--- /dev/null
+++ b/tests/unit_tests/difficulty.cpp
@@ -0,0 +1,68 @@
+// Copyright (c) 2019, 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 "cryptonote_basic/difficulty.h"
+
+static cryptonote::difficulty_type MKDIFF(uint64_t high, uint64_t low)
+{
+ cryptonote::difficulty_type d = high;
+ d = (d << 64) | low;
+ return d;
+}
+
+static crypto::hash MKHASH(uint64_t high, uint64_t low)
+{
+ cryptonote::difficulty_type hash_target = high;
+ hash_target = (hash_target << 64) | low;
+ boost::multiprecision::uint256_t hash_value = std::numeric_limits<boost::multiprecision::uint256_t>::max() / hash_target;
+ crypto::hash h;
+ ((uint64_t*)&h)[0] = hash_value.convert_to<uint64_t>();
+ hash_value >>= 64;
+ ((uint64_t*)&h)[1] = hash_value.convert_to<uint64_t>();
+ hash_value >>= 64;
+ ((uint64_t*)&h)[2] = hash_value.convert_to<uint64_t>();
+ hash_value >>= 64;
+ ((uint64_t*)&h)[3] = hash_value.convert_to<uint64_t>();
+ return h;
+}
+
+TEST(difficulty, check_hash)
+{
+ ASSERT_TRUE(cryptonote::check_hash(MKHASH(0, 1), MKDIFF(0, 1)));
+ ASSERT_FALSE(cryptonote::check_hash(MKHASH(0, 1), MKDIFF(0, 2)));
+
+ ASSERT_TRUE(cryptonote::check_hash(MKHASH(0, 0xffffffffffffffff), MKDIFF(0, 0xffffffffffffffff)));
+ ASSERT_FALSE(cryptonote::check_hash(MKHASH(0, 0xffffffffffffffff), MKDIFF(1, 0)));
+
+ ASSERT_TRUE(cryptonote::check_hash(MKHASH(1, 1), MKDIFF(1, 1)));
+ ASSERT_FALSE(cryptonote::check_hash(MKHASH(1, 1), MKDIFF(1, 2)));
+
+ ASSERT_TRUE(cryptonote::check_hash(MKHASH(0xffffffffffffffff, 1), MKDIFF(0xffffffffffffffff, 1)));
+ ASSERT_FALSE(cryptonote::check_hash(MKHASH(0xffffffffffffffff, 1), MKDIFF(0xffffffffffffffff, 2)));
+}
diff --git a/tests/unit_tests/hmac_keccak.cpp b/tests/unit_tests/hmac_keccak.cpp
new file mode 100644
index 000000000..cb35d272a
--- /dev/null
+++ b/tests/unit_tests/hmac_keccak.cpp
@@ -0,0 +1,152 @@
+// Copyright (c) 2018, 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 "../io.h"
+
+extern "C" {
+#include "crypto/hmac-keccak.h"
+}
+
+#define KECCAK_BLOCKLEN 136
+
+static const struct {
+ const char *key;
+ const char *inp;
+ const char *res;
+} keccak_hmac_vectors[] = {
+ {"",
+ "",
+ "042186ec4e98680a0866091d6fb89b60871134b44327f8f467c14e9841d3e97b",
+ },
+ {"00",
+ "",
+ "042186ec4e98680a0866091d6fb89b60871134b44327f8f467c14e9841d3e97b",
+ },
+ {"00000000000000000000000000000000",
+ "",
+ "042186ec4e98680a0866091d6fb89b60871134b44327f8f467c14e9841d3e97b",
+ },
+ {"",
+ "00",
+ "402541d5d678ad30217023a12efbd2f367388dc0253ccddb8f915d187e03d414",
+ },
+ {"0000000000000000000000000000000000000000000000000000000000000000",
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "d164c38ca454176281b3c09dc83cf70bd00290835ff5490356993d368cde0577",
+ },
+ {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "d52c9100301a9546d8c97d7f32e8178fd5f4b0a7646ab761db9e0f503f8b0542",
+ },
+ {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "d52c9100301a9546d8c97d7f32e8178fd5f4b0a7646ab761db9e0f503f8b0542",
+ "5b9d98c5d3249176230d70fdb215ee2f93e4783064c9564384ddc396e63c18cb",
+ },
+ {"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "98d033ba0c95bb3aaf5709733443cbedba20f6451b710ccba4118fc5523013c8",
+ },
+ {"65768798a9bacbdcedfe0f2031425364758697a8b9cadbecfd0e1f30415263748596a7b8c9daebfc0d1e2f405162738495a6b7c8d9eafb0c1d2e3f5061728394a5b6c7d8e9fa0b1c2d3e4f60718293a4b5c6d7e8f90a1b2c3d4e5f708192a3b4c5d6e7f8091a2b3c4d5e6f8091a2b3c4d5e6f708192a3b4c5d6e7f90a1b2c3d4e5f60718293a4b5c6d7e8fa0b1c2d3e4f5061728394a5b6c7d8e9fb0c1d2e3f405162738495a6b7c8d9eafc0d1e2f30415263748596a7b8c9daebfd0e1f2031425364758697a8b9cadbecfe0f102132435465768798a9bacbdcedff00112233445566778899aabbccddeef00112233445566778899aabbccddeeff102132435465768798a9bacbdcedfe0f2031425364758697a8b9cadbecfd0e1f30415263748596a7b8c9daebfc0d1e2f405162738495a6b7c8d9eafb0c1d2e3f5061728394",
+ "7b8895a2afbcc9d6e3f0fd0a1724313e4b5865727f8c99a6b3c0cddae7f4010e1b2835424f5c697683909daab7c4d1deebf805121f2c394653606d7a8794a1aebbc8d5e2effc091623303d4a5764717e8b98a5b2bfccd9e6f3000d1a2734414e5b6875828f9ca9b6c3d0ddeaf704111e2b3845525f6c798693a0adbac7d4e1eefb0815222f3c495663707d8a97a4b1becbd8e5f2ff0c192633404d5a6774818e9ba8b5c2cfdce9f603101d2a3744515e6b7885929facb9c6d3e0edfa0714212e3b4855626f7c8996a3b0bdcad7e4f1fe0b1825323f4c596673808d9aa7b4c1cedbe8f5020f1c293643505d6a7784919eabb8c5d2dfecf90613202d3a4754616e7b8895a2afbcc9d6e3f0fd0a1724313e4b5865727f8c99a6b3c0cddae7f4010e1b2835424f5c697683909daab7c4d1deebf805121f2c394653606d7a8794a1ae",
+ "117b60a7f474fd2245adff82a69429367de8f5263fa96c411986009a743b0e70",
+ },
+ {"00112233445566778899aabbccddeeff102132435465768798a9bacbdcedfe0f",
+ "000d1a2734414e5b6875828f9ca9b6c3d0ddeaf704111e2b3845525f6c798693a0adbac7d4e1eefb0815222f3c495663707d8a97a4b1becbd8e5f2ff0c192633404d5a6774818e9ba8b5c2cfdce9f603101d2a3744515e6b7885929facb9c6d3e0edfa0714212e3b4855626f7c8996a3b0bdcad7e4f1fe0b1825323f4c596673808d9aa7b4c1cedbe8f5020f1c293643505d6a7784919eabb8c5d2dfecf90613202d3a4754616e7b8895a2afbcc9d6e3f0fd0a1724313e4b5865727f8c99a6b3c0cddae7f4010e1b",
+ "cbe3ca627c6432c9a66f07c6411fccca894c9b083b55d0773152460142a676ed",
+ },
+};
+
+static void test_keccak_hmac(const size_t * chunks)
+{
+ uint8_t inp_buff[1024];
+ uint8_t key_buff[1024];
+ uint8_t res_exp[32];
+ uint8_t res_comp[32];
+ const size_t len_chunks = chunks ? sizeof(chunks) / sizeof(*chunks) : 0;
+
+ for (size_t i = 0; i < (sizeof(keccak_hmac_vectors) / sizeof(*keccak_hmac_vectors)); i++)
+ {
+ const size_t inp_len = strlen(keccak_hmac_vectors[i].inp)/2;
+ const size_t key_len = strlen(keccak_hmac_vectors[i].key)/2;
+ ASSERT_TRUE(hexdecode(keccak_hmac_vectors[i].inp, inp_len, inp_buff));
+ ASSERT_TRUE(hexdecode(keccak_hmac_vectors[i].key, key_len, key_buff));
+ ASSERT_TRUE(hexdecode(keccak_hmac_vectors[i].res, 32, res_exp));
+ if (len_chunks == 0)
+ {
+ hmac_keccak_hash(res_comp, key_buff, key_len, inp_buff, inp_len);
+ }
+ else
+ {
+ hmac_keccak_state S;
+ hmac_keccak_init(&S, key_buff, key_len);
+ size_t inp_passed = 0;
+ size_t chunk_size = 0;
+ while(inp_passed < inp_len){
+ const size_t to_pass = std::min(inp_len - inp_passed, chunks[chunk_size]);
+ hmac_keccak_update(&S, inp_buff + inp_passed, to_pass);
+
+ inp_passed += to_pass;
+ chunk_size = (chunk_size + 1) % len_chunks;
+ }
+
+ hmac_keccak_finish(&S, res_comp);
+ }
+ ASSERT_EQ(memcmp(res_exp, res_comp, 32), 0);
+ }
+}
+
+
+TEST(keccak_hmac, )
+{
+ test_keccak_hmac({});
+}
+
+TEST(keccak_hmac, 1)
+{
+ static const size_t chunks[] = {1};
+ test_keccak_hmac(chunks);
+}
+
+TEST(keccak_hmac, 1_20)
+{
+ static const size_t chunks[] = {1, 20};
+ test_keccak_hmac(chunks);
+}
+
+TEST(keccak_hmac, 136_1)
+{
+ static const size_t chunks[] = {136, 1};
+ test_keccak_hmac(chunks);
+}
+
+TEST(keccak_hmac, 137_1)
+{
+ static const size_t chunks[] = {137, 1};
+ test_keccak_hmac(chunks);
+}
diff --git a/tests/unit_tests/lmdb.cpp b/tests/unit_tests/lmdb.cpp
new file mode 100644
index 000000000..c37c83a32
--- /dev/null
+++ b/tests/unit_tests/lmdb.cpp
@@ -0,0 +1,404 @@
+// Copyright (c) 2014-2018, 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 <boost/range/algorithm_ext/iota.hpp>
+#include <boost/range/algorithm/equal.hpp>
+#include <gtest/gtest.h>
+
+#include "lmdb/database.h"
+#include "lmdb/table.h"
+#include "lmdb/transaction.h"
+#include "lmdb/util.h"
+
+namespace
+{
+ enum class choice : unsigned {};
+ enum class big_choice : unsigned long {};
+
+ struct bytes {
+ char data[16];
+ };
+
+ MONERO_CURSOR(test_cursor);
+
+ template<typename T>
+ int run_compare(T left, T right, MDB_cmp_func* cmp)
+ {
+ MDB_val left_val = lmdb::to_val(left);
+ MDB_val right_val = lmdb::to_val(right);
+ return (*cmp)(&left_val, &right_val);
+ }
+}
+
+TEST(LMDB, Traits)
+{
+ EXPECT_TRUE((std::is_same<void, lmdb::identity<void>::type>()));
+ EXPECT_TRUE((std::is_same<unsigned, lmdb::identity<unsigned>::type>()));
+
+ EXPECT_TRUE((std::is_same<void, lmdb::native_type<void>>()));
+ EXPECT_TRUE((std::is_same<unsigned, lmdb::native_type<unsigned>>()));
+ EXPECT_TRUE((std::is_same<unsigned, lmdb::native_type<choice>>()));
+ EXPECT_TRUE((std::is_same<unsigned long, lmdb::native_type<big_choice>>()));
+}
+
+TEST(LMDB, ToNative)
+{
+ enum class negative_choice : int {};
+
+ EXPECT_TRUE((std::is_same<unsigned, decltype(lmdb::to_native(choice(0)))>()));
+ EXPECT_TRUE(
+ (std::is_same<unsigned long, decltype(lmdb::to_native(big_choice(0)))>())
+ );
+ EXPECT_TRUE(
+ (std::is_same<int, decltype(lmdb::to_native(negative_choice(0)))>())
+ );
+
+ EXPECT_EQ(unsigned(0), lmdb::to_native(choice(0)));
+ EXPECT_EQ(unsigned(0xffffffff), lmdb::to_native(choice(0xffffffff)));
+ EXPECT_EQ(-1, lmdb::to_native(negative_choice(-1)));
+
+ // test constexpr
+ static_assert(100 == lmdb::to_native(choice(100)), "to_native failed");
+ static_assert(-100 == lmdb::to_native(negative_choice(-100)), "to_native failed");
+}
+
+TEST(LMDB, Conversions)
+{
+ struct one
+ {
+ big_choice i;
+ choice j;
+ };
+
+ const one test{big_choice(100), choice(95)};
+ one test2{big_choice(1000), choice(950)};
+
+ EXPECT_EQ(&test, lmdb::to_val(test).mv_data);
+ EXPECT_NE(&test2, lmdb::to_val(test).mv_data);
+ EXPECT_EQ(
+ &test,
+ static_cast<const void*>(lmdb::to_byte_span(lmdb::to_val(test)).begin())
+ );
+ EXPECT_EQ(sizeof(test), lmdb::to_val(test).mv_size);
+ EXPECT_EQ(sizeof(test), lmdb::to_byte_span(lmdb::to_val(test)).size());
+
+ EXPECT_EQ(&test2, lmdb::to_val(test2).mv_data);
+ EXPECT_NE(&test, lmdb::to_val(test2).mv_data);
+ EXPECT_EQ(
+ &test2,
+ static_cast<const void*>(lmdb::to_byte_span(lmdb::to_val(test2)).begin())
+ );
+ EXPECT_EQ(sizeof(test2), lmdb::to_val(test2).mv_size);
+ EXPECT_EQ(sizeof(test2), lmdb::to_byte_span(lmdb::to_val(test2)).size());
+}
+
+TEST(LMDB, LessSort)
+{
+ struct one
+ {
+ unsigned i;
+ unsigned j;
+ };
+
+ struct two
+ {
+ unsigned i;
+ choice j;
+ };
+
+ EXPECT_EQ(0, run_compare(0u, 0u, &lmdb::less<unsigned>));
+ EXPECT_EQ(-1, run_compare(0u, 1u, &lmdb::less<unsigned>));
+ EXPECT_EQ(1, run_compare(1u, 0u, &lmdb::less<unsigned>));
+
+ EXPECT_EQ(0, run_compare<one>({0, 1}, {0, 1}, &lmdb::less<unsigned, sizeof(unsigned)>));
+ EXPECT_EQ(-1, run_compare<one>({0, 0}, {0, 1}, &lmdb::less<unsigned, sizeof(unsigned)>));
+ EXPECT_EQ(1, run_compare<one>({0, 1}, {0, 0}, &lmdb::less<unsigned, sizeof(unsigned)>));
+
+ EXPECT_EQ(0, run_compare<one>({0, 1}, {0, 1}, MONERO_SORT_BY(one, j)));
+ EXPECT_EQ(-1, run_compare<one>({0, 0}, {0, 1}, MONERO_SORT_BY(one, j)));
+ EXPECT_EQ(1, run_compare<one>({0, 1}, {0, 0}, MONERO_SORT_BY(one, j)));
+
+ EXPECT_EQ(0, run_compare<two>({0, choice(1)}, {0, choice(1)}, MONERO_SORT_BY(two, j)));
+ EXPECT_EQ(-1, run_compare<two>({0, choice(0)}, {0, choice(1)}, MONERO_SORT_BY(two, j)));
+ EXPECT_EQ(1, run_compare<two>({0, choice(1)}, {0, choice(0)}, MONERO_SORT_BY(two, j)));
+
+ // compare function addresses
+ EXPECT_EQ((MONERO_SORT_BY(one, i)), (MONERO_SORT_BY(two, i)));
+ EXPECT_EQ((MONERO_SORT_BY(one, j)), (MONERO_SORT_BY(two, j)));
+ EXPECT_NE((MONERO_SORT_BY(one, i)), (MONERO_SORT_BY(two, j)));
+ EXPECT_NE((MONERO_SORT_BY(one, j)), (MONERO_SORT_BY(two, i)));
+}
+
+TEST(LMDB, SortCompare)
+{
+ struct one
+ {
+ unsigned i;
+ bytes j;
+ };
+
+ one test{55};
+ boost::iota(test.j.data, 10);
+
+ const one test2 = test;
+
+ EXPECT_EQ(0, run_compare(test, test2, MONERO_COMPARE(one, j)));
+
+ test.j.data[15] = 1;
+ EXPECT_GT(0, run_compare(test, test2, MONERO_COMPARE(one, j)));
+
+ test.j.data[15] = 100;
+ EXPECT_LT(0, run_compare(test, test2, MONERO_COMPARE(one, j)));
+}
+
+TEST(LMDB, Table)
+{
+ struct one
+ {
+ bytes i;
+ bytes j;
+ };
+
+ constexpr lmdb::basic_table<choice, bytes> test{"foo"};
+
+ EXPECT_STREQ("foo", test.name);
+ static_assert(test.flags == 0, "bad flags");
+ static_assert(&lmdb::less<unsigned> == test.key_cmp, "bad key_cmp");
+ static_assert(test.value_cmp == nullptr, "bad value_cmp");
+ EXPECT_TRUE(test.get_value<bytes>(MDB_val{}).matches(std::errc::invalid_argument));
+
+ lmdb::basic_table<big_choice, one> test2{
+ "foo2", MDB_DUPSORT, &lmdb::compare<one>
+ };
+
+ EXPECT_STREQ("foo2", test2.name);
+ EXPECT_EQ((MDB_DUPSORT | MDB_DUPFIXED), test2.flags);
+ EXPECT_EQ(&lmdb::less<unsigned long>, test2.key_cmp);
+ EXPECT_EQ(&lmdb::compare<one>, test2.value_cmp);
+ EXPECT_TRUE(test2.get_value<one>(MDB_val{}).matches(std::errc::invalid_argument));
+
+ one record{};
+ boost::iota(record.i.data, 0);
+ boost::iota(record.i.data, 20);
+
+ const one record_copy = MONERO_UNWRAP(test2.get_value<one>(lmdb::to_val(record)));
+ EXPECT_TRUE(boost::equal(record.i.data, record_copy.i.data));
+ EXPECT_TRUE(boost::equal(record.j.data, record_copy.j.data));
+
+ const bytes j_copy = MONERO_UNWRAP(
+ test2.get_value<MONERO_FIELD(one, j)>(lmdb::to_val(record))
+ );
+ EXPECT_TRUE(boost::equal(record.j.data, j_copy.data));
+
+ EXPECT_TRUE(
+ test.get_key_stream(test_cursor{}).matches(std::errc::invalid_argument)
+ );
+ EXPECT_TRUE(
+ test2.get_key_stream(test_cursor{}).matches(std::errc::invalid_argument)
+ );
+
+
+ EXPECT_TRUE(
+ test.get_value_stream(choice(0), test_cursor{}).matches(std::errc::invalid_argument)
+ );
+ EXPECT_TRUE(
+ test2.get_value_stream(big_choice(0), test_cursor{}).matches(std::errc::invalid_argument)
+ );
+}
+
+TEST(LMDB, InvalidDatabase)
+{
+ lmdb::database test{lmdb::environment{}};
+
+ EXPECT_TRUE(test.resize().matches(std::errc::invalid_argument));
+ EXPECT_TRUE(test.create_read_txn().matches(std::errc::invalid_argument));
+ EXPECT_TRUE(test.reset_txn(lmdb::read_txn{}).matches(std::errc::invalid_argument));
+ EXPECT_TRUE(test.create_write_txn().matches(std::errc::invalid_argument));
+ EXPECT_TRUE(test.commit(lmdb::write_txn{}).matches(std::errc::invalid_argument));
+
+ EXPECT_TRUE(
+ test.try_write( [](MDB_txn&) { return success(); } ).matches(std::errc::invalid_argument)
+ );
+}
+
+TEST(LMDB, InvalidValueStream)
+{
+ struct one
+ {
+ choice i;
+ choice j;
+ bytes k;
+ };
+
+ lmdb::value_stream<one, close_test_cursor> test{test_cursor{}};
+
+ EXPECT_TRUE((std::is_same<one, decltype(*(test.make_iterator()))>()));
+ EXPECT_TRUE((std::is_same<one, decltype(*(test.make_range().begin()))>()));
+ EXPECT_TRUE(
+ (std::is_same<bytes, decltype(*(test.make_iterator<MONERO_FIELD(one, k)>()))>())
+ );
+ EXPECT_TRUE(
+ (std::is_same<bytes, decltype(*(test.make_range<MONERO_FIELD(one, k)>().begin()))>())
+ );
+
+ EXPECT_NO_THROW(test.reset());
+ EXPECT_EQ(0u, test.count());
+ EXPECT_TRUE(test.make_iterator().is_end());
+ EXPECT_TRUE(test.make_range().empty());
+ EXPECT_EQ(nullptr, test.give_cursor());
+
+ EXPECT_EQ(0u, test.count());
+ EXPECT_TRUE(test.make_iterator().is_end());
+ EXPECT_TRUE(test.make_range().empty());
+ EXPECT_EQ(nullptr, test.give_cursor());
+}
+
+TEST(LMDB, InvalidValueIterator)
+{
+ struct one
+ {
+ choice i;
+ choice j;
+ bytes k;
+ };
+
+ lmdb::value_iterator<one> test1{};
+
+ EXPECT_TRUE((std::is_same<one, decltype(*test1)>()));
+ EXPECT_TRUE(
+ (std::is_same<bytes, decltype(test1.get_value<MONERO_FIELD(one, k)>())>())
+ );
+
+ EXPECT_TRUE(test1.is_end());
+ EXPECT_NO_THROW(++test1);
+ EXPECT_NO_THROW(test1++);
+ EXPECT_TRUE(test1.is_end());
+
+ lmdb::value_iterator<one> test2{nullptr};
+
+ EXPECT_TRUE(test2.is_end());
+ EXPECT_NO_THROW(++test2);
+ EXPECT_NO_THROW(test2++);
+ EXPECT_TRUE(test2.is_end());
+
+ EXPECT_TRUE(test1.equal(test2));
+ EXPECT_TRUE(test2.equal(test1));
+ EXPECT_TRUE(test1 == test2);
+ EXPECT_TRUE(test2 == test1);
+ EXPECT_FALSE(test1 != test2);
+ EXPECT_FALSE(test2 != test1);
+
+ lmdb::value_iterator<MONERO_FIELD(one, k)> test3{};
+
+ EXPECT_TRUE((std::is_same<bytes, decltype(*test3)>()));
+ EXPECT_TRUE((std::is_same<one, decltype(test3.get_value<one>())>()));
+ EXPECT_TRUE(
+ (std::is_same<choice, decltype(test1.get_value<MONERO_FIELD(one, j)>())>())
+ );
+
+ EXPECT_TRUE(test3.is_end());
+ EXPECT_NO_THROW(++test3);
+ EXPECT_NO_THROW(test3++);
+ EXPECT_TRUE(test3.is_end());
+}
+
+TEST(LMDB, InvalidKeyStream)
+{
+ struct one
+ {
+ choice i;
+ choice j;
+ bytes k;
+ };
+
+ using record = std::pair<choice, boost::iterator_range<lmdb::value_iterator<one>>>;
+
+ lmdb::key_stream<choice, one, close_test_cursor> test{test_cursor{}};
+
+ EXPECT_TRUE((std::is_same<record, decltype(*(test.make_iterator()))>()));
+ EXPECT_TRUE((std::is_same<record, decltype(*(test.make_range().begin()))>()));
+
+ EXPECT_NO_THROW(test.reset());
+ EXPECT_TRUE(test.make_iterator().is_end());
+ EXPECT_TRUE(test.make_range().empty());
+ EXPECT_EQ(nullptr, test.give_cursor());
+
+ EXPECT_TRUE(test.make_iterator().is_end());
+ EXPECT_TRUE(test.make_range().empty());
+ EXPECT_EQ(nullptr, test.give_cursor());
+}
+
+TEST(LMDB, InvalidKeyIterator)
+{
+ struct one
+ {
+ choice i;
+ choice j;
+ bytes k;
+ };
+
+ using record = std::pair<choice, boost::iterator_range<lmdb::value_iterator<one>>>;
+
+ lmdb::key_iterator<choice, one> test1{};
+
+ EXPECT_TRUE((std::is_same<record, decltype(*test1)>()));
+ EXPECT_TRUE((std::is_same<choice, decltype(test1.get_key())>()));
+ EXPECT_TRUE((std::is_same<one, decltype(*(test1.make_value_iterator()))>()));
+ EXPECT_TRUE((std::is_same<one, decltype(*(test1.make_value_range().begin()))>()));
+ EXPECT_TRUE(
+ (std::is_same<bytes, decltype(*(test1.make_value_iterator<MONERO_FIELD(one, k)>()))>())
+ );
+ EXPECT_TRUE(
+ (std::is_same<bytes, decltype(*(test1.make_value_range<MONERO_FIELD(one, k)>().begin()))>())
+ );
+
+ EXPECT_TRUE(test1.is_end());
+ EXPECT_NO_THROW(++test1);
+ EXPECT_NO_THROW(test1++);
+ EXPECT_TRUE(test1.is_end());
+ EXPECT_TRUE(test1.make_value_iterator().is_end());
+ EXPECT_TRUE(test1.make_value_range().empty());
+
+ lmdb::key_iterator<choice, one> test2{nullptr};
+
+ EXPECT_TRUE(test2.is_end());
+ EXPECT_NO_THROW(++test2);
+ EXPECT_NO_THROW(test2++);
+ EXPECT_TRUE(test2.is_end());
+ EXPECT_TRUE(test2.make_value_iterator().is_end());
+ EXPECT_TRUE(test2.make_value_range().empty());
+
+ EXPECT_TRUE(test1.equal(test2));
+ EXPECT_TRUE(test2.equal(test1));
+ EXPECT_TRUE(test1 == test2);
+ EXPECT_TRUE(test2 == test1);
+ EXPECT_FALSE(test1 != test2);
+ EXPECT_FALSE(test2 != test1);
+}
+
+
diff --git a/tests/unit_tests/long_term_block_weight.cpp b/tests/unit_tests/long_term_block_weight.cpp
index f37b608b6..ce6ff3551 100644
--- a/tests/unit_tests/long_term_block_weight.cpp
+++ b/tests/unit_tests/long_term_block_weight.cpp
@@ -64,6 +64,18 @@ public:
virtual uint64_t height() const override { return blocks.size(); }
virtual size_t get_block_weight(const uint64_t &h) const override { return blocks[h].weight; }
virtual uint64_t get_block_long_term_weight(const uint64_t &h) const override { return blocks[h].long_term_weight; }
+ virtual std::vector<uint64_t> get_block_weights(uint64_t start_height, size_t count) const override {
+ std::vector<uint64_t> ret;
+ ret.reserve(count);
+ while (count-- && start_height < blocks.size()) ret.push_back(blocks[start_height++].weight);
+ return ret;
+ }
+ virtual std::vector<uint64_t> get_long_term_block_weights(uint64_t start_height, size_t count) const override {
+ std::vector<uint64_t> ret;
+ ret.reserve(count);
+ while (count-- && start_height < blocks.size()) ret.push_back(blocks[start_height++].long_term_weight);
+ return ret;
+ }
virtual crypto::hash top_block_hash(uint64_t *block_height = NULL) const override {
uint64_t h = height();
crypto::hash top = crypto::null_hash;
diff --git a/tests/unit_tests/multisig.cpp b/tests/unit_tests/multisig.cpp
index 9a74b3dce..c5917200e 100644
--- a/tests/unit_tests/multisig.cpp
+++ b/tests/unit_tests/multisig.cpp
@@ -71,7 +71,7 @@ static void make_wallet(unsigned int idx, tools::wallet2 &wallet)
try
{
- wallet.init("");
+ wallet.init("", boost::none, boost::asio::ip::tcp::endpoint{}, 0, true, epee::net_utils::ssl_support_t::e_ssl_support_disabled);
wallet.set_subaddress_lookahead(1, 1);
wallet.generate("", "", spendkey, true, false);
ASSERT_TRUE(test_addresses[idx].address == wallet.get_account().get_public_address_str(cryptonote::TESTNET));
diff --git a/tests/unit_tests/net.cpp b/tests/unit_tests/net.cpp
index a38ecfe81..77fb71d96 100644
--- a/tests/unit_tests/net.cpp
+++ b/tests/unit_tests/net.cpp
@@ -33,6 +33,7 @@
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/read.hpp>
+#include <boost/asio/steady_timer.hpp>
#include <boost/asio/write.hpp>
#include <boost/endian/conversion.hpp>
#include <boost/system/error_code.hpp>
@@ -45,6 +46,7 @@
#include "net/error.h"
#include "net/net_utils_base.h"
#include "net/socks.h"
+#include "net/socks_connect.h"
#include "net/parse.h"
#include "net/tor_address.h"
#include "p2p/net_peerlist_boost_serialization.h"
@@ -742,4 +744,92 @@ TEST(socks_client, resolve_command)
while (test_client->called_ == 1);
}
+TEST(socks_connector, host)
+{
+ io_thread io{};
+ boost::asio::steady_timer timeout{io.io_service};
+ timeout.expires_from_now(std::chrono::seconds{5});
+
+ boost::unique_future<boost::asio::ip::tcp::socket> sock =
+ net::socks::connector{io.acceptor.local_endpoint()}("example.com", "8080", timeout);
+
+ while (!io.connected);
+ const std::uint8_t expected_bytes[] = {
+ 4, 1, 0x1f, 0x90, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm', 0x00
+ };
+
+ std::uint8_t actual_bytes[sizeof(expected_bytes)];
+ boost::asio::read(io.server, boost::asio::buffer(actual_bytes));
+ EXPECT_TRUE(std::memcmp(expected_bytes, actual_bytes, sizeof(actual_bytes)) == 0);
+
+ const std::uint8_t reply_bytes[] = {0, 90, 0, 0, 0, 0, 0, 0};
+ boost::asio::write(io.server, boost::asio::buffer(reply_bytes));
+
+ ASSERT_EQ(boost::future_status::ready, sock.wait_for(boost::chrono::seconds{3}));
+ EXPECT_TRUE(sock.get().is_open());
+}
+
+TEST(socks_connector, ipv4)
+{
+ io_thread io{};
+ boost::asio::steady_timer timeout{io.io_service};
+ timeout.expires_from_now(std::chrono::seconds{5});
+
+ boost::unique_future<boost::asio::ip::tcp::socket> sock =
+ net::socks::connector{io.acceptor.local_endpoint()}("250.88.125.99", "8080", timeout);
+
+ while (!io.connected);
+ const std::uint8_t expected_bytes[] = {
+ 4, 1, 0x1f, 0x90, 0xfa, 0x58, 0x7d, 0x63, 0x00
+ };
+
+ std::uint8_t actual_bytes[sizeof(expected_bytes)];
+ boost::asio::read(io.server, boost::asio::buffer(actual_bytes));
+ EXPECT_TRUE(std::memcmp(expected_bytes, actual_bytes, sizeof(actual_bytes)) == 0);
+
+ const std::uint8_t reply_bytes[] = {0, 90, 0, 0, 0, 0, 0, 0};
+ boost::asio::write(io.server, boost::asio::buffer(reply_bytes));
+
+ ASSERT_EQ(boost::future_status::ready, sock.wait_for(boost::chrono::seconds{3}));
+ EXPECT_TRUE(sock.get().is_open());
+}
+
+TEST(socks_connector, error)
+{
+ io_thread io{};
+ boost::asio::steady_timer timeout{io.io_service};
+ timeout.expires_from_now(std::chrono::seconds{5});
+
+ boost::unique_future<boost::asio::ip::tcp::socket> sock =
+ net::socks::connector{io.acceptor.local_endpoint()}("250.88.125.99", "8080", timeout);
+
+ while (!io.connected);
+ const std::uint8_t expected_bytes[] = {
+ 4, 1, 0x1f, 0x90, 0xfa, 0x58, 0x7d, 0x63, 0x00
+ };
+
+ std::uint8_t actual_bytes[sizeof(expected_bytes)];
+ boost::asio::read(io.server, boost::asio::buffer(actual_bytes));
+ EXPECT_TRUE(std::memcmp(expected_bytes, actual_bytes, sizeof(actual_bytes)) == 0);
+
+ const std::uint8_t reply_bytes[] = {0, 91, 0, 0, 0, 0, 0, 0};
+ boost::asio::write(io.server, boost::asio::buffer(reply_bytes));
+
+ ASSERT_EQ(boost::future_status::ready, sock.wait_for(boost::chrono::seconds{3}));
+ EXPECT_THROW(sock.get().is_open(), boost::system::system_error);
+}
+
+TEST(socks_connector, timeout)
+{
+ io_thread io{};
+ boost::asio::steady_timer timeout{io.io_service};
+ timeout.expires_from_now(std::chrono::milliseconds{10});
+
+ boost::unique_future<boost::asio::ip::tcp::socket> sock =
+ net::socks::connector{io.acceptor.local_endpoint()}("250.88.125.99", "8080", timeout);
+
+ ASSERT_EQ(boost::future_status::ready, sock.wait_for(boost::chrono::seconds{3}));
+ EXPECT_THROW(sock.get().is_open(), boost::system::system_error);
+}
diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp
index eb70caefc..27b14ffff 100644
--- a/tests/unit_tests/serialization.cpp
+++ b/tests/unit_tests/serialization.cpp
@@ -1187,3 +1187,26 @@ TEST(Serialization, portability_signed_tx)
ASSERT_TRUE(epee::string_tools::pod_to_hex(ki1) == "d54cbd435a8d636ad9b01b8d4f3eb13bd0cf1ce98eddf53ab1617f9b763e66c0");
ASSERT_TRUE(epee::string_tools::pod_to_hex(ki2) == "6c3cd6af97c4070a7aef9b1344e7463e29c7cd245076fdb65da447a34da3ca76");
}
+
+TEST(Serialization, difficulty_type)
+{
+ std::vector<cryptonote::difficulty_type> v_original;
+
+ for(int i = 0; i != 100; i++)
+ {
+ v_original.push_back(cryptonote::difficulty_type("117868131154734361989189100"));
+ if(v_original.size() > 1)
+ v_original.back() *= v_original[v_original.size()-2];
+ }
+
+ std::stringstream ss;
+ boost::archive::portable_binary_oarchive a(ss);
+ a << v_original;
+
+ std::vector<cryptonote::difficulty_type> v_unserialized;
+
+ boost::archive::portable_binary_iarchive a2(ss);
+ a2 >> v_unserialized;
+
+ ASSERT_EQ(v_original, v_unserialized);
+}