mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge branch 'develop' into p2p
This commit is contained in:
commit
4b9d760d73
@ -3,6 +3,7 @@ cmake_policy(SET CMP0015 NEW)
|
||||
aux_source_directory(. SRC_LIST)
|
||||
list(REMOVE_ITEM SRC_LIST "./createRandomTest.cpp")
|
||||
|
||||
include_directories(${Boost_INCLUDE_DIRS})
|
||||
include_directories(${CRYPTOPP_INCLUDE_DIRS})
|
||||
include_directories(${JSONCPP_INCLUDE_DIRS})
|
||||
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS})
|
||||
|
@ -54,9 +54,18 @@ bytes compileContract(const string& _sourceCode)
|
||||
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
|
||||
{
|
||||
BOOST_REQUIRE_NO_THROW(resolver.resolveNamesAndTypes(*contract));
|
||||
|
||||
}
|
||||
for (ASTPointer<ASTNode> const& node: sourceUnit->getNodes())
|
||||
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
|
||||
{
|
||||
BOOST_REQUIRE_NO_THROW(resolver.checkTypeRequirements(*contract));
|
||||
}
|
||||
for (ASTPointer<ASTNode> const& node: sourceUnit->getNodes())
|
||||
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
|
||||
{
|
||||
Compiler compiler;
|
||||
compiler.compileContract(*contract, {});
|
||||
compiler.compileContract(*contract, {}, map<ContractDefinition const*, bytes const*>{});
|
||||
|
||||
// debug
|
||||
//compiler.streamAssembly(cout);
|
||||
return compiler.getAssembledBytecode();
|
||||
|
@ -176,6 +176,80 @@ BOOST_AUTO_TEST_CASE(nested_loops)
|
||||
testSolidityAgainstCppOnRange(0, nested_loops_cpp, 0, 12);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(for_loop)
|
||||
{
|
||||
char const* sourceCode = "contract test {\n"
|
||||
" function f(uint n) returns(uint nfac) {\n"
|
||||
" nfac = 1;\n"
|
||||
" for (var i = 2; i <= n; i++)\n"
|
||||
" nfac *= i;\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
compileAndRun(sourceCode);
|
||||
|
||||
auto for_loop_cpp = [](u256 const& n) -> u256
|
||||
{
|
||||
u256 nfac = 1;
|
||||
for (auto i = 2; i <= n; i++)
|
||||
nfac *= i;
|
||||
return nfac;
|
||||
};
|
||||
|
||||
testSolidityAgainstCppOnRange(0, for_loop_cpp, 0, 5);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(for_loop_empty)
|
||||
{
|
||||
char const* sourceCode = "contract test {\n"
|
||||
" function f() returns(uint ret) {\n"
|
||||
" ret = 1;\n"
|
||||
" for (;;)\n"
|
||||
" {\n"
|
||||
" ret += 1;\n"
|
||||
" if (ret >= 10) break;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
compileAndRun(sourceCode);
|
||||
|
||||
auto for_loop_empty_cpp = []() -> u256
|
||||
{
|
||||
u256 ret = 1;
|
||||
for (;;)
|
||||
{
|
||||
ret += 1;
|
||||
if (ret >= 10) break;
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
testSolidityAgainstCpp(0, for_loop_empty_cpp);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(for_loop_simple_init_expr)
|
||||
{
|
||||
char const* sourceCode = "contract test {\n"
|
||||
" function f(uint n) returns(uint nfac) {\n"
|
||||
" nfac = 1;\n"
|
||||
" uint256 i;\n"
|
||||
" for (i = 2; i <= n; i++)\n"
|
||||
" nfac *= i;\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
compileAndRun(sourceCode);
|
||||
|
||||
auto for_loop_simple_init_expr_cpp = [](u256 const& n) -> u256
|
||||
{
|
||||
u256 nfac = 1;
|
||||
u256 i;
|
||||
for (i = 2; i <= n; i++)
|
||||
nfac *= i;
|
||||
return nfac;
|
||||
};
|
||||
|
||||
testSolidityAgainstCppOnRange(0, for_loop_simple_init_expr_cpp, 0, 5);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(calling_other_functions)
|
||||
{
|
||||
// note that the index of a function is its index in the sorted sequence of functions
|
||||
@ -1012,6 +1086,49 @@ BOOST_AUTO_TEST_CASE(strings_in_calls)
|
||||
BOOST_CHECK(callContractFunction(0, bytes({0, 'a', 1})) == bytes({0, 'a', 0, 0, 0}));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(constructor_arguments)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract Helper {
|
||||
string3 name;
|
||||
bool flag;
|
||||
function Helper(string3 x, bool f) {
|
||||
name = x;
|
||||
flag = f;
|
||||
}
|
||||
function getName() returns (string3 ret) { return name; }
|
||||
function getFlag() returns (bool ret) { return flag; }
|
||||
}
|
||||
contract Main {
|
||||
Helper h;
|
||||
function Main() {
|
||||
h = new Helper("abc", true);
|
||||
}
|
||||
function getFlag() returns (bool ret) { return h.getFlag(); }
|
||||
function getName() returns (string3 ret) { return h.getName(); }
|
||||
})";
|
||||
compileAndRun(sourceCode, 0, "Main");
|
||||
BOOST_REQUIRE(callContractFunction(0) == bytes({byte(0x01)}));
|
||||
BOOST_REQUIRE(callContractFunction(1) == bytes({'a', 'b', 'c'}));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(functions_called_by_constructor)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract Test {
|
||||
string3 name;
|
||||
bool flag;
|
||||
function Test() {
|
||||
setName("abc");
|
||||
}
|
||||
function getName() returns (string3 ret) { return name; }
|
||||
private:
|
||||
function setName(string3 _name) { name = _name; }
|
||||
})";
|
||||
compileAndRun(sourceCode);
|
||||
BOOST_REQUIRE(callContractFunction(0) == bytes({'a', 'b', 'c'}));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
}
|
||||
|
@ -97,6 +97,15 @@ bytes compileFirstExpression(const string& _sourceCode, vector<vector<string>> _
|
||||
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
|
||||
{
|
||||
BOOST_REQUIRE_NO_THROW(resolver.resolveNamesAndTypes(*contract));
|
||||
}
|
||||
for (ASTPointer<ASTNode> const& node: sourceUnit->getNodes())
|
||||
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
|
||||
{
|
||||
BOOST_REQUIRE_NO_THROW(resolver.checkTypeRequirements(*contract));
|
||||
}
|
||||
for (ASTPointer<ASTNode> const& node: sourceUnit->getNodes())
|
||||
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
|
||||
{
|
||||
FirstExpressionExtractor extractor(*contract);
|
||||
BOOST_REQUIRE(extractor.getExpression() != nullptr);
|
||||
|
||||
|
@ -47,6 +47,9 @@ void parseTextAndResolveNames(std::string const& _source)
|
||||
for (ASTPointer<ASTNode> const& node: sourceUnit->getNodes())
|
||||
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
|
||||
resolver.resolveNamesAndTypes(*contract);
|
||||
for (ASTPointer<ASTNode> const& node: sourceUnit->getNodes())
|
||||
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
|
||||
resolver.checkTypeRequirements(*contract);
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,6 +287,30 @@ BOOST_AUTO_TEST_CASE(assignment_to_struct)
|
||||
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(returns_in_constructor)
|
||||
{
|
||||
char const* text = "contract test {\n"
|
||||
" function test() returns (uint a) {\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(forward_function_reference)
|
||||
{
|
||||
char const* text = "contract First {\n"
|
||||
" function fun() returns (bool ret) {\n"
|
||||
" return Second(1).fun(1, true, 3) > 0;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"contract Second {\n"
|
||||
" function fun(uint a, bool b, uint c) returns (uint ret) {\n"
|
||||
" if (First(2).fun() == true) return 1;\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
}
|
||||
|
@ -49,6 +49,23 @@ ASTPointer<ContractDefinition> parseText(std::string const& _source)
|
||||
BOOST_FAIL("No contract found in source.");
|
||||
return ASTPointer<ContractDefinition>();
|
||||
}
|
||||
|
||||
ASTPointer<ContractDefinition> parseTextExplainError(std::string const& _source)
|
||||
{
|
||||
try
|
||||
{
|
||||
return parseText(_source);
|
||||
}
|
||||
catch (Exception const& exception)
|
||||
{
|
||||
// LTODO: Print the error in a kind of a better way?
|
||||
// In absence of CompilerStack we can't use SourceReferenceFormatter
|
||||
cout << "Exception while parsing: " << diagnostic_information(exception);
|
||||
// rethrow to signal test failure
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -357,6 +374,53 @@ BOOST_AUTO_TEST_CASE(while_loop)
|
||||
BOOST_CHECK_NO_THROW(parseText(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(for_loop_vardef_initexpr)
|
||||
{
|
||||
char const* text = "contract test {\n"
|
||||
" function fun(uint256 a) {\n"
|
||||
" for (uint256 i = 0; i < 10; i++)\n"
|
||||
" { uint256 x = i; break; continue; }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
BOOST_CHECK_NO_THROW(parseTextExplainError(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(for_loop_simple_initexpr)
|
||||
{
|
||||
char const* text = "contract test {\n"
|
||||
" function fun(uint256 a) {\n"
|
||||
" uint256 i =0;\n"
|
||||
" for (i = 0; i < 10; i++)\n"
|
||||
" { uint256 x = i; break; continue; }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
BOOST_CHECK_NO_THROW(parseTextExplainError(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(for_loop_simple_noexpr)
|
||||
{
|
||||
char const* text = "contract test {\n"
|
||||
" function fun(uint256 a) {\n"
|
||||
" uint256 i =0;\n"
|
||||
" for (;;)\n"
|
||||
" { uint256 x = i; break; continue; }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
BOOST_CHECK_NO_THROW(parseTextExplainError(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(for_loop_single_stmt_body)
|
||||
{
|
||||
char const* text = "contract test {\n"
|
||||
" function fun(uint256 a) {\n"
|
||||
" uint256 i =0;\n"
|
||||
" for (i = 0; i < 10; i++)\n"
|
||||
" continue;\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
BOOST_CHECK_NO_THROW(parseTextExplainError(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(if_statement)
|
||||
{
|
||||
char const* text = "contract test {\n"
|
||||
|
40
vm.cpp
40
vm.cpp
@ -262,12 +262,44 @@ eth::OnOpFunc FakeExtVM::simpleTrace()
|
||||
dev::LogOutputStream<eth::VMTraceChannel, false>(true) << o.str();
|
||||
dev::LogOutputStream<eth::VMTraceChannel, false>(false) << " | " << std::dec << ext.depth << " | " << ext.myAddress << " | #" << steps << " | " << std::hex << std::setw(4) << std::setfill('0') << vm.curPC() << " : " << instructionInfo(inst).name << " | " << std::dec << vm.gas() << " | -" << std::dec << gasCost << " | " << newMemSize << "x32" << " ]";
|
||||
|
||||
/*creates json stack trace*/
|
||||
if (eth::VMTraceChannel::verbosity <= g_logVerbosity)
|
||||
{
|
||||
std::ofstream f;
|
||||
f.open("./vmtrace.log", std::ofstream::app);
|
||||
f << o.str();
|
||||
f << " | " << std::dec << ext.depth << " | " << ext.myAddress << " | #" << steps << " | " << std::hex << std::setw(4) << std::setfill('0') << vm.curPC() << " : " << instructionInfo(inst).name << " | " << std::dec << vm.gas() << " | -" << std::dec << gasCost << " | " << newMemSize << "x32";
|
||||
Object o_step;
|
||||
|
||||
/*add the stack*/
|
||||
Array a_stack;
|
||||
for (auto i: vm.stack())
|
||||
a_stack.push_back((string)i);
|
||||
|
||||
o_step.push_back(Pair( "stack", a_stack ));
|
||||
|
||||
/*add the memory*/
|
||||
Array a_mem;
|
||||
for(auto i: vm.memory())
|
||||
a_mem.push_back(i);
|
||||
|
||||
o_step.push_back(Pair("memory", a_mem));
|
||||
|
||||
/*add the storage*/
|
||||
Object storage;
|
||||
for (auto const& i: std::get<2>(ext.addresses.find(ext.myAddress)->second))
|
||||
storage.push_back(Pair( (string)i.first , (string)i.second));
|
||||
|
||||
/*add all the other details*/
|
||||
o_step.push_back(Pair("storage", storage));
|
||||
o_step.push_back(Pair("depth", to_string(ext.depth)));
|
||||
o_step.push_back(Pair("gas", (string)vm.gas()));
|
||||
o_step.push_back(Pair("address", "0x" + toString(ext.myAddress )));
|
||||
o_step.push_back(Pair("step", steps ));
|
||||
o_step.push_back(Pair("pc", (int)vm.curPC()));
|
||||
o_step.push_back(Pair("opcode", instructionInfo(inst).name ));
|
||||
|
||||
/*append the JSON object to the log file*/
|
||||
Value v(o_step);
|
||||
ofstream os( "./stackTrace.json", ofstream::app);
|
||||
os << write_string(v, true) << ",";
|
||||
os.close();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
2
vm.h
2
vm.h
@ -26,7 +26,7 @@ along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <fstream>
|
||||
#include <cstdint>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include "JsonSpiritHeaders.h"
|
||||
#include <json_spirit/json_spirit.h>
|
||||
#include <libdevcore/Log.h>
|
||||
#include <libdevcore/CommonIO.h>
|
||||
#include <libevmcore/Instruction.h>
|
||||
|
Loading…
Reference in New Issue
Block a user