diff options
Diffstat (limited to 'test')
31 files changed, 533 insertions, 164 deletions
diff --git a/test/ExecutionFramework.cpp b/test/ExecutionFramework.cpp index 85b5bd3b..a24f78fb 100644 --- a/test/ExecutionFramework.cpp +++ b/test/ExecutionFramework.cpp @@ -20,13 +20,15 @@ * Framework for executing contracts and testing them using RPC. */ -#include <cstdlib> -#include <boost/test/framework.hpp> -#include <libdevcore/CommonIO.h> #include <test/ExecutionFramework.h> +#include <libdevcore/CommonIO.h> + +#include <boost/test/framework.hpp> #include <boost/algorithm/string/replace.hpp> +#include <cstdlib> + using namespace std; using namespace dev; using namespace dev::test; @@ -49,6 +51,7 @@ string getIPCSocketPath() ExecutionFramework::ExecutionFramework() : m_rpc(RPCSession::instance(getIPCSocketPath())), + m_evmVersion(dev::test::Options::get().evmVersion()), m_optimize(dev::test::Options::get().optimize), m_showMessages(dev::test::Options::get().showMessages), m_sender(m_rpc.account(0)) diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index 8aa99473..a7971b81 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -25,6 +25,8 @@ #include <test/TestHelper.h> #include <test/RPCSession.h> +#include <libsolidity/interface/EVMVersion.h> + #include <libdevcore/FixedHash.h> #include <libdevcore/SHA3.h> @@ -227,6 +229,7 @@ protected: bytes data; }; + solidity::EVMVersion m_evmVersion; unsigned m_optimizeRuns = 200; bool m_optimize = false; bool m_showMessages = false; diff --git a/test/Metadata.cpp b/test/Metadata.cpp index 1ebfd468..c130d346 100644 --- a/test/Metadata.cpp +++ b/test/Metadata.cpp @@ -60,7 +60,8 @@ bool isValidMetadata(string const& _metadata) !metadata.isMember("compiler") || !metadata.isMember("settings") || !metadata.isMember("sources") || - !metadata.isMember("output") + !metadata.isMember("output") || + !metadata["settings"].isMember("evmVersion") ) return false; diff --git a/test/RPCSession.cpp b/test/RPCSession.cpp index 69c75cee..54871057 100644 --- a/test/RPCSession.cpp +++ b/test/RPCSession.cpp @@ -19,7 +19,11 @@ /// @file RPCSession.cpp /// Low-level IPC communication between the test framework and the Ethereum node. -#include "RPCSession.h" +#include <test/RPCSession.h> + +#include <test/TestHelper.h> + +#include <libsolidity/interface/EVMVersion.h> #include <libdevcore/CommonData.h> @@ -215,6 +219,13 @@ string RPCSession::personal_newAccount(string const& _password) void RPCSession::test_setChainParams(vector<string> const& _accounts) { + string forks; + if (test::Options::get().evmVersion() >= solidity::EVMVersion::tangerineWhistle()) + forks += "\"EIP150ForkBlock\": \"0x00\",\n"; + if (test::Options::get().evmVersion() >= solidity::EVMVersion::spuriousDragon()) + forks += "\"EIP158ForkBlock\": \"0x00\",\n"; + if (test::Options::get().evmVersion() >= solidity::EVMVersion::byzantium()) + forks += "\"byzantiumForkBlock\": \"0x00\",\n"; static string const c_configString = R"( { "sealEngine": "NoProof", @@ -223,9 +234,8 @@ void RPCSession::test_setChainParams(vector<string> const& _accounts) "maximumExtraDataSize": "0x1000000", "blockReward": "0x", "allowFutureBlocks": true, - "homesteadForkBlock": "0x00", - "EIP150ForkBlock": "0x00", - "EIP158ForkBlock": "0x00" + )" + forks + R"( + "homesteadForkBlock": "0x00" }, "genesis": { "author": "0000000000000010000000000000000000000000", diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index c8747a06..e0d4423d 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -19,8 +19,12 @@ * @date 2014 */ +#include <test/TestHelper.h> + +#include <libsolidity/interface/EVMVersion.h> + #include <boost/test/framework.hpp> -#include "TestHelper.h" + using namespace std; using namespace dev::test; @@ -41,6 +45,11 @@ Options::Options() } else if (string(suite.argv[i]) == "--optimize") optimize = true; + else if (string(suite.argv[i]) == "--evm-version") + { + evmVersionString = i + 1 < suite.argc ? suite.argv[i + 1] : "INVALID"; + ++i; + } else if (string(suite.argv[i]) == "--show-messages") showMessages = true; else if (string(suite.argv[i]) == "--no-ipc") @@ -52,3 +61,17 @@ Options::Options() if (auto path = getenv("ETH_TEST_IPC")) ipcPath = path; } + +dev::solidity::EVMVersion Options::evmVersion() const +{ + if (!evmVersionString.empty()) + { + // We do this check as opposed to in the constructor because the BOOST_REQUIRE + // macros cannot yet be used in the constructor. + auto version = solidity::EVMVersion::fromString(evmVersionString); + BOOST_REQUIRE_MESSAGE(version, "Invalid EVM version: " + evmVersionString); + return *version; + } + else + return dev::solidity::EVMVersion(); +} diff --git a/test/TestHelper.h b/test/TestHelper.h index d25c5cd8..8c2eec36 100644 --- a/test/TestHelper.h +++ b/test/TestHelper.h @@ -19,11 +19,14 @@ #pragma once -#include <functional> +#include <libsolidity/interface/EVMVersion.h> + #include <boost/test/unit_test.hpp> #include <boost/filesystem.hpp> #include <boost/version.hpp> +#include <functional> + namespace dev { namespace test @@ -37,9 +40,13 @@ struct Options: boost::noncopyable bool disableIPC = false; bool disableSMT = false; + solidity::EVMVersion evmVersion() const; + static Options const& get(); private: + std::string evmVersionString; + Options(); }; diff --git a/test/contracts/LLL_ENS.cpp b/test/contracts/LLL_ENS.cpp index c5fe8a82..028d58c8 100644 --- a/test/contracts/LLL_ENS.cpp +++ b/test/contracts/LLL_ENS.cpp @@ -345,7 +345,7 @@ protected: if (!s_compiledEns) { vector<string> errors; - s_compiledEns.reset(new bytes(compileLLL(ensCode, dev::test::Options::get().optimize, &errors))); + s_compiledEns.reset(new bytes(compileLLL(ensCode, dev::test::Options::get().evmVersion(), dev::test::Options::get().optimize, &errors))); BOOST_REQUIRE(errors.empty()); } sendMessage(*s_compiledEns, true); diff --git a/test/contracts/LLL_ERC20.cpp b/test/contracts/LLL_ERC20.cpp index 25665d64..60b43e4f 100644 --- a/test/contracts/LLL_ERC20.cpp +++ b/test/contracts/LLL_ERC20.cpp @@ -396,7 +396,7 @@ protected: if (!s_compiledErc20) { vector<string> errors; - s_compiledErc20.reset(new bytes(compileLLL(erc20Code, dev::test::Options::get().optimize, &errors))); + s_compiledErc20.reset(new bytes(compileLLL(erc20Code, dev::test::Options::get().evmVersion(), dev::test::Options::get().optimize, &errors))); BOOST_REQUIRE(errors.empty()); } sendMessage(*s_compiledErc20, true); diff --git a/test/fuzzer.cpp b/test/fuzzer.cpp index 45738baa..71f38b67 100644 --- a/test/fuzzer.cpp +++ b/test/fuzzer.cpp @@ -76,6 +76,7 @@ void testConstantOptimizer() ConstantOptimisationMethod::optimiseConstants( isCreation, runs, + EVMVersion{}, assembly, const_cast<AssemblyItems&>(assembly.items()) ); diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index 0ab95b08..e6abcb53 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -20,6 +20,8 @@ * Tests for the Solidity optimizer. */ +#include <test/TestHelper.h> + #include <libevmasm/CommonSubexpressionEliminator.h> #include <libevmasm/PeepholeOptimiser.h> #include <libevmasm/JumpdestRemover.h> @@ -916,7 +918,7 @@ BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies) main.append(t1.toSubAssemblyTag(subId)); main.append(u256(8)); - main.optimise(true); + main.optimise(true, dev::test::Options::get().evmVersion()); AssemblyItems expectationMain{ AssemblyItem(PushSubSize, 0), diff --git a/test/libjulia/Common.cpp b/test/libjulia/Common.cpp index 7053a68d..d8cd20b6 100644 --- a/test/libjulia/Common.cpp +++ b/test/libjulia/Common.cpp @@ -21,6 +21,8 @@ #include <test/libjulia/Common.h> +#include <test/TestHelper.h> + #include <libjulia/optimiser/Disambiguator.h> #include <libsolidity/parsing/Scanner.h> @@ -61,7 +63,12 @@ pair<shared_ptr<Block>, shared_ptr<assembly::AsmAnalysisInfo>> dev::julia::test: { BOOST_REQUIRE(errorReporter.errors().empty()); auto analysisInfo = make_shared<assembly::AsmAnalysisInfo>(); - assembly::AsmAnalyzer analyzer(*analysisInfo, errorReporter, flavour); + assembly::AsmAnalyzer analyzer( + *analysisInfo, + errorReporter, + dev::test::Options::get().evmVersion(), + flavour + ); if (analyzer.analyze(*parserResult)) { BOOST_REQUIRE(errorReporter.errors().empty()); diff --git a/test/libjulia/Parser.cpp b/test/libjulia/Parser.cpp index ff9474c1..6476c4d4 100644 --- a/test/libjulia/Parser.cpp +++ b/test/libjulia/Parser.cpp @@ -56,7 +56,12 @@ bool parse(string const& _source, ErrorReporter& errorReporter) if (parserResult) { assembly::AsmAnalysisInfo analysisInfo; - return (assembly::AsmAnalyzer(analysisInfo, errorReporter, assembly::AsmFlavour::IULIA)).analyze(*parserResult); + return (assembly::AsmAnalyzer( + analysisInfo, + errorReporter, + dev::test::Options::get().evmVersion(), + assembly::AsmFlavour::IULIA + )).analyze(*parserResult); } } catch (FatalError const&) diff --git a/test/liblll/Compiler.cpp b/test/liblll/Compiler.cpp index ace97e15..6c6eae3f 100644 --- a/test/liblll/Compiler.cpp +++ b/test/liblll/Compiler.cpp @@ -20,11 +20,16 @@ * Unit tests for the LLL compiler. */ +#include <test/TestHelper.h> + +#include <libdevcore/FixedHash.h> + +#include <liblll/Compiler.h> + +#include <boost/test/unit_test.hpp> + #include <string> #include <memory> -#include <boost/test/unit_test.hpp> -#include <liblll/Compiler.h> -#include <libdevcore/FixedHash.h> using namespace std; @@ -41,7 +46,7 @@ namespace bool successCompile(string const& _sourceCode) { vector<string> errors; - bytes bytecode = eth::compileLLL(_sourceCode, false, &errors); + bytes bytecode = eth::compileLLL(_sourceCode, dev::test::Options::get().evmVersion(), false, &errors); if (!errors.empty()) return false; if (bytecode.empty()) @@ -353,7 +358,7 @@ BOOST_AUTO_TEST_CASE(valid_opcodes_functional) for (size_t i = 0; i < opcodes_bytecode.size(); i++) { vector<string> errors; - bytes code = eth::compileLLL(opcodes_lll[i], false, &errors); + bytes code = eth::compileLLL(opcodes_lll[i], dev::test::Options::get().evmVersion(), false, &errors); BOOST_REQUIRE_MESSAGE(errors.empty(), opcodes_lll[i]); @@ -641,7 +646,7 @@ BOOST_AUTO_TEST_CASE(valid_opcodes_asm) for (size_t i = 0; i < opcodes_bytecode.size(); i++) { vector<string> errors; - bytes code = eth::compileLLL(opcodes_lll[i], false, &errors); + bytes code = eth::compileLLL(opcodes_lll[i], dev::test::Options::get().evmVersion(), false, &errors); BOOST_REQUIRE_MESSAGE(errors.empty(), opcodes_lll[i]); diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp index 1a5bb490..e5e70cf8 100644 --- a/test/liblll/EndToEndTest.cpp +++ b/test/liblll/EndToEndTest.cpp @@ -20,10 +20,13 @@ * End to end tests for LLL. */ +#include <test/liblll/ExecutionFramework.h> +#include <test/TestHelper.h> + +#include <boost/test/unit_test.hpp> + #include <string> #include <memory> -#include <boost/test/unit_test.hpp> -#include <test/liblll/ExecutionFramework.h> using namespace std; @@ -583,24 +586,34 @@ BOOST_AUTO_TEST_CASE(allgas) BOOST_AUTO_TEST_CASE(send_two_args) { - char const* sourceCode = R"( - (returnlll - (send 0xdead 42)) - )"; - compileAndRun(sourceCode); - callFallbackWithValue(42); - BOOST_CHECK(balanceAt(Address(0xdead)) == 42); + // "send" does not retain enough gas to be able to pay for account creation. + // Disabling for non-tangerineWhistle VMs. + if (dev::test::Options::get().evmVersion().canOverchargeGasForCall()) + { + char const* sourceCode = R"( + (returnlll + (send 0xdead 42)) + )"; + compileAndRun(sourceCode); + callFallbackWithValue(42); + BOOST_CHECK(balanceAt(Address(0xdead)) == 42); + } } BOOST_AUTO_TEST_CASE(send_three_args) { - char const* sourceCode = R"( - (returnlll - (send allgas 0xdead 42)) - )"; - compileAndRun(sourceCode); - callFallbackWithValue(42); - BOOST_CHECK(balanceAt(Address(0xdead)) == 42); + // "send" does not retain enough gas to be able to pay for account creation. + // Disabling for non-tangerineWhistle VMs. + if (dev::test::Options::get().evmVersion().canOverchargeGasForCall()) + { + char const* sourceCode = R"( + (returnlll + (send allgas 0xdead 42)) + )"; + compileAndRun(sourceCode); + callFallbackWithValue(42); + BOOST_CHECK(balanceAt(Address(0xdead)) == 42); + } } // Regression test for edge case that previously failed @@ -708,56 +721,76 @@ BOOST_AUTO_TEST_CASE(msg_four_args) BOOST_AUTO_TEST_CASE(msg_three_args) { - char const* sourceCode = R"( - (returnlll - (seq - (when (= 0 (calldatasize)) - (return (msg (address) 42 0xff))) - (return (callvalue)))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallbackWithValue(42) == encodeArgs(u256(42))); + // "msg" does not retain enough gas. + // Disabling for non-tangerineWhistle VMs. + if (dev::test::Options::get().evmVersion().canOverchargeGasForCall()) + { + char const* sourceCode = R"( + (returnlll + (seq + (when (= 0 (calldatasize)) + (return (msg (address) 42 0xff))) + (return (callvalue)))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallbackWithValue(42) == encodeArgs(u256(42))); + } } BOOST_AUTO_TEST_CASE(msg_two_args) { - char const* sourceCode = R"( - (returnlll - (seq - (when (= 0 (calldatasize)) - (return (msg (address) 0xff))) - (return 42))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(u256(42))); + // "msg" does not retain enough gas. + // Disabling for non-tangerineWhistle VMs. + if (dev::test::Options::get().evmVersion().canOverchargeGasForCall()) + { + char const* sourceCode = R"( + (returnlll + (seq + (when (= 0 (calldatasize)) + (return (msg (address) 0xff))) + (return 42))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == encodeArgs(u256(42))); + } } BOOST_AUTO_TEST_CASE(create_one_arg) { - char const* sourceCode = R"( - (returnlll - (seq - (call allgas - (create (returnlll (return 42))) - 0 0 0 0x00 0x20) - (return 0x00 0x20))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(u256(42))); + // "call" does not retain enough gas. + // Disabling for non-tangerineWhistle VMs. + if (dev::test::Options::get().evmVersion().canOverchargeGasForCall()) + { + char const* sourceCode = R"( + (returnlll + (seq + (call allgas + (create (returnlll (return 42))) + 0 0 0 0x00 0x20) + (return 0x00 0x20))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == encodeArgs(u256(42))); + } } BOOST_AUTO_TEST_CASE(create_two_args) { - char const* sourceCode = R"( - (returnlll - (seq - (call allgas - (create 42 (returnlll (return (balance (address))))) - 0 0 0 0x00 0x20) - (return 0x00 0x20))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallbackWithValue(42) == encodeArgs(u256(42))); + // "call" does not retain enough gas. + // Disabling for non-tangerineWhistle VMs. + if (dev::test::Options::get().evmVersion().canOverchargeGasForCall()) + { + char const* sourceCode = R"( + (returnlll + (seq + (call allgas + (create 42 (returnlll (return (balance (address))))) + 0 0 0 0x00 0x20) + (return 0x00 0x20))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallbackWithValue(42) == encodeArgs(u256(42))); + } } BOOST_AUTO_TEST_CASE(sha3_two_args) @@ -822,77 +855,102 @@ BOOST_AUTO_TEST_CASE(makeperm) // Covers makeperm (implicit), permcount and perm BOOST_AUTO_TEST_CASE(ecrecover) { - char const* sourceCode = R"( - (returnlll - (return - (ecrecover - ; Hash of 'hello world' - 0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad - ; v = 1 + 27 - 0x1c - ; r - 0xdebaaa0cddb321b2dcaaf846d39605de7b97e77ba6106587855b9106cb104215 - ; s - 0x61a22d94fa8b8a687ff9c911c844d1c016d1a685a9166858f9c7c1bc85128aca))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(fromHex("0x8743523d96a1b2cbe0c6909653a56da18ed484af"))); + // "ecrecover" does not retain enough gas. + // Disabling for non-tangerineWhistle VMs. + if (dev::test::Options::get().evmVersion().canOverchargeGasForCall()) + { + char const* sourceCode = R"( + (returnlll + (return + (ecrecover + ; Hash of 'hello world' + 0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad + ; v = 1 + 27 + 0x1c + ; r + 0xdebaaa0cddb321b2dcaaf846d39605de7b97e77ba6106587855b9106cb104215 + ; s + 0x61a22d94fa8b8a687ff9c911c844d1c016d1a685a9166858f9c7c1bc85128aca))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == encodeArgs(fromHex("0x8743523d96a1b2cbe0c6909653a56da18ed484af"))); + } } BOOST_AUTO_TEST_CASE(sha256_two_args) { - char const* sourceCode = R"( - (returnlll - (seq - (lit 0x20 "abcdefghijklmnopqrstuvwxyzABCDEF") - (lit 0x40 "GHIJKLMNOPQRSTUVWXYZ0123456789?!") - (sha256 0x20 0x40) - (return 0x00 0x20))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs( - fromHex("0xcf25a9fe3d86ae228c226c81d2d8c64c687cd6dc4586d10d8e7e4e5b6706d429"))); + // "sha256" does not retain enough gas. + // Disabling for non-tangerineWhistle VMs. + if (dev::test::Options::get().evmVersion().canOverchargeGasForCall()) + { + char const* sourceCode = R"( + (returnlll + (seq + (lit 0x20 "abcdefghijklmnopqrstuvwxyzABCDEF") + (lit 0x40 "GHIJKLMNOPQRSTUVWXYZ0123456789?!") + (sha256 0x20 0x40) + (return 0x00 0x20))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == encodeArgs( + fromHex("0xcf25a9fe3d86ae228c226c81d2d8c64c687cd6dc4586d10d8e7e4e5b6706d429"))); + } } BOOST_AUTO_TEST_CASE(ripemd160_two_args) { - char const* sourceCode = R"( - (returnlll - (seq - (lit 0x20 "abcdefghijklmnopqrstuvwxyzABCDEF") - (lit 0x40 "GHIJKLMNOPQRSTUVWXYZ0123456789?!") - (ripemd160 0x20 0x40) - (return 0x00 0x20))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs( - fromHex("0x36c6b90a49e17d4c1e1b0e634ec74124d9b207da"))); + // "ripemd160" does not retain enough gas. + // Disabling for non-tangerineWhistle VMs. + if (dev::test::Options::get().evmVersion().canOverchargeGasForCall()) + { + char const* sourceCode = R"( + (returnlll + (seq + (lit 0x20 "abcdefghijklmnopqrstuvwxyzABCDEF") + (lit 0x40 "GHIJKLMNOPQRSTUVWXYZ0123456789?!") + (ripemd160 0x20 0x40) + (return 0x00 0x20))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == encodeArgs( + fromHex("0x36c6b90a49e17d4c1e1b0e634ec74124d9b207da"))); + } } BOOST_AUTO_TEST_CASE(sha256_one_arg) { - char const* sourceCode = R"( - (returnlll - (seq - (sha256 0x6162636465666768696a6b6c6d6e6f707172737475767778797a414243444546) - (return 0x00 0x20))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs( - fromHex("0xcfd2f1fad75a1978da0a444883db7251414b139f31f5a04704c291fdb0e175e6"))); + // "sha256" does not retain enough gas. + // Disabling for non-tangerineWhistle VMs. + if (dev::test::Options::get().evmVersion().canOverchargeGasForCall()) + { + char const* sourceCode = R"( + (returnlll + (seq + (sha256 0x6162636465666768696a6b6c6d6e6f707172737475767778797a414243444546) + (return 0x00 0x20))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == encodeArgs( + fromHex("0xcfd2f1fad75a1978da0a444883db7251414b139f31f5a04704c291fdb0e175e6"))); + } } BOOST_AUTO_TEST_CASE(ripemd160_one_arg) { - char const* sourceCode = R"( - (returnlll - (seq - (ripemd160 0x6162636465666768696a6b6c6d6e6f707172737475767778797a414243444546) - (return 0x00 0x20))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs( - fromHex("0xac5ab22e07b0fb80c69b6207902f725e2507e546"))); + // "ripemd160" does not retain enough gas. + // Disabling for non-tangerineWhistle VMs. + if (dev::test::Options::get().evmVersion().canOverchargeGasForCall()) + { + char const* sourceCode = R"( + (returnlll + (seq + (ripemd160 0x6162636465666768696a6b6c6d6e6f707172737475767778797a414243444546) + (return 0x00 0x20))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == encodeArgs( + fromHex("0xac5ab22e07b0fb80c69b6207902f725e2507e546"))); + } } BOOST_AUTO_TEST_CASE(wei_szabo_finney_ether) diff --git a/test/liblll/ExecutionFramework.h b/test/liblll/ExecutionFramework.h index 58e1f0ad..ae5cd988 100644 --- a/test/liblll/ExecutionFramework.h +++ b/test/liblll/ExecutionFramework.h @@ -56,7 +56,7 @@ public: BOOST_REQUIRE(_libraryAddresses.empty()); std::vector<std::string> errors; - bytes bytecode = eth::compileLLL(_sourceCode, m_optimize, &errors); + bytes bytecode = eth::compileLLL(_sourceCode, dev::test::Options::get().evmVersion(), m_optimize, &errors); if (!errors.empty()) { for (auto const& error: errors) diff --git a/test/libsolidity/ASTJSON.cpp b/test/libsolidity/ASTJSON.cpp index a165f7a9..9bf60b64 100644 --- a/test/libsolidity/ASTJSON.cpp +++ b/test/libsolidity/ASTJSON.cpp @@ -20,12 +20,16 @@ * Tests for the json ast output. */ -#include <string> -#include <boost/test/unit_test.hpp> +#include <test/TestHelper.h> + #include <libsolidity/interface/Exceptions.h> #include <libsolidity/interface/CompilerStack.h> #include <libsolidity/ast/ASTJsonConverter.h> +#include <boost/test/unit_test.hpp> + +#include <string> + using namespace std; namespace dev @@ -41,6 +45,7 @@ BOOST_AUTO_TEST_CASE(smoke_test) { CompilerStack c; c.addSource("a", "contract C {}"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; @@ -52,6 +57,7 @@ BOOST_AUTO_TEST_CASE(source_location) { CompilerStack c; c.addSource("a", "contract C { function f() { var x = 2; x++; } }"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; @@ -66,6 +72,7 @@ BOOST_AUTO_TEST_CASE(inheritance_specifier) { CompilerStack c; c.addSource("a", "contract C1 {} contract C2 is C1 {}"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; @@ -81,6 +88,7 @@ BOOST_AUTO_TEST_CASE(using_for_directive) { CompilerStack c; c.addSource("a", "library L {} contract C { using L for uint; }"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; @@ -98,6 +106,7 @@ BOOST_AUTO_TEST_CASE(enum_value) { CompilerStack c; c.addSource("a", "contract C { enum E { A, B } }"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; @@ -115,6 +124,7 @@ BOOST_AUTO_TEST_CASE(modifier_definition) { CompilerStack c; c.addSource("a", "contract C { modifier M(uint i) { _; } function F() M(1) {} }"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; @@ -129,6 +139,7 @@ BOOST_AUTO_TEST_CASE(modifier_invocation) { CompilerStack c; c.addSource("a", "contract C { modifier M(uint i) { _; } function F() M(1) {} }"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; @@ -145,6 +156,7 @@ BOOST_AUTO_TEST_CASE(event_definition) { CompilerStack c; c.addSource("a", "contract C { event E(); }"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; @@ -159,6 +171,7 @@ BOOST_AUTO_TEST_CASE(array_type_name) { CompilerStack c; c.addSource("a", "contract C { uint[] i; }"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; @@ -172,6 +185,7 @@ BOOST_AUTO_TEST_CASE(placeholder_statement) { CompilerStack c; c.addSource("a", "contract C { modifier M { _; } }"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; @@ -185,6 +199,7 @@ BOOST_AUTO_TEST_CASE(non_utf8) { CompilerStack c; c.addSource("a", "contract C { function f() { var x = hex\"ff\"; } }"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; @@ -204,6 +219,7 @@ BOOST_AUTO_TEST_CASE(function_type) "contract C { function f(function() external payable returns (uint) x) " "returns (function() external constant returns (uint)) {} }" ); + c.setEVMVersion(dev::test::Options::get().evmVersion()); c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; @@ -244,6 +260,7 @@ BOOST_AUTO_TEST_CASE(documentation) " /** Some comment on fn.*/ function fn() public {}" "}" ); + c.setEVMVersion(dev::test::Options::get().evmVersion()); c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 0; diff --git a/test/libsolidity/AnalysisFramework.cpp b/test/libsolidity/AnalysisFramework.cpp index a27e3222..7c335a48 100644 --- a/test/libsolidity/AnalysisFramework.cpp +++ b/test/libsolidity/AnalysisFramework.cpp @@ -20,6 +20,8 @@ #include <test/libsolidity/AnalysisFramework.h> +#include <test/TestHelper.h> + #include <libsolidity/interface/CompilerStack.h> #include <libsolidity/interface/SourceReferenceFormatter.h> @@ -46,6 +48,7 @@ AnalysisFramework::parseAnalyseAndReturnError( { m_compiler.reset(); m_compiler.addSource("", _insertVersionPragma ? "pragma solidity >=0.0;\n" + _source : _source); + m_compiler.setEVMVersion(dev::test::Options::get().evmVersion()); if (!m_compiler.parse()) { BOOST_ERROR("Parsing contract failed in analysis test suite:" + formatErrors()); diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index 59af6d41..aff610a4 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -20,11 +20,11 @@ * Unit tests for Assembly Items from evmasm/Assembly.h */ -#include <string> -#include <iostream> -#include <boost/test/unit_test.hpp> +#include <test/TestHelper.h> + #include <libevmasm/SourceLocation.h> #include <libevmasm/Assembly.h> + #include <libsolidity/parsing/Scanner.h> #include <libsolidity/parsing/Parser.h> #include <libsolidity/analysis/NameAndTypeResolver.h> @@ -33,6 +33,11 @@ #include <libsolidity/analysis/TypeChecker.h> #include <libsolidity/interface/ErrorReporter.h> +#include <boost/test/unit_test.hpp> + +#include <string> +#include <iostream> + using namespace std; using namespace dev::eth; @@ -46,7 +51,7 @@ namespace test namespace { -eth::AssemblyItems compileContract(const string& _sourceCode) +eth::AssemblyItems compileContract(string const& _sourceCode) { ErrorList errors; ErrorReporter errorReporter(errors); @@ -69,7 +74,7 @@ eth::AssemblyItems compileContract(const string& _sourceCode) for (ASTPointer<ASTNode> const& node: sourceUnit->nodes()) if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get())) { - TypeChecker checker(errorReporter); + TypeChecker checker(dev::test::Options::get().evmVersion(), errorReporter); BOOST_REQUIRE_NO_THROW(checker.checkTypeRequirements(*contract)); if (!Error::containsOnlyWarnings(errorReporter.errors())) return AssemblyItems(); @@ -77,7 +82,7 @@ eth::AssemblyItems compileContract(const string& _sourceCode) for (ASTPointer<ASTNode> const& node: sourceUnit->nodes()) if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get())) { - Compiler compiler; + Compiler compiler(dev::test::Options::get().evmVersion()); compiler.compileContract(*contract, map<ContractDefinition const*, Assembly const*>{}, bytes()); return compiler.runtimeAssemblyItems(); diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp index 9d3409dd..fd2017f9 100644 --- a/test/libsolidity/GasMeter.cpp +++ b/test/libsolidity/GasMeter.cpp @@ -49,13 +49,14 @@ public: m_compiler.reset(false); m_compiler.addSource("", "pragma solidity >=0.0;\n" + _sourceCode); m_compiler.setOptimiserSettings(dev::test::Options::get().optimize); + m_compiler.setEVMVersion(m_evmVersion); BOOST_REQUIRE_MESSAGE(m_compiler.compile(), "Compiling contract failed"); AssemblyItems const* items = m_compiler.runtimeAssemblyItems(m_compiler.lastContractName()); ASTNode const& sourceUnit = m_compiler.ast(""); BOOST_REQUIRE(items != nullptr); m_gasCosts = GasEstimator::breakToStatementLevel( - GasEstimator::structuralEstimation(*items, vector<ASTNode const*>({&sourceUnit})), + GasEstimator(dev::test::Options::get().evmVersion()).structuralEstimation(*items, vector<ASTNode const*>({&sourceUnit})), {&sourceUnit} ); } @@ -64,7 +65,7 @@ public: { compileAndRun(_sourceCode); auto state = make_shared<KnownState>(); - PathGasMeter meter(*m_compiler.assemblyItems(m_compiler.lastContractName())); + PathGasMeter meter(*m_compiler.assemblyItems(m_compiler.lastContractName()), dev::test::Options::get().evmVersion()); GasMeter::GasConsumption gas = meter.estimateMax(0, state); u256 bytecodeSize(m_compiler.runtimeObject(m_compiler.lastContractName()).bytecode.size()); // costs for deployment @@ -73,7 +74,7 @@ public: gas += gasForTransaction(m_compiler.object(m_compiler.lastContractName()).bytecode, true); BOOST_REQUIRE(!gas.isInfinite); - BOOST_CHECK(gas.value == m_gasUsed); + BOOST_CHECK_EQUAL(gas.value, m_gasUsed); } /// Compares the gas computed by PathGasMeter for the given signature (but unknown arguments) @@ -90,12 +91,12 @@ public: gas = max(gas, gasForTransaction(hash.asBytes() + arguments, false)); } - gas += GasEstimator::functionalEstimation( + gas += GasEstimator(dev::test::Options::get().evmVersion()).functionalEstimation( *m_compiler.runtimeAssemblyItems(m_compiler.lastContractName()), _sig ); BOOST_REQUIRE(!gas.isInfinite); - BOOST_CHECK(gas.value == m_gasUsed); + BOOST_CHECK_EQUAL(gas.value, m_gasUsed); } static GasMeter::GasConsumption gasForTransaction(bytes const& _data, bool _isCreation) diff --git a/test/libsolidity/Imports.cpp b/test/libsolidity/Imports.cpp index dc1174f4..bc81b3b1 100644 --- a/test/libsolidity/Imports.cpp +++ b/test/libsolidity/Imports.cpp @@ -21,6 +21,7 @@ */ #include <test/libsolidity/ErrorCheck.h> +#include <test/TestHelper.h> #include <libsolidity/interface/Exceptions.h> #include <libsolidity/interface/CompilerStack.h> @@ -44,6 +45,7 @@ BOOST_AUTO_TEST_CASE(smoke_test) { CompilerStack c; c.addSource("a", "contract C {} pragma solidity >=0.0;"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(c.compile()); } @@ -52,6 +54,7 @@ BOOST_AUTO_TEST_CASE(regular_import) CompilerStack c; c.addSource("a", "contract C {} pragma solidity >=0.0;"); c.addSource("b", "import \"a\"; contract D is C {} pragma solidity >=0.0;"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(c.compile()); } @@ -60,6 +63,7 @@ BOOST_AUTO_TEST_CASE(import_does_not_clutter_importee) CompilerStack c; c.addSource("a", "contract C { D d; } pragma solidity >=0.0;"); c.addSource("b", "import \"a\"; contract D is C {} pragma solidity >=0.0;"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(!c.compile()); } @@ -69,6 +73,7 @@ BOOST_AUTO_TEST_CASE(import_is_transitive) c.addSource("a", "contract C { } pragma solidity >=0.0;"); c.addSource("b", "import \"a\"; pragma solidity >=0.0;"); c.addSource("c", "import \"b\"; contract D is C {} pragma solidity >=0.0;"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(c.compile()); } @@ -77,6 +82,7 @@ BOOST_AUTO_TEST_CASE(circular_import) CompilerStack c; c.addSource("a", "import \"b\"; contract C { D d; } pragma solidity >=0.0;"); c.addSource("b", "import \"a\"; contract D { C c; } pragma solidity >=0.0;"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(c.compile()); } @@ -86,6 +92,7 @@ BOOST_AUTO_TEST_CASE(relative_import) c.addSource("a", "import \"./dir/b\"; contract A is B {} pragma solidity >=0.0;"); c.addSource("dir/b", "contract B {} pragma solidity >=0.0;"); c.addSource("dir/c", "import \"../a\"; contract C is A {} pragma solidity >=0.0;"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(c.compile()); } @@ -94,6 +101,7 @@ BOOST_AUTO_TEST_CASE(relative_import_multiplex) CompilerStack c; c.addSource("a", "contract A {} pragma solidity >=0.0;"); c.addSource("dir/a/b/c", "import \"../../.././a\"; contract B is A {} pragma solidity >=0.0;"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(c.compile()); } @@ -102,6 +110,7 @@ BOOST_AUTO_TEST_CASE(simple_alias) CompilerStack c; c.addSource("a", "contract A {} pragma solidity >=0.0;"); c.addSource("dir/a/b/c", "import \"../../.././a\" as x; contract B is x.A { function() { x.A r = x.A(20); } } pragma solidity >=0.0;"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(c.compile()); } @@ -111,6 +120,7 @@ BOOST_AUTO_TEST_CASE(library_name_clash) c.addSource("a", "library A {} pragma solidity >=0.0;"); c.addSource("b", "library A {} pragma solidity >=0.0;"); c.addSource("c", "import {A} from \"./a\"; import {A} from \"./b\";"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(!c.compile()); } @@ -119,6 +129,7 @@ BOOST_AUTO_TEST_CASE(library_name_clash_with_contract) CompilerStack c; c.addSource("a", "contract A {} pragma solidity >=0.0;"); c.addSource("b", "library A {} pragma solidity >=0.0;"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(c.compile()); } @@ -128,6 +139,7 @@ BOOST_AUTO_TEST_CASE(complex_import) c.addSource("a", "contract A {} contract B {} contract C { struct S { uint a; } } pragma solidity >=0.0;"); c.addSource("b", "import \"a\" as x; import {B as b, C as c, C} from \"a\"; " "contract D is b { function f(c.S var1, x.C.S var2, C.S var3) internal {} } pragma solidity >=0.0;"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(c.compile()); } @@ -136,14 +148,19 @@ BOOST_AUTO_TEST_CASE(name_clash_in_import) CompilerStack c; c.addSource("a", "contract A {} pragma solidity >=0.0;"); c.addSource("b", "import \"a\"; contract A {} pragma solidity >=0.0;"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(!c.compile()); c.addSource("b", "import \"a\" as A; contract A {} pragma solidity >=0.0;"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(!c.compile()); c.addSource("b", "import {A as b} from \"a\"; contract b {} pragma solidity >=0.0;"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(!c.compile()); c.addSource("b", "import {A} from \"a\"; contract A {} pragma solidity >=0.0;"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(!c.compile()); c.addSource("b", "import {A} from \"a\"; contract B {} pragma solidity >=0.0;"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(c.compile()); } @@ -155,6 +172,7 @@ BOOST_AUTO_TEST_CASE(remappings) c.addSource("b", "import \"t/tee.sol\"; contract A is Tee {} pragma solidity >=0.0;"); c.addSource("s_1.4.6/s.sol", "contract S {} pragma solidity >=0.0;"); c.addSource("Tee/tee.sol", "contract Tee {} pragma solidity >=0.0;"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(c.compile()); } @@ -166,6 +184,7 @@ BOOST_AUTO_TEST_CASE(context_dependent_remappings) c.addSource("b/b.sol", "import \"s/s.sol\"; contract B is SSeven {} pragma solidity >=0.0;"); c.addSource("s_1.4.6/s.sol", "contract SSix {} pragma solidity >=0.0;"); c.addSource("s_1.4.7/s.sol", "contract SSeven {} pragma solidity >=0.0;"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(c.compile()); } @@ -174,6 +193,7 @@ BOOST_AUTO_TEST_CASE(filename_with_period) CompilerStack c; c.addSource("a/a.sol", "import \".b.sol\"; contract A is B {} pragma solidity >=0.0;"); c.addSource("a/.b.sol", "contract B {} pragma solidity >=0.0;"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(!c.compile()); } @@ -185,6 +205,7 @@ BOOST_AUTO_TEST_CASE(context_dependent_remappings_ensure_default_and_module_pres c.addSource("vendor/bar/bar.sol", "import \"foo/foo.sol\"; contract Bar {Foo1 foo;} pragma solidity >=0.0;"); c.addSource("vendor/foo_1.0.0/foo.sol", "contract Foo1 {} pragma solidity >=0.0;"); c.addSource("vendor/foo_2.0.0/foo.sol", "contract Foo2 {} pragma solidity >=0.0;"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(c.compile()); } @@ -196,6 +217,7 @@ BOOST_AUTO_TEST_CASE(context_dependent_remappings_order_independent) c.addSource("a/b/main.sol", "import \"x/y/z/z.sol\"; contract Main is E {} pragma solidity >=0.0;"); c.addSource("d/z.sol", "contract D {} pragma solidity >=0.0;"); c.addSource("e/y/z/z.sol", "contract E {} pragma solidity >=0.0;"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(c.compile()); CompilerStack d; d.setRemappings(vector<string>{"a/b:x=e", "a:x/y/z=d"}); @@ -203,6 +225,7 @@ BOOST_AUTO_TEST_CASE(context_dependent_remappings_order_independent) d.addSource("a/b/main.sol", "import \"x/y/z/z.sol\"; contract Main is E {} pragma solidity >=0.0;"); d.addSource("d/z.sol", "contract D {} pragma solidity >=0.0;"); d.addSource("e/y/z/z.sol", "contract E {} pragma solidity >=0.0;"); + d.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(d.compile()); } @@ -212,6 +235,7 @@ BOOST_AUTO_TEST_CASE(shadowing_via_import) c.addSource("a", "library A {} pragma solidity >=0.0;"); c.addSource("b", "library A {} pragma solidity >=0.0;"); c.addSource("c", "import {A} from \"./a\"; import {A} from \"./b\";"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(!c.compile()); } @@ -225,6 +249,7 @@ BOOST_AUTO_TEST_CASE(shadowing_builtins_with_imports) contract C { } )"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(c.compile()); size_t errorCount = 0; for (auto const& e: c.errors()) @@ -251,6 +276,7 @@ BOOST_AUTO_TEST_CASE(shadowing_builtins_with_multiple_imports) contract C { } )"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(c.compile()); auto numErrors = c.errors().size(); // Sometimes we get the prerelease warning, sometimes not. @@ -274,6 +300,7 @@ BOOST_AUTO_TEST_CASE(shadowing_builtins_with_alias) pragma solidity >=0.0; import {C as msg} from "B.sol"; )"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(c.compile()); auto numErrors = c.errors().size(); // Sometimes we get the prerelease warning, sometimes not. diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index ea120657..a4dcc4d5 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -55,7 +55,7 @@ boost::optional<Error> parseAndReturnFirstError( AssemblyStack::Machine _machine = AssemblyStack::Machine::EVM ) { - AssemblyStack stack(_language); + AssemblyStack stack(dev::test::Options::get().evmVersion(), _language); bool success = false; try { @@ -117,7 +117,7 @@ Error expectError( void parsePrintCompare(string const& _source, bool _canWarn = false) { - AssemblyStack stack; + AssemblyStack stack(dev::test::Options::get().evmVersion()); BOOST_REQUIRE(stack.parseAndAnalyze("", _source)); if (_canWarn) BOOST_REQUIRE(Error::containsOnlyWarnings(stack.errors())); @@ -567,7 +567,7 @@ BOOST_AUTO_TEST_CASE(print_string_literal_unicode) { string source = "{ let x := \"\\u1bac\" }"; string parsed = "{\n let x := \"\\xe1\\xae\\xac\"\n}"; - AssemblyStack stack; + AssemblyStack stack(dev::test::Options::get().evmVersion()); BOOST_REQUIRE(stack.parseAndAnalyze("", source)); BOOST_REQUIRE(stack.errors().empty()); BOOST_CHECK_EQUAL(stack.print(), parsed); @@ -783,9 +783,9 @@ BOOST_AUTO_TEST_CASE(shift) BOOST_AUTO_TEST_CASE(shift_constantinople_warning) { - CHECK_PARSE_WARNING("{ pop(shl(10, 32)) }", Warning, "The \"shl\" instruction is only available after the Constantinople hard fork"); - CHECK_PARSE_WARNING("{ pop(shr(10, 32)) }", Warning, "The \"shr\" instruction is only available after the Constantinople hard fork"); - CHECK_PARSE_WARNING("{ pop(sar(10, 32)) }", Warning, "The \"sar\" instruction is only available after the Constantinople hard fork"); + CHECK_PARSE_WARNING("{ pop(shl(10, 32)) }", Warning, "The \"shl\" instruction is only available for Constantinople-compatible VMs."); + CHECK_PARSE_WARNING("{ pop(shr(10, 32)) }", Warning, "The \"shr\" instruction is only available for Constantinople-compatible VMs."); + CHECK_PARSE_WARNING("{ pop(sar(10, 32)) }", Warning, "The \"sar\" instruction is only available for Constantinople-compatible VMs."); } BOOST_AUTO_TEST_CASE(jump_warning) diff --git a/test/libsolidity/Metadata.cpp b/test/libsolidity/Metadata.cpp index 47cf1d3d..f1edeeb7 100644 --- a/test/libsolidity/Metadata.cpp +++ b/test/libsolidity/Metadata.cpp @@ -46,6 +46,7 @@ BOOST_AUTO_TEST_CASE(metadata_stamp) )"; CompilerStack compilerStack; compilerStack.addSource("", std::string(sourceCode)); + compilerStack.setEVMVersion(dev::test::Options::get().evmVersion()); compilerStack.setOptimiserSettings(dev::test::Options::get().optimize); BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); bytes const& bytecode = compilerStack.runtimeObject("test").bytecode; @@ -72,6 +73,7 @@ BOOST_AUTO_TEST_CASE(metadata_stamp_experimental) )"; CompilerStack compilerStack; compilerStack.addSource("", std::string(sourceCode)); + compilerStack.setEVMVersion(dev::test::Options::get().evmVersion()); compilerStack.setOptimiserSettings(dev::test::Options::get().optimize); BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); bytes const& bytecode = compilerStack.runtimeObject("test").bytecode; @@ -106,6 +108,7 @@ BOOST_AUTO_TEST_CASE(metadata_relevant_sources) } )"; compilerStack.addSource("B", std::string(sourceCode)); + compilerStack.setEVMVersion(dev::test::Options::get().evmVersion()); compilerStack.setOptimiserSettings(dev::test::Options::get().optimize); BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); @@ -144,6 +147,7 @@ BOOST_AUTO_TEST_CASE(metadata_relevant_sources_imports) } )"; compilerStack.addSource("C", std::string(sourceCode)); + compilerStack.setEVMVersion(dev::test::Options::get().evmVersion()); compilerStack.setOptimiserSettings(dev::test::Options::get().optimize); BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp index e242508a..0d471b32 100644 --- a/test/libsolidity/SolidityABIJSON.cpp +++ b/test/libsolidity/SolidityABIJSON.cpp @@ -44,6 +44,8 @@ public: { m_compilerStack.reset(false); m_compilerStack.addSource("", "pragma solidity >=0.0;\n" + _code); + m_compilerStack.setEVMVersion(dev::test::Options::get().evmVersion()); + m_compilerStack.setOptimiserSettings(dev::test::Options::get().optimize); BOOST_REQUIRE_MESSAGE(m_compilerStack.parseAndAnalyze(), "Parsing contract failed"); Json::Value generatedInterface = m_compilerStack.contractABI(m_compilerStack.lastContractName()); diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index c352a2c2..ebb2f3ff 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -5352,6 +5352,18 @@ BOOST_AUTO_TEST_CASE(super_overload) ABI_CHECK(callContractFunction("h()"), encodeArgs(2)); } +BOOST_AUTO_TEST_CASE(gasleft_shadow_resolution) +{ + char const* sourceCode = R"( + contract C { + function gasleft() returns(uint256) { return 0; } + function f() returns(uint256) { return gasleft(); } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f()"), encodeArgs(0)); +} + BOOST_AUTO_TEST_CASE(bool_conversion) { char const* sourceCode = R"( diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h index f562721d..12687dd1 100644 --- a/test/libsolidity/SolidityExecutionFramework.h +++ b/test/libsolidity/SolidityExecutionFramework.h @@ -68,6 +68,7 @@ public: m_compiler.reset(false); m_compiler.addSource("", sourceCode); m_compiler.setLibraries(_libraryAddresses); + m_compiler.setEVMVersion(m_evmVersion); m_compiler.setOptimiserSettings(m_optimize, m_optimizeRuns); if (!m_compiler.compile()) { diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index e2a0c3cd..5f044b44 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -132,7 +132,7 @@ bytes compileFirstExpression( if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get())) { ErrorReporter errorReporter(errors); - TypeChecker typeChecker(errorReporter); + TypeChecker typeChecker(dev::test::Options::get().evmVersion(), errorReporter); BOOST_REQUIRE(typeChecker.checkTypeRequirements(*contract)); } for (ASTPointer<ASTNode> const& node: sourceUnit->nodes()) @@ -141,7 +141,7 @@ bytes compileFirstExpression( FirstExpressionExtractor extractor(*contract); BOOST_REQUIRE(extractor.expression() != nullptr); - CompilerContext context; + CompilerContext context(dev::test::Options::get().evmVersion()); context.resetVisitedNodes(contract); context.setInheritanceHierarchy(inheritanceHierarchy); unsigned parametersSize = _localVariables.size(); // assume they are all one slot on the stack @@ -515,6 +515,39 @@ BOOST_AUTO_TEST_CASE(blockhash) BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } +BOOST_AUTO_TEST_CASE(gas_left) +{ + char const* sourceCode = R"( + contract test { + function f() returns (uint256 val) { + return msg.gas; + } + } + )"; + bytes code = compileFirstExpression( + sourceCode, {}, {}, + {make_shared<MagicVariableDeclaration>("msg", make_shared<MagicType>(MagicType::Kind::Message))} + ); + + bytes expectation({byte(Instruction::GAS)}); + BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); + + sourceCode = R"( + contract test { + function f() returns (uint256 val) { + return gasleft(); + } + } + )"; + code = compileFirstExpression( + sourceCode, {}, {}, + {make_shared<MagicVariableDeclaration>("gasleft", make_shared<FunctionType>(strings(), strings{"uint256"}, FunctionType::Kind::GasLeft))} + ); + + expectation = bytes({byte(Instruction::GAS)}); + BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 1fadcbde..87d62973 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -22,6 +22,8 @@ #include <test/libsolidity/AnalysisFramework.h> +#include <test/TestHelper.h> + #include <libsolidity/ast/AST.h> #include <libdevcore/SHA3.h> @@ -100,7 +102,6 @@ BOOST_AUTO_TEST_CASE(double_variable_declaration_050) )"; CHECK_WARNING_ALLOW_MULTI(text, (vector<string>{ "This declaration shadows an existing declaration.", - "Experimental features", "Unused local variable", "Unused local variable" })); @@ -131,7 +132,6 @@ BOOST_AUTO_TEST_CASE(double_variable_declaration_disjoint_scope_050) } )"; CHECK_WARNING_ALLOW_MULTI(text, (vector<string>{ - "Experimental features", "Unused local variable", "Unused local variable" })); @@ -162,7 +162,6 @@ BOOST_AUTO_TEST_CASE(double_variable_declaration_disjoint_scope_activation_050) } )"; CHECK_WARNING_ALLOW_MULTI(text, (vector<string>{ - "Experimental features", "Unused local variable", "Unused local variable" })); @@ -260,7 +259,7 @@ BOOST_AUTO_TEST_CASE(scoping_for) } } )"; - CHECK_WARNING(text, "Experimental features"); + CHECK_SUCCESS_NO_WARNINGS(text); } BOOST_AUTO_TEST_CASE(scoping_for2) @@ -274,7 +273,7 @@ BOOST_AUTO_TEST_CASE(scoping_for2) } } )"; - CHECK_WARNING(text, "Experimental features"); + CHECK_SUCCESS_NO_WARNINGS(text); } BOOST_AUTO_TEST_CASE(scoping_for3) @@ -2773,6 +2772,25 @@ BOOST_AUTO_TEST_CASE(explicit_conversion_from_decimal_to_bytesxx) CHECK_SUCCESS_NO_WARNINGS(text); } +BOOST_AUTO_TEST_CASE(combining_hex_and_denomination) +{ + char const* text = R"( + contract Foo { + uint constant x = 0x01 wei; + } + )"; + CHECK_WARNING(text, "Hexadecimal numbers with unit denominations are deprecated."); + + char const* textV050 = R"( + pragma experimental "v0.5.0"; + + contract Foo { + uint constant x = 0x01 wei; + } + )"; + CHECK_ERROR(textV050, TypeError, "Hexadecimal numbers cannot be used with unit denominations."); +} + BOOST_AUTO_TEST_CASE(assigning_value_to_const_variable) { char const* text = R"( @@ -7137,11 +7155,13 @@ BOOST_AUTO_TEST_CASE(returndatacopy_as_variable) char const* text = R"( contract c { function f() public { uint returndatasize; assembly { returndatasize }}} )"; - CHECK_ALLOW_MULTI(text, (std::vector<std::pair<Error::Type, std::string>>{ + vector<pair<Error::Type, std::string>> expectations(vector<pair<Error::Type, std::string>>{ {Error::Type::Warning, "Variable is shadowed in inline assembly by an instruction of the same name"}, - {Error::Type::DeclarationError, "Unbalanced stack"}, - {Error::Type::Warning, "only available after the Metropolis"} - })); + {Error::Type::DeclarationError, "Unbalanced stack"} + }); + if (!dev::test::Options::get().evmVersion().supportsReturndata()) + expectations.emplace_back(make_pair(Error::Type::Warning, std::string("\"returndatasize\" instruction is only available for Byzantium-compatible"))); + CHECK_ALLOW_MULTI(text, expectations); } BOOST_AUTO_TEST_CASE(create2_as_variable) @@ -7151,7 +7171,7 @@ BOOST_AUTO_TEST_CASE(create2_as_variable) )"; CHECK_ALLOW_MULTI(text, (std::vector<std::pair<Error::Type, std::string>>{ {Error::Type::Warning, "Variable is shadowed in inline assembly by an instruction of the same name"}, - {Error::Type::Warning, "only available after the Metropolis"}, + {Error::Type::Warning, "The \"create2\" instruction is not supported by the VM version"}, {Error::Type::DeclarationError, "Unbalanced stack"} })); } @@ -7446,6 +7466,50 @@ BOOST_AUTO_TEST_CASE(builtin_reject_gas) CHECK_ERROR(text, TypeError, "Member \"gas\" not found or not visible after argument-dependent lookup"); } +BOOST_AUTO_TEST_CASE(gasleft) +{ + char const* text = R"( + contract C { + function f() public view returns (uint256 val) { return msg.gas; } + } + )"; + CHECK_WARNING(text, "\"msg.gas\" has been deprecated in favor of \"gasleft()\""); + + text = R"( + contract C { + function f() public view returns (uint256 val) { return gasleft(); } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); + + text = R"( + pragma experimental "v0.5.0"; + contract C { + function f() public returns (uint256 val) { return msg.gas; } + } + )"; + CHECK_ERROR(text, TypeError, "\"msg.gas\" has been deprecated in favor of \"gasleft()\""); +} + +BOOST_AUTO_TEST_CASE(gasleft_shadowing) +{ + char const* text = R"( + contract C { + function gasleft() public pure returns (bytes32 val) { return "abc"; } + function f() public pure returns (bytes32 val) { return gasleft(); } + } + )"; + CHECK_WARNING(text, "This declaration shadows a builtin symbol."); + + text = R"( + contract C { + uint gasleft; + function f() public { gasleft = 42; } + } + )"; + CHECK_WARNING(text, "This declaration shadows a builtin symbol."); +} + BOOST_AUTO_TEST_CASE(builtin_reject_value) { char const* text = R"( @@ -7707,7 +7771,7 @@ BOOST_AUTO_TEST_CASE(non_external_fallback) function () external { } } )"; - CHECK_WARNING(text, "Experimental features are turned on."); + CHECK_SUCCESS_NO_WARNINGS(text); text = R"( pragma experimental "v0.5.0"; contract C { diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp index e8906bb9..49a725e0 100644 --- a/test/libsolidity/SolidityNatspecJSON.cpp +++ b/test/libsolidity/SolidityNatspecJSON.cpp @@ -47,6 +47,7 @@ public: { m_compilerStack.reset(false); m_compilerStack.addSource("", "pragma solidity >=0.0;\n" + _code); + m_compilerStack.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_REQUIRE_MESSAGE(m_compilerStack.parseAndAnalyze(), "Parsing contract failed"); Json::Value generatedDocumentation; @@ -67,6 +68,7 @@ public: { m_compilerStack.reset(false); m_compilerStack.addSource("", "pragma solidity >=0.0;\n" + _code); + m_compilerStack.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(!m_compilerStack.parseAndAnalyze()); BOOST_REQUIRE(Error::containsErrorOfType(m_compilerStack.errors(), Error::Type::DocstringParsingError)); } diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index b7097d0f..f03b30e1 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -1164,6 +1164,36 @@ BOOST_AUTO_TEST_CASE(constant_is_keyword) CHECK_PARSE_ERROR(text, "Expected identifier"); } +BOOST_AUTO_TEST_CASE(keyword_is_reserved) +{ + auto keywords = { + "abstract", + "after", + "case", + "catch", + "default", + "final", + "in", + "inline", + "let", + "match", + "null", + "of", + "relocatable", + "static", + "switch", + "try", + "type", + "typeof" + }; + + for (const auto& keyword: keywords) + { + auto text = std::string("contract ") + keyword + " {}"; + CHECK_PARSE_ERROR(text.c_str(), "Expected identifier"); + } +} + BOOST_AUTO_TEST_CASE(var_array) { char const* text = R"( diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index eb2773ba..4c8918be 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -724,6 +724,43 @@ BOOST_AUTO_TEST_CASE(library_linking) BOOST_CHECK(contract["evm"]["bytecode"]["linkReferences"]["library2.sol"]["L2"][0].isObject()); } +BOOST_AUTO_TEST_CASE(evm_version) +{ + auto inputForVersion = [](string const& _version) + { + return R"( + { + "language": "Solidity", + "sources": { "fileA": { "content": "contract A { }" } }, + "settings": { + )" + _version + R"( + "outputSelection": { + "fileA": { + "A": [ "metadata" ] + } + } + } + } + )"; + }; + Json::Value result; + result = compile(inputForVersion("\"evmVersion\": \"homestead\",")); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"homestead\"") != string::npos); + result = compile(inputForVersion("\"evmVersion\": \"tangerineWhistle\",")); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"tangerineWhistle\"") != string::npos); + result = compile(inputForVersion("\"evmVersion\": \"spuriousDragon\",")); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"spuriousDragon\"") != string::npos); + result = compile(inputForVersion("\"evmVersion\": \"byzantium\",")); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"byzantium\"") != string::npos); + // test default + result = compile(inputForVersion("")); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"byzantium\"") != string::npos); + // test invalid + result = compile(inputForVersion("\"evmVersion\": \"invalid\",")); + BOOST_CHECK(result["errors"][0]["message"].asString() == "Invalid EVM version requested."); +} + + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/ViewPureChecker.cpp b/test/libsolidity/ViewPureChecker.cpp index 2599ca28..ed4cf792 100644 --- a/test/libsolidity/ViewPureChecker.cpp +++ b/test/libsolidity/ViewPureChecker.cpp @@ -20,6 +20,8 @@ #include <test/libsolidity/AnalysisFramework.h> +#include <test/TestHelper.h> + #include <boost/test/unit_test.hpp> #include <string> @@ -109,6 +111,7 @@ BOOST_AUTO_TEST_CASE(environment_access) "block.difficulty", "block.number", "block.gaslimit", + "gasleft()", "msg.gas", "msg.value", "msg.sender", @@ -423,7 +426,10 @@ BOOST_AUTO_TEST_CASE(assembly_staticcall) } } )"; - CHECK_WARNING(text, "only available after the Metropolis"); + if (!dev::test::Options::get().evmVersion().hasStaticCall()) + CHECK_WARNING(text, "\"staticcall\" instruction is only available for Byzantium-compatible"); + else + CHECK_SUCCESS_NO_WARNINGS(text); } BOOST_AUTO_TEST_CASE(assembly_jump) |