aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/RPCSession.cpp6
-rw-r--r--test/libevmasm/Optimiser.cpp43
-rw-r--r--test/libsolidity/AnalysisFramework.cpp28
-rw-r--r--test/libsolidity/AnalysisFramework.h7
-rw-r--r--test/libsolidity/JSONCompiler.cpp8
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp145
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp125
-rw-r--r--test/libsolidity/SolidityOptimizer.cpp28
-rw-r--r--test/libsolidity/SolidityParser.cpp20
-rw-r--r--test/libsolidity/SolidityTypes.cpp1
-rw-r--r--test/libsolidity/StandardCompiler.cpp6
-rw-r--r--test/libsolidity/SyntaxTest.cpp98
-rw-r--r--test/libsolidity/SyntaxTest.h31
-rw-r--r--test/libsolidity/syntaxTests/constants/cyclic_dependency_1.sol5
-rw-r--r--test/libsolidity/syntaxTests/constants/cyclic_dependency_2.sol10
-rw-r--r--test/libsolidity/syntaxTests/constants/cyclic_dependency_3.sol11
-rw-r--r--test/libsolidity/syntaxTests/constants/cyclic_dependency_4.sol6
-rw-r--r--test/libsolidity/syntaxTests/inheritance/base_arguments_empty_parentheses.sol3
-rw-r--r--test/libsolidity/syntaxTests/inheritance/base_arguments_empty_parentheses_V050.sol9
-rw-r--r--test/libsolidity/syntaxTests/inheritance/base_arguments_no_parentheses.sol5
-rw-r--r--test/libsolidity/syntaxTests/parsing/missing_variable_name_in_declaration.sol5
-rw-r--r--test/libsolidity/syntaxTests/parsing/smoke_test.sol4
-rw-r--r--test/libsolidity/syntaxTests/structs/recursion/multi_struct_composition.sol15
-rw-r--r--test/libsolidity/syntaxTests/structs/recursion/parallel_structs.sol15
-rw-r--r--test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs.sol7
-rw-r--r--test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs2.sol7
-rw-r--r--test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs3.sol8
-rw-r--r--test/libsolidity/syntaxTests/structs/recursion/struct_definition_directly_recursive.sol8
-rw-r--r--test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive.sol12
-rw-r--r--test/libsolidity/syntaxTests/structs/recursion/struct_definition_not_really_recursive.sol4
-rw-r--r--test/libsolidity/syntaxTests/structs/recursion/struct_definition_recursion_via_mapping.sol7
-rw-r--r--test/tools/isoltest.cpp65
32 files changed, 465 insertions, 287 deletions
diff --git a/test/RPCSession.cpp b/test/RPCSession.cpp
index 03b1341c..f4eae865 100644
--- a/test/RPCSession.cpp
+++ b/test/RPCSession.cpp
@@ -226,6 +226,8 @@ void RPCSession::test_setChainParams(vector<string> const& _accounts)
forks += "\"EIP158ForkBlock\": \"0x00\",\n";
if (test::Options::get().evmVersion() >= solidity::EVMVersion::byzantium())
forks += "\"byzantiumForkBlock\": \"0x00\",\n";
+ if (test::Options::get().evmVersion() >= solidity::EVMVersion::constantinople())
+ forks += "\"constantinopleForkBlock\": \"0x00\",\n";
static string const c_configString = R"(
{
"sealEngine": "NoProof",
@@ -337,7 +339,9 @@ Json::Value RPCSession::rpcCall(string const& _methodName, vector<string> const&
BOOST_TEST_MESSAGE("Reply: " + reply);
Json::Value result;
- BOOST_REQUIRE(jsonParseStrict(reply, result));
+ string errorMsg;
+ if (!jsonParseStrict(reply, result, &errorMsg))
+ BOOST_REQUIRE_MESSAGE(false, errorMsg);
if (result.isMember("error"))
{
diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp
index b622b4fb..089be45d 100644
--- a/test/libevmasm/Optimiser.cpp
+++ b/test/libevmasm/Optimiser.cpp
@@ -888,7 +888,7 @@ BOOST_AUTO_TEST_CASE(peephole_commutative_swap1)
PeepholeOptimiser peepOpt(items);
BOOST_REQUIRE(peepOpt.optimise());
BOOST_CHECK_EQUAL_COLLECTIONS(
- items.begin(), items.end(),
+ items.begin(), items.end(),
expectation.begin(), expectation.end()
);
}
@@ -903,9 +903,7 @@ BOOST_AUTO_TEST_CASE(peephole_noncommutative_swap1)
Instruction::SDIV,
Instruction::MOD,
Instruction::SMOD,
- Instruction::EXP,
- Instruction::LT,
- Instruction::GT
+ Instruction::EXP
};
for (Instruction const op: ops)
{
@@ -928,7 +926,42 @@ BOOST_AUTO_TEST_CASE(peephole_noncommutative_swap1)
PeepholeOptimiser peepOpt(items);
BOOST_REQUIRE(!peepOpt.optimise());
BOOST_CHECK_EQUAL_COLLECTIONS(
- items.begin(), items.end(),
+ items.begin(), items.end(),
+ expectation.begin(), expectation.end()
+ );
+ }
+}
+
+BOOST_AUTO_TEST_CASE(peephole_swap_comparison)
+{
+ map<Instruction, Instruction> swappableOps{
+ { Instruction::LT, Instruction::GT },
+ { Instruction::GT, Instruction::LT },
+ { Instruction::SLT, Instruction::SGT },
+ { Instruction::SGT, Instruction::SLT }
+ };
+
+ for (auto const& op: swappableOps)
+ {
+ AssemblyItems items{
+ u256(1),
+ u256(2),
+ Instruction::SWAP1,
+ op.first,
+ u256(4),
+ u256(5)
+ };
+ AssemblyItems expectation{
+ u256(1),
+ u256(2),
+ op.second,
+ u256(4),
+ u256(5)
+ };
+ PeepholeOptimiser peepOpt(items);
+ BOOST_REQUIRE(peepOpt.optimise());
+ BOOST_CHECK_EQUAL_COLLECTIONS(
+ items.begin(), items.end(),
expectation.begin(), expectation.end()
);
}
diff --git a/test/libsolidity/AnalysisFramework.cpp b/test/libsolidity/AnalysisFramework.cpp
index 4538757d..72b86767 100644
--- a/test/libsolidity/AnalysisFramework.cpp
+++ b/test/libsolidity/AnalysisFramework.cpp
@@ -56,12 +56,23 @@ AnalysisFramework::parseAnalyseAndReturnError(
m_compiler.analyze();
+ ErrorList errors = filterErrors(m_compiler.errors(), _reportWarnings);
+ if (errors.size() > 1 && !_allowMultipleErrors)
+ BOOST_FAIL("Multiple errors found: " + formatErrors());
+
+ return make_pair(&m_compiler.ast(""), std::move(errors));
+}
+
+ErrorList AnalysisFramework::filterErrors(ErrorList const& _errorList, bool _includeWarnings) const
+{
ErrorList errors;
- for (auto const& currentError: m_compiler.errors())
+ for (auto const& currentError: _errorList)
{
solAssert(currentError->comment(), "");
if (currentError->type() == Error::Type::Warning)
{
+ if (!_includeWarnings)
+ continue;
bool ignoreWarning = false;
for (auto const& filter: m_warningsToFilter)
if (currentError->comment()->find(filter) == 0)
@@ -73,17 +84,10 @@ AnalysisFramework::parseAnalyseAndReturnError(
continue;
}
- if (_reportWarnings || (currentError->type() != Error::Type::Warning))
- {
- if (!_allowMultipleErrors && !errors.empty())
- {
- BOOST_FAIL("Multiple errors found: " + formatErrors());
- }
- errors.emplace_back(std::move(currentError));
- }
+ errors.emplace_back(currentError);
}
- return make_pair(&m_compiler.ast(""), errors);
+ return errors;
}
SourceUnit const* AnalysisFramework::parseAndAnalyse(string const& _source)
@@ -110,7 +114,7 @@ ErrorList AnalysisFramework::expectError(std::string const& _source, bool _warni
return sourceAndErrors.second;
}
-string AnalysisFramework::formatErrors()
+string AnalysisFramework::formatErrors() const
{
string message;
for (auto const& error: m_compiler.errors())
@@ -118,7 +122,7 @@ string AnalysisFramework::formatErrors()
return message;
}
-string AnalysisFramework::formatError(Error const& _error)
+string AnalysisFramework::formatError(Error const& _error) const
{
return SourceReferenceFormatter::formatExceptionInformation(
_error,
diff --git a/test/libsolidity/AnalysisFramework.h b/test/libsolidity/AnalysisFramework.h
index 6ecf4a5a..05490a42 100644
--- a/test/libsolidity/AnalysisFramework.h
+++ b/test/libsolidity/AnalysisFramework.h
@@ -57,8 +57,8 @@ protected:
bool success(std::string const& _source);
ErrorList expectError(std::string const& _source, bool _warning = false, bool _allowMultiple = false);
- std::string formatErrors();
- std::string formatError(Error const& _error);
+ std::string formatErrors() const;
+ std::string formatError(Error const& _error) const;
static ContractDefinition const* retrieveContractByName(SourceUnit const& _source, std::string const& _name);
static FunctionTypePointer retrieveFunctionBySignature(
@@ -66,6 +66,9 @@ protected:
std::string const& _signature
);
+ // filter out the warnings in m_warningsToFilter or all warnings if _includeWarnings is false
+ ErrorList filterErrors(ErrorList const& _errorList, bool _includeWarnings) const;
+
std::vector<std::string> m_warningsToFilter = {"This is a pre-release compiler version"};
dev::solidity::CompilerStack m_compiler;
};
diff --git a/test/libsolidity/JSONCompiler.cpp b/test/libsolidity/JSONCompiler.cpp
index aed0a370..cdcc22a6 100644
--- a/test/libsolidity/JSONCompiler.cpp
+++ b/test/libsolidity/JSONCompiler.cpp
@@ -111,12 +111,12 @@ BOOST_AUTO_TEST_CASE(basic_compilation)
BOOST_CHECK(contract["bytecode"].isString());
BOOST_CHECK_EQUAL(
dev::test::bytecodeSansMetadata(contract["bytecode"].asString()),
- "60606040523415600e57600080fd5b603580601b6000396000f3006060604052600080fd00"
+ "60806040523415600e57600080fd5b603580601b6000396000f3006080604052600080fd00"
);
BOOST_CHECK(contract["runtimeBytecode"].isString());
BOOST_CHECK_EQUAL(
dev::test::bytecodeSansMetadata(contract["runtimeBytecode"].asString()),
- "6060604052600080fd00"
+ "6080604052600080fd00"
);
BOOST_CHECK(contract["functionHashes"].isObject());
BOOST_CHECK(contract["gasEstimates"].isObject());
@@ -153,12 +153,12 @@ BOOST_AUTO_TEST_CASE(single_compilation)
BOOST_CHECK(contract["bytecode"].isString());
BOOST_CHECK_EQUAL(
dev::test::bytecodeSansMetadata(contract["bytecode"].asString()),
- "60606040523415600e57600080fd5b603580601b6000396000f3006060604052600080fd00"
+ "60806040523415600e57600080fd5b603580601b6000396000f3006080604052600080fd00"
);
BOOST_CHECK(contract["runtimeBytecode"].isString());
BOOST_CHECK_EQUAL(
dev::test::bytecodeSansMetadata(contract["runtimeBytecode"].asString()),
- "6060604052600080fd00"
+ "6080604052600080fd00"
);
BOOST_CHECK(contract["functionHashes"].isObject());
BOOST_CHECK(contract["gasEstimates"].isObject());
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index 38d3ce4d..beeae786 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -4884,6 +4884,48 @@ BOOST_AUTO_TEST_CASE(array_push)
ABI_CHECK(callContractFunction("test()"), encodeArgs(5, 4, 3, 3));
}
+BOOST_AUTO_TEST_CASE(array_push_struct)
+{
+ char const* sourceCode = R"(
+ contract c {
+ struct S { uint16 a; uint16 b; uint16[3] c; uint16[] d; }
+ S[] data;
+ function test() returns (uint16, uint16, uint16, uint16) {
+ S memory s;
+ s.a = 2;
+ s.b = 3;
+ s.c[2] = 4;
+ s.d = new uint16[](4);
+ s.d[2] = 5;
+ data.push(s);
+ return (data[0].a, data[0].b, data[0].c[2], data[0].d[2]);
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ ABI_CHECK(callContractFunction("test()"), encodeArgs(2, 3, 4, 5));
+}
+
+BOOST_AUTO_TEST_CASE(array_push_packed_array)
+{
+ char const* sourceCode = R"(
+ contract c {
+ uint80[] x;
+ function test() returns (uint80, uint80, uint80, uint80) {
+ x.push(1);
+ x.push(2);
+ x.push(3);
+ x.push(4);
+ x.push(5);
+ x.length = 4;
+ return (x[0], x[1], x[2], x[3]);
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ ABI_CHECK(callContractFunction("test()"), encodeArgs(1, 2, 3, 4));
+}
+
BOOST_AUTO_TEST_CASE(byte_array_push)
{
char const* sourceCode = R"(
@@ -4904,6 +4946,29 @@ BOOST_AUTO_TEST_CASE(byte_array_push)
ABI_CHECK(callContractFunction("test()"), encodeArgs(false));
}
+BOOST_AUTO_TEST_CASE(byte_array_push_transition)
+{
+ // Tests transition between short and long encoding
+ char const* sourceCode = R"(
+ contract c {
+ bytes data;
+ function test() returns (uint) {
+ for (uint i = 1; i < 40; i++)
+ {
+ data.push(byte(i));
+ if (data.length != i) return 0x1000 + i;
+ if (data[data.length - 1] != byte(i)) return i;
+ }
+ for (i = 1; i < 40; i++)
+ if (data[i - 1] != byte(i)) return 0x1000000 + i;
+ return 0;
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ ABI_CHECK(callContractFunction("test()"), encodeArgs(0));
+}
+
BOOST_AUTO_TEST_CASE(external_array_args)
{
char const* sourceCode = R"(
@@ -7687,7 +7752,6 @@ BOOST_AUTO_TEST_CASE(create_memory_array_allocation_size)
ABI_CHECK(callContractFunction("f()"), encodeArgs(0x40, 0x40, 0x20 + 256));
}
-
BOOST_AUTO_TEST_CASE(memory_arrays_of_various_sizes)
{
// Computes binomial coefficients the chinese way
@@ -7710,6 +7774,41 @@ BOOST_AUTO_TEST_CASE(memory_arrays_of_various_sizes)
ABI_CHECK(callContractFunction("f(uint256,uint256)", encodeArgs(u256(9), u256(5))), encodeArgs(u256(70)));
}
+BOOST_AUTO_TEST_CASE(create_multiple_dynamic_arrays)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f() returns (uint) {
+ uint[][] memory x = new uint[][](42);
+ assert(x[0].length == 0);
+ x[0] = new uint[](1);
+ x[0][0] = 1;
+ assert(x[4].length == 0);
+ x[4] = new uint[](1);
+ x[4][0] = 2;
+ assert(x[10].length == 0);
+ x[10] = new uint[](1);
+ x[10][0] = 44;
+ uint[][] memory y = new uint[][](24);
+ assert(y[0].length == 0);
+ y[0] = new uint[](1);
+ y[0][0] = 1;
+ assert(y[4].length == 0);
+ y[4] = new uint[](1);
+ y[4][0] = 2;
+ assert(y[10].length == 0);
+ y[10] = new uint[](1);
+ y[10][0] = 88;
+ if ((x[0][0] == y[0][0]) && (x[4][0] == y[4][0]) && (x[10][0] == 44) && (y[10][0] == 88))
+ return 7;
+ return 0;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(7)));
+}
+
BOOST_AUTO_TEST_CASE(memory_overwrite)
{
char const* sourceCode = R"(
@@ -10998,6 +11097,50 @@ BOOST_AUTO_TEST_CASE(staticcall_for_view_and_pure)
}
}
+BOOST_AUTO_TEST_CASE(swap_peephole_optimisation)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function lt(uint a, uint b) returns (bool c) {
+ assembly {
+ a
+ b
+ swap1
+ lt
+ =: c
+ }
+ }
+ function add(uint a, uint b) returns (uint c) {
+ assembly {
+ a
+ b
+ swap1
+ add
+ =: c
+ }
+ }
+ function div(uint a, uint b) returns (uint c) {
+ assembly {
+ a
+ b
+ swap1
+ div
+ =: c
+ }
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callContractFunction("lt(uint256,uint256)", u256(1), u256(2)) == encodeArgs(u256(1)));
+ BOOST_CHECK(callContractFunction("lt(uint256,uint256)", u256(2), u256(1)) == encodeArgs(u256(0)));
+ BOOST_CHECK(callContractFunction("add(uint256,uint256)", u256(1), u256(2)) == encodeArgs(u256(3)));
+ BOOST_CHECK(callContractFunction("add(uint256,uint256)", u256(100), u256(200)) == encodeArgs(u256(300)));
+ BOOST_CHECK(callContractFunction("div(uint256,uint256)", u256(2), u256(1)) == encodeArgs(u256(2)));
+ BOOST_CHECK(callContractFunction("div(uint256,uint256)", u256(200), u256(10)) == encodeArgs(u256(20)));
+ BOOST_CHECK(callContractFunction("div(uint256,uint256)", u256(1), u256(0)) == encodeArgs(u256(0)));
+ BOOST_CHECK(callContractFunction("div(uint256,uint256)", u256(0), u256(1)) == encodeArgs(u256(0)));
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp
index b6596327..fcee0df3 100644
--- a/test/libsolidity/SolidityNameAndTypeResolution.cpp
+++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp
@@ -92,61 +92,6 @@ BOOST_AUTO_TEST_CASE(reference_to_later_declaration)
CHECK_SUCCESS(text);
}
-BOOST_AUTO_TEST_CASE(struct_definition_directly_recursive)
-{
- char const* text = R"(
- contract test {
- struct MyStructName {
- address addr;
- MyStructName x;
- }
- }
- )";
- CHECK_ERROR(text, TypeError, "Recursive struct definition.");
-}
-
-BOOST_AUTO_TEST_CASE(struct_definition_indirectly_recursive)
-{
- char const* text = R"(
- contract test {
- struct MyStructName1 {
- address addr;
- uint256 count;
- MyStructName2 x;
- }
- struct MyStructName2 {
- MyStructName1 x;
- }
- }
- )";
- CHECK_ERROR(text, TypeError, "Recursive struct definition.");
-}
-
-BOOST_AUTO_TEST_CASE(struct_definition_not_really_recursive)
-{
- char const* text = R"(
- contract test {
- struct s1 { uint a; }
- struct s2 { s1 x; s1 y; }
- }
- )";
- CHECK_SUCCESS(text);
-}
-
-BOOST_AUTO_TEST_CASE(struct_definition_recursion_via_mapping)
-{
- char const* text = R"(
- contract test {
- struct MyStructName1 {
- address addr;
- uint256 count;
- mapping(uint => MyStructName1) x;
- }
- }
- )";
- CHECK_SUCCESS(text);
-}
-
BOOST_AUTO_TEST_CASE(type_inference_smoke_test)
{
char const* text = R"(
@@ -6222,44 +6167,6 @@ BOOST_AUTO_TEST_CASE(read_returned_struct)
)";
CHECK_WARNING(text, "Experimental features");
}
-
-BOOST_AUTO_TEST_CASE(return_recursive_structs)
-{
- char const* text = R"(
- contract C {
- struct S { uint a; S[] sub; }
- function f() returns (uint, S) {
- }
- }
- )";
- CHECK_ERROR(text, TypeError, "Internal or recursive type is not allowed for public or external functions.");
-}
-
-BOOST_AUTO_TEST_CASE(return_recursive_structs2)
-{
- char const* text = R"(
- contract C {
- struct S { uint a; S[2][] sub; }
- function f() returns (uint, S) {
- }
- }
- )";
- CHECK_ERROR(text, TypeError, "Internal or recursive type is not allowed for public or external functions.");
-}
-
-BOOST_AUTO_TEST_CASE(return_recursive_structs3)
-{
- char const* text = R"(
- contract C {
- struct S { uint a; S[][][] sub; }
- struct T { S s; }
- function f() returns (uint x, T t) {
- }
- }
- )";
- CHECK_ERROR(text, TypeError, "Internal or recursive type is not allowed for public or external functions.");
-}
-
BOOST_AUTO_TEST_CASE(address_checksum_type_deduction)
{
char const* text = R"(
@@ -6382,38 +6289,6 @@ BOOST_AUTO_TEST_CASE(address_methods)
CHECK_SUCCESS(text);
}
-BOOST_AUTO_TEST_CASE(cyclic_dependency_for_constants)
-{
- char const* text = R"(
- contract C {
- uint constant a = a;
- }
- )";
- CHECK_ERROR(text, TypeError, "cyclic dependency via a");
- text = R"(
- contract C {
- uint constant a = b * c;
- uint constant b = 7;
- uint constant c = b + uint(keccak256(d));
- uint constant d = 2 + a;
- }
- )";
- CHECK_ERROR_ALLOW_MULTI(text, TypeError, (std::vector<std::string>{
- "a has a cyclic dependency via c",
- "c has a cyclic dependency via d",
- "d has a cyclic dependency via a"
- }));
- text = R"(
- contract C {
- uint constant a = b * c;
- uint constant b = 7;
- uint constant c = 4 + uint(keccak256(d));
- uint constant d = 2 + b;
- }
- )";
- CHECK_SUCCESS(text);
-}
-
BOOST_AUTO_TEST_CASE(interface)
{
char const* text = R"(
diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp
index cf4550c7..5326feaf 100644
--- a/test/libsolidity/SolidityOptimizer.cpp
+++ b/test/libsolidity/SolidityOptimizer.cpp
@@ -93,8 +93,10 @@ public:
{
m_contractAddress = m_nonOptimizedContract;
bytes nonOptimizedOutput = callContractFunction(_sig, _arguments...);
+ m_gasUsedNonOptimized = m_gasUsed;
m_contractAddress = m_optimizedContract;
bytes optimizedOutput = callContractFunction(_sig, _arguments...);
+ m_gasUsedOptimized = m_gasUsed;
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."
@@ -120,6 +122,8 @@ public:
}
protected:
+ u256 m_gasUsedOptimized;
+ u256 m_gasUsedNonOptimized;
bytes m_nonOptimizedBytecode;
bytes m_optimizedBytecode;
Address m_optimizedContract;
@@ -584,6 +588,26 @@ BOOST_AUTO_TEST_CASE(invalid_state_at_control_flow_join)
compareVersions("test()");
}
+BOOST_AUTO_TEST_CASE(init_empty_dynamic_arrays)
+{
+ // This is not so much an optimizer test, but rather a test
+ // that allocating empty arrays is implemented efficiently.
+ // In particular, initializing a dynamic memory array does
+ // not use any memory.
+ char const* sourceCode = R"(
+ contract Test {
+ function f() pure returns (uint r) {
+ uint[][] memory x = new uint[][](20000);
+ return x.length;
+ }
+ }
+ )";
+ compileBothVersions(sourceCode);
+ compareVersions("f()");
+ BOOST_CHECK_LE(m_gasUsedNonOptimized, 1900000);
+ BOOST_CHECK_LE(1600000, m_gasUsedNonOptimized);
+}
+
BOOST_AUTO_TEST_CASE(optimise_multi_stores)
{
char const* sourceCode = R"(
@@ -603,8 +627,8 @@ BOOST_AUTO_TEST_CASE(optimise_multi_stores)
)";
compileBothVersions(sourceCode);
compareVersions("f()");
- BOOST_CHECK_EQUAL(numInstructions(m_nonOptimizedBytecode, Instruction::SSTORE), 13);
- BOOST_CHECK_EQUAL(numInstructions(m_optimizedBytecode, Instruction::SSTORE), 11);
+ BOOST_CHECK_EQUAL(numInstructions(m_nonOptimizedBytecode, Instruction::SSTORE), 9);
+ BOOST_CHECK_EQUAL(numInstructions(m_optimizedBytecode, Instruction::SSTORE), 8);
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp
index 4e862f60..93e6bcaa 100644
--- a/test/libsolidity/SolidityParser.cpp
+++ b/test/libsolidity/SolidityParser.cpp
@@ -112,26 +112,6 @@ while(0)
BOOST_AUTO_TEST_SUITE(SolidityParser)
-BOOST_AUTO_TEST_CASE(smoke_test)
-{
- char const* text = R"(
- contract test {
- uint256 stateVariable1;
- }
- )";
- BOOST_CHECK(successParse(text));
-}
-
-BOOST_AUTO_TEST_CASE(missing_variable_name_in_declaration)
-{
- char const* text = R"(
- contract test {
- uint256 ;
- }
- )";
- CHECK_PARSE_ERROR(text, "Expected identifier");
-}
-
BOOST_AUTO_TEST_CASE(empty_function)
{
char const* text = R"(
diff --git a/test/libsolidity/SolidityTypes.cpp b/test/libsolidity/SolidityTypes.cpp
index bc9f2fe1..738b24bc 100644
--- a/test/libsolidity/SolidityTypes.cpp
+++ b/test/libsolidity/SolidityTypes.cpp
@@ -123,6 +123,7 @@ BOOST_AUTO_TEST_CASE(type_identifiers)
BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("bytes32")->identifier(), "t_bytes32");
BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("bool")->identifier(), "t_bool");
BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("bytes")->identifier(), "t_bytes_storage_ptr");
+ BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("bytes memory")->identifier(), "t_bytes_memory_ptr");
BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("string")->identifier(), "t_string_storage_ptr");
ArrayType largeintArray(DataLocation::Memory, Type::fromElementaryTypeName("int128"), u256("2535301200456458802993406410752"));
BOOST_CHECK_EQUAL(largeintArray.identifier(), "t_array$_t_int128_$2535301200456458802993406410752_memory_ptr");
diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp
index dd6eb7c4..b285a2a0 100644
--- a/test/libsolidity/StandardCompiler.cpp
+++ b/test/libsolidity/StandardCompiler.cpp
@@ -261,14 +261,14 @@ BOOST_AUTO_TEST_CASE(basic_compilation)
BOOST_CHECK(contract["evm"]["bytecode"]["object"].isString());
BOOST_CHECK_EQUAL(
dev::test::bytecodeSansMetadata(contract["evm"]["bytecode"]["object"].asString()),
- "60606040523415600e57600080fd5b603580601b6000396000f3006060604052600080fd00"
+ "60806040523415600e57600080fd5b603580601b6000396000f3006080604052600080fd00"
);
BOOST_CHECK(contract["evm"]["assembly"].isString());
BOOST_CHECK(contract["evm"]["assembly"].asString().find(
- " /* \"fileA\":0:14 contract A { } */\n mstore(0x40, 0x60)\n jumpi(tag_1, iszero(callvalue))\n"
+ " /* \"fileA\":0:14 contract A { } */\n mstore(0x40, 0x80)\n jumpi(tag_1, iszero(callvalue))\n"
" 0x0\n dup1\n revert\ntag_1:\n dataSize(sub_0)\n dup1\n dataOffset(sub_0)\n 0x0\n codecopy\n 0x0\n"
" return\nstop\n\nsub_0: assembly {\n /* \"fileA\":0:14 contract A { } */\n"
- " mstore(0x40, 0x60)\n 0x0\n dup1\n revert\n\n"
+ " mstore(0x40, 0x80)\n 0x0\n dup1\n revert\n\n"
" auxdata: 0xa165627a7a7230582") == 0);
BOOST_CHECK(contract["evm"]["gasEstimates"].isObject());
BOOST_CHECK_EQUAL(
diff --git a/test/libsolidity/SyntaxTest.cpp b/test/libsolidity/SyntaxTest.cpp
index ca051138..329543bf 100644
--- a/test/libsolidity/SyntaxTest.cpp
+++ b/test/libsolidity/SyntaxTest.cpp
@@ -16,6 +16,7 @@
*/
#include <test/libsolidity/SyntaxTest.h>
+#include <test/Options.h>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/throw_exception.hpp>
@@ -59,93 +60,52 @@ SyntaxTest::SyntaxTest(string const& _filename)
bool SyntaxTest::run(ostream& _stream, string const& _linePrefix, bool const _formatted)
{
- m_errorList = parseAnalyseAndReturnError(m_source, true, true, true).second;
- if (!matchesExpectations(m_errorList))
+ m_compiler.reset();
+ m_compiler.addSource("", "pragma solidity >=0.0;\n" + m_source);
+ m_compiler.setEVMVersion(dev::test::Options::get().evmVersion());
+
+ if (m_compiler.parse())
+ m_compiler.analyze();
+
+ for (auto const& currentError: filterErrors(m_compiler.errors(), true))
+ m_errorList.emplace_back(SyntaxTestError{currentError->typeName(), errorMessage(*currentError)});
+
+ if (m_expectations != m_errorList)
{
- std::string nextIndentLevel = _linePrefix + " ";
+ string nextIndentLevel = _linePrefix + " ";
FormattedScope(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Expected result:" << endl;
- printExpected(_stream, nextIndentLevel, _formatted);
+ printErrorList(_stream, m_expectations, nextIndentLevel, _formatted);
FormattedScope(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Obtained result:\n";
- printErrorList(_stream, m_errorList, nextIndentLevel, false, false, _formatted);
+ printErrorList(_stream, m_errorList, nextIndentLevel, _formatted);
return false;
}
return true;
}
-void SyntaxTest::printExpected(ostream& _stream, string const& _linePrefix, bool const _formatted) const
-{
- if (m_expectations.empty())
- FormattedScope(_stream, _formatted, {BOLD, GREEN}) << _linePrefix << "Success" << endl;
- else
- for (auto const& expectation: m_expectations)
- {
- FormattedScope(_stream, _formatted, {BOLD, expectation.type == "Warning" ? YELLOW : RED}) <<
- _linePrefix << expectation.type << ": ";
- _stream << expectation.message << endl;
- }
-}
-
void SyntaxTest::printErrorList(
ostream& _stream,
- ErrorList const& _errorList,
+ vector<SyntaxTestError> const& _errorList,
string const& _linePrefix,
- bool const _ignoreWarnings,
- bool const _lineNumbers,
bool const _formatted
-) const
+)
{
if (_errorList.empty())
FormattedScope(_stream, _formatted, {BOLD, GREEN}) << _linePrefix << "Success" << endl;
else
for (auto const& error: _errorList)
{
- bool isWarning = (error->type() == Error::Type::Warning);
- if (isWarning && _ignoreWarnings) continue;
-
{
- FormattedScope scope(_stream, _formatted, {BOLD, isWarning ? YELLOW : RED});
+ FormattedScope scope(_stream, _formatted, {BOLD, (error.type == "Warning") ? YELLOW : RED});
_stream << _linePrefix;
- if (_lineNumbers)
- {
- int line = offsetToLineNumber(
- boost::get_error_info<errinfo_sourceLocation>(*error)->start
- );
- if (line >= 0)
- _stream << "(" << line << "): ";
- }
- _stream << error->typeName() << ": ";
+ _stream << error.type << ": ";
}
- _stream << errorMessage(*error) << endl;
+ _stream << error.message << endl;
}
}
-int SyntaxTest::offsetToLineNumber(int _location) const
-{
- // parseAnalyseAndReturnError(...) prepends a version pragma
- _location -= strlen("pragma solidity >=0.0;\n");
- if (_location < 0 || static_cast<size_t>(_location) >= m_source.size())
- return -1;
- else
- return 1 + std::count(m_source.begin(), m_source.begin() + _location, '\n');
-}
-
-bool SyntaxTest::matchesExpectations(ErrorList const& _errorList) const
-{
- if (_errorList.size() != m_expectations.size())
- return false;
- else
- for (size_t i = 0; i < _errorList.size(); i++)
- if (
- (_errorList[i]->typeName() != m_expectations[i].type) ||
- (errorMessage(*_errorList[i]) != m_expectations[i].message)
- )
- return false;
- return true;
-}
-
-string SyntaxTest::errorMessage(Error const& _e)
+string SyntaxTest::errorMessage(Exception const& _e)
{
- if (_e.comment())
+ if (_e.comment() && !_e.comment()->empty())
return boost::replace_all_copy(*_e.comment(), "\n", "\\n");
else
return "NONE";
@@ -164,9 +124,9 @@ string SyntaxTest::parseSource(istream& _stream)
return source;
}
-vector<SyntaxTestExpectation> SyntaxTest::parseExpectations(istream& _stream)
+vector<SyntaxTestError> SyntaxTest::parseExpectations(istream& _stream)
{
- vector<SyntaxTestExpectation> expectations;
+ vector<SyntaxTestError> expectations;
string line;
while (getline(_stream, line))
{
@@ -188,7 +148,7 @@ vector<SyntaxTestExpectation> SyntaxTest::parseExpectations(istream& _stream)
skipWhitespace(it, line.end());
string errorMessage(it, line.end());
- expectations.emplace_back(SyntaxTestExpectation{move(errorType), move(errorMessage)});
+ expectations.emplace_back(SyntaxTestError{move(errorType), move(errorMessage)});
}
return expectations;
}
@@ -239,9 +199,11 @@ int SyntaxTest::registerTests(
_suite.add(make_test_case(
[fullpath]
{
- std::stringstream errorStream;
- if (!SyntaxTest(fullpath.string()).run(errorStream))
- BOOST_ERROR("Test expectation mismatch.\n" + errorStream.str());
+ BOOST_REQUIRE_NO_THROW({
+ stringstream errorStream;
+ if (!SyntaxTest(fullpath.string()).run(errorStream))
+ BOOST_ERROR("Test expectation mismatch.\n" + errorStream.str());
+ });
},
_path.stem().string(),
*filenames.back(),
diff --git a/test/libsolidity/SyntaxTest.h b/test/libsolidity/SyntaxTest.h
index cb6ee05c..dddd86ef 100644
--- a/test/libsolidity/SyntaxTest.h
+++ b/test/libsolidity/SyntaxTest.h
@@ -36,10 +36,14 @@ namespace solidity
namespace test
{
-struct SyntaxTestExpectation
+struct SyntaxTestError
{
std::string type;
std::string message;
+ bool operator==(SyntaxTestError const& _rhs) const
+ {
+ return type == _rhs.type && message == _rhs.message;
+ }
};
@@ -50,21 +54,16 @@ public:
bool run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false);
- std::vector<SyntaxTestExpectation> const& expectations() const { return m_expectations; }
+ std::vector<SyntaxTestError> const& expectations() const { return m_expectations; }
std::string const& source() const { return m_source; }
- ErrorList const& errorList() const { return m_errorList; }
- ErrorList const& compilerErrors() const { return m_compiler.errors(); }
+ std::vector<SyntaxTestError> const& errorList() const { return m_errorList; }
- void printExpected(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted = false) const;
-
- void printErrorList(
+ static void printErrorList(
std::ostream& _stream,
- ErrorList const& _errors,
+ std::vector<SyntaxTestError> const& _errors,
std::string const& _linePrefix,
- bool const _ignoreWarnings,
- bool const _lineNumbers,
bool const _formatted = false
- ) const;
+ );
static int registerTests(
boost::unit_test::test_suite& _suite,
@@ -72,16 +71,14 @@ public:
boost::filesystem::path const& _path
);
static bool isTestFilename(boost::filesystem::path const& _filename);
+ static std::string errorMessage(Exception const& _e);
private:
- bool matchesExpectations(ErrorList const& _errors) const;
- static std::string errorMessage(Error const& _e);
static std::string parseSource(std::istream& _stream);
- static std::vector<SyntaxTestExpectation> parseExpectations(std::istream& _stream);
- int offsetToLineNumber(int _location) const;
+ static std::vector<SyntaxTestError> parseExpectations(std::istream& _stream);
std::string m_source;
- std::vector<SyntaxTestExpectation> m_expectations;
- ErrorList m_errorList;
+ std::vector<SyntaxTestError> m_expectations;
+ std::vector<SyntaxTestError> m_errorList;
};
}
diff --git a/test/libsolidity/syntaxTests/constants/cyclic_dependency_1.sol b/test/libsolidity/syntaxTests/constants/cyclic_dependency_1.sol
new file mode 100644
index 00000000..2b6aa088
--- /dev/null
+++ b/test/libsolidity/syntaxTests/constants/cyclic_dependency_1.sol
@@ -0,0 +1,5 @@
+contract C {
+ uint constant a = a;
+}
+// ----
+// TypeError: The value of the constant a has a cyclic dependency via a.
diff --git a/test/libsolidity/syntaxTests/constants/cyclic_dependency_2.sol b/test/libsolidity/syntaxTests/constants/cyclic_dependency_2.sol
new file mode 100644
index 00000000..461979f8
--- /dev/null
+++ b/test/libsolidity/syntaxTests/constants/cyclic_dependency_2.sol
@@ -0,0 +1,10 @@
+contract C {
+ uint constant a = b * c;
+ uint constant b = 7;
+ uint constant c = b + uint(keccak256(d));
+ uint constant d = 2 + a;
+}
+// ----
+// TypeError: The value of the constant a has a cyclic dependency via c.
+// TypeError: The value of the constant c has a cyclic dependency via d.
+// TypeError: The value of the constant d has a cyclic dependency via a.
diff --git a/test/libsolidity/syntaxTests/constants/cyclic_dependency_3.sol b/test/libsolidity/syntaxTests/constants/cyclic_dependency_3.sol
new file mode 100644
index 00000000..f63be05e
--- /dev/null
+++ b/test/libsolidity/syntaxTests/constants/cyclic_dependency_3.sol
@@ -0,0 +1,11 @@
+contract C {
+ uint constant x = a;
+ uint constant a = b * c;
+ uint constant b = c;
+ uint constant c = b;
+}
+// ----
+// TypeError: The value of the constant x has a cyclic dependency via a.
+// TypeError: The value of the constant a has a cyclic dependency via b.
+// TypeError: The value of the constant b has a cyclic dependency via c.
+// TypeError: The value of the constant c has a cyclic dependency via b.
diff --git a/test/libsolidity/syntaxTests/constants/cyclic_dependency_4.sol b/test/libsolidity/syntaxTests/constants/cyclic_dependency_4.sol
new file mode 100644
index 00000000..f01cb98e
--- /dev/null
+++ b/test/libsolidity/syntaxTests/constants/cyclic_dependency_4.sol
@@ -0,0 +1,6 @@
+contract C {
+ uint constant a = b * c;
+ uint constant b = 7;
+ uint constant c = 4 + uint(keccak256(d));
+ uint constant d = 2 + b;
+} \ No newline at end of file
diff --git a/test/libsolidity/syntaxTests/inheritance/base_arguments_empty_parentheses.sol b/test/libsolidity/syntaxTests/inheritance/base_arguments_empty_parentheses.sol
index 9607ed60..b3fbd04a 100644
--- a/test/libsolidity/syntaxTests/inheritance/base_arguments_empty_parentheses.sol
+++ b/test/libsolidity/syntaxTests/inheritance/base_arguments_empty_parentheses.sol
@@ -3,4 +3,5 @@ contract Base {
}
contract Derived is Base(2) { }
contract Derived2 is Base(), Derived() { }
-contract Derived3 is Base, Derived {}
+// ----
+// Warning: Wrong argument count for constructor call: 0 arguments given but expected 1.
diff --git a/test/libsolidity/syntaxTests/inheritance/base_arguments_empty_parentheses_V050.sol b/test/libsolidity/syntaxTests/inheritance/base_arguments_empty_parentheses_V050.sol
new file mode 100644
index 00000000..b3728634
--- /dev/null
+++ b/test/libsolidity/syntaxTests/inheritance/base_arguments_empty_parentheses_V050.sol
@@ -0,0 +1,9 @@
+pragma experimental "v0.5.0";
+
+contract Base {
+ constructor(uint) public {}
+}
+contract Derived is Base(2) { }
+contract Derived2 is Base(), Derived() { }
+// ----
+// TypeError: Wrong argument count for constructor call: 0 arguments given but expected 1.
diff --git a/test/libsolidity/syntaxTests/inheritance/base_arguments_no_parentheses.sol b/test/libsolidity/syntaxTests/inheritance/base_arguments_no_parentheses.sol
new file mode 100644
index 00000000..24cca8f0
--- /dev/null
+++ b/test/libsolidity/syntaxTests/inheritance/base_arguments_no_parentheses.sol
@@ -0,0 +1,5 @@
+contract Base {
+ constructor(uint) public {}
+}
+contract Derived is Base(2) { }
+contract Derived2 is Base, Derived {}
diff --git a/test/libsolidity/syntaxTests/parsing/missing_variable_name_in_declaration.sol b/test/libsolidity/syntaxTests/parsing/missing_variable_name_in_declaration.sol
new file mode 100644
index 00000000..c03fd97d
--- /dev/null
+++ b/test/libsolidity/syntaxTests/parsing/missing_variable_name_in_declaration.sol
@@ -0,0 +1,5 @@
+contract test {
+ uint256 ;
+}
+// ----
+// ParserError: Expected identifier, got 'Semicolon'
diff --git a/test/libsolidity/syntaxTests/parsing/smoke_test.sol b/test/libsolidity/syntaxTests/parsing/smoke_test.sol
new file mode 100644
index 00000000..d328b167
--- /dev/null
+++ b/test/libsolidity/syntaxTests/parsing/smoke_test.sol
@@ -0,0 +1,4 @@
+contract test {
+ uint256 stateVariable1;
+}
+// ----
diff --git a/test/libsolidity/syntaxTests/structs/recursion/multi_struct_composition.sol b/test/libsolidity/syntaxTests/structs/recursion/multi_struct_composition.sol
new file mode 100644
index 00000000..9a1c22f1
--- /dev/null
+++ b/test/libsolidity/syntaxTests/structs/recursion/multi_struct_composition.sol
@@ -0,0 +1,15 @@
+pragma experimental ABIEncoderV2;
+
+contract C {
+ struct T { U u; V v; }
+
+ struct U { W w; }
+
+ struct V { W w; }
+
+ struct W { uint x; }
+
+ function f(T) public pure { }
+}
+// ----
+// Warning: Experimental features are turned on. Do not use experimental features on live deployments.
diff --git a/test/libsolidity/syntaxTests/structs/recursion/parallel_structs.sol b/test/libsolidity/syntaxTests/structs/recursion/parallel_structs.sol
new file mode 100644
index 00000000..d4ad088d
--- /dev/null
+++ b/test/libsolidity/syntaxTests/structs/recursion/parallel_structs.sol
@@ -0,0 +1,15 @@
+pragma experimental ABIEncoderV2;
+
+contract TestContract
+{
+ struct SubStruct {
+ uint256 id;
+ }
+ struct TestStruct {
+ SubStruct subStruct1;
+ SubStruct subStruct2;
+ }
+ function addTestStruct(TestStruct) public pure {}
+}
+// ----
+// Warning: Experimental features are turned on. Do not use experimental features on live deployments.
diff --git a/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs.sol b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs.sol
new file mode 100644
index 00000000..c02a8aa4
--- /dev/null
+++ b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs.sol
@@ -0,0 +1,7 @@
+contract C {
+ struct S { uint a; S[] sub; }
+ function f() public pure returns (uint, S) {
+ }
+}
+// ----
+// TypeError: Internal or recursive type is not allowed for public or external functions.
diff --git a/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs2.sol b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs2.sol
new file mode 100644
index 00000000..e9488cf4
--- /dev/null
+++ b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs2.sol
@@ -0,0 +1,7 @@
+contract C {
+ struct S { uint a; S[2][] sub; }
+ function f() public pure returns (uint, S) {
+ }
+}
+// ----
+// TypeError: Internal or recursive type is not allowed for public or external functions.
diff --git a/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs3.sol b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs3.sol
new file mode 100644
index 00000000..6728baec
--- /dev/null
+++ b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs3.sol
@@ -0,0 +1,8 @@
+contract C {
+ struct S { uint a; S[][][] sub; }
+ struct T { S s; }
+ function f() public pure returns (uint x, T t) {
+ }
+}
+// ----
+// TypeError: Internal or recursive type is not allowed for public or external functions.
diff --git a/test/libsolidity/syntaxTests/structs/recursion/struct_definition_directly_recursive.sol b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_directly_recursive.sol
new file mode 100644
index 00000000..cac2e23f
--- /dev/null
+++ b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_directly_recursive.sol
@@ -0,0 +1,8 @@
+contract Test {
+ struct MyStructName {
+ address addr;
+ MyStructName x;
+ }
+}
+// ----
+// TypeError: Recursive struct definition.
diff --git a/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive.sol b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive.sol
new file mode 100644
index 00000000..11fc6307
--- /dev/null
+++ b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive.sol
@@ -0,0 +1,12 @@
+contract Test {
+ struct MyStructName1 {
+ address addr;
+ uint256 count;
+ MyStructName2 x;
+ }
+ struct MyStructName2 {
+ MyStructName1 x;
+ }
+}
+// ----
+// TypeError: Recursive struct definition.
diff --git a/test/libsolidity/syntaxTests/structs/recursion/struct_definition_not_really_recursive.sol b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_not_really_recursive.sol
new file mode 100644
index 00000000..6ec4ee01
--- /dev/null
+++ b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_not_really_recursive.sol
@@ -0,0 +1,4 @@
+contract Test {
+ struct S1 { uint a; }
+ struct S2 { S1 x; S1 y; }
+}
diff --git a/test/libsolidity/syntaxTests/structs/recursion/struct_definition_recursion_via_mapping.sol b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_recursion_via_mapping.sol
new file mode 100644
index 00000000..926981b3
--- /dev/null
+++ b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_recursion_via_mapping.sol
@@ -0,0 +1,7 @@
+contract Test {
+ struct MyStructName1 {
+ address addr;
+ uint256 count;
+ mapping(uint => MyStructName1) x;
+ }
+}
diff --git a/test/tools/isoltest.cpp b/test/tools/isoltest.cpp
index 5efec421..07df8f60 100644
--- a/test/tools/isoltest.cpp
+++ b/test/tools/isoltest.cpp
@@ -55,8 +55,8 @@ public:
{
Success,
Failure,
- ParserError,
- InputOutputError
+ InputOutputError,
+ Exception
};
Result process();
@@ -76,7 +76,7 @@ private:
Quit
};
- Request handleResponse(bool const _parserError);
+ Request handleResponse(bool const _exception);
void printContract() const;
@@ -100,7 +100,6 @@ void SyntaxTestTool::printContract() const
SyntaxTestTool::Result SyntaxTestTool::process()
{
bool success;
- bool parserError = false;
std::stringstream outputMessages;
(FormattedScope(cout, m_formatted, {BOLD}) << m_name << ": ").flush();
@@ -119,10 +118,35 @@ SyntaxTestTool::Result SyntaxTestTool::process()
{
success = m_test->run(outputMessages, " ", m_formatted);
}
- catch (...)
+ catch(CompilerError const& _e)
{
- success = false;
- parserError = true;
+ FormattedScope(cout, m_formatted, {BOLD, RED}) <<
+ "Exception: " << SyntaxTest::errorMessage(_e) << endl;
+ return Result::Exception;
+ }
+ catch(InternalCompilerError const& _e)
+ {
+ FormattedScope(cout, m_formatted, {BOLD, RED}) <<
+ "InternalCompilerError: " << SyntaxTest::errorMessage(_e) << endl;
+ return Result::Exception;
+ }
+ catch(FatalError const& _e)
+ {
+ FormattedScope(cout, m_formatted, {BOLD, RED}) <<
+ "FatalError: " << SyntaxTest::errorMessage(_e) << endl;
+ return Result::Exception;
+ }
+ catch(UnimplementedFeatureError const& _e)
+ {
+ FormattedScope(cout, m_formatted, {BOLD, RED}) <<
+ "UnimplementedFeatureError: " << SyntaxTest::errorMessage(_e) << endl;
+ return Result::Exception;
+ }
+ catch(...)
+ {
+ FormattedScope(cout, m_formatted, {BOLD, RED}) <<
+ "Unknown Exception" << endl;
+ return Result::Exception;
}
if (success)
@@ -137,25 +161,14 @@ SyntaxTestTool::Result SyntaxTestTool::process()
FormattedScope(cout, m_formatted, {BOLD, CYAN}) << " Contract:" << endl;
printContract();
- if (parserError)
- {
- cout << " ";
- FormattedScope(cout, m_formatted, {INVERSE, RED}) << "Parsing failed:" << endl;
- m_test->printErrorList(cout, m_test->compilerErrors(), " ", true, true, m_formatted);
- cout << endl;
- return Result::ParserError;
- }
- else
- {
- cout << outputMessages.str() << endl;
- return Result::Failure;
- }
+ cout << outputMessages.str() << endl;
+ return Result::Failure;
}
}
-SyntaxTestTool::Request SyntaxTestTool::handleResponse(bool const _parserError)
+SyntaxTestTool::Request SyntaxTestTool::handleResponse(bool const _exception)
{
- if (_parserError)
+ if (_exception)
cout << "(e)dit/(s)kip/(q)uit? ";
else
cout << "(e)dit/(u)pdate expectations/(s)kip/(q)uit? ";
@@ -169,7 +182,7 @@ SyntaxTestTool::Request SyntaxTestTool::handleResponse(bool const _parserError)
cout << endl;
return Request::Skip;
case 'u':
- if (_parserError)
+ if (_exception)
break;
else
{
@@ -178,7 +191,7 @@ SyntaxTestTool::Request SyntaxTestTool::handleResponse(bool const _parserError)
file << m_test->source();
file << "// ----" << endl;
if (!m_test->errorList().empty())
- m_test->printErrorList(file, m_test->errorList(), "// ", false, false, false);
+ m_test->printErrorList(file, m_test->errorList(), "// ", false);
return Request::Rerun;
}
case 'e':
@@ -231,8 +244,8 @@ SyntaxTestStats SyntaxTestTool::processPath(
switch(result)
{
case Result::Failure:
- case Result::ParserError:
- switch(testTool.handleResponse(result == Result::ParserError))
+ case Result::Exception:
+ switch(testTool.handleResponse(result == Result::Exception))
{
case Request::Quit:
return { successCount, runCount };