Browse Source

libtestutils

cl-refactor
Marek Kotewicz 10 years ago
parent
commit
a70b84cb3d
  1. 1
      CMakeLists.txt
  2. 101
      libtestutils/BlockChainLoader.cpp
  3. 51
      libtestutils/BlockChainLoader.h
  4. 44
      libtestutils/CMakeLists.txt
  5. 80
      libtestutils/Common.cpp
  6. 44
      libtestutils/Common.h
  7. 41
      libtestutils/FixedClient.cpp
  8. 55
      libtestutils/FixedClient.h
  9. 2
      libtestutils/FixedWebThreeServer.cpp
  10. 32
      libtestutils/FixedWebThreeServer.h
  11. 44
      libtestutils/ShortLivingDirectory.cpp
  12. 45
      libtestutils/ShortLivingDirectory.h
  13. 57
      libtestutils/StateLoader.cpp
  14. 42
      libtestutils/StateLoader.h

1
CMakeLists.txt

@ -195,6 +195,7 @@ add_subdirectory(libevm)
add_subdirectory(libethereum)
add_subdirectory(libwebthree)
add_subdirectory(libtestutils)
add_subdirectory(test)
if (NOT JUSTTESTS)

101
libtestutils/BlockChainLoader.cpp

@ -0,0 +1,101 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/** @file BlockChainLoader.cpp
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
#include "BlockChainLoader.h"
#include "StateLoader.h"
#include "Common.h"
using namespace std;
using namespace dev;
using namespace dev::test;
using namespace dev::eth;
namespace dev
{
namespace test
{
dev::eth::BlockInfo toBlockInfo(Json::Value const& _json);
bytes toGenesisBlock(Json::Value const& _json);
}
}
dev::eth::BlockInfo dev::test::toBlockInfo(Json::Value const& _json)
{
RLPStream rlpStream;
auto size = _json.getMemberNames().size();
rlpStream.appendList(_json["hash"].empty() ? size : (size - 1));
rlpStream << fromHex(_json["parentHash"].asString());
rlpStream << fromHex(_json["uncleHash"].asString());
rlpStream << fromHex(_json["coinbase"].asString());
rlpStream << fromHex(_json["stateRoot"].asString());
rlpStream << fromHex(_json["transactionsTrie"].asString());
rlpStream << fromHex(_json["receiptTrie"].asString());
rlpStream << fromHex(_json["bloom"].asString());
rlpStream << bigint(_json["difficulty"].asString());
rlpStream << bigint(_json["number"].asString());
rlpStream << bigint(_json["gasLimit"].asString());
rlpStream << bigint(_json["gasUsed"].asString());
rlpStream << bigint(_json["timestamp"].asString());
rlpStream << fromHex(_json["extraData"].asString());
rlpStream << fromHex(_json["mixHash"].asString());
rlpStream << fromHex(_json["nonce"].asString());
BlockInfo result;
RLP rlp(rlpStream.out());
result.populateFromHeader(rlp, IgnoreNonce);
return result;
}
bytes dev::test::toGenesisBlock(Json::Value const& _json)
{
BlockInfo bi = toBlockInfo(_json);
RLPStream rlpStream;
bi.streamRLP(rlpStream, WithNonce);
RLPStream fullStream(3);
fullStream.appendRaw(rlpStream.out());
fullStream.appendRaw(RLPEmptyList);
fullStream.appendRaw(RLPEmptyList);
bi.verifyInternals(&fullStream.out());
return fullStream.out();
}
BlockChainLoader::BlockChainLoader(Json::Value const& _json)
{
// load pre state
StateLoader sl(_json["pre"]);
m_state = sl.state();
// load genesisBlock
m_bc.reset(new BlockChain(toGenesisBlock(_json["genesisBlockHeader"]), m_dir.path(), true));
// load blocks
for (auto const& block: _json["blocks"])
{
bytes rlp = fromHex(block["rlp"].asString());
m_bc->import(rlp, m_state.db());
}
// sync state
m_state.sync(*m_bc);
}

51
libtestutils/BlockChainLoader.h

@ -0,0 +1,51 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/** @file BlockChainLoader.h
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
#pragma once
#include <string>
#include <json/json.h>
#include <libethereum/BlockChain.h>
#include <libethereum/State.h>
#include "ShortLivingDirectory.h"
namespace dev
{
namespace test
{
/**
* @brief - loads the blockchain from json, creates temporary directory to store it, removes this temporary directory on dealloc
*/
class BlockChainLoader
{
public:
BlockChainLoader(Json::Value const& _json);
eth::BlockChain& bc() { return *m_bc; }
eth::State state() { return m_state; }
private:
ShortLivingDirectory m_dir;
std::auto_ptr<eth::BlockChain> m_bc;
eth::State m_state;
};
}
}

44
libtestutils/CMakeLists.txt

@ -0,0 +1,44 @@
cmake_policy(SET CMP0015 NEW)
# this policy was introduced in cmake 3.0
# remove if, once 3.0 will be used on unix
if (${CMAKE_MAJOR_VERSION} GREATER 2)
# old policy do not use MACOSX_RPATH
cmake_policy(SET CMP0042 OLD)
endif()
set(CMAKE_AUTOMOC OFF)
aux_source_directory(. SRC_LIST)
include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS})
include_directories(BEFORE ..)
include_directories(${MHD_INCLUDE_DIRS})
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS})
include_directories(${LEVELDB_INCLUDE_DIRS})
include_directories(${Boost_INCLUDE_DIRS})
set(EXECUTABLE testutils)
file(GLOB HEADERS "*.h")
if (ETH_STATIC)
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_SERVER_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${MHD_LIBRARIES})
target_link_libraries(${EXECUTABLE} webthree)
target_link_libraries(${EXECUTABLE} secp256k1)
target_link_libraries(${EXECUTABLE} solidity)
if (NOT ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC"))
target_link_libraries(${EXECUTABLE} serpent)
endif()
install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

80
libtestutils/Common.cpp

@ -0,0 +1,80 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/** @file Common.cpp
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
#include <random>
#include <libdevcore/CommonData.h>
#include <libdevcore/CommonIO.h>
#include <libdevcrypto/FileSystem.h>
#include "Common.h"
using namespace std;
using namespace dev;
using namespace dev::test;
std::string dev::test::getTestPath()
{
string testPath;
const char* ptestPath = getenv("ETHEREUM_TEST_PATH");
if (ptestPath == NULL)
{
ctest << " could not find environment variable ETHEREUM_TEST_PATH \n";
testPath = "../../../tests";
}
else
testPath = ptestPath;
return testPath;
}
int dev::test::randomNumber()
{
static std::mt19937 randomGenerator(time(0));
randomGenerator.seed(std::random_device()());
return std::uniform_int_distribution<int>(1)(randomGenerator);
}
Json::Value dev::test::loadJsonFromFile(std::string const& _path)
{
Json::Reader reader;
Json::Value result;
string s = asString(dev::contents(_path));
if (!s.length())
ctest << "Contents of " + _path + " is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?";
else
ctest << "FIXTURE: loaded test from file: " << _path;
reader.parse(s, result);
return result;
}
std::string dev::test::toTestFilePath(std::string const& _filename)
{
return getTestPath() + "/" + _filename + ".json";
}
std::string dev::test::getRandomPath()
{
std::stringstream stream;
stream << getDataDir() << "/EthereumTests/" << randomNumber();
return stream.str();
}

44
libtestutils/Common.h

@ -0,0 +1,44 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/** @file Common.h
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
#pragma once
#include <string>
#include <json/json.h>
#include <libdevcore/Log.h>
namespace dev
{
namespace test
{
struct TestChannel: public LogChannel { static const char* name() { return "TEST"; } };
#define ctest dev::LogOutputStream<dev::test::TestChannel, true>()
std::string getTestPath();
int randomNumber();
Json::Value loadJsonFromFile(std::string const& _path);
std::string toTestFilePath(std::string const& _filename);
std::string getRandomPath();
}
}

41
libtestutils/FixedClient.cpp

@ -0,0 +1,41 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/** @file FixedClient.cpp
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
#include "FixedClient.h"
using namespace dev;
using namespace dev::eth;
using namespace dev::test;
eth::State FixedClient::asOf(BlockNumber _h) const
{
ReadGuard l(x_stateDB);
if (_h == PendingBlock || _h == LatestBlock)
return m_state;
return State(m_state.db(), bc(), bc().numberHash(_h));
}
eth::State FixedClient::asOf(h256 _h) const
{
ReadGuard l(x_stateDB);
return State(m_state.db(), bc(), _h);
}

55
libtestutils/FixedClient.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 <http://www.gnu.org/licenses/>.
*/
/** @file FixedClient.h
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
#pragma once
#include <libethereum/ClientBase.h>
#include <libethereum/BlockChain.h>
#include <libethereum/State.h>
namespace dev
{
namespace test
{
class FixedClient: public dev::eth::ClientBase
{
public:
FixedClient(eth::BlockChain const& _bc, eth::State _state) : m_bc(_bc), m_state(_state) {}
virtual ~FixedClient() {}
// stub
virtual void flushTransactions() override {}
virtual eth::BlockChain const& bc() const override { return m_bc; }
virtual eth::State asOf(eth::BlockNumber _h) const override;
virtual eth::State asOf(h256 _h) const override;
virtual eth::State preMine() const override { ReadGuard l(x_stateDB); return m_state; }
virtual eth::State postMine() const override { ReadGuard l(x_stateDB); return m_state; }
virtual void prepareForTransaction() override {}
private:
eth::BlockChain const& m_bc;
eth::State m_state;
mutable SharedMutex x_stateDB; ///< Lock on the state DB, effectively a lock on m_postMine.
};
}
}

2
libtestutils/FixedWebThreeServer.cpp

@ -0,0 +1,2 @@
#include "FixedWebThreeServer.h"

32
libtestutils/FixedWebThreeServer.h

@ -0,0 +1,32 @@
#pragma once
#include <libdevcore/Exceptions.h>
#include <libweb3jsonrpc/WebThreeStubServerBase.h>
class FixedWebThreeServer: public dev::WebThreeStubServerBase, public dev::WebThreeStubDatabaseFace
{
public:
FixedWebThreeServer(jsonrpc::AbstractServerConnector& _conn, std::vector<dev::KeyPair> const& _accounts, dev::eth::Interface* _client): WebThreeStubServerBase(_conn, _accounts), m_client(_client) {};
private:
dev::eth::Interface* client() override { return m_client; }
std::shared_ptr<dev::shh::Interface> face() override { BOOST_THROW_EXCEPTION(dev::InterfaceNotSupported("dev::shh::Interface")); }
dev::WebThreeNetworkFace* network() override { BOOST_THROW_EXCEPTION(dev::InterfaceNotSupported("dev::WebThreeNetworkFace")); }
dev::WebThreeStubDatabaseFace* db() override { return this; }
std::string get(std::string const& _name, std::string const& _key) override
{
std::string k(_name + "/" + _key);
return m_db[k];
}
void put(std::string const& _name, std::string const& _key, std::string const& _value) override
{
std::string k(_name + "/" + _key);
m_db[k] = _value;
}
private:
dev::eth::Interface* m_client;
std::map<std::string, std::string> m_db;
};

44
libtestutils/ShortLivingDirectory.cpp

@ -0,0 +1,44 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/** @file ShortLivingDirectory.cpp
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
#include <boost/filesystem.hpp>
#include "ShortLivingDirectory.h"
#include "Common.h"
using namespace std;
using namespace dev;
using namespace dev::test;
ShortLivingDirectory::ShortLivingDirectory()
{
m_path = getRandomPath();
boost::filesystem::create_directories(m_path);
}
ShortLivingDirectory::ShortLivingDirectory(std::string const& _path) : m_path(_path)
{
boost::filesystem::create_directories(m_path);
}
ShortLivingDirectory::~ShortLivingDirectory()
{
boost::filesystem::remove_all(m_path);
}

45
libtestutils/ShortLivingDirectory.h

@ -0,0 +1,45 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/** @file ShortLivingDirectory.h
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
#pragma once
#include <string>
namespace dev
{
namespace test
{
class ShortLivingDirectory
{
public:
ShortLivingDirectory();
ShortLivingDirectory(std::string const& _path);
~ShortLivingDirectory();
std::string path(){ return m_path; }
private:
std::string m_path;
};
}
}

57
libtestutils/StateLoader.cpp

@ -0,0 +1,57 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/** @file StateLoader.cpp
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
#include "StateLoader.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
using namespace dev::test;
StateLoader::StateLoader(Json::Value const& _json)
: m_state(Address(), OverlayDB(), BaseState::Empty)
{
for (string const& name: _json.getMemberNames())
{
Json::Value o = _json[name];
Address address = Address(name);
bytes code = fromHex(o["code"].asString().substr(2));
if (code.size())
{
m_state.m_cache[address] = Account(u256(o["balance"].asString()), Account::ContractConception);
m_state.m_cache[address].setCode(code);
}
else
m_state.m_cache[address] = Account(u256(o["balance"].asString()), Account::NormalCreation);
for (string const& j: o["storage"].getMemberNames())
m_state.setStorage(address, u256(j), u256(o["storage"][j].asString()));
for (auto i = 0; i < u256(o["nonce"].asString()); ++i)
m_state.noteSending(address);
m_state.ensureCached(address, false, false);
}
m_state.commit();
}

42
libtestutils/StateLoader.h

@ -0,0 +1,42 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/** @file StateLoader.h
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
#pragma once
#include <json/json.h>
#include <libethereum/State.h>
namespace dev
{
namespace test
{
class StateLoader
{
public:
StateLoader(Json::Value const& _json);
eth::State state() { return m_state; }
private:
eth::State m_state;
};
}
}
Loading…
Cancel
Save