mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge remote-tracking branch 'upstream/develop' into evmjit-develop
This commit is contained in:
commit
2a304c87a3
@ -25,6 +25,11 @@ add_subdirectory(libethereum)
|
||||
add_subdirectory(libevm)
|
||||
add_subdirectory(libnatspec)
|
||||
add_subdirectory(libp2p)
|
||||
|
||||
if (JSCONSOLE)
|
||||
add_subdirectory(libjsengine)
|
||||
endif()
|
||||
|
||||
if (SOLIDITY)
|
||||
add_subdirectory(libsolidity)
|
||||
endif ()
|
||||
@ -41,6 +46,10 @@ include_directories(${Boost_INCLUDE_DIRS})
|
||||
include_directories(${CRYPTOPP_INCLUDE_DIRS})
|
||||
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS})
|
||||
|
||||
if (JSCONSOLE)
|
||||
include_directories(${V8_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
# search for test names and create ctest tests
|
||||
enable_testing()
|
||||
foreach(file ${SRC_LIST})
|
||||
@ -65,14 +74,22 @@ target_link_libraries(testeth ${CURL_LIBRARIES})
|
||||
target_link_libraries(testeth ethereum)
|
||||
target_link_libraries(testeth ethcore)
|
||||
target_link_libraries(testeth secp256k1)
|
||||
|
||||
if (JSCONSOLE)
|
||||
target_link_libraries(testeth jsengine)
|
||||
endif()
|
||||
|
||||
if (SOLIDITY)
|
||||
target_link_libraries(testeth solidity)
|
||||
endif ()
|
||||
|
||||
target_link_libraries(testeth testutils)
|
||||
|
||||
if (GUI AND NOT JUSTTESTS)
|
||||
target_link_libraries(testeth webthree)
|
||||
target_link_libraries(testeth natspec)
|
||||
endif()
|
||||
|
||||
if (JSONRPC)
|
||||
target_link_libraries(testeth web3jsonrpc)
|
||||
target_link_libraries(testeth ${JSON_RPC_CPP_CLIENT_LIBRARIES})
|
||||
|
@ -305,7 +305,7 @@ void ImportTest::checkExpectedState(State const& _stateExpect, State const& _sta
|
||||
|
||||
if (addressOptions.m_bHasStorage)
|
||||
{
|
||||
map<u256, u256> stateStorage = _statePost.storage(a.first);
|
||||
unordered_map<u256, u256> stateStorage = _statePost.storage(a.first);
|
||||
for (auto const& s: _stateExpect.storage(a.first))
|
||||
CHECK(stateStorage[s.first] == s.second,
|
||||
"Check State: " << a.first << ": incorrect storage [" << s.first << "] = " << toHex(stateStorage[s.first]) << ", expected [" << s.first << "] = " << toHex(s.second));
|
||||
|
@ -525,6 +525,49 @@ BOOST_AUTO_TEST_CASE(constructor_abi)
|
||||
checkInterface(sourceCode, interface);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(return_param_in_abi)
|
||||
{
|
||||
// bug #1801
|
||||
char const* sourceCode = R"(
|
||||
contract test {
|
||||
enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
|
||||
function test(ActionChoices param) {}
|
||||
function ret() returns(ActionChoices){
|
||||
ActionChoices action = ActionChoices.GoLeft;
|
||||
return action;
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
char const* interface = R"(
|
||||
[
|
||||
{
|
||||
"constant" : false,
|
||||
"inputs" : [],
|
||||
"name" : "ret",
|
||||
"outputs" : [
|
||||
{
|
||||
"name" : "",
|
||||
"type" : "uint8"
|
||||
}
|
||||
],
|
||||
"type" : "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"name": "param",
|
||||
"type": "uint8"
|
||||
}
|
||||
],
|
||||
"type": "constructor"
|
||||
}
|
||||
]
|
||||
)";
|
||||
checkInterface(sourceCode, interface);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ BOOST_AUTO_TEST_CASE(smoke_test)
|
||||
"}\n";
|
||||
bytes code = compileContract(sourceCode);
|
||||
|
||||
unsigned boilerplateSize = 70;
|
||||
unsigned boilerplateSize = 73;
|
||||
bytes expectation({byte(Instruction::JUMPDEST),
|
||||
byte(Instruction::PUSH1), 0x0, // initialize local variable x
|
||||
byte(Instruction::PUSH1), 0x2,
|
||||
@ -114,8 +114,8 @@ BOOST_AUTO_TEST_CASE(ifStatement)
|
||||
" function f() { bool x; if (x) 77; else if (!x) 78; else 79; }"
|
||||
"}\n";
|
||||
bytes code = compileContract(sourceCode);
|
||||
unsigned shift = 57;
|
||||
unsigned boilerplateSize = 70;
|
||||
unsigned shift = 60;
|
||||
unsigned boilerplateSize = 73;
|
||||
bytes expectation({byte(Instruction::JUMPDEST),
|
||||
byte(Instruction::PUSH1), 0x0,
|
||||
byte(Instruction::DUP1),
|
||||
@ -155,8 +155,8 @@ BOOST_AUTO_TEST_CASE(loops)
|
||||
" function f() { while(true){1;break;2;continue;3;return;4;} }"
|
||||
"}\n";
|
||||
bytes code = compileContract(sourceCode);
|
||||
unsigned shift = 57;
|
||||
unsigned boilerplateSize = 70;
|
||||
unsigned shift = 60;
|
||||
unsigned boilerplateSize = 73;
|
||||
bytes expectation({byte(Instruction::JUMPDEST),
|
||||
byte(Instruction::JUMPDEST),
|
||||
byte(Instruction::PUSH1), 0x1,
|
||||
|
@ -2962,12 +2962,13 @@ BOOST_AUTO_TEST_CASE(bytes_in_arguments)
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
|
||||
string innercalldata1 = asString(FixedHash<4>(dev::sha3("f(uint256,uint256)")).asBytes() + encodeArgs(8, 9));
|
||||
bytes calldata1 = encodeArgs(u256(innercalldata1.length()), 12, innercalldata1, 13);
|
||||
string innercalldata2 = asString(FixedHash<4>(dev::sha3("g(uint256)")).asBytes() + encodeArgs(3));
|
||||
bytes calldata = encodeArgs(
|
||||
12, u256(innercalldata1.length()), u256(innercalldata2.length()), 13,
|
||||
innercalldata1, innercalldata2);
|
||||
12, 32 * 4, u256(32 * 4 + 32 + (innercalldata1.length() + 31) / 32 * 32), 13,
|
||||
u256(innercalldata1.length()), innercalldata1,
|
||||
u256(innercalldata2.length()), innercalldata2);
|
||||
BOOST_CHECK(callContractFunction("test(uint256,bytes,bytes,uint256)", calldata)
|
||||
== encodeArgs(12, (8 + 9) * 3, 13, u256(innercalldata1.length())));
|
||||
}
|
||||
@ -3383,9 +3384,10 @@ BOOST_AUTO_TEST_CASE(external_array_args)
|
||||
compileAndRun(sourceCode);
|
||||
bytes params = encodeArgs(
|
||||
1, 2, 3, 4, 5, 6, 7, 8, // a
|
||||
3, // b.length
|
||||
32 * (8 + 1 + 5 + 1 + 1 + 1), // offset to b
|
||||
21, 22, 23, 24, 25, // c
|
||||
0, 1, 2, // (a,b,c)_index
|
||||
3, // b.length
|
||||
11, 12, 13 // b
|
||||
);
|
||||
BOOST_CHECK(callContractFunction("test(uint256[8],uint256[],uint256[5],uint256,uint256,uint256)", params) == encodeArgs(1, 12, 23));
|
||||
@ -3422,8 +3424,8 @@ BOOST_AUTO_TEST_CASE(bytes_index_access)
|
||||
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
|
||||
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
|
||||
30, 31, 32, 33};
|
||||
BOOST_CHECK(callContractFunction("direct(bytes,uint256)", u256(array.length()), 32, array) == encodeArgs(32));
|
||||
BOOST_CHECK(callContractFunction("storageCopyRead(bytes,uint256)", u256(array.length()), 32, array) == encodeArgs(32));
|
||||
BOOST_CHECK(callContractFunction("direct(bytes,uint256)", 64, 33, u256(array.length()), array) == encodeArgs(33));
|
||||
BOOST_CHECK(callContractFunction("storageCopyRead(bytes,uint256)", 64, 33, u256(array.length()), array) == encodeArgs(33));
|
||||
BOOST_CHECK(callContractFunction("storageWrite()") == encodeArgs(0x193));
|
||||
}
|
||||
|
||||
@ -3474,6 +3476,7 @@ BOOST_AUTO_TEST_CASE(array_copy_calldata_storage)
|
||||
compileAndRun(sourceCode);
|
||||
BOOST_CHECK(callContractFunction("store(uint256[9],uint8[3][])", encodeArgs(
|
||||
21, 22, 23, 24, 25, 26, 27, 28, 29, // a
|
||||
u256(32 * (9 + 1)),
|
||||
4, // size of b
|
||||
1, 2, 3, // b[0]
|
||||
11, 12, 13, // b[1]
|
||||
@ -3502,7 +3505,7 @@ BOOST_AUTO_TEST_CASE(array_copy_nested_array)
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
BOOST_CHECK(callContractFunction("test(uint256[2][])", encodeArgs(
|
||||
3,
|
||||
32, 3,
|
||||
7, 8,
|
||||
9, 10,
|
||||
11, 12
|
||||
@ -3910,6 +3913,90 @@ BOOST_AUTO_TEST_CASE(external_types_in_calls)
|
||||
BOOST_CHECK(callContractFunction("nonexisting") == encodeArgs(u256(9)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(proper_order_of_overwriting_of_attributes)
|
||||
{
|
||||
// bug #1798
|
||||
char const* sourceCode = R"(
|
||||
contract init {
|
||||
function isOk() returns (bool) { return false; }
|
||||
bool public ok = false;
|
||||
}
|
||||
contract fix {
|
||||
function isOk() returns (bool) { return true; }
|
||||
bool public ok = true;
|
||||
}
|
||||
|
||||
contract init_fix is init, fix {
|
||||
function checkOk() returns (bool) { return ok; }
|
||||
}
|
||||
contract fix_init is fix, init {
|
||||
function checkOk() returns (bool) { return ok; }
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "init_fix");
|
||||
BOOST_CHECK(callContractFunction("isOk()") == encodeArgs(true));
|
||||
BOOST_CHECK(callContractFunction("ok()") == encodeArgs(true));
|
||||
|
||||
compileAndRun(sourceCode, 0, "fix_init");
|
||||
BOOST_CHECK(callContractFunction("isOk()") == encodeArgs(false));
|
||||
BOOST_CHECK(callContractFunction("ok()") == encodeArgs(false));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(proper_overwriting_accessor_by_function)
|
||||
{
|
||||
// bug #1798
|
||||
char const* sourceCode = R"(
|
||||
contract attribute {
|
||||
bool ok = false;
|
||||
}
|
||||
contract func {
|
||||
function ok() returns (bool) { return true; }
|
||||
}
|
||||
|
||||
contract attr_func is attribute, func {
|
||||
function checkOk() returns (bool) { return ok(); }
|
||||
}
|
||||
contract func_attr is func, attribute {
|
||||
function checkOk() returns (bool) { return ok; }
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "attr_func");
|
||||
BOOST_CHECK(callContractFunction("ok()") == encodeArgs(true));
|
||||
compileAndRun(sourceCode, 0, "func_attr");
|
||||
BOOST_CHECK(callContractFunction("checkOk()") == encodeArgs(false));
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(overwriting_inheritance)
|
||||
{
|
||||
// bug #1798
|
||||
char const* sourceCode = R"(
|
||||
contract A {
|
||||
function ok() returns (uint) { return 1; }
|
||||
}
|
||||
contract B {
|
||||
function ok() returns (uint) { return 2; }
|
||||
}
|
||||
contract C {
|
||||
uint ok = 6;
|
||||
}
|
||||
contract AB is A, B {
|
||||
function ok() returns (uint) { return 4; }
|
||||
}
|
||||
contract reversedE is C, AB {
|
||||
function checkOk() returns (uint) { return ok(); }
|
||||
}
|
||||
contract E is AB, C {
|
||||
function checkOk() returns (uint) { return ok; }
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "reversedE");
|
||||
BOOST_CHECK(callContractFunction("checkOk()") == encodeArgs(4));
|
||||
compileAndRun(sourceCode, 0, "E");
|
||||
BOOST_CHECK(callContractFunction("checkOk()") == encodeArgs(6));
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
}
|
||||
|
@ -508,6 +508,28 @@ BOOST_AUTO_TEST_CASE(function_external_types)
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(enum_external_type)
|
||||
{
|
||||
// bug #1801
|
||||
ASTPointer<SourceUnit> sourceUnit;
|
||||
char const* text = R"(
|
||||
contract Test {
|
||||
enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
|
||||
function boo(ActionChoices enumArg) external returns (uint ret) {
|
||||
ret = 5;
|
||||
}
|
||||
})";
|
||||
ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseTextAndResolveNames(text), "Parsing and name Resolving failed");
|
||||
for (ASTPointer<ASTNode> const& node: sourceUnit->getNodes())
|
||||
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
|
||||
{
|
||||
auto functions = contract->getDefinedFunctions();
|
||||
if (functions.empty())
|
||||
continue;
|
||||
BOOST_CHECK_EQUAL("boo(uint8)", functions[0]->externalSignature());
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(function_external_call_allowed_conversion)
|
||||
{
|
||||
char const* text = R"(
|
||||
|
@ -83,14 +83,28 @@ public:
|
||||
"\nOptimized: " + toHex(optimizedOutput));
|
||||
}
|
||||
|
||||
AssemblyItems getCSE(AssemblyItems const& _input)
|
||||
AssemblyItems addDummyLocations(AssemblyItems const& _input)
|
||||
{
|
||||
// add dummy locations to each item so that we can check that they are not deleted
|
||||
AssemblyItems input = _input;
|
||||
for (AssemblyItem& item: input)
|
||||
item.setLocation(SourceLocation(1, 3, make_shared<string>("")));
|
||||
return input;
|
||||
}
|
||||
|
||||
eth::CommonSubexpressionEliminator cse;
|
||||
eth::KnownState createInitialState(AssemblyItems const& _input)
|
||||
{
|
||||
eth::KnownState state;
|
||||
for (auto const& item: addDummyLocations(_input))
|
||||
state.feedItem(item);
|
||||
return state;
|
||||
}
|
||||
|
||||
AssemblyItems getCSE(AssemblyItems const& _input, eth::KnownState const& _state = eth::KnownState())
|
||||
{
|
||||
AssemblyItems input = addDummyLocations(_input);
|
||||
|
||||
eth::CommonSubexpressionEliminator cse(_state);
|
||||
BOOST_REQUIRE(cse.feedItems(input.begin(), input.end()) == input.end());
|
||||
AssemblyItems output = cse.getOptimizedItems();
|
||||
|
||||
@ -101,9 +115,13 @@ public:
|
||||
return output;
|
||||
}
|
||||
|
||||
void checkCSE(AssemblyItems const& _input, AssemblyItems const& _expectation)
|
||||
void checkCSE(
|
||||
AssemblyItems const& _input,
|
||||
AssemblyItems const& _expectation,
|
||||
KnownState const& _state = eth::KnownState()
|
||||
)
|
||||
{
|
||||
AssemblyItems output = getCSE(_input);
|
||||
AssemblyItems output = getCSE(_input, _state);
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(_expectation.begin(), _expectation.end(), output.begin(), output.end());
|
||||
}
|
||||
|
||||
@ -113,8 +131,12 @@ public:
|
||||
// Running it four times should be enough for these tests.
|
||||
for (unsigned i = 0; i < 4; ++i)
|
||||
{
|
||||
eth::ControlFlowGraph cfg(output);
|
||||
output = cfg.optimisedItems();
|
||||
ControlFlowGraph cfg(output);
|
||||
AssemblyItems optItems;
|
||||
for (BasicBlock const& block: cfg.optimisedBlocks())
|
||||
copy(output.begin() + block.begin, output.begin() + block.end,
|
||||
back_inserter(optItems));
|
||||
output = move(optItems);
|
||||
}
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(_expectation.begin(), _expectation.end(), output.begin(), output.end());
|
||||
}
|
||||
@ -231,7 +253,8 @@ BOOST_AUTO_TEST_CASE(function_calls)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(cse_intermediate_swap)
|
||||
{
|
||||
eth::CommonSubexpressionEliminator cse;
|
||||
eth::KnownState state;
|
||||
eth::CommonSubexpressionEliminator cse(state);
|
||||
AssemblyItems input{
|
||||
Instruction::SWAP1, Instruction::POP, Instruction::ADD, u256(0), Instruction::SWAP1,
|
||||
Instruction::SLOAD, Instruction::SWAP1, u256(100), Instruction::EXP, Instruction::SWAP1,
|
||||
@ -754,6 +777,30 @@ BOOST_AUTO_TEST_CASE(cse_sha3_twice_same_content_noninterfering_store_in_between
|
||||
BOOST_CHECK_EQUAL(1, count(output.begin(), output.end(), AssemblyItem(Instruction::SHA3)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(cse_with_initially_known_stack)
|
||||
{
|
||||
eth::KnownState state = createInitialState(AssemblyItems{
|
||||
u256(0x12),
|
||||
u256(0x20),
|
||||
Instruction::ADD
|
||||
});
|
||||
AssemblyItems input{
|
||||
u256(0x12 + 0x20)
|
||||
};
|
||||
checkCSE(input, AssemblyItems{Instruction::DUP1}, state);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(cse_equality_on_initially_known_stack)
|
||||
{
|
||||
eth::KnownState state = createInitialState(AssemblyItems{Instruction::DUP1});
|
||||
AssemblyItems input{
|
||||
Instruction::EQ
|
||||
};
|
||||
AssemblyItems output = getCSE(input, state);
|
||||
// check that it directly pushes 1 (true)
|
||||
BOOST_CHECK(find(output.begin(), output.end(), AssemblyItem(u256(1))) != output.end());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(control_flow_graph_remove_unused)
|
||||
{
|
||||
// remove parts of the code that are unused
|
||||
|
Loading…
Reference in New Issue
Block a user