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
64ea4a1959
@ -41,13 +41,9 @@ public:
|
|||||||
{
|
{
|
||||||
m_compilerStack.parse(_code);
|
m_compilerStack.parse(_code);
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch(boost::exception const& _e)
|
||||||
{
|
{
|
||||||
std::string const* extra = boost::get_error_info<errinfo_comment>(e);
|
auto msg = std::string("Parsing contract failed with: ") + boost::diagnostic_information(_e);
|
||||||
std::string msg = std::string("Parsing contract failed with: ") +
|
|
||||||
e.what() + std::string("\n");
|
|
||||||
if (extra)
|
|
||||||
msg += *extra;
|
|
||||||
BOOST_FAIL(msg);
|
BOOST_FAIL(msg);
|
||||||
}
|
}
|
||||||
std::string generatedInterfaceString = m_compilerStack.getMetadata("", DocumentationType::ABI_INTERFACE);
|
std::string generatedInterfaceString = m_compilerStack.getMetadata("", DocumentationType::ABI_INTERFACE);
|
||||||
|
@ -64,7 +64,7 @@ bytes compileContract(const string& _sourceCode)
|
|||||||
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
|
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
|
||||||
{
|
{
|
||||||
Compiler compiler;
|
Compiler compiler;
|
||||||
compiler.compileContract(*contract, {}, map<ContractDefinition const*, bytes const*>{});
|
compiler.compileContract(*contract, map<ContractDefinition const*, bytes const*>{});
|
||||||
|
|
||||||
// debug
|
// debug
|
||||||
//compiler.streamAssembly(cout);
|
//compiler.streamAssembly(cout);
|
||||||
|
@ -772,6 +772,94 @@ BOOST_AUTO_TEST_CASE(struct_reference)
|
|||||||
BOOST_CHECK(callContractFunction("check()") == encodeArgs(true));
|
BOOST_CHECK(callContractFunction("check()") == encodeArgs(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(deleteStruct)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
contract test {
|
||||||
|
struct topStruct {
|
||||||
|
nestedStruct nstr;
|
||||||
|
emptyStruct empty;
|
||||||
|
uint topValue;
|
||||||
|
mapping (uint => uint) topMapping;
|
||||||
|
}
|
||||||
|
uint toDelete;
|
||||||
|
topStruct str;
|
||||||
|
struct nestedStruct {
|
||||||
|
uint nestedValue;
|
||||||
|
mapping (uint => bool) nestedMapping;
|
||||||
|
}
|
||||||
|
struct emptyStruct{
|
||||||
|
}
|
||||||
|
function test(){
|
||||||
|
toDelete = 5;
|
||||||
|
str.topValue = 1;
|
||||||
|
str.topMapping[0] = 1;
|
||||||
|
str.topMapping[1] = 2;
|
||||||
|
|
||||||
|
str.nstr.nestedValue = 2;
|
||||||
|
str.nstr.nestedMapping[0] = true;
|
||||||
|
str.nstr.nestedMapping[1] = false;
|
||||||
|
delete str;
|
||||||
|
delete toDelete;
|
||||||
|
}
|
||||||
|
function getToDelete() returns (uint res){
|
||||||
|
res = toDelete;
|
||||||
|
}
|
||||||
|
function getTopValue() returns(uint topValue){
|
||||||
|
topValue = str.topValue;
|
||||||
|
}
|
||||||
|
function getNestedValue() returns(uint nestedValue){
|
||||||
|
nestedValue = str.nstr.nestedValue;
|
||||||
|
}
|
||||||
|
function getTopMapping(uint index) returns(uint ret) {
|
||||||
|
ret = str.topMapping[index];
|
||||||
|
}
|
||||||
|
function getNestedMapping(uint index) returns(bool ret) {
|
||||||
|
return str.nstr.nestedMapping[index];
|
||||||
|
}
|
||||||
|
})";
|
||||||
|
compileAndRun(sourceCode);
|
||||||
|
BOOST_CHECK(callContractFunction("getToDelete()") == encodeArgs(0));
|
||||||
|
BOOST_CHECK(callContractFunction("getTopValue()") == encodeArgs(0));
|
||||||
|
BOOST_CHECK(callContractFunction("getNestedValue()") == encodeArgs(0));
|
||||||
|
// mapping values should be the same
|
||||||
|
BOOST_CHECK(callContractFunction("getTopMapping(uint256)", 0) == encodeArgs(1));
|
||||||
|
BOOST_CHECK(callContractFunction("getTopMapping(uint256)", 1) == encodeArgs(2));
|
||||||
|
BOOST_CHECK(callContractFunction("getNestedMapping(uint256)", 0) == encodeArgs(true));
|
||||||
|
BOOST_CHECK(callContractFunction("getNestedMapping(uint256)", 1) == encodeArgs(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(deleteLocal)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
contract test {
|
||||||
|
function delLocal() returns (uint res){
|
||||||
|
uint v = 5;
|
||||||
|
delete v;
|
||||||
|
res = v;
|
||||||
|
}
|
||||||
|
})";
|
||||||
|
compileAndRun(sourceCode);
|
||||||
|
BOOST_CHECK(callContractFunction("delLocal()") == encodeArgs(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(deleteLocals)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
contract test {
|
||||||
|
function delLocal() returns (uint res1, uint res2){
|
||||||
|
uint v = 5;
|
||||||
|
uint w = 6;
|
||||||
|
uint x = 7;
|
||||||
|
delete v;
|
||||||
|
res1 = w;
|
||||||
|
res2 = x;
|
||||||
|
}
|
||||||
|
})";
|
||||||
|
compileAndRun(sourceCode);
|
||||||
|
BOOST_CHECK(callContractFunction("delLocal()") == encodeArgs(6, 7));
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(constructor)
|
BOOST_AUTO_TEST_CASE(constructor)
|
||||||
{
|
{
|
||||||
char const* sourceCode = "contract test {\n"
|
char const* sourceCode = "contract test {\n"
|
||||||
@ -1243,6 +1331,7 @@ BOOST_AUTO_TEST_CASE(constructor_arguments)
|
|||||||
contract Helper {
|
contract Helper {
|
||||||
string3 name;
|
string3 name;
|
||||||
bool flag;
|
bool flag;
|
||||||
|
|
||||||
function Helper(string3 x, bool f) {
|
function Helper(string3 x, bool f) {
|
||||||
name = x;
|
name = x;
|
||||||
flag = f;
|
flag = f;
|
||||||
@ -1404,6 +1493,163 @@ BOOST_AUTO_TEST_CASE(value_for_constructor)
|
|||||||
BOOST_REQUIRE(callContractFunction("getBalances()") == encodeArgs(12, 10));
|
BOOST_REQUIRE(callContractFunction("getBalances()") == encodeArgs(12, 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(virtual_function_calls)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
contract Base {
|
||||||
|
function f() returns (uint i) { return g(); }
|
||||||
|
function g() returns (uint i) { return 1; }
|
||||||
|
}
|
||||||
|
contract Derived is Base {
|
||||||
|
function g() returns (uint i) { return 2; }
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
compileAndRun(sourceCode, 0, "Derived");
|
||||||
|
BOOST_CHECK(callContractFunction("g()") == encodeArgs(2));
|
||||||
|
BOOST_CHECK(callContractFunction("f()") == encodeArgs(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(access_base_storage)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
contract Base {
|
||||||
|
uint dataBase;
|
||||||
|
function getViaBase() returns (uint i) { return dataBase; }
|
||||||
|
}
|
||||||
|
contract Derived is Base {
|
||||||
|
uint dataDerived;
|
||||||
|
function setData(uint base, uint derived) returns (bool r) {
|
||||||
|
dataBase = base;
|
||||||
|
dataDerived = derived;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
function getViaDerived() returns (uint base, uint derived) {
|
||||||
|
base = dataBase;
|
||||||
|
derived = dataDerived;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
compileAndRun(sourceCode, 0, "Derived");
|
||||||
|
BOOST_CHECK(callContractFunction("setData(uint256,uint256)", 1, 2) == encodeArgs(true));
|
||||||
|
BOOST_CHECK(callContractFunction("getViaBase()") == encodeArgs(1));
|
||||||
|
BOOST_CHECK(callContractFunction("getViaDerived()") == encodeArgs(1, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(single_copy_with_multiple_inheritance)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
contract Base {
|
||||||
|
uint data;
|
||||||
|
function setData(uint i) { data = i; }
|
||||||
|
function getViaBase() returns (uint i) { return data; }
|
||||||
|
}
|
||||||
|
contract A is Base { function setViaA(uint i) { setData(i); } }
|
||||||
|
contract B is Base { function getViaB() returns (uint i) { return getViaBase(); } }
|
||||||
|
contract Derived is A, B, Base { }
|
||||||
|
)";
|
||||||
|
compileAndRun(sourceCode, 0, "Derived");
|
||||||
|
BOOST_CHECK(callContractFunction("getViaB()") == encodeArgs(0));
|
||||||
|
BOOST_CHECK(callContractFunction("setViaA(uint256)", 23) == encodeArgs());
|
||||||
|
BOOST_CHECK(callContractFunction("getViaB()") == encodeArgs(23));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(explicit_base_cass)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
contract BaseBase { function g() returns (uint r) { return 1; } }
|
||||||
|
contract Base is BaseBase { function g() returns (uint r) { return 2; } }
|
||||||
|
contract Derived is Base {
|
||||||
|
function f() returns (uint r) { return BaseBase.g(); }
|
||||||
|
function g() returns (uint r) { return 3; }
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
compileAndRun(sourceCode, 0, "Derived");
|
||||||
|
BOOST_CHECK(callContractFunction("g()") == encodeArgs(3));
|
||||||
|
BOOST_CHECK(callContractFunction("f()") == encodeArgs(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(base_constructor_arguments)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
contract BaseBase {
|
||||||
|
uint m_a;
|
||||||
|
function BaseBase(uint a) {
|
||||||
|
m_a = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contract Base is BaseBase(7) {
|
||||||
|
function Base() {
|
||||||
|
m_a *= m_a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contract Derived is Base() {
|
||||||
|
function getA() returns (uint r) { return m_a; }
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
compileAndRun(sourceCode, 0, "Derived");
|
||||||
|
BOOST_CHECK(callContractFunction("getA()") == encodeArgs(7 * 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(function_usage_in_constructor_arguments)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
contract BaseBase {
|
||||||
|
uint m_a;
|
||||||
|
function BaseBase(uint a) {
|
||||||
|
m_a = a;
|
||||||
|
}
|
||||||
|
function g() returns (uint r) { return 2; }
|
||||||
|
}
|
||||||
|
contract Base is BaseBase(BaseBase.g()) {
|
||||||
|
}
|
||||||
|
contract Derived is Base() {
|
||||||
|
function getA() returns (uint r) { return m_a; }
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
compileAndRun(sourceCode, 0, "Derived");
|
||||||
|
BOOST_CHECK(callContractFunction("getA()") == encodeArgs(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(virtual_function_usage_in_constructor_arguments)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
contract BaseBase {
|
||||||
|
uint m_a;
|
||||||
|
function BaseBase(uint a) {
|
||||||
|
m_a = a;
|
||||||
|
}
|
||||||
|
function overridden() returns (uint r) { return 1; }
|
||||||
|
function g() returns (uint r) { return overridden(); }
|
||||||
|
}
|
||||||
|
contract Base is BaseBase(BaseBase.g()) {
|
||||||
|
}
|
||||||
|
contract Derived is Base() {
|
||||||
|
function getA() returns (uint r) { return m_a; }
|
||||||
|
function overridden() returns (uint r) { return 2; }
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
compileAndRun(sourceCode, 0, "Derived");
|
||||||
|
BOOST_CHECK(callContractFunction("getA()") == encodeArgs(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(constructor_argument_overriding)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
contract BaseBase {
|
||||||
|
uint m_a;
|
||||||
|
function BaseBase(uint a) {
|
||||||
|
m_a = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contract Base is BaseBase(2) { }
|
||||||
|
contract Derived is Base, BaseBase(3) {
|
||||||
|
function getA() returns (uint r) { return m_a; }
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
compileAndRun(sourceCode, 0, "Derived");
|
||||||
|
BOOST_CHECK(callContractFunction("getA()") == encodeArgs(3));
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -86,13 +86,19 @@ Declaration const& resolveDeclaration(vector<string> const& _namespacedName,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bytes compileFirstExpression(const string& _sourceCode, vector<vector<string>> _functions = {},
|
bytes compileFirstExpression(const string& _sourceCode, vector<vector<string>> _functions = {},
|
||||||
vector<vector<string>> _localVariables = {})
|
vector<vector<string>> _localVariables = {}, vector<shared_ptr<MagicVariableDeclaration const>> _globalDeclarations = {})
|
||||||
{
|
{
|
||||||
Parser parser;
|
Parser parser;
|
||||||
ASTPointer<SourceUnit> sourceUnit;
|
ASTPointer<SourceUnit> sourceUnit;
|
||||||
BOOST_REQUIRE_NO_THROW(sourceUnit = parser.parse(make_shared<Scanner>(CharStream(_sourceCode))));
|
BOOST_REQUIRE_NO_THROW(sourceUnit = parser.parse(make_shared<Scanner>(CharStream(_sourceCode))));
|
||||||
NameAndTypeResolver resolver({});
|
|
||||||
|
vector<Declaration const*> declarations;
|
||||||
|
declarations.reserve(_globalDeclarations.size() + 1);
|
||||||
|
for (ASTPointer<Declaration const> const& variable: _globalDeclarations)
|
||||||
|
declarations.push_back(variable.get());
|
||||||
|
NameAndTypeResolver resolver(declarations);
|
||||||
resolver.registerDeclarations(*sourceUnit);
|
resolver.registerDeclarations(*sourceUnit);
|
||||||
|
|
||||||
for (ASTPointer<ASTNode> const& node: sourceUnit->getNodes())
|
for (ASTPointer<ASTNode> const& node: sourceUnit->getNodes())
|
||||||
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
|
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
|
||||||
{
|
{
|
||||||
@ -390,6 +396,21 @@ BOOST_AUTO_TEST_CASE(intermediately_overflowing_literals)
|
|||||||
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
|
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(blockhash)
|
||||||
|
{
|
||||||
|
char const* sourceCode = "contract test {\n"
|
||||||
|
" function f() {\n"
|
||||||
|
" block.blockhash(3);\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
|
bytes code = compileFirstExpression(sourceCode, {}, {},
|
||||||
|
{make_shared<MagicVariableDeclaration>("block", make_shared<MagicType>(MagicType::Kind::BLOCK))});
|
||||||
|
|
||||||
|
bytes expectation({byte(eth::Instruction::PUSH1), 0x03,
|
||||||
|
byte(eth::Instruction::BLOCKHASH)});
|
||||||
|
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -357,7 +357,6 @@ BOOST_AUTO_TEST_CASE(function_canonical_signature_type_aliases)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(hash_collision_in_interface)
|
BOOST_AUTO_TEST_CASE(hash_collision_in_interface)
|
||||||
{
|
{
|
||||||
char const* text = "contract test {\n"
|
char const* text = "contract test {\n"
|
||||||
@ -369,6 +368,128 @@ BOOST_AUTO_TEST_CASE(hash_collision_in_interface)
|
|||||||
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
|
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(inheritance_basic)
|
||||||
|
{
|
||||||
|
char const* text = R"(
|
||||||
|
contract base { uint baseMember; struct BaseType { uint element; } }
|
||||||
|
contract derived is base {
|
||||||
|
BaseType data;
|
||||||
|
function f() { baseMember = 7; }
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(inheritance_diamond_basic)
|
||||||
|
{
|
||||||
|
char const* text = R"(
|
||||||
|
contract root { function rootFunction() {} }
|
||||||
|
contract inter1 is root { function f() {} }
|
||||||
|
contract inter2 is root { function f() {} }
|
||||||
|
contract derived is inter1, inter2, root {
|
||||||
|
function g() { f(); rootFunction(); }
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(cyclic_inheritance)
|
||||||
|
{
|
||||||
|
char const* text = R"(
|
||||||
|
contract A is B { }
|
||||||
|
contract B is A { }
|
||||||
|
)";
|
||||||
|
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(illegal_override_direct)
|
||||||
|
{
|
||||||
|
char const* text = R"(
|
||||||
|
contract B { function f() {} }
|
||||||
|
contract C is B { function f(uint i) {} }
|
||||||
|
)";
|
||||||
|
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(illegal_override_indirect)
|
||||||
|
{
|
||||||
|
char const* text = R"(
|
||||||
|
contract A { function f(uint a) {} }
|
||||||
|
contract B { function f() {} }
|
||||||
|
contract C is A, B { }
|
||||||
|
)";
|
||||||
|
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(complex_inheritance)
|
||||||
|
{
|
||||||
|
char const* text = R"(
|
||||||
|
contract A { function f() { uint8 x = C(0).g(); } }
|
||||||
|
contract B { function f() {} function g() returns (uint8 r) {} }
|
||||||
|
contract C is A, B { }
|
||||||
|
)";
|
||||||
|
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(constructor_visibility)
|
||||||
|
{
|
||||||
|
// The constructor of a base class should not be visible in the derived class
|
||||||
|
char const* text = R"(
|
||||||
|
contract A { function A() { } }
|
||||||
|
contract B is A { function f() { A x = A(0); } }
|
||||||
|
)";
|
||||||
|
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(overriding_constructor)
|
||||||
|
{
|
||||||
|
// It is fine to "override" constructor of a base class since it is invisible
|
||||||
|
char const* text = R"(
|
||||||
|
contract A { function A() { } }
|
||||||
|
contract B is A { function A() returns (uint8 r) {} }
|
||||||
|
)";
|
||||||
|
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(missing_base_constructor_arguments)
|
||||||
|
{
|
||||||
|
char const* text = R"(
|
||||||
|
contract A { function A(uint a) { } }
|
||||||
|
contract B is A { }
|
||||||
|
)";
|
||||||
|
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(base_constructor_arguments_override)
|
||||||
|
{
|
||||||
|
char const* text = R"(
|
||||||
|
contract A { function A(uint a) { } }
|
||||||
|
contract B is A { }
|
||||||
|
)";
|
||||||
|
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(implicit_derived_to_base_conversion)
|
||||||
|
{
|
||||||
|
char const* text = R"(
|
||||||
|
contract A { }
|
||||||
|
contract B is A {
|
||||||
|
function f() { A a = B(1); }
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
|
||||||
|
}
|
||||||
|
BOOST_AUTO_TEST_CASE(implicit_base_to_derived_conversion)
|
||||||
|
{
|
||||||
|
char const* text = R"(
|
||||||
|
contract A { }
|
||||||
|
contract B is A {
|
||||||
|
function f() { B b = A(1); }
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -45,13 +45,9 @@ public:
|
|||||||
{
|
{
|
||||||
m_compilerStack.parse(_code);
|
m_compilerStack.parse(_code);
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch(boost::exception const& _e)
|
||||||
{
|
{
|
||||||
std::string const* extra = boost::get_error_info<errinfo_comment>(e);
|
auto msg = std::string("Parsing contract failed with: ") + boost::diagnostic_information(_e);
|
||||||
std::string msg = std::string("Parsing contract failed with: ") +
|
|
||||||
e.what() + std::string("\n");
|
|
||||||
if (extra)
|
|
||||||
msg += *extra;
|
|
||||||
BOOST_FAIL(msg);
|
BOOST_FAIL(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -510,17 +506,35 @@ BOOST_AUTO_TEST_CASE(dev_title_at_function_error)
|
|||||||
BOOST_CHECK_THROW(checkNatspec(sourceCode, natspec, false), DocstringParsingError);
|
BOOST_CHECK_THROW(checkNatspec(sourceCode, natspec, false), DocstringParsingError);
|
||||||
}
|
}
|
||||||
|
|
||||||
// test for bug where having no tags in docstring would cause infinite loop
|
BOOST_AUTO_TEST_CASE(natspec_notice_without_tag)
|
||||||
BOOST_AUTO_TEST_CASE(natspec_no_tags)
|
|
||||||
{
|
{
|
||||||
char const* sourceCode = "contract test {\n"
|
char const* sourceCode = "contract test {\n"
|
||||||
" /// I do something awesome\n"
|
" /// I do something awesome\n"
|
||||||
" function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n"
|
" function mul(uint a) returns(uint d) { return a * 7; }\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
char const* natspec = "{\"methods\": {}}";
|
char const* natspec = "{"
|
||||||
|
"\"methods\":{"
|
||||||
|
" \"mul(uint256)\":{ \"notice\": \"I do something awesome\"}"
|
||||||
|
"}}";
|
||||||
|
|
||||||
checkNatspec(sourceCode, natspec, false);
|
checkNatspec(sourceCode, natspec, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(natspec_multiline_notice_without_tag)
|
||||||
|
{
|
||||||
|
char const* sourceCode = "contract test {\n"
|
||||||
|
" /// I do something awesome\n"
|
||||||
|
" /// which requires two lines to explain\n"
|
||||||
|
" function mul(uint a) returns(uint d) { return a * 7; }\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
char const* natspec = "{"
|
||||||
|
"\"methods\":{"
|
||||||
|
" \"mul(uint256)\":{ \"notice\": \"I do something awesome which requires two lines to explain\"}"
|
||||||
|
"}}";
|
||||||
|
|
||||||
|
checkNatspec(sourceCode, natspec, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
@ -495,6 +495,51 @@ BOOST_AUTO_TEST_CASE(multiple_contracts_and_imports)
|
|||||||
BOOST_CHECK_NO_THROW(parseText(text));
|
BOOST_CHECK_NO_THROW(parseText(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(contract_inheritance)
|
||||||
|
{
|
||||||
|
char const* text = "contract base {\n"
|
||||||
|
" function fun() {\n"
|
||||||
|
" uint64(2);\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n"
|
||||||
|
"contract derived is base {\n"
|
||||||
|
" function fun() {\n"
|
||||||
|
" uint64(2);\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseText(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(contract_multiple_inheritance)
|
||||||
|
{
|
||||||
|
char const* text = "contract base {\n"
|
||||||
|
" function fun() {\n"
|
||||||
|
" uint64(2);\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n"
|
||||||
|
"contract derived is base, nonExisting {\n"
|
||||||
|
" function fun() {\n"
|
||||||
|
" uint64(2);\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseText(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(contract_multiple_inheritance_with_arguments)
|
||||||
|
{
|
||||||
|
char const* text = "contract base {\n"
|
||||||
|
" function fun() {\n"
|
||||||
|
" uint64(2);\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n"
|
||||||
|
"contract derived is base(2), nonExisting(\"abc\", \"def\", base.fun()) {\n"
|
||||||
|
" function fun() {\n"
|
||||||
|
" uint64(2);\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseText(text));
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ void ImportTest::importState(json_spirit::mObject& _o, State& _state)
|
|||||||
if (code.size())
|
if (code.size())
|
||||||
{
|
{
|
||||||
_state.m_cache[address] = Account(toInt(o["balance"]), Account::ContractConception);
|
_state.m_cache[address] = Account(toInt(o["balance"]), Account::ContractConception);
|
||||||
_state.m_cache[address].setCode(bytesConstRef(&code));
|
_state.m_cache[address].setCode(code);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_state.m_cache[address] = Account(toInt(o["balance"]), Account::NormalCreation);
|
_state.m_cache[address] = Account(toInt(o["balance"]), Account::NormalCreation);
|
||||||
|
@ -46,7 +46,16 @@ public:
|
|||||||
bytes const& compileAndRun(std::string const& _sourceCode, u256 const& _value = 0, std::string const& _contractName = "")
|
bytes const& compileAndRun(std::string const& _sourceCode, u256 const& _value = 0, std::string const& _contractName = "")
|
||||||
{
|
{
|
||||||
dev::solidity::CompilerStack compiler;
|
dev::solidity::CompilerStack compiler;
|
||||||
compiler.compile(_sourceCode, m_optimize);
|
try
|
||||||
|
{
|
||||||
|
compiler.compile(_sourceCode, m_optimize);
|
||||||
|
}
|
||||||
|
catch(boost::exception const& _e)
|
||||||
|
{
|
||||||
|
auto msg = std::string("Compiling contract failed with: ") + boost::diagnostic_information(_e);
|
||||||
|
BOOST_FAIL(msg);
|
||||||
|
}
|
||||||
|
|
||||||
bytes code = compiler.getBytecode(_contractName);
|
bytes code = compiler.getBytecode(_contractName);
|
||||||
sendMessage(code, true, _value);
|
sendMessage(code, true, _value);
|
||||||
BOOST_REQUIRE(!m_output.empty());
|
BOOST_REQUIRE(!m_output.empty());
|
||||||
@ -97,6 +106,7 @@ public:
|
|||||||
static bytes encode(char const* _value) { return encode(std::string(_value)); }
|
static bytes encode(char const* _value) { return encode(std::string(_value)); }
|
||||||
static bytes encode(byte _value) { return bytes(31, 0) + bytes{_value}; }
|
static bytes encode(byte _value) { return bytes(31, 0) + bytes{_value}; }
|
||||||
static bytes encode(u256 const& _value) { return toBigEndian(_value); }
|
static bytes encode(u256 const& _value) { return toBigEndian(_value); }
|
||||||
|
static bytes encode(h256 const& _value) { return _value.asBytes(); }
|
||||||
static bytes encode(bytes const& _value, bool _padLeft = true)
|
static bytes encode(bytes const& _value, bool _padLeft = true)
|
||||||
{
|
{
|
||||||
bytes padding = bytes((32 - _value.size() % 32) % 32, 0);
|
bytes padding = bytes((32 - _value.size() % 32) % 32, 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user