blob: 7893df045c5f72aff2bc7055086c8bc71625d472 [file] [log] [blame]
Yingdi Yu0c3e5912015-03-17 14:22:38 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyevbe998ac2017-05-06 13:11:42 -07003 * Copyright (c) 2014-2017, Regents of the University of California
Yingdi Yu0c3e5912015-03-17 14:22:38 -07004 *
Alexander Afanasyevbe998ac2017-05-06 13:11:42 -07005 * This file is part of NDN DeLorean, An Authentication System for Data Archives in
6 * Named Data Networking. See AUTHORS.md for complete list of NDN DeLorean authors
7 * and contributors.
Yingdi Yu0c3e5912015-03-17 14:22:38 -07008 *
Alexander Afanasyevbe998ac2017-05-06 13:11:42 -07009 * NDN DeLorean is free software: you can redistribute it and/or modify it under
10 * the terms of the GNU General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option) any later
12 * version.
Yingdi Yu0c3e5912015-03-17 14:22:38 -070013 *
Alexander Afanasyevbe998ac2017-05-06 13:11:42 -070014 * NDN DeLorean is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
16 * PARTICULAR PURPOSE. See the GNU General Public License for more details.
Yingdi Yu0c3e5912015-03-17 14:22:38 -070017 *
Alexander Afanasyevbe998ac2017-05-06 13:11:42 -070018 * You should have received a copy of the GNU General Public License along with NDN
19 * DeLorean, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Yingdi Yu0c3e5912015-03-17 14:22:38 -070020 */
21
22#include "merkle-tree.hpp"
23#include "../tree-generator.hpp"
24#include "db-fixture.hpp"
25
26#include <boost/mpl/list.hpp>
27#include "boost-test.hpp"
28
Alexander Afanasyev49e2e4c2017-05-06 13:42:57 -070029namespace ndn {
30namespace delorean {
Yingdi Yu0c3e5912015-03-17 14:22:38 -070031namespace tests {
32
33BOOST_FIXTURE_TEST_SUITE(TestMerkleTree, DbFixture)
34
35BOOST_AUTO_TEST_CASE(Basic)
36{
37 MerkleTree merkleTree(TreeGenerator::LOGGER_NAME, db);
38 BOOST_CHECK_EQUAL(merkleTree.getNextLeafSeqNo(), 0);
39 BOOST_CHECK(merkleTree.getRootHash() == nullptr);
40}
41
42template<NonNegativeInteger N, size_t L>
43struct MerkleTreeTestParam
44{
45 const NonNegativeInteger leafNo = N;
46 const size_t rootLevel = L;
47};
48
49typedef boost::mpl::list<MerkleTreeTestParam<5, 3>,
50 MerkleTreeTestParam<32, 5>,
51 MerkleTreeTestParam<33, 6>,
52 MerkleTreeTestParam<1024, 10>,
53 MerkleTreeTestParam<1025, 11>> AddLeafTestParams;
54
55BOOST_AUTO_TEST_CASE_TEMPLATE(AddLeaf, T, AddLeafTestParams)
56{
57 T param;
58
59 NonNegativeInteger leafNo = param.leafNo;
60 size_t rootLevel = param.rootLevel;
61
62 MerkleTree merkleTree(TreeGenerator::LOGGER_NAME, db);
63 for (NonNegativeInteger i = 0; i < leafNo ; i++) {
64 BOOST_REQUIRE(merkleTree.addLeaf(i, Node::getEmptyHash()));
65 }
66
67 auto hash1 = TreeGenerator::getHash(Node::Index(0, rootLevel), leafNo);
68 auto hash2 = merkleTree.getRootHash();
69
70 BOOST_REQUIRE(hash1 != nullptr);
71 BOOST_REQUIRE(hash2 != nullptr);
72
73 BOOST_CHECK_EQUAL_COLLECTIONS(hash1->begin(), hash1->end(), hash2->begin(), hash2->end());
74}
75
76class MerkleTreeLoadTestParam1
77{
78public:
79 void
80 insertData(Db& db)
81 {
82 // partial first sub-tree
83 auto subtree1 = TreeGenerator::getSubTreeBinary(Node::Index(0, 5), 5);
84 db.insertSubTreeData(5, 0, *subtree1->encode(), false, 5);
85 }
86
87 const NonNegativeInteger seqNo = 0;
88 const size_t level = 3;
89 const NonNegativeInteger nextLeafSeqNo = 5;
90};
91
92class MerkleTreeLoadTestParam2
93{
94public:
95 void
96 insertData(Db& db)
97 {
98 // full first sub-tree
99 auto subtree1 = TreeGenerator::getSubTreeBinary(Node::Index(0, 5), 32);
100 auto subtree1Data = subtree1->encode();
101 db.insertSubTreeData(5, 0, *subtree1Data);
102
103 auto subtree2 = TreeGenerator::getSubTreeBinary(Node::Index(0, 10), 32);
104 auto subtree2Data = subtree2->encode();
105 db.insertSubTreeData(10, 0, *subtree2Data, false, 32);
106
107 auto subtree3 = make_shared<SubTreeBinary>(TreeGenerator::LOGGER_NAME,
108 Node::Index(32, 5),
109 [&] (const Node::Index&) {},
110 [&] (const Node::Index&,
111 const NonNegativeInteger&,
112 ndn::ConstBufferPtr) {});
113 auto subtree3Data = subtree3->encode();
114
115 db.insertSubTreeData(5, 32, *subtree3Data, false, 32);
116 }
117
118 const NonNegativeInteger seqNo = 0;
119 const size_t level = 5;
120 const NonNegativeInteger nextLeafSeqNo = 32;
121};
122
123class MerkleTreeLoadTestParam3
124{
125public:
126 void
127 insertData(Db& db)
128 {
129 auto subtree1 = TreeGenerator::getSubTreeBinary(Node::Index(0, 15), 1025);
130 auto subtree1Data = subtree1->encode();
131 db.insertSubTreeData(15, 0, *subtree1Data, false, 1025);
132
133 auto subtree2 = TreeGenerator::getSubTreeBinary(Node::Index(1024, 10), 1025);
134 auto subtree2Data = subtree2->encode();
135 db.insertSubTreeData(10, 1024, *subtree2Data, false, 1025);
136
137 auto subtree3 = TreeGenerator::getSubTreeBinary(Node::Index(1024, 5), 1025);
138 auto subtree3Data = subtree3->encode();
139 db.insertSubTreeData(5, 1024, *subtree3Data, false, 1025);
140 }
141
142 const NonNegativeInteger seqNo = 0;
143 const size_t level = 11;
144 const NonNegativeInteger nextLeafSeqNo = 1025;
145};
146
147
148typedef boost::mpl::list<MerkleTreeLoadTestParam1,
149 MerkleTreeLoadTestParam2,
150 MerkleTreeLoadTestParam3> DbLoadTestParams;
151
152BOOST_AUTO_TEST_CASE_TEMPLATE(DbLoad, T, DbLoadTestParams)
153{
154 T param;
155
156 param.insertData(db);
157
158 MerkleTree merkleTree(TreeGenerator::LOGGER_NAME, db);
159
160 auto hash1 = TreeGenerator::getHash(Node::Index(param.seqNo, param.level), param.nextLeafSeqNo);
161 auto hash2 = merkleTree.getRootHash();
162
163 BOOST_REQUIRE(hash1 != nullptr);
164 BOOST_REQUIRE(hash2 != nullptr);
165
166 BOOST_CHECK_EQUAL_COLLECTIONS(hash1->begin(), hash1->end(), hash2->begin(), hash2->end());
167}
168
169BOOST_AUTO_TEST_CASE(DbSave1)
170{
171 MerkleTree merkleTree(TreeGenerator::LOGGER_NAME, db);
172 for (NonNegativeInteger i = 0; i < 5 ; i++) {
173 BOOST_REQUIRE(merkleTree.addLeaf(i, Node::getEmptyHash()));
174 }
175
176 merkleTree.savePendingTree();
177 auto data1 = db.getPendingSubTrees()[0];
178 auto data2 = TreeGenerator::getSubTreeBinary(Node::Index(0, 5), 5)->encode();
179
180 BOOST_CHECK(data1->wireEncode() == data2->wireEncode());
181}
182
183BOOST_AUTO_TEST_CASE(DbSave2)
184{
185 MerkleTree merkleTree(TreeGenerator::LOGGER_NAME, db);
186 for (NonNegativeInteger i = 0; i < 32 ; i++) {
187 BOOST_REQUIRE(merkleTree.addLeaf(i, Node::getEmptyHash()));
188 }
189
190 merkleTree.savePendingTree();
191 auto data1 = db.getPendingSubTrees()[0];
192 auto data2 = TreeGenerator::getSubTreeBinary(Node::Index(0, 10), 32)->encode();
193
194 auto data3 = db.getPendingSubTrees()[1];
195 auto subtree = make_shared<SubTreeBinary>(TreeGenerator::LOGGER_NAME,
196 Node::Index(32, 5),
197 [&] (const Node::Index&) {},
198 [&] (const Node::Index&,
199 const NonNegativeInteger&,
200 ndn::ConstBufferPtr) {});
201 auto data4 = subtree->encode();
202
203 BOOST_CHECK(data1->wireEncode() == data2->wireEncode());
204 BOOST_CHECK(data3->wireEncode() == data4->wireEncode());
205
206 auto dataA = TreeGenerator::getSubTreeBinary(Node::Index(0, 5), 32)->encode();
207 auto dataB = db.getSubTreeData(5, 0);
208
209 BOOST_CHECK(dataA->wireEncode() == dataB->wireEncode());
210}
211
212BOOST_AUTO_TEST_CASE(DbSave3)
213{
214 MerkleTree merkleTree(TreeGenerator::LOGGER_NAME, db);
215 for (NonNegativeInteger i = 0; i < 1025 ; i++) {
216 BOOST_REQUIRE(merkleTree.addLeaf(i, Node::getEmptyHash()));
217 }
218
219 merkleTree.savePendingTree();
220
221 auto data1 = db.getPendingSubTrees()[0];
222 auto data2 = TreeGenerator::getSubTreeBinary(Node::Index(0, 15), 1025)->encode();
223
224 auto data3 = db.getPendingSubTrees()[1];
225 auto data4 = TreeGenerator::getSubTreeBinary(Node::Index(1024, 10), 1025)->encode();
226
227 auto data5 = db.getPendingSubTrees()[2];
228 auto data6 = TreeGenerator::getSubTreeBinary(Node::Index(1024, 5), 1025)->encode();
229
230 BOOST_CHECK(data1->wireEncode() == data2->wireEncode());
231 BOOST_CHECK(data3->wireEncode() == data4->wireEncode());
232 BOOST_CHECK(data5->wireEncode() == data6->wireEncode());
233
234 for (NonNegativeInteger i = 0; i < 1024 ; i += 32) {
235 auto dataA = TreeGenerator::getSubTreeBinary(Node::Index(i, 5), i + 32)->encode();
236 auto dataB = db.getSubTreeData(5, i);
237
238 BOOST_CHECK(dataA->wireEncode() == dataB->wireEncode());
239 }
240
241 auto dataA = TreeGenerator::getSubTreeBinary(Node::Index(0, 10), 1024)->encode();
242 auto dataB = db.getSubTreeData(10, 0);
243
244 BOOST_CHECK(dataA->wireEncode() == dataB->wireEncode());
245}
246
247BOOST_AUTO_TEST_SUITE_END()
248
249} // namespace tests
Alexander Afanasyev49e2e4c2017-05-06 13:42:57 -0700250} // namespace delorean
251} // namespace ndn