From 6c819747bc6502325006f0a8780443e43ffece61 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Fri, 12 Dec 2014 21:07:47 +0100 Subject: [PATCH] include original trie test --- trie.cpp.orig | 374 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 374 insertions(+) create mode 100644 trie.cpp.orig diff --git a/trie.cpp.orig b/trie.cpp.orig new file mode 100644 index 000000000..7a9461ce2 --- /dev/null +++ b/trie.cpp.orig @@ -0,0 +1,374 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file trie.cpp + * @author Gav Wood + * @date 2014 + * Trie test functions. + */ + +#include +#include +#include "JsonSpiritHeaders.h" +#include +#include +#include "TrieHash.h" +#include "MemTrie.h" +#include +#include "TestHelper.h" + +using namespace std; +using namespace dev; + +namespace js = json_spirit; + +namespace dev +{ +namespace test +{ + +static unsigned fac(unsigned _i) +{ + return _i > 2 ? _i * fac(_i - 1) : _i; +} + +} +} + +BOOST_AUTO_TEST_SUITE(TrieTests) + +BOOST_AUTO_TEST_CASE(trie_tests) +{ + string testPath = test::getTestPath(); + + + testPath += "/TrieTests"; + + cnote << "Testing Trie..."; + js::mValue v; + string s = asString(contents(testPath + "/trieanyorder.json")); + BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of 'trieanyorder.json' is empty. Have you cloned the 'tests' repo branch develop?"); + js::read_string(s, v); + for (auto& i: v.get_obj()) + { + cnote << i.first; + js::mObject& o = i.second.get_obj(); + vector> ss; + for (auto& i: o["in"].get_array()) + { + vector values; + for (auto& s: i.get_array()) + values.push_back(s.get_str()); + + assert(values.size() == 2); + ss.push_back(make_pair(values[0], values[1])); + if (!ss.back().first.find("0x")) + ss.back().first = asString(fromHex(ss.back().first.substr(2))); + if (!ss.back().second.find("0x")) + ss.back().second = asString(fromHex(ss.back().second.substr(2))); + } + for (unsigned j = 0; j < min(1000u, dev::test::fac((unsigned)ss.size())); ++j) + { + MemoryDB m; + GenericTrieDB t(&m); + t.init(); + BOOST_REQUIRE(t.check(true)); + for (auto const& k: ss) + { + t.insert(k.first, k.second); + BOOST_REQUIRE(t.check(true)); + } + BOOST_REQUIRE(!o["root"].is_null()); + BOOST_CHECK_EQUAL(o["root"].get_str(), "0x" + toHex(t.root().asArray())); +<<<<<<< HEAD + if (o["root"].get_str() != "0x" + toHex(t.root().asArray())) + break; +======= +>>>>>>> upstream/develop + } + } +} + +inline h256 stringMapHash256(StringMap const& _s) +{ + return hash256(_s); +} + +BOOST_AUTO_TEST_CASE(moreTrieTests) +{ + cnote << "Testing Trie more..."; +#if 0 + // More tests... + { + MemoryDB m; + GenericTrieDB t(&m); + t.init(); // initialise as empty tree. + cout << t; + cout << m; + cout << t.root() << endl; + cout << hash256(StringMap()) << endl; + + t.insert(string("tesz"), string("test")); + cout << t; + cout << m; + cout << t.root() << endl; + cout << stringMapHash256({{"test", "test"}}) << endl; + + t.insert(string("tesa"), string("testy")); + cout << t; + cout << m; + cout << t.root() << endl; + cout << stringMapHash256({{"test", "test"}, {"te", "testy"}}) << endl; + cout << t.at(string("test")) << endl; + cout << t.at(string("te")) << endl; + cout << t.at(string("t")) << endl; + + t.remove(string("te")); + cout << m; + cout << t.root() << endl; + cout << stringMapHash256({{"test", "test"}}) << endl; + + t.remove(string("test")); + cout << m; + cout << t.root() << endl; + cout << hash256(StringMap()) << endl; + } + { + MemoryDB m; + GenericTrieDB t(&m); + t.init(); // initialise as empty tree. + t.insert(string("a"), string("A")); + t.insert(string("b"), string("B")); + cout << t; + cout << m; + cout << t.root() << endl; + cout << stringMapHash256({{"b", "B"}, {"a", "A"}}) << endl; + cout << RLP(rlp256({{"b", "B"}, {"a", "A"}})) << endl; + } + { + MemTrie t; + t.insert("dog", "puppy"); + cout << hex << t.hash256() << endl; + cout << RLP(t.rlp()) << endl; + } + { + MemTrie t; + t.insert("bed", "d"); + t.insert("be", "e"); + cout << hex << t.hash256() << endl; + cout << RLP(t.rlp()) << endl; + } + { + cout << hex << stringMapHash256({{"dog", "puppy"}, {"doe", "reindeer"}}) << endl; + MemTrie t; + t.insert("dog", "puppy"); + t.insert("doe", "reindeer"); + cout << hex << t.hash256() << endl; + cout << RLP(t.rlp()) << endl; + cout << toHex(t.rlp()) << endl; + } +#endif + { + MemoryDB m; + GenericTrieDB d(&m); + d.init(); // initialise as empty tree. + MemTrie t; + StringMap s; + + auto add = [&](char const* a, char const* b) + { + d.insert(string(a), string(b)); + t.insert(a, b); + s[a] = b; + + /*cout << endl << "-------------------------------" << endl; + cout << a << " -> " << b << endl; + cout << d; + cout << m; + cout << d.root() << endl; + cout << hash256(s) << endl;*/ + + BOOST_REQUIRE(d.check(true)); + BOOST_REQUIRE_EQUAL(t.hash256(), hash256(s)); + BOOST_REQUIRE_EQUAL(d.root(), hash256(s)); + for (auto const& i: s) + { + (void)i; + BOOST_REQUIRE_EQUAL(t.at(i.first), i.second); + BOOST_REQUIRE_EQUAL(d.at(i.first), i.second); + } + }; + + auto remove = [&](char const* a) + { + s.erase(a); + t.remove(a); + d.remove(string(a)); + + /*cout << endl << "-------------------------------" << endl; + cout << "X " << a << endl; + cout << d; + cout << m; + cout << d.root() << endl; + cout << hash256(s) << endl;*/ + + BOOST_REQUIRE(d.check(true)); + BOOST_REQUIRE(t.at(a).empty()); + BOOST_REQUIRE(d.at(string(a)).empty()); + BOOST_REQUIRE_EQUAL(t.hash256(), hash256(s)); + BOOST_REQUIRE_EQUAL(d.root(), hash256(s)); + for (auto const& i: s) + { + (void)i; + BOOST_REQUIRE_EQUAL(t.at(i.first), i.second); + BOOST_REQUIRE_EQUAL(d.at(i.first), i.second); + } + }; + + add("dogglesworth", "cat"); + add("doe", "reindeer"); + remove("dogglesworth"); + add("horse", "stallion"); + add("do", "verb"); + add("doge", "coin"); + remove("horse"); + remove("do"); + remove("doge"); + remove("doe"); + } +} + +BOOST_AUTO_TEST_CASE(trieLowerBound) +{ + cnote << "Stress-testing Trie.lower_bound..."; + { + MemoryDB dm; + EnforceRefs e(dm, true); + GenericTrieDB d(&dm); + d.init(); // initialise as empty tree. + for (int a = 0; a < 20; ++a) + { + StringMap m; + for (int i = 0; i < 50; ++i) + { + auto k = randomWord(); + auto v = toString(i); + m[k] = v; + d.insert(k, v); + } + + for (auto i: d) + { + auto it = d.lower_bound(i.first); + for (auto iit = d.begin(); iit != d.end(); ++iit) + if ((*iit).first.toString() >= i.first.toString()) + { + BOOST_REQUIRE(it == iit); + break; + } + } + for (unsigned i = 0; i < 100; ++i) + { + auto k = randomWord(); + auto it = d.lower_bound(k); + for (auto iit = d.begin(); iit != d.end(); ++iit) + if ((*iit).first.toString() >= k) + { + BOOST_REQUIRE(it == iit); + break; + } + } + + } + } +} + +BOOST_AUTO_TEST_CASE(trieStess) +{ + cnote << "Stress-testing Trie..."; + { + MemoryDB m; + MemoryDB dm; + EnforceRefs e(dm, true); + GenericTrieDB d(&dm); + d.init(); // initialise as empty tree. + MemTrie t; + BOOST_REQUIRE(d.check(true)); + for (int a = 0; a < 20; ++a) + { + StringMap m; + for (int i = 0; i < 50; ++i) + { + auto k = randomWord(); + auto v = toString(i); + m[k] = v; + t.insert(k, v); + d.insert(k, v); + BOOST_REQUIRE_EQUAL(hash256(m), t.hash256()); + BOOST_REQUIRE_EQUAL(hash256(m), d.root()); + BOOST_REQUIRE(d.check(true)); + } + while (!m.empty()) + { + auto k = m.begin()->first; + auto v = m.begin()->second; + d.remove(k); + t.remove(k); + m.erase(k); + if (!d.check(true)) + { + // cwarn << m; + for (auto i: d) + cwarn << i.first.toString() << i.second.toString(); + + MemoryDB dm2; + EnforceRefs e2(dm2, true); + GenericTrieDB d2(&dm2); + d2.init(); // initialise as empty tree. + for (auto i: d) + d2.insert(i.first, i.second); + + cwarn << "Good:" << d2.root(); +// for (auto i: dm2.get()) +// cwarn << i.first.abridged() << ": " << RLP(i.second); + d2.debugStructure(cerr); + cwarn << "Broken:" << d.root(); // Leaves an extension -> extension (3c1... -> 742...) +// for (auto i: dm.get()) +// cwarn << i.first.abridged() << ": " << RLP(i.second); + d.debugStructure(cerr); + + d2.insert(k, v); + cwarn << "Pres:" << d2.root(); +// for (auto i: dm2.get()) +// cwarn << i.first.abridged() << ": " << RLP(i.second); + d2.debugStructure(cerr); + g_logVerbosity = 99; + d2.remove(k); + g_logVerbosity = 4; + + cwarn << "Good?" << d2.root(); + } + BOOST_REQUIRE(d.check(true)); + BOOST_REQUIRE_EQUAL(hash256(m), t.hash256()); + BOOST_REQUIRE_EQUAL(hash256(m), d.root()); + } + } + } +} + +BOOST_AUTO_TEST_SUITE_END() + +