aboutsummaryrefslogtreecommitdiff
path: root/tests/unit_tests/pruning.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/unit_tests/pruning.cpp')
-rw-r--r--tests/unit_tests/pruning.cpp240
1 files changed, 240 insertions, 0 deletions
diff --git a/tests/unit_tests/pruning.cpp b/tests/unit_tests/pruning.cpp
new file mode 100644
index 000000000..83c35df68
--- /dev/null
+++ b/tests/unit_tests/pruning.cpp
@@ -0,0 +1,240 @@
+// 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 "misc_log_ex.h"
+#include "cryptonote_config.h"
+#include "common/pruning.h"
+
+#define ASSERT_EX(x) do { bool ex = false; try { x; } catch(...) { ex = true; } ASSERT_TRUE(ex); } while(0)
+
+TEST(pruning, parts)
+{
+ ASSERT_EQ(tools::get_pruning_stripe(tools::make_pruning_seed(3, 2)), 3);
+ ASSERT_EQ(tools::get_pruning_stripe(tools::make_pruning_seed(1, 2)), 1);
+ ASSERT_EQ(tools::get_pruning_stripe(tools::make_pruning_seed(7, 7)), 7);
+
+ ASSERT_EQ(tools::get_pruning_log_stripes(tools::make_pruning_seed(1, 2)), 2);
+ ASSERT_EQ(tools::get_pruning_log_stripes(tools::make_pruning_seed(1, 0)), 0);
+ ASSERT_EQ(tools::get_pruning_log_stripes(tools::make_pruning_seed(1, 7)), 7);
+ ASSERT_EQ(tools::get_pruning_log_stripes(tools::make_pruning_seed(7, 7)), 7);
+
+ for (uint32_t log_stripes = 1; log_stripes <= tools::PRUNING_SEED_LOG_STRIPES_MASK; ++log_stripes)
+ {
+ for (uint32_t stripe = 1; stripe <= (1 << log_stripes); ++stripe)
+ {
+ ASSERT_EQ(tools::get_pruning_log_stripes(tools::make_pruning_seed(stripe, log_stripes)), log_stripes);
+ ASSERT_EQ(tools::get_pruning_stripe(tools::make_pruning_seed(stripe, log_stripes)), stripe);
+ }
+ }
+}
+
+TEST(pruning, out_of_range)
+{
+ ASSERT_EX(tools::make_pruning_seed(5, 2));
+ ASSERT_EX(tools::make_pruning_seed(0, 2));
+}
+
+TEST(pruning, fits)
+{
+ const uint32_t log_stripes = 3;
+ const uint32_t num_stripes = 1 << log_stripes;
+ for (uint32_t stripe = 1; stripe <= num_stripes; ++stripe)
+ {
+ const uint32_t seed = tools::make_pruning_seed(stripe, log_stripes);
+ ASSERT_NE(seed, 0);
+ ASSERT_EQ(tools::get_pruning_log_stripes(seed), log_stripes);
+ ASSERT_EQ(tools::get_pruning_stripe(seed), stripe);
+ }
+}
+
+TEST(pruning, tip)
+{
+ static constexpr uint64_t H = CRYPTONOTE_PRUNING_TIP_BLOCKS + 1000;
+ static_assert(H >= CRYPTONOTE_PRUNING_TIP_BLOCKS, "H must be >= CRYPTONOTE_PRUNING_TIP_BLOCKS");
+ for (uint64_t h = H - CRYPTONOTE_PRUNING_TIP_BLOCKS; h < H; ++h)
+ {
+ uint32_t pruning_seed = tools::get_pruning_seed(h, H, CRYPTONOTE_PRUNING_LOG_STRIPES);
+ ASSERT_EQ(pruning_seed, 0);
+ for (pruning_seed = 0; pruning_seed <= (1 << CRYPTONOTE_PRUNING_LOG_STRIPES); ++pruning_seed)
+ ASSERT_TRUE(tools::has_unpruned_block(h, H, pruning_seed));
+ }
+}
+
+TEST(pruning, seed)
+{
+ const uint64_t SS = CRYPTONOTE_PRUNING_STRIPE_SIZE;
+ const uint64_t NS = 1 << CRYPTONOTE_PRUNING_LOG_STRIPES;
+ const uint64_t TB = NS * SS;
+
+ for (uint64_t cycle = 0; cycle < 10; ++cycle)
+ {
+ const uint64_t O = TB * cycle;
+ ASSERT_EQ(tools::get_pruning_stripe(O + 0, 10000000, CRYPTONOTE_PRUNING_LOG_STRIPES), 1);
+ ASSERT_EQ(tools::get_pruning_stripe(O + 1, 10000000, CRYPTONOTE_PRUNING_LOG_STRIPES), 1);
+ ASSERT_EQ(tools::get_pruning_stripe(O + SS-1, 10000000, CRYPTONOTE_PRUNING_LOG_STRIPES), 1);
+ ASSERT_EQ(tools::get_pruning_stripe(O + SS, 10000000, CRYPTONOTE_PRUNING_LOG_STRIPES), 2);
+ ASSERT_EQ(tools::get_pruning_stripe(O + SS*2-1, 10000000, CRYPTONOTE_PRUNING_LOG_STRIPES), 2);
+ ASSERT_EQ(tools::get_pruning_stripe(O + SS*2, 10000000, CRYPTONOTE_PRUNING_LOG_STRIPES), 3);
+ ASSERT_EQ(tools::get_pruning_stripe(O + SS*NS-1, 10000000, CRYPTONOTE_PRUNING_LOG_STRIPES), NS);
+ ASSERT_EQ(tools::get_pruning_stripe(O + SS*NS, 10000000, CRYPTONOTE_PRUNING_LOG_STRIPES), 1);
+ }
+}
+
+TEST(pruning, match)
+{
+ static constexpr uint64_t H = CRYPTONOTE_PRUNING_TIP_BLOCKS + 1000;
+ static_assert(H >= CRYPTONOTE_PRUNING_TIP_BLOCKS, "H must be >= CRYPTONOTE_PRUNING_TIP_BLOCKS");
+ for (uint64_t h = 0; h < H - CRYPTONOTE_PRUNING_TIP_BLOCKS; ++h)
+ {
+ uint32_t pruning_seed = tools::get_pruning_seed(h, H, CRYPTONOTE_PRUNING_LOG_STRIPES);
+ uint32_t pruning_stripe = tools::get_pruning_stripe(pruning_seed);
+ ASSERT_TRUE(pruning_stripe > 0 && pruning_stripe <= (1 << CRYPTONOTE_PRUNING_LOG_STRIPES));
+ for (uint32_t other_pruning_stripe = 1; other_pruning_stripe <= (1 << CRYPTONOTE_PRUNING_LOG_STRIPES); ++other_pruning_stripe)
+ {
+ uint32_t other_pruning_seed = tools::make_pruning_seed(other_pruning_stripe, CRYPTONOTE_PRUNING_LOG_STRIPES);
+ ASSERT_TRUE(tools::has_unpruned_block(h, H, other_pruning_seed) == (other_pruning_seed == pruning_seed));
+ }
+ }
+}
+
+TEST(pruning, stripe_size)
+{
+ static constexpr uint64_t H = CRYPTONOTE_PRUNING_TIP_BLOCKS + CRYPTONOTE_PRUNING_STRIPE_SIZE * (1 << CRYPTONOTE_PRUNING_LOG_STRIPES) + 1000;
+ static_assert(H >= CRYPTONOTE_PRUNING_TIP_BLOCKS + CRYPTONOTE_PRUNING_STRIPE_SIZE * (1 << CRYPTONOTE_PRUNING_LOG_STRIPES), "H must be >= that stuff in front");
+ for (uint32_t pruning_stripe = 1; pruning_stripe <= (1 << CRYPTONOTE_PRUNING_LOG_STRIPES); ++pruning_stripe)
+ {
+ uint32_t pruning_seed = tools::make_pruning_seed(pruning_stripe, CRYPTONOTE_PRUNING_LOG_STRIPES);
+ unsigned int current_run = 0, best_run = 0;
+ for (uint64_t h = 0; h < H - CRYPTONOTE_PRUNING_TIP_BLOCKS; ++h)
+ {
+ if (tools::has_unpruned_block(h, H, pruning_seed))
+ {
+ ++current_run;
+ }
+ else if (current_run)
+ {
+ ASSERT_EQ(current_run, CRYPTONOTE_PRUNING_STRIPE_SIZE);
+ best_run = std::max(best_run, current_run);
+ current_run = 0;
+ }
+ }
+ ASSERT_EQ(best_run, CRYPTONOTE_PRUNING_STRIPE_SIZE);
+ }
+}
+
+TEST(pruning, next_unpruned)
+{
+ static_assert((1 << CRYPTONOTE_PRUNING_LOG_STRIPES) >= 4, "CRYPTONOTE_PRUNING_LOG_STRIPES too low");
+
+ const uint64_t SS = CRYPTONOTE_PRUNING_STRIPE_SIZE;
+ const uint64_t NS = 1 << CRYPTONOTE_PRUNING_LOG_STRIPES;
+ const uint64_t TB = NS * SS;
+
+ for (uint64_t h = 0; h < 100; ++h)
+ ASSERT_EQ(tools::get_next_unpruned_block_height(h, 10000000, 0), h);
+
+ const uint32_t seed1 = tools::make_pruning_seed(1, CRYPTONOTE_PRUNING_LOG_STRIPES);
+ const uint32_t seed2 = tools::make_pruning_seed(2, CRYPTONOTE_PRUNING_LOG_STRIPES);
+ const uint32_t seed3 = tools::make_pruning_seed(3, CRYPTONOTE_PRUNING_LOG_STRIPES);
+ const uint32_t seed4 = tools::make_pruning_seed(4, CRYPTONOTE_PRUNING_LOG_STRIPES);
+ const uint32_t seedNS = tools::make_pruning_seed(NS, CRYPTONOTE_PRUNING_LOG_STRIPES);
+
+ ASSERT_EQ(tools::get_next_unpruned_block_height(0, 10000000, seed1), 0);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(1, 10000000, seed1), 1);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(SS-1, 10000000, seed1), SS-1);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(SS, 10000000, seed1), TB);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(TB, 10000000, seed1), TB);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(TB-1, 10000000, seed1), TB);
+
+ ASSERT_EQ(tools::get_next_unpruned_block_height(0, 10000000, seed2), SS);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(1, 10000000, seed2), SS);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(SS-1, 10000000, seed2), SS);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(SS, 10000000, seed2), SS);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(2*SS-1, 10000000, seed2), 2*SS-1);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(2*SS, 10000000, seed2), TB+SS);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(TB+2*SS,10000000, seed2), TB*2+SS);
+
+ ASSERT_EQ(tools::get_next_unpruned_block_height(0, 10000000, seed3), SS*2);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(SS, 10000000, seed3), SS*2);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(2*SS, 10000000, seed3), SS*2);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(3*SS-1, 10000000, seed3), SS*3-1);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(3*SS, 10000000, seed3), TB+SS*2);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(TB+3*SS,10000000, seed3), TB*2+SS*2);
+
+ ASSERT_EQ(tools::get_next_unpruned_block_height(SS, 10000000, seed4), 3*SS);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(4*SS-1, 10000000, seed4), 4*SS-1);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(4*SS, 10000000, seed4), TB+3*SS);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(TB+4*SS,10000000, seed4), TB*2+3*SS);
+
+ ASSERT_EQ(tools::get_next_unpruned_block_height(SS, 10000000, seedNS), (NS-1)*SS);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(NS*SS-1,10000000, seedNS), NS*SS-1);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(NS*SS, 10000000, seedNS), TB+(NS-1)*SS);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(TB+NS*SS, 10000000, seedNS), TB*2+(NS-1)*SS);
+}
+
+TEST(pruning, next_pruned)
+{
+ static_assert((1 << CRYPTONOTE_PRUNING_LOG_STRIPES) >= 4, "CRYPTONOTE_PRUNING_LOG_STRIPES too low");
+
+ const uint64_t SS = CRYPTONOTE_PRUNING_STRIPE_SIZE;
+ const uint64_t NS = 1 << CRYPTONOTE_PRUNING_LOG_STRIPES;
+ const uint64_t TB = NS * SS;
+
+ const uint32_t seed1 = tools::make_pruning_seed(1, CRYPTONOTE_PRUNING_LOG_STRIPES);
+ const uint32_t seed2 = tools::make_pruning_seed(2, CRYPTONOTE_PRUNING_LOG_STRIPES);
+ const uint32_t seedNS_1 = tools::make_pruning_seed(NS-1, CRYPTONOTE_PRUNING_LOG_STRIPES);
+ const uint32_t seedNS = tools::make_pruning_seed(NS, CRYPTONOTE_PRUNING_LOG_STRIPES);
+
+ for (uint64_t h = 0; h < 100; ++h)
+ ASSERT_EQ(tools::get_next_pruned_block_height(h, 10000000, 0), 10000000);
+ for (uint64_t h = 10000000 - 1 - CRYPTONOTE_PRUNING_TIP_BLOCKS; h < 10000000; ++h)
+ ASSERT_EQ(tools::get_next_pruned_block_height(h, 10000000, 0), 10000000);
+
+ ASSERT_EQ(tools::get_next_pruned_block_height(1, 10000000, seed1), SS);
+ ASSERT_EQ(tools::get_next_pruned_block_height(SS-1, 10000000, seed1), SS);
+ ASSERT_EQ(tools::get_next_pruned_block_height(SS, 10000000, seed1), SS);
+ ASSERT_EQ(tools::get_next_pruned_block_height(TB-1, 10000000, seed1), TB-1);
+ ASSERT_EQ(tools::get_next_pruned_block_height(TB, 10000000, seed1), TB+SS);
+
+ ASSERT_EQ(tools::get_next_pruned_block_height(1, 10000000, seed2), 1);
+ ASSERT_EQ(tools::get_next_pruned_block_height(SS-1, 10000000, seed2), SS-1);
+ ASSERT_EQ(tools::get_next_pruned_block_height(SS, 10000000, seed2), 2*SS);
+ ASSERT_EQ(tools::get_next_pruned_block_height(TB-1, 10000000, seed2), TB-1);
+
+ ASSERT_EQ(tools::get_next_pruned_block_height(1, 10000000, seedNS_1), 1);
+ ASSERT_EQ(tools::get_next_pruned_block_height(SS-1, 10000000, seedNS_1), SS-1);
+ ASSERT_EQ(tools::get_next_pruned_block_height(SS, 10000000, seedNS_1), SS);
+ ASSERT_EQ(tools::get_next_pruned_block_height(TB-1, 10000000, seedNS_1), TB-1);
+
+ ASSERT_EQ(tools::get_next_pruned_block_height(1, 10000000, seedNS), 1);
+ ASSERT_EQ(tools::get_next_pruned_block_height(SS-1, 10000000, seedNS), SS-1);
+ ASSERT_EQ(tools::get_next_pruned_block_height(SS, 10000000, seedNS), SS);
+ ASSERT_EQ(tools::get_next_pruned_block_height(TB-1, 10000000, seedNS), TB);
+}