aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/CMakeLists.txt2
-rw-r--r--test/RPCSession.cpp101
-rw-r--r--test/RPCSession.h32
-rw-r--r--test/TestHelper.cpp45
-rw-r--r--test/TestHelper.h11
-rw-r--r--test/boostTest.cpp5
-rw-r--r--test/contracts/AuctionRegistrar.cpp34
-rw-r--r--test/contracts/FixedFeeRegistrar.cpp15
-rw-r--r--test/contracts/Wallet.cpp46
-rw-r--r--test/libsolidity/ASTJSON.cpp218
-rw-r--r--test/libsolidity/Assembly.cpp4
-rw-r--r--test/libsolidity/GasMeter.cpp5
-rw-r--r--test/libsolidity/Imports.cpp74
-rw-r--r--test/libsolidity/InlineAssembly.cpp7
-rw-r--r--test/libsolidity/SemVerMatcher.cpp223
-rw-r--r--test/libsolidity/SolidityABIJSON.cpp99
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp604
-rw-r--r--test/libsolidity/SolidityExecutionFramework.cpp29
-rw-r--r--test/libsolidity/SolidityExecutionFramework.h53
-rw-r--r--test/libsolidity/SolidityExpressionCompiler.cpp8
-rw-r--r--test/libsolidity/SolidityInterface.cpp165
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp263
-rw-r--r--test/libsolidity/SolidityNatspecJSON.cpp4
-rw-r--r--test/libsolidity/SolidityOptimizer.cpp76
-rw-r--r--test/libsolidity/SolidityParser.cpp28
-rw-r--r--test/libsolidity/SolidityScanner.cpp82
26 files changed, 1763 insertions, 470 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index efcbb82e..2f001b21 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -26,7 +26,7 @@ file(GLOB HEADERS "*.h" "*/*.h")
set(EXECUTABLE soltest)
eth_simple_add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
-eth_use(${EXECUTABLE} REQUIRED Solidity::solidity Eth::ethcore)
+eth_use(${EXECUTABLE} REQUIRED Solidity::solidity)
include_directories(BEFORE ..)
target_link_libraries(${EXECUTABLE} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES})
diff --git a/test/RPCSession.cpp b/test/RPCSession.cpp
index 54e1675f..0a01ddb2 100644
--- a/test/RPCSession.cpp
+++ b/test/RPCSession.cpp
@@ -13,6 +13,8 @@
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+
+ The Implementation originally from https://msdn.microsoft.com/en-us/library/windows/desktop/aa365592(v=vs.85).aspx
*/
/** @file RPCSession.cpp
* @author Dimtiry Khokhlov <dimitry@ethdev.com>
@@ -32,26 +34,84 @@ using namespace dev;
IPCSocket::IPCSocket(string const& _path): m_path(_path)
{
+#if defined(_WIN32)
+ m_socket = CreateFile(
+ m_path.c_str(), // pipe name
+ GENERIC_READ | // read and write access
+ GENERIC_WRITE,
+ 0, // no sharing
+ NULL, // default security attribute
+ OPEN_EXISTING, // opens existing pipe
+ 0, // default attributes
+ NULL); // no template file
+
+ if (m_socket == INVALID_HANDLE_VALUE)
+ BOOST_FAIL("Error creating IPC socket object!");
+
+#else
if (_path.length() >= sizeof(sockaddr_un::sun_path))
BOOST_FAIL("Error opening IPC: socket path is too long!");
struct sockaddr_un saun;
+ memset(&saun, 0, sizeof(sockaddr_un));
saun.sun_family = AF_UNIX;
strcpy(saun.sun_path, _path.c_str());
+// http://idletechnology.blogspot.ca/2011/12/unix-domain-sockets-on-osx.html
+//
+// SUN_LEN() might be optimal, but it seemingly affects the portability,
+// with at least Android missing this macro. Just using the sizeof() for
+// structure seemingly works, and would only have the side-effect of
+// sending larger-than-required packets over the socket. Given that this
+// code is only used for unit-tests, that approach seems simpler.
+#if defined(__APPLE__)
+ saun.sun_len = sizeof(struct sockaddr_un);
+#endif // defined(__APPLE__)
+
if ((m_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
BOOST_FAIL("Error creating IPC socket object");
- int len = sizeof(saun.sun_family) + strlen(saun.sun_path);
-
- if (connect(m_socket, reinterpret_cast<struct sockaddr const*>(&saun), len) < 0)
+ if (connect(m_socket, reinterpret_cast<struct sockaddr const*>(&saun), sizeof(struct sockaddr_un)) < 0)
BOOST_FAIL("Error connecting to IPC socket: " << _path);
m_fp = fdopen(m_socket, "r");
+#endif
}
string IPCSocket::sendRequest(string const& _req)
{
+#if defined(_WIN32)
+ string returnStr;
+ DWORD cbWritten;
+ BOOL fSuccess = WriteFile(
+ m_socket, // pipe handle
+ _req.c_str(), // message
+ _req.size(), // message length
+ &cbWritten, // bytes written
+ NULL); // not overlapped
+
+ if (!fSuccess)
+ BOOST_FAIL("WriteFile to pipe failed");
+
+ DWORD cbRead;
+ TCHAR chBuf[c_buffsize];
+
+ // Read from the pipe.
+ fSuccess = ReadFile(
+ m_socket, // pipe handle
+ chBuf, // buffer to receive reply
+ c_buffsize,// size of buffer
+ &cbRead, // number of bytes read
+ NULL); // not overlapped
+
+ returnStr += chBuf;
+
+ if (!fSuccess)
+ BOOST_FAIL("ReadFile from pipe failed");
+
+ cerr << "."; //Output for log activity
+ return returnStr;
+#else
send(m_socket, _req.c_str(), _req.length(), 0);
char c;
@@ -64,6 +124,7 @@ string IPCSocket::sendRequest(string const& _req)
break;
}
return response;
+#endif
}
RPCSession& RPCSession::instance(const string& _path)
@@ -183,15 +244,39 @@ void RPCSession::test_mineBlocks(int _number)
u256 startBlock = fromBigEndian<u256>(fromHex(rpcCall("eth_blockNumber").asString()));
rpcCall("test_mineBlocks", { to_string(_number) }, true);
- //@TODO do not use polling - but that would probably need a change to the test client
- for (size_t polls = 0; polls < 100; ++polls)
+ bool mined = false;
+
+ // We auto-calibrate the time it takes to mine the transaction.
+ // It would be better to go without polling, but that would probably need a change to the test client
+
+ unsigned sleepTime = m_sleepTime;
+ size_t polls = 0;
+ for (; polls < 14 && !mined; ++polls)
{
+ std::this_thread::sleep_for(chrono::milliseconds(sleepTime));
if (fromBigEndian<u256>(fromHex(rpcCall("eth_blockNumber").asString())) >= startBlock + _number)
- return;
- std::this_thread::sleep_for(chrono::milliseconds(10)); //it does not work faster then 10 ms
+ mined = true;
+ else
+ sleepTime *= 2;
+ }
+ if (polls > 1)
+ {
+ m_successfulMineRuns = 0;
+ m_sleepTime += 2;
+ }
+ else if (polls == 1)
+ {
+ m_successfulMineRuns++;
+ if (m_successfulMineRuns > 5)
+ {
+ m_successfulMineRuns = 0;
+ if (m_sleepTime > 2)
+ m_sleepTime--;
+ }
}
- BOOST_FAIL("Error in test_mineBlocks: block mining timeout!");
+ if (!mined)
+ BOOST_FAIL("Error in test_mineBlocks: block mining timeout!");
}
void RPCSession::test_modifyTimestamp(size_t _timestamp)
diff --git a/test/RPCSession.h b/test/RPCSession.h
index 1a1fbbe5..2a9825b0 100644
--- a/test/RPCSession.h
+++ b/test/RPCSession.h
@@ -19,15 +19,37 @@
* @date 2016
*/
-#include <string>
-#include <stdio.h>
-#include <map>
+#if defined(_WIN32)
+#include <windows.h>
+#include "libdevcore/UndefMacros.h"
+#else
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
+#endif
+
+#include <string>
+#include <stdio.h>
+#include <map>
#include <json/value.h>
#include <boost/test/unit_test.hpp>
+#if defined(_WIN32)
+const int c_buffsize = 5120000; //because windows pipe is broken and wont work as in examples. use larger buffer limit to receive whole package in one call
+class IPCSocket : public boost::noncopyable
+{
+public:
+ IPCSocket(std::string const& _path);
+ std::string sendRequest(std::string const& _req);
+ ~IPCSocket() { CloseHandle(m_socket); }
+
+ std::string const& path() const { return m_path; }
+
+private:
+ std::string m_path;
+ HANDLE m_socket;
+};
+#else
class IPCSocket: public boost::noncopyable
{
public:
@@ -41,8 +63,8 @@ private:
FILE *m_fp;
std::string m_path;
int m_socket;
-
};
+#endif
class RPCSession: public boost::noncopyable
{
@@ -102,6 +124,8 @@ private:
IPCSocket m_ipcSocket;
size_t m_rpcSequence = 1;
+ unsigned m_sleepTime = 10;
+ unsigned m_successfulMineRuns = 0;
std::vector<std::string> m_accounts;
};
diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp
new file mode 100644
index 00000000..df35ff53
--- /dev/null
+++ b/test/TestHelper.cpp
@@ -0,0 +1,45 @@
+/*
+ This file is part of cpp-ethereum.
+
+ cpp-ethereum 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.
+
+ cpp-ethereum 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+*/
+/** @file TestHelper.h
+* @author Marko Simovic <markobarko@gmail.com>
+* @date 2014
+*/
+
+#include <boost/test/framework.hpp>
+#include "TestHelper.h"
+using namespace std;
+using namespace dev::test;
+
+Options const& Options::get()
+{
+ static Options instance;
+ return instance;
+}
+
+Options::Options()
+{
+ auto const& suite = boost::unit_test::framework::master_test_suite();
+ for (auto i = 0; i < suite.argc; i++)
+ if (string(suite.argv[i]) == "--ipcpath" && i + 1 < suite.argc)
+ {
+ ipcPath = suite.argv[i + 1];
+ i++;
+ }
+ if (ipcPath.empty())
+ if (auto path = getenv("ETH_TEST_IPC"))
+ ipcPath = path;
+}
diff --git a/test/TestHelper.h b/test/TestHelper.h
index 2d08d62c..2cb24fd7 100644
--- a/test/TestHelper.h
+++ b/test/TestHelper.h
@@ -102,5 +102,16 @@ namespace test
} \
while (0)
+
+struct Options: boost::noncopyable
+{
+ std::string ipcPath;
+
+ static Options const& get();
+
+private:
+ Options();
+};
+
}
}
diff --git a/test/boostTest.cpp b/test/boostTest.cpp
index a2cfa5ee..4ddae0b7 100644
--- a/test/boostTest.cpp
+++ b/test/boostTest.cpp
@@ -25,6 +25,7 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
+
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4535) // calling _set_se_translator requires /EHa
@@ -35,7 +36,3 @@
#endif
#pragma GCC diagnostic pop
-
-#include <test/TestHelper.h>
-using namespace boost::unit_test;
-
diff --git a/test/contracts/AuctionRegistrar.cpp b/test/contracts/AuctionRegistrar.cpp
index 9aa47189..277de4eb 100644
--- a/test/contracts/AuctionRegistrar.cpp
+++ b/test/contracts/AuctionRegistrar.cpp
@@ -23,8 +23,7 @@
#include <string>
#include <tuple>
#include <boost/test/unit_test.hpp>
-#include <libdevcore/Hash.h>
-#include <libethcore/ABI.h>
+#include <libdevcore/ABI.h>
#include <test/libsolidity/SolidityExecutionFramework.h>
using namespace std;
@@ -40,7 +39,7 @@ namespace
{
static char const* registrarCode = R"DELIMITER(
-//sol
+pragma solidity ^0.4.0;
contract NameRegister {
function addr(string _name) constant returns (address o_owner);
@@ -116,11 +115,6 @@ contract GlobalRegistrar is Registrar, AuctionSystem {
// TODO: Populate with hall-of-fame.
}
- function() {
- // prevent people from just sending funds to the registrar
- throw;
- }
-
function onAuctionEnd(string _name) internal {
var auction = m_auctions[_name];
var record = m_toRecord[_name];
@@ -131,15 +125,13 @@ contract GlobalRegistrar is Registrar, AuctionSystem {
if (previousOwner != 0) {
if (!record.owner.send(auction.sumOfBids - auction.highestBid / 100))
throw;
- }
- else
- {
+ } else {
if (!auction.highestBidder.send(auction.highestBid - auction.secondHighestBid))
throw;
}
}
- function reserve(string _name) external {
+ function reserve(string _name) external payable {
if (bytes(_name).length == 0)
throw;
bool needAuction = requiresAuction(_name);
@@ -148,9 +140,7 @@ contract GlobalRegistrar is Registrar, AuctionSystem {
if (now < m_toRecord[_name].renewalDate)
throw;
bid(_name, msg.sender, msg.value);
- }
- else
- {
+ } else {
Record record = m_toRecord[_name];
if (record.owner != 0)
throw;
@@ -163,7 +153,7 @@ contract GlobalRegistrar is Registrar, AuctionSystem {
return bytes(_name).length < c_freeBytes;
}
- modifier onlyrecordowner(string _name) { if (m_toRecord[_name].owner == msg.sender) _ }
+ modifier onlyrecordowner(string _name) { if (m_toRecord[_name].owner == msg.sender) _; }
function transfer(string _name, address _newOwner) onlyrecordowner(_name) {
m_toRecord[_name].owner = _newOwner;
@@ -231,7 +221,7 @@ protected:
if (!s_compiledRegistrar)
{
m_optimize = true;
- m_compiler.reset(false, m_addStandardSources);
+ m_compiler.reset(false);
m_compiler.addSource("", registrarCode);
ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(m_optimize, m_optimizeRuns), "Compiling contract failed");
s_compiledRegistrar.reset(new bytes(m_compiler.object("GlobalRegistrar").bytecode));
@@ -333,7 +323,7 @@ BOOST_AUTO_TEST_CASE(double_reserve_long)
registrar.reserve(name);
BOOST_CHECK_EQUAL(registrar.owner(name), m_sender);
- sendEther(account(1), u256(10) * eth::ether);
+ sendEther(account(1), u256(10) * ether);
m_sender = account(1);
registrar.reserve(name);
BOOST_CHECK_EQUAL(registrar.owner(name), account(0));
@@ -350,7 +340,7 @@ BOOST_AUTO_TEST_CASE(properties)
for (string const& name: names)
{
m_sender = account(0);
- sendEther(account(count), u256(20) * eth::ether);
+ sendEther(account(count), u256(20) * ether);
m_sender = account(count);
auto sender = m_sender;
addr += count;
@@ -402,7 +392,7 @@ BOOST_AUTO_TEST_CASE(disown)
BOOST_CHECK_EQUAL(registrar.name(u160(124)), name);
// someone else tries disowning
- sendEther(account(1), u256(10) * eth::ether);
+ sendEther(account(1), u256(10) * ether);
m_sender = account(1);
registrar.disown(name);
BOOST_CHECK_EQUAL(registrar.owner(name), account(0));
@@ -451,7 +441,7 @@ BOOST_AUTO_TEST_CASE(auction_bidding)
registrar.setNextValue(12);
registrar.reserve(name);
// another bid by someone else
- sendEther(account(1), 10 * eth::ether);
+ sendEther(account(1), 10 * ether);
m_sender = account(1);
m_rpc.test_modifyTimestamp(startTime + 2 * m_biddingTime - 50);
registrar.setNextValue(13);
@@ -480,7 +470,7 @@ BOOST_AUTO_TEST_CASE(auction_renewal)
BOOST_CHECK_EQUAL(registrar.owner(name), m_sender);
// try to re-register before interval end
- sendEther(account(1), 10 * eth::ether);
+ sendEther(account(1), 10 * ether);
m_sender = account(1);
m_rpc.test_modifyTimestamp(currentTimestamp() + m_renewalInterval - 1);
registrar.setNextValue(80);
diff --git a/test/contracts/FixedFeeRegistrar.cpp b/test/contracts/FixedFeeRegistrar.cpp
index 8cb8257a..736015fa 100644
--- a/test/contracts/FixedFeeRegistrar.cpp
+++ b/test/contracts/FixedFeeRegistrar.cpp
@@ -32,7 +32,6 @@
#pragma warning(pop)
#endif
-#include <libdevcore/Hash.h>
#include <test/libsolidity/SolidityExecutionFramework.h>
using namespace std;
@@ -53,6 +52,8 @@ static char const* registrarCode = R"DELIMITER(
// @authors:
// Gav Wood <g@ethdev.com>
+pragma solidity ^0.4.0;
+
contract Registrar {
event Changed(string indexed name);
@@ -70,9 +71,9 @@ contract FixedFeeRegistrar is Registrar {
address owner;
}
- modifier onlyrecordowner(string _name) { if (m_record(_name).owner == msg.sender) _ }
+ modifier onlyrecordowner(string _name) { if (m_record(_name).owner == msg.sender) _; }
- function reserve(string _name) {
+ function reserve(string _name) payable {
Record rec = m_record(_name);
if (rec.owner == 0 && msg.value >= c_fee) {
rec.owner = msg.sender;
@@ -132,7 +133,7 @@ protected:
if (!s_compiledRegistrar)
{
m_optimize = true;
- m_compiler.reset(false, m_addStandardSources);
+ m_compiler.reset(false);
m_compiler.addSource("", registrarCode);
ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(m_optimize, m_optimizeRuns), "Compiling contract failed");
s_compiledRegistrar.reset(new bytes(m_compiler.object("FixedFeeRegistrar").bytecode));
@@ -174,7 +175,7 @@ BOOST_AUTO_TEST_CASE(double_reserve)
BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee, encodeDyn(name)) == encodeArgs());
BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name)) == encodeArgs(h256(account(0), h256::AlignRight)));
- sendEther(account(1), 100 * eth::ether);
+ sendEther(account(1), 100 * ether);
m_sender = account(1);
BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee, encodeDyn(name)) == encodeArgs());
BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name)) == encodeArgs(h256(account(0), h256::AlignRight)));
@@ -191,7 +192,7 @@ BOOST_AUTO_TEST_CASE(properties)
{
addr++;
m_sender = account(0);
- sendEther(account(count), 100 * eth::ether);
+ sendEther(account(count), 100 * ether);
m_sender = account(count);
Address owner = m_sender;
// setting by sender works
@@ -206,7 +207,7 @@ BOOST_AUTO_TEST_CASE(properties)
count++;
// but not by someone else
m_sender = account(0);
- sendEther(account(count), 100 * eth::ether);
+ sendEther(account(count), 100 * ether);
m_sender = account(count);
BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name)) == encodeArgs(h256(owner, h256::AlignRight)));
BOOST_CHECK(callContractFunction("setAddr(string,address)", u256(0x40), addr + 1, u256(name.length()), name) == encodeArgs());
diff --git a/test/contracts/Wallet.cpp b/test/contracts/Wallet.cpp
index fbab2404..ec968058 100644
--- a/test/contracts/Wallet.cpp
+++ b/test/contracts/Wallet.cpp
@@ -32,7 +32,6 @@
#pragma warning(pop)
#endif
-#include <libdevcore/Hash.h>
#include <test/libsolidity/SolidityExecutionFramework.h>
using namespace std;
@@ -55,6 +54,9 @@ static char const* walletCode = R"DELIMITER(
// use modifiers onlyowner (just own owned) or onlymanyowners(hash), whereby the same hash must be provided by
// some number (specified in constructor) of the set of owners (specified in the constructor, modifiable) before the
// interior is executed.
+
+pragma solidity ^0.4.0;
+
contract multiowned {
// TYPES
@@ -84,14 +86,14 @@ contract multiowned {
// simple single-sig function modifier.
modifier onlyowner {
if (isOwner(msg.sender))
- _
+ _;
}
// multi-sig function modifier: the operation must have an intrinsic hash in order
// that later attempts can be realised as the same underlying operation and
// thus count as confirmations.
modifier onlymanyowners(bytes32 _operation) {
if (confirmAndCheck(_operation))
- _
+ _;
}
// METHODS
@@ -279,7 +281,7 @@ contract daylimit is multiowned {
// simple modifier for daily limit.
modifier limitedDaily(uint _value) {
if (underLimit(_value))
- _
+ _;
}
// METHODS
@@ -376,7 +378,7 @@ contract Wallet is multisig, multiowned, daylimit {
}
// gets called when no other function matches
- function() {
+ function() payable {
// just being sent some cash?
if (msg.value > 0)
Deposit(msg.sender, msg.value);
@@ -446,7 +448,7 @@ protected:
if (!s_compiledWallet)
{
m_optimize = true;
- m_compiler.reset(false, m_addStandardSources);
+ m_compiler.reset(false);
m_compiler.addSource("", walletCode);
ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(m_optimize, m_optimizeRuns), "Compiling contract failed");
s_compiledWallet.reset(new bytes(m_compiler.object("Wallet").bytecode));
@@ -474,13 +476,13 @@ BOOST_AUTO_TEST_CASE(add_owners)
BOOST_REQUIRE(callContractFunction("addOwner(address)", h256(account(1), h256::AlignRight)) == encodeArgs());
BOOST_REQUIRE(callContractFunction("isOwner(address)", h256(account(1), h256::AlignRight)) == encodeArgs(true));
// now let the new owner add someone
- sendEther(account(1), 10 * eth::ether);
+ sendEther(account(1), 10 * ether);
m_sender = account(1);
BOOST_REQUIRE(callContractFunction("addOwner(address)", h256(0x13)) == encodeArgs());
BOOST_REQUIRE(callContractFunction("isOwner(address)", h256(0x13)) == encodeArgs(true));
// and check that a non-owner cannot add a new owner
m_sender = account(0);
- sendEther(account(2), 10 * eth::ether);
+ sendEther(account(2), 10 * ether);
m_sender = account(2);
BOOST_REQUIRE(callContractFunction("addOwner(address)", h256(0x20)) == encodeArgs());
BOOST_REQUIRE(callContractFunction("isOwner(address)", h256(0x20)) == encodeArgs(false));
@@ -559,17 +561,17 @@ BOOST_AUTO_TEST_CASE(multisig_value_transfer)
// check that balance is and stays zero at destination address
BOOST_CHECK_EQUAL(balanceAt(Address(0x05)), 0);
m_sender = account(0);
- sendEther(account(1), 10 * eth::ether);
+ sendEther(account(1), 10 * ether);
m_sender = account(1);
auto ophash = callContractFunction("execute(address,uint256,bytes)", h256(0x05), 100, 0x60, 0x00);
BOOST_CHECK_EQUAL(balanceAt(Address(0x05)), 0);
m_sender = account(0);
- sendEther(account(2), 10 * eth::ether);
+ sendEther(account(2), 10 * ether);
m_sender = account(2);
callContractFunction("confirm(bytes32)", ophash);
BOOST_CHECK_EQUAL(balanceAt(Address(0x05)), 0);
m_sender = account(0);
- sendEther(account(3), 10 * eth::ether);
+ sendEther(account(3), 10 * ether);
m_sender = account(3);
callContractFunction("confirm(bytes32)", ophash);
// now it should go through
@@ -586,11 +588,11 @@ BOOST_AUTO_TEST_CASE(revoke_addOwner)
BOOST_REQUIRE(callContractFunction("changeRequirement(uint256)", u256(3)) == encodeArgs());
// add a new owner
Address deployer = m_sender;
- h256 opHash = sha3(FixedHash<4>(dev::sha3("addOwner(address)")).asBytes() + h256(0x33).asBytes());
+ h256 opHash = dev::keccak256(FixedHash<4>(dev::keccak256("addOwner(address)")).asBytes() + h256(0x33).asBytes());
BOOST_REQUIRE(callContractFunction("addOwner(address)", h256(0x33)) == encodeArgs());
BOOST_REQUIRE(callContractFunction("isOwner(address)", h256(0x33)) == encodeArgs(false));
m_sender = account(0);
- sendEther(account(1), 10 * eth::ether);
+ sendEther(account(1), 10 * ether);
m_sender = account(1);
BOOST_REQUIRE(callContractFunction("addOwner(address)", h256(0x33)) == encodeArgs());
BOOST_REQUIRE(callContractFunction("isOwner(address)", h256(0x33)) == encodeArgs(false));
@@ -598,12 +600,12 @@ BOOST_AUTO_TEST_CASE(revoke_addOwner)
m_sender = deployer;
BOOST_REQUIRE(callContractFunction("revoke(bytes32)", opHash) == encodeArgs());
m_sender = account(0);
- sendEther(account(2), 10 * eth::ether);
+ sendEther(account(2), 10 * ether);
m_sender = account(2);
BOOST_REQUIRE(callContractFunction("addOwner(address)", h256(0x33)) == encodeArgs());
BOOST_REQUIRE(callContractFunction("isOwner(address)", h256(0x33)) == encodeArgs(false));
m_sender = account(0);
- sendEther(account(3), 10 * eth::ether);
+ sendEther(account(3), 10 * ether);
m_sender = account(3);
BOOST_REQUIRE(callContractFunction("addOwner(address)", h256(0x33)) == encodeArgs());
BOOST_REQUIRE(callContractFunction("isOwner(address)", h256(0x33)) == encodeArgs(true));
@@ -621,24 +623,24 @@ BOOST_AUTO_TEST_CASE(revoke_transaction)
Address deployer = m_sender;
BOOST_CHECK_EQUAL(balanceAt(Address(0x05)), 0);
m_sender = account(0);
- sendEther(account(1), 10 * eth::ether);
+ sendEther(account(1), 10 * ether);
m_sender = account(1);
auto opHash = callContractFunction("execute(address,uint256,bytes)", h256(0x05), 100, 0x60, 0x00);
BOOST_CHECK_EQUAL(balanceAt(Address(0x05)), 0);
m_sender = account(0);
- sendEther(account(2), 10 * eth::ether);
+ sendEther(account(2), 10 * ether);
m_sender = account(2);
callContractFunction("confirm(bytes32)", opHash);
BOOST_CHECK_EQUAL(balanceAt(Address(0x05)), 0);
m_sender = account(0);
- sendEther(account(1), 10 * eth::ether);
+ sendEther(account(1), 10 * ether);
m_sender = account(1);
BOOST_REQUIRE(callContractFunction("revoke(bytes32)", opHash) == encodeArgs());
m_sender = deployer;
callContractFunction("confirm(bytes32)", opHash);
BOOST_CHECK_EQUAL(balanceAt(Address(0x05)), 0);
m_sender = account(0);
- sendEther(account(3), 10 * eth::ether);
+ sendEther(account(3), 10 * ether);
m_sender = account(3);
callContractFunction("confirm(bytes32)", opHash);
// now it should go through
@@ -659,7 +661,7 @@ BOOST_AUTO_TEST_CASE(daylimit)
// try to send tx over daylimit
BOOST_CHECK_EQUAL(balanceAt(Address(0x05)), 0);
- sendEther(account(1), 10 * eth::ether);
+ sendEther(account(1), 10 * ether);
m_sender = account(1);
BOOST_REQUIRE(
callContractFunction("execute(address,uint256,bytes)", h256(0x05), 150, 0x60, 0x00) !=
@@ -668,7 +670,7 @@ BOOST_AUTO_TEST_CASE(daylimit)
BOOST_CHECK_EQUAL(balanceAt(Address(0x05)), 0);
// try to send tx under daylimit by stranger
m_sender = account(0);
- sendEther(account(4), 10 * eth::ether);
+ sendEther(account(4), 10 * ether);
m_sender = account(4);
BOOST_REQUIRE(
callContractFunction("execute(address,uint256,bytes)", h256(0x05), 90, 0x60, 0x00) ==
@@ -677,7 +679,7 @@ BOOST_AUTO_TEST_CASE(daylimit)
BOOST_CHECK_EQUAL(balanceAt(Address(0x05)), 0);
// now send below limit by owner
m_sender = account(0);
- sendEther(account(1), 10 * eth::ether);
+ sendEther(account(1), 10 * ether);
BOOST_REQUIRE(
callContractFunction("execute(address,uint256,bytes)", h256(0x05), 90, 0x60, 0x00) ==
encodeArgs(u256(0))
diff --git a/test/libsolidity/ASTJSON.cpp b/test/libsolidity/ASTJSON.cpp
new file mode 100644
index 00000000..a0fc5dd7
--- /dev/null
+++ b/test/libsolidity/ASTJSON.cpp
@@ -0,0 +1,218 @@
+/*
+ This file is part of cpp-ethereum.
+
+ cpp-ethereum 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.
+
+ cpp-ethereum 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @author Christian <c@ethdev.com>
+ * @date 2016
+ * Tests for the json ast output.
+ */
+
+#include <string>
+#include <boost/test/unit_test.hpp>
+#include <libsolidity/interface/Exceptions.h>
+#include <libsolidity/interface/CompilerStack.h>
+#include <libsolidity/ast/ASTJsonConverter.h>
+
+using namespace std;
+
+namespace dev
+{
+namespace solidity
+{
+namespace test
+{
+
+BOOST_AUTO_TEST_SUITE(SolidityASTJSON)
+
+BOOST_AUTO_TEST_CASE(smoke_test)
+{
+ CompilerStack c;
+ c.addSource("a", "contract C {}");
+ c.parse();
+ map<string, unsigned> sourceIndices;
+ sourceIndices["a"] = 1;
+ Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ BOOST_CHECK_EQUAL(astJson["name"], "SourceUnit");
+}
+
+BOOST_AUTO_TEST_CASE(source_location)
+{
+ CompilerStack c;
+ c.addSource("a", "contract C { function f() { var x = 2; x++; } }");
+ c.parse();
+ map<string, unsigned> sourceIndices;
+ sourceIndices["a"] = 1;
+ Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ BOOST_CHECK_EQUAL(astJson["name"], "SourceUnit");
+ BOOST_CHECK_EQUAL(astJson["children"][0]["name"], "ContractDefinition");
+ BOOST_CHECK_EQUAL(astJson["children"][0]["children"][0]["name"], "FunctionDefinition");
+ BOOST_CHECK_EQUAL(astJson["children"][0]["children"][0]["src"], "13:32:1");
+}
+
+BOOST_AUTO_TEST_CASE(inheritance_specifier)
+{
+ CompilerStack c;
+ c.addSource("a", "contract C1 {} contract C2 is C1 {}");
+ c.parse();
+ map<string, unsigned> sourceIndices;
+ sourceIndices["a"] = 1;
+ Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ BOOST_CHECK_EQUAL(astJson["children"][1]["attributes"]["name"], "C2");
+ BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["name"], "InheritanceSpecifier");
+ BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["src"], "30:2:1");
+ BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["children"][0]["name"], "UserDefinedTypeName");
+ BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["children"][0]["attributes"]["name"], "C1");
+}
+
+BOOST_AUTO_TEST_CASE(using_for_directive)
+{
+ CompilerStack c;
+ c.addSource("a", "library L {} contract C { using L for uint; }");
+ c.parse();
+ map<string, unsigned> sourceIndices;
+ sourceIndices["a"] = 1;
+ Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ Json::Value usingFor = astJson["children"][1]["children"][0];
+ BOOST_CHECK_EQUAL(usingFor["name"], "UsingForDirective");
+ BOOST_CHECK_EQUAL(usingFor["src"], "26:17:1");
+ BOOST_CHECK_EQUAL(usingFor["children"][0]["name"], "UserDefinedTypeName");
+ BOOST_CHECK_EQUAL(usingFor["children"][0]["attributes"]["name"], "L");
+ BOOST_CHECK_EQUAL(usingFor["children"][1]["name"], "ElementaryTypeName");
+ BOOST_CHECK_EQUAL(usingFor["children"][1]["attributes"]["name"], "uint");
+}
+
+BOOST_AUTO_TEST_CASE(enum_definition)
+{
+ CompilerStack c;
+ c.addSource("a", "contract C { enum E {} }");
+ c.parse();
+ map<string, unsigned> sourceIndices;
+ sourceIndices["a"] = 1;
+ Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ Json::Value enumDefinition = astJson["children"][0]["children"][0];
+ BOOST_CHECK_EQUAL(enumDefinition["name"], "EnumDefinition");
+ BOOST_CHECK_EQUAL(enumDefinition["attributes"]["name"], "E");
+ BOOST_CHECK_EQUAL(enumDefinition["src"], "13:9:1");
+}
+
+BOOST_AUTO_TEST_CASE(enum_value)
+{
+ CompilerStack c;
+ c.addSource("a", "contract C { enum E { A, B } }");
+ c.parse();
+ map<string, unsigned> sourceIndices;
+ sourceIndices["a"] = 1;
+ Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ Json::Value enumDefinition = astJson["children"][0]["children"][0];
+ BOOST_CHECK_EQUAL(enumDefinition["children"][0]["name"], "EnumValue");
+ BOOST_CHECK_EQUAL(enumDefinition["children"][0]["attributes"]["name"], "A");
+ BOOST_CHECK_EQUAL(enumDefinition["children"][0]["src"], "22:1:1");
+ BOOST_CHECK_EQUAL(enumDefinition["children"][1]["name"], "EnumValue");
+ BOOST_CHECK_EQUAL(enumDefinition["children"][1]["attributes"]["name"], "B");
+ BOOST_CHECK_EQUAL(enumDefinition["children"][1]["src"], "25:1:1");
+}
+
+BOOST_AUTO_TEST_CASE(modifier_definition)
+{
+ CompilerStack c;
+ c.addSource("a", "contract C { modifier M(uint i) { _; } function F() M(1) {} }");
+ c.parse();
+ map<string, unsigned> sourceIndices;
+ sourceIndices["a"] = 1;
+ Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ Json::Value modifier = astJson["children"][0]["children"][0];
+ BOOST_CHECK_EQUAL(modifier["name"], "ModifierDefinition");
+ BOOST_CHECK_EQUAL(modifier["attributes"]["name"], "M");
+ BOOST_CHECK_EQUAL(modifier["src"], "13:25:1");
+}
+
+BOOST_AUTO_TEST_CASE(modifier_invocation)
+{
+ CompilerStack c;
+ c.addSource("a", "contract C { modifier M(uint i) { _; } function F() M(1) {} }");
+ c.parse();
+ map<string, unsigned> sourceIndices;
+ sourceIndices["a"] = 1;
+ Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ Json::Value modifier = astJson["children"][0]["children"][1]["children"][2];
+ BOOST_CHECK_EQUAL(modifier["name"], "ModifierInvocation");
+ BOOST_CHECK_EQUAL(modifier["src"], "52:4:1");
+ BOOST_CHECK_EQUAL(modifier["children"][0]["attributes"]["type"], "modifier (uint256)");
+ BOOST_CHECK_EQUAL(modifier["children"][0]["attributes"]["value"], "M");
+ BOOST_CHECK_EQUAL(modifier["children"][1]["attributes"]["value"], "1");
+}
+
+BOOST_AUTO_TEST_CASE(event_definition)
+{
+ CompilerStack c;
+ c.addSource("a", "contract C { event E(); }");
+ c.parse();
+ map<string, unsigned> sourceIndices;
+ sourceIndices["a"] = 1;
+ Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ Json::Value event = astJson["children"][0]["children"][0];
+ BOOST_CHECK_EQUAL(event["name"], "EventDefinition");
+ BOOST_CHECK_EQUAL(event["attributes"]["name"], "E");
+ BOOST_CHECK_EQUAL(event["src"], "13:10:1");
+}
+
+BOOST_AUTO_TEST_CASE(array_type_name)
+{
+ CompilerStack c;
+ c.addSource("a", "contract C { uint[] i; }");
+ c.parse();
+ map<string, unsigned> sourceIndices;
+ sourceIndices["a"] = 1;
+ Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ Json::Value array = astJson["children"][0]["children"][0]["children"][0];
+ BOOST_CHECK_EQUAL(array["name"], "ArrayTypeName");
+ BOOST_CHECK_EQUAL(array["src"], "13:6:1");
+}
+
+BOOST_AUTO_TEST_CASE(placeholder_statement)
+{
+ CompilerStack c;
+ c.addSource("a", "contract C { modifier M { _; } }");
+ c.parse();
+ map<string, unsigned> sourceIndices;
+ sourceIndices["a"] = 1;
+ Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ Json::Value placeholder = astJson["children"][0]["children"][0]["children"][1]["children"][0];
+ BOOST_CHECK_EQUAL(placeholder["name"], "PlaceholderStatement");
+ BOOST_CHECK_EQUAL(placeholder["src"], "26:1:1");
+}
+
+BOOST_AUTO_TEST_CASE(non_utf8)
+{
+ CompilerStack c;
+ c.addSource("a", "contract C { function f() { var x = hex\"ff\"; } }");
+ c.parse();
+ map<string, unsigned> sourceIndices;
+ sourceIndices["a"] = 1;
+ Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ Json::Value literal = astJson["children"][0]["children"][0]["children"][2]["children"][0]["children"][1];
+ BOOST_CHECK_EQUAL(literal["name"], "Literal");
+ BOOST_CHECK_EQUAL(literal["attributes"]["hexvalue"], "ff");
+ BOOST_CHECK_EQUAL(literal["attributes"]["token"], Json::nullValue);
+ BOOST_CHECK_EQUAL(literal["attributes"]["value"], Json::nullValue);
+ BOOST_CHECK(literal["attributes"]["type"].asString().find("invalid") != string::npos);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+}
+}
+} // end namespaces
diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp
index 557d496a..8d7a3540 100644
--- a/test/libsolidity/Assembly.cpp
+++ b/test/libsolidity/Assembly.cpp
@@ -114,8 +114,8 @@ BOOST_AUTO_TEST_CASE(location_test)
shared_ptr<string const> n = make_shared<string>("source");
AssemblyItems items = compileContract(sourceCode);
vector<SourceLocation> locations =
- vector<SourceLocation>(17, SourceLocation(2, 75, n)) +
- vector<SourceLocation>(28, SourceLocation(20, 72, n)) +
+ vector<SourceLocation>(18, SourceLocation(2, 75, n)) +
+ vector<SourceLocation>(31, SourceLocation(20, 72, n)) +
vector<SourceLocation>{SourceLocation(42, 51, n), SourceLocation(65, 67, n)} +
vector<SourceLocation>(4, SourceLocation(58, 67, n)) +
vector<SourceLocation>(3, SourceLocation(20, 72, n));
diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp
index fc7a033f..fc103393 100644
--- a/test/libsolidity/GasMeter.cpp
+++ b/test/libsolidity/GasMeter.cpp
@@ -21,6 +21,7 @@
*/
#include <test/libsolidity/SolidityExecutionFramework.h>
+#include <libevmasm/EVMSchedule.h>
#include <libevmasm/GasMeter.h>
#include <libevmasm/KnownState.h>
#include <libevmasm/PathGasMeter.h>
@@ -45,7 +46,7 @@ public:
GasMeterTestFramework() { }
void compile(string const& _sourceCode)
{
- m_compiler.setSource(_sourceCode);
+ m_compiler.setSource("pragma solidity >= 0.0;" + _sourceCode);
ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(), "Compiling contract failed");
AssemblyItems const* items = m_compiler.runtimeAssemblyItems("");
@@ -81,7 +82,7 @@ public:
{
u256 gasUsed = 0;
GasMeter::GasConsumption gas;
- FixedHash<4> hash(dev::sha3(_sig));
+ FixedHash<4> hash(dev::keccak256(_sig));
for (bytes const& arguments: _argumentVariants)
{
sendMessage(hash.asBytes() + arguments, false, 0);
diff --git a/test/libsolidity/Imports.cpp b/test/libsolidity/Imports.cpp
index 0736a853..1a9e16cc 100644
--- a/test/libsolidity/Imports.cpp
+++ b/test/libsolidity/Imports.cpp
@@ -39,106 +39,106 @@ BOOST_AUTO_TEST_SUITE(SolidityImports)
BOOST_AUTO_TEST_CASE(smoke_test)
{
CompilerStack c;
- c.addSource("a", "contract C {}");
+ c.addSource("a", "contract C {} pragma solidity >=0.0;");
BOOST_CHECK(c.compile());
}
BOOST_AUTO_TEST_CASE(regular_import)
{
CompilerStack c;
- c.addSource("a", "contract C {}");
- c.addSource("b", "import \"a\"; contract D is C {}");
+ c.addSource("a", "contract C {} pragma solidity >=0.0;");
+ c.addSource("b", "import \"a\"; contract D is C {} pragma solidity >=0.0;");
BOOST_CHECK(c.compile());
}
BOOST_AUTO_TEST_CASE(import_does_not_clutter_importee)
{
CompilerStack c;
- c.addSource("a", "contract C { D d; }");
- c.addSource("b", "import \"a\"; contract D is 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;");
BOOST_CHECK(!c.compile());
}
BOOST_AUTO_TEST_CASE(import_is_transitive)
{
CompilerStack c;
- c.addSource("a", "contract C { }");
- c.addSource("b", "import \"a\";");
- c.addSource("c", "import \"b\"; contract D is C {}");
+ 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;");
BOOST_CHECK(c.compile());
}
BOOST_AUTO_TEST_CASE(circular_import)
{
CompilerStack c;
- c.addSource("a", "import \"b\"; contract C { D d; }");
- c.addSource("b", "import \"a\"; contract D { C 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;");
BOOST_CHECK(c.compile());
}
BOOST_AUTO_TEST_CASE(relative_import)
{
CompilerStack c;
- c.addSource("a", "import \"./dir/b\"; contract A is B {}");
- c.addSource("dir/b", "contract B {}");
- c.addSource("dir/c", "import \"../a\"; contract C is A {}");
+ 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;");
BOOST_CHECK(c.compile());
}
BOOST_AUTO_TEST_CASE(relative_import_multiplex)
{
CompilerStack c;
- c.addSource("a", "contract A {}");
- c.addSource("dir/a/b/c", "import \"../../.././a\"; contract B is A {}");
+ 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;");
BOOST_CHECK(c.compile());
}
BOOST_AUTO_TEST_CASE(simple_alias)
{
CompilerStack c;
- c.addSource("a", "contract A {}");
- c.addSource("dir/a/b/c", "import \"../../.././a\" as x; contract B is x.A { function() { x.A r = x.A(20); } }");
+ 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;");
BOOST_CHECK(c.compile());
}
BOOST_AUTO_TEST_CASE(library_name_clash)
{
CompilerStack c;
- c.addSource("a", "library A {}");
- c.addSource("b", "library A {}");
+ c.addSource("a", "library A {} pragma solidity >=0.0;");
+ c.addSource("b", "library A {} pragma solidity >=0.0;");
BOOST_CHECK(!c.compile());
}
BOOST_AUTO_TEST_CASE(library_name_clash_with_contract)
{
CompilerStack c;
- c.addSource("a", "contract A {}");
- c.addSource("b", "library A {}");
+ c.addSource("a", "contract A {} pragma solidity >=0.0;");
+ c.addSource("b", "library A {} pragma solidity >=0.0;");
BOOST_CHECK(c.compile());
}
BOOST_AUTO_TEST_CASE(complex_import)
{
CompilerStack c;
- c.addSource("a", "contract A {} contract B {} contract C { struct S { uint a; } }");
+ 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 {} }");
+ "contract D is b { function f(c.S var1, x.C.S var2, C.S var3) internal {} } pragma solidity >=0.0;");
BOOST_CHECK(c.compile());
}
BOOST_AUTO_TEST_CASE(name_clash_in_import)
{
CompilerStack c;
- c.addSource("a", "contract A {}");
- c.addSource("b", "import \"a\"; contract A {} ");
+ c.addSource("a", "contract A {} pragma solidity >=0.0;");
+ c.addSource("b", "import \"a\"; contract A {} pragma solidity >=0.0;");
BOOST_CHECK(!c.compile());
- c.addSource("b", "import \"a\" as A; contract A {} ");
+ c.addSource("b", "import \"a\" as A; contract A {} pragma solidity >=0.0;");
BOOST_CHECK(!c.compile());
- c.addSource("b", "import {A as b} from \"a\"; contract b {} ");
+ c.addSource("b", "import {A as b} from \"a\"; contract b {} pragma solidity >=0.0;");
BOOST_CHECK(!c.compile());
- c.addSource("b", "import {A} from \"a\"; contract A {} ");
+ c.addSource("b", "import {A} from \"a\"; contract A {} pragma solidity >=0.0;");
BOOST_CHECK(!c.compile());
- c.addSource("b", "import {A} from \"a\"; contract B {} ");
+ c.addSource("b", "import {A} from \"a\"; contract B {} pragma solidity >=0.0;");
BOOST_CHECK(c.compile());
}
@@ -146,10 +146,10 @@ BOOST_AUTO_TEST_CASE(remappings)
{
CompilerStack c;
c.setRemappings(vector<string>{"s=s_1.4.6", "t=Tee"});
- c.addSource("a", "import \"s/s.sol\"; contract A is S {}");
- c.addSource("b", "import \"t/tee.sol\"; contract A is Tee {} ");
- c.addSource("s_1.4.6/s.sol", "contract S {}");
- c.addSource("Tee/tee.sol", "contract Tee {}");
+ c.addSource("a", "import \"s/s.sol\"; contract A is S {} pragma solidity >=0.0;");
+ 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;");
BOOST_CHECK(c.compile());
}
@@ -157,10 +157,10 @@ BOOST_AUTO_TEST_CASE(context_dependent_remappings)
{
CompilerStack c;
c.setRemappings(vector<string>{"a:s=s_1.4.6", "b:s=s_1.4.7"});
- c.addSource("a/a.sol", "import \"s/s.sol\"; contract A is SSix {}");
- c.addSource("b/b.sol", "import \"s/s.sol\"; contract B is SSeven {}");
- c.addSource("s_1.4.6/s.sol", "contract SSix {} ");
- c.addSource("s_1.4.7/s.sol", "contract SSeven {} ");
+ c.addSource("a/a.sol", "import \"s/s.sol\"; contract A is SSix {} pragma solidity >=0.0;");
+ 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;");
BOOST_CHECK(c.compile());
}
diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp
index 8d1a1d6c..136d72e6 100644
--- a/test/libsolidity/InlineAssembly.cpp
+++ b/test/libsolidity/InlineAssembly.cpp
@@ -87,9 +87,14 @@ BOOST_AUTO_TEST_CASE(simple_instructions)
BOOST_CHECK(successParse("{ dup1 dup1 mul dup1 sub }"));
}
+BOOST_AUTO_TEST_CASE(suicide_selfdestruct)
+{
+ BOOST_CHECK(successParse("{ suicide selfdestruct }"));
+}
+
BOOST_AUTO_TEST_CASE(keywords)
{
- BOOST_CHECK(successParse("{ byte return }"));
+ BOOST_CHECK(successParse("{ byte return address }"));
}
BOOST_AUTO_TEST_CASE(constants)
diff --git a/test/libsolidity/SemVerMatcher.cpp b/test/libsolidity/SemVerMatcher.cpp
new file mode 100644
index 00000000..80bdf16f
--- /dev/null
+++ b/test/libsolidity/SemVerMatcher.cpp
@@ -0,0 +1,223 @@
+/*
+ This file is part of cpp-ethereum.
+
+ cpp-ethereum 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.
+
+ cpp-ethereum 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @author Christian <chris@ethereum.org>
+ * @date 2016
+ * Unit tests for the semantic versioning matcher.
+ */
+
+#include <string>
+#include <vector>
+#include <tuple>
+#include <libsolidity/parsing/Scanner.h>
+#include <libsolidity/analysis/SemVerHandler.h>
+#include "../TestHelper.h"
+
+using namespace std;
+
+namespace dev
+{
+namespace solidity
+{
+namespace test
+{
+
+BOOST_AUTO_TEST_SUITE(SemVerMatcher)
+
+SemVerMatchExpression parseExpression(string const& _input)
+{
+ Scanner scanner{CharStream(_input)};
+ vector<string> literals;
+ vector<Token::Value> tokens;
+ while (scanner.currentToken() != Token::EOS)
+ {
+ auto token = scanner.currentToken();
+ string literal = scanner.currentLiteral();
+ if (literal.empty() && Token::toString(token))
+ literal = Token::toString(token);
+ literals.push_back(literal);
+ tokens.push_back(token);
+ scanner.next();
+ }
+
+ auto expression = SemVerMatchExpressionParser(tokens, literals).parse();
+ BOOST_CHECK_MESSAGE(
+ expression.isValid(),
+ "Expression \"" + _input + "\" did not parse properly."
+ );
+ return expression;
+}
+
+BOOST_AUTO_TEST_CASE(positive_range)
+{
+ // Positive range tests
+ vector<pair<string, string>> tests = {
+ {"*", "1.2.3-foo"},
+ {"1.0.0 - 2.0.0", "1.2.3"},
+ {"1.0.0", "1.0.0"},
+ {">=*", "0.2.4"},
+ {"*", "1.2.3"},
+ {">=1.0.0", "1.0.0"},
+ {">=1.0.0", "1.0.1"},
+ {">=1.0.0", "1.1.0"},
+ {">1.0.0", "1.0.1"},
+ {">1.0.0", "1.1.0"},
+ {"<=2.0.0", "2.0.0"},
+ {"<=2.0.0", "1.9999.9999"},
+ {"<=2.0.0", "0.2.9"},
+ {"<2.0.0", "1.9999.9999"},
+ {"<2.0.0", "0.2.9"},
+ {">= 1.0.0", "1.0.0"},
+ {">= 1.0.0", "1.0.1"},
+ {">= 1.0.0", "1.1.0"},
+ {"> 1.0.0", "1.0.1"},
+ {"> 1.0.0", "1.1.0"},
+ {"<= 2.0.0", "2.0.0"},
+ {"<= 2.0.0", "1.9999.9999"},
+ {"<= 2.0.0", "0.2.9"},
+ {"< 2.0.0", "1.9999.9999"},
+ {"<\t2.0.0", "0.2.9"},
+ {">=0.1.97", "0.1.97"},
+ {"0.1.20 || 1.2.4", "1.2.4"},
+ {">=0.2.3 || <0.0.1", "0.0.0"},
+ {">=0.2.3 || <0.0.1", "0.2.3"},
+ {">=0.2.3 || <0.0.1", "0.2.4"},
+ {"\"2.x.x\"", "2.1.3"},
+ {"1.2.x", "1.2.3"},
+ {"\"1.2.x\" || \"2.x\"", "2.1.3"},
+ {"\"1.2.x\" || \"2.x\"", "1.2.3"},
+ {"x", "1.2.3"},
+ {"2.*.*", "2.1.3"},
+ {"1.2.*", "1.2.3"},
+ {"1.2.* || 2.*", "2.1.3"},
+ {"1.2.* || 2.*", "1.2.3"},
+ {"*", "1.2.3"},
+ {"2", "2.1.2"},
+ {"2.3", "2.3.1"},
+ {"~2.4", "2.4.0"}, // >=2.4.0 <2.5.0
+ {"~2.4", "2.4.5"},
+ {"~1", "1.2.3"}, // >=1.0.0 <2.0.0
+ {"~1.0", "1.0.2"}, // >=1.0.0 <1.1.0,
+ {"~ 1.0", "1.0.2"},
+ {"~ 1.0.3", "1.0.12"},
+ {">=1", "1.0.0"},
+ {">= 1", "1.0.0"},
+ {"<1.2", "1.1.1"},
+ {"< 1.2", "1.1.1"},
+ {"=0.7.x", "0.7.2"},
+ {"<=0.7.x", "0.7.2"},
+ {">=0.7.x", "0.7.2"},
+ {"<=0.7.x", "0.6.2"},
+ {"~1.2.1 >=1.2.3", "1.2.3"},
+ {"~1.2.1 =1.2.3", "1.2.3"},
+ {"~1.2.1 1.2.3", "1.2.3"},
+ {"~1.2.1 >=1.2.3 1.2.3", "1.2.3"},
+ {"~1.2.1 1.2.3 >=1.2.3", "1.2.3"},
+ {">=\"1.2.1\" 1.2.3", "1.2.3"},
+ {"1.2.3 >=1.2.1", "1.2.3"},
+ {">=1.2.3 >=1.2.1", "1.2.3"},
+ {">=1.2.1 >=1.2.3", "1.2.3"},
+ {">=1.2", "1.2.8"},
+ {"^1.2.3", "1.8.1"},
+ {"^0.1.2", "0.1.2"},
+ {"^0.1", "0.1.2"},
+ {"^1.2", "1.4.2"},
+ {"<=1.2.3", "1.2.3-beta"},
+ {">1.2", "1.3.0-beta"},
+ {"<1.2.3", "1.2.3-beta"},
+ {"^1.2 ^1", "1.4.2"}
+ };
+ for (auto const& t: tests)
+ {
+ SemVerVersion version(t.second);
+ SemVerMatchExpression expression = parseExpression(t.first);
+ BOOST_CHECK_MESSAGE(
+ expression.matches(version),
+ "Version \"" + t.second + "\" did not satisfy expression \"" + t.first + "\""
+ );
+ }
+}
+
+BOOST_AUTO_TEST_CASE(negative_range)
+{
+ // Positive range tests
+ vector<pair<string, string>> tests = {
+ {"1.0.0 - 2.0.0", "2.2.3"},
+ {"^1.2.3", "1.2.3-pre"},
+ {"^1.2", "1.2.0-pre"},
+ {"^1.2.3", "1.2.3-beta"},
+ {"=0.7.x", "0.7.0-asdf"},
+ {">=0.7.x", "0.7.0-asdf"},
+ {"1.0.0", "1.0.1"},
+ {">=1.0.0", "0.0.0"},
+ {">=1.0.0", "0.0.1"},
+ {">=1.0.0", "0.1.0"},
+ {">1.0.0", "0.0.1"},
+ {">1.0.0", "0.1.0"},
+ {"<=2.0.0", "3.0.0"},
+ {"<=2.0.0", "2.9999.9999"},
+ {"<=2.0.0", "2.2.9"},
+ {"<2.0.0", "2.9999.9999"},
+ {"<2.0.0", "2.2.9"},
+ {">=0.1.97", "0.1.93"},
+ {"0.1.20 || 1.2.4", "1.2.3"},
+ {">=0.2.3 || <0.0.1", "0.0.3"},
+ {">=0.2.3 || <0.0.1", "0.2.2"},
+ {"\"2.x.x\"", "1.1.3"},
+ {"\"2.x.x\"", "3.1.3"},
+ {"1.2.x", "1.3.3"},
+ {"\"1.2.x\" || \"2.x\"", "3.1.3"},
+ {"\"1.2.x\" || \"2.x\"", "1.1.3"},
+ {"2.*.*", "1.1.3"},
+ {"2.*.*", "3.1.3"},
+ {"1.2.*", "1.3.3"},
+ {"1.2.* || 2.*", "3.1.3"},
+ {"1.2.* || 2.*", "1.1.3"},
+ {"2", "1.1.2"},
+ {"2.3", "2.4.1"},
+ {"~2.4", "2.5.0"}, // >=2.4.0 <2.5.0
+ {"~2.4", "2.3.9"},
+ {"~1", "0.2.3"}, // >=1.0.0 <2.0.0
+ {"~1.0", "1.1.0"}, // >=1.0.0 <1.1.0
+ {"<1", "1.0.0"},
+ {">=1.2", "1.1.1"},
+ {"=0.7.x", "0.8.2"},
+ {">=0.7.x", "0.6.2"},
+ {"<0.7.x", "0.7.2"},
+ {"=1.2.3", "1.2.3-beta"},
+ {">1.2", "1.2.8"},
+ {"^1.2.3", "2.0.0-alpha"},
+ {"^1.2.3", "1.2.2"},
+ {"^1.2", "1.1.9"}
+ };
+ for (auto const& t: tests)
+ {
+ SemVerVersion version(t.second);
+ SemVerMatchExpression expression = parseExpression(t.first);
+ BOOST_CHECK_MESSAGE(
+ !expression.matches(version),
+ "Version \"" + t.second + "\" did satisfy expression \"" + t.first + "\" " +
+ "(although it should not)"
+ );
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+}
+}
+} // end namespaces
diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp
index 77b39978..073d7d97 100644
--- a/test/libsolidity/SolidityABIJSON.cpp
+++ b/test/libsolidity/SolidityABIJSON.cpp
@@ -35,11 +35,11 @@ namespace test
class JSONInterfaceChecker
{
public:
- JSONInterfaceChecker(): m_compilerStack(false) {}
+ JSONInterfaceChecker(): m_compilerStack() {}
void checkInterface(std::string const& _code, std::string const& _expectedInterfaceString)
{
- ETH_TEST_REQUIRE_NO_THROW(m_compilerStack.parse(_code), "Parsing contract failed");
+ ETH_TEST_REQUIRE_NO_THROW(m_compilerStack.parse("pragma solidity >=0.0;\n" + _code), "Parsing contract failed");
std::string generatedInterfaceString = m_compilerStack.metadata("", DocumentationType::ABIInterface);
Json::Value generatedInterface;
m_reader.parse(generatedInterfaceString, generatedInterface);
@@ -68,6 +68,7 @@ BOOST_AUTO_TEST_CASE(basic_test)
{
"name": "f",
"constant": false,
+ "payable" : false,
"type": "function",
"inputs": [
{
@@ -107,6 +108,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods)
{
"name": "f",
"constant": false,
+ "payable" : false,
"type": "function",
"inputs": [
{
@@ -124,6 +126,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods)
{
"name": "g",
"constant": false,
+ "payable" : false,
"type": "function",
"inputs": [
{
@@ -153,6 +156,7 @@ BOOST_AUTO_TEST_CASE(multiple_params)
{
"name": "f",
"constant": false,
+ "payable" : false,
"type": "function",
"inputs": [
{
@@ -188,6 +192,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods_order)
{
"name": "c",
"constant": false,
+ "payable" : false,
"type": "function",
"inputs": [
{
@@ -205,6 +210,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods_order)
{
"name": "f",
"constant": false,
+ "payable" : false,
"type": "function",
"inputs": [
{
@@ -235,6 +241,7 @@ BOOST_AUTO_TEST_CASE(const_function)
{
"name": "foo",
"constant": false,
+ "payable" : false,
"type": "function",
"inputs": [
{
@@ -256,6 +263,7 @@ BOOST_AUTO_TEST_CASE(const_function)
{
"name": "boo",
"constant": true,
+ "payable" : false,
"type": "function",
"inputs": [{
"name": "a",
@@ -273,15 +281,6 @@ BOOST_AUTO_TEST_CASE(const_function)
checkInterface(sourceCode, interface);
}
-BOOST_AUTO_TEST_CASE(exclude_fallback_function)
-{
- char const* sourceCode = "contract test { function() {} }";
-
- char const* interface = "[]";
-
- checkInterface(sourceCode, interface);
-}
-
BOOST_AUTO_TEST_CASE(events)
{
char const* sourceCode = "contract test {\n"
@@ -293,6 +292,7 @@ BOOST_AUTO_TEST_CASE(events)
{
"name": "f",
"constant": false,
+ "payable" : false,
"type": "function",
"inputs": [
{
@@ -370,6 +370,7 @@ BOOST_AUTO_TEST_CASE(inherited)
{
"name": "baseFunction",
"constant": false,
+ "payable" : false,
"type": "function",
"inputs":
[{
@@ -385,6 +386,7 @@ BOOST_AUTO_TEST_CASE(inherited)
{
"name": "derivedFunction",
"constant": false,
+ "payable" : false,
"type": "function",
"inputs":
[{
@@ -438,6 +440,7 @@ BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one)
{
"name": "f",
"constant": false,
+ "payable" : false,
"type": "function",
"inputs": [
{
@@ -478,6 +481,7 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter)
{
"name": "f",
"constant": false,
+ "payable" : false,
"type": "function",
"inputs": [
{
@@ -545,6 +549,7 @@ BOOST_AUTO_TEST_CASE(return_param_in_abi)
[
{
"constant" : false,
+ "payable" : false,
"inputs" : [],
"name" : "ret",
"outputs" : [
@@ -582,6 +587,7 @@ BOOST_AUTO_TEST_CASE(strings_and_arrays)
[
{
"constant" : false,
+ "payable" : false,
"name": "f",
"inputs": [
{ "name": "a", "type": "string" },
@@ -609,6 +615,7 @@ BOOST_AUTO_TEST_CASE(library_function)
[
{
"constant" : false,
+ "payable" : false,
"name": "f",
"inputs": [
{ "name": "b", "type": "test.StructType storage" },
@@ -626,6 +633,76 @@ BOOST_AUTO_TEST_CASE(library_function)
checkInterface(sourceCode, interface);
}
+BOOST_AUTO_TEST_CASE(include_fallback_function)
+{
+ char const* sourceCode = R"(
+ contract test {
+ function() {}
+ }
+ )";
+
+ char const* interface = R"(
+ [
+ {
+ "payable": false,
+ "type" : "fallback"
+ }
+ ]
+ )";
+ checkInterface(sourceCode, interface);
+}
+
+BOOST_AUTO_TEST_CASE(payable_function)
+{
+ char const* sourceCode = R"(
+ contract test {
+ function f() {}
+ function g() payable {}
+ }
+ )";
+
+ char const* interface = R"(
+ [
+ {
+ "constant" : false,
+ "payable": false,
+ "inputs": [],
+ "name": "f",
+ "outputs": [],
+ "type" : "function"
+ },
+ {
+ "constant" : false,
+ "payable": true,
+ "inputs": [],
+ "name": "g",
+ "outputs": [],
+ "type" : "function"
+ }
+ ]
+ )";
+ checkInterface(sourceCode, interface);
+}
+
+BOOST_AUTO_TEST_CASE(payable_fallback_unction)
+{
+ char const* sourceCode = R"(
+ contract test {
+ function () payable {}
+ }
+ )";
+
+ char const* interface = R"(
+ [
+ {
+ "payable": true,
+ "type" : "fallback"
+ }
+ ]
+ )";
+ checkInterface(sourceCode, interface);
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index 8dcc878e..155f117f 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -21,14 +21,15 @@
* Unit tests for the solidity expression compiler, testing the behaviour of the code.
*/
+#include <functional>
#include <string>
#include <tuple>
#include <boost/test/unit_test.hpp>
-#include <libdevcore/Hash.h>
#include <libsolidity/interface/Exceptions.h>
#include <test/libsolidity/SolidityExecutionFramework.h>
using namespace std;
+using namespace std::placeholders;
namespace dev
{
@@ -1259,7 +1260,7 @@ BOOST_AUTO_TEST_CASE(multiple_elementary_accessors)
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("data()") == encodeArgs(8));
BOOST_CHECK(callContractFunction("name()") == encodeArgs("Celina"));
- BOOST_CHECK(callContractFunction("a_hash()") == encodeArgs(dev::sha3(bytes(1, 0x7b))));
+ BOOST_CHECK(callContractFunction("a_hash()") == encodeArgs(dev::keccak256(bytes(1, 0x7b))));
BOOST_CHECK(callContractFunction("an_address()") == encodeArgs(toBigEndian(u160(0x1337))));
BOOST_CHECK(callContractFunction("super_secret_data()") == bytes());
}
@@ -1319,7 +1320,7 @@ BOOST_AUTO_TEST_CASE(balance)
BOOST_AUTO_TEST_CASE(blockchain)
{
char const* sourceCode = "contract test {\n"
- " function someInfo() returns (uint256 value, address coinbase, uint256 blockNumber) {\n"
+ " function someInfo() payable returns (uint256 value, address coinbase, uint256 blockNumber) {\n"
" value = msg.value;\n"
" coinbase = block.coinbase;\n"
" blockNumber = block.number;\n"
@@ -1341,7 +1342,7 @@ BOOST_AUTO_TEST_CASE(msg_sig)
}
)";
compileAndRun(sourceCode);
- BOOST_CHECK(callContractFunctionWithValue("foo(uint256)", 13) == encodeArgs(asString(FixedHash<4>(dev::sha3("foo(uint256)")).asBytes())));
+ BOOST_CHECK(callContractFunction("foo(uint256)") == encodeArgs(asString(FixedHash<4>(dev::keccak256("foo(uint256)")).asBytes())));
}
BOOST_AUTO_TEST_CASE(msg_sig_after_internal_call_is_same)
@@ -1357,7 +1358,7 @@ BOOST_AUTO_TEST_CASE(msg_sig_after_internal_call_is_same)
}
)";
compileAndRun(sourceCode);
- BOOST_CHECK(callContractFunctionWithValue("foo(uint256)", 13) == encodeArgs(asString(FixedHash<4>(dev::sha3("foo(uint256)")).asBytes())));
+ BOOST_CHECK(callContractFunction("foo(uint256)") == encodeArgs(asString(FixedHash<4>(dev::keccak256("foo(uint256)")).asBytes())));
}
BOOST_AUTO_TEST_CASE(now)
@@ -1525,8 +1526,10 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_greater_size)
}
})";
compileAndRun(sourceCode);
- BOOST_CHECK(callContractFunction("UintToBytes(uint16)", u256("0x6162")) ==
- encodeArgs(string("\0\0\0\0\0\0ab", 8)));
+ BOOST_CHECK(
+ callContractFunction("UintToBytes(uint16)", u256("0x6162")) ==
+ encodeArgs(string("\0\0\0\0\0\0ab", 8))
+ );
}
BOOST_AUTO_TEST_CASE(send_ether)
@@ -1683,7 +1686,7 @@ BOOST_AUTO_TEST_CASE(sha3)
compileAndRun(sourceCode);
auto f = [&](u256 const& _x) -> u256
{
- return dev::sha3(toBigEndian(_x));
+ return dev::keccak256(toBigEndian(_x));
};
testSolidityAgainstCpp("a(bytes32)", f, u256(4));
testSolidityAgainstCpp("a(bytes32)", f, u256(5));
@@ -1698,9 +1701,15 @@ BOOST_AUTO_TEST_CASE(sha256)
" }\n"
"}\n";
compileAndRun(sourceCode);
- auto f = [&](u256 const& _input) -> u256
+ auto f = [&](u256 const& _x) -> bytes
{
- return dev::sha256(dev::ref(toBigEndian(_input)));
+ if (_x == u256(4))
+ return fromHex("e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f");
+ if (_x == u256(5))
+ return fromHex("96de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c47");
+ if (_x == u256(-1))
+ return fromHex("af9613760f72635fbdb44a5a0a63c39f12af30f950a6ee5c971be188e89c4051");
+ return fromHex("");
};
testSolidityAgainstCpp("a(bytes32)", f, u256(4));
testSolidityAgainstCpp("a(bytes32)", f, u256(5));
@@ -1715,9 +1724,15 @@ BOOST_AUTO_TEST_CASE(ripemd)
" }\n"
"}\n";
compileAndRun(sourceCode);
- auto f = [&](u256 const& _input) -> u256
+ auto f = [&](u256 const& _x) -> bytes
{
- return h256(dev::ripemd160(h256(_input).ref()), h256::AlignLeft); // This should be aligned right. i guess it's fixed elsewhere?
+ if (_x == u256(4))
+ return fromHex("1b0f3c404d12075c68c938f9f60ebea4f74941a0000000000000000000000000");
+ if (_x == u256(5))
+ return fromHex("ee54aa84fc32d8fed5a5fe160442ae84626829d9000000000000000000000000");
+ if (_x == u256(-1))
+ return fromHex("1cf4e77f5966e13e109703cd8a0df7ceda7f3dc3000000000000000000000000");
+ return fromHex("");
};
testSolidityAgainstCpp("a(bytes32)", f, u256(4));
testSolidityAgainstCpp("a(bytes32)", f, u256(5));
@@ -2040,10 +2055,11 @@ BOOST_AUTO_TEST_CASE(contracts_as_addresses)
{
char const* sourceCode = R"(
contract helper {
+ function() payable { } // can receive ether
}
contract test {
helper h;
- function test() { h = new helper(); h.send(5); }
+ function test() payable { h = new helper(); h.send(5); }
function getBalance() returns (uint256 myBalance, uint256 helperBalance) {
myBalance = this.balance;
helperBalance = h.balance;
@@ -2051,6 +2067,7 @@ BOOST_AUTO_TEST_CASE(contracts_as_addresses)
}
)";
compileAndRun(sourceCode, 20);
+ BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 20 - 5);
BOOST_REQUIRE(callContractFunction("getBalance()") == encodeArgs(u256(20 - 5), u256(5)));
}
@@ -2059,7 +2076,7 @@ BOOST_AUTO_TEST_CASE(gas_and_value_basic)
char const* sourceCode = R"(
contract helper {
bool flag;
- function getBalance() returns (uint256 myBalance) {
+ function getBalance() payable returns (uint256 myBalance) {
return this.balance;
}
function setFlag() { flag = true; }
@@ -2067,8 +2084,8 @@ BOOST_AUTO_TEST_CASE(gas_and_value_basic)
}
contract test {
helper h;
- function test() { h = new helper(); }
- function sendAmount(uint amount) returns (uint256 bal) {
+ function test() payable { h = new helper(); }
+ function sendAmount(uint amount) payable returns (uint256 bal) {
return h.getBalance.value(amount)();
}
function outOfGas() returns (bool ret) {
@@ -2084,8 +2101,8 @@ BOOST_AUTO_TEST_CASE(gas_and_value_basic)
compileAndRun(sourceCode, 20);
BOOST_REQUIRE(callContractFunction("sendAmount(uint256)", 5) == encodeArgs(5));
// call to helper should not succeed but amount should be transferred anyway
- BOOST_REQUIRE(callContractFunction("outOfGas()", 5) == bytes());
- BOOST_REQUIRE(callContractFunction("checkState()", 5) == encodeArgs(false, 20 - 5));
+ BOOST_REQUIRE(callContractFunction("outOfGas()") == bytes());
+ BOOST_REQUIRE(callContractFunction("checkState()") == encodeArgs(false, 20 - 5));
}
BOOST_AUTO_TEST_CASE(gas_for_builtin)
@@ -2107,14 +2124,14 @@ BOOST_AUTO_TEST_CASE(value_complex)
{
char const* sourceCode = R"(
contract helper {
- function getBalance() returns (uint256 myBalance) {
+ function getBalance() payable returns (uint256 myBalance) {
return this.balance;
}
}
contract test {
helper h;
- function test() { h = new helper(); }
- function sendAmount(uint amount) returns (uint256 bal) {
+ function test() payable { h = new helper(); }
+ function sendAmount(uint amount) payable returns (uint256 bal) {
var x1 = h.getBalance.value(amount);
uint someStackElement = 20;
var x2 = x1.gas(1000);
@@ -2130,13 +2147,13 @@ BOOST_AUTO_TEST_CASE(value_insane)
{
char const* sourceCode = R"(
contract helper {
- function getBalance() returns (uint256 myBalance) {
+ function getBalance() payable returns (uint256 myBalance) {
return this.balance;
}
}
contract test {
helper h;
- function test() { h = new helper(); }
+ function test() payable { h = new helper(); }
function sendAmount(uint amount) returns (uint256 bal) {
var x1 = h.getBalance.value;
var x2 = x1(amount).gas;
@@ -2155,7 +2172,7 @@ BOOST_AUTO_TEST_CASE(value_for_constructor)
contract Helper {
bytes3 name;
bool flag;
- function Helper(bytes3 x, bool f) {
+ function Helper(bytes3 x, bool f) payable {
name = x;
flag = f;
}
@@ -2164,7 +2181,7 @@ BOOST_AUTO_TEST_CASE(value_for_constructor)
}
contract Main {
Helper h;
- function Main() {
+ function Main() payable {
h = (new Helper).value(10)("abc", true);
}
function getFlag() returns (bool ret) { return h.getFlag(); }
@@ -2338,8 +2355,8 @@ BOOST_AUTO_TEST_CASE(function_modifier)
{
char const* sourceCode = R"(
contract C {
- function getOne() nonFree returns (uint r) { return 1; }
- modifier nonFree { if (msg.value > 0) _ }
+ function getOne() payable nonFree returns (uint r) { return 1; }
+ modifier nonFree { if (msg.value > 0) _; }
}
)";
compileAndRun(sourceCode);
@@ -2351,8 +2368,8 @@ BOOST_AUTO_TEST_CASE(function_modifier_local_variables)
{
char const* sourceCode = R"(
contract C {
- modifier mod1 { var a = 1; var b = 2; _ }
- modifier mod2(bool a) { if (a) return; else _ }
+ modifier mod1 { var a = 1; var b = 2; _; }
+ modifier mod2(bool a) { if (a) return; else _; }
function f(bool a) mod1 mod2(a) returns (uint r) { return 3; }
}
)";
@@ -2365,7 +2382,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_loop)
{
char const* sourceCode = R"(
contract C {
- modifier repeat(uint count) { for (var i = 0; i < count; ++i) _ }
+ modifier repeat(uint count) { for (var i = 0; i < count; ++i) _; }
function f() repeat(10) returns (uint r) { r += 1; }
}
)";
@@ -2377,7 +2394,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_multi_invocation)
{
char const* sourceCode = R"(
contract C {
- modifier repeat(bool twice) { if (twice) _ _ }
+ modifier repeat(bool twice) { if (twice) _; _; }
function f(bool twice) repeat(twice) returns (uint r) { r += 1; }
}
)";
@@ -2388,16 +2405,17 @@ BOOST_AUTO_TEST_CASE(function_modifier_multi_invocation)
BOOST_AUTO_TEST_CASE(function_modifier_multi_with_return)
{
- // Here, the explicit return prevents the second execution
+ // Note that return sets the return variable and jumps to the end of the current function or
+ // modifier code block.
char const* sourceCode = R"(
contract C {
- modifier repeat(bool twice) { if (twice) _ _ }
+ modifier repeat(bool twice) { if (twice) _; _; }
function f(bool twice) repeat(twice) returns (uint r) { r += 1; return r; }
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(1));
- BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(1));
+ BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(2));
}
BOOST_AUTO_TEST_CASE(function_modifier_overriding)
@@ -2405,10 +2423,10 @@ BOOST_AUTO_TEST_CASE(function_modifier_overriding)
char const* sourceCode = R"(
contract A {
function f() mod returns (bool r) { return true; }
- modifier mod { _ }
+ modifier mod { _; }
}
contract C is A {
- modifier mod { }
+ modifier mod { if (false) _; }
}
)";
compileAndRun(sourceCode);
@@ -2424,12 +2442,12 @@ BOOST_AUTO_TEST_CASE(function_modifier_calling_functions_in_creation_context)
function f1() mod2 { data |= 0x1; }
function f2() { data |= 0x20; }
function f3() { }
- modifier mod1 { f2(); _ }
- modifier mod2 { f3(); }
+ modifier mod1 { f2(); _; }
+ modifier mod2 { f3(); if (false) _; }
function getData() returns (uint r) { return data; }
}
contract C is A {
- modifier mod1 { f4(); _ }
+ modifier mod1 { f4(); _; }
function f3() { data |= 0x300; }
function f4() { data |= 0x4000; }
}
@@ -2444,32 +2462,17 @@ BOOST_AUTO_TEST_CASE(function_modifier_for_constructor)
contract A {
uint data;
function A() mod1 { data |= 2; }
- modifier mod1 { data |= 1; _ }
+ modifier mod1 { data |= 1; _; }
function getData() returns (uint r) { return data; }
}
contract C is A {
- modifier mod1 { data |= 4; _ }
+ modifier mod1 { data |= 4; _; }
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("getData()") == encodeArgs(4 | 2));
}
-BOOST_AUTO_TEST_CASE(use_std_lib)
-{
- char const* sourceCode = R"(
- import "mortal";
- contract Icarus is mortal { }
- )";
- m_addStandardSources = true;
- u256 amount(130 * eth::ether);
- compileAndRun(sourceCode, amount, "Icarus");
- u256 balanceBefore = balanceAt(m_sender);
- BOOST_CHECK(callContractFunction("kill()") == bytes());
- BOOST_CHECK(!addressHasCode(m_contractAddress));
- BOOST_CHECK(balanceAt(m_sender) > balanceBefore);
-}
-
BOOST_AUTO_TEST_CASE(crazy_elementary_typenames_on_stack)
{
char const* sourceCode = R"(
@@ -2515,13 +2518,13 @@ BOOST_AUTO_TEST_CASE(fallback_function)
char const* sourceCode = R"(
contract A {
uint data;
- function() returns (uint r) { data = 1; return 2; }
+ function() { data = 1; }
function getData() returns (uint r) { return data; }
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("getData()") == encodeArgs(0));
- BOOST_CHECK(callContractFunction("") == encodeArgs(2));
+ BOOST_CHECK(callContractFunction("") == encodeArgs());
BOOST_CHECK(callContractFunction("getData()") == encodeArgs(1));
}
@@ -2530,28 +2533,42 @@ BOOST_AUTO_TEST_CASE(inherited_fallback_function)
char const* sourceCode = R"(
contract A {
uint data;
- function() returns (uint r) { data = 1; return 2; }
+ function() { data = 1; }
function getData() returns (uint r) { return data; }
}
contract B is A {}
)";
compileAndRun(sourceCode, 0, "B");
BOOST_CHECK(callContractFunction("getData()") == encodeArgs(0));
- BOOST_CHECK(callContractFunction("") == encodeArgs(2));
+ BOOST_CHECK(callContractFunction("") == encodeArgs());
BOOST_CHECK(callContractFunction("getData()") == encodeArgs(1));
}
+BOOST_AUTO_TEST_CASE(default_fallback_throws)
+{
+ char const* sourceCode = R"(
+ contract A {
+ function f() returns (bool) {
+ return this.call();
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs(0));
+}
+
BOOST_AUTO_TEST_CASE(event)
{
char const* sourceCode = R"(
contract ClientReceipt {
event Deposit(address indexed _from, bytes32 indexed _id, uint _value);
- function deposit(bytes32 _id, bool _manually) {
+ function deposit(bytes32 _id, bool _manually) payable {
if (_manually) {
bytes32 s = 0x19dacbf83c5de6658e14cbf7bcae5c15eca2eedecf1c66fbca928e4d351bea0f;
log3(bytes32(msg.value), s, bytes32(msg.sender), _id);
- } else
+ } else {
Deposit(msg.sender, _id, msg.value);
+ }
}
}
)";
@@ -2565,7 +2582,7 @@ BOOST_AUTO_TEST_CASE(event)
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(value)));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 3);
- BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("Deposit(address,bytes32,uint256)")));
+ BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address,bytes32,uint256)")));
BOOST_CHECK_EQUAL(m_logs[0].topics[1], h256(m_sender, h256::AlignRight));
BOOST_CHECK_EQUAL(m_logs[0].topics[2], h256(id));
}
@@ -2587,7 +2604,7 @@ BOOST_AUTO_TEST_CASE(event_no_arguments)
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK(m_logs[0].data.empty());
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
- BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("Deposit()")));
+ BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit()")));
}
BOOST_AUTO_TEST_CASE(event_anonymous)
@@ -2610,7 +2627,7 @@ BOOST_AUTO_TEST_CASE(event_anonymous_with_topics)
char const* sourceCode = R"(
contract ClientReceipt {
event Deposit(address indexed _from, bytes32 indexed _id, uint indexed _value, uint indexed _value2, bytes32 data) anonymous;
- function deposit(bytes32 _id, bool _manually) {
+ function deposit(bytes32 _id, bool _manually) payable {
Deposit(msg.sender, _id, msg.value, 2, "abc");
}
}
@@ -2634,7 +2651,7 @@ BOOST_AUTO_TEST_CASE(event_lots_of_data)
char const* sourceCode = R"(
contract ClientReceipt {
event Deposit(address _from, bytes32 _id, uint _value, bool _flag);
- function deposit(bytes32 _id) {
+ function deposit(bytes32 _id) payable {
Deposit(msg.sender, _id, msg.value, true);
}
}
@@ -2647,7 +2664,7 @@ BOOST_AUTO_TEST_CASE(event_lots_of_data)
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK(m_logs[0].data == encodeArgs((u160)m_sender, id, value, true));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
- BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("Deposit(address,bytes32,uint256,bool)")));
+ BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address,bytes32,uint256,bool)")));
}
BOOST_AUTO_TEST_CASE(event_really_lots_of_data)
@@ -2664,9 +2681,9 @@ BOOST_AUTO_TEST_CASE(event_really_lots_of_data)
callContractFunction("deposit()");
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
- BOOST_CHECK(m_logs[0].data == encodeArgs(10, 0x60, 15, 4) + FixedHash<4>(dev::sha3("deposit()")).asBytes());
+ BOOST_CHECK(m_logs[0].data == encodeArgs(10, 0x60, 15, 4) + FixedHash<4>(dev::keccak256("deposit()")).asBytes());
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
- BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("Deposit(uint256,bytes,uint256)")));
+ BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(uint256,bytes,uint256)")));
}
BOOST_AUTO_TEST_CASE(event_really_lots_of_data_from_storage)
@@ -2690,7 +2707,7 @@ BOOST_AUTO_TEST_CASE(event_really_lots_of_data_from_storage)
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK(m_logs[0].data == encodeArgs(10, 0x60, 15, 3, string("ABC")));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
- BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("Deposit(uint256,bytes,uint256)")));
+ BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(uint256,bytes,uint256)")));
}
BOOST_AUTO_TEST_CASE(event_indexed_string)
@@ -2721,11 +2738,11 @@ BOOST_AUTO_TEST_CASE(event_indexed_string)
dynx[i] = i;
BOOST_CHECK(m_logs[0].data == bytes());
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 3);
- BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::sha3(dynx));
- BOOST_CHECK_EQUAL(m_logs[0].topics[2], dev::sha3(
+ BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(dynx));
+ BOOST_CHECK_EQUAL(m_logs[0].topics[2], dev::keccak256(
encodeArgs(u256(4), u256(5), u256(6), u256(7))
));
- BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("E(string,uint256[4])")));
+ BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(string,uint256[4])")));
}
BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one)
@@ -2767,7 +2784,7 @@ BOOST_AUTO_TEST_CASE(sha3_multiple_arguments)
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("foo(uint256,uint256,uint256)", 10, 12, 13) == encodeArgs(
- dev::sha3(
+ dev::keccak256(
toBigEndian(u256(10)) +
toBigEndian(u256(12)) +
toBigEndian(u256(13)))));
@@ -2785,7 +2802,7 @@ BOOST_AUTO_TEST_CASE(sha3_multiple_arguments_with_numeric_literals)
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("foo(uint256,uint16)", 10, 12) == encodeArgs(
- dev::sha3(
+ dev::keccak256(
toBigEndian(u256(10)) +
bytes{0x0, 0xc} +
bytes(1, 0x91))));
@@ -2806,10 +2823,10 @@ BOOST_AUTO_TEST_CASE(sha3_multiple_arguments_with_string_literals)
})";
compileAndRun(sourceCode);
- BOOST_CHECK(callContractFunction("foo()") == encodeArgs(dev::sha3("foo")));
+ BOOST_CHECK(callContractFunction("foo()") == encodeArgs(dev::keccak256("foo")));
BOOST_CHECK(callContractFunction("bar(uint256,uint16)", 10, 12) == encodeArgs(
- dev::sha3(
+ dev::keccak256(
toBigEndian(u256(10)) +
bytes{0x0, 0xc} +
bytes(1, 0x91) +
@@ -2851,7 +2868,27 @@ BOOST_AUTO_TEST_CASE(iterated_sha3_with_bytes)
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("foo()") == encodeArgs(
- u256(dev::sha3(bytes{'b'} + dev::sha3("xyz").asBytes() + bytes{'a'}))
+ u256(dev::keccak256(bytes{'b'} + dev::keccak256("xyz").asBytes() + bytes{'a'}))
+ ));
+}
+
+BOOST_AUTO_TEST_CASE(keccak256_multiple_arguments)
+{
+ char const* sourceCode = R"(
+ contract c {
+ function foo(uint a, uint b, uint c) returns (bytes32 d)
+ {
+ d = keccak256(a, b, c);
+ }
+ })";
+ compileAndRun(sourceCode);
+
+ BOOST_CHECK(callContractFunction("foo(uint256,uint256,uint256)", 10, 12, 13) == encodeArgs(
+ dev::keccak256(
+ toBigEndian(u256(10)) +
+ toBigEndian(u256(12)) +
+ toBigEndian(u256(13))
+ )
));
}
@@ -2860,9 +2897,10 @@ BOOST_AUTO_TEST_CASE(generic_call)
char const* sourceCode = R"**(
contract receiver {
uint public received;
- function receive(uint256 x) { received = x; }
+ function receive(uint256 x) payable { received = x; }
}
contract sender {
+ function sender() payable {}
function doSend(address rec) returns (uint d)
{
bytes4 signature = bytes4(bytes32(sha3("receive(uint256)")));
@@ -2883,10 +2921,11 @@ BOOST_AUTO_TEST_CASE(generic_callcode)
char const* sourceCode = R"**(
contract receiver {
uint public received;
- function receive(uint256 x) { received = x; }
+ function receive(uint256 x) payable { received = x; }
}
contract sender {
uint public received;
+ function sender() payable { }
function doSend(address rec) returns (uint d)
{
bytes4 signature = bytes4(bytes32(sha3("receive(uint256)")));
@@ -2916,16 +2955,16 @@ BOOST_AUTO_TEST_CASE(generic_delegatecall)
uint public received;
address public sender;
uint public value;
- function receive(uint256 x) { received = x; sender = msg.sender; value = msg.value; }
+ function receive(uint256 x) payable { received = x; sender = msg.sender; value = msg.value; }
}
contract sender {
uint public received;
address public sender;
uint public value;
- function doSend(address rec)
+ function doSend(address rec) payable
{
bytes4 signature = bytes4(bytes32(sha3("receive(uint256)")));
- rec.delegatecall(signature, 23);
+ if (rec.delegatecall(signature, 23)) {}
}
}
)**";
@@ -2988,15 +3027,15 @@ BOOST_AUTO_TEST_CASE(bytes_from_calldata_to_memory)
{
char const* sourceCode = R"(
contract C {
- function() returns (bytes32) {
+ function f() returns (bytes32) {
return sha3("abc", msg.data);
}
}
)";
compileAndRun(sourceCode);
- bytes calldata1 = bytes(61, 0x22) + bytes(12, 0x12);
+ bytes calldata1 = FixedHash<4>(dev::keccak256("f()")).asBytes() + bytes(61, 0x22) + bytes(12, 0x12);
sendMessage(calldata1, false);
- BOOST_CHECK(m_output == encodeArgs(dev::sha3(bytes{'a', 'b', 'c'} + calldata1)));
+ BOOST_CHECK(m_output == encodeArgs(dev::keccak256(bytes{'a', 'b', 'c'} + calldata1)));
}
BOOST_AUTO_TEST_CASE(call_forward_bytes)
@@ -3010,7 +3049,7 @@ BOOST_AUTO_TEST_CASE(call_forward_bytes)
contract sender {
function sender() { rec = new receiver(); }
function() { savedData = msg.data; }
- function forward() returns (bool) { rec.call(savedData); return true; }
+ function forward() returns (bool) { !rec.call(savedData); return true; }
function clear() returns (bool) { delete savedData; return true; }
function val() returns (uint) { return rec.received(); }
receiver rec;
@@ -3370,8 +3409,8 @@ BOOST_AUTO_TEST_CASE(bytes_in_arguments)
)";
compileAndRun(sourceCode);
- string innercalldata1 = asString(FixedHash<4>(dev::sha3("f(uint256,uint256)")).asBytes() + encodeArgs(8, 9));
- string innercalldata2 = asString(FixedHash<4>(dev::sha3("g(uint256)")).asBytes() + encodeArgs(3));
+ string innercalldata1 = asString(FixedHash<4>(dev::keccak256("f(uint256,uint256)")).asBytes() + encodeArgs(8, 9));
+ string innercalldata2 = asString(FixedHash<4>(dev::keccak256("g(uint256)")).asBytes() + encodeArgs(3));
bytes calldata = encodeArgs(
12, 32 * 4, u256(32 * 4 + 32 + (innercalldata1.length() + 31) / 32 * 32), 13,
u256(innercalldata1.length()), innercalldata1,
@@ -4328,12 +4367,12 @@ BOOST_AUTO_TEST_CASE(external_types_in_calls)
y = this.t1(C1(7));
}
function t1(C1 a) returns (C1) { return a; }
- function() returns (C1) { return C1(9); }
+ function t2() returns (C1) { return C1(9); }
}
)";
compileAndRun(sourceCode, 0, "C");
BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(9), u256(7)));
- BOOST_CHECK(callContractFunction("nonexisting") == encodeArgs(u256(9)));
+ BOOST_CHECK(callContractFunction("t2()") == encodeArgs(u256(9)));
}
BOOST_AUTO_TEST_CASE(proper_order_of_overwriting_of_attributes)
@@ -4606,6 +4645,26 @@ BOOST_AUTO_TEST_CASE(failing_send)
BOOST_REQUIRE(callContractFunction("callHelper(address)", c_helperAddress) == encodeArgs(true, 20));
}
+BOOST_AUTO_TEST_CASE(send_zero_ether)
+{
+ // Sending zero ether to a contract should still invoke the fallback function
+ // (it previously did not because the gas stipend was not provided by the EVM)
+ char const* sourceCode = R"(
+ contract Receiver {
+ function () payable {
+ }
+ }
+ contract Main {
+ function s() returns (bool) {
+ var r = new Receiver();
+ return r.send(0);
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 20, "Main");
+ BOOST_REQUIRE(callContractFunction("s()") == encodeArgs(true));
+}
+
BOOST_AUTO_TEST_CASE(reusing_memory)
{
// Invoke some features that use memory and test that they do not interfere with each other.
@@ -4629,7 +4688,7 @@ BOOST_AUTO_TEST_CASE(reusing_memory)
}
)";
compileAndRun(sourceCode, 0, "Main");
- BOOST_REQUIRE(callContractFunction("f(uint256)", 0x34) == encodeArgs(dev::sha3(dev::toBigEndian(u256(0x34)))));
+ BOOST_REQUIRE(callContractFunction("f(uint256)", 0x34) == encodeArgs(dev::keccak256(dev::toBigEndian(u256(0x34)))));
}
BOOST_AUTO_TEST_CASE(return_string)
@@ -5921,9 +5980,9 @@ BOOST_AUTO_TEST_CASE(version_stamp_for_libraries)
m_optimize = true;
bytes runtimeCode = compileAndRun(sourceCode, 0, "lib");
BOOST_CHECK(runtimeCode.size() >= 8);
- BOOST_CHECK_EQUAL(runtimeCode[0], int(eth::Instruction::PUSH6)); // might change once we switch to 1.x.x
- BOOST_CHECK_EQUAL(runtimeCode[1], 3); // might change once we switch away from x.3.x
- BOOST_CHECK_EQUAL(runtimeCode[7], int(eth::Instruction::POP));
+ BOOST_CHECK_EQUAL(runtimeCode[0], int(Instruction::PUSH6)); // might change once we switch to 1.x.x
+ BOOST_CHECK_EQUAL(runtimeCode[1], 4); // might change once we switch away from x.4.x
+ BOOST_CHECK_EQUAL(runtimeCode[7], int(Instruction::POP));
}
BOOST_AUTO_TEST_CASE(contract_binary_dependencies)
@@ -5944,6 +6003,7 @@ BOOST_AUTO_TEST_CASE(reject_ether_sent_to_library)
function f(address x) returns (bool) {
return x.send(1);
}
+ function () payable {}
}
)";
compileAndRun(sourceCode, 0, "lib");
@@ -6206,6 +6266,27 @@ BOOST_AUTO_TEST_CASE(addmod_mulmod)
BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(0)));
}
+BOOST_AUTO_TEST_CASE(divisiod_by_zero)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function div(uint a, uint b) returns (uint) {
+ return a / b;
+ }
+ function mod(uint a, uint b) returns (uint) {
+ return a % b;
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callContractFunction("div(uint256,uint256)", 7, 2) == encodeArgs(u256(3)));
+ // throws
+ BOOST_CHECK(callContractFunction("div(uint256,uint256)", 7, 0) == encodeArgs());
+ BOOST_CHECK(callContractFunction("mod(uint256,uint256)", 7, 2) == encodeArgs(u256(1)));
+ // throws
+ BOOST_CHECK(callContractFunction("mod(uint256,uint256)", 7, 0) == encodeArgs());
+}
+
BOOST_AUTO_TEST_CASE(string_allocation_bug)
{
char const* sourceCode = R"(
@@ -6837,6 +6918,339 @@ BOOST_AUTO_TEST_CASE(skip_dynamic_types_for_structs)
BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(2), u256(6)));
}
+BOOST_AUTO_TEST_CASE(failed_create)
+{
+ char const* sourceCode = R"(
+ contract D { function D() payable {} }
+ contract C {
+ uint public x;
+ function f(uint amount) returns (address) {
+ x++;
+ return (new D).value(amount)();
+ }
+ function stack(uint depth) returns (address) {
+ if (depth < 1024)
+ return this.stack(depth - 1);
+ else
+ return f(0);
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 20, "C");
+ BOOST_CHECK(callContractFunction("f(uint256)", 20) != encodeArgs(u256(0)));
+ BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1)));
+ BOOST_CHECK(callContractFunction("f(uint256)", 20) == encodeArgs());
+ BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1)));
+ BOOST_CHECK(callContractFunction("stack(uint256)", 1023) == encodeArgs());
+ BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1)));
+}
+
+BOOST_AUTO_TEST_CASE(create_dynamic_array_with_zero_length)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f() returns (uint) {
+ var a = new uint[][](0);
+ return 7;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7)));
+}
+
+BOOST_AUTO_TEST_CASE(return_does_not_skip_modifier)
+{
+ char const* sourceCode = R"(
+ contract C {
+ uint public x;
+ modifier setsx {
+ _;
+ x = 9;
+ }
+ function f() setsx returns (uint) {
+ return 2;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0)));
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(2)));
+ BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(9)));
+}
+
+BOOST_AUTO_TEST_CASE(break_in_modifier)
+{
+ char const* sourceCode = R"(
+ contract C {
+ uint public x;
+ modifier run() {
+ for (uint i = 0; i < 10; i++) {
+ _;
+ break;
+ }
+ }
+ function f() run {
+ x++;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0)));
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs());
+ BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1)));
+}
+
+BOOST_AUTO_TEST_CASE(stacked_return_with_modifiers)
+{
+ char const* sourceCode = R"(
+ contract C {
+ uint public x;
+ modifier run() {
+ for (uint i = 0; i < 10; i++) {
+ _;
+ break;
+ }
+ }
+ function f() run {
+ x++;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0)));
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs());
+ BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1)));
+}
+
+BOOST_AUTO_TEST_CASE(mutex)
+{
+ char const* sourceCode = R"(
+ contract mutexed {
+ bool locked;
+ modifier protected {
+ if (locked) throw;
+ locked = true;
+ _;
+ locked = false;
+ }
+ }
+ contract Fund is mutexed {
+ uint shares;
+ function Fund() { shares = msg.value; }
+ function withdraw(uint amount) protected returns (uint) {
+ // NOTE: It is very bad practice to write this function this way.
+ // Please refer to the documentation of how to do this properly.
+ if (amount > shares) throw;
+ if (!msg.sender.call.value(amount)()) throw;
+ shares -= amount;
+ return shares;
+ }
+ function withdrawUnprotected(uint amount) returns (uint) {
+ // NOTE: It is very bad practice to write this function this way.
+ // Please refer to the documentation of how to do this properly.
+ if (amount > shares) throw;
+ if (!msg.sender.call.value(amount)()) throw;
+ shares -= amount;
+ return shares;
+ }
+ }
+ contract Attacker {
+ Fund public fund;
+ uint callDepth;
+ bool protected;
+ function setProtected(bool _protected) { protected = _protected; }
+ function Attacker(Fund _fund) { fund = _fund; }
+ function attack() returns (uint) {
+ callDepth = 0;
+ return attackInternal();
+ }
+ function attackInternal() internal returns (uint) {
+ if (protected)
+ return fund.withdraw(10);
+ else
+ return fund.withdrawUnprotected(10);
+ }
+ function() payable {
+ callDepth++;
+ if (callDepth < 4)
+ attackInternal();
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 500, "Fund");
+ auto fund = m_contractAddress;
+ BOOST_CHECK_EQUAL(balanceAt(fund), 500);
+ compileAndRun(sourceCode, 0, "Attacker", encodeArgs(u160(fund)));
+ BOOST_CHECK(callContractFunction("setProtected(bool)", true) == encodeArgs());
+ BOOST_CHECK(callContractFunction("attack()") == encodeArgs());
+ BOOST_CHECK_EQUAL(balanceAt(fund), 500);
+ BOOST_CHECK(callContractFunction("setProtected(bool)", false) == encodeArgs());
+ BOOST_CHECK(callContractFunction("attack()") == encodeArgs(u256(460)));
+ BOOST_CHECK_EQUAL(balanceAt(fund), 460);
+}
+
+BOOST_AUTO_TEST_CASE(failing_ecrecover_invalid_input)
+{
+ // ecrecover should return zero for malformed input
+ // (v should be 27 or 28, not 1)
+ // Note that the precompile does not return zero but returns nothing.
+ char const* sourceCode = R"(
+ contract C {
+ function f() returns (address) {
+ return ecrecover(bytes32(uint(-1)), 1, 2, 3);
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0)));
+}
+
+BOOST_AUTO_TEST_CASE(calling_nonexisting_contract_throws)
+{
+ char const* sourceCode = R"(
+ contract D { function g(); }
+ contract C {
+ D d = D(0x1212);
+ function f() returns (uint) {
+ d.g();
+ return 7;
+ }
+ function g() returns (uint) {
+ d.g.gas(200)();
+ return 7;
+ }
+ function h() returns (uint) {
+ d.call(); // this does not throw (low-level)
+ return 7;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs());
+ BOOST_CHECK(callContractFunction("g()") == encodeArgs());
+ BOOST_CHECK(callContractFunction("h()") == encodeArgs(u256(7)));
+}
+
+BOOST_AUTO_TEST_CASE(payable_constructor)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function C() payable { }
+ }
+ )";
+ compileAndRun(sourceCode, 27, "C");
+}
+
+BOOST_AUTO_TEST_CASE(payable_function)
+{
+ char const* sourceCode = R"(
+ contract C {
+ uint public a;
+ function f() payable returns (uint) {
+ return msg.value;
+ }
+ function() payable {
+ a = msg.value + 1;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunctionWithValue("f()", 27) == encodeArgs(u256(27)));
+ BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 27);
+ BOOST_CHECK(callContractFunctionWithValue("", 27) == encodeArgs());
+ BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 27 + 27);
+ BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(28)));
+ BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 27 + 27);
+}
+
+BOOST_AUTO_TEST_CASE(payable_function_calls_library)
+{
+ char const* sourceCode = R"(
+ library L {
+ function f() returns (uint) { return 7; }
+ }
+ contract C {
+ function f() payable returns (uint) {
+ return L.f();
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "L");
+ compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{"L", m_contractAddress}});
+ BOOST_CHECK(callContractFunctionWithValue("f()", 27) == encodeArgs(u256(7)));
+}
+
+BOOST_AUTO_TEST_CASE(non_payable_throw)
+{
+ char const* sourceCode = R"(
+ contract C {
+ uint public a;
+ function f() returns (uint) {
+ return msg.value;
+ }
+ function() {
+ a = msg.value + 1;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunctionWithValue("f()", 27) == encodeArgs());
+ BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 0);
+ BOOST_CHECK(callContractFunction("") == encodeArgs());
+ BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(1)));
+ BOOST_CHECK(callContractFunctionWithValue("", 27) == encodeArgs());
+ BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 0);
+ BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(1)));
+ BOOST_CHECK(callContractFunctionWithValue("a()", 27) == encodeArgs());
+ BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 0);
+}
+
+BOOST_AUTO_TEST_CASE(no_nonpayable_circumvention_by_modifier)
+{
+ char const* sourceCode = R"(
+ contract C {
+ modifier tryCircumvent {
+ if (false) _; // avoid the function, we should still not accept ether
+ }
+ function f() tryCircumvent returns (uint) {
+ return msg.value;
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callContractFunctionWithValue("f()", 27) == encodeArgs());
+ BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 0);
+}
+
+BOOST_AUTO_TEST_CASE(mem_resize_is_not_paid_at_call)
+{
+ // This tests that memory resize for return values is not paid during the call, which would
+ // make the gas calculation overly complex. We access the end of the output area before
+ // the call is made.
+ // Tests that this also survives the optimizer.
+ char const* sourceCode = R"(
+ contract C {
+ function f() returns (uint[200]) {}
+ }
+ contract D {
+ function f(C c) returns (uint) { c.f(); return 7; }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ u160 cAddr = m_contractAddress;
+ compileAndRun(sourceCode, 0, "D");
+ BOOST_CHECK(callContractFunction("f(address)", cAddr) == encodeArgs(u256(7)));
+
+ m_optimize = true;
+
+ compileAndRun(sourceCode, 0, "C");
+ u160 cAddrOpt = m_contractAddress;
+ compileAndRun(sourceCode, 0, "D");
+ BOOST_CHECK(callContractFunction("f(address)", cAddrOpt) == encodeArgs(u256(7)));
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/SolidityExecutionFramework.cpp b/test/libsolidity/SolidityExecutionFramework.cpp
index da9cf5f1..02548121 100644
--- a/test/libsolidity/SolidityExecutionFramework.cpp
+++ b/test/libsolidity/SolidityExecutionFramework.cpp
@@ -22,6 +22,7 @@
#include <cstdlib>
#include <boost/test/framework.hpp>
+#include <libdevcore/CommonIO.h>
#include <test/libsolidity/SolidityExecutionFramework.h>
using namespace std;
@@ -29,26 +30,17 @@ using namespace dev;
using namespace dev::solidity;
using namespace dev::solidity::test;
-string getIPCSocketPath()
+namespace // anonymous
{
- string ipcPath;
+ h256 const EmptyTrie("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421");
+}
- size_t argc = boost::unit_test::framework::master_test_suite().argc;
- char** argv = boost::unit_test::framework::master_test_suite().argv;
- for (size_t i = 0; i < argc; i++)
- {
- string arg = argv[i];
- if (arg == "--ipc" && i + 1 < argc)
- {
- ipcPath = argv[i + 1];
- i++;
- }
- }
- if (ipcPath.empty())
- if (auto path = getenv("ETH_TEST_IPC"))
- ipcPath = path;
+string getIPCSocketPath()
+{
+ string ipcPath = dev::test::Options::get().ipcPath;
if (ipcPath.empty())
- BOOST_FAIL("ERROR: ipcPath not set! (use --ipc <path> or the environment variable ETH_TEST_IPC)");
+ BOOST_FAIL("ERROR: ipcPath not set! (use --ipcpath <path> or the environment variable ETH_TEST_IPC)");
+
return ipcPath;
}
@@ -56,9 +48,6 @@ ExecutionFramework::ExecutionFramework() :
m_rpc(RPCSession::instance(getIPCSocketPath())),
m_sender(m_rpc.account(0))
{
- if (g_logVerbosity != -1)
- g_logVerbosity = 0;
-
m_rpc.test_rewindToBlock(0);
}
diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h
index 2b589498..1cd45603 100644
--- a/test/libsolidity/SolidityExecutionFramework.h
+++ b/test/libsolidity/SolidityExecutionFramework.h
@@ -22,25 +22,34 @@
#pragma once
-#include <string>
-#include <tuple>
-#include <fstream>
+#include <functional>
+
#include "../TestHelper.h"
#include "../RPCSession.h"
-#include <libethcore/ABI.h>
-#include <libethcore/SealEngine.h>
-#include <libethereum/State.h>
-#include <libethereum/Executive.h>
-#include <libethereum/ChainParams.h>
+
+#include <libdevcore/ABI.h>
+#include <libdevcore/FixedHash.h>
+#include <libevmasm/Instruction.h>
+
#include <libsolidity/interface/CompilerStack.h>
#include <libsolidity/interface/Exceptions.h>
-#include <libethcore/BasicAuthority.h>
-#include <libethcore/SealEngine.h>
+#include <libsolidity/interface/SourceReferenceFormatter.h>
namespace dev
{
namespace solidity
{
+ /// An Ethereum address: 20 bytes.
+ /// @NOTE This is not endian-specific; it's just a bunch of bytes.
+ using Address = h160;
+
+ // The various denominations; here for ease of use where needed within code.
+ static const u256 ether = exp10<18>();
+ static const u256 finney = exp10<15>();
+ static const u256 szabo = exp10<12>();
+ static const u256 shannon = exp10<9>();
+ static const u256 wei = exp10<0>();
+
namespace test
{
@@ -58,9 +67,21 @@ public:
std::map<std::string, Address> const& _libraryAddresses = std::map<std::string, Address>()
)
{
- m_compiler.reset(false, m_addStandardSources);
- m_compiler.addSource("", _sourceCode);
- ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(m_optimize, m_optimizeRuns), "Compiling contract failed");
+ // Silence compiler version warning
+ std::string sourceCode = "pragma solidity >=0.0;\n" + _sourceCode;
+ m_compiler.reset(false);
+ m_compiler.addSource("", sourceCode);
+ if (!m_compiler.compile(m_optimize, m_optimizeRuns))
+ {
+ for (auto const& error: m_compiler.errors())
+ SourceReferenceFormatter::printExceptionInformation(
+ std::cerr,
+ *error,
+ (error->type() == Error::Type::Warning) ? "Warning" : "Error",
+ [&](std::string const& _sourceName) -> solidity::Scanner const& { return m_compiler.scanner(_sourceName); }
+ );
+ BOOST_ERROR("Compiling contract failed");
+ }
eth::LinkerObject obj = m_compiler.object(_contractName);
obj.link(_libraryAddresses);
BOOST_REQUIRE(obj.linkReferences.empty());
@@ -84,7 +105,7 @@ public:
template <class... Args>
bytes const& callContractFunctionWithValue(std::string _sig, u256 const& _value, Args const&... _arguments)
{
- FixedHash<4> hash(dev::sha3(_sig));
+ FixedHash<4> hash(dev::keccak256(_sig));
sendMessage(hash.asBytes() + encodeArgs(_arguments...), false, _value);
return m_output;
}
@@ -271,12 +292,10 @@ protected:
size_t m_optimizeRuns = 200;
bool m_optimize = false;
- bool m_addStandardSources = false;
dev::solidity::CompilerStack m_compiler;
Address m_sender;
Address m_contractAddress;
- eth::EnvInfo m_envInfo;
- u256 const m_gasPrice = 100 * eth::szabo;
+ u256 const m_gasPrice = 100 * szabo;
u256 const m_gas = 100000000;
bytes m_output;
std::vector<LogEntry> m_logs;
diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp
index 967b2907..e9a05745 100644
--- a/test/libsolidity/SolidityExpressionCompiler.cpp
+++ b/test/libsolidity/SolidityExpressionCompiler.cpp
@@ -323,7 +323,15 @@ BOOST_AUTO_TEST_CASE(arithmetics)
byte(Instruction::OR),
byte(Instruction::SUB),
byte(Instruction::ADD),
+ byte(Instruction::DUP2),
+ byte(Instruction::ISZERO),
+ byte(Instruction::PUSH1), 0x2,
+ byte(Instruction::JUMPI),
byte(Instruction::MOD),
+ byte(Instruction::DUP2),
+ byte(Instruction::ISZERO),
+ byte(Instruction::PUSH1), 0x2,
+ byte(Instruction::JUMPI),
byte(Instruction::DIV),
byte(Instruction::MUL)});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
diff --git a/test/libsolidity/SolidityInterface.cpp b/test/libsolidity/SolidityInterface.cpp
deleted file mode 100644
index 9a1c104d..00000000
--- a/test/libsolidity/SolidityInterface.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- This file is part of cpp-ethereum.
-
- cpp-ethereum 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.
-
- cpp-ethereum 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
- */
-/**
- * @author Christian <c@ethdev.com>
- * @date 2015
- * Unit tests for generating source interfaces for Solidity contracts.
- */
-
-#include "../TestHelper.h"
-#include <libsolidity/interface/CompilerStack.h>
-#include <libsolidity/ast/AST.h>
-
-using namespace std;
-
-namespace dev
-{
-namespace solidity
-{
-namespace test
-{
-
-class SolidityInterfaceChecker
-{
-public:
- SolidityInterfaceChecker(): m_compilerStack(false) {}
-
- /// Compiles the given code, generates the interface and parses that again.
- ContractDefinition const& checkInterface(string const& _code, string const& _contractName = "")
- {
- m_code = _code;
- ETH_TEST_REQUIRE_NO_THROW(m_compilerStack.parse(_code), "Parsing failed");
- m_interface = m_compilerStack.metadata("", DocumentationType::ABISolidityInterface);
- ETH_TEST_REQUIRE_NO_THROW(m_reCompiler.parse(m_interface), "Interface parsing failed");
- return m_reCompiler.contractDefinition(_contractName);
- }
-
- string sourcePart(ASTNode const& _node) const
- {
- SourceLocation location = _node.location();
- BOOST_REQUIRE(!location.isEmpty());
- return m_interface.substr(location.start, location.end - location.start);
- }
-
-protected:
- string m_code;
- string m_interface;
- CompilerStack m_compilerStack;
- CompilerStack m_reCompiler;
-};
-
-BOOST_FIXTURE_TEST_SUITE(SolidityInterface, SolidityInterfaceChecker)
-
-BOOST_AUTO_TEST_CASE(empty_contract)
-{
- ContractDefinition const& contract = checkInterface("contract test {}");
- BOOST_CHECK_EQUAL(sourcePart(contract), "contract test{}");
-}
-
-BOOST_AUTO_TEST_CASE(single_function)
-{
- ContractDefinition const& contract = checkInterface(
- "contract test {\n"
- " function f(uint a) returns(uint d) { return a * 7; }\n"
- "}\n");
- BOOST_REQUIRE_EQUAL(1, contract.definedFunctions().size());
- BOOST_CHECK_EQUAL(sourcePart(*contract.definedFunctions().front()),
- "function f(uint256 a)returns(uint256 d);");
-}
-
-BOOST_AUTO_TEST_CASE(single_constant_function)
-{
- ContractDefinition const& contract = checkInterface(
- "contract test { function f(uint a) constant returns(bytes1 x) { 1==2; } }");
- BOOST_REQUIRE_EQUAL(1, contract.definedFunctions().size());
- BOOST_CHECK_EQUAL(sourcePart(*contract.definedFunctions().front()),
- "function f(uint256 a)constant returns(bytes1 x);");
-}
-
-BOOST_AUTO_TEST_CASE(multiple_functions)
-{
- char const* sourceCode = "contract test {\n"
- " function f(uint a) returns(uint d) { return a * 7; }\n"
- " function g(uint b) returns(uint e) { return b * 8; }\n"
- "}\n";
- ContractDefinition const& contract = checkInterface(sourceCode);
- set<string> expectation({"function f(uint256 a)returns(uint256 d);",
- "function g(uint256 b)returns(uint256 e);"});
- BOOST_REQUIRE_EQUAL(2, contract.definedFunctions().size());
- BOOST_CHECK(expectation == set<string>({sourcePart(*contract.definedFunctions().at(0)),
- sourcePart(*contract.definedFunctions().at(1))}));
-}
-
-BOOST_AUTO_TEST_CASE(exclude_fallback_function)
-{
- char const* sourceCode = "contract test { function() {} }";
- ContractDefinition const& contract = checkInterface(sourceCode);
- BOOST_CHECK_EQUAL(sourcePart(contract), "contract test{}");
-}
-
-BOOST_AUTO_TEST_CASE(events)
-{
- char const* sourceCode = "contract test {\n"
- " function f(uint a) returns(uint d) { return a * 7; }\n"
- " event e1(uint b, address indexed c); \n"
- " event e2(); \n"
- "}\n";
- ContractDefinition const& contract = checkInterface(sourceCode);
- // events should not appear in the Solidity Interface
- BOOST_REQUIRE_EQUAL(0, contract.events().size());
-}
-
-BOOST_AUTO_TEST_CASE(inheritance)
-{
- char const* sourceCode =
- " contract Base { \n"
- " function baseFunction(uint p) returns (uint i) { return p; } \n"
- " event baseEvent(bytes32 indexed evtArgBase); \n"
- " } \n"
- " contract Derived is Base { \n"
- " function derivedFunction(bytes32 p) returns (bytes32 i) { return p; } \n"
- " event derivedEvent(uint indexed evtArgDerived); \n"
- " }";
- ContractDefinition const& contract = checkInterface(sourceCode);
- set<string> expectedFunctions({"function baseFunction(uint256 p)returns(uint256 i);",
- "function derivedFunction(bytes32 p)returns(bytes32 i);"});
- BOOST_REQUIRE_EQUAL(2, contract.definedFunctions().size());
- BOOST_CHECK(expectedFunctions == set<string>({sourcePart(*contract.definedFunctions().at(0)),
- sourcePart(*contract.definedFunctions().at(1))}));
-}
-
-BOOST_AUTO_TEST_CASE(libraries)
-{
- char const* sourceCode = R"(
- library Lib {
- struct Str { uint a; }
- enum E { E1, E2 }
- function f(uint[] x,Str storage y,E z) external;
- }
- )";
- ContractDefinition const& contract = checkInterface(sourceCode);
- BOOST_CHECK(contract.isLibrary());
- set<string> expectedFunctions({"function f(uint256[] x,Lib.Str storage y,Lib.E z);"});
- BOOST_REQUIRE_EQUAL(1, contract.definedFunctions().size());
- BOOST_CHECK(expectedFunctions == set<string>({sourcePart(*contract.definedFunctions().at(0))}));
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-}
-}
-}
diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp
index 7e81bd7e..76141f41 100644
--- a/test/libsolidity/SolidityNameAndTypeResolution.cpp
+++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp
@@ -45,15 +45,17 @@ namespace
{
pair<ASTPointer<SourceUnit>, std::shared_ptr<Error::Type const>>
-parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false)
+parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false, bool _insertVersionPragma = true)
{
+ // Silence compiler version warning
+ string source = _insertVersionPragma ? "pragma solidity >=0.0;\n" + _source : _source;
ErrorList errors;
Parser parser(errors);
ASTPointer<SourceUnit> sourceUnit;
// catch exceptions for a transition period
try
{
- sourceUnit = parser.parse(std::make_shared<Scanner>(CharStream(_source)));
+ sourceUnit = parser.parse(std::make_shared<Scanner>(CharStream(source)));
if(!sourceUnit)
return make_pair(sourceUnit, nullptr);
@@ -152,7 +154,7 @@ static FunctionTypePointer retrieveFunctionBySignature(
std::string const& _signature
)
{
- FixedHash<4> hash(dev::sha3(_signature));
+ FixedHash<4> hash(dev::keccak256(_signature));
return _contract->interfaceFunctions()[hash];
}
@@ -445,8 +447,8 @@ BOOST_AUTO_TEST_CASE(function_no_implementation)
"}\n";
ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed");
std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->nodes();
- ContractDefinition* contract = dynamic_cast<ContractDefinition*>(nodes[0].get());
- BOOST_CHECK(contract);
+ ContractDefinition* contract = dynamic_cast<ContractDefinition*>(nodes[1].get());
+ BOOST_REQUIRE(contract);
BOOST_CHECK(!contract->annotation().isFullyImplemented);
BOOST_CHECK(!contract->definedFunctions()[0]->isImplemented());
}
@@ -460,12 +462,12 @@ BOOST_AUTO_TEST_CASE(abstract_contract)
)";
ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed");
std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->nodes();
- ContractDefinition* base = dynamic_cast<ContractDefinition*>(nodes[0].get());
- ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[1].get());
- BOOST_CHECK(base);
+ ContractDefinition* base = dynamic_cast<ContractDefinition*>(nodes[1].get());
+ ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[2].get());
+ BOOST_REQUIRE(base);
BOOST_CHECK(!base->annotation().isFullyImplemented);
BOOST_CHECK(!base->definedFunctions()[0]->isImplemented());
- BOOST_CHECK(derived);
+ BOOST_REQUIRE(derived);
BOOST_CHECK(derived->annotation().isFullyImplemented);
BOOST_CHECK(derived->definedFunctions()[0]->isImplemented());
}
@@ -479,8 +481,8 @@ BOOST_AUTO_TEST_CASE(abstract_contract_with_overload)
)";
ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed");
std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->nodes();
- ContractDefinition* base = dynamic_cast<ContractDefinition*>(nodes[0].get());
- ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[1].get());
+ ContractDefinition* base = dynamic_cast<ContractDefinition*>(nodes[1].get());
+ ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[2].get());
BOOST_REQUIRE(base);
BOOST_CHECK(!base->annotation().isFullyImplemented);
BOOST_REQUIRE(derived);
@@ -527,9 +529,9 @@ BOOST_AUTO_TEST_CASE(abstract_contract_constructor_args_not_provided)
)";
ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name resolving failed");
std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->nodes();
- BOOST_CHECK_EQUAL(nodes.size(), 3);
- ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[2].get());
- BOOST_CHECK(derived);
+ BOOST_CHECK_EQUAL(nodes.size(), 4);
+ ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[3].get());
+ BOOST_REQUIRE(derived);
BOOST_CHECK(!derived->annotation().isFullyImplemented);
}
@@ -553,9 +555,9 @@ BOOST_AUTO_TEST_CASE(implement_abstract_via_constructor)
)";
ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name resolving failed");
std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->nodes();
- BOOST_CHECK_EQUAL(nodes.size(), 2);
- ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[1].get());
- BOOST_CHECK(derived);
+ BOOST_CHECK_EQUAL(nodes.size(), 3);
+ ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[2].get());
+ BOOST_REQUIRE(derived);
BOOST_CHECK(!derived->annotation().isFullyImplemented);
}
@@ -857,8 +859,8 @@ BOOST_AUTO_TEST_CASE(function_modifier_invocation)
char const* text = R"(
contract B {
function f() mod1(2, true) mod2("0123456") { }
- modifier mod1(uint a, bool b) { if (b) _ }
- modifier mod2(bytes7 a) { while (a == "1234567") _ }
+ modifier mod1(uint a, bool b) { if (b) _; }
+ modifier mod2(bytes7 a) { while (a == "1234567") _; }
}
)";
BOOST_CHECK(success(text));
@@ -869,7 +871,7 @@ BOOST_AUTO_TEST_CASE(invalid_function_modifier_type)
char const* text = R"(
contract B {
function f() mod1(true) { }
- modifier mod1(uint a) { if (a > 0) _ }
+ modifier mod1(uint a) { if (a > 0) _; }
}
)";
BOOST_CHECK(expectError(text) == Error::Type::TypeError);
@@ -880,8 +882,8 @@ BOOST_AUTO_TEST_CASE(function_modifier_invocation_parameters)
char const* text = R"(
contract B {
function f(uint8 a) mod1(a, true) mod2(r) returns (bytes7 r) { }
- modifier mod1(uint a, bool b) { if (b) _ }
- modifier mod2(bytes7 a) { while (a == "1234567") _ }
+ modifier mod1(uint a, bool b) { if (b) _; }
+ modifier mod2(bytes7 a) { while (a == "1234567") _; }
}
)";
BOOST_CHECK(success(text));
@@ -892,7 +894,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_invocation_local_variables)
char const* text = R"(
contract B {
function f() mod(x) { uint x = 7; }
- modifier mod(uint a) { if (a > 0) _ }
+ modifier mod(uint a) { if (a > 0) _; }
}
)";
BOOST_CHECK(success(text));
@@ -901,8 +903,8 @@ BOOST_AUTO_TEST_CASE(function_modifier_invocation_local_variables)
BOOST_AUTO_TEST_CASE(legal_modifier_override)
{
char const* text = R"(
- contract A { modifier mod(uint a) {} }
- contract B is A { modifier mod(uint a) {} }
+ contract A { modifier mod(uint a) { _; } }
+ contract B is A { modifier mod(uint a) { _; } }
)";
BOOST_CHECK(success(text));
}
@@ -910,8 +912,8 @@ BOOST_AUTO_TEST_CASE(legal_modifier_override)
BOOST_AUTO_TEST_CASE(illegal_modifier_override)
{
char const* text = R"(
- contract A { modifier mod(uint a) {} }
- contract B is A { modifier mod(uint8 a) {} }
+ contract A { modifier mod(uint a) { _; } }
+ contract B is A { modifier mod(uint8 a) { _; } }
)";
BOOST_CHECK(expectError(text) == Error::Type::TypeError);
}
@@ -919,8 +921,8 @@ BOOST_AUTO_TEST_CASE(illegal_modifier_override)
BOOST_AUTO_TEST_CASE(modifier_overrides_function)
{
char const* text = R"(
- contract A { modifier mod(uint a) {} }
- contract B is A { function mod(uint a) {} }
+ contract A { modifier mod(uint a) { _; } }
+ contract B is A { function mod(uint a) { } }
)";
BOOST_CHECK(expectError(text) == Error::Type::TypeError);
}
@@ -928,8 +930,8 @@ BOOST_AUTO_TEST_CASE(modifier_overrides_function)
BOOST_AUTO_TEST_CASE(function_overrides_modifier)
{
char const* text = R"(
- contract A { function mod(uint a) {} }
- contract B is A { modifier mod(uint a) {} }
+ contract A { function mod(uint a) { } }
+ contract B is A { modifier mod(uint a) { _; } }
)";
BOOST_CHECK(expectError(text) == Error::Type::TypeError);
}
@@ -938,8 +940,8 @@ BOOST_AUTO_TEST_CASE(modifier_returns_value)
{
char const* text = R"(
contract A {
- function f(uint a) mod(2) returns (uint r) {}
- modifier mod(uint a) { return 7; }
+ function f(uint a) mod(2) returns (uint r) { }
+ modifier mod(uint a) { _; return 7; }
}
)";
BOOST_CHECK(expectError(text) == Error::Type::TypeError);
@@ -1102,6 +1104,37 @@ BOOST_AUTO_TEST_CASE(fallback_function_with_arguments)
BOOST_CHECK(expectError(text) == Error::Type::TypeError);
}
+BOOST_AUTO_TEST_CASE(fallback_function_in_library)
+{
+ char const* text = R"(
+ library C {
+ function() {}
+ }
+ )";
+ BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+}
+
+BOOST_AUTO_TEST_CASE(fallback_function_with_return_parameters)
+{
+ char const* text = R"(
+ contract C {
+ function() returns (uint) { }
+ }
+ )";
+ BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+}
+
+BOOST_AUTO_TEST_CASE(fallback_function_with_constant_modifier)
+{
+ char const* text = R"(
+ contract C {
+ uint x;
+ function() constant { x = 2; }
+ }
+ )";
+ BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+}
+
BOOST_AUTO_TEST_CASE(fallback_function_twice)
{
char const* text = R"(
@@ -3823,6 +3856,170 @@ BOOST_AUTO_TEST_CASE(unused_return_value_delegatecall)
BOOST_CHECK(expectError(text, true) == Error::Type::Warning);
}
+BOOST_AUTO_TEST_CASE(modifier_without_underscore)
+{
+ char const* text = R"(
+ contract test {
+ modifier m() {}
+ }
+ )";
+ BOOST_CHECK(expectError(text) == Error::Type::SyntaxError);
+}
+
+BOOST_AUTO_TEST_CASE(payable_in_library)
+{
+ char const* text = R"(
+ library test {
+ function f() payable {}
+ }
+ )";
+ BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+}
+
+BOOST_AUTO_TEST_CASE(payable_external)
+{
+ char const* text = R"(
+ contract test {
+ function f() payable external {}
+ }
+ )";
+ BOOST_CHECK(success(text));
+}
+
+BOOST_AUTO_TEST_CASE(payable_internal)
+{
+ char const* text = R"(
+ contract test {
+ function f() payable internal {}
+ }
+ )";
+ BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+}
+
+BOOST_AUTO_TEST_CASE(payable_private)
+{
+ char const* text = R"(
+ contract test {
+ function f() payable private {}
+ }
+ )";
+ BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+}
+
+BOOST_AUTO_TEST_CASE(illegal_override_payable)
+{
+ char const* text = R"(
+ contract B { function f() payable {} }
+ contract C is B { function f() {} }
+ )";
+ BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+}
+
+BOOST_AUTO_TEST_CASE(illegal_override_payable_nonpayable)
+{
+ char const* text = R"(
+ contract B { function f() {} }
+ contract C is B { function f() payable {} }
+ )";
+ BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+}
+
+BOOST_AUTO_TEST_CASE(payable_constant_conflict)
+{
+ char const* text = R"(
+ contract C { function f() payable constant {} }
+ )";
+ BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+}
+
+BOOST_AUTO_TEST_CASE(calling_payable)
+{
+ char const* text = R"(
+ contract receiver { function pay() payable {} }
+ contract test {
+ funciton f() { (new receiver()).pay.value(10)(); }
+ recevier r = new receiver();
+ function g() { r.pay.value(10)(); }
+ }
+ )";
+ BOOST_CHECK(success(text));
+}
+
+BOOST_AUTO_TEST_CASE(calling_nonpayable)
+{
+ char const* text = R"(
+ contract receiver { function nopay() {} }
+ contract test {
+ function f() { (new receiver()).nopay.value(10)(); }
+ }
+ )";
+ BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+}
+
+BOOST_AUTO_TEST_CASE(non_payable_constructor)
+{
+ char const* text = R"(
+ contract C {
+ function C() { }
+ }
+ contract D {
+ function f() returns (uint) {
+ (new C).value(2)();
+ return 2;
+ }
+ }
+ )";
+ BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+}
+
+BOOST_AUTO_TEST_CASE(warn_nonpresent_pragma)
+{
+ char const* text = "contract C {}";
+ auto sourceAndError = parseAnalyseAndReturnError(text, true, false);
+ BOOST_REQUIRE(!!sourceAndError.second);
+ BOOST_REQUIRE(!!sourceAndError.first);
+ BOOST_CHECK(*sourceAndError.second == Error::Type::Warning);
+}
+
+BOOST_AUTO_TEST_CASE(unsatisfied_version)
+{
+ char const* text = R"(
+ pragma solidity ^99.99.0;
+ )";
+ BOOST_CHECK(expectError(text, true) == Error::Type::SyntaxError);
+}
+
+BOOST_AUTO_TEST_CASE(constant_constructor)
+{
+ char const* text = R"(
+ contract test {
+ function test() constant {}
+ }
+ )";
+ BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
+}
+
+BOOST_AUTO_TEST_CASE(external_constructor)
+{
+ char const* text = R"(
+ contract test {
+ function test() external {}
+ }
+ )";
+ BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
+}
+
+BOOST_AUTO_TEST_CASE(invalid_array_as_statement)
+{
+ char const* text = R"(
+ contract test {
+ struct S { uint x; }
+ function test(uint k) { S[k]; }
+ }
+ )";
+ BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp
index 8c0c2098..1f74e928 100644
--- a/test/libsolidity/SolidityNatspecJSON.cpp
+++ b/test/libsolidity/SolidityNatspecJSON.cpp
@@ -37,7 +37,7 @@ namespace test
class DocumentationChecker
{
public:
- DocumentationChecker(): m_compilerStack(false) {}
+ DocumentationChecker(): m_compilerStack() {}
void checkNatspec(
std::string const& _code,
@@ -46,7 +46,7 @@ public:
)
{
std::string generatedDocumentationString;
- ETH_TEST_REQUIRE_NO_THROW(m_compilerStack.parse(_code), "Parsing failed");
+ ETH_TEST_REQUIRE_NO_THROW(m_compilerStack.parse("pragma solidity >=0.0;\n" + _code), "Parsing failed");
if (_userDocumentation)
generatedDocumentationString = m_compilerStack.metadata("", DocumentationType::NatspecUser);
diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp
index ad573823..562b7859 100644
--- a/test/libsolidity/SolidityOptimizer.cpp
+++ b/test/libsolidity/SolidityOptimizer.cpp
@@ -79,6 +79,8 @@ public:
bytes nonOptimizedOutput = callContractFunction(_sig, _arguments...);
m_contractAddress = m_optimizedContract;
bytes optimizedOutput = callContractFunction(_sig, _arguments...);
+ BOOST_CHECK_MESSAGE(!optimizedOutput.empty(), "No optimized output for " + _sig);
+ BOOST_CHECK_MESSAGE(!nonOptimizedOutput.empty(), "No un-optimized output for " + _sig);
BOOST_CHECK_MESSAGE(nonOptimizedOutput == optimizedOutput, "Computed values do not match."
"\nNon-Optimized: " + toHex(nonOptimizedOutput) +
"\nOptimized: " + toHex(optimizedOutput));
@@ -176,7 +178,7 @@ BOOST_AUTO_TEST_CASE(identities)
}
})";
compileBothVersions(sourceCode);
- compareVersions("f(uint256)", u256(0x12334664));
+ compareVersions("f(int256)", u256(0x12334664));
}
BOOST_AUTO_TEST_CASE(unused_expressions)
@@ -230,6 +232,7 @@ BOOST_AUTO_TEST_CASE(array_copy)
bytes2[] data1;
bytes5[] data2;
function f(uint x) returns (uint l, uint y) {
+ data1.length = msg.data.length;
for (uint i = 0; i < msg.data.length; ++i)
data1[i] = msg.data[i];
data2 = data1;
@@ -241,7 +244,7 @@ BOOST_AUTO_TEST_CASE(array_copy)
compileBothVersions(sourceCode);
compareVersions("f(uint256)", 0);
compareVersions("f(uint256)", 10);
- compareVersions("f(uint256)", 36);
+ compareVersions("f(uint256)", 35);
}
BOOST_AUTO_TEST_CASE(function_calls)
@@ -279,6 +282,8 @@ BOOST_AUTO_TEST_CASE(storage_write_in_loops)
compareVersions("f(uint256)", 36);
}
+// Test disabled with https://github.com/ethereum/solidity/pull/762
+// Information in joining branches is not retained anymore.
BOOST_AUTO_TEST_CASE(retain_information_in_branches)
{
// This tests that the optimizer knows that we already have "z == sha3(y)" inside both branches.
@@ -312,7 +317,8 @@ BOOST_AUTO_TEST_CASE(retain_information_in_branches)
if (_instr == Instruction::SHA3)
numSHA3s++;
});
- BOOST_CHECK_EQUAL(1, numSHA3s);
+// TEST DISABLED - OPTIMIZER IS NOT EFFECTIVE ON THIS ONE ANYMORE
+// BOOST_CHECK_EQUAL(1, numSHA3s);
}
BOOST_AUTO_TEST_CASE(store_tags_as_unions)
@@ -346,7 +352,7 @@ BOOST_AUTO_TEST_CASE(store_tags_as_unions)
}
)";
compileBothVersions(sourceCode);
- compareVersions("f()", 7, "abc");
+ compareVersions("f(uint256,bytes32)", 7, "abc");
m_optimize = true;
bytes optimizedBytecode = compileAndRun(sourceCode, 0, "test");
@@ -799,7 +805,7 @@ BOOST_AUTO_TEST_CASE(cse_empty_sha3)
Instruction::SHA3
};
checkCSE(input, {
- u256(sha3(bytesConstRef()))
+ u256(dev::keccak256(bytesConstRef()))
});
}
@@ -817,7 +823,7 @@ BOOST_AUTO_TEST_CASE(cse_partial_sha3)
u256(0xabcd) << (256 - 16),
u256(0),
Instruction::MSTORE,
- u256(sha3(bytes{0xab, 0xcd}))
+ u256(dev::keccak256(bytes{0xab, 0xcd}))
});
}
@@ -1174,6 +1180,64 @@ BOOST_AUTO_TEST_CASE(computing_constants)
) == optimizedBytecode.cend());
}
+BOOST_AUTO_TEST_CASE(inconsistency)
+{
+ // This is a test of a bug in the optimizer.
+ char const* sourceCode = R"(
+ contract Inconsistency {
+ struct Value {
+ uint badnum;
+ uint number;
+ }
+
+ struct Container {
+ uint[] valueIndices;
+ Value[] values;
+ }
+
+ Container[] containers;
+ uint[] valueIndices;
+ uint INDEX_ZERO = 0;
+ uint debug;
+
+ // Called with params: containerIndex=0, valueIndex=0
+ function levelIII(uint containerIndex, uint valueIndex) private {
+ Container container = containers[containerIndex];
+ Value value = container.values[valueIndex];
+ debug = container.valueIndices[value.number];
+ }
+ function levelII() private {
+ for (uint i = 0; i < valueIndices.length; i++) {
+ levelIII(INDEX_ZERO, valueIndices[i]);
+ }
+ }
+
+ function trigger() public returns (uint) {
+ containers.length++;
+ Container container = containers[0];
+
+ container.values.push(Value({
+ badnum: 9000,
+ number: 0
+ }));
+
+ container.valueIndices.length++;
+ valueIndices.length++;
+
+ levelII();
+ return debug;
+ }
+
+ function DoNotCallButDoNotDelete() public {
+ levelII();
+ levelIII(1, 2);
+ }
+ }
+ )";
+ compileBothVersions(sourceCode);
+ compareVersions("trigger()");
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp
index 909d18c9..a81a9828 100644
--- a/test/libsolidity/SolidityParser.cpp
+++ b/test/libsolidity/SolidityParser.cpp
@@ -540,7 +540,7 @@ BOOST_AUTO_TEST_CASE(if_statement)
{
char const* text = "contract test {\n"
" function fun(uint256 a) {\n"
- " if (a >= 8) return 2; else { var b = 7; }\n"
+ " if (a >= 8) { return 2; } else { var b = 7; }\n"
" }\n"
"}\n";
BOOST_CHECK(successParse(text));
@@ -681,15 +681,23 @@ BOOST_AUTO_TEST_CASE(placeholder_in_function_context)
BOOST_AUTO_TEST_CASE(modifier)
{
char const* text = "contract c {\n"
- " modifier mod { if (msg.sender == 0) _ }\n"
+ " modifier mod { if (msg.sender == 0) _; }\n"
"}\n";
BOOST_CHECK(successParse(text));
}
+BOOST_AUTO_TEST_CASE(modifier_without_semicolon)
+{
+ char const* text = "contract c {\n"
+ " modifier mod { if (msg.sender == 0) _ }\n"
+ "}\n";
+ BOOST_CHECK(!successParse(text));
+}
+
BOOST_AUTO_TEST_CASE(modifier_arguments)
{
char const* text = "contract c {\n"
- " modifier mod(uint a) { if (msg.sender == a) _ }\n"
+ " modifier mod(uint a) { if (msg.sender == a) _; }\n"
"}\n";
BOOST_CHECK(successParse(text));
}
@@ -697,8 +705,8 @@ BOOST_AUTO_TEST_CASE(modifier_arguments)
BOOST_AUTO_TEST_CASE(modifier_invocation)
{
char const* text = "contract c {\n"
- " modifier mod1(uint a) { if (msg.sender == a) _ }\n"
- " modifier mod2 { if (msg.sender == 2) _ }\n"
+ " modifier mod1(uint a) { if (msg.sender == a) _; }\n"
+ " modifier mod2 { if (msg.sender == 2) _; }\n"
" function f() mod1(7) mod2 { }\n"
"}\n";
BOOST_CHECK(successParse(text));
@@ -1223,6 +1231,16 @@ BOOST_AUTO_TEST_CASE(invalid_fixed_conversion_leading_zeroes_check)
BOOST_CHECK(!successParse(text));
}
+BOOST_AUTO_TEST_CASE(payable_accessor)
+{
+ char const* text = R"(
+ contract test {
+ uint payable x;
+ }
+ )";
+ BOOST_CHECK(!successParse(text));
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/SolidityScanner.cpp b/test/libsolidity/SolidityScanner.cpp
index 10f30b8e..31b75f25 100644
--- a/test/libsolidity/SolidityScanner.cpp
+++ b/test/libsolidity/SolidityScanner.cpp
@@ -275,12 +275,6 @@ BOOST_AUTO_TEST_CASE(time_subdenominations)
BOOST_CHECK_EQUAL(scanner.next(), Token::SubYear);
}
-BOOST_AUTO_TEST_CASE(time_after)
-{
- Scanner scanner(CharStream("after 1"));
- BOOST_CHECK_EQUAL(scanner.currentToken(), Token::After);
-}
-
BOOST_AUTO_TEST_CASE(empty_comment)
{
Scanner scanner(CharStream("//\ncontract{}"));
@@ -291,6 +285,82 @@ BOOST_AUTO_TEST_CASE(empty_comment)
}
+BOOST_AUTO_TEST_CASE(valid_unicode_string_escape)
+{
+ Scanner scanner(CharStream("{ \"\\u00DAnicode\""));
+ BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
+ BOOST_CHECK_EQUAL(scanner.next(), Token::StringLiteral);
+ BOOST_CHECK_EQUAL(scanner.currentLiteral(), std::string("\xC3\x9Anicode", 8));
+}
+
+BOOST_AUTO_TEST_CASE(valid_unicode_string_escape_7f)
+{
+ Scanner scanner(CharStream("{ \"\\u007Fnicode\""));
+ BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
+ BOOST_CHECK_EQUAL(scanner.next(), Token::StringLiteral);
+ BOOST_CHECK_EQUAL(scanner.currentLiteral(), std::string("\x7Fnicode", 7));
+}
+
+BOOST_AUTO_TEST_CASE(valid_unicode_string_escape_7ff)
+{
+ Scanner scanner(CharStream("{ \"\\u07FFnicode\""));
+ BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
+ BOOST_CHECK_EQUAL(scanner.next(), Token::StringLiteral);
+ BOOST_CHECK_EQUAL(scanner.currentLiteral(), std::string("\xDF\xBFnicode", 8));
+}
+
+BOOST_AUTO_TEST_CASE(valid_unicode_string_escape_ffff)
+{
+ Scanner scanner(CharStream("{ \"\\uFFFFnicode\""));
+ BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
+ BOOST_CHECK_EQUAL(scanner.next(), Token::StringLiteral);
+ BOOST_CHECK_EQUAL(scanner.currentLiteral(), std::string("\xEF\xBF\xBFnicode", 9));
+}
+
+BOOST_AUTO_TEST_CASE(invalid_short_unicode_string_escape)
+{
+ Scanner scanner(CharStream("{ \"\\uFFnicode\""));
+ BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
+ BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal);
+}
+
+BOOST_AUTO_TEST_CASE(valid_hex_literal)
+{
+ Scanner scanner(CharStream("{ hex\"00112233FF\""));
+ BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
+ BOOST_CHECK_EQUAL(scanner.next(), Token::StringLiteral);
+ BOOST_CHECK_EQUAL(scanner.currentLiteral(), std::string("\x00\x11\x22\x33\xFF", 5));
+}
+
+BOOST_AUTO_TEST_CASE(invalid_short_hex_literal)
+{
+ Scanner scanner(CharStream("{ hex\"00112233F\""));
+ BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
+ BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal);
+}
+
+BOOST_AUTO_TEST_CASE(invalid_hex_literal_with_space)
+{
+ Scanner scanner(CharStream("{ hex\"00112233FF \""));
+ BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
+ BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal);
+}
+
+BOOST_AUTO_TEST_CASE(invalid_hex_literal_with_wrong_quotes)
+{
+ Scanner scanner(CharStream("{ hex\"00112233FF'"));
+ BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
+ BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal);
+}
+
+BOOST_AUTO_TEST_CASE(invalid_hex_literal_nonhex_string)
+{
+ Scanner scanner(CharStream("{ hex\"hello\""));
+ BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
+ BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal);
+}
+
+
BOOST_AUTO_TEST_SUITE_END()
}