aboutsummaryrefslogtreecommitdiffstats
path: root/test/libsolidity
diff options
context:
space:
mode:
Diffstat (limited to 'test/libsolidity')
-rw-r--r--test/libsolidity/AnalysisFramework.cpp45
-rw-r--r--test/libsolidity/AnalysisFramework.h11
-rw-r--r--test/libsolidity/GasMeter.cpp10
-rw-r--r--test/libsolidity/SMTChecker.cpp86
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp25
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp161
-rw-r--r--test/libsolidity/StandardCompiler.cpp177
7 files changed, 485 insertions, 30 deletions
diff --git a/test/libsolidity/AnalysisFramework.cpp b/test/libsolidity/AnalysisFramework.cpp
index 5f5f6411..3bdc40a0 100644
--- a/test/libsolidity/AnalysisFramework.cpp
+++ b/test/libsolidity/AnalysisFramework.cpp
@@ -25,6 +25,8 @@
#include <libsolidity/ast/AST.h>
+#include <libsolidity/parsing/Scanner.h>
+
#include <libdevcore/SHA3.h>
#include <boost/test/unit_test.hpp>
@@ -46,8 +48,7 @@ AnalysisFramework::parseAnalyseAndReturnError(
m_compiler.addSource("", _insertVersionPragma ? "pragma solidity >=0.0;\n" + _source : _source);
if (!m_compiler.parse())
{
- printErrors();
- BOOST_ERROR("Parsing contract failed in analysis test suite.");
+ BOOST_ERROR("Parsing contract failed in analysis test suite:" + formatErrors());
}
m_compiler.analyze();
@@ -56,15 +57,24 @@ AnalysisFramework::parseAnalyseAndReturnError(
for (auto const& currentError: m_compiler.errors())
{
solAssert(currentError->comment(), "");
- if (currentError->comment()->find("This is a pre-release compiler version") == 0)
- continue;
+ if (currentError->type() == Error::Type::Warning)
+ {
+ bool ignoreWarning = false;
+ for (auto const& filter: m_warningsToFilter)
+ if (currentError->comment()->find(filter) == 0)
+ {
+ ignoreWarning = true;
+ break;
+ }
+ if (ignoreWarning)
+ continue;
+ }
if (_reportWarnings || (currentError->type() != Error::Type::Warning))
{
if (firstError && !_allowMultipleErrors)
{
- printErrors();
- BOOST_FAIL("Multiple errors found.");
+ BOOST_FAIL("Multiple errors found: " + formatErrors());
}
if (!firstError)
firstError = currentError;
@@ -78,7 +88,10 @@ SourceUnit const* AnalysisFramework::parseAndAnalyse(string const& _source)
{
auto sourceAndError = parseAnalyseAndReturnError(_source);
BOOST_REQUIRE(!!sourceAndError.first);
- BOOST_REQUIRE(!sourceAndError.second);
+ string message;
+ if (sourceAndError.second)
+ message = "Unexpected error: " + formatError(*sourceAndError.second);
+ BOOST_REQUIRE_MESSAGE(!sourceAndError.second, message);
return sourceAndError.first;
}
@@ -91,17 +104,23 @@ Error AnalysisFramework::expectError(std::string const& _source, bool _warning,
{
auto sourceAndError = parseAnalyseAndReturnError(_source, _warning, true, _allowMultiple);
BOOST_REQUIRE(!!sourceAndError.second);
- BOOST_REQUIRE(!!sourceAndError.first);
+ BOOST_REQUIRE_MESSAGE(!!sourceAndError.first, "Expected error, but no error happened.");
return *sourceAndError.second;
}
-void AnalysisFramework::printErrors()
+string AnalysisFramework::formatErrors()
{
+ string message;
for (auto const& error: m_compiler.errors())
- SourceReferenceFormatter::printExceptionInformation(
- std::cerr,
- *error,
- (error->type() == Error::Type::Warning) ? "Warning" : "Error",
+ message += formatError(*error);
+ return message;
+}
+
+string AnalysisFramework::formatError(Error const& _error)
+{
+ return SourceReferenceFormatter::formatExceptionInformation(
+ _error,
+ (_error.type() == Error::Type::Warning) ? "Warning" : "Error",
[&](std::string const& _sourceName) -> solidity::Scanner const& { return m_compiler.scanner(_sourceName); }
);
}
diff --git a/test/libsolidity/AnalysisFramework.h b/test/libsolidity/AnalysisFramework.h
index 172ae01b..a566ba1d 100644
--- a/test/libsolidity/AnalysisFramework.h
+++ b/test/libsolidity/AnalysisFramework.h
@@ -45,7 +45,7 @@ class AnalysisFramework
{
protected:
- std::pair<SourceUnit const*, std::shared_ptr<Error const>>
+ virtual std::pair<SourceUnit const*, std::shared_ptr<Error const>>
parseAnalyseAndReturnError(
std::string const& _source,
bool _reportWarnings = false,
@@ -57,7 +57,8 @@ protected:
bool success(std::string const& _source);
Error expectError(std::string const& _source, bool _warning = false, bool _allowMultiple = false);
- void printErrors();
+ std::string formatErrors();
+ std::string formatError(Error const& _error);
static ContractDefinition const* retrieveContractByName(SourceUnit const& _source, std::string const& _name);
static FunctionTypePointer retrieveFunctionBySignature(
@@ -65,6 +66,7 @@ protected:
std::string const& _signature
);
+ std::vector<std::string> m_warningsToFilter = {"This is a pre-release compiler version"};
dev::solidity::CompilerStack m_compiler;
};
@@ -104,7 +106,10 @@ CHECK_ERROR_OR_WARNING(text, Warning, substring, true, true)
do \
{ \
auto sourceAndError = parseAnalyseAndReturnError((text), true); \
- BOOST_CHECK(sourceAndError.second == nullptr); \
+ std::string message; \
+ if (sourceAndError.second) \
+ message = formatError(*sourceAndError.second); \
+ BOOST_CHECK_MESSAGE(!sourceAndError.second, message); \
} \
while(0)
diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp
index b759678f..c2886f5b 100644
--- a/test/libsolidity/GasMeter.cpp
+++ b/test/libsolidity/GasMeter.cpp
@@ -21,7 +21,6 @@
*/
#include <test/libsolidity/SolidityExecutionFramework.h>
-#include <libevmasm/EVMSchedule.h>
#include <libevmasm/GasMeter.h>
#include <libevmasm/KnownState.h>
#include <libevmasm/PathGasMeter.h>
@@ -63,15 +62,13 @@ public:
void testCreationTimeGas(string const& _sourceCode)
{
- EVMSchedule schedule;
-
compileAndRun(_sourceCode);
auto state = make_shared<KnownState>();
PathGasMeter meter(*m_compiler.assemblyItems());
GasMeter::GasConsumption gas = meter.estimateMax(0, state);
u256 bytecodeSize(m_compiler.runtimeObject().bytecode.size());
// costs for deployment
- gas += bytecodeSize * schedule.createDataGas;
+ gas += bytecodeSize * GasCosts::createDataGas;
// costs for transaction
gas += gasForTransaction(m_compiler.object().bytecode, true);
@@ -103,10 +100,9 @@ public:
static GasMeter::GasConsumption gasForTransaction(bytes const& _data, bool _isCreation)
{
- EVMSchedule schedule;
- GasMeter::GasConsumption gas = _isCreation ? schedule.txCreateGas : schedule.txGas;
+ GasMeter::GasConsumption gas = _isCreation ? GasCosts::txCreateGas : GasCosts::txGas;
for (auto i: _data)
- gas += i != 0 ? schedule.txDataNonZeroGas : schedule.txDataZeroGas;
+ gas += i != 0 ? GasCosts::txDataNonZeroGas : GasCosts::txDataZeroGas;
return gas;
}
diff --git a/test/libsolidity/SMTChecker.cpp b/test/libsolidity/SMTChecker.cpp
new file mode 100644
index 00000000..d58f296f
--- /dev/null
+++ b/test/libsolidity/SMTChecker.cpp
@@ -0,0 +1,86 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * Unit tests for the SMT checker.
+ */
+
+#include <test/libsolidity/AnalysisFramework.h>
+
+#include <boost/test/unit_test.hpp>
+
+#include <string>
+
+using namespace std;
+
+namespace dev
+{
+namespace solidity
+{
+namespace test
+{
+
+class SMTCheckerFramework: public AnalysisFramework
+{
+public:
+ SMTCheckerFramework()
+ {
+ m_warningsToFilter.push_back("Experimental features are turned on.");
+ }
+
+protected:
+ virtual std::pair<SourceUnit const*, std::shared_ptr<Error const>>
+ parseAnalyseAndReturnError(
+ std::string const& _source,
+ bool _reportWarnings = false,
+ bool _insertVersionPragma = true,
+ bool _allowMultipleErrors = false
+ )
+ {
+ return AnalysisFramework::parseAnalyseAndReturnError(
+ "pragma experimental SMTChecker;\n" + _source,
+ _reportWarnings,
+ _insertVersionPragma,
+ _allowMultipleErrors
+ );
+ }
+};
+
+BOOST_FIXTURE_TEST_SUITE(SMTChecker, SMTCheckerFramework)
+
+BOOST_AUTO_TEST_CASE(smoke_test)
+{
+ string text = R"(
+ contract C { }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+}
+
+BOOST_AUTO_TEST_CASE(simple_overflow)
+{
+ string text = R"(
+ contract C {
+ function f(uint a, uint b) public pure returns (uint) { return a + b; }
+ }
+ )";
+ CHECK_WARNING(text, "Overflow (resulting value larger than");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+}
+}
+}
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index df9332c4..35916ec7 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -10151,6 +10151,31 @@ BOOST_AUTO_TEST_CASE(constant_string)
ABI_CHECK(callContractFunction("h()"), encodeDyn(string("hello")));
}
+BOOST_AUTO_TEST_CASE(address_overload_resolution)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function balance() returns (uint) {
+ return 1;
+ }
+ function transfer(uint amount) returns (uint) {
+ return amount;
+ }
+ }
+ contract D {
+ function f() returns (uint) {
+ return (new C()).balance();
+ }
+ function g() returns (uint) {
+ return (new C()).transfer(5);
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "D");
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1)));
+ BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(5)));
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp
index 39c47f9c..350d41f1 100644
--- a/test/libsolidity/SolidityNameAndTypeResolution.cpp
+++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp
@@ -1395,6 +1395,61 @@ BOOST_AUTO_TEST_CASE(events_with_same_name)
BOOST_CHECK(success(text));
}
+BOOST_AUTO_TEST_CASE(events_with_same_name_unnamed_arguments)
+{
+ char const* text = R"(
+ contract test {
+ event A(uint);
+ event A(uint, uint);
+ }
+ )";
+ CHECK_SUCCESS(text);
+}
+
+BOOST_AUTO_TEST_CASE(events_with_same_name_different_types)
+{
+ char const* text = R"(
+ contract test {
+ event A(uint);
+ event A(bytes);
+ }
+ )";
+ CHECK_SUCCESS(text);
+}
+
+BOOST_AUTO_TEST_CASE(double_event_declaration)
+{
+ char const* text = R"(
+ contract test {
+ event A(uint i);
+ event A(uint i);
+ }
+ )";
+ CHECK_ERROR(text, DeclarationError, "Event with same name and arguments defined twice.");
+}
+
+BOOST_AUTO_TEST_CASE(double_event_declaration_ignores_anonymous)
+{
+ char const* text = R"(
+ contract test {
+ event A(uint i);
+ event A(uint i) anonymous;
+ }
+ )";
+ CHECK_ERROR(text, DeclarationError, "Event with same name and arguments defined twice.");
+}
+
+BOOST_AUTO_TEST_CASE(double_event_declaration_ignores_indexed)
+{
+ char const* text = R"(
+ contract test {
+ event A(uint i);
+ event A(uint indexed i);
+ }
+ )";
+ CHECK_ERROR(text, DeclarationError, "Event with same name and arguments defined twice.");
+}
+
BOOST_AUTO_TEST_CASE(event_call)
{
char const* text = R"(
@@ -2306,17 +2361,28 @@ BOOST_AUTO_TEST_CASE(assigning_value_to_const_variable)
CHECK_ERROR(text, TypeError, "Cannot assign to a constant variable.");
}
-BOOST_AUTO_TEST_CASE(assigning_state_to_const_variable)
+BOOST_AUTO_TEST_CASE(assigning_state_to_const_variable_0_4_x)
{
char const* text = R"(
contract C {
address constant x = msg.sender;
}
)";
- // Change to TypeError for 0.5.0.
CHECK_WARNING(text, "Initial value for constant variable has to be compile-time constant.");
}
+BOOST_AUTO_TEST_CASE(assigning_state_to_const_variable)
+{
+ char const* text = R"(
+ pragma experimental "v0.5.0";
+
+ contract C {
+ address constant x = msg.sender;
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "Initial value for constant variable has to be compile-time constant.");
+}
+
BOOST_AUTO_TEST_CASE(constant_string_literal_disallows_assignment)
{
char const* text = R"(
@@ -2333,7 +2399,7 @@ BOOST_AUTO_TEST_CASE(constant_string_literal_disallows_assignment)
CHECK_ERROR(text, TypeError, "Index access for string is not possible.");
}
-BOOST_AUTO_TEST_CASE(assign_constant_function_value_to_constant)
+BOOST_AUTO_TEST_CASE(assign_constant_function_value_to_constant_0_4_x)
{
char const* text = R"(
contract C {
@@ -2341,10 +2407,22 @@ BOOST_AUTO_TEST_CASE(assign_constant_function_value_to_constant)
uint constant y = x();
}
)";
- // Change to TypeError for 0.5.0.
CHECK_WARNING(text, "Initial value for constant variable has to be compile-time constant.");
}
+BOOST_AUTO_TEST_CASE(assign_constant_function_value_to_constant)
+{
+ char const* text = R"(
+ pragma experimental "v0.5.0";
+
+ contract C {
+ function () constant returns (uint) x;
+ uint constant y = x();
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "Initial value for constant variable has to be compile-time constant.");
+}
+
BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_conversion)
{
char const* text = R"(
@@ -4135,6 +4213,8 @@ BOOST_AUTO_TEST_CASE(rational_unary_operation)
}
)";
CHECK_SUCCESS_NO_WARNINGS(text);
+
+ // Test deprecation warning under < 0.5.0
text = R"(
contract test {
function f() pure public {
@@ -4154,6 +4234,29 @@ BOOST_AUTO_TEST_CASE(rational_unary_operation)
}
)";
CHECK_WARNING(text,"Use of unary + is deprecated");
+
+ // Test syntax error under 0.5.0
+ text = R"(
+ pragma experimental "v0.5.0";
+ contract test {
+ function f() pure public {
+ ufixed16x2 a = +3.25;
+ fixed16x2 b = -3.25;
+ a; b;
+ }
+ }
+ )";
+ CHECK_ERROR(text, SyntaxError, "Use of unary + is deprecated");
+ text = R"(
+ pragma experimental "v0.5.0";
+ contract test {
+ function f(uint x) pure public {
+ uint y = +x;
+ y;
+ }
+ }
+ )";
+ CHECK_ERROR(text, SyntaxError, "Use of unary + is deprecated");
}
BOOST_AUTO_TEST_CASE(leading_zero_rationals_convert)
@@ -4251,7 +4354,7 @@ BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_rational)
}
}
)";
- CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal");
+ CHECK_ERROR(text, TypeError, "Array with fractional length specified.");
}
BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_signed_fixed_type)
@@ -4263,7 +4366,7 @@ BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_signed_fixed_type)
}
}
)";
- CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal");
+ CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal.");
}
BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_unsigned_fixed_type)
@@ -4275,7 +4378,7 @@ BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_unsigned_fixed_type)
}
}
)";
- CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal");
+ CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal.");
}
BOOST_AUTO_TEST_CASE(rational_to_bytes_implicit_conversion)
@@ -6268,6 +6371,17 @@ BOOST_AUTO_TEST_CASE(function_override_is_not_shadowing)
CHECK_SUCCESS_NO_WARNINGS(text);
}
+BOOST_AUTO_TEST_CASE(event_parameter_cannot_shadow_state_variable)
+{
+ char const* text = R"(
+ contract C {
+ address a;
+ event E(address a);
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+}
+
BOOST_AUTO_TEST_CASE(callable_crash)
{
char const* text = R"(
@@ -6953,6 +7067,39 @@ BOOST_AUTO_TEST_CASE(warn_about_suicide)
CHECK_WARNING(text, "\"suicide\" has been deprecated in favour of \"selfdestruct\"");
}
+BOOST_AUTO_TEST_CASE(address_overload_resolution)
+{
+ char const* text = R"(
+ contract C {
+ function balance() returns (uint) {
+ this.balance; // to avoid pureness warning
+ return 1;
+ }
+ function transfer(uint amount) {
+ address(this).transfer(amount); // to avoid pureness warning
+ }
+ }
+ contract D {
+ function f() {
+ var x = (new C()).balance();
+ x;
+ (new C()).transfer(5);
+ }
+ }
+ )";
+ CHECK_SUCCESS(text);
+}
+
+BOOST_AUTO_TEST_CASE(array_length_validation)
+{
+ char const* text = R"(
+ contract C {
+ uint[8**90] ids;
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal.");
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp
index 24f915c0..4504946b 100644
--- a/test/libsolidity/StandardCompiler.cpp
+++ b/test/libsolidity/StandardCompiler.cpp
@@ -226,6 +226,183 @@ BOOST_AUTO_TEST_CASE(basic_compilation)
);
}
+BOOST_AUTO_TEST_CASE(output_selection_explicit)
+{
+ char const* input = R"(
+ {
+ "language": "Solidity",
+ "settings": {
+ "outputSelection": {
+ "fileA": {
+ "A": [
+ "abi"
+ ]
+ }
+ }
+ },
+ "sources": {
+ "fileA": {
+ "content": "contract A { }"
+ }
+ }
+ }
+ )";
+ Json::Value result = compile(input);
+ BOOST_CHECK(containsAtMostWarnings(result));
+ Json::Value contract = getContractResult(result, "fileA", "A");
+ BOOST_CHECK(contract.isObject());
+ BOOST_CHECK(contract["abi"].isArray());
+ BOOST_CHECK_EQUAL(dev::jsonCompactPrint(contract["abi"]), "[]");
+}
+
+BOOST_AUTO_TEST_CASE(output_selection_all_contracts)
+{
+ char const* input = R"(
+ {
+ "language": "Solidity",
+ "settings": {
+ "outputSelection": {
+ "fileA": {
+ "*": [
+ "abi"
+ ]
+ }
+ }
+ },
+ "sources": {
+ "fileA": {
+ "content": "contract A { }"
+ }
+ }
+ }
+ )";
+ Json::Value result = compile(input);
+ BOOST_CHECK(containsAtMostWarnings(result));
+ Json::Value contract = getContractResult(result, "fileA", "A");
+ BOOST_CHECK(contract.isObject());
+ BOOST_CHECK(contract["abi"].isArray());
+ BOOST_CHECK_EQUAL(dev::jsonCompactPrint(contract["abi"]), "[]");
+}
+
+BOOST_AUTO_TEST_CASE(output_selection_all_files_single_contract)
+{
+ char const* input = R"(
+ {
+ "language": "Solidity",
+ "settings": {
+ "outputSelection": {
+ "*": {
+ "A": [
+ "abi"
+ ]
+ }
+ }
+ },
+ "sources": {
+ "fileA": {
+ "content": "contract A { }"
+ }
+ }
+ }
+ )";
+ Json::Value result = compile(input);
+ BOOST_CHECK(containsAtMostWarnings(result));
+ Json::Value contract = getContractResult(result, "fileA", "A");
+ BOOST_CHECK(contract.isObject());
+ BOOST_CHECK(contract["abi"].isArray());
+ BOOST_CHECK_EQUAL(dev::jsonCompactPrint(contract["abi"]), "[]");
+}
+
+BOOST_AUTO_TEST_CASE(output_selection_all_files_all_contracts)
+{
+ char const* input = R"(
+ {
+ "language": "Solidity",
+ "settings": {
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi"
+ ]
+ }
+ }
+ },
+ "sources": {
+ "fileA": {
+ "content": "contract A { }"
+ }
+ }
+ }
+ )";
+ Json::Value result = compile(input);
+ BOOST_CHECK(containsAtMostWarnings(result));
+ Json::Value contract = getContractResult(result, "fileA", "A");
+ BOOST_CHECK(contract.isObject());
+ BOOST_CHECK(contract["abi"].isArray());
+ BOOST_CHECK_EQUAL(dev::jsonCompactPrint(contract["abi"]), "[]");
+}
+
+BOOST_AUTO_TEST_CASE(output_selection_dependent_contract)
+{
+ char const* input = R"(
+ {
+ "language": "Solidity",
+ "settings": {
+ "outputSelection": {
+ "*": {
+ "A": [
+ "abi"
+ ]
+ }
+ }
+ },
+ "sources": {
+ "fileA": {
+ "content": "contract B { } contract A { function f() { new B(); } }"
+ }
+ }
+ }
+ )";
+ Json::Value result = compile(input);
+ BOOST_CHECK(containsAtMostWarnings(result));
+ Json::Value contract = getContractResult(result, "fileA", "A");
+ BOOST_CHECK(contract.isObject());
+ BOOST_CHECK(contract["abi"].isArray());
+ BOOST_CHECK_EQUAL(dev::jsonCompactPrint(contract["abi"]), "[{\"constant\":false,\"inputs\":[],\"name\":\"f\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]");
+}
+
+BOOST_AUTO_TEST_CASE(output_selection_dependent_contract_with_import)
+{
+ char const* input = R"(
+ {
+ "language": "Solidity",
+ "settings": {
+ "outputSelection": {
+ "*": {
+ "A": [
+ "abi"
+ ]
+ }
+ }
+ },
+ "sources": {
+ "fileA": {
+ "content": "import \"fileB\"; contract A { function f() { new B(); } }"
+ },
+ "fileB": {
+ "content": "contract B { }"
+ }
+ }
+ }
+ )";
+ Json::Value result = compile(input);
+ BOOST_CHECK(containsAtMostWarnings(result));
+ Json::Value contract = getContractResult(result, "fileA", "A");
+ BOOST_CHECK(contract.isObject());
+ BOOST_CHECK(contract["abi"].isArray());
+ BOOST_CHECK_EQUAL(dev::jsonCompactPrint(contract["abi"]), "[{\"constant\":false,\"inputs\":[],\"name\":\"f\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]");
+}
+
BOOST_AUTO_TEST_SUITE_END()
}