diff --git a/libwhisper/WhisperDB.cpp b/libwhisper/WhisperDB.cpp new file mode 100644 index 000000000..fd2eef060 --- /dev/null +++ b/libwhisper/WhisperDB.cpp @@ -0,0 +1,69 @@ +/* + 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 WhisperDB.cpp +* @author Vladislav Gluhovsky +* @date July 2015 + */ + +#include "WhisperDB.h" +#include +#include + +using namespace std; +using namespace dev; +using namespace dev::shh; + +WhisperDB::WhisperDB() +{ + string path = dev::getDataDir("shh"); + boost::filesystem::create_directories(path); + leveldb::Options op; + op.create_if_missing = true; + op.max_open_files = 256; + leveldb::DB* p = nullptr; + leveldb::Status status = leveldb::DB::Open(op, path + "/messages", &p); + m_db.reset(p); + if (!status.ok()) + BOOST_THROW_EXCEPTION(FailedToOpenLevelDB(status.ToString())); +} + +string WhisperDB::lookup(dev::h256 const& _key) const +{ + string ret; + leveldb::Slice slice((char const*)_key.data(), _key.size); + leveldb::Status status = m_db->Get(m_readOptions, slice, &ret); + if (!status.ok() && !status.IsNotFound()) + BOOST_THROW_EXCEPTION(FailedLookupInLevelDB(status.ToString())); + + return ret; +} + +void WhisperDB::insert(dev::h256 const& _key, string const& _value) +{ + leveldb::Slice slice((char const*)_key.data(), _key.size); + leveldb::Status status = m_db->Put(m_writeOptions, slice, _value); + if (!status.ok()) + BOOST_THROW_EXCEPTION(FailedInsertInLevelDB(status.ToString())); +} + +void WhisperDB::kill(dev::h256 const& _key) +{ + leveldb::Slice slice((char const*)_key.data(), _key.size); + leveldb::Status status = m_db->Delete(m_writeOptions, slice); + if (!status.ok()) + BOOST_THROW_EXCEPTION(FailedDeleteInLevelDB(status.ToString())); +} diff --git a/libwhisper/WhisperDB.h b/libwhisper/WhisperDB.h new file mode 100644 index 000000000..0cb97e244 --- /dev/null +++ b/libwhisper/WhisperDB.h @@ -0,0 +1,55 @@ +/* + 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 WhisperDB.h +* @author Vladislav Gluhovsky +* @date July 2015 + */ + +#pragma once + +#include +#include +#include "Common.h" + +namespace dev +{ +namespace shh +{ + +struct FailedToOpenLevelDB: virtual Exception { FailedToOpenLevelDB(std::string const& _message): Exception(_message) {} }; +struct FailedInsertInLevelDB: virtual Exception { FailedInsertInLevelDB(std::string const& _message): Exception(_message) {} }; +struct FailedLookupInLevelDB: virtual Exception { FailedLookupInLevelDB(std::string const& _message): Exception(_message) {} }; +struct FailedDeleteInLevelDB: virtual Exception { FailedDeleteInLevelDB(std::string const& _message): Exception(_message) {} }; + +class WhisperDB +{ + public: + WhisperDB(); + ~WhisperDB() {} + + std::string lookup(dev::h256 const& _key) const; + void insert(dev::h256 const& _key, std::string const& _value); + void kill(dev::h256 const& _key); + +private: + leveldb::ReadOptions m_readOptions; + leveldb::WriteOptions m_writeOptions; + std::unique_ptr m_db; +}; + +} +} \ No newline at end of file diff --git a/test/libp2p/peer.cpp b/test/libp2p/peer.cpp index e84e86027..5417450b4 100644 --- a/test/libp2p/peer.cpp +++ b/test/libp2p/peer.cpp @@ -43,28 +43,32 @@ BOOST_AUTO_TEST_CASE(host) if (test::Options::get().nonetwork) return; - VerbosityHolder sentinel(10); - + VerbosityHolder setTemporaryLevel(10); NetworkPreferences host1prefs("127.0.0.1", 30301, false); - NetworkPreferences host2prefs("127.0.0.1", 30302, false); - + NetworkPreferences host2prefs("127.0.0.1", 30302, false); Host host1("Test", host1prefs); - host1.start(); - Host host2("Test", host2prefs); - auto node2 = host2.id(); + host1.start(); host2.start(); - - while (!host2.haveNetwork()) - this_thread::sleep_for(chrono::milliseconds(20)); + auto node2 = host2.id(); + int const step = 10; + + for (int i = 0; i < 3000 && (!host1.isStarted() || !host2.isStarted()); i += step) + this_thread::sleep_for(chrono::milliseconds(step)); + + BOOST_REQUIRE(host1.isStarted() && host2.isStarted()); host1.addNode(node2, NodeIPEndpoint(bi::address::from_string("127.0.0.1"), host2prefs.listenPort, host2prefs.listenPort)); - this_thread::sleep_for(chrono::seconds(3)); - - auto host1peerCount = host1.peerCount(); - auto host2peerCount = host2.peerCount(); - BOOST_REQUIRE_EQUAL(host1peerCount, 1); - BOOST_REQUIRE_EQUAL(host2peerCount, 1); + for (int i = 0; i < 3000 && (!host1.haveNetwork() || !host2.haveNetwork()); i += step) + this_thread::sleep_for(chrono::milliseconds(step)); + + BOOST_REQUIRE(host1.haveNetwork() && host2.haveNetwork()); + + for (int i = 0; i < 3000 && (!host1.peerCount() || !host2.peerCount()); i += step) + this_thread::sleep_for(chrono::milliseconds(step)); + + BOOST_REQUIRE_EQUAL(host1.peerCount(), 1); + BOOST_REQUIRE_EQUAL(host2.peerCount(), 1); } BOOST_AUTO_TEST_CASE(networkConfig) diff --git a/test/libwhisper/whisperDB.cpp b/test/libwhisper/whisperDB.cpp new file mode 100644 index 000000000..552820621 --- /dev/null +++ b/test/libwhisper/whisperDB.cpp @@ -0,0 +1,122 @@ +/* +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 whisperMessage.cpp +* @author Vladislav Gluhovsky +* @date July 2015 +*/ + +#include +#include +#include + +using namespace std; +using namespace dev; +using namespace dev::shh; + +BOOST_AUTO_TEST_SUITE(whisperDB) + +BOOST_AUTO_TEST_CASE(basic) +{ + VerbosityHolder setTemporaryLevel(10); + cnote << "Testing Whisper DB..."; + + string s; + string const text1 = "lorem"; + string const text2 = "ipsum"; + h256 h1(0xBEEF); + h256 h2(0xC0FFEE); + WhisperDB db; + + db.kill(h1); + db.kill(h2); + + s = db.lookup(h1); + BOOST_REQUIRE(s.empty()); + + db.insert(h1, text2); + s = db.lookup(h2); + BOOST_REQUIRE(s.empty()); + s = db.lookup(h1); + BOOST_REQUIRE(!s.compare(text2)); + + db.insert(h1, text1); + s = db.lookup(h2); + BOOST_REQUIRE(s.empty()); + s = db.lookup(h1); + BOOST_REQUIRE(!s.compare(text1)); + + db.insert(h2, text2); + s = db.lookup(h2); + BOOST_REQUIRE(!s.compare(text2)); + s = db.lookup(h1); + BOOST_REQUIRE(!s.compare(text1)); + + db.kill(h1); + db.kill(h2); + + s = db.lookup(h2); + BOOST_REQUIRE(s.empty()); + s = db.lookup(h1); + BOOST_REQUIRE(s.empty()); +} + +BOOST_AUTO_TEST_CASE(persistence) +{ + VerbosityHolder setTemporaryLevel(10); + cnote << "Testing persistence of Whisper DB..."; + + string s; + string const text1 = "sator"; + string const text2 = "arepo"; + h256 const h1(0x12345678); + h256 const h2(0xBADD00DE); + + { + WhisperDB db; + db.kill(h1); + db.kill(h2); + s = db.lookup(h1); + BOOST_REQUIRE(s.empty()); + db.insert(h1, text2); + s = db.lookup(h2); + BOOST_REQUIRE(s.empty()); + s = db.lookup(h1); + BOOST_REQUIRE(!s.compare(text2)); + } + + this_thread::sleep_for(chrono::milliseconds(20)); + + { + WhisperDB db; + db.insert(h1, text1); + db.insert(h2, text2); + } + + this_thread::sleep_for(chrono::milliseconds(20)); + + { + WhisperDB db; + s = db.lookup(h2); + BOOST_REQUIRE(!s.compare(text2)); + s = db.lookup(h1); + BOOST_REQUIRE(!s.compare(text1)); + db.kill(h1); + db.kill(h2); + } +} + +BOOST_AUTO_TEST_SUITE_END()