2022-12-24 23:49:50 +00:00
|
|
|
// Copyright (c) 2015-2022 The Bitcoin Core developers
|
2015-10-29 07:11:24 +01:00
|
|
|
// Distributed under the MIT software license, see the accompanying
|
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
|
2017-11-10 13:57:53 +13:00
|
|
|
#include <prevector.h>
|
|
|
|
#include <serialize.h>
|
|
|
|
#include <streams.h>
|
2023-01-22 09:57:19 -08:00
|
|
|
#include <test/util/random.h>
|
2019-11-05 15:18:59 -05:00
|
|
|
#include <test/util/setup_common.h>
|
2015-10-29 07:11:24 +01:00
|
|
|
|
|
|
|
#include <boost/test/unit_test.hpp>
|
|
|
|
|
2023-10-19 12:46:32 +01:00
|
|
|
#include <ranges>
|
|
|
|
#include <vector>
|
|
|
|
|
2018-03-18 18:52:30 +01:00
|
|
|
BOOST_FIXTURE_TEST_SUITE(prevector_tests, TestingSetup)
|
2015-10-29 07:11:24 +01:00
|
|
|
|
|
|
|
template<unsigned int N, typename T>
|
|
|
|
class prevector_tester {
|
|
|
|
typedef std::vector<T> realtype;
|
|
|
|
realtype real_vector;
|
2016-04-16 06:49:38 -07:00
|
|
|
realtype real_vector_alt;
|
2015-10-29 07:11:24 +01:00
|
|
|
|
|
|
|
typedef prevector<N, T> pretype;
|
|
|
|
pretype pre_vector;
|
2016-04-16 06:49:38 -07:00
|
|
|
pretype pre_vector_alt;
|
2015-10-29 07:11:24 +01:00
|
|
|
|
|
|
|
typedef typename pretype::size_type Size;
|
2016-09-06 16:19:25 -04:00
|
|
|
bool passed = true;
|
2016-10-13 16:19:20 +02:00
|
|
|
FastRandomContext rand_cache;
|
2017-02-15 17:45:22 -08:00
|
|
|
uint256 rand_seed;
|
2015-10-29 07:11:24 +01:00
|
|
|
|
2016-09-06 16:19:25 -04:00
|
|
|
|
|
|
|
template <typename A, typename B>
|
|
|
|
void local_check_equal(A a, B b)
|
|
|
|
{
|
|
|
|
local_check(a == b);
|
|
|
|
}
|
2018-07-24 16:59:49 +01:00
|
|
|
void local_check(bool b)
|
2016-09-06 16:19:25 -04:00
|
|
|
{
|
|
|
|
passed &= b;
|
|
|
|
}
|
2015-10-29 07:11:24 +01:00
|
|
|
void test() {
|
|
|
|
const pretype& const_pre_vector = pre_vector;
|
2016-09-06 16:19:25 -04:00
|
|
|
local_check_equal(real_vector.size(), pre_vector.size());
|
|
|
|
local_check_equal(real_vector.empty(), pre_vector.empty());
|
2015-10-29 07:11:24 +01:00
|
|
|
for (Size s = 0; s < real_vector.size(); s++) {
|
2016-09-06 16:19:25 -04:00
|
|
|
local_check(real_vector[s] == pre_vector[s]);
|
|
|
|
local_check(&(pre_vector[s]) == &(pre_vector.begin()[s]));
|
|
|
|
local_check(&(pre_vector[s]) == &*(pre_vector.begin() + s));
|
|
|
|
local_check(&(pre_vector[s]) == &*((pre_vector.end() + s) - real_vector.size()));
|
2015-10-29 07:11:24 +01:00
|
|
|
}
|
2016-09-06 16:19:25 -04:00
|
|
|
// local_check(realtype(pre_vector) == real_vector);
|
|
|
|
local_check(pretype(real_vector.begin(), real_vector.end()) == pre_vector);
|
|
|
|
local_check(pretype(pre_vector.begin(), pre_vector.end()) == pre_vector);
|
2015-10-29 07:11:24 +01:00
|
|
|
size_t pos = 0;
|
2017-06-02 03:18:57 +02:00
|
|
|
for (const T& v : pre_vector) {
|
2016-09-06 16:19:25 -04:00
|
|
|
local_check(v == real_vector[pos++]);
|
2015-10-29 07:11:24 +01:00
|
|
|
}
|
2023-10-19 12:46:32 +01:00
|
|
|
for (const T& v : pre_vector | std::views::reverse) {
|
|
|
|
local_check(v == real_vector[--pos]);
|
2015-10-29 07:11:24 +01:00
|
|
|
}
|
2017-06-02 03:18:57 +02:00
|
|
|
for (const T& v : const_pre_vector) {
|
2016-09-06 16:19:25 -04:00
|
|
|
local_check(v == real_vector[pos++]);
|
2015-10-29 07:11:24 +01:00
|
|
|
}
|
2023-10-19 12:46:32 +01:00
|
|
|
for (const T& v : const_pre_vector | std::views::reverse) {
|
|
|
|
local_check(v == real_vector[--pos]);
|
2015-10-29 07:11:24 +01:00
|
|
|
}
|
2023-01-03 13:21:44 +01:00
|
|
|
DataStream ss1{};
|
|
|
|
DataStream ss2{};
|
2015-10-29 07:11:24 +01:00
|
|
|
ss1 << real_vector;
|
|
|
|
ss2 << pre_vector;
|
2016-09-06 16:19:25 -04:00
|
|
|
local_check_equal(ss1.size(), ss2.size());
|
2015-10-29 07:11:24 +01:00
|
|
|
for (Size s = 0; s < ss1.size(); s++) {
|
2016-09-06 16:19:25 -04:00
|
|
|
local_check_equal(ss1[s], ss2[s]);
|
2015-10-29 07:11:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
void resize(Size s) {
|
|
|
|
real_vector.resize(s);
|
2016-09-06 16:19:25 -04:00
|
|
|
local_check_equal(real_vector.size(), s);
|
2015-10-29 07:11:24 +01:00
|
|
|
pre_vector.resize(s);
|
2016-09-06 16:19:25 -04:00
|
|
|
local_check_equal(pre_vector.size(), s);
|
2015-10-29 07:11:24 +01:00
|
|
|
test();
|
|
|
|
}
|
|
|
|
|
|
|
|
void reserve(Size s) {
|
|
|
|
real_vector.reserve(s);
|
2016-09-06 16:19:25 -04:00
|
|
|
local_check(real_vector.capacity() >= s);
|
2015-10-29 07:11:24 +01:00
|
|
|
pre_vector.reserve(s);
|
2016-09-06 16:19:25 -04:00
|
|
|
local_check(pre_vector.capacity() >= s);
|
2015-10-29 07:11:24 +01:00
|
|
|
test();
|
|
|
|
}
|
|
|
|
|
|
|
|
void insert(Size position, const T& value) {
|
|
|
|
real_vector.insert(real_vector.begin() + position, value);
|
|
|
|
pre_vector.insert(pre_vector.begin() + position, value);
|
|
|
|
test();
|
|
|
|
}
|
|
|
|
|
|
|
|
void insert(Size position, Size count, const T& value) {
|
|
|
|
real_vector.insert(real_vector.begin() + position, count, value);
|
|
|
|
pre_vector.insert(pre_vector.begin() + position, count, value);
|
|
|
|
test();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename I>
|
|
|
|
void insert_range(Size position, I first, I last) {
|
|
|
|
real_vector.insert(real_vector.begin() + position, first, last);
|
|
|
|
pre_vector.insert(pre_vector.begin() + position, first, last);
|
|
|
|
test();
|
|
|
|
}
|
|
|
|
|
|
|
|
void erase(Size position) {
|
|
|
|
real_vector.erase(real_vector.begin() + position);
|
|
|
|
pre_vector.erase(pre_vector.begin() + position);
|
|
|
|
test();
|
|
|
|
}
|
|
|
|
|
|
|
|
void erase(Size first, Size last) {
|
|
|
|
real_vector.erase(real_vector.begin() + first, real_vector.begin() + last);
|
|
|
|
pre_vector.erase(pre_vector.begin() + first, pre_vector.begin() + last);
|
|
|
|
test();
|
|
|
|
}
|
|
|
|
|
|
|
|
void update(Size pos, const T& value) {
|
|
|
|
real_vector[pos] = value;
|
|
|
|
pre_vector[pos] = value;
|
|
|
|
test();
|
|
|
|
}
|
|
|
|
|
|
|
|
void push_back(const T& value) {
|
|
|
|
real_vector.push_back(value);
|
|
|
|
pre_vector.push_back(value);
|
|
|
|
test();
|
|
|
|
}
|
|
|
|
|
|
|
|
void pop_back() {
|
|
|
|
real_vector.pop_back();
|
|
|
|
pre_vector.pop_back();
|
|
|
|
test();
|
|
|
|
}
|
|
|
|
|
|
|
|
void clear() {
|
|
|
|
real_vector.clear();
|
|
|
|
pre_vector.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void assign(Size n, const T& value) {
|
|
|
|
real_vector.assign(n, value);
|
|
|
|
pre_vector.assign(n, value);
|
|
|
|
}
|
|
|
|
|
2017-03-09 13:34:54 +01:00
|
|
|
Size size() const {
|
2015-10-29 07:11:24 +01:00
|
|
|
return real_vector.size();
|
|
|
|
}
|
|
|
|
|
2017-03-09 13:34:54 +01:00
|
|
|
Size capacity() const {
|
2015-10-29 07:11:24 +01:00
|
|
|
return pre_vector.capacity();
|
|
|
|
}
|
|
|
|
|
|
|
|
void shrink_to_fit() {
|
|
|
|
pre_vector.shrink_to_fit();
|
|
|
|
test();
|
|
|
|
}
|
2016-04-16 06:49:38 -07:00
|
|
|
|
2022-04-28 13:33:57 +02:00
|
|
|
void swap() noexcept
|
|
|
|
{
|
2016-04-16 06:49:38 -07:00
|
|
|
real_vector.swap(real_vector_alt);
|
|
|
|
pre_vector.swap(pre_vector_alt);
|
|
|
|
test();
|
|
|
|
}
|
2016-12-13 19:36:46 -08:00
|
|
|
|
|
|
|
void move() {
|
|
|
|
real_vector = std::move(real_vector_alt);
|
|
|
|
real_vector_alt.clear();
|
|
|
|
pre_vector = std::move(pre_vector_alt);
|
|
|
|
pre_vector_alt.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void copy() {
|
|
|
|
real_vector = real_vector_alt;
|
|
|
|
pre_vector = pre_vector_alt;
|
|
|
|
}
|
|
|
|
|
2018-02-01 19:34:50 +09:00
|
|
|
void resize_uninitialized(realtype values) {
|
|
|
|
size_t r = values.size();
|
|
|
|
size_t s = real_vector.size() / 2;
|
|
|
|
if (real_vector.capacity() < s + r) {
|
|
|
|
real_vector.reserve(s + r);
|
|
|
|
}
|
|
|
|
real_vector.resize(s);
|
|
|
|
pre_vector.resize_uninitialized(s);
|
|
|
|
for (auto v : values) {
|
|
|
|
real_vector.push_back(v);
|
|
|
|
}
|
|
|
|
auto p = pre_vector.size();
|
|
|
|
pre_vector.resize_uninitialized(p + r);
|
|
|
|
for (auto v : values) {
|
|
|
|
pre_vector[p] = v;
|
|
|
|
++p;
|
|
|
|
}
|
|
|
|
test();
|
|
|
|
}
|
|
|
|
|
2016-09-06 16:19:25 -04:00
|
|
|
~prevector_tester() {
|
2017-02-15 17:45:22 -08:00
|
|
|
BOOST_CHECK_MESSAGE(passed, "insecure_rand: " + rand_seed.ToString());
|
2016-09-06 16:19:25 -04:00
|
|
|
}
|
2017-02-15 17:45:22 -08:00
|
|
|
|
2016-09-06 16:19:25 -04:00
|
|
|
prevector_tester() {
|
tests: overhaul deterministic test randomness
The existing code provides two randomness mechanisms for test purposes:
- g_insecure_rand_ctx (with its wrappers InsecureRand*), which during tests is
initialized using either zeros (SeedRand::ZEROS), or using environment-provided
randomness (SeedRand::SEED).
- g_mock_deterministic_tests, which controls some (but not all) of the normal
randomness output if set, but then makes it extremely predictable (identical
output repeatedly).
Replace this with a single mechanism, which retains the SeedRand modes to control
all randomness. There is a new internal deterministic PRNG inside the random
module, which is used in GetRandBytes() when in test mode, and which is also used
to initialize g_insecure_rand_ctx. This means that during tests, all random numbers
are made deterministic. There is one exception, GetStrongRandBytes(), which even
in test mode still uses the normal PRNG state.
This probably opens the door to removing a lot of the ad-hoc "deterministic" mode
functions littered through the codebase (by simply running relevant tests in
SeedRand::ZEROS mode), but this isn't done yet.
2024-03-10 19:49:42 -04:00
|
|
|
SeedRandomForTest();
|
2018-10-31 15:51:57 -07:00
|
|
|
rand_seed = InsecureRand256();
|
2024-05-31 10:39:23 -04:00
|
|
|
rand_cache.Reseed(rand_seed);
|
2016-09-06 16:19:25 -04:00
|
|
|
}
|
2015-10-29 07:11:24 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(PrevectorTestInt)
|
|
|
|
{
|
|
|
|
for (int j = 0; j < 64; j++) {
|
|
|
|
prevector_tester<8, int> test;
|
|
|
|
for (int i = 0; i < 2048; i++) {
|
2017-06-07 12:03:17 -07:00
|
|
|
if (InsecureRandBits(2) == 0) {
|
2022-01-02 16:53:02 +01:00
|
|
|
test.insert(InsecureRandRange(test.size() + 1), int(InsecureRand32()));
|
2015-10-29 07:11:24 +01:00
|
|
|
}
|
2017-06-07 12:03:17 -07:00
|
|
|
if (test.size() > 0 && InsecureRandBits(2) == 1) {
|
|
|
|
test.erase(InsecureRandRange(test.size()));
|
2015-10-29 07:11:24 +01:00
|
|
|
}
|
2017-06-07 12:03:17 -07:00
|
|
|
if (InsecureRandBits(3) == 2) {
|
2018-02-23 08:10:42 +01:00
|
|
|
int new_size = std::max(0, std::min(30, (int)test.size() + (int)InsecureRandRange(5) - 2));
|
2015-10-29 07:11:24 +01:00
|
|
|
test.resize(new_size);
|
|
|
|
}
|
2017-06-07 12:03:17 -07:00
|
|
|
if (InsecureRandBits(3) == 3) {
|
2022-01-02 16:53:02 +01:00
|
|
|
test.insert(InsecureRandRange(test.size() + 1), 1 + InsecureRandBool(), int(InsecureRand32()));
|
2015-10-29 07:11:24 +01:00
|
|
|
}
|
2017-06-07 12:03:17 -07:00
|
|
|
if (InsecureRandBits(3) == 4) {
|
|
|
|
int del = std::min<int>(test.size(), 1 + (InsecureRandBool()));
|
|
|
|
int beg = InsecureRandRange(test.size() + 1 - del);
|
2015-10-29 07:11:24 +01:00
|
|
|
test.erase(beg, beg + del);
|
|
|
|
}
|
2017-06-07 12:03:17 -07:00
|
|
|
if (InsecureRandBits(4) == 5) {
|
2022-01-02 16:53:02 +01:00
|
|
|
test.push_back(int(InsecureRand32()));
|
2015-10-29 07:11:24 +01:00
|
|
|
}
|
2017-06-07 12:03:17 -07:00
|
|
|
if (test.size() > 0 && InsecureRandBits(4) == 6) {
|
2015-10-29 07:11:24 +01:00
|
|
|
test.pop_back();
|
|
|
|
}
|
2017-06-07 12:03:17 -07:00
|
|
|
if (InsecureRandBits(5) == 7) {
|
2015-10-29 07:11:24 +01:00
|
|
|
int values[4];
|
2017-06-07 12:03:17 -07:00
|
|
|
int num = 1 + (InsecureRandBits(2));
|
2016-06-07 21:22:48 +02:00
|
|
|
for (int k = 0; k < num; k++) {
|
2022-01-02 16:53:02 +01:00
|
|
|
values[k] = int(InsecureRand32());
|
2015-10-29 07:11:24 +01:00
|
|
|
}
|
2017-06-07 12:03:17 -07:00
|
|
|
test.insert_range(InsecureRandRange(test.size() + 1), values, values + num);
|
2015-10-29 07:11:24 +01:00
|
|
|
}
|
2017-06-07 12:03:17 -07:00
|
|
|
if (InsecureRandBits(5) == 8) {
|
|
|
|
int del = std::min<int>(test.size(), 1 + (InsecureRandBits(2)));
|
|
|
|
int beg = InsecureRandRange(test.size() + 1 - del);
|
2015-10-29 07:11:24 +01:00
|
|
|
test.erase(beg, beg + del);
|
|
|
|
}
|
2017-06-07 12:03:17 -07:00
|
|
|
if (InsecureRandBits(5) == 9) {
|
|
|
|
test.reserve(InsecureRandBits(5));
|
2015-10-29 07:11:24 +01:00
|
|
|
}
|
2017-06-07 12:03:17 -07:00
|
|
|
if (InsecureRandBits(6) == 10) {
|
2015-10-29 07:11:24 +01:00
|
|
|
test.shrink_to_fit();
|
|
|
|
}
|
|
|
|
if (test.size() > 0) {
|
2022-01-02 16:53:02 +01:00
|
|
|
test.update(InsecureRandRange(test.size()), int(InsecureRand32()));
|
2015-10-29 07:11:24 +01:00
|
|
|
}
|
2017-06-07 12:03:17 -07:00
|
|
|
if (InsecureRandBits(10) == 11) {
|
2015-10-29 07:11:24 +01:00
|
|
|
test.clear();
|
|
|
|
}
|
2017-06-07 12:03:17 -07:00
|
|
|
if (InsecureRandBits(9) == 12) {
|
2022-01-02 16:53:02 +01:00
|
|
|
test.assign(InsecureRandBits(5), int(InsecureRand32()));
|
2015-10-29 07:11:24 +01:00
|
|
|
}
|
2017-06-07 12:03:17 -07:00
|
|
|
if (InsecureRandBits(3) == 3) {
|
2016-04-16 06:49:38 -07:00
|
|
|
test.swap();
|
|
|
|
}
|
2017-06-07 12:03:17 -07:00
|
|
|
if (InsecureRandBits(4) == 8) {
|
2016-12-13 19:36:46 -08:00
|
|
|
test.copy();
|
|
|
|
}
|
2017-06-07 12:03:17 -07:00
|
|
|
if (InsecureRandBits(5) == 18) {
|
2016-12-13 19:36:46 -08:00
|
|
|
test.move();
|
|
|
|
}
|
2018-02-01 19:34:50 +09:00
|
|
|
if (InsecureRandBits(5) == 19) {
|
|
|
|
unsigned int num = 1 + (InsecureRandBits(4));
|
|
|
|
std::vector<int> values(num);
|
2022-01-02 16:53:02 +01:00
|
|
|
for (int& v : values) {
|
|
|
|
v = int(InsecureRand32());
|
2018-02-01 19:34:50 +09:00
|
|
|
}
|
|
|
|
test.resize_uninitialized(values);
|
|
|
|
}
|
2015-10-29 07:11:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_SUITE_END()
|