Browse Source

FuzzTests: Boost Macro

cl-refactor
Dimitry 10 years ago
parent
commit
3660c44336
  1. 16
      test/TestHelper.h
  2. 5
      test/fuzzTesting/CMakeLists.txt
  3. 143
      test/fuzzTesting/createRandomTest.cpp
  4. 43
      test/libethereum/transaction.cpp

16
test/TestHelper.h

@ -31,6 +31,19 @@
#include <libevm/ExtVMFace.h>
#include <libtestutils/Common.h>
#define DONTUSE_BOOST_MACROS
#ifdef DONTUSE_BOOST_MACROS
#define TBOOST_THROW_EXCEPTION(arg) throw;
#define TBOOST_REQUIRE(arg) if(arg == false) throw;
#define TBOOST_CHECK_MESSAGE(arg1, arg2) if(arg1 == false) throw;
#define TBOOST_WARN_MESSAGE(arg1, arg2) throw;
#else
#define TBOOST_THROW_EXCEPTION(arg) BOOST_THROW_EXCEPTION(arg)
#define TBOOST_REQUIRE(arg) BOOST_REQUIRE(arg)
#define TBOOST_CHECK_MESSAGE(arg1, arg2) BOOST_CHECK_MESSAGE(arg1, arg2)
#define TBOOST_WARN_MESSAGE(arg1, arg2) BOOST_WARN_MESSAGE(arg1, arg2)
#endif
namespace dev
{
namespace eth
@ -163,6 +176,9 @@ eth::LastHashes lastHashes(u256 _currentBlockNumber);
json_spirit::mObject fillJsonWithState(eth::State _state);
json_spirit::mObject fillJsonWithTransaction(eth::Transaction _txn);
//Fill Test Functions
void doTransactionTests(json_spirit::mValue& _v, bool _fillin);
template<typename mapType>
void checkAddresses(mapType& _expectedAddrs, mapType& _resultAddrs)
{

5
test/fuzzTesting/CMakeLists.txt

@ -8,6 +8,7 @@ include_directories(${Boost_INCLUDE_DIRS})
include_directories(${CRYPTOPP_INCLUDE_DIRS})
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS})
add_executable(createRandomTest "./createRandomTest.cpp" "../TestHelper.cpp" "../Stats.cpp" "fuzzHelper.cpp" "../libethereum/transaction.cpp")
add_executable(createRandomVMTest "./createRandomVMTest.cpp" "../libevm/vm.cpp" "../TestHelper.cpp" "../Stats.cpp")
add_executable(createRandomStateTest "./createRandomStateTest.cpp" "../TestHelper.cpp" "../Stats.cpp" "fuzzHelper.cpp")
add_executable(checkRandomVMTest "./checkRandomVMTest.cpp" "../libevm/vm.cpp" "../TestHelper.cpp" "../Stats.cpp" )
@ -32,3 +33,7 @@ target_link_libraries(checkRandomStateTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES
target_link_libraries(checkRandomStateTest ethereum)
target_link_libraries(checkRandomStateTest ethcore)
target_link_libraries(checkRandomStateTest testutils)
target_link_libraries(createRandomTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES})
target_link_libraries(createRandomTest ethereum)
target_link_libraries(createRandomTest ethcore)
target_link_libraries(createRandomTest testutils)

143
test/fuzzTesting/createRandomTest.cpp

@ -0,0 +1,143 @@
/*
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 createRandomTest.cpp
* @author Dimitry Khokhlov <winsvega@mail.ru>
* @date 2015
*/
#include <string>
#include <iostream>
#include <test/TestHelper.h>
#include <test/fuzzTesting/fuzzHelper.h>
extern std::string const c_testExampleTransactionTest;
std::vector<std::string> getTypes();
void parseTestWithTypes(std::string& test);
void randomTransactionTest();
void randomBlockChainTest();
int main(int argc, char *argv[])
{
std::string testSuite;
for (auto i = 0; i < argc; ++i)
{
auto arg = std::string{argv[i]};
dev::test::Options& options = const_cast<dev::test::Options&>(dev::test::Options::get());
if (arg == "--fulloutput")
options.fulloutput = true;
if (arg == "-t" && i + 1 < argc)
{
testSuite = argv[i + 1];
if (testSuite != "BlockChainTests" && testSuite != "TransactionTests")
testSuite = "";
}
}
if (testSuite == "")
std::cout << "Error! Test suite not supported! (Usage -t TestSuite)";
else
if (testSuite == "BlockChainTests")
randomBlockChainTest();
else
if (testSuite == "TransactionTests")
randomTransactionTest();
return 0;
}
void randomTransactionTest()
{
std::string newTest = c_testExampleTransactionTest;
parseTestWithTypes(newTest);
json_spirit::mValue v;
json_spirit::read_string(newTest, v);
dev::test::doTransactionTests(v, true);
std::cout << json_spirit::write_string(v, true);
}
void randomBlockChainTest()
{
}
/// Parse Test string replacing keywords to fuzzed values
void parseTestWithTypes(std::string& test)
{
std::vector<std::string> types = getTypes();
for (unsigned i = 0; i < types.size(); i++)
{
std::size_t pos = test.find(types.at(i));
while (pos != std::string::npos)
{
if (types.at(i) == "[CODE]")
test.replace(pos, 6, "0x"+dev::test::RandomCode::generate(10));
else
if (types.at(i) == "[HEX]")
test.replace(pos, 5, dev::test::RandomCode::randomUniIntHex());
else
if (types.at(i) == "[HASH20]")
test.replace(pos, 8, dev::test::RandomCode::rndByteSequence(20));
else
if (types.at(i) == "[0xHASH32]")
test.replace(pos, 10, "0x" + dev::test::RandomCode::rndByteSequence(32));
else
if (types.at(i) == "[V]")
{
int random = dev::test::RandomCode::randomUniInt() % 100;
if (random < 30)
test.replace(pos, 3, "28");
else
if (random < 60)
test.replace(pos, 3, "29");
else
test.replace(pos, 3, "0x" + dev::test::RandomCode::rndByteSequence(1));
}
pos = test.find(types.at(i));
}
}
}
std::vector<std::string> getTypes()
{
return {"[CODE]", "[HEX]", "[HASH20]", "[0xHASH32]", "[V]"};
}
std::string const c_testExampleTransactionTest = R"(
{
"TransactionTest" : {
"transaction" :
{
"data" : "[CODE]",
"gasLimit" : "[HEX]",
"gasPrice" : "[HEX]",
"nonce" : "[HEX]",
"to" : "[HASH20]",
"value" : "[HEX]",
"v" : "[V]",
"r" : "[0xHASH32]",
"s" : "[0xHASH32]"
}
}
}
)";

43
test/libethereum/transaction.cpp

@ -21,6 +21,7 @@
*/
#include "../TestHelper.h"
#include "test/fuzzTesting/fuzzHelper.h"
using namespace std;
using namespace json_spirit;
@ -38,7 +39,7 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin)
if (_fillin)
{
BOOST_REQUIRE(o.count("transaction") > 0);
TBOOST_REQUIRE((o.count("transaction") > 0));
mObject tObj = o["transaction"].get_obj();
//Construct Rlp of the given transaction
@ -49,7 +50,7 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin)
{
Transaction txFromFields(rlpStream.out(), CheckTransaction::Everything);
if (!txFromFields.signature().isValid())
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") );
TBOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") );
o["sender"] = toString(txFromFields.sender());
o["transaction"] = ImportTest::makeAllFieldsHex(tObj);
@ -63,9 +64,9 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin)
{
bool expectInValid = (o["expect"].get_str() == "invalid");
if (Options::get().checkState)
BOOST_CHECK_MESSAGE(expectInValid, "Check state: Transaction '" << i.first << "' is expected to be valid!");
{TBOOST_CHECK_MESSAGE(expectInValid, "Check state: Transaction '" << i.first << "' is expected to be valid!");}
else
BOOST_WARN_MESSAGE(expectInValid, "Check state: Transaction '" << i.first << "' is expected to be valid!");
{TBOOST_WARN_MESSAGE(expectInValid, "Check state: Transaction '" << i.first << "' is expected to be valid!");}
o.erase(o.find("expect"));
}
@ -76,16 +77,16 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin)
{
bool expectValid = (o["expect"].get_str() == "valid");
if (Options::get().checkState)
BOOST_CHECK_MESSAGE(expectValid, "Check state: Transaction '" << i.first << "' is expected to be invalid!");
{TBOOST_CHECK_MESSAGE(expectValid, "Check state: Transaction '" << i.first << "' is expected to be invalid!");}
else
BOOST_WARN_MESSAGE(expectValid, "Check state: Transaction '" << i.first << "' is expected to be invalid!");
{TBOOST_WARN_MESSAGE(expectValid, "Check state: Transaction '" << i.first << "' is expected to be invalid!");}
o.erase(o.find("expect"));
}
}
else
{
BOOST_REQUIRE(o.count("rlp") > 0);
TBOOST_REQUIRE((o.count("rlp") > 0));
Transaction txFromRlp;
try
{
@ -93,39 +94,39 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin)
RLP rlp(stream);
txFromRlp = Transaction(rlp.data(), CheckTransaction::Everything);
if (!txFromRlp.signature().isValid())
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") );
TBOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") );
}
catch(Exception const& _e)
{
cnote << i.first;
cnote << "Transaction Exception: " << diagnostic_information(_e);
BOOST_CHECK_MESSAGE(o.count("transaction") == 0, "A transaction object should not be defined because the RLP is invalid!");
TBOOST_CHECK_MESSAGE((o.count("transaction") == 0), "A transaction object should not be defined because the RLP is invalid!");
continue;
}
catch(...)
{
BOOST_CHECK_MESSAGE(o.count("transaction") == 0, "A transaction object should not be defined because the RLP is invalid!");
TBOOST_CHECK_MESSAGE((o.count("transaction") == 0), "A transaction object should not be defined because the RLP is invalid!");
continue;
}
BOOST_REQUIRE(o.count("transaction") > 0);
TBOOST_REQUIRE((o.count("transaction") > 0));
mObject tObj = o["transaction"].get_obj();
Transaction txFromFields(createRLPStreamFromTransactionFields(tObj).out(), CheckTransaction::Everything);
//Check the fields restored from RLP to original fields
BOOST_CHECK_MESSAGE(txFromFields.data() == txFromRlp.data(), "Data in given RLP not matching the Transaction data!");
BOOST_CHECK_MESSAGE(txFromFields.value() == txFromRlp.value(), "Value in given RLP not matching the Transaction value!");
BOOST_CHECK_MESSAGE(txFromFields.gasPrice() == txFromRlp.gasPrice(), "GasPrice in given RLP not matching the Transaction gasPrice!");
BOOST_CHECK_MESSAGE(txFromFields.gas() == txFromRlp.gas(),"Gas in given RLP not matching the Transaction gas!");
BOOST_CHECK_MESSAGE(txFromFields.nonce() == txFromRlp.nonce(),"Nonce in given RLP not matching the Transaction nonce!");
BOOST_CHECK_MESSAGE(txFromFields.receiveAddress() == txFromRlp.receiveAddress(), "Receive address in given RLP not matching the Transaction 'to' address!");
BOOST_CHECK_MESSAGE(txFromFields.sender() == txFromRlp.sender(), "Transaction sender address in given RLP not matching the Transaction 'vrs' signature!");
BOOST_CHECK_MESSAGE(txFromFields == txFromRlp, "However, txFromFields != txFromRlp!");
BOOST_REQUIRE (o.count("sender") > 0);
TBOOST_CHECK_MESSAGE((txFromFields.data() == txFromRlp.data()), "Data in given RLP not matching the Transaction data!");
TBOOST_CHECK_MESSAGE((txFromFields.value() == txFromRlp.value()), "Value in given RLP not matching the Transaction value!");
TBOOST_CHECK_MESSAGE((txFromFields.gasPrice() == txFromRlp.gasPrice()), "GasPrice in given RLP not matching the Transaction gasPrice!");
TBOOST_CHECK_MESSAGE((txFromFields.gas() == txFromRlp.gas()),"Gas in given RLP not matching the Transaction gas!");
TBOOST_CHECK_MESSAGE((txFromFields.nonce() == txFromRlp.nonce()),"Nonce in given RLP not matching the Transaction nonce!");
TBOOST_CHECK_MESSAGE((txFromFields.receiveAddress() == txFromRlp.receiveAddress()), "Receive address in given RLP not matching the Transaction 'to' address!");
TBOOST_CHECK_MESSAGE((txFromFields.sender() == txFromRlp.sender()), "Transaction sender address in given RLP not matching the Transaction 'vrs' signature!");
TBOOST_CHECK_MESSAGE((txFromFields == txFromRlp), "However, txFromFields != txFromRlp!");
TBOOST_REQUIRE ((o.count("sender") > 0));
Address addressReaded = Address(o["sender"].get_str());
BOOST_CHECK_MESSAGE(txFromFields.sender() == addressReaded || txFromRlp.sender() == addressReaded, "Signature address of sender does not match given sender address!");
TBOOST_CHECK_MESSAGE((txFromFields.sender() == addressReaded || txFromRlp.sender() == addressReaded), "Signature address of sender does not match given sender address!");
}
}//for
}//doTransactionTests

Loading…
Cancel
Save