Skip to content

Commit

Permalink
Merge pull request ethereum#4658 from ethereum/options
Browse files Browse the repository at this point in the history
options for createRandomTest from file
  • Loading branch information
winsvega authored Nov 30, 2017
2 parents 5f2f8ee + 8061b9a commit f9d9a62
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 8 deletions.
4 changes: 2 additions & 2 deletions test/tools/fuzzTesting/RandomCode.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* @date 2017
*/

#pragma once
#include <string>
#include <random>
#include <boost/filesystem/path.hpp>
Expand All @@ -28,8 +29,6 @@
#include <libevm/Instruction.h>
#include <test/tools/libtesteth/TestSuite.h>

#pragma once

namespace dev
{
namespace test
Expand All @@ -56,6 +55,7 @@ struct RandomCodeOptions
RandomCodeOptions();
void setWeight(dev::eth::Instruction _opCode, int _weight);
void addAddress(dev::Address const& _address, AddressType _type);
void loadFromFile(boost::filesystem::path const& _file);
dev::Address getRandomAddress(AddressType _type = AddressType::All) const;
int getWeightedRandomOpcode() const;

Expand Down
6 changes: 4 additions & 2 deletions test/tools/fuzzTesting/createRandomTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ bool createRandomTest()
}
else
{
RandomCodeOptions options;
std::string test = test::RandomCode::get().fillRandomTest(suite, c_testExampleStateTest, options);
RandomCodeOptions codeOptions;
if (options.randomCodeOptionsPath.is_initialized())
codeOptions.loadFromFile(options.randomCodeOptionsPath.get());
std::string test = test::RandomCode::get().fillRandomTest(suite, c_testExampleStateTest, codeOptions);
std::cout << test << "\n";
return test.empty() ? false : true;
}
Expand Down
41 changes: 41 additions & 0 deletions test/tools/fuzzTesting/fuzzHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
#include <test/tools/fuzzTesting/fuzzHelper.h>
#include <test/tools/libtesteth/TestOutputHelper.h>
#include <test/tools/jsontests/StateTests.h>
#include <json_spirit/json_spirit.h>

using namespace dev;
using namespace std;
const static std::array<eth::Instruction, 47> invalidOpcodes {{
eth::Instruction::INVALID,
eth::Instruction::PUSHC,
Expand Down Expand Up @@ -485,6 +487,45 @@ RandomCodeOptions::RandomCodeOptions() :
addAddress(Address("0x0000000000000000000000000000000000000008"), AddressType::ByzantiumPrecompiled);
}

void boost_require_range(int _value, int _min, int _max)
{
BOOST_REQUIRE(_value >= _min);
BOOST_REQUIRE(_value <= _max);
}

int getProbability(json_spirit::mValue const& _obj)
{
int probability = _obj.get_int();
boost_require_range(probability, 0, 100);
return probability;
}

void RandomCodeOptions::loadFromFile(boost::filesystem::path const& _jsonFileName)
{
json_spirit::mValue v;
bytes const byteContents = dev::contents(_jsonFileName);
string const s = asString(byteContents);
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + _jsonFileName.string() + " is empty.");
json_spirit::read_string(s, v);

BOOST_REQUIRE(v.type() == json_spirit::obj_type);
json_spirit::mObject obj = v.get_obj();
BOOST_REQUIRE(obj.count("probabilities"));
BOOST_REQUIRE(obj.at("probabilities").type() == json_spirit::obj_type);

//Parse Probabilities
json_spirit::mObject probObj = obj.at("probabilities").get_obj();
useUndefinedOpCodes = probObj.at("useUndefinedOpCodes").get_bool();
smartCodeProbability = getProbability(probObj.at("smartCodeProbability"));
randomAddressProbability = getProbability(probObj.at("randomAddressProbability"));
emptyCodeProbability = getProbability(probObj.at("emptyCodeProbability"));
emptyAddressProbability = getProbability(probObj.at("emptyAddressProbability"));
precompiledAddressProbability = getProbability(probObj.at("precompiledAddressProbability"));
byzPrecompiledAddressProbability = getProbability(probObj.at("byzPrecompiledAddressProbability"));
precompiledDestProbability = getProbability(probObj.at("precompiledDestProbability"));
sendingAddressProbability = getProbability(probObj.at("sendingAddressProbability"));
}

void RandomCodeOptions::setWeight(eth::Instruction _opCode, int _weight)
{
mapWeights.at((uint8_t)_opCode) = _weight;
Expand Down
35 changes: 31 additions & 4 deletions test/tools/libtesteth/Options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ void printHelp()
cout << setw(30) << "--fillchain" << setw(25) << "When filling the state tests, fill tests as blockchain instead\n";
cout << setw(30) << "--randomcode <MaxOpcodeNum>" << setw(25) << "Generate smart random EVM code\n";
cout << setw(30) << "--createRandomTest" << setw(25) << "Create random test and output it to the console\n";
cout << setw(30) << "--createRandomTest <PathToOptions.json>" << setw(25) << "Use following options file for random code generation\n";
cout << setw(30) << "--seed <uint>" << setw(25) << "Define a seed for random test\n";
cout << setw(30) << "--options <PathTo.json>" << setw(25) << "Use following options file for random code generation\n";
//cout << setw(30) << "--fulloutput" << setw(25) << "Disable address compression in the output field\n";

cout << setw(30) << "--help" << setw(25) << "Display list of command arguments\n";
Expand Down Expand Up @@ -204,6 +206,18 @@ Options::Options(int argc, char** argv)
if (indentLevelInt > g_logVerbosity)
g_logVerbosity = indentLevelInt;
}
else if (arg == "--options")
{
throwIfNoArgumentFollows();
boost::filesystem::path file(std::string{argv[++i]});
if (boost::filesystem::exists(file))
randomCodeOptionsPath = file;
else
{
std::cerr << "Options file not found! Default options at: tests/src/randomCodeOptions.json\n";
exit(0);
}
}
else if (arg == "-t")
{
throwIfAfterSeparator();
Expand Down Expand Up @@ -248,7 +262,23 @@ Options::Options(int argc, char** argv)
exit(0);
}
else if (arg == "--createRandomTest")
{
createRandomTest = true;
if (i + 1 < argc) // two params
{
auto options = std::string{argv[++i]};
if (options[0] == '-') // not param, another option
i--;
else
{
boost::filesystem::path file(options);
if (boost::filesystem::exists(file))
randomCodeOptionsPath = file;
else
BOOST_THROW_EXCEPTION(InvalidOption("Options file not found! Default options at: tests/src/randomCodeOptions.json\n"));
}
}
}
else if (arg == "--seed")
{
throwIfNoArgumentFollows();
Expand Down Expand Up @@ -279,10 +309,7 @@ Options::Options(int argc, char** argv)
else
{
if (randomTestSeed.is_initialized())
{
cerr << "--seed <uint> could be used only with --createRandomTest \n";
exit(1);
}
BOOST_THROW_EXCEPTION(InvalidOption("--seed <uint> could be used only with --createRandomTest \n"));
}

//Default option
Expand Down
1 change: 1 addition & 0 deletions test/tools/libtesteth/Options.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class Options
eth::StandardTrace::DebugOptions jsontraceOptions; ///< output config for jsontrace
std::string testpath; ///< Custom test folder path
Verbosity logVerbosity = Verbosity::NiceReport;
boost::optional<boost::filesystem::path> randomCodeOptionsPath; ///< Options for random code generation in fuzz tests

/// Test selection
/// @{
Expand Down

0 comments on commit f9d9a62

Please sign in to comment.