diff options
author | Leonardo Alt <leo@ethereum.org> | 2018-11-15 23:47:52 +0800 |
---|---|---|
committer | Alex Beregszaszi <alex@rtfs.hu> | 2018-11-23 18:51:06 +0800 |
commit | 0ff4cbe51ba653397a1937c8c08b3d09541492ef (patch) | |
tree | 03a8798bca8f2ef221d77fc8a4c6c5390105800c /test | |
parent | 6251a289dd55cc54f8da5a907dc4982a4b5e57fa (diff) | |
download | dexon-solidity-0ff4cbe51ba653397a1937c8c08b3d09541492ef.tar dexon-solidity-0ff4cbe51ba653397a1937c8c08b3d09541492ef.tar.gz dexon-solidity-0ff4cbe51ba653397a1937c8c08b3d09541492ef.tar.bz2 dexon-solidity-0ff4cbe51ba653397a1937c8c08b3d09541492ef.tar.lz dexon-solidity-0ff4cbe51ba653397a1937c8c08b3d09541492ef.tar.xz dexon-solidity-0ff4cbe51ba653397a1937c8c08b3d09541492ef.tar.zst dexon-solidity-0ff4cbe51ba653397a1937c8c08b3d09541492ef.zip |
Add SMTChecker tests for standard JSON
Diffstat (limited to 'test')
-rw-r--r-- | test/boostTest.cpp | 10 | ||||
-rw-r--r-- | test/libsolidity/SMTCheckerJSONTest.cpp | 128 | ||||
-rw-r--r-- | test/libsolidity/SMTCheckerJSONTest.h | 53 | ||||
-rw-r--r-- | test/libsolidity/SyntaxTest.cpp | 5 | ||||
-rw-r--r-- | test/libsolidity/SyntaxTest.h | 4 | ||||
-rw-r--r-- | test/libsolidity/smtCheckerTestsJSON/multi.json | 11 | ||||
-rw-r--r-- | test/libsolidity/smtCheckerTestsJSON/multi.sol | 13 | ||||
-rw-r--r-- | test/libsolidity/smtCheckerTestsJSON/simple.json | 9 | ||||
-rw-r--r-- | test/libsolidity/smtCheckerTestsJSON/simple.sol | 10 | ||||
-rw-r--r-- | test/tools/CMakeLists.txt | 2 | ||||
-rw-r--r-- | test/tools/isoltest.cpp | 12 |
11 files changed, 255 insertions, 2 deletions
diff --git a/test/boostTest.cpp b/test/boostTest.cpp index 5352ef85..6ff6d2d2 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -38,6 +38,7 @@ #include <test/Options.h> #include <test/libsolidity/ASTJSONTest.h> #include <test/libsolidity/SyntaxTest.h> +#include <test/libsolidity/SMTCheckerJSONTest.h> #include <test/libyul/YulOptimizerTest.h> #include <boost/algorithm/string.hpp> @@ -146,12 +147,21 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] ) dev::yul::test::YulOptimizerTest::create ) > 0, "no Yul Optimizer tests found"); if (!dev::test::Options::get().disableSMT) + { solAssert(registerTests( master, dev::test::Options::get().testPath / "libsolidity", "smtCheckerTests", SyntaxTest::create ) > 0, "no SMT checker tests found"); + + solAssert(registerTests( + master, + dev::test::Options::get().testPath / "libsolidity", + "smtCheckerTestsJSON", + SMTCheckerTest::create + ) > 0, "no SMT checker JSON tests found"); + } if (dev::test::Options::get().disableIPC) { for (auto suite: { diff --git a/test/libsolidity/SMTCheckerJSONTest.cpp b/test/libsolidity/SMTCheckerJSONTest.cpp new file mode 100644 index 00000000..6e1329a9 --- /dev/null +++ b/test/libsolidity/SMTCheckerJSONTest.cpp @@ -0,0 +1,128 @@ +/* + 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 <http://www.gnu.org/licenses/>. +*/ + +#include <test/libsolidity/SMTCheckerJSONTest.h> +#include <test/Options.h> +#include <libsolidity/interface/StandardCompiler.h> +#include <libdevcore/JSON.h> +#include <boost/algorithm/string.hpp> +#include <boost/algorithm/string/join.hpp> +#include <boost/algorithm/string/predicate.hpp> +#include <boost/throw_exception.hpp> +#include <fstream> +#include <memory> +#include <stdexcept> +#include <sstream> + +using namespace dev; +using namespace solidity; +using namespace dev::solidity::test; +using namespace dev::solidity::test::formatting; +using namespace std; +using namespace boost::unit_test; + +SMTCheckerTest::SMTCheckerTest(string const& _filename) +: SyntaxTest(_filename) +{ + BOOST_REQUIRE_MESSAGE(boost::algorithm::ends_with(_filename, ".sol"), "Invalid test contract file name: \"" + _filename + "\"."); + + string jsonFilename = _filename.substr(0, _filename.size() - 4) + ".json"; + BOOST_CHECK(jsonParseFile(jsonFilename, m_smtResponses)); + BOOST_CHECK(m_smtResponses.isObject()); +} + +bool SMTCheckerTest::run(ostream& _stream, string const& _linePrefix, bool const _formatted) +{ + StandardCompiler compiler; + + // Run the compiler and retrieve the smtlib2queries (1st run) + string versionPragma = "pragma solidity >=0.0;\n"; + Json::Value input = buildJson(versionPragma); + Json::Value result = compiler.compile(input); + + // This is the list of query hashes requested by the 1st run + vector<string> outHashes = hashesFromJson(result, "auxiliaryInputRequested", "smtlib2queries"); + + // This is the list of responses provided in the test + string auxInput("auxiliaryInput"); + BOOST_CHECK(m_smtResponses.isMember(auxInput)); + vector<string> inHashes = hashesFromJson(m_smtResponses, auxInput, "smtlib2responses"); + + // Ensure that the provided list matches the requested one + BOOST_CHECK_MESSAGE( + outHashes == inHashes, + "SMT query hashes differ: " + boost::algorithm::join(outHashes, ", ") + " x " + boost::algorithm::join(inHashes, ", ") + ); + + // Rerun the compiler with the provided hashed (2nd run) + input[auxInput] = m_smtResponses[auxInput]; + Json::Value endResult = compiler.compile(input); + + BOOST_CHECK(endResult.isMember("errors")); + Json::Value const& errors = endResult["errors"]; + for (auto const& error: errors) + { + BOOST_CHECK(error.isMember("type") && error["type"].isString()); + BOOST_CHECK(error.isMember("message") && error["message"].isString()); + if (!error.isMember("sourceLocation")) + continue; + Json::Value const& location = error["sourceLocation"]; + BOOST_CHECK(location.isMember("start") && location["start"].isInt()); + BOOST_CHECK(location.isMember("end") && location["end"].isInt()); + int start = location["start"].asInt(); + int end = location["end"].asInt(); + if (start >= static_cast<int>(versionPragma.size())) + start -= versionPragma.size(); + if (end >= static_cast<int>(versionPragma.size())) + end -= versionPragma.size(); + m_errorList.emplace_back(SyntaxTestError{ + error["type"].asString(), + error["message"].asString(), + start, + end + }); + } + + return printExpectationAndError(_stream, _linePrefix, _formatted); +} + +vector<string> SMTCheckerTest::hashesFromJson(Json::Value const& _jsonObj, string const& _auxInput, string const& _smtlib) +{ + vector<string> hashes; + Json::Value const& auxInputs = _jsonObj[_auxInput]; + if (!!auxInputs) + { + Json::Value const& smtlib = auxInputs[_smtlib]; + if (!!smtlib) + for (auto const& hashString: smtlib.getMemberNames()) + hashes.push_back(hashString); + } + return hashes; +} + +Json::Value SMTCheckerTest::buildJson(string const& _extra) +{ + string language = "\"language\": \"Solidity\""; + string sourceName = "\"A\""; + string sourceContent = "\"" + _extra + m_source + "\""; + string sourceObj = "{ \"content\": " + sourceContent + "}"; + string sources = " \"sources\": { " + sourceName + ": " + sourceObj + "}"; + string input = "{" + language + ", " + sources + "}"; + Json::Value source; + BOOST_REQUIRE(jsonParse(input, source)); + return source; +} diff --git a/test/libsolidity/SMTCheckerJSONTest.h b/test/libsolidity/SMTCheckerJSONTest.h new file mode 100644 index 00000000..cf41acac --- /dev/null +++ b/test/libsolidity/SMTCheckerJSONTest.h @@ -0,0 +1,53 @@ +/* + 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 <http://www.gnu.org/licenses/>. +*/ + +#pragma once + +#include <test/libsolidity/SyntaxTest.h> + +#include <libdevcore/JSON.h> + +#include <string> + +namespace dev +{ +namespace solidity +{ +namespace test +{ + +class SMTCheckerTest: public SyntaxTest +{ +public: + static std::unique_ptr<TestCase> create(std::string const& _filename) + { + return std::unique_ptr<TestCase>(new SMTCheckerTest(_filename)); + } + SMTCheckerTest(std::string const& _filename); + + bool run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; + +private: + std::vector<std::string> hashesFromJson(Json::Value const& _jsonObj, std::string const& _auxInput, std::string const& _smtlib); + Json::Value buildJson(std::string const& _extra); + + Json::Value m_smtResponses; +}; + +} +} +} diff --git a/test/libsolidity/SyntaxTest.cpp b/test/libsolidity/SyntaxTest.cpp index 45d32b55..c47ea599 100644 --- a/test/libsolidity/SyntaxTest.cpp +++ b/test/libsolidity/SyntaxTest.cpp @@ -92,6 +92,11 @@ bool SyntaxTest::run(ostream& _stream, string const& _linePrefix, bool const _fo }); } + return printExpectationAndError(_stream, _linePrefix, _formatted); +} + +bool SyntaxTest::printExpectationAndError(ostream& _stream, string const& _linePrefix, bool const _formatted) +{ if (m_expectations != m_errorList) { string nextIndentLevel = _linePrefix + " "; diff --git a/test/libsolidity/SyntaxTest.h b/test/libsolidity/SyntaxTest.h index 0f151e66..d286f934 100644 --- a/test/libsolidity/SyntaxTest.h +++ b/test/libsolidity/SyntaxTest.h @@ -67,7 +67,7 @@ public: } static std::string errorMessage(Exception const& _e); -private: +protected: static void printErrorList( std::ostream& _stream, std::vector<SyntaxTestError> const& _errors, @@ -75,6 +75,8 @@ private: bool const _formatted = false ); + virtual bool printExpectationAndError(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false); + static std::vector<SyntaxTestError> parseExpectations(std::istream& _stream); std::string m_source; diff --git a/test/libsolidity/smtCheckerTestsJSON/multi.json b/test/libsolidity/smtCheckerTestsJSON/multi.json new file mode 100644 index 00000000..2ed5150d --- /dev/null +++ b/test/libsolidity/smtCheckerTestsJSON/multi.json @@ -0,0 +1,11 @@ +{ + "auxiliaryInput": + { + "smtlib2responses": + { + "0x0426cd198d1e7123a28ffac2b759a666b86508ad046babf5166500dd6d8ed308": "unsat\n(error \"line 31 column 26: model is not available\")", + "0xa51ca41ae407f5a727f27101cbc079834743cc8955f9f585582034ca634953f6": "sat\n((|EVALEXPR_0| 1))", + "0xe9477f683ff20aa57fcb08682150f86c5917e1d4c0686b278ab9b73446d0682c": "sat\n((|EVALEXPR_0| 0))" + } + } +} diff --git a/test/libsolidity/smtCheckerTestsJSON/multi.sol b/test/libsolidity/smtCheckerTestsJSON/multi.sol new file mode 100644 index 00000000..e0d69b1d --- /dev/null +++ b/test/libsolidity/smtCheckerTestsJSON/multi.sol @@ -0,0 +1,13 @@ +pragma experimental SMTChecker; + +contract C +{ + function f(uint x) public pure { + assert(x > 0); + assert(x > 100); + assert(x >= 0); + } +} +// ---- +// Warning: (82-95): Assertion violation happens here +// Warning: (99-114): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTestsJSON/simple.json b/test/libsolidity/smtCheckerTestsJSON/simple.json new file mode 100644 index 00000000..fd976b63 --- /dev/null +++ b/test/libsolidity/smtCheckerTestsJSON/simple.json @@ -0,0 +1,9 @@ +{ + "auxiliaryInput": + { + "smtlib2responses": + { + "0xe9477f683ff20aa57fcb08682150f86c5917e1d4c0686b278ab9b73446d0682c": "sat\n((|EVALEXPR_0| 0))" + } + } +} diff --git a/test/libsolidity/smtCheckerTestsJSON/simple.sol b/test/libsolidity/smtCheckerTestsJSON/simple.sol new file mode 100644 index 00000000..6bc7193d --- /dev/null +++ b/test/libsolidity/smtCheckerTestsJSON/simple.sol @@ -0,0 +1,10 @@ +pragma experimental SMTChecker; + +contract C +{ + function f(uint x) public pure { + assert(x > 0); + } +} +// ---- +// Warning: (82-95): Assertion violation happens here diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt index 19a1d958..a0fbe140 100644 --- a/test/tools/CMakeLists.txt +++ b/test/tools/CMakeLists.txt @@ -6,5 +6,5 @@ target_link_libraries(yulopti PRIVATE solidity ${Boost_PROGRAM_OPTIONS_LIBRARIES add_executable(isoltest isoltest.cpp ../Options.cpp ../Common.cpp ../libsolidity/TestCase.cpp ../libsolidity/SyntaxTest.cpp ../libsolidity/AnalysisFramework.cpp ../libsolidity/SolidityExecutionFramework.cpp ../ExecutionFramework.cpp - ../RPCSession.cpp ../libsolidity/ASTJSONTest.cpp ../libyul/YulOptimizerTest.cpp) + ../RPCSession.cpp ../libsolidity/ASTJSONTest.cpp ../libsolidity/SMTCheckerJSONTest.cpp ../libyul/YulOptimizerTest.cpp) target_link_libraries(isoltest PRIVATE libsolc solidity evmasm ${Boost_PROGRAM_OPTIONS_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) diff --git a/test/tools/isoltest.cpp b/test/tools/isoltest.cpp index 1b6fd54a..f8e2dc58 100644 --- a/test/tools/isoltest.cpp +++ b/test/tools/isoltest.cpp @@ -21,6 +21,7 @@ #include <test/libsolidity/AnalysisFramework.h> #include <test/libsolidity/SyntaxTest.h> #include <test/libsolidity/ASTJSONTest.h> +#include <test/libsolidity/SMTCheckerJSONTest.h> #include <test/libyul/YulOptimizerTest.h> #include <boost/algorithm/string.hpp> @@ -412,6 +413,17 @@ Allowed options)", global_stats += *stats; else return 1; + + if (auto stats = runTestSuite( + "SMT Checker JSON", + testPath / "libsolidity", + "smtCheckerTestsJSON", + SMTCheckerTest::create, + formatted + )) + global_stats += *stats; + else + return 1; } cout << endl << "Summary: "; |