@@ -31,6 +31,24 @@ class snapshotted_tester : public base_tester {
31
31
init (copied_config, snapshot);
32
32
}
33
33
34
+ snapshotted_tester (controller::config config, const snapshot_reader_ptr& snapshot, int ordinal, int copy_block_log_from_ordinal) {
35
+ FC_ASSERT (config.blocks_dir .filename ().generic_string () != " ."
36
+ && config.state_dir .filename ().generic_string () != " ." , " invalid path names in controller::config" );
37
+
38
+ controller::config copied_config = config;
39
+ copied_config.blocks_dir =
40
+ config.blocks_dir .parent_path () / std::to_string (ordinal).append (config.blocks_dir .filename ().generic_string ());
41
+ copied_config.state_dir =
42
+ config.state_dir .parent_path () / std::to_string (ordinal).append (config.state_dir .filename ().generic_string ());
43
+
44
+ // create a copy of the desired block log and reversible
45
+ auto block_log_path = config.blocks_dir .parent_path () / std::to_string (copy_block_log_from_ordinal).append (config.blocks_dir .filename ().generic_string ());
46
+ fc::create_directories (copied_config.blocks_dir );
47
+ fc::copy (block_log_path / " blocks.log" , copied_config.blocks_dir / " blocks.log" );
48
+ fc::copy (block_log_path / config::reversible_blocks_dir_name, copied_config.blocks_dir / config::reversible_blocks_dir_name );
49
+
50
+ init (copied_config, snapshot);
51
+ }
34
52
signed_block_ptr produce_block ( fc::microseconds skip_time = fc::milliseconds(config::block_interval_ms), uint32_t skip_flag = 0/* skip_missed_block_penalty*/ )override {
35
53
return _produce_block (skip_time, false , skip_flag);
36
54
}
@@ -45,7 +63,7 @@ class snapshotted_tester : public base_tester {
45
63
46
64
BOOST_AUTO_TEST_SUITE (snapshot_tests)
47
65
48
- BOOST_AUTO_TEST_CASE(test_multi_index_snapshot )
66
+ BOOST_AUTO_TEST_CASE(test_exhaustive_snapshot )
49
67
{
50
68
tester chain;
51
69
@@ -56,8 +74,7 @@ BOOST_AUTO_TEST_CASE(test_multi_index_snapshot)
56
74
chain.produce_blocks (1 );
57
75
chain.control ->abort_block ();
58
76
59
-
60
- static const int generation_count = 20 ;
77
+ static const int generation_count = 8 ;
61
78
std::list<snapshotted_tester> sub_testers;
62
79
63
80
for (int generation = 0 ; generation < generation_count; generation++) {
@@ -71,6 +88,9 @@ BOOST_AUTO_TEST_CASE(test_multi_index_snapshot)
71
88
sub_testers.emplace_back (chain.get_config (), std::make_shared<variant_snapshot_reader>(snapshot), generation);
72
89
73
90
// increment the test contract
91
+ chain.push_action (N (snapshot), N (increment), N (snapshot), mutable_variant_object ()
92
+ ( " value" , 1 )
93
+ );
74
94
75
95
// produce block
76
96
auto new_block = chain.produce_block ();
@@ -88,4 +108,62 @@ BOOST_AUTO_TEST_CASE(test_multi_index_snapshot)
88
108
}
89
109
}
90
110
111
+ BOOST_AUTO_TEST_CASE (test_replay_over_snapshot)
112
+ {
113
+ tester chain;
114
+
115
+ chain.create_account (N (snapshot));
116
+ chain.produce_blocks (1 );
117
+ chain.set_code (N (snapshot), snapshot_test_wast);
118
+ chain.set_abi (N (snapshot), snapshot_test_abi);
119
+ chain.produce_blocks (1 );
120
+ chain.control ->abort_block ();
121
+
122
+ static const int pre_snapshot_block_count = 12 ;
123
+ static const int post_snapshot_block_count = 12 ;
124
+
125
+ for (int itr = 0 ; itr < pre_snapshot_block_count; itr++) {
126
+ // increment the contract
127
+ chain.push_action (N (snapshot), N (increment), N (snapshot), mutable_variant_object ()
128
+ ( " value" , 1 )
129
+ );
130
+
131
+ // produce block
132
+ chain.produce_block ();
133
+ }
134
+
135
+ chain.control ->abort_block ();
136
+ auto expected_pre_integrity_hash = chain.control ->calculate_integrity_hash ();
137
+
138
+ // create a new snapshot child
139
+ variant_snapshot_writer writer;
140
+ auto writer_p = std::shared_ptr<snapshot_writer>(&writer, [](snapshot_writer *){});
141
+ chain.control ->write_snapshot (writer_p);
142
+ auto snapshot = writer.finalize ();
143
+
144
+ // create a new child at this snapshot
145
+ snapshotted_tester snap_chain (chain.get_config (), std::make_shared<variant_snapshot_reader>(snapshot), 1 );
146
+ BOOST_REQUIRE_EQUAL (expected_pre_integrity_hash.str (), snap_chain.control ->calculate_integrity_hash ().str ());
147
+
148
+ // push more blocks to build up a block log
149
+ for (int itr = 0 ; itr < post_snapshot_block_count; itr++) {
150
+ // increment the contract
151
+ chain.push_action (N (snapshot), N (increment), N (snapshot), mutable_variant_object ()
152
+ ( " value" , 1 )
153
+ );
154
+
155
+ // produce & push block
156
+ snap_chain.push_block (chain.produce_block ());
157
+ }
158
+
159
+ // verify the hash at the end
160
+ chain.control ->abort_block ();
161
+ auto expected_post_integrity_hash = chain.control ->calculate_integrity_hash ();
162
+ BOOST_REQUIRE_EQUAL (expected_post_integrity_hash.str (), snap_chain.control ->calculate_integrity_hash ().str ());
163
+
164
+ // replay the block log from the snapshot child, from the snapshot
165
+ snapshotted_tester replay_chain (chain.get_config (), std::make_shared<variant_snapshot_reader>(snapshot), 2 , 1 );
166
+ BOOST_REQUIRE_EQUAL (expected_post_integrity_hash.str (), snap_chain.control ->calculate_integrity_hash ().str ());
167
+ }
168
+
91
169
BOOST_AUTO_TEST_SUITE_END ()
0 commit comments