aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/CMakeLists.txt30
-rw-r--r--test/ExecutionFramework.cpp9
-rw-r--r--test/ExecutionFramework.h5
-rw-r--r--test/Metadata.cpp3
-rw-r--r--test/Options.cpp (renamed from test/TestHelper.cpp)48
-rw-r--r--test/Options.h (renamed from test/TestHelper.h)11
-rw-r--r--test/RPCSession.cpp18
-rw-r--r--test/boostTest.cpp9
-rwxr-xr-xtest/cmdlineTests.sh19
-rw-r--r--test/contracts/AuctionRegistrar.cpp9
-rw-r--r--test/contracts/FixedFeeRegistrar.cpp9
-rw-r--r--test/contracts/LLL_ENS.cpp2
-rw-r--r--test/contracts/LLL_ERC20.cpp2
-rw-r--r--test/contracts/Wallet.cpp9
-rw-r--r--test/libdevcore/Checksum.cpp2
-rw-r--r--test/libdevcore/IndentedWriter.cpp2
-rw-r--r--test/libdevcore/JSON.cpp2
-rw-r--r--test/libdevcore/StringUtils.cpp2
-rw-r--r--test/libdevcore/SwarmHash.cpp2
-rw-r--r--test/libdevcore/UTF8.cpp2
-rw-r--r--test/libdevcore/Whiskers.cpp2
-rw-r--r--test/libevmasm/Optimiser.cpp4
-rw-r--r--test/libevmasm/SourceLocation.cpp2
-rw-r--r--test/libjulia/Common.cpp10
-rw-r--r--test/libjulia/Parser.cpp10
-rw-r--r--test/liblll/Compiler.cpp17
-rw-r--r--test/liblll/EndToEndTest.cpp276
-rw-r--r--test/liblll/ExecutionFramework.h2
-rw-r--r--test/libsolidity/ASTJSON.cpp21
-rw-r--r--test/libsolidity/AnalysisFramework.cpp3
-rw-r--r--test/libsolidity/Assembly.cpp17
-rw-r--r--test/libsolidity/GasMeter.cpp11
-rw-r--r--test/libsolidity/Imports.cpp27
-rw-r--r--test/libsolidity/InlineAssembly.cpp14
-rw-r--r--test/libsolidity/JSONCompiler.cpp4
-rw-r--r--test/libsolidity/Metadata.cpp8
-rw-r--r--test/libsolidity/SMTChecker.cpp144
-rw-r--r--test/libsolidity/SemVerMatcher.cpp2
-rw-r--r--test/libsolidity/SolidityABIJSON.cpp4
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp204
-rw-r--r--test/libsolidity/SolidityExecutionFramework.h15
-rw-r--r--test/libsolidity/SolidityExpressionCompiler.cpp58
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp749
-rw-r--r--test/libsolidity/SolidityNatspecJSON.cpp4
-rw-r--r--test/libsolidity/SolidityParser.cpp34
-rw-r--r--test/libsolidity/StandardCompiler.cpp192
-rw-r--r--test/libsolidity/SyntaxTest.cpp209
-rw-r--r--test/libsolidity/SyntaxTest.h77
-rw-r--r--test/libsolidity/ViewPureChecker.cpp20
-rw-r--r--test/libsolidity/syntaxTests/docstring_empty_description.sol6
-rw-r--r--test/libsolidity/syntaxTests/double_stateVariable_declaration.sol6
-rw-r--r--test/libsolidity/syntaxTests/double_variable_declaration.sol8
-rw-r--r--test/libsolidity/syntaxTests/double_variable_declaration_050.sol11
-rw-r--r--test/libsolidity/syntaxTests/smoke_test.sol6
-rw-r--r--test/libsolidity/syntaxTests/virtualLookup/modifiers_in_libraries.sol14
-rw-r--r--test/libsolidity/syntaxTests/visibility/external_library_function.sol14
-rw-r--r--test/tools/CMakeLists.txt2
-rw-r--r--test/tools/fuzzer.cpp (renamed from test/fuzzer.cpp)1
58 files changed, 2135 insertions, 268 deletions
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/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..ee8da322 100644
--- a/test/ExecutionFramework.h
+++ b/test/ExecutionFramework.h
@@ -22,9 +22,11 @@
#pragma once
-#include <test/TestHelper.h>
+#include <test/Options.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/TestHelper.cpp b/test/Options.cpp
index c8747a06..ff4a7c98 100644
--- a/test/TestHelper.cpp
+++ b/test/Options.cpp
@@ -19,8 +19,13 @@
* @date 2014
*/
+#include <test/Options.h>
+
+#include <libsolidity/interface/EVMVersion.h>
+#include <libsolidity/interface/Exceptions.h>
+
#include <boost/test/framework.hpp>
-#include "TestHelper.h"
+
using namespace std;
using namespace dev::test;
@@ -39,8 +44,18 @@ Options::Options()
ipcPath = suite.argv[i + 1];
i++;
}
+ else if (string(suite.argv[i]) == "--testpath" && i + 1 < suite.argc)
+ {
+ testPath = suite.argv[i + 1];
+ i++;
+ }
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")
@@ -51,4 +66,35 @@ Options::Options()
if (!disableIPC && ipcPath.empty())
if (auto path = getenv("ETH_TEST_IPC"))
ipcPath = path;
+
+ if (testPath.empty())
+ if (auto path = getenv("ETH_TEST_PATH"))
+ testPath = path;
+}
+
+void Options::validate() const
+{
+ solAssert(
+ !dev::test::Options::get().testPath.empty(),
+ "No test path specified. The --testpath argument is required."
+ );
+ if (!disableIPC)
+ solAssert(
+ !dev::test::Options::get().ipcPath.empty(),
+ "No ipc path specified. The --ipcpath argument is required, unless --no-ipc is used."
+ );
+}
+
+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/Options.h
index d25c5cd8..9bc69876 100644
--- a/test/TestHelper.h
+++ b/test/Options.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
@@ -32,14 +35,20 @@ namespace test
struct Options: boost::noncopyable
{
std::string ipcPath;
+ boost::filesystem::path testPath;
bool showMessages = false;
bool optimize = false;
bool disableIPC = false;
bool disableSMT = false;
+ void validate() const;
+ solidity::EVMVersion evmVersion() const;
+
static Options const& get();
private:
+ std::string evmVersionString;
+
Options();
};
diff --git a/test/RPCSession.cpp b/test/RPCSession.cpp
index 69c75cee..03b1341c 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/Options.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/boostTest.cpp b/test/boostTest.cpp
index a3cc51c5..f16973b5 100644
--- a/test/boostTest.cpp
+++ b/test/boostTest.cpp
@@ -35,7 +35,8 @@
#pragma GCC diagnostic pop
-#include <test/TestHelper.h>
+#include <test/Options.h>
+#include <test/libsolidity/SyntaxTest.h>
using namespace boost::unit_test;
@@ -54,6 +55,12 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] )
{
master_test_suite_t& master = framework::master_test_suite();
master.p_name.value = "SolidityTests";
+ dev::test::Options::get().validate();
+ solAssert(dev::solidity::test::SyntaxTest::registerTests(
+ master,
+ dev::test::Options::get().testPath / "libsolidity",
+ "syntaxTests"
+ ) > 0, "no syntax tests found");
if (dev::test::Options::get().disableIPC)
{
for (auto suite: {
diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh
index 32456fd0..92f9569a 100755
--- a/test/cmdlineTests.sh
+++ b/test/cmdlineTests.sh
@@ -83,6 +83,21 @@ function compileWithoutWarning()
test -z "$output" -a "$failed" -eq 0
}
+printTask "Testing unknown options..."
+(
+ set +e
+ output=$("$SOLC" --allow=test 2>&1)
+ failed=$?
+ set -e
+
+ if [ "$output" == "unrecognised option '--allow=test'" ] && [ $failed -ne 0 ] ; then
+ echo "Passed"
+ else
+ printError "Incorrect response to unknown options: $STDERR"
+ exit 1
+ fi
+)
+
printTask "Compiling various other contracts and libraries..."
(
cd "$REPO_ROOT"/test/compilationTests/
@@ -155,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/contracts/AuctionRegistrar.cpp b/test/contracts/AuctionRegistrar.cpp
index c9c744af..5e4991e2 100644
--- a/test/contracts/AuctionRegistrar.cpp
+++ b/test/contracts/AuctionRegistrar.cpp
@@ -220,13 +220,8 @@ protected:
void deployRegistrar()
{
if (!s_compiledRegistrar)
- {
- m_compiler.reset(false);
- m_compiler.addSource("", registrarCode);
- m_compiler.setOptimiserSettings(m_optimize, m_optimizeRuns);
- BOOST_REQUIRE_MESSAGE(m_compiler.compile(), "Compiling contract failed");
- s_compiledRegistrar.reset(new bytes(m_compiler.object("GlobalRegistrar").bytecode));
- }
+ s_compiledRegistrar.reset(new bytes(compileContract(registrarCode, "GlobalRegistrar")));
+
sendMessage(*s_compiledRegistrar, true);
BOOST_REQUIRE(!m_output.empty());
}
diff --git a/test/contracts/FixedFeeRegistrar.cpp b/test/contracts/FixedFeeRegistrar.cpp
index 8327999d..a3a27c37 100644
--- a/test/contracts/FixedFeeRegistrar.cpp
+++ b/test/contracts/FixedFeeRegistrar.cpp
@@ -132,13 +132,8 @@ protected:
void deployRegistrar()
{
if (!s_compiledRegistrar)
- {
- m_compiler.reset(false);
- m_compiler.addSource("", registrarCode);
- m_compiler.setOptimiserSettings(m_optimize, m_optimizeRuns);
- BOOST_REQUIRE_MESSAGE(m_compiler.compile(), "Compiling contract failed");
- s_compiledRegistrar.reset(new bytes(m_compiler.object("FixedFeeRegistrar").bytecode));
- }
+ s_compiledRegistrar.reset(new bytes(compileContract(registrarCode, "FixedFeeRegistrar")));
+
sendMessage(*s_compiledRegistrar, true);
BOOST_REQUIRE(!m_output.empty());
}
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/contracts/Wallet.cpp b/test/contracts/Wallet.cpp
index 90334ad6..1031e8f1 100644
--- a/test/contracts/Wallet.cpp
+++ b/test/contracts/Wallet.cpp
@@ -447,13 +447,8 @@ protected:
)
{
if (!s_compiledWallet)
- {
- m_compiler.reset(false);
- m_compiler.addSource("", walletCode);
- m_compiler.setOptimiserSettings(m_optimize, m_optimizeRuns);
- BOOST_REQUIRE_MESSAGE(m_compiler.compile(), "Compiling contract failed");
- s_compiledWallet.reset(new bytes(m_compiler.object("Wallet").bytecode));
- }
+ s_compiledWallet.reset(new bytes(compileContract(walletCode, "Wallet")));
+
bytes args = encodeArgs(u256(0x60), _required, _dailyLimit, u256(_owners.size()), _owners);
sendMessage(*s_compiledWallet + args, true, _value);
BOOST_REQUIRE(!m_output.empty());
diff --git a/test/libdevcore/Checksum.cpp b/test/libdevcore/Checksum.cpp
index 4eedbd99..95066b69 100644
--- a/test/libdevcore/Checksum.cpp
+++ b/test/libdevcore/Checksum.cpp
@@ -22,7 +22,7 @@
#include <libdevcore/Exceptions.h>
-#include "../TestHelper.h"
+#include <test/Options.h>
using namespace std;
diff --git a/test/libdevcore/IndentedWriter.cpp b/test/libdevcore/IndentedWriter.cpp
index a694aa1b..916c99d0 100644
--- a/test/libdevcore/IndentedWriter.cpp
+++ b/test/libdevcore/IndentedWriter.cpp
@@ -20,7 +20,7 @@
#include <libdevcore/IndentedWriter.h>
-#include "../TestHelper.h"
+#include <test/Options.h>
using namespace std;
diff --git a/test/libdevcore/JSON.cpp b/test/libdevcore/JSON.cpp
index 39d71b42..39d958f5 100644
--- a/test/libdevcore/JSON.cpp
+++ b/test/libdevcore/JSON.cpp
@@ -21,7 +21,7 @@
#include <libdevcore/JSON.h>
-#include "../TestHelper.h"
+#include <test/Options.h>
using namespace std;
diff --git a/test/libdevcore/StringUtils.cpp b/test/libdevcore/StringUtils.cpp
index 597457cc..9ee93d02 100644
--- a/test/libdevcore/StringUtils.cpp
+++ b/test/libdevcore/StringUtils.cpp
@@ -20,7 +20,7 @@
#include <libdevcore/StringUtils.h>
-#include "../TestHelper.h"
+#include <test/Options.h>
using namespace std;
diff --git a/test/libdevcore/SwarmHash.cpp b/test/libdevcore/SwarmHash.cpp
index 1ed1da18..913586f8 100644
--- a/test/libdevcore/SwarmHash.cpp
+++ b/test/libdevcore/SwarmHash.cpp
@@ -20,7 +20,7 @@
#include <libdevcore/SwarmHash.h>
-#include "../TestHelper.h"
+#include <test/Options.h>
using namespace std;
diff --git a/test/libdevcore/UTF8.cpp b/test/libdevcore/UTF8.cpp
index 719ada72..6de4570f 100644
--- a/test/libdevcore/UTF8.cpp
+++ b/test/libdevcore/UTF8.cpp
@@ -21,7 +21,7 @@
#include <libdevcore/CommonData.h>
#include <libdevcore/UTF8.h>
-#include "../TestHelper.h"
+#include <test/Options.h>
using namespace std;
diff --git a/test/libdevcore/Whiskers.cpp b/test/libdevcore/Whiskers.cpp
index 84149173..b12acdd7 100644
--- a/test/libdevcore/Whiskers.cpp
+++ b/test/libdevcore/Whiskers.cpp
@@ -20,7 +20,7 @@
#include <libdevcore/Whiskers.h>
-#include "../TestHelper.h"
+#include <test/Options.h>
using namespace std;
diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp
index 0ab95b08..f630b304 100644
--- a/test/libevmasm/Optimiser.cpp
+++ b/test/libevmasm/Optimiser.cpp
@@ -20,6 +20,8 @@
* Tests for the Solidity optimizer.
*/
+#include <test/Options.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/libevmasm/SourceLocation.cpp b/test/libevmasm/SourceLocation.cpp
index 6889b3e6..764da3cd 100644
--- a/test/libevmasm/SourceLocation.cpp
+++ b/test/libevmasm/SourceLocation.cpp
@@ -22,7 +22,7 @@
#include <libevmasm/SourceLocation.h>
-#include "../TestHelper.h"
+#include <test/Options.h>
namespace dev
{
diff --git a/test/libjulia/Common.cpp b/test/libjulia/Common.cpp
index 7053a68d..24519b01 100644
--- a/test/libjulia/Common.cpp
+++ b/test/libjulia/Common.cpp
@@ -21,6 +21,8 @@
#include <test/libjulia/Common.h>
+#include <test/Options.h>
+
#include <libjulia/optimiser/Disambiguator.h>
#include <libsolidity/parsing/Scanner.h>
@@ -61,7 +63,13 @@ 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(),
+ boost::none,
+ flavour
+ );
if (analyzer.analyze(*parserResult))
{
BOOST_REQUIRE(errorReporter.errors().empty());
diff --git a/test/libjulia/Parser.cpp b/test/libjulia/Parser.cpp
index ff9474c1..9d66658e 100644
--- a/test/libjulia/Parser.cpp
+++ b/test/libjulia/Parser.cpp
@@ -19,7 +19,7 @@
* Unit tests for parsing Julia.
*/
-#include "../TestHelper.h"
+#include <test/Options.h>
#include <test/libsolidity/ErrorCheck.h>
@@ -56,7 +56,13 @@ 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(),
+ boost::none,
+ assembly::AsmFlavour::IULIA
+ )).analyze(*parserResult);
}
}
catch (FatalError const&)
diff --git a/test/liblll/Compiler.cpp b/test/liblll/Compiler.cpp
index ace97e15..ebdea185 100644
--- a/test/liblll/Compiler.cpp
+++ b/test/liblll/Compiler.cpp
@@ -20,11 +20,16 @@
* Unit tests for the LLL compiler.
*/
+#include <test/Options.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..fd8099f2 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/Options.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..b44dd331 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/Options.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..4538757d 100644
--- a/test/libsolidity/AnalysisFramework.cpp
+++ b/test/libsolidity/AnalysisFramework.cpp
@@ -20,6 +20,8 @@
#include <test/libsolidity/AnalysisFramework.h>
+#include <test/Options.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..5519ae0d 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/Options.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..1b5dd4a5 100644
--- a/test/libsolidity/Imports.cpp
+++ b/test/libsolidity/Imports.cpp
@@ -21,6 +21,7 @@
*/
#include <test/libsolidity/ErrorCheck.h>
+#include <test/Options.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..34ca33e3 100644
--- a/test/libsolidity/InlineAssembly.cpp
+++ b/test/libsolidity/InlineAssembly.cpp
@@ -20,7 +20,7 @@
* Unit tests for inline assembly.
*/
-#include "../TestHelper.h"
+#include <test/Options.h>
#include <libsolidity/interface/AssemblyStack.h>
#include <libsolidity/parsing/Scanner.h>
@@ -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/JSONCompiler.cpp b/test/libsolidity/JSONCompiler.cpp
index 285c5604..aed0a370 100644
--- a/test/libsolidity/JSONCompiler.cpp
+++ b/test/libsolidity/JSONCompiler.cpp
@@ -25,8 +25,8 @@
#include <libsolidity/interface/Version.h>
#include <libsolc/libsolc.h>
-#include "../Metadata.h"
-#include "../TestHelper.h"
+#include <test/Metadata.h>
+#include <test/Options.h>
using namespace std;
diff --git a/test/libsolidity/Metadata.cpp b/test/libsolidity/Metadata.cpp
index 47cf1d3d..808bd1e1 100644
--- a/test/libsolidity/Metadata.cpp
+++ b/test/libsolidity/Metadata.cpp
@@ -19,8 +19,8 @@
* Unit tests for the metadata output.
*/
-#include "../Metadata.h"
-#include "../TestHelper.h"
+#include <test/Metadata.h>
+#include <test/Options.h>
#include <libsolidity/interface/CompilerStack.h>
#include <libdevcore/SwarmHash.h>
#include <libdevcore/JSON.h>
@@ -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/SMTChecker.cpp b/test/libsolidity/SMTChecker.cpp
index 5088ab94..beb933a4 100644
--- a/test/libsolidity/SMTChecker.cpp
+++ b/test/libsolidity/SMTChecker.cpp
@@ -329,6 +329,144 @@ BOOST_AUTO_TEST_CASE(ways_to_merge_variables)
CHECK_WARNING(text, "Assertion violation happens here");
}
+BOOST_AUTO_TEST_CASE(bool_simple)
+{
+ string text = R"(
+ contract C {
+ function f(bool x) public pure {
+ assert(x);
+ }
+ }
+ )";
+ CHECK_WARNING(text, "Assertion violation happens here");
+ text = R"(
+ contract C {
+ function f(bool x, bool y) public pure {
+ assert(x == y);
+ }
+ }
+ )";
+ CHECK_WARNING(text, "Assertion violation happens here");
+ text = R"(
+ contract C {
+ function f(bool x, bool y) public pure {
+ bool z = x || y;
+ assert(!(x && y) || z);
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+ text = R"(
+ contract C {
+ function f(bool x) public pure {
+ if(x) {
+ assert(x);
+ } else {
+ assert(!x);
+ }
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+ text = R"(
+ contract C {
+ function f(bool x) public pure {
+ bool y = x;
+ assert(x == y);
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+ text = R"(
+ contract C {
+ function f(bool x) public pure {
+ require(x);
+ bool y;
+ y = false;
+ assert(x || y);
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+ text = R"(
+ contract C {
+ function f(bool x) public pure {
+ bool y;
+ assert(x <= y);
+ }
+ }
+ )";
+ CHECK_WARNING(text, "Assertion violation happens here");
+ text = R"(
+ contract C {
+ function f(bool x) public pure {
+ bool y;
+ assert(x >= y);
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+ text = R"(
+ contract C {
+ function f(bool x) public pure {
+ require(x);
+ bool y;
+ assert(x > y);
+ assert(y < x);
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+}
+
+BOOST_AUTO_TEST_CASE(bool_int_mixed)
+{
+ string text = R"(
+ contract C {
+ function f(bool x) public pure {
+ uint a;
+ if(x)
+ a = 1;
+ assert(!x || a > 0);
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+ text = R"(
+ contract C {
+ function f(bool x, uint a) public pure {
+ require(!x || a > 0);
+ uint b = a;
+ assert(!x || b > 0);
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+ text = R"(
+ contract C {
+ function f(bool x, bool y) public pure {
+ uint a;
+ if (x) {
+ if (y) {
+ a = 0;
+ } else {
+ a = 1;
+ }
+ } else {
+ if (y) {
+ a = 1;
+ } else {
+ a = 0;
+ }
+ }
+ bool xor_x_y = (x && !y) || (!x && y);
+ assert(!xor_x_y || a > 0);
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+}
+
BOOST_AUTO_TEST_CASE(while_loop_simple)
{
// Check that variables are cleared
@@ -466,7 +604,8 @@ BOOST_AUTO_TEST_CASE(for_loop)
text = R"(
contract C {
function f(uint x) public pure {
- for (uint y = 2; x < 10; ) {
+ uint y;
+ for (y = 2; x < 10; ) {
y = 3;
}
assert(y == 3);
@@ -477,7 +616,8 @@ BOOST_AUTO_TEST_CASE(for_loop)
text = R"(
contract C {
function f(uint x) public pure {
- for (uint y = 2; x < 10; ) {
+ uint y;
+ for (y = 2; x < 10; ) {
y = 3;
}
assert(y == 2);
diff --git a/test/libsolidity/SemVerMatcher.cpp b/test/libsolidity/SemVerMatcher.cpp
index 08ef5277..07f8fba6 100644
--- a/test/libsolidity/SemVerMatcher.cpp
+++ b/test/libsolidity/SemVerMatcher.cpp
@@ -25,7 +25,7 @@
#include <tuple>
#include <libsolidity/parsing/Scanner.h>
#include <libsolidity/analysis/SemVerHandler.h>
-#include "../TestHelper.h"
+#include <test/Options.h>
using namespace std;
diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp
index e242508a..107abc26 100644
--- a/test/libsolidity/SolidityABIJSON.cpp
+++ b/test/libsolidity/SolidityABIJSON.cpp
@@ -20,7 +20,7 @@
* Unit tests for the solidity compiler JSON Interface output.
*/
-#include "../TestHelper.h"
+#include <test/Options.h>
#include <libsolidity/interface/CompilerStack.h>
#include <libdevcore/Exceptions.h>
@@ -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 3882e4ea..44dc40f7 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -21,13 +21,20 @@
* Unit tests for the solidity expression compiler, testing the behaviour of the code.
*/
+#include <test/libsolidity/SolidityExecutionFramework.h>
+
+#include <test/Options.h>
+
+#include <libsolidity/interface/Exceptions.h>
+#include <libsolidity/interface/EVMVersion.h>
+
+#include <libevmasm/Assembly.h>
+
+#include <boost/test/unit_test.hpp>
+
#include <functional>
#include <string>
#include <tuple>
-#include <boost/test/unit_test.hpp>
-#include <libevmasm/Assembly.h>
-#include <libsolidity/interface/Exceptions.h>
-#include <test/libsolidity/SolidityExecutionFramework.h>
using namespace std;
using namespace std::placeholders;
@@ -284,6 +291,54 @@ BOOST_AUTO_TEST_CASE(conditional_expression_functions)
ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(u256(2)));
}
+BOOST_AUTO_TEST_CASE(C99_scoping_activation)
+{
+ char const* sourceCode = R"(
+ pragma experimental "v0.5.0";
+ contract test {
+ function f() pure public returns (uint) {
+ uint x = 7;
+ {
+ x = 3; // This should still assign to the outer variable
+ uint x;
+ x = 4; // This should assign to the new one
+ }
+ return x;
+ }
+ function g() pure public returns (uint x) {
+ x = 7;
+ {
+ x = 3;
+ uint x;
+ return x; // This returns the new variable, i.e. 0
+ }
+ }
+ function h() pure public returns (uint x, uint a, uint b) {
+ x = 7;
+ {
+ x = 3;
+ a = x; // This should read from the outer
+ uint x = 4;
+ b = x;
+ }
+ }
+ function i() pure public returns (uint x, uint a) {
+ x = 7;
+ {
+ x = 3;
+ uint x = x; // This should read from the outer and assign to the inner
+ a = x;
+ }
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ ABI_CHECK(callContractFunction("f()"), encodeArgs(3));
+ ABI_CHECK(callContractFunction("g()"), encodeArgs(0));
+ ABI_CHECK(callContractFunction("h()"), encodeArgs(3, 3, 4));
+ ABI_CHECK(callContractFunction("i()"), encodeArgs(3, 3));
+}
+
BOOST_AUTO_TEST_CASE(recursive_calls)
{
char const* sourceCode = R"(
@@ -1733,6 +1788,23 @@ BOOST_AUTO_TEST_CASE(transfer_ether)
ABI_CHECK(callContractFunction("b(address,uint256)", oogRecipient, 10), encodeArgs());
}
+BOOST_AUTO_TEST_CASE(uncalled_blockhash)
+{
+ char const* code = R"(
+ contract C {
+ function f() public view returns (bytes32)
+ {
+ var x = block.blockhash;
+ return x(block.number - 1);
+ }
+ }
+ )";
+ compileAndRun(code, 0, "C");
+ bytes result = callContractFunction("f()");
+ BOOST_REQUIRE_EQUAL(result.size(), 32);
+ BOOST_CHECK(result[0] != 0 || result[1] != 0 || result[2] != 0);
+}
+
BOOST_AUTO_TEST_CASE(log0)
{
char const* sourceCode = R"(
@@ -2824,6 +2896,58 @@ BOOST_AUTO_TEST_CASE(function_modifier_multiple_times_local_vars)
ABI_CHECK(callContractFunction("a()"), encodeArgs(0));
}
+BOOST_AUTO_TEST_CASE(function_modifier_library)
+{
+ char const* sourceCode = R"(
+ library L {
+ struct S { uint v; }
+ modifier mod(S storage s) { s.v++; _; }
+ function libFun(S storage s) mod(s) internal { s.v += 0x100; }
+ }
+
+ contract Test {
+ using L for *;
+ L.S s;
+
+ function f() public returns (uint) {
+ s.libFun();
+ L.libFun(s);
+ return s.v;
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ ABI_CHECK(callContractFunction("f()"), encodeArgs(0x202));
+}
+
+BOOST_AUTO_TEST_CASE(function_modifier_library_inheritance)
+{
+ // Tests that virtual lookup for modifiers in libraries does not consider
+ // the current inheritance hierarchy.
+
+ char const* sourceCode = R"(
+ library L {
+ struct S { uint v; }
+ modifier mod(S storage s) { s.v++; _; }
+ function libFun(S storage s) mod(s) internal { s.v += 0x100; }
+ }
+
+ contract Test {
+ using L for *;
+ L.S s;
+ modifier mod(L.S storage) { revert(); _; }
+
+ function f() public returns (uint) {
+ s.libFun();
+ L.libFun(s);
+ return s.v;
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ ABI_CHECK(callContractFunction("f()"), encodeArgs(0x202));
+}
+
BOOST_AUTO_TEST_CASE(crazy_elementary_typenames_on_stack)
{
char const* sourceCode = R"(
@@ -5304,6 +5428,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"(
@@ -6888,6 +7024,21 @@ BOOST_AUTO_TEST_CASE(library_call)
ABI_CHECK(callContractFunction("f(uint256)", u256(33)), encodeArgs(u256(33) * 9));
}
+BOOST_AUTO_TEST_CASE(library_function_external)
+{
+ char const* sourceCode = R"(
+ library Lib { function m(bytes b) external pure returns (byte) { return b[2]; } }
+ contract Test {
+ function f(bytes b) public pure returns (byte) {
+ return Lib.m(b);
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "Lib");
+ compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}});
+ ABI_CHECK(callContractFunction("f(bytes)", u256(0x20), u256(5), "abcde"), encodeArgs("c"));
+}
+
BOOST_AUTO_TEST_CASE(library_stray_values)
{
char const* sourceCode = R"(
@@ -10718,6 +10869,51 @@ BOOST_AUTO_TEST_CASE(snark)
BOOST_CHECK(callContractFunction("verifyTx()") == encodeArgs(true));
}
+BOOST_AUTO_TEST_CASE(staticcall_for_view_and_pure)
+{
+ char const* sourceCode = R"(
+ pragma experimental "v0.5.0";
+ contract C {
+ uint x;
+ function f() public returns (uint) {
+ x = 3;
+ return 1;
+ }
+ }
+ interface CView {
+ function f() view external returns (uint);
+ }
+ interface CPure {
+ function f() pure external returns (uint);
+ }
+ contract D {
+ function f() public returns (uint) {
+ return (new C()).f();
+ }
+ function fview() public returns (uint) {
+ return (CView(new C())).f();
+ }
+ function fpure() public returns (uint) {
+ return (CPure(new C())).f();
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "D");
+ // This should work (called via CALL)
+ ABI_CHECK(callContractFunction("f()"), encodeArgs(1));
+ if (dev::test::Options::get().evmVersion().hasStaticCall())
+ {
+ // These should throw (called via STATICCALL)
+ ABI_CHECK(callContractFunction("fview()"), encodeArgs());
+ ABI_CHECK(callContractFunction("fpure()"), encodeArgs());
+ }
+ else
+ {
+ ABI_CHECK(callContractFunction("fview()"), encodeArgs(1));
+ ABI_CHECK(callContractFunction("fpure()"), encodeArgs(1));
+ }
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h
index b853d558..12687dd1 100644
--- a/test/libsolidity/SolidityExecutionFramework.h
+++ b/test/libsolidity/SolidityExecutionFramework.h
@@ -52,11 +52,23 @@ public:
std::map<std::string, dev::test::Address> const& _libraryAddresses = std::map<std::string, dev::test::Address>()
) override
{
+ bytes bytecode = compileContract(_sourceCode, _contractName, _libraryAddresses);
+ sendMessage(bytecode + _arguments, true, _value);
+ return m_output;
+ }
+
+ bytes compileContract(
+ std::string const& _sourceCode,
+ std::string const& _contractName = "",
+ std::map<std::string, dev::test::Address> const& _libraryAddresses = std::map<std::string, dev::test::Address>()
+ )
+ {
// Silence compiler version warning
std::string sourceCode = "pragma solidity >=0.0;\n" + _sourceCode;
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())
{
@@ -72,8 +84,7 @@ public:
}
eth::LinkerObject obj = m_compiler.object(_contractName.empty() ? m_compiler.lastContractName() : _contractName);
BOOST_REQUIRE(obj.linkReferences.empty());
- sendMessage(obj.bytecode + _arguments, true, _value);
- return m_output;
+ return obj.bytecode;
}
protected:
diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp
index 67747386..c8adfc6e 100644
--- a/test/libsolidity/SolidityExpressionCompiler.cpp
+++ b/test/libsolidity/SolidityExpressionCompiler.cpp
@@ -30,7 +30,7 @@
#include <libsolidity/ast/AST.h>
#include <libsolidity/analysis/TypeChecker.h>
#include <libsolidity/interface/ErrorReporter.h>
-#include "../TestHelper.h"
+#include <test/Options.h>
using namespace std;
@@ -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
@@ -322,10 +322,10 @@ BOOST_AUTO_TEST_CASE(arithmetics)
{
char const* sourceCode = R"(
contract test {
- function f(uint y) { var x = ((((((((y ^ 8) & 7) | 6) - 5) + 4) % 3) / 2) * 1); }
+ function f(uint y) { ((((((((y ^ 8) & 7) | 6) - 5) + 4) % 3) / 2) * 1); }
}
)";
- bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}, {"test", "f", "x"}});
+ bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}});
bytes expectation({byte(Instruction::PUSH1), 0x1,
byte(Instruction::PUSH1), 0x2,
byte(Instruction::PUSH1), 0x3,
@@ -334,7 +334,7 @@ BOOST_AUTO_TEST_CASE(arithmetics)
byte(Instruction::PUSH1), 0x6,
byte(Instruction::PUSH1), 0x7,
byte(Instruction::PUSH1), 0x8,
- byte(Instruction::DUP10),
+ byte(Instruction::DUP9),
byte(Instruction::XOR),
byte(Instruction::AND),
byte(Instruction::OR),
@@ -364,13 +364,13 @@ BOOST_AUTO_TEST_CASE(unary_operators)
{
char const* sourceCode = R"(
contract test {
- function f(int y) { var x = !(~+- y == 2); }
+ function f(int y) { !(~+- y == 2); }
}
)";
- bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}, {"test", "f", "x"}});
+ bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}});
bytes expectation({byte(Instruction::PUSH1), 0x2,
- byte(Instruction::DUP3),
+ byte(Instruction::DUP2),
byte(Instruction::PUSH1), 0x0,
byte(Instruction::SUB),
byte(Instruction::NOT),
@@ -383,7 +383,7 @@ BOOST_AUTO_TEST_CASE(unary_inc_dec)
{
char const* sourceCode = R"(
contract test {
- function f(uint a) { var x = --a ^ (a-- ^ (++a ^ a++)); }
+ function f(uint a) returns (uint x) { x = --a ^ (a-- ^ (++a ^ a++)); }
}
)";
bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "a"}, {"test", "f", "x"}});
@@ -426,7 +426,10 @@ BOOST_AUTO_TEST_CASE(unary_inc_dec)
byte(Instruction::POP), // second ++
// Stack here: a x a^(a+2)^(a+2)
byte(Instruction::DUP3), // will change
- byte(Instruction::XOR)});
+ byte(Instruction::XOR),
+ byte(Instruction::SWAP1),
+ byte(Instruction::POP),
+ byte(Instruction::DUP1)});
// Stack here: a x a^(a+2)^(a+2)^a
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
@@ -512,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 be147e48..c757037c 100644
--- a/test/libsolidity/SolidityNameAndTypeResolution.cpp
+++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp
@@ -22,6 +22,8 @@
#include <test/libsolidity/AnalysisFramework.h>
+#include <test/Options.h>
+
#include <libsolidity/ast/AST.h>
#include <libdevcore/SHA3.h>
@@ -41,50 +43,216 @@ namespace test
BOOST_FIXTURE_TEST_SUITE(SolidityNameAndTypeResolution, AnalysisFramework)
-BOOST_AUTO_TEST_CASE(smoke_test)
+
+BOOST_AUTO_TEST_CASE(double_function_declaration)
{
char const* text = R"(
contract test {
- uint256 stateVariable1;
- function fun(uint256 arg1) public { uint256 y; y = arg1; }
+ function fun() public { }
+ function fun() public { }
}
)";
- CHECK_SUCCESS(text);
+ CHECK_ERROR(text, DeclarationError, "Function with same name and arguments defined twice.");
}
-BOOST_AUTO_TEST_CASE(double_stateVariable_declaration)
+BOOST_AUTO_TEST_CASE(double_variable_declaration_disjoint_scope)
{
- char const* text = R"(
+ string text = R"(
contract test {
- uint256 variable;
- uint128 variable;
+ function f() pure public {
+ { uint x; }
+ { uint x; }
+ }
}
)";
- CHECK_ERROR(text, DeclarationError, "Identifier already declared.");
+ CHECK_ERROR(text, DeclarationError, "Identifier already declared");
}
-BOOST_AUTO_TEST_CASE(double_function_declaration)
+BOOST_AUTO_TEST_CASE(double_variable_declaration_disjoint_scope_050)
+{
+ string text = R"(
+ pragma experimental "v0.5.0";
+ contract test {
+ function f() pure public {
+ { uint x; }
+ { uint x; }
+ }
+ }
+ )";
+ CHECK_WARNING_ALLOW_MULTI(text, (vector<string>{
+ "Unused local variable",
+ "Unused local variable"
+ }));
+}
+
+BOOST_AUTO_TEST_CASE(double_variable_declaration_disjoint_scope_activation)
+{
+ string text = R"(
+ contract test {
+ function f() pure public {
+ { uint x; }
+ uint x;
+ }
+ }
+ )";
+ CHECK_ERROR(text, DeclarationError, "Identifier already declared");
+}
+
+BOOST_AUTO_TEST_CASE(double_variable_declaration_disjoint_scope_activation_050)
+{
+ string text = R"(
+ pragma experimental "v0.5.0";
+ contract test {
+ function f() pure public {
+ { uint x; }
+ uint x;
+ }
+ }
+ )";
+ CHECK_WARNING_ALLOW_MULTI(text, (vector<string>{
+ "Unused local variable",
+ "Unused local variable"
+ }));
+}
+BOOST_AUTO_TEST_CASE(scoping_old)
{
char const* text = R"(
contract test {
- function fun() public { }
- function fun() public { }
+ function f() pure public {
+ x = 4;
+ uint256 x = 2;
+ }
}
)";
- CHECK_ERROR(text, DeclarationError, "Function with same name and arguments defined twice.");
+ CHECK_SUCCESS_NO_WARNINGS(text);
}
-BOOST_AUTO_TEST_CASE(double_variable_declaration)
+BOOST_AUTO_TEST_CASE(scoping)
{
char const* text = R"(
+ pragma experimental "v0.5.0";
contract test {
function f() public {
- uint256 x;
- if (true) { uint256 x; }
+ {
+ uint256 x;
+ }
+ x = 2;
}
}
)";
- CHECK_ERROR(text, DeclarationError, "Identifier already declared.");
+ CHECK_ERROR(text, DeclarationError, "Undeclared identifier");
+}
+
+BOOST_AUTO_TEST_CASE(scoping_activation_old)
+{
+ char const* text = R"(
+ contract test {
+ function f() pure public {
+ x = 3;
+ uint x;
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+}
+
+BOOST_AUTO_TEST_CASE(scoping_activation)
+{
+ char const* text = R"(
+ pragma experimental "v0.5.0";
+ contract test {
+ function f() pure public {
+ x = 3;
+ uint x;
+ }
+ }
+ )";
+ CHECK_ERROR(text, DeclarationError, "Undeclared identifier");
+}
+
+BOOST_AUTO_TEST_CASE(scoping_self_use)
+{
+ char const* text = R"(
+ contract test {
+ function f() pure public {
+ uint a = a;
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+}
+
+BOOST_AUTO_TEST_CASE(scoping_self_use_050)
+{
+ char const* text = R"(
+ pragma experimental "v0.5.0";
+ contract test {
+ function f() pure public {
+ uint a = a;
+ }
+ }
+ )";
+ CHECK_ERROR(text, DeclarationError, "Undeclared identifier");
+}
+
+BOOST_AUTO_TEST_CASE(scoping_for)
+{
+ char const* text = R"(
+ pragma experimental "v0.5.0";
+ contract test {
+ function f() pure public {
+ for (uint x = 0; x < 10; x ++){
+ x = 2;
+ }
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+}
+
+BOOST_AUTO_TEST_CASE(scoping_for2)
+{
+ char const* text = R"(
+ pragma experimental "v0.5.0";
+ contract test {
+ function f() pure public {
+ for (uint x = 0; x < 10; x ++)
+ x = 2;
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+}
+
+BOOST_AUTO_TEST_CASE(scoping_for3)
+{
+ char const* text = R"(
+ pragma experimental "v0.5.0";
+ contract test {
+ function f() pure public {
+ for (uint x = 0; x < 10; x ++){
+ x = 2;
+ }
+ x = 4;
+ }
+ }
+ )";
+ CHECK_ERROR(text, DeclarationError, "Undeclared identifier");
+}
+
+BOOST_AUTO_TEST_CASE(scoping_for_decl_in_body)
+{
+ char const* text = R"(
+ pragma experimental "v0.5.0";
+ contract test {
+ function f() pure public {
+ for (;; y++){
+ uint y = 3;
+ }
+ }
+ }
+ )";
+ CHECK_ERROR(text, DeclarationError, "Undeclared identifier");
}
BOOST_AUTO_TEST_CASE(name_shadowing)
@@ -758,6 +926,62 @@ BOOST_AUTO_TEST_CASE(functions_with_stucts_of_non_external_types_in_interface_ne
CHECK_ERROR(text, TypeError, "Internal or recursive type is not allowed for public or external functions.");
}
+BOOST_AUTO_TEST_CASE(returning_multi_dimensional_arrays_new_abi)
+{
+ char const* text = R"(
+ pragma experimental ABIEncoderV2;
+
+ contract C {
+ function f() public pure returns (string[][]) {}
+ }
+ )";
+ CHECK_WARNING(text, "Experimental features");
+}
+
+BOOST_AUTO_TEST_CASE(returning_multi_dimensional_arrays)
+{
+ char const* text = R"(
+ contract C {
+ function f() public pure returns (string[][]) {}
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "only supported in the new experimental ABI encoder");
+}
+
+BOOST_AUTO_TEST_CASE(returning_multi_dimensional_static_arrays)
+{
+ char const* text = R"(
+ contract C {
+ function f() public pure returns (uint[][2]) {}
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "only supported in the new experimental ABI encoder");
+}
+
+BOOST_AUTO_TEST_CASE(returning_arrays_in_structs_new_abi)
+{
+ char const* text = R"(
+ pragma experimental ABIEncoderV2;
+
+ contract C {
+ struct S { string[] s; }
+ function f() public pure returns (S) {}
+ }
+ )";
+ CHECK_WARNING(text, "Experimental features");
+}
+
+BOOST_AUTO_TEST_CASE(returning_arrays_in_structs_arrays)
+{
+ char const* text = R"(
+ contract C {
+ struct S { string[] s; }
+ function f() public pure returns (S x) {}
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "only supported in the new experimental ABI encoder");
+}
+
BOOST_AUTO_TEST_CASE(function_external_call_allowed_conversion)
{
char const* text = R"(
@@ -1004,7 +1228,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_invocation)
{
char const* text = R"(
contract B {
- function f() mod1(2, true) mod2("0123456") public { }
+ function f() mod1(2, true) mod2("0123456") pure public { }
modifier mod1(uint a, bool b) { if (b) _; }
modifier mod2(bytes7 a) { while (a == "1234567") _; }
}
@@ -1039,11 +1263,23 @@ BOOST_AUTO_TEST_CASE(function_modifier_invocation_local_variables)
{
char const* text = R"(
contract B {
- function f() mod(x) public { uint x = 7; }
+ function f() mod(x) pure public { uint x = 7; }
modifier mod(uint a) { if (a > 0) _; }
}
)";
- CHECK_SUCCESS(text);
+ CHECK_SUCCESS_NO_WARNINGS(text);
+}
+
+BOOST_AUTO_TEST_CASE(function_modifier_invocation_local_variables050)
+{
+ char const* text = R"(
+ pragma experimental "v0.5.0";
+ contract B {
+ function f() mod(x) pure public { uint x = 7; }
+ modifier mod(uint a) { if (a > 0) _; }
+ }
+ )";
+ CHECK_ERROR(text, DeclarationError, "Undeclared identifier.");
}
BOOST_AUTO_TEST_CASE(function_modifier_double_invocation)
@@ -2484,6 +2720,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"(
@@ -5639,10 +5894,11 @@ BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_negative_stack)
BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_two_stack_load)
{
char const* text = R"(
+ pragma experimental "v0.5.0";
contract c {
uint8 x;
function f() public {
- assembly { x pop }
+ assembly { pop(x) }
}
}
)";
@@ -5652,6 +5908,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_two_stack_load)
BOOST_AUTO_TEST_CASE(inline_assembly_in_modifier)
{
char const* text = R"(
+ pragma experimental "v0.5.0";
contract test {
modifier m {
uint a = 1;
@@ -5660,7 +5917,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_in_modifier)
}
_;
}
- function f() m {
+ function f() public m {
}
}
)";
@@ -5670,6 +5927,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_in_modifier)
BOOST_AUTO_TEST_CASE(inline_assembly_storage)
{
char const* text = R"(
+ pragma experimental "v0.5.0";
contract test {
uint x = 1;
function f() public {
@@ -5685,6 +5943,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage)
BOOST_AUTO_TEST_CASE(inline_assembly_storage_in_modifiers)
{
char const* text = R"(
+ pragma experimental "v0.5.0";
contract test {
uint x = 1;
modifier m {
@@ -5693,7 +5952,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage_in_modifiers)
}
_;
}
- function f() m {
+ function f() public m {
}
}
)";
@@ -5703,6 +5962,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage_in_modifiers)
BOOST_AUTO_TEST_CASE(inline_assembly_constant_assign)
{
char const* text = R"(
+ pragma experimental "v0.5.0";
contract test {
uint constant x = 1;
function f() public {
@@ -5718,6 +5978,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_constant_assign)
BOOST_AUTO_TEST_CASE(inline_assembly_constant_access)
{
char const* text = R"(
+ pragma experimental "v0.5.0";
contract test {
uint constant x = 1;
function f() public {
@@ -5733,6 +5994,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_constant_access)
BOOST_AUTO_TEST_CASE(inline_assembly_local_variable_access_out_of_functions)
{
char const* text = R"(
+ pragma experimental "v0.5.0";
contract test {
function f() public {
uint a;
@@ -5748,6 +6010,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_local_variable_access_out_of_functions)
BOOST_AUTO_TEST_CASE(inline_assembly_local_variable_access_out_of_functions_storage_ptr)
{
char const* text = R"(
+ pragma experimental "v0.5.0";
contract test {
uint[] r;
function f() public {
@@ -5764,6 +6027,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_local_variable_access_out_of_functions_stor
BOOST_AUTO_TEST_CASE(inline_assembly_storage_variable_access_out_of_functions)
{
char const* text = R"(
+ pragma experimental "v0.5.0";
contract test {
uint a;
function f() pure public {
@@ -5794,6 +6058,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_constant_variable_via_offset)
BOOST_AUTO_TEST_CASE(inline_assembly_calldata_variables)
{
char const* text = R"(
+ pragma experimental "v0.5.0";
contract C {
function f(bytes bytesAsCalldata) external {
assembly {
@@ -5805,6 +6070,182 @@ BOOST_AUTO_TEST_CASE(inline_assembly_calldata_variables)
CHECK_ERROR(text, TypeError, "Call data elements cannot be accessed directly.");
}
+BOOST_AUTO_TEST_CASE(inline_assembly_050_literals_on_stack)
+{
+ char const* text = R"(
+ pragma experimental "v0.5.0";
+ contract C {
+ function f() pure public {
+ assembly {
+ 1
+ }
+ }
+ }
+ )";
+ CHECK_ALLOW_MULTI(text, (std::vector<std::pair<Error::Type, std::string>>{
+ {Error::Type::SyntaxError, "are not supposed to return"},
+ {Error::Type::DeclarationError, "Unbalanced stack"},
+ }));
+}
+
+BOOST_AUTO_TEST_CASE(inline_assembly_literals_on_stack)
+{
+ char const* text = R"(
+ contract C {
+ function f() pure public {
+ assembly {
+ 1
+ }
+ }
+ }
+ )";
+ CHECK_ALLOW_MULTI(text, (std::vector<std::pair<Error::Type, std::string>>{
+ {Error::Type::Warning, "are not supposed to return"},
+ {Error::Type::DeclarationError, "Unbalanced stack"},
+ }));
+}
+
+BOOST_AUTO_TEST_CASE(inline_assembly_050_bare_instructions)
+{
+ char const* text = R"(
+ pragma experimental "v0.5.0";
+ contract C {
+ function f() view public {
+ assembly {
+ address
+ pop
+ }
+ }
+ }
+ )";
+ CHECK_ALLOW_MULTI(text, (std::vector<std::pair<Error::Type, std::string>>{
+ {Error::Type::SyntaxError, "The use of non-functional"},
+ {Error::Type::SyntaxError, "The use of non-functional"}
+ }));
+}
+
+BOOST_AUTO_TEST_CASE(inline_assembly_bare_instructions)
+{
+ char const* text = R"(
+ contract C {
+ function f() view public {
+ assembly {
+ address
+ pop
+ }
+ }
+ }
+ )";
+ CHECK_ALLOW_MULTI(text, (std::vector<std::pair<Error::Type, std::string>>{
+ {Error::Type::Warning, "The use of non-functional"},
+ {Error::Type::Warning, "The use of non-functional"}
+ }));
+}
+
+BOOST_AUTO_TEST_CASE(inline_assembly_050_labels)
+{
+ char const* text = R"(
+ pragma experimental "v0.5.0";
+ contract C {
+ function f() pure public {
+ assembly {
+ label:
+ }
+ }
+ }
+ )";
+ CHECK_ALLOW_MULTI(text, (std::vector<std::pair<Error::Type, std::string>>{
+ {Error::Type::SyntaxError, "Jump instructions and labels are low-level"},
+ {Error::Type::SyntaxError, "The use of labels is deprecated"}
+ }));
+}
+
+BOOST_AUTO_TEST_CASE(inline_assembly_labels)
+{
+ char const* text = R"(
+ contract C {
+ function f() pure public {
+ assembly {
+ label:
+ }
+ }
+ }
+ )";
+ CHECK_ALLOW_MULTI(text, (std::vector<std::pair<Error::Type, std::string>>{
+ {Error::Type::Warning, "Jump instructions and labels are low-level"},
+ {Error::Type::Warning, "The use of labels is deprecated"}
+ }));
+}
+
+BOOST_AUTO_TEST_CASE(inline_assembly_050_jump)
+{
+ char const* text = R"(
+ pragma experimental "v0.5.0";
+ contract C {
+ function f() pure public {
+ assembly {
+ jump(2)
+ }
+ }
+ }
+ )";
+ CHECK_ALLOW_MULTI(text, (std::vector<std::pair<Error::Type, std::string>>{
+ {Error::Type::SyntaxError, "Jump instructions and labels are low-level"}
+ }));
+}
+
+BOOST_AUTO_TEST_CASE(inline_assembly_jump)
+{
+ char const* text = R"(
+ contract C {
+ function f() pure public {
+ assembly {
+ jump(2)
+ }
+ }
+ }
+ )";
+ CHECK_ALLOW_MULTI(text, (std::vector<std::pair<Error::Type, std::string>>{
+ {Error::Type::TypeError, "Function declared as pure"},
+ {Error::Type::Warning, "Jump instructions and labels are low-level"}
+ }));
+}
+
+BOOST_AUTO_TEST_CASE(inline_assembly_050_leave_items_on_stack)
+{
+ char const* text = R"(
+ pragma experimental "v0.5.0";
+ contract C {
+ function f() pure public {
+ assembly {
+ mload(0)
+ }
+ }
+ }
+ )";
+ CHECK_ALLOW_MULTI(text, (std::vector<std::pair<Error::Type, std::string>>{
+ {Error::Type::SyntaxError, "are not supposed to return"},
+ {Error::Type::DeclarationError, "Unbalanced stack"},
+ }));
+}
+
+BOOST_AUTO_TEST_CASE(inline_assembly_leave_items_on_stack)
+{
+ char const* text = R"(
+ contract C {
+ function f() pure public {
+ assembly {
+ mload(0)
+ }
+ }
+ }
+ )";
+ CHECK_ALLOW_MULTI(text, (std::vector<std::pair<Error::Type, std::string>>{
+ {Error::Type::Warning, "are not supposed to return"},
+ {Error::Type::DeclarationError, "Unbalanced stack"},
+ }));
+}
+
BOOST_AUTO_TEST_CASE(invalid_mobile_type)
{
char const* text = R"(
@@ -6757,6 +7198,8 @@ BOOST_AUTO_TEST_CASE(callable_crash)
BOOST_AUTO_TEST_CASE(error_transfer_non_payable_fallback)
{
+ // This used to be a test for a.transfer to generate a warning
+ // because A's fallback function is not payable.
char const* text = R"(
contract A {
function() public {}
@@ -6770,12 +7213,17 @@ BOOST_AUTO_TEST_CASE(error_transfer_non_payable_fallback)
}
}
)";
- CHECK_ERROR(text, TypeError, "Value transfer to a contract without a payable fallback function.");
+ CHECK_ALLOW_MULTI(text, (std::vector<std::pair<Error::Type, std::string>>{
+ {Error::Type::Warning, "Using contract member \"transfer\" inherited from the address type is deprecated"},
+ {Error::Type::TypeError, "Value transfer to a contract without a payable fallback function"}
+ }));
}
BOOST_AUTO_TEST_CASE(error_transfer_no_fallback)
{
- char const* text = R"(
+ // This used to be a test for a.transfer to generate a warning
+ // because A does not have a payable fallback function.
+ std::string text = R"(
contract A {}
contract B {
@@ -6786,12 +7234,17 @@ BOOST_AUTO_TEST_CASE(error_transfer_no_fallback)
}
}
)";
- CHECK_ERROR(text, TypeError, "Value transfer to a contract without a payable fallback function.");
+ CHECK_ALLOW_MULTI(text, (std::vector<std::pair<Error::Type, std::string>>{
+ {Error::Type::Warning, "Using contract member \"transfer\" inherited from the address type is deprecated"},
+ {Error::Type::TypeError, "Value transfer to a contract without a payable fallback function"}
+ }));
}
BOOST_AUTO_TEST_CASE(error_send_non_payable_fallback)
{
- char const* text = R"(
+ // This used to be a test for a.send to generate a warning
+ // because A does not have a payable fallback function.
+ std::string text = R"(
contract A {
function() public {}
}
@@ -6804,11 +7257,16 @@ BOOST_AUTO_TEST_CASE(error_send_non_payable_fallback)
}
}
)";
- CHECK_ERROR(text, TypeError, "Value transfer to a contract without a payable fallback function.");
+ CHECK_ALLOW_MULTI(text, (std::vector<std::pair<Error::Type, std::string>>{
+ {Error::Type::Warning, "Using contract member \"send\" inherited from the address type is deprecated"},
+ {Error::Type::TypeError, "Value transfer to a contract without a payable fallback function"}
+ }));
}
BOOST_AUTO_TEST_CASE(does_not_error_transfer_payable_fallback)
{
+ // This used to be a test for a.transfer to generate a warning
+ // because A does not have a payable fallback function.
char const* text = R"(
contract A {
function() payable public {}
@@ -6822,7 +7280,7 @@ BOOST_AUTO_TEST_CASE(does_not_error_transfer_payable_fallback)
}
}
)";
- CHECK_SUCCESS_NO_WARNINGS(text);
+ CHECK_WARNING(text, "Using contract member \"transfer\" inherited from the address type is deprecated.");
}
BOOST_AUTO_TEST_CASE(does_not_error_transfer_regular_function)
@@ -6848,11 +7306,14 @@ 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::Warning, "The use of non-functional instructions is deprecated."},
+ {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)
@@ -6862,8 +7323,9 @@ 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::DeclarationError, "Unbalanced stack"}
+ {Error::Type::Warning, "The \"create2\" instruction is not supported by the VM version"},
+ {Error::Type::DeclarationError, "Unbalanced stack"},
+ {Error::Type::Warning, "not supposed to return values"}
}));
}
@@ -7157,6 +7619,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"(
@@ -7418,7 +7924,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 {
@@ -7736,12 +8242,140 @@ BOOST_AUTO_TEST_CASE(array_length_invalid_expression)
CHECK_ERROR(text, TypeError, "Operator / not compatible with types int_const 3 and int_const 0");
}
+BOOST_AUTO_TEST_CASE(warn_about_address_members_on_contract)
+{
+ std::string text = R"(
+ contract C {
+ function f() view public {
+ this.balance;
+ }
+ }
+ )";
+ CHECK_WARNING(text, "Using contract member \"balance\" inherited from the address type is deprecated.");
+ text = R"(
+ contract C {
+ function f() view public {
+ this.transfer;
+ }
+ }
+ )";
+ CHECK_ALLOW_MULTI(text, (vector<pair<Error::Type, std::string>>{
+ {Error::Type::Warning, "Using contract member \"transfer\" inherited from the address type is deprecated"},
+ {Error::Type::TypeError, "Value transfer to a contract without a payable fallback function"}
+ }));
+ text = R"(
+ contract C {
+ function f() view public {
+ this.send;
+ }
+ }
+ )";
+ CHECK_ALLOW_MULTI(text, (vector<pair<Error::Type, std::string>>{
+ {Error::Type::Warning, "Using contract member \"send\" inherited from the address type is deprecated"},
+ {Error::Type::TypeError, "Value transfer to a contract without a payable fallback function"}
+ }));
+ text = R"(
+ contract C {
+ function f() view public {
+ this.call;
+ }
+ }
+ )";
+ CHECK_WARNING(text, "Using contract member \"call\" inherited from the address type is deprecated.");
+ text = R"(
+ contract C {
+ function f() view public {
+ this.callcode;
+ }
+ }
+ )";
+ CHECK_ALLOW_MULTI(text, (vector<pair<Error::Type, std::string>>{
+ {Error::Type::Warning, "Using contract member \"callcode\" inherited from the address type is deprecated"},
+ {Error::Type::Warning, "\"callcode\" has been deprecated in favour of \"delegatecall\""}
+ }));
+ text = R"(
+ contract C {
+ function f() view public {
+ this.delegatecall;
+ }
+ }
+ )";
+ CHECK_WARNING(text, "Using contract member \"delegatecall\" inherited from the address type is deprecated.");
+}
+
+BOOST_AUTO_TEST_CASE(warn_about_address_members_on_non_this_contract)
+{
+ std::string text = R"(
+ contract C {
+ function f() view public {
+ C c;
+ c.balance;
+ }
+ }
+ )";
+ CHECK_WARNING(text, "Using contract member \"balance\" inherited from the address type is deprecated");
+ text = R"(
+ contract C {
+ function f() view public {
+ C c;
+ c.transfer;
+ }
+ }
+ )";
+ CHECK_ALLOW_MULTI(text, (vector<pair<Error::Type, std::string>>{
+ {Error::Type::Warning, "Using contract member \"transfer\" inherited from the address type is deprecated"},
+ {Error::Type::TypeError, "Value transfer to a contract without a payable fallback function"}
+ }));
+ text = R"(
+ contract C {
+ function f() view public {
+ C c;
+ c.send;
+ }
+ }
+ )";
+ CHECK_ALLOW_MULTI(text, (vector<pair<Error::Type, std::string>>{
+ {Error::Type::Warning, "Using contract member \"send\" inherited from the address type is deprecated"},
+ {Error::Type::TypeError, "Value transfer to a contract without a payable fallback function"}
+ }));
+ text = R"(
+ contract C {
+ function f() pure public {
+ C c;
+ c.call;
+ }
+ }
+ )";
+ CHECK_WARNING(text, "Using contract member \"call\" inherited from the address type is deprecated");
+ text = R"(
+ contract C {
+ function f() pure public {
+ C c;
+ c.callcode;
+ }
+ }
+ )";
+ CHECK_WARNING_ALLOW_MULTI(text, (std::vector<std::string>{
+ "Using contract member \"callcode\" inherited from the address type is deprecated",
+ "\"callcode\" has been deprecated in favour of \"delegatecall\""
+ }));
+ text = R"(
+ contract C {
+ function f() pure public {
+ C c;
+ c.delegatecall;
+ }
+ }
+ )";
+ CHECK_WARNING(text, "Using contract member \"delegatecall\" inherited from the address type is deprecated");
+}
+
BOOST_AUTO_TEST_CASE(no_address_members_on_contract)
{
char const* text = R"(
pragma experimental "v0.5.0";
contract C {
- function f() {
+ function f() public {
this.balance;
}
}
@@ -7750,7 +8384,7 @@ BOOST_AUTO_TEST_CASE(no_address_members_on_contract)
text = R"(
pragma experimental "v0.5.0";
contract C {
- function f() {
+ function f() public {
this.transfer;
}
}
@@ -7759,7 +8393,7 @@ BOOST_AUTO_TEST_CASE(no_address_members_on_contract)
text = R"(
pragma experimental "v0.5.0";
contract C {
- function f() {
+ function f() public {
this.send;
}
}
@@ -7768,7 +8402,7 @@ BOOST_AUTO_TEST_CASE(no_address_members_on_contract)
text = R"(
pragma experimental "v0.5.0";
contract C {
- function f() {
+ function f() public {
this.call;
}
}
@@ -7777,7 +8411,7 @@ BOOST_AUTO_TEST_CASE(no_address_members_on_contract)
text = R"(
pragma experimental "v0.5.0";
contract C {
- function f() {
+ function f() public {
this.callcode;
}
}
@@ -7786,7 +8420,7 @@ BOOST_AUTO_TEST_CASE(no_address_members_on_contract)
text = R"(
pragma experimental "v0.5.0";
contract C {
- function f() {
+ function f() public {
this.delegatecall;
}
}
@@ -7794,6 +8428,20 @@ BOOST_AUTO_TEST_CASE(no_address_members_on_contract)
CHECK_ERROR(text, TypeError, "Member \"delegatecall\" not found or not visible after argument-dependent lookup in contract");
}
+BOOST_AUTO_TEST_CASE(no_warning_for_using_members_that_look_like_address_members)
+{
+ char const* text = R"(
+ pragma experimental "v0.5.0";
+ contract C {
+ function transfer(uint) public;
+ function f() public {
+ this.transfer(10);
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+}
+
BOOST_AUTO_TEST_CASE(emit_events)
{
char const* text = R"(
@@ -7870,6 +8518,23 @@ BOOST_AUTO_TEST_CASE(getter_is_memory_type)
}
}
+BOOST_AUTO_TEST_CASE(require_visibility_specifiers)
+{
+ char const* text = R"(
+ contract C {
+ function f() pure { }
+ }
+ )";
+ CHECK_WARNING(text, "No visibility specified. Defaulting to");
+ text = R"(
+ pragma experimental "v0.5.0";
+ contract C {
+ function f() pure { }
+ }
+ )";
+ CHECK_ERROR(text, SyntaxError, "No visibility specified.");
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp
index e8906bb9..eeebeb74 100644
--- a/test/libsolidity/SolidityNatspecJSON.cpp
+++ b/test/libsolidity/SolidityNatspecJSON.cpp
@@ -20,7 +20,7 @@
* Unit tests for the solidity compiler JSON Interface output.
*/
-#include "../TestHelper.h"
+#include <test/Options.h>
#include <string>
#include <libdevcore/JSON.h>
#include <libsolidity/interface/CompilerStack.h>
@@ -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..4e862f60 100644
--- a/test/libsolidity/SolidityParser.cpp
+++ b/test/libsolidity/SolidityParser.cpp
@@ -25,8 +25,8 @@
#include <libsolidity/parsing/Scanner.h>
#include <libsolidity/parsing/Parser.h>
#include <libsolidity/interface/ErrorReporter.h>
-#include "../TestHelper.h"
-#include "ErrorCheck.h"
+#include <test/Options.h>
+#include <test/libsolidity/ErrorCheck.h>
using namespace std;
@@ -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 404f709d..dd6eb7c4 100644
--- a/test/libsolidity/StandardCompiler.cpp
+++ b/test/libsolidity/StandardCompiler.cpp
@@ -570,6 +570,198 @@ BOOST_AUTO_TEST_CASE(library_filename_with_colon)
BOOST_CHECK(contract["evm"]["bytecode"]["linkReferences"]["git:library.sol"]["L"][0].isObject());
}
+BOOST_AUTO_TEST_CASE(libraries_invalid_top_level)
+{
+ char const* input = R"(
+ {
+ "language": "Solidity",
+ "settings": {
+ "libraries": "42"
+ },
+ "sources": {
+ "empty": {
+ "content": ""
+ }
+ }
+ }
+ )";
+ Json::Value result = compile(input);
+ BOOST_CHECK(containsError(result, "JSONError", "\"libraries\" is not a JSON object."));
+}
+
+BOOST_AUTO_TEST_CASE(libraries_invalid_entry)
+{
+ char const* input = R"(
+ {
+ "language": "Solidity",
+ "settings": {
+ "libraries": {
+ "L": "42"
+ }
+ },
+ "sources": {
+ "empty": {
+ "content": ""
+ }
+ }
+ }
+ )";
+ Json::Value result = compile(input);
+ BOOST_CHECK(containsError(result, "JSONError", "library entry is not a JSON object."));
+}
+
+BOOST_AUTO_TEST_CASE(libraries_invalid_hex)
+{
+ char const* input = R"(
+ {
+ "language": "Solidity",
+ "settings": {
+ "libraries": {
+ "library.sol": {
+ "L": "0x4200000000000000000000000000000000000xx1"
+ }
+ }
+ },
+ "sources": {
+ "empty": {
+ "content": ""
+ }
+ }
+ }
+ )";
+ Json::Value result = compile(input);
+ BOOST_CHECK(containsError(result, "JSONError", "Invalid library address (\"0x4200000000000000000000000000000000000xx1\") supplied."));
+}
+
+BOOST_AUTO_TEST_CASE(libraries_invalid_length)
+{
+ char const* input = R"(
+ {
+ "language": "Solidity",
+ "settings": {
+ "libraries": {
+ "library.sol": {
+ "L1": "0x42",
+ "L2": "0x4200000000000000000000000000000000000001ff"
+ }
+ }
+ },
+ "sources": {
+ "empty": {
+ "content": ""
+ }
+ }
+ }
+ )";
+ Json::Value result = compile(input);
+ BOOST_CHECK(containsError(result, "JSONError", "Library address is of invalid length."));
+}
+
+BOOST_AUTO_TEST_CASE(libraries_missing_hex_prefix)
+{
+ char const* input = R"(
+ {
+ "language": "Solidity",
+ "settings": {
+ "libraries": {
+ "library.sol": {
+ "L": "4200000000000000000000000000000000000001"
+ }
+ }
+ },
+ "sources": {
+ "empty": {
+ "content": ""
+ }
+ }
+ }
+ )";
+ Json::Value result = compile(input);
+ BOOST_CHECK(containsError(result, "JSONError", "Library address is not prefixed with \"0x\"."));
+}
+
+BOOST_AUTO_TEST_CASE(library_linking)
+{
+ char const* input = R"(
+ {
+ "language": "Solidity",
+ "settings": {
+ "libraries": {
+ "library.sol": {
+ "L": "0x4200000000000000000000000000000000000001"
+ }
+ },
+ "outputSelection": {
+ "fileA": {
+ "A": [
+ "evm.bytecode"
+ ]
+ }
+ }
+ },
+ "sources": {
+ "fileA": {
+ "content": "import \"library.sol\"; import \"library2.sol\"; contract A { function f() returns (uint) { L2.g(); return L.g(); } }"
+ },
+ "library.sol": {
+ "content": "library L { function g() returns (uint) { return 1; } }"
+ },
+ "library2.sol": {
+ "content": "library L2 { function g() { } }"
+ }
+ }
+ }
+ )";
+ Json::Value result = compile(input);
+ BOOST_CHECK(containsAtMostWarnings(result));
+ Json::Value contract = getContractResult(result, "fileA", "A");
+ BOOST_CHECK(contract.isObject());
+ BOOST_CHECK(contract["evm"]["bytecode"].isObject());
+ BOOST_CHECK(contract["evm"]["bytecode"]["linkReferences"].isObject());
+ BOOST_CHECK(!contract["evm"]["bytecode"]["linkReferences"]["library.sol"].isObject());
+ BOOST_CHECK(contract["evm"]["bytecode"]["linkReferences"]["library2.sol"].isObject());
+ BOOST_CHECK(contract["evm"]["bytecode"]["linkReferences"]["library2.sol"]["L2"].isArray());
+ 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);
+ result = compile(inputForVersion("\"evmVersion\": \"constantinople\","));
+ BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"constantinople\"") != 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/SyntaxTest.cpp b/test/libsolidity/SyntaxTest.cpp
new file mode 100644
index 00000000..45a851b6
--- /dev/null
+++ b/test/libsolidity/SyntaxTest.cpp
@@ -0,0 +1,209 @@
+/*
+ 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/SyntaxTest.h>
+#include <boost/algorithm/string.hpp>
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/throw_exception.hpp>
+#include <cctype>
+#include <fstream>
+#include <memory>
+#include <stdexcept>
+
+using namespace dev;
+using namespace solidity;
+using namespace dev::solidity::test;
+using namespace std;
+namespace fs = boost::filesystem;
+using namespace boost::unit_test;
+
+template<typename IteratorType>
+void skipWhitespace(IteratorType& it, IteratorType end)
+{
+ while (it != end && isspace(*it))
+ ++it;
+}
+
+template<typename IteratorType>
+void skipSlashes(IteratorType& it, IteratorType end)
+{
+ while (it != end && *it == '/')
+ ++it;
+}
+
+SyntaxTest::SyntaxTest(string const& _filename)
+{
+ ifstream file(_filename);
+ if (!file)
+ BOOST_THROW_EXCEPTION(runtime_error("Cannot open test contract: \"" + _filename + "\"."));
+ file.exceptions(ios::badbit);
+
+ m_source = parseSource(file);
+ m_expectations = parseExpectations(file);
+}
+
+bool SyntaxTest::run(ostream& _stream, string const& _indent)
+{
+ m_errorList = parseAnalyseAndReturnError(m_source, true, true, true).second;
+ if (!matchesExpectations(m_errorList))
+ {
+ std::string nextIndentLevel = _indent + "\t";
+ _stream << _indent << "Expected result:" << endl;
+ printExpected(_stream, nextIndentLevel);
+ _stream << _indent << "Obtained result:\n";
+ printErrorList(_stream, m_errorList, nextIndentLevel);
+ return false;
+ }
+ return true;
+}
+
+void SyntaxTest::printExpected(ostream& _stream, string const& _indent) const
+{
+ if (m_expectations.empty())
+ _stream << _indent << "Success" << endl;
+ else
+ for (auto const& expectation: m_expectations)
+ _stream << _indent << expectation.type << ": " << expectation.message << endl;
+}
+
+void SyntaxTest::printErrorList(
+ ostream& _stream,
+ ErrorList const& _errorList,
+ string const& _indent
+) const
+{
+ if (_errorList.empty())
+ _stream << _indent << "Success" << endl;
+ else
+ for (auto const& error: _errorList)
+ _stream << _indent << error->typeName() << ": " << errorMessage(*error) << endl;
+}
+
+bool SyntaxTest::matchesExpectations(ErrorList const& _errorList) const
+{
+ if (_errorList.size() != m_expectations.size())
+ return false;
+ else
+ for (size_t i = 0; i < _errorList.size(); i++)
+ if (
+ (_errorList[i]->typeName() != m_expectations[i].type) ||
+ (errorMessage(*_errorList[i]) != m_expectations[i].message)
+ )
+ return false;
+ return true;
+}
+
+string SyntaxTest::errorMessage(Error const& _e)
+{
+ if (_e.comment())
+ return boost::replace_all_copy(*_e.comment(), "\n", "\\n");
+ else
+ return "NONE";
+}
+
+string SyntaxTest::parseSource(istream& _stream)
+{
+ string source;
+ string line;
+ string const delimiter("// ----");
+ while (getline(_stream, line))
+ if (boost::algorithm::starts_with(line, delimiter))
+ break;
+ else
+ source += line + "\n";
+ return source;
+}
+
+vector<SyntaxTestExpectation> SyntaxTest::parseExpectations(istream& _stream)
+{
+ vector<SyntaxTestExpectation> expectations;
+ string line;
+ while (getline(_stream, line))
+ {
+ auto it = line.begin();
+
+ skipSlashes(it, line.end());
+ skipWhitespace(it, line.end());
+
+ if (it == line.end()) continue;
+
+ auto typeBegin = it;
+ while (it != line.end() && *it != ':')
+ ++it;
+ string errorType(typeBegin, it);
+
+ // skip colon
+ if (it != line.end()) it++;
+
+ skipWhitespace(it, line.end());
+
+ string errorMessage(it, line.end());
+ expectations.emplace_back(SyntaxTestExpectation{move(errorType), move(errorMessage)});
+ }
+ return expectations;
+}
+
+#if BOOST_VERSION < 105900
+test_case *make_test_case(
+ function<void()> const& _fn,
+ string const& _name,
+ string const& /* _filename */,
+ size_t /* _line */
+)
+{
+ return make_test_case(_fn, _name);
+}
+#endif
+
+int SyntaxTest::registerTests(
+ boost::unit_test::test_suite& _suite,
+ boost::filesystem::path const& _basepath,
+ boost::filesystem::path const& _path
+)
+{
+ int numTestsAdded = 0;
+ fs::path fullpath = _basepath / _path;
+ if (fs::is_directory(fullpath))
+ {
+ test_suite* sub_suite = BOOST_TEST_SUITE(_path.filename().string());
+ for (auto const& entry: boost::iterator_range<fs::directory_iterator>(
+ fs::directory_iterator(fullpath),
+ fs::directory_iterator()
+ ))
+ numTestsAdded += registerTests(*sub_suite, _basepath, _path / entry.path().filename());
+ _suite.add(sub_suite);
+ }
+ else
+ {
+ static vector<unique_ptr<string>> filenames;
+
+ filenames.emplace_back(new string(_path.string()));
+ _suite.add(make_test_case(
+ [fullpath]
+ {
+ std::stringstream errorStream;
+ if (!SyntaxTest(fullpath.string()).run(errorStream, ""))
+ BOOST_ERROR("Test expectation mismatch.\n" + errorStream.str());
+ },
+ _path.stem().string(),
+ *filenames.back(),
+ 0
+ ));
+ numTestsAdded = 1;
+ }
+ return numTestsAdded;
+}
diff --git a/test/libsolidity/SyntaxTest.h b/test/libsolidity/SyntaxTest.h
new file mode 100644
index 00000000..4379c77b
--- /dev/null
+++ b/test/libsolidity/SyntaxTest.h
@@ -0,0 +1,77 @@
+/*
+ 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/AnalysisFramework.h>
+#include <libsolidity/interface/Exceptions.h>
+
+#include <boost/noncopyable.hpp>
+#include <boost/test/unit_test.hpp>
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+#include <utility>
+
+namespace dev
+{
+namespace solidity
+{
+namespace test
+{
+
+struct SyntaxTestExpectation
+{
+ std::string type;
+ std::string message;
+};
+
+
+class SyntaxTest: AnalysisFramework
+{
+public:
+ SyntaxTest(std::string const& _filename);
+
+ bool run(std::ostream& _stream, std::string const& _indent);
+
+ void printExpected(std::ostream& _stream, std::string const& _indent) const;
+ void printErrorList(
+ std::ostream& _stream,
+ ErrorList const& _errors,
+ std::string const& _indent
+ ) const;
+
+ static int registerTests(
+ boost::unit_test::test_suite& _suite,
+ boost::filesystem::path const& _basepath,
+ boost::filesystem::path const& _path
+ );
+private:
+ bool matchesExpectations(ErrorList const& _errors) const;
+ static std::string errorMessage(Error const& _e);
+ static std::string parseSource(std::istream& _stream);
+ static std::vector<SyntaxTestExpectation> parseExpectations(std::istream& _stream);
+
+ std::string m_source;
+ std::vector<SyntaxTestExpectation> m_expectations;
+ ErrorList m_errorList;
+};
+
+}
+}
+}
diff --git a/test/libsolidity/ViewPureChecker.cpp b/test/libsolidity/ViewPureChecker.cpp
index 3a03c877..a6ce6d91 100644
--- a/test/libsolidity/ViewPureChecker.cpp
+++ b/test/libsolidity/ViewPureChecker.cpp
@@ -20,6 +20,8 @@
#include <test/libsolidity/AnalysisFramework.h>
+#include <test/Options.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",
@@ -148,7 +151,7 @@ BOOST_AUTO_TEST_CASE(environment_access)
BOOST_AUTO_TEST_CASE(view_error_for_050)
{
CHECK_ERROR(
- "pragma experimental \"v0.5.0\"; contract C { uint x; function f() view { x = 2; } }",
+ "pragma experimental \"v0.5.0\"; contract C { uint x; function f() view public { x = 2; } }",
TypeError,
"Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable."
);
@@ -277,11 +280,11 @@ BOOST_AUTO_TEST_CASE(builtin_functions)
string text = R"(
contract C {
function f() public {
- this.transfer(1);
- require(this.send(2));
- selfdestruct(this);
- require(this.delegatecall());
- require(this.call());
+ address(this).transfer(1);
+ require(address(this).send(2));
+ selfdestruct(address(this));
+ require(address(this).delegatecall());
+ require(address(this).call());
}
function g() pure public {
bytes32 x = keccak256("abc");
@@ -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)
diff --git a/test/libsolidity/syntaxTests/docstring_empty_description.sol b/test/libsolidity/syntaxTests/docstring_empty_description.sol
new file mode 100644
index 00000000..0caa1b23
--- /dev/null
+++ b/test/libsolidity/syntaxTests/docstring_empty_description.sol
@@ -0,0 +1,6 @@
+contract C {
+ /// @param id
+ function vote(uint id) public;
+}
+// ----
+// DocstringParsingError: No description given for param id
diff --git a/test/libsolidity/syntaxTests/double_stateVariable_declaration.sol b/test/libsolidity/syntaxTests/double_stateVariable_declaration.sol
new file mode 100644
index 00000000..c5507b64
--- /dev/null
+++ b/test/libsolidity/syntaxTests/double_stateVariable_declaration.sol
@@ -0,0 +1,6 @@
+contract test {
+ uint256 variable;
+ uint128 variable;
+}
+// ----
+// DeclarationError: Identifier already declared.
diff --git a/test/libsolidity/syntaxTests/double_variable_declaration.sol b/test/libsolidity/syntaxTests/double_variable_declaration.sol
new file mode 100644
index 00000000..3349cfec
--- /dev/null
+++ b/test/libsolidity/syntaxTests/double_variable_declaration.sol
@@ -0,0 +1,8 @@
+contract test {
+ function f() pure public {
+ uint256 x;
+ if (true) { uint256 x; }
+ }
+}
+// ----
+// DeclarationError: Identifier already declared.
diff --git a/test/libsolidity/syntaxTests/double_variable_declaration_050.sol b/test/libsolidity/syntaxTests/double_variable_declaration_050.sol
new file mode 100644
index 00000000..9c2d40d5
--- /dev/null
+++ b/test/libsolidity/syntaxTests/double_variable_declaration_050.sol
@@ -0,0 +1,11 @@
+pragma experimental "v0.5.0";
+contract test {
+ function f() pure public {
+ uint256 x;
+ if (true) { uint256 x; }
+ }
+}
+// ----
+// Warning: This declaration shadows an existing declaration.
+// Warning: Unused local variable.
+// Warning: Unused local variable.
diff --git a/test/libsolidity/syntaxTests/smoke_test.sol b/test/libsolidity/syntaxTests/smoke_test.sol
new file mode 100644
index 00000000..2d48098a
--- /dev/null
+++ b/test/libsolidity/syntaxTests/smoke_test.sol
@@ -0,0 +1,6 @@
+contract test {
+ uint256 stateVariable1;
+ function fun(uint256 arg1) public { uint256 y; y = arg1; }
+}
+// ----
+// Warning: Function state mutability can be restricted to pure
diff --git a/test/libsolidity/syntaxTests/virtualLookup/modifiers_in_libraries.sol b/test/libsolidity/syntaxTests/virtualLookup/modifiers_in_libraries.sol
new file mode 100644
index 00000000..b033fd0c
--- /dev/null
+++ b/test/libsolidity/syntaxTests/virtualLookup/modifiers_in_libraries.sol
@@ -0,0 +1,14 @@
+library WithModifier {
+ modifier mod() { require(msg.value > 10 ether); _; }
+ function withMod(uint self) mod() internal view { require(self > 0); }
+}
+
+contract Test {
+ using WithModifier for *;
+
+ function f(uint _value) public payable {
+ _value.withMod();
+ WithModifier.withMod(_value);
+ }
+}
+// ----
diff --git a/test/libsolidity/syntaxTests/visibility/external_library_function.sol b/test/libsolidity/syntaxTests/visibility/external_library_function.sol
new file mode 100644
index 00000000..110e74db
--- /dev/null
+++ b/test/libsolidity/syntaxTests/visibility/external_library_function.sol
@@ -0,0 +1,14 @@
+library L {
+ function f(uint) pure external {}
+}
+
+contract C {
+ using L for *;
+
+ function f() public pure {
+ L.f(2);
+ uint x;
+ x.f();
+ }
+}
+// ----
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/fuzzer.cpp b/test/tools/fuzzer.cpp
index 45738baa..71f38b67 100644
--- a/test/fuzzer.cpp
+++ b/test/tools/fuzzer.cpp
@@ -76,6 +76,7 @@ void testConstantOptimizer()
ConstantOptimisationMethod::optimiseConstants(
isCreation,
runs,
+ EVMVersion{},
assembly,
const_cast<AssemblyItems&>(assembly.items())
);