From 121f87b043d7c3f01c760589edf1bf342d67c634 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Mon, 12 Mar 2018 14:13:19 +0100 Subject: Move test tools to the subdirectory test/tools and adjust CMakeLists.txt. --- circle.yml | 2 +- scripts/uniqueErrors.sh | 2 +- test/CMakeLists.txt | 30 +++++-- test/cmdlineTests.sh | 4 +- test/fuzzer.cpp | 216 ---------------------------------------------- test/tools/CMakeLists.txt | 2 + test/tools/fuzzer.cpp | 216 ++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 246 insertions(+), 226 deletions(-) delete mode 100644 test/fuzzer.cpp create mode 100644 test/tools/CMakeLists.txt create mode 100644 test/tools/fuzzer.cpp diff --git a/circle.yml b/circle.yml index 263cb700..49c73ce4 100644 --- a/circle.yml +++ b/circle.yml @@ -126,7 +126,7 @@ jobs: paths: - solc/solc - test/soltest - - test/solfuzzer + - test/tools/solfuzzer test_x86: docker: diff --git a/scripts/uniqueErrors.sh b/scripts/uniqueErrors.sh index eee1df90..fa2c7b4c 100755 --- a/scripts/uniqueErrors.sh +++ b/scripts/uniqueErrors.sh @@ -9,6 +9,6 @@ do echo -n $x " # " # This subshell is a workaround to prevent the shell from printing # "Aborted" - ("$REPO"/build/test/solfuzzer < "$x" || true) 2>&1 | head -n 1 + ("$REPO"/build/test/tools/solfuzzer < "$x" || true) 2>&1 | head -n 1 done ) | sort -u -t'#' -k 2 diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f36ad4c5..522856cc 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,9 +1,27 @@ -file(GLOB_RECURSE sources "*.cpp") -list(REMOVE_ITEM sources "${CMAKE_CURRENT_SOURCE_DIR}/fuzzer.cpp") -file(GLOB_RECURSE headers "*.h") +file(GLOB sources "*.cpp") +file(GLOB headers "*.h") -add_executable(soltest ${sources} ${headers}) +file(GLOB contracts_sources "contracts/*.cpp") +file(GLOB contracts_headers "contracts/*.h") +file(GLOB libdevcore_sources "libdevcore/*.cpp") +file(GLOB libdevcore_headers "libdevcore/*.h") +file(GLOB libevmasm_sources "libevmasm/*.cpp") +file(GLOB libevmasm_headers "libevmasm/*.h") +file(GLOB libjulia_sources "libjulia/*.cpp") +file(GLOB libjulia_headers "libjulia/*.h") +file(GLOB liblll_sources "liblll/*.cpp") +file(GLOB liblll_headers "liblll/*.h") +file(GLOB libsolidity_sources "libsolidity/*.cpp") +file(GLOB libsolidity_headers "libsolidity/*.h") + +add_executable(soltest ${sources} ${headers} + ${contracts_sources} ${contracts_headers} + ${libdevcore_sources} ${libdevcore_headers} + ${libevmasm_sources} ${libevmasm_headers} + ${libjulia_sources} ${libjulia_headers} + ${liblll_sources} ${liblll_headers} + ${libsolidity_sources} ${libsolidity_headers} +) target_link_libraries(soltest PRIVATE libsolc solidity lll evmasm devcore ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) -add_executable(solfuzzer fuzzer.cpp) -target_link_libraries(solfuzzer PRIVATE libsolc evmasm ${Boost_PROGRAM_OPTIONS_LIBRARIES}) +add_subdirectory(tools) diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index e86e0ad4..92f9569a 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -170,14 +170,14 @@ TMPDIR=$(mktemp -d) for f in *.sol do set +e - "$REPO_ROOT"/build/test/solfuzzer --quiet < "$f" + "$REPO_ROOT"/build/test/tools/solfuzzer --quiet < "$f" if [ $? -ne 0 ]; then printError "Fuzzer failed on:" cat "$f" exit 1 fi - "$REPO_ROOT"/build/test/solfuzzer --without-optimizer --quiet < "$f" + "$REPO_ROOT"/build/test/tools/solfuzzer --without-optimizer --quiet < "$f" if [ $? -ne 0 ]; then printError "Fuzzer (without optimizer) failed on:" cat "$f" diff --git a/test/fuzzer.cpp b/test/fuzzer.cpp deleted file mode 100644 index 71f38b67..00000000 --- a/test/fuzzer.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - This file is part of solidity. - - solidity 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. - - solidity 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 solidity. If not, see . -*/ -/** - * Executable for use with AFL . - */ - -#include -#include -#include -#include - -#include - -#include - -#include -#include - -using namespace std; -using namespace dev; -using namespace dev::eth; -namespace po = boost::program_options; - -namespace -{ - -bool quiet = false; - -string contains(string const& _haystack, vector const& _needles) -{ - for (string const& needle: _needles) - if (_haystack.find(needle) != string::npos) - return needle; - return ""; -} - -void testConstantOptimizer() -{ - if (!quiet) - cout << "Testing constant optimizer" << endl; - vector numbers; - while (!cin.eof()) - { - h256 data; - cin.read(reinterpret_cast(data.data()), 32); - numbers.push_back(u256(data)); - } - if (!quiet) - cout << "Got " << numbers.size() << " inputs:" << endl; - - Assembly assembly; - for (u256 const& n: numbers) - { - if (!quiet) - cout << n << endl; - assembly.append(n); - } - for (bool isCreation: {false, true}) - { - for (unsigned runs: {1, 2, 3, 20, 40, 100, 200, 400, 1000}) - { - ConstantOptimisationMethod::optimiseConstants( - isCreation, - runs, - EVMVersion{}, - assembly, - const_cast(assembly.items()) - ); - } - } -} - -void testStandardCompiler() -{ - if (!quiet) - cout << "Testing compiler via JSON interface." << endl; - string input = readStandardInput(); - - string outputString(compileStandard(input.c_str(), NULL)); - Json::Value output; - if (!jsonParseStrict(outputString, output)) - { - cout << "Compiler produced invalid JSON output." << endl; - abort(); - } - if (output.isMember("errors")) - for (auto const& error: output["errors"]) - { - string invalid = contains(error["type"].asString(), vector{ - "Exception", - "InternalCompilerError" - }); - if (!invalid.empty()) - { - cout << "Invalid error: \"" << error["type"].asString() << "\"" << endl; - abort(); - } - } -} - -void testCompiler(bool optimize) -{ - if (!quiet) - cout << "Testing compiler " << (optimize ? "with" : "without") << " optimizer." << endl; - string input = readStandardInput(); - - string outputString(compileJSON(input.c_str(), optimize)); - Json::Value outputJson; - if (!jsonParseStrict(outputString, outputJson)) - { - cout << "Compiler produced invalid JSON output." << endl; - abort(); - } - if (outputJson.isMember("errors")) - { - if (!outputJson["errors"].isArray()) - { - cout << "Output JSON has \"errors\" but it is not an array." << endl; - abort(); - } - for (Json::Value const& error: outputJson["errors"]) - { - string invalid = contains(error.asString(), vector{ - "Internal compiler error", - "Exception during compilation", - "Unknown exception during compilation", - "Unknown exception while generating contract data output", - "Unknown exception while generating source name output", - "Unknown error while generating JSON" - }); - if (!invalid.empty()) - { - cout << "Invalid error: \"" << error.asString() << "\"" << endl; - abort(); - } - } - } - else if (!outputJson.isMember("contracts")) - { - cout << "Output JSON has neither \"errors\" nor \"contracts\"." << endl; - abort(); - } -} - -} - -int main(int argc, char** argv) -{ - po::options_description options( - R"(solfuzzer, fuzz-testing binary for use with AFL. -Usage: solfuzzer [Options] < input -Reads a single source from stdin, compiles it and signals a failure for internal errors. - -Allowed options)", - po::options_description::m_default_line_length, - po::options_description::m_default_line_length - 23); - options.add_options() - ("help", "Show this help screen.") - ("quiet", "Only output errors.") - ( - "standard-json", - "Test via the standard-json interface, i.e. " - "input is expected to be JSON-encoded instead of " - "plain source file." - ) - ( - "const-opt", - "Run the constant optimizer instead of compiling. " - "Expects a binary string of up to 32 bytes on stdin." - ) - ( - "without-optimizer", - "Run without optimizations. Cannot be used together with standard-json." - ); - - po::variables_map arguments; - try - { - po::command_line_parser cmdLineParser(argc, argv); - cmdLineParser.options(options); - po::store(cmdLineParser.run(), arguments); - } - catch (po::error const& _exception) - { - cerr << _exception.what() << endl; - return 1; - } - - if (arguments.count("quiet")) - quiet = true; - - if (arguments.count("help")) - cout << options; - else if (arguments.count("const-opt")) - testConstantOptimizer(); - else if (arguments.count("standard-json")) - testStandardCompiler(); - else - testCompiler(!arguments.count("without-optimizer")); - - return 0; -} diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt new file mode 100644 index 00000000..a693ebab --- /dev/null +++ b/test/tools/CMakeLists.txt @@ -0,0 +1,2 @@ +add_executable(solfuzzer fuzzer.cpp) +target_link_libraries(solfuzzer PRIVATE libsolc evmasm ${Boost_PROGRAM_OPTIONS_LIBRARIES}) diff --git a/test/tools/fuzzer.cpp b/test/tools/fuzzer.cpp new file mode 100644 index 00000000..71f38b67 --- /dev/null +++ b/test/tools/fuzzer.cpp @@ -0,0 +1,216 @@ +/* + This file is part of solidity. + + solidity 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. + + solidity 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 solidity. If not, see . +*/ +/** + * Executable for use with AFL . + */ + +#include +#include +#include +#include + +#include + +#include + +#include +#include + +using namespace std; +using namespace dev; +using namespace dev::eth; +namespace po = boost::program_options; + +namespace +{ + +bool quiet = false; + +string contains(string const& _haystack, vector const& _needles) +{ + for (string const& needle: _needles) + if (_haystack.find(needle) != string::npos) + return needle; + return ""; +} + +void testConstantOptimizer() +{ + if (!quiet) + cout << "Testing constant optimizer" << endl; + vector numbers; + while (!cin.eof()) + { + h256 data; + cin.read(reinterpret_cast(data.data()), 32); + numbers.push_back(u256(data)); + } + if (!quiet) + cout << "Got " << numbers.size() << " inputs:" << endl; + + Assembly assembly; + for (u256 const& n: numbers) + { + if (!quiet) + cout << n << endl; + assembly.append(n); + } + for (bool isCreation: {false, true}) + { + for (unsigned runs: {1, 2, 3, 20, 40, 100, 200, 400, 1000}) + { + ConstantOptimisationMethod::optimiseConstants( + isCreation, + runs, + EVMVersion{}, + assembly, + const_cast(assembly.items()) + ); + } + } +} + +void testStandardCompiler() +{ + if (!quiet) + cout << "Testing compiler via JSON interface." << endl; + string input = readStandardInput(); + + string outputString(compileStandard(input.c_str(), NULL)); + Json::Value output; + if (!jsonParseStrict(outputString, output)) + { + cout << "Compiler produced invalid JSON output." << endl; + abort(); + } + if (output.isMember("errors")) + for (auto const& error: output["errors"]) + { + string invalid = contains(error["type"].asString(), vector{ + "Exception", + "InternalCompilerError" + }); + if (!invalid.empty()) + { + cout << "Invalid error: \"" << error["type"].asString() << "\"" << endl; + abort(); + } + } +} + +void testCompiler(bool optimize) +{ + if (!quiet) + cout << "Testing compiler " << (optimize ? "with" : "without") << " optimizer." << endl; + string input = readStandardInput(); + + string outputString(compileJSON(input.c_str(), optimize)); + Json::Value outputJson; + if (!jsonParseStrict(outputString, outputJson)) + { + cout << "Compiler produced invalid JSON output." << endl; + abort(); + } + if (outputJson.isMember("errors")) + { + if (!outputJson["errors"].isArray()) + { + cout << "Output JSON has \"errors\" but it is not an array." << endl; + abort(); + } + for (Json::Value const& error: outputJson["errors"]) + { + string invalid = contains(error.asString(), vector{ + "Internal compiler error", + "Exception during compilation", + "Unknown exception during compilation", + "Unknown exception while generating contract data output", + "Unknown exception while generating source name output", + "Unknown error while generating JSON" + }); + if (!invalid.empty()) + { + cout << "Invalid error: \"" << error.asString() << "\"" << endl; + abort(); + } + } + } + else if (!outputJson.isMember("contracts")) + { + cout << "Output JSON has neither \"errors\" nor \"contracts\"." << endl; + abort(); + } +} + +} + +int main(int argc, char** argv) +{ + po::options_description options( + R"(solfuzzer, fuzz-testing binary for use with AFL. +Usage: solfuzzer [Options] < input +Reads a single source from stdin, compiles it and signals a failure for internal errors. + +Allowed options)", + po::options_description::m_default_line_length, + po::options_description::m_default_line_length - 23); + options.add_options() + ("help", "Show this help screen.") + ("quiet", "Only output errors.") + ( + "standard-json", + "Test via the standard-json interface, i.e. " + "input is expected to be JSON-encoded instead of " + "plain source file." + ) + ( + "const-opt", + "Run the constant optimizer instead of compiling. " + "Expects a binary string of up to 32 bytes on stdin." + ) + ( + "without-optimizer", + "Run without optimizations. Cannot be used together with standard-json." + ); + + po::variables_map arguments; + try + { + po::command_line_parser cmdLineParser(argc, argv); + cmdLineParser.options(options); + po::store(cmdLineParser.run(), arguments); + } + catch (po::error const& _exception) + { + cerr << _exception.what() << endl; + return 1; + } + + if (arguments.count("quiet")) + quiet = true; + + if (arguments.count("help")) + cout << options; + else if (arguments.count("const-opt")) + testConstantOptimizer(); + else if (arguments.count("standard-json")) + testStandardCompiler(); + else + testCompiler(!arguments.count("without-optimizer")); + + return 0; +} -- cgit v1.2.3