Merge branch 'develop' of https://github.com/ethereum/cpp-ethereum into develop

This commit is contained in:
winsvega 2015-02-10 13:19:27 +03:00
commit 30db15c1a9
23 changed files with 1249 additions and 136 deletions

View File

@ -21,8 +21,10 @@ target_link_libraries(testeth ethereum)
target_link_libraries(testeth ethcore) target_link_libraries(testeth ethcore)
target_link_libraries(testeth secp256k1) target_link_libraries(testeth secp256k1)
target_link_libraries(testeth solidity) target_link_libraries(testeth solidity)
target_link_libraries(testeth webthree) if (NOT HEADLESS)
target_link_libraries(testeth webthree)
target_link_libraries(testeth natspec)
endif()
if (JSONRPC) if (JSONRPC)
target_link_libraries(testeth web3jsonrpc) target_link_libraries(testeth web3jsonrpc)
target_link_libraries(testeth ${JSON_RPC_CPP_CLIENT_LIBRARIES}) target_link_libraries(testeth ${JSON_RPC_CPP_CLIENT_LIBRARIES})

View File

@ -32,12 +32,12 @@ namespace solidity
namespace test namespace test
{ {
class InterfaceChecker class JSONInterfaceChecker
{ {
public: public:
InterfaceChecker(): m_compilerStack(false) {} JSONInterfaceChecker(): m_compilerStack(false) {}
void checkInterface(std::string const& _code, std::string const& _expectedInterfaceString, std::string const& expectedSolidityInterface) void checkInterface(std::string const& _code, std::string const& _expectedInterfaceString)
{ {
try try
{ {
@ -48,8 +48,7 @@ public:
auto msg = std::string("Parsing contract failed with: ") + boost::diagnostic_information(_e); auto msg = std::string("Parsing contract failed with: ") + boost::diagnostic_information(_e);
BOOST_FAIL(msg); BOOST_FAIL(msg);
} }
std::string generatedInterfaceString = m_compilerStack.getMetadata("", DocumentationType::ABI_INTERFACE); std::string generatedInterfaceString = m_compilerStack.getMetadata("", DocumentationType::ABIInterface);
std::string generatedSolidityInterfaceString = m_compilerStack.getMetadata("", DocumentationType::ABI_SOLIDITY_INTERFACE);
Json::Value generatedInterface; Json::Value generatedInterface;
m_reader.parse(generatedInterfaceString, generatedInterface); m_reader.parse(generatedInterfaceString, generatedInterface);
Json::Value expectedInterface; Json::Value expectedInterface;
@ -57,9 +56,6 @@ public:
BOOST_CHECK_MESSAGE(expectedInterface == generatedInterface, BOOST_CHECK_MESSAGE(expectedInterface == generatedInterface,
"Expected:\n" << expectedInterface.toStyledString() << "Expected:\n" << expectedInterface.toStyledString() <<
"\n but got:\n" << generatedInterface.toStyledString()); "\n but got:\n" << generatedInterface.toStyledString());
BOOST_CHECK_MESSAGE(expectedSolidityInterface == generatedSolidityInterfaceString,
"Expected:\n" << expectedSolidityInterface <<
"\n but got:\n" << generatedSolidityInterfaceString);
} }
private: private:
@ -67,7 +63,7 @@ private:
Json::Reader m_reader; Json::Reader m_reader;
}; };
BOOST_FIXTURE_TEST_SUITE(SolidityABIJSON, InterfaceChecker) BOOST_FIXTURE_TEST_SUITE(SolidityABIJSON, JSONInterfaceChecker)
BOOST_AUTO_TEST_CASE(basic_test) BOOST_AUTO_TEST_CASE(basic_test)
{ {
@ -75,8 +71,6 @@ BOOST_AUTO_TEST_CASE(basic_test)
" function f(uint a) returns(uint d) { return a * 7; }\n" " function f(uint a) returns(uint d) { return a * 7; }\n"
"}\n"; "}\n";
char const* sourceInterface = "contract test{function f(uint256 a)returns(uint256 d){}}";
char const* interface = R"([ char const* interface = R"([
{ {
"name": "f", "name": "f",
@ -97,18 +91,16 @@ BOOST_AUTO_TEST_CASE(basic_test)
} }
])"; ])";
checkInterface(sourceCode, interface, sourceInterface); checkInterface(sourceCode, interface);
} }
BOOST_AUTO_TEST_CASE(empty_contract) BOOST_AUTO_TEST_CASE(empty_contract)
{ {
char const* sourceCode = "contract test {\n" char const* sourceCode = "contract test {\n"
"}\n"; "}\n";
char const* sourceInterface = "contract test{}";
char const* interface = "[]"; char const* interface = "[]";
checkInterface(sourceCode, interface, sourceInterface); checkInterface(sourceCode, interface);
} }
BOOST_AUTO_TEST_CASE(multiple_methods) BOOST_AUTO_TEST_CASE(multiple_methods)
@ -117,7 +109,6 @@ BOOST_AUTO_TEST_CASE(multiple_methods)
" function f(uint a) returns(uint d) { return a * 7; }\n" " function f(uint a) returns(uint d) { return a * 7; }\n"
" function g(uint b) returns(uint e) { return b * 8; }\n" " function g(uint b) returns(uint e) { return b * 8; }\n"
"}\n"; "}\n";
char const* sourceInterface = "contract test{function f(uint256 a)returns(uint256 d){}function g(uint256 b)returns(uint256 e){}}";
char const* interface = R"([ char const* interface = R"([
{ {
@ -156,7 +147,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods)
} }
])"; ])";
checkInterface(sourceCode, interface, sourceInterface); checkInterface(sourceCode, interface);
} }
BOOST_AUTO_TEST_CASE(multiple_params) BOOST_AUTO_TEST_CASE(multiple_params)
@ -164,7 +155,6 @@ BOOST_AUTO_TEST_CASE(multiple_params)
char const* sourceCode = "contract test {\n" char const* sourceCode = "contract test {\n"
" function f(uint a, uint b) returns(uint d) { return a + b; }\n" " function f(uint a, uint b) returns(uint d) { return a + b; }\n"
"}\n"; "}\n";
char const* sourceInterface = "contract test{function f(uint256 a,uint256 b)returns(uint256 d){}}";
char const* interface = R"([ char const* interface = R"([
{ {
@ -190,7 +180,7 @@ BOOST_AUTO_TEST_CASE(multiple_params)
} }
])"; ])";
checkInterface(sourceCode, interface, sourceInterface); checkInterface(sourceCode, interface);
} }
BOOST_AUTO_TEST_CASE(multiple_methods_order) BOOST_AUTO_TEST_CASE(multiple_methods_order)
@ -200,7 +190,6 @@ BOOST_AUTO_TEST_CASE(multiple_methods_order)
" function f(uint a) returns(uint d) { return a * 7; }\n" " function f(uint a) returns(uint d) { return a * 7; }\n"
" function c(uint b) returns(uint e) { return b * 8; }\n" " function c(uint b) returns(uint e) { return b * 8; }\n"
"}\n"; "}\n";
char const* sourceInterface = "contract test{function c(uint256 b)returns(uint256 e){}function f(uint256 a)returns(uint256 d){}}";
char const* interface = R"([ char const* interface = R"([
{ {
@ -239,7 +228,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods_order)
} }
])"; ])";
checkInterface(sourceCode, interface, sourceInterface); checkInterface(sourceCode, interface);
} }
BOOST_AUTO_TEST_CASE(const_function) BOOST_AUTO_TEST_CASE(const_function)
@ -248,7 +237,6 @@ BOOST_AUTO_TEST_CASE(const_function)
" function foo(uint a, uint b) returns(uint d) { return a + b; }\n" " function foo(uint a, uint b) returns(uint d) { return a + b; }\n"
" function boo(uint32 a) constant returns(uint b) { return a * 4; }\n" " function boo(uint32 a) constant returns(uint b) { return a * 4; }\n"
"}\n"; "}\n";
char const* sourceInterface = "contract test{function foo(uint256 a,uint256 b)returns(uint256 d){}function boo(uint32 a)constant returns(uint256 b){}}";
char const* interface = R"([ char const* interface = R"([
{ {
@ -289,17 +277,16 @@ BOOST_AUTO_TEST_CASE(const_function)
} }
])"; ])";
checkInterface(sourceCode, interface, sourceInterface); checkInterface(sourceCode, interface);
} }
BOOST_AUTO_TEST_CASE(exclude_fallback_function) BOOST_AUTO_TEST_CASE(exclude_fallback_function)
{ {
char const* sourceCode = "contract test { function() {} }"; char const* sourceCode = "contract test { function() {} }";
char const* sourceInterface = "contract test{}";
char const* interface = "[]"; char const* interface = "[]";
checkInterface(sourceCode, interface, sourceInterface); checkInterface(sourceCode, interface);
} }
BOOST_AUTO_TEST_CASE(events) BOOST_AUTO_TEST_CASE(events)
@ -309,8 +296,6 @@ BOOST_AUTO_TEST_CASE(events)
" event e1(uint b, address indexed c); \n" " event e1(uint b, address indexed c); \n"
" event e2(); \n" " event e2(); \n"
"}\n"; "}\n";
char const* sourceInterface = "contract test{function f(uint256 a)returns(uint256 d){}event e1(uint256 b,address indexed c);event e2;}";
char const* interface = R"([ char const* interface = R"([
{ {
"name": "f", "name": "f",
@ -353,7 +338,7 @@ BOOST_AUTO_TEST_CASE(events)
])"; ])";
checkInterface(sourceCode, interface, sourceInterface); checkInterface(sourceCode, interface);
} }
@ -368,7 +353,6 @@ BOOST_AUTO_TEST_CASE(inherited)
" function derivedFunction(string32 p) returns (string32 i) { return p; } \n" " function derivedFunction(string32 p) returns (string32 i) { return p; } \n"
" event derivedEvent(uint indexed evtArgDerived); \n" " event derivedEvent(uint indexed evtArgDerived); \n"
" }"; " }";
char const* sourceInterface = "contract Derived{function baseFunction(uint256 p)returns(uint256 i){}function derivedFunction(string32 p)returns(string32 i){}event derivedEvent(uint256 indexed evtArgDerived);event baseEvent(string32 indexed evtArgBase);}";
char const* interface = R"([ char const* interface = R"([
{ {
@ -423,9 +407,80 @@ BOOST_AUTO_TEST_CASE(inherited)
}])"; }])";
checkInterface(sourceCode, interface, sourceInterface); checkInterface(sourceCode, interface);
}
BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one)
{
char const* sourceCode = R"(
contract test {
function f(uint, uint k) returns(uint ret_k, uint ret_g){
uint g = 8;
ret_k = k;
ret_g = g;
}
})";
char const* interface = R"([
{
"name": "f",
"constant": false,
"type": "function",
"inputs": [
{
"name": "",
"type": "uint256"
},
{
"name": "k",
"type": "uint256"
}
],
"outputs": [
{
"name": "ret_k",
"type": "uint256"
},
{
"name": "ret_g",
"type": "uint256"
}
]
}
])";
checkInterface(sourceCode, interface);
} }
BOOST_AUTO_TEST_CASE(empty_name_return_parameter)
{
char const* sourceCode = R"(
contract test {
function f(uint k) returns(uint){
return k;
}
})";
char const* interface = R"([
{
"name": "f",
"constant": false,
"type": "function",
"inputs": [
{
"name": "k",
"type": "uint256"
}
],
"outputs": [
{
"name": "",
"type": "uint256"
}
]
}
])";
checkInterface(sourceCode, interface);
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

View File

@ -92,6 +92,26 @@ BOOST_AUTO_TEST_CASE(multiple_functions)
BOOST_CHECK(callContractFunction("i_am_not_there()", bytes()) == bytes()); BOOST_CHECK(callContractFunction("i_am_not_there()", bytes()) == bytes());
} }
BOOST_AUTO_TEST_CASE(named_args)
{
char const* sourceCode = "contract test {\n"
" function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }\n"
" function b() returns (uint r) { r = a({a: 1, b: 2, c: 3}); }\n"
"}\n";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("b()", bytes()) == toBigEndian(u256(123)));
}
BOOST_AUTO_TEST_CASE(disorder_named_args)
{
char const* sourceCode = "contract test {\n"
" function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }\n"
" function b() returns (uint r) { r = a({c: 3, a: 1, b: 2}); }\n"
"}\n";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("b()", bytes()) == toBigEndian(u256(123)));
}
BOOST_AUTO_TEST_CASE(while_loop) BOOST_AUTO_TEST_CASE(while_loop)
{ {
char const* sourceCode = "contract test {\n" char const* sourceCode = "contract test {\n"
@ -556,7 +576,7 @@ BOOST_AUTO_TEST_CASE(simple_mapping)
" }\n" " }\n"
"}"; "}";
compileAndRun(sourceCode); compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("get(uint8)", byte(0)) == encodeArgs(byte(0x00))); BOOST_CHECK(callContractFunction("get(uint8)", byte(0)) == encodeArgs(byte(0x00)));
BOOST_CHECK(callContractFunction("get(uint8)", byte(0x01)) == encodeArgs(byte(0x00))); BOOST_CHECK(callContractFunction("get(uint8)", byte(0x01)) == encodeArgs(byte(0x00)));
BOOST_CHECK(callContractFunction("get(uint8)", byte(0xa7)) == encodeArgs(byte(0x00))); BOOST_CHECK(callContractFunction("get(uint8)", byte(0xa7)) == encodeArgs(byte(0x00)));
@ -885,7 +905,7 @@ BOOST_AUTO_TEST_CASE(constructor)
BOOST_AUTO_TEST_CASE(simple_accessor) BOOST_AUTO_TEST_CASE(simple_accessor)
{ {
char const* sourceCode = "contract test {\n" char const* sourceCode = "contract test {\n"
" uint256 data;\n" " uint256 public data;\n"
" function test() {\n" " function test() {\n"
" data = 8;\n" " data = 8;\n"
" }\n" " }\n"
@ -897,10 +917,10 @@ BOOST_AUTO_TEST_CASE(simple_accessor)
BOOST_AUTO_TEST_CASE(multiple_elementary_accessors) BOOST_AUTO_TEST_CASE(multiple_elementary_accessors)
{ {
char const* sourceCode = "contract test {\n" char const* sourceCode = "contract test {\n"
" uint256 data;\n" " uint256 public data;\n"
" string6 name;\n" " string6 public name;\n"
" hash a_hash;\n" " hash public a_hash;\n"
" address an_address;\n" " address public an_address;\n"
" function test() {\n" " function test() {\n"
" data = 8;\n" " data = 8;\n"
" name = \"Celina\";\n" " name = \"Celina\";\n"
@ -908,17 +928,55 @@ BOOST_AUTO_TEST_CASE(multiple_elementary_accessors)
" an_address = address(0x1337);\n" " an_address = address(0x1337);\n"
" super_secret_data = 42;\n" " super_secret_data = 42;\n"
" }\n" " }\n"
" private:"
" uint256 super_secret_data;" " uint256 super_secret_data;"
"}\n"; "}\n";
compileAndRun(sourceCode); compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("data()") == encodeArgs(8)); BOOST_CHECK(callContractFunction("data()") == encodeArgs(8));
BOOST_CHECK(callContractFunction("name()") == encodeArgs("Celina")); BOOST_CHECK(callContractFunction("name()") == encodeArgs("Celina"));
BOOST_CHECK(callContractFunction("a_hash()") == encodeArgs(dev::sha3(toBigEndian(u256(123))))); BOOST_CHECK(callContractFunction("a_hash()") == encodeArgs(dev::sha3(bytes({0x7b}))));
BOOST_CHECK(callContractFunction("an_address()") == encodeArgs(toBigEndian(u160(0x1337)))); BOOST_CHECK(callContractFunction("an_address()") == encodeArgs(toBigEndian(u160(0x1337))));
BOOST_CHECK(callContractFunction("super_secret_data()") == bytes()); BOOST_CHECK(callContractFunction("super_secret_data()") == bytes());
} }
BOOST_AUTO_TEST_CASE(complex_accessors)
{
char const* sourceCode = "contract test {\n"
" mapping(uint256 => string4) public to_string_map;\n"
" mapping(uint256 => bool) public to_bool_map;\n"
" mapping(uint256 => uint256) public to_uint_map;\n"
" mapping(uint256 => mapping(uint256 => uint256)) public to_multiple_map;\n"
" function test() {\n"
" to_string_map[42] = \"24\";\n"
" to_bool_map[42] = false;\n"
" to_uint_map[42] = 12;\n"
" to_multiple_map[42][23] = 31;\n"
" }\n"
"}\n";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("to_string_map(uint256)", 42) == encodeArgs("24"));
BOOST_CHECK(callContractFunction("to_bool_map(uint256)", 42) == encodeArgs(false));
BOOST_CHECK(callContractFunction("to_uint_map(uint256)", 42) == encodeArgs(12));
BOOST_CHECK(callContractFunction("to_multiple_map(uint256,uint256)", 42, 23) == encodeArgs(31));
}
BOOST_AUTO_TEST_CASE(struct_accessor)
{
char const* sourceCode = R"(
contract test {
struct Data { uint a; uint8 b; mapping(uint => uint) c; bool d; }
mapping(uint => Data) public data;
function test() {
data[7].a = 1;
data[7].b = 2;
data[7].c[0] = 3;
data[7].d = true;
}
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("data(uint256)", 7) == encodeArgs(1, 2, true));
}
BOOST_AUTO_TEST_CASE(balance) BOOST_AUTO_TEST_CASE(balance)
{ {
char const* sourceCode = "contract test {\n" char const* sourceCode = "contract test {\n"
@ -1490,8 +1548,7 @@ BOOST_AUTO_TEST_CASE(functions_called_by_constructor)
setName("abc"); setName("abc");
} }
function getName() returns (string3 ret) { return name; } function getName() returns (string3 ret) { return name; }
private: function setName(string3 _name) private { name = _name; }
function setName(string3 _name) { name = _name; }
})"; })";
compileAndRun(sourceCode); compileAndRun(sourceCode);
BOOST_REQUIRE(callContractFunction("getName()") == encodeArgs("abc")); BOOST_REQUIRE(callContractFunction("getName()") == encodeArgs("abc"));
@ -2056,6 +2113,94 @@ BOOST_AUTO_TEST_CASE(event_lots_of_data)
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("Deposit(address,hash256,uint256,bool)"))); BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("Deposit(address,hash256,uint256,bool)")));
} }
BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one)
{
char const* sourceCode = R"(
contract test {
function f(uint, uint k) returns(uint ret_k, uint ret_g){
uint g = 8;
ret_k = k;
ret_g = g;
}
})";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("f(uint256,uint256)", 5, 9) != encodeArgs(5, 8));
BOOST_CHECK(callContractFunction("f(uint256,uint256)", 5, 9) == encodeArgs(9, 8));
}
BOOST_AUTO_TEST_CASE(empty_name_return_parameter)
{
char const* sourceCode = R"(
contract test {
function f(uint k) returns(uint){
return k;
}
})";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("f(uint256)", 9) == encodeArgs(9));
}
BOOST_AUTO_TEST_CASE(sha3_multiple_arguments)
{
char const* sourceCode = R"(
contract c {
function foo(uint a, uint b, uint c) returns (hash d)
{
d = sha3(a, b, c);
}
})";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("foo(uint256,uint256,uint256)", 10, 12, 13) == encodeArgs(
dev::sha3(
toBigEndian(u256(10)) +
toBigEndian(u256(12)) +
toBigEndian(u256(13)))));
}
BOOST_AUTO_TEST_CASE(sha3_multiple_arguments_with_numeric_literals)
{
char const* sourceCode = R"(
contract c {
function foo(uint a, uint16 b) returns (hash d)
{
d = sha3(a, b, 145);
}
})";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("foo(uint256,uint16)", 10, 12) == encodeArgs(
dev::sha3(
toBigEndian(u256(10)) +
bytes({0x0, 0xc}) +
bytes({0x91}))));
}
BOOST_AUTO_TEST_CASE(sha3_multiple_arguments_with_string_literals)
{
char const* sourceCode = R"(
contract c {
function foo() returns (hash d)
{
d = sha3("foo");
}
function bar(uint a, uint16 b) returns (hash d)
{
d = sha3(a, b, 145, "foo");
}
})";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("foo()") == encodeArgs(dev::sha3("foo")));
BOOST_CHECK(callContractFunction("bar(uint256,uint16)", 10, 12) == encodeArgs(
dev::sha3(
toBigEndian(u256(10)) +
bytes({0x0, 0xc}) +
bytes({0x91}) +
bytes({0x66, 0x6f, 0x6f}))));
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
} }

View File

@ -91,7 +91,15 @@ bytes compileFirstExpression(const string& _sourceCode, vector<vector<string>> _
{ {
Parser parser; Parser parser;
ASTPointer<SourceUnit> sourceUnit; ASTPointer<SourceUnit> sourceUnit;
BOOST_REQUIRE_NO_THROW(sourceUnit = parser.parse(make_shared<Scanner>(CharStream(_sourceCode)))); try
{
sourceUnit = parser.parse(make_shared<Scanner>(CharStream(_sourceCode)));
}
catch(boost::exception const& _e)
{
auto msg = std::string("Parsing source code failed with: \n") + boost::diagnostic_information(_e);
BOOST_FAIL(msg);
}
vector<Declaration const*> declarations; vector<Declaration const*> declarations;
declarations.reserve(_globalDeclarations.size() + 1); declarations.reserve(_globalDeclarations.size() + 1);
@ -177,6 +185,66 @@ BOOST_AUTO_TEST_CASE(int_literal)
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(int_with_wei_ether_subdenomination)
{
char const* sourceCode = R"(
contract test {
function test ()
{
var x = 1 wei;
}
})";
bytes code = compileFirstExpression(sourceCode);
bytes expectation({byte(eth::Instruction::PUSH1), 0x1});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
BOOST_AUTO_TEST_CASE(int_with_szabo_ether_subdenomination)
{
char const* sourceCode = R"(
contract test {
function test ()
{
var x = 1 szabo;
}
})";
bytes code = compileFirstExpression(sourceCode);
bytes expectation({byte(eth::Instruction::PUSH5), 0xe8, 0xd4, 0xa5, 0x10, 0x00});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
BOOST_AUTO_TEST_CASE(int_with_finney_ether_subdenomination)
{
char const* sourceCode = R"(
contract test {
function test ()
{
var x = 1 finney;
}
})";
bytes code = compileFirstExpression(sourceCode);
bytes expectation({byte(eth::Instruction::PUSH7), 0x3, 0x8d, 0x7e, 0xa4, 0xc6, 0x80, 0x00});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
BOOST_AUTO_TEST_CASE(int_with_ether_ether_subdenomination)
{
char const* sourceCode = R"(
contract test {
function test ()
{
var x = 1 ether;
}
})";
bytes code = compileFirstExpression(sourceCode);
bytes expectation({byte(eth::Instruction::PUSH8), 0xd, 0xe0, 0xb6, 0xb3, 0xa7, 0x64, 0x00, 0x00});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
BOOST_AUTO_TEST_CASE(comparison) BOOST_AUTO_TEST_CASE(comparison)
{ {
char const* sourceCode = "contract test {\n" char const* sourceCode = "contract test {\n"
@ -409,7 +477,7 @@ BOOST_AUTO_TEST_CASE(blockhash)
" }\n" " }\n"
"}\n"; "}\n";
bytes code = compileFirstExpression(sourceCode, {}, {}, bytes code = compileFirstExpression(sourceCode, {}, {},
{make_shared<MagicVariableDeclaration>("block", make_shared<MagicType>(MagicType::Kind::BLOCK))}); {make_shared<MagicVariableDeclaration>("block", make_shared<MagicType>(MagicType::Kind::Block))});
bytes expectation({byte(eth::Instruction::PUSH1), 0x03, bytes expectation({byte(eth::Instruction::PUSH1), 0x03,
byte(eth::Instruction::BLOCKHASH)}); byte(eth::Instruction::BLOCKHASH)});

173
SolidityInterface.cpp Normal file
View File

@ -0,0 +1,173 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum 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.
cpp-ethereum 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
* @date 2015
* Unit tests for generating source interfaces for Solidity contracts.
*/
#include <boost/test/unit_test.hpp>
#include <libsolidity/CompilerStack.h>
#include <libsolidity/AST.h>
using namespace std;
namespace dev
{
namespace solidity
{
namespace test
{
class SolidityInterfaceChecker
{
public:
SolidityInterfaceChecker(): m_compilerStack(false) {}
/// Compiles the given code, generates the interface and parses that again.
ContractDefinition const& checkInterface(string const& _code, string const& _contractName = "")
{
m_code = _code;
BOOST_REQUIRE_NO_THROW(m_compilerStack.parse(_code));
m_interface = m_compilerStack.getMetadata("", DocumentationType::ABISolidityInterface);
BOOST_REQUIRE_NO_THROW(m_reCompiler.parse(m_interface));
return m_reCompiler.getContractDefinition(_contractName);
}
string getSourcePart(ASTNode const& _node) const
{
Location location = _node.getLocation();
BOOST_REQUIRE(!location.isEmpty());
return m_interface.substr(location.start, location.end - location.start);
}
protected:
string m_code;
string m_interface;
CompilerStack m_compilerStack;
CompilerStack m_reCompiler;
};
BOOST_FIXTURE_TEST_SUITE(SolidityInterface, SolidityInterfaceChecker)
BOOST_AUTO_TEST_CASE(empty_contract)
{
ContractDefinition const& contract = checkInterface("contract test {}");
BOOST_CHECK_EQUAL(getSourcePart(contract), "contract test{}");
}
BOOST_AUTO_TEST_CASE(single_function)
{
ContractDefinition const& contract = checkInterface(
"contract test {\n"
" function f(uint a) returns(uint d) { return a * 7; }\n"
"}\n");
BOOST_REQUIRE_EQUAL(1, contract.getDefinedFunctions().size());
BOOST_CHECK_EQUAL(getSourcePart(*contract.getDefinedFunctions().front()),
"function f(uint256 a)returns(uint256 d){}");
}
BOOST_AUTO_TEST_CASE(single_constant_function)
{
ContractDefinition const& contract = checkInterface(
"contract test { function f(uint a) constant returns(hash8 x) { 1==2; } }");
BOOST_REQUIRE_EQUAL(1, contract.getDefinedFunctions().size());
BOOST_CHECK_EQUAL(getSourcePart(*contract.getDefinedFunctions().front()),
"function f(uint256 a)constant returns(hash8 x){}");
}
BOOST_AUTO_TEST_CASE(multiple_functions)
{
char const* sourceCode = "contract test {\n"
" function f(uint a) returns(uint d) { return a * 7; }\n"
" function g(uint b) returns(uint e) { return b * 8; }\n"
"}\n";
ContractDefinition const& contract = checkInterface(sourceCode);
set<string> expectation({"function f(uint256 a)returns(uint256 d){}",
"function g(uint256 b)returns(uint256 e){}"});
BOOST_REQUIRE_EQUAL(2, contract.getDefinedFunctions().size());
BOOST_CHECK(expectation == set<string>({getSourcePart(*contract.getDefinedFunctions().at(0)),
getSourcePart(*contract.getDefinedFunctions().at(1))}));
}
BOOST_AUTO_TEST_CASE(exclude_fallback_function)
{
char const* sourceCode = "contract test { function() {} }";
ContractDefinition const& contract = checkInterface(sourceCode);
BOOST_CHECK_EQUAL(getSourcePart(contract), "contract test{}");
}
BOOST_AUTO_TEST_CASE(event)
{
ContractDefinition const& contract = checkInterface(
"contract test { event Event; }");
BOOST_REQUIRE_EQUAL(1, contract.getEvents().size());
BOOST_CHECK_EQUAL(getSourcePart(*contract.getEvents().front()),
"event Event;");
}
BOOST_AUTO_TEST_CASE(event_arguments)
{
ContractDefinition const& contract = checkInterface(
"contract test { event Event(uint a, uint indexed b); }");
BOOST_REQUIRE_EQUAL(1, contract.getEvents().size());
BOOST_CHECK_EQUAL(getSourcePart(*contract.getEvents().front()),
"event Event(uint256 a,uint256 indexed b);");
}
BOOST_AUTO_TEST_CASE(events)
{
char const* sourceCode = "contract test {\n"
" function f(uint a) returns(uint d) { return a * 7; }\n"
" event e1(uint b, address indexed c); \n"
" event e2(); \n"
"}\n";
ContractDefinition const& contract = checkInterface(sourceCode);
set<string> expectation({"event e1(uint256 b,address indexed c);", "event e2;"});
BOOST_REQUIRE_EQUAL(2, contract.getEvents().size());
BOOST_CHECK(expectation == set<string>({getSourcePart(*contract.getEvents().at(0)),
getSourcePart(*contract.getEvents().at(1))}));
}
BOOST_AUTO_TEST_CASE(inheritance)
{
char const* sourceCode =
" contract Base { \n"
" function baseFunction(uint p) returns (uint i) { return p; } \n"
" event baseEvent(string32 indexed evtArgBase); \n"
" } \n"
" contract Derived is Base { \n"
" function derivedFunction(string32 p) returns (string32 i) { return p; } \n"
" event derivedEvent(uint indexed evtArgDerived); \n"
" }";
ContractDefinition const& contract = checkInterface(sourceCode);
set<string> expectedEvents({"event derivedEvent(uint256 indexed evtArgDerived);",
"event baseEvent(string32 indexed evtArgBase);"});
set<string> expectedFunctions({"function baseFunction(uint256 p)returns(uint256 i){}",
"function derivedFunction(string32 p)returns(string32 i){}"});
BOOST_CHECK(expectedEvents == set<string>({getSourcePart(*contract.getEvents().at(0)),
getSourcePart(*contract.getEvents().at(1))}));
BOOST_REQUIRE_EQUAL(2, contract.getDefinedFunctions().size());
BOOST_CHECK(expectedFunctions == set<string>({getSourcePart(*contract.getDefinedFunctions().at(0)),
getSourcePart(*contract.getDefinedFunctions().at(1))}));
}
BOOST_AUTO_TEST_SUITE_END()
}
}
}

View File

@ -467,6 +467,24 @@ BOOST_AUTO_TEST_CASE(illegal_override_indirect)
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
} }
BOOST_AUTO_TEST_CASE(illegal_override_visibility)
{
char const* text = R"(
contract B { function f() protected {} }
contract C is B { function f() public {} }
)";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(illegal_override_constness)
{
char const* text = R"(
contract B { function f() constant {} }
contract C is B { function f() {} }
)";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(complex_inheritance) BOOST_AUTO_TEST_CASE(complex_inheritance)
{ {
char const* text = R"( char const* text = R"(
@ -636,7 +654,9 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors)
" function fun() {\n" " function fun() {\n"
" uint64(2);\n" " uint64(2);\n"
" }\n" " }\n"
"uint256 foo;\n" "uint256 public foo;\n"
"mapping(uint=>string4) public map;\n"
"mapping(uint=>mapping(uint=>string4)) public multiple_map;\n"
"}\n"; "}\n";
ASTPointer<SourceUnit> source; ASTPointer<SourceUnit> source;
@ -644,10 +664,27 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors)
BOOST_CHECK_NO_THROW(source = parseTextAndResolveNamesWithChecks(text)); BOOST_CHECK_NO_THROW(source = parseTextAndResolveNamesWithChecks(text));
BOOST_REQUIRE((contract = retrieveContract(source, 0)) != nullptr); BOOST_REQUIRE((contract = retrieveContract(source, 0)) != nullptr);
FunctionTypePointer function = retrieveFunctionBySignature(contract, "foo()"); FunctionTypePointer function = retrieveFunctionBySignature(contract, "foo()");
BOOST_REQUIRE(function->hasDeclaration()); BOOST_REQUIRE(function && function->hasDeclaration());
auto returnParams = function->getReturnParameterTypeNames(); auto returnParams = function->getReturnParameterTypeNames();
BOOST_CHECK_EQUAL(returnParams.at(0), "uint256"); BOOST_CHECK_EQUAL(returnParams.at(0), "uint256");
BOOST_CHECK(function->isConstant()); BOOST_CHECK(function->isConstant());
function = retrieveFunctionBySignature(contract, "map(uint256)");
BOOST_REQUIRE(function && function->hasDeclaration());
auto params = function->getParameterTypeNames();
BOOST_CHECK_EQUAL(params.at(0), "uint256");
returnParams = function->getReturnParameterTypeNames();
BOOST_CHECK_EQUAL(returnParams.at(0), "string4");
BOOST_CHECK(function->isConstant());
function = retrieveFunctionBySignature(contract, "multiple_map(uint256,uint256)");
BOOST_REQUIRE(function && function->hasDeclaration());
params = function->getParameterTypeNames();
BOOST_CHECK_EQUAL(params.at(0), "uint256");
BOOST_CHECK_EQUAL(params.at(1), "uint256");
returnParams = function->getReturnParameterTypeNames();
BOOST_CHECK_EQUAL(returnParams.at(0), "string4");
BOOST_CHECK(function->isConstant());
} }
BOOST_AUTO_TEST_CASE(function_clash_with_state_variable_accessor) BOOST_AUTO_TEST_CASE(function_clash_with_state_variable_accessor)
@ -668,16 +705,19 @@ BOOST_AUTO_TEST_CASE(private_state_variable)
" function fun() {\n" " function fun() {\n"
" uint64(2);\n" " uint64(2);\n"
" }\n" " }\n"
"private:\n" "uint256 private foo;\n"
"uint256 foo;\n" "uint256 protected bar;\n"
"}\n"; "}\n";
ASTPointer<SourceUnit> source; ASTPointer<SourceUnit> source;
ContractDefinition const* contract; ContractDefinition const* contract;
BOOST_CHECK_NO_THROW(source = parseTextAndResolveNamesWithChecks(text)); BOOST_CHECK_NO_THROW(source = parseTextAndResolveNamesWithChecks(text));
BOOST_CHECK((contract = retrieveContract(source, 0)) != nullptr); BOOST_CHECK((contract = retrieveContract(source, 0)) != nullptr);
FunctionTypePointer function = retrieveFunctionBySignature(contract, "foo()"); FunctionTypePointer function;
function = retrieveFunctionBySignature(contract, "foo()");
BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of a private variable should not exist"); BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of a private variable should not exist");
function = retrieveFunctionBySignature(contract, "bar()");
BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of a protected variable should not exist");
} }
BOOST_AUTO_TEST_CASE(fallback_function) BOOST_AUTO_TEST_CASE(fallback_function)
@ -780,6 +820,160 @@ BOOST_AUTO_TEST_CASE(multiple_events_argument_clash)
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
} }
BOOST_AUTO_TEST_CASE(access_to_default_function_visibility)
{
char const* text = R"(
contract c {
function f() {}
}
contract d {
function g() { c(0).f(); }
})";
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
}
BOOST_AUTO_TEST_CASE(access_to_protected_function)
{
char const* text = R"(
contract c {
function f() protected {}
}
contract d {
function g() { c(0).f(); }
})";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(access_to_default_state_variable_visibility)
{
char const* text = R"(
contract c {
uint a;
}
contract d {
function g() { c(0).a(); }
})";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(access_to_protected_state_variable)
{
char const* text = R"(
contract c {
uint public a;
}
contract d {
function g() { c(0).a(); }
})";
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
}
BOOST_AUTO_TEST_CASE(error_count_in_named_args)
{
char const* sourceCode = "contract test {\n"
" function a(uint a, uint b) returns (uint r) { r = a + b; }\n"
" function b() returns (uint r) { r = a({a: 1}); }\n"
"}\n";
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
}
BOOST_AUTO_TEST_CASE(empty_in_named_args)
{
char const* sourceCode = "contract test {\n"
" function a(uint a, uint b) returns (uint r) { r = a + b; }\n"
" function b() returns (uint r) { r = a({}); }\n"
"}\n";
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
}
BOOST_AUTO_TEST_CASE(duplicate_parameter_names_in_named_args)
{
char const* sourceCode = "contract test {\n"
" function a(uint a, uint b) returns (uint r) { r = a + b; }\n"
" function b() returns (uint r) { r = a({a: 1, a: 2}); }\n"
"}\n";
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
}
BOOST_AUTO_TEST_CASE(invalid_parameter_names_in_named_args)
{
char const* sourceCode = "contract test {\n"
" function a(uint a, uint b) returns (uint r) { r = a + b; }\n"
" function b() returns (uint r) { r = a({a: 1, c: 2}); }\n"
"}\n";
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
}
BOOST_AUTO_TEST_CASE(empty_name_input_parameter)
{
char const* text = R"(
contract test {
function f(uint){
}
})";
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
}
BOOST_AUTO_TEST_CASE(empty_name_return_parameter)
{
char const* text = R"(
contract test {
function f() returns(bool){
}
})";
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
}
BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one)
{
char const* text = R"(
contract test {
function f(uint, uint k) returns(uint ret_k){
return k;
}
})";
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
}
BOOST_AUTO_TEST_CASE(empty_name_return_parameter_with_named_one)
{
char const* text = R"(
contract test {
function f() returns(uint ret_k, uint){
return 5;
}
})";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(disallow_declaration_of_void_type)
{
char const* sourceCode = "contract c { function f() { var x = f(); } }";
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
}
BOOST_AUTO_TEST_CASE(overflow_caused_by_ether_units)
{
char const* sourceCodeFine = R"(
contract c {
function c ()
{
a = 115792089237316195423570985008687907853269984665640564039458;
}
uint256 a;
})";
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(sourceCodeFine));
char const* sourceCode = R"(
contract c {
function c ()
{
a = 115792089237316195423570985008687907853269984665640564039458 ether;
}
uint256 a;
})";
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
} }

View File

@ -54,9 +54,9 @@ public:
} }
if (_userDocumentation) if (_userDocumentation)
generatedDocumentationString = m_compilerStack.getMetadata("", DocumentationType::NATSPEC_USER); generatedDocumentationString = m_compilerStack.getMetadata("", DocumentationType::NatspecUser);
else else
generatedDocumentationString = m_compilerStack.getMetadata("", DocumentationType::NATSPEC_DEV); generatedDocumentationString = m_compilerStack.getMetadata("", DocumentationType::NatspecDev);
Json::Value generatedDocumentation; Json::Value generatedDocumentation;
m_reader.parse(generatedDocumentationString, generatedDocumentation); m_reader.parse(generatedDocumentationString, generatedDocumentation);
Json::Value expectedDocumentation; Json::Value expectedDocumentation;

View File

@ -124,14 +124,30 @@ BOOST_AUTO_TEST_CASE(single_function_param)
BOOST_CHECK_NO_THROW(parseText(text)); BOOST_CHECK_NO_THROW(parseText(text));
} }
BOOST_AUTO_TEST_CASE(missing_parameter_name_in_named_args)
{
char const* text = "contract test {\n"
" function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }\n"
" function b() returns (uint r) { r = a({: 1, : 2, : 3}); }\n"
"}\n";
BOOST_CHECK_THROW(parseText(text), ParserError);
}
BOOST_AUTO_TEST_CASE(missing_argument_in_named_args)
{
char const* text = "contract test {\n"
" function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }\n"
" function b() returns (uint r) { r = a({a: , b: , c: }); }\n"
"}\n";
BOOST_CHECK_THROW(parseText(text), ParserError);
}
BOOST_AUTO_TEST_CASE(function_natspec_documentation) BOOST_AUTO_TEST_CASE(function_natspec_documentation)
{ {
ASTPointer<ContractDefinition> contract; ASTPointer<ContractDefinition> contract;
ASTPointer<FunctionDefinition> function; ASTPointer<FunctionDefinition> function;
char const* text = "contract test {\n" char const* text = "contract test {\n"
" private:\n" " uint256 stateVar;\n"
" uint256 stateVar;\n"
" public:\n"
" /// This is a test function\n" " /// This is a test function\n"
" function functionName(hash hashin) returns (hash hashout) {}\n" " function functionName(hash hashin) returns (hash hashout) {}\n"
"}\n"; "}\n";
@ -162,9 +178,7 @@ BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation)
ASTPointer<ContractDefinition> contract; ASTPointer<ContractDefinition> contract;
ASTPointer<FunctionDefinition> function; ASTPointer<FunctionDefinition> function;
char const* text = "contract test {\n" char const* text = "contract test {\n"
" private:\n"
" uint256 stateVar;\n" " uint256 stateVar;\n"
" public:\n"
" /// This is test function 1\n" " /// This is test function 1\n"
" function functionName1(hash hashin) returns (hash hashout) {}\n" " function functionName1(hash hashin) returns (hash hashout) {}\n"
" /// This is test function 2\n" " /// This is test function 2\n"
@ -621,6 +635,63 @@ BOOST_AUTO_TEST_CASE(event_arguments_indexed)
BOOST_CHECK_NO_THROW(parseText(text)); BOOST_CHECK_NO_THROW(parseText(text));
} }
BOOST_AUTO_TEST_CASE(visibility_specifiers)
{
char const* text = R"(
contract c {
uint private a;
uint protected b;
uint public c;
uint d;
function f() {}
function f_priv() private {}
function f_public() public {}
function f_protected() protected {}
})";
BOOST_CHECK_NO_THROW(parseText(text));
}
BOOST_AUTO_TEST_CASE(multiple_visibility_specifiers)
{
char const* text = R"(
contract c {
uint private protected a;
})";
BOOST_CHECK_THROW(parseText(text), ParserError);
}
BOOST_AUTO_TEST_CASE(literal_constants_with_ether_subdenominations)
{
char const* text = R"(
contract c {
function c ()
{
a = 1 wei;
b = 2 szabo;
c = 3 finney;
b = 4 ether;
}
uint256 a;
uint256 b;
uint256 c;
uint256 d;
})";
BOOST_CHECK_NO_THROW(parseTextExplainError(text));
}
BOOST_AUTO_TEST_CASE(literal_constants_with_ether_subdenominations_in_expressions)
{
char const* text = R"(
contract c {
function c ()
{
a = 1 wei * 100 wei + 7 szabo - 3;
}
uint256 a;
})";
BOOST_CHECK_NO_THROW(parseTextExplainError(text));
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
} }

View File

@ -41,17 +41,17 @@ BOOST_AUTO_TEST_CASE(test_empty)
BOOST_AUTO_TEST_CASE(smoke_test) BOOST_AUTO_TEST_CASE(smoke_test)
{ {
Scanner scanner(CharStream("function break;765 \t \"string1\",'string2'\nidentifier1")); Scanner scanner(CharStream("function break;765 \t \"string1\",'string2'\nidentifier1"));
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::FUNCTION); BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::Function);
BOOST_CHECK_EQUAL(scanner.next(), Token::BREAK); BOOST_CHECK_EQUAL(scanner.next(), Token::Break);
BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); BOOST_CHECK_EQUAL(scanner.next(), Token::Semicolon);
BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); BOOST_CHECK_EQUAL(scanner.next(), Token::Number);
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "765"); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "765");
BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); BOOST_CHECK_EQUAL(scanner.next(), Token::StringLiteral);
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "string1"); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "string1");
BOOST_CHECK_EQUAL(scanner.next(), Token::COMMA); BOOST_CHECK_EQUAL(scanner.next(), Token::Comma);
BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); BOOST_CHECK_EQUAL(scanner.next(), Token::StringLiteral);
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "string2"); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "string2");
BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "identifier1"); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "identifier1");
BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS);
} }
@ -59,85 +59,85 @@ BOOST_AUTO_TEST_CASE(smoke_test)
BOOST_AUTO_TEST_CASE(string_escapes) BOOST_AUTO_TEST_CASE(string_escapes)
{ {
Scanner scanner(CharStream(" { \"a\\x61\"")); Scanner scanner(CharStream(" { \"a\\x61\""));
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LBRACE); BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LBrace);
BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); BOOST_CHECK_EQUAL(scanner.next(), Token::StringLiteral);
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "aa"); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "aa");
} }
BOOST_AUTO_TEST_CASE(string_escapes_with_zero) BOOST_AUTO_TEST_CASE(string_escapes_with_zero)
{ {
Scanner scanner(CharStream(" { \"a\\x61\\x00abc\"")); Scanner scanner(CharStream(" { \"a\\x61\\x00abc\""));
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LBRACE); BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LBrace);
BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); BOOST_CHECK_EQUAL(scanner.next(), Token::StringLiteral);
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), std::string("aa\0abc", 6)); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), std::string("aa\0abc", 6));
} }
BOOST_AUTO_TEST_CASE(string_escape_illegal) BOOST_AUTO_TEST_CASE(string_escape_illegal)
{ {
Scanner scanner(CharStream(" bla \"\\x6rf\" (illegalescape)")); Scanner scanner(CharStream(" bla \"\\x6rf\" (illegalescape)"));
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL); BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal);
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), ""); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "");
// TODO recovery from illegal tokens should be improved // TODO recovery from illegal tokens should be improved
BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL); BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal);
BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL); BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal);
BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS);
} }
BOOST_AUTO_TEST_CASE(hex_numbers) BOOST_AUTO_TEST_CASE(hex_numbers)
{ {
Scanner scanner(CharStream("var x = 0x765432536763762734623472346;")); Scanner scanner(CharStream("var x = 0x765432536763762734623472346;"));
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::VAR); BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::Var);
BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::ASSIGN); BOOST_CHECK_EQUAL(scanner.next(), Token::Assign);
BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); BOOST_CHECK_EQUAL(scanner.next(), Token::Number);
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "0x765432536763762734623472346"); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "0x765432536763762734623472346");
BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); BOOST_CHECK_EQUAL(scanner.next(), Token::Semicolon);
BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS);
} }
BOOST_AUTO_TEST_CASE(negative_numbers) BOOST_AUTO_TEST_CASE(negative_numbers)
{ {
Scanner scanner(CharStream("var x = -.2 + -0x78 + -7.3 + 8.9;")); Scanner scanner(CharStream("var x = -.2 + -0x78 + -7.3 + 8.9;"));
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::VAR); BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::Var);
BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::ASSIGN); BOOST_CHECK_EQUAL(scanner.next(), Token::Assign);
BOOST_CHECK_EQUAL(scanner.next(), Token::SUB); BOOST_CHECK_EQUAL(scanner.next(), Token::Sub);
BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); BOOST_CHECK_EQUAL(scanner.next(), Token::Number);
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), ".2"); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), ".2");
BOOST_CHECK_EQUAL(scanner.next(), Token::ADD); BOOST_CHECK_EQUAL(scanner.next(), Token::Add);
BOOST_CHECK_EQUAL(scanner.next(), Token::SUB); BOOST_CHECK_EQUAL(scanner.next(), Token::Sub);
BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); BOOST_CHECK_EQUAL(scanner.next(), Token::Number);
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "0x78"); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "0x78");
BOOST_CHECK_EQUAL(scanner.next(), Token::ADD); BOOST_CHECK_EQUAL(scanner.next(), Token::Add);
BOOST_CHECK_EQUAL(scanner.next(), Token::SUB); BOOST_CHECK_EQUAL(scanner.next(), Token::Sub);
BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); BOOST_CHECK_EQUAL(scanner.next(), Token::Number);
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "7.3"); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "7.3");
BOOST_CHECK_EQUAL(scanner.next(), Token::ADD); BOOST_CHECK_EQUAL(scanner.next(), Token::Add);
BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); BOOST_CHECK_EQUAL(scanner.next(), Token::Number);
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "8.9"); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "8.9");
BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); BOOST_CHECK_EQUAL(scanner.next(), Token::Semicolon);
BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS);
} }
BOOST_AUTO_TEST_CASE(locations) BOOST_AUTO_TEST_CASE(locations)
{ {
Scanner scanner(CharStream("function_identifier has ; -0x743/*comment*/\n ident //comment")); Scanner scanner(CharStream("function_identifier has ; -0x743/*comment*/\n ident //comment"));
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 0); BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 0);
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 19); BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 19);
BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 20); BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 20);
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 23); BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 23);
BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); BOOST_CHECK_EQUAL(scanner.next(), Token::Semicolon);
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 24); BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 24);
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 25); BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 25);
BOOST_CHECK_EQUAL(scanner.next(), Token::SUB); BOOST_CHECK_EQUAL(scanner.next(), Token::Sub);
BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); BOOST_CHECK_EQUAL(scanner.next(), Token::Number);
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 27); BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 27);
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 32); BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 32);
BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 45); BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 45);
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 50); BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 50);
BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS);
@ -147,13 +147,13 @@ BOOST_AUTO_TEST_CASE(ambiguities)
{ {
// test scanning of some operators which need look-ahead // test scanning of some operators which need look-ahead
Scanner scanner(CharStream("<=""<""+ +=a++ =>""<<")); Scanner scanner(CharStream("<=""<""+ +=a++ =>""<<"));
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LTE); BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LessThanOrEqual);
BOOST_CHECK_EQUAL(scanner.next(), Token::LT); BOOST_CHECK_EQUAL(scanner.next(), Token::LessThan);
BOOST_CHECK_EQUAL(scanner.next(), Token::ADD); BOOST_CHECK_EQUAL(scanner.next(), Token::Add);
BOOST_CHECK_EQUAL(scanner.next(), Token::ASSIGN_ADD); BOOST_CHECK_EQUAL(scanner.next(), Token::AssignAdd);
BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::INC); BOOST_CHECK_EQUAL(scanner.next(), Token::Inc);
BOOST_CHECK_EQUAL(scanner.next(), Token::ARROW); BOOST_CHECK_EQUAL(scanner.next(), Token::Arrow);
BOOST_CHECK_EQUAL(scanner.next(), Token::SHL); BOOST_CHECK_EQUAL(scanner.next(), Token::SHL);
} }
@ -174,9 +174,9 @@ BOOST_AUTO_TEST_CASE(multiline_documentation_comments_parsed_begin)
BOOST_AUTO_TEST_CASE(documentation_comments_parsed) BOOST_AUTO_TEST_CASE(documentation_comments_parsed)
{ {
Scanner scanner(CharStream("some other tokens /// Send $(value / 1000) chocolates to the user")); Scanner scanner(CharStream("some other tokens /// Send $(value / 1000) chocolates to the user"));
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS);
BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), "Send $(value / 1000) chocolates to the user"); BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), "Send $(value / 1000) chocolates to the user");
} }
@ -186,9 +186,9 @@ BOOST_AUTO_TEST_CASE(multiline_documentation_comments_parsed)
Scanner scanner(CharStream("some other tokens /**\n" Scanner scanner(CharStream("some other tokens /**\n"
"* Send $(value / 1000) chocolates to the user\n" "* Send $(value / 1000) chocolates to the user\n"
"*/")); "*/"));
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS);
BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), "Send $(value / 1000) chocolates to the user"); BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), "Send $(value / 1000) chocolates to the user");
} }
@ -198,9 +198,9 @@ BOOST_AUTO_TEST_CASE(multiline_documentation_no_stars)
Scanner scanner(CharStream("some other tokens /**\n" Scanner scanner(CharStream("some other tokens /**\n"
" Send $(value / 1000) chocolates to the user\n" " Send $(value / 1000) chocolates to the user\n"
"*/")); "*/"));
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS);
BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), "Send $(value / 1000) chocolates to the user"); BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), "Send $(value / 1000) chocolates to the user");
} }
@ -210,9 +210,9 @@ BOOST_AUTO_TEST_CASE(multiline_documentation_whitespace_hell)
Scanner scanner(CharStream("some other tokens /** \t \r \n" Scanner scanner(CharStream("some other tokens /** \t \r \n"
"\t \r * Send $(value / 1000) chocolates to the user\n" "\t \r * Send $(value / 1000) chocolates to the user\n"
"*/")); "*/"));
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS);
BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), "Send $(value / 1000) chocolates to the user"); BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), "Send $(value / 1000) chocolates to the user");
} }
@ -250,11 +250,20 @@ BOOST_AUTO_TEST_CASE(comments_mixed_in_sequence)
Scanner scanner(CharStream("hello_world ///documentation comment \n" Scanner scanner(CharStream("hello_world ///documentation comment \n"
"//simple comment \n" "//simple comment \n"
"<<")); "<<"));
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::SHL); BOOST_CHECK_EQUAL(scanner.next(), Token::SHL);
BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), "documentation comment "); BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), "documentation comment ");
} }
BOOST_AUTO_TEST_CASE(ether_subdenominations)
{
Scanner scanner(CharStream("wei szabo finney ether"));
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::SubWei);
BOOST_CHECK_EQUAL(scanner.next(), Token::SubSzabo);
BOOST_CHECK_EQUAL(scanner.next(), Token::SubFinney);
BOOST_CHECK_EQUAL(scanner.next(), Token::SubEther);
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
} }

View File

@ -20,7 +20,8 @@
*/ */
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <libdevcore/CommonJS.h> #include <libdevcore/Log.h>
#include <libethcore/CommonJS.h>
BOOST_AUTO_TEST_SUITE(commonjs) BOOST_AUTO_TEST_SUITE(commonjs)
using namespace std; using namespace std;
@ -41,7 +42,7 @@ BOOST_AUTO_TEST_CASE(jsToAddress)
cnote << "Testing jsToPublic..."; cnote << "Testing jsToPublic...";
KeyPair kp = KeyPair::create(); KeyPair kp = KeyPair::create();
string string = toJS(kp.address()); string string = toJS(kp.address());
Address address = dev::jsToAddress(string); Address address = dev::eth::jsToAddress(string);
BOOST_CHECK_EQUAL(kp.address(), address); BOOST_CHECK_EQUAL(kp.address(), address);
} }

View File

@ -23,7 +23,7 @@
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <boost/filesystem/operations.hpp> #include <boost/filesystem/operations.hpp>
#include <libethereum/Client.h> #include <libethereum/Client.h>
#include <libethereum/BlockChain.h> #include <libethereum/CanonBlockChain.h>
#include <libethereum/EthereumHost.h> #include <libethereum/EthereumHost.h>
#include "TestHelper.h" #include "TestHelper.h"
using namespace std; using namespace std;

View File

@ -24,7 +24,7 @@
#include <random> #include <random>
#include "JsonSpiritHeaders.h" #include "JsonSpiritHeaders.h"
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libethereum/BlockChain.h> #include <libethereum/CanonBlockChain.h>
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include "TestHelper.h" #include "TestHelper.h"
@ -58,9 +58,9 @@ BOOST_AUTO_TEST_CASE(genesis_tests)
js::mObject o = v.get_obj(); js::mObject o = v.get_obj();
BOOST_CHECK_EQUAL(BlockChain::genesis().stateRoot, h256(o["genesis_state_root"].get_str())); BOOST_CHECK_EQUAL(CanonBlockChain::genesis().stateRoot, h256(o["genesis_state_root"].get_str()));
BOOST_CHECK_EQUAL(toHex(BlockChain::createGenesisBlock()), toHex(fromHex(o["genesis_rlp_hex"].get_str()))); BOOST_CHECK_EQUAL(toHex(CanonBlockChain::createGenesisBlock()), toHex(fromHex(o["genesis_rlp_hex"].get_str())));
BOOST_CHECK_EQUAL(BlockInfo::headerHash(BlockChain::createGenesisBlock()), h256(o["genesis_hash"].get_str())); BOOST_CHECK_EQUAL(BlockInfo::headerHash(CanonBlockChain::createGenesisBlock()), h256(o["genesis_hash"].get_str()));
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

View File

@ -28,7 +28,7 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libdevcore/CommonJS.h> #include <libethcore/CommonJS.h>
#include <libwebthree/WebThree.h> #include <libwebthree/WebThree.h>
#include <libweb3jsonrpc/WebThreeStubServer.h> #include <libweb3jsonrpc/WebThreeStubServer.h>
#include <jsonrpccpp/server/connectors/httpserver.h> #include <jsonrpccpp/server/connectors/httpserver.h>

116
natspec.cpp Normal file
View File

@ -0,0 +1,116 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum 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.
cpp-ethereum 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file natspec.cpp
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
#if !ETH_HEADLESS
#include <boost/test/unit_test.hpp>
#include <libdevcore/Log.h>
#include <libnatspec/NatspecExpressionEvaluator.h>
using namespace std;
BOOST_AUTO_TEST_SUITE(natspec)
BOOST_AUTO_TEST_CASE(natspec_eval_function_exists)
{
// given
NatspecExpressionEvaluator e;
// when
string result = e.evalExpression("`typeof evaluateExpression`").toStdString();
// then
BOOST_CHECK_EQUAL(result, "function");
}
BOOST_AUTO_TEST_CASE(natspec_js_eval)
{
// given
NatspecExpressionEvaluator e;
// when
string result = e.evalExpression("`1 + 2`").toStdString();
// then
BOOST_CHECK_EQUAL(result, "3");
}
BOOST_AUTO_TEST_CASE(natspec_create_custom_function)
{
// given
NatspecExpressionEvaluator e;
// when
auto x = e.evalExpression("`test = function (x) { return x + 'ok'; }`"); // ommit var, make it global
string result = e.evalExpression("`test(5)`").toStdString();
string result2 = e.evalExpression("`typeof test`").toStdString();
// then
BOOST_CHECK_EQUAL(result, "5ok");
BOOST_CHECK_EQUAL(result2, "function");
}
BOOST_AUTO_TEST_CASE(natspec_js_eval_separated_expressions)
{
// given
NatspecExpressionEvaluator e;
// when
string result = e.evalExpression("`x = 1` + `y = 2` will be equal `x + y`").toStdString();
// then
BOOST_CHECK_EQUAL(result, "1 + 2 will be equal 3");
}
BOOST_AUTO_TEST_CASE(natspec_js_eval_input_params)
{
// given
char const* abi = R"([
{
"name": "f",
"constant": false,
"type": "function",
"inputs": [
{
"name": "a",
"type": "uint256"
}
],
"outputs": [
{
"name": "d",
"type": "uint256"
}
]
}
])";
NatspecExpressionEvaluator e(abi, "'f'", "[4]");
// when
string result = e.evalExpression("Will multiply `a` by 7 and return `a * 7`.").toStdString();
// then
BOOST_CHECK_EQUAL(result, "Will multiply 4 by 7 and return 28.");
}
BOOST_AUTO_TEST_CASE(natspec_js_eval_error)
{
// given
NatspecExpressionEvaluator e;
// when
string result = e.evalExpression("`test(`").toStdString();
// then
BOOST_CHECK_EQUAL(result, "`test(`");
}
BOOST_AUTO_TEST_SUITE_END()
#endif

View File

@ -303,6 +303,34 @@
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"data" : "" "data" : ""
} }
} },
"RefundOverflow" : {
"env" : {
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"currentDifficulty" : "45678256",
"currentGasLimit" : "115792089237316195423570985008687907853269984665640564039457584007913129639935",
"currentNumber" : "0",
"currentTimestamp" : 1,
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"
},
"pre" : {
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "400",
"code" : "0x",
"nonce" : "0",
"storage" : {
}
}
},
"transaction" : {
"data" : "",
"gasLimit" : "5789604461865809771178549250434395392663499233282028201972879200395656482016",
"gasPrice" : "20",
"nonce" : "0",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "b94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"value" : ""
}
}
} }

View File

@ -33,6 +33,76 @@
} }
}, },
"testRandomTest": {
"env" : {
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"currentDifficulty" : "115792089237316195423570985008687907853269984665640564039457584007913129639935",
"currentGasLimit" : "1000000",
"currentNumber" : "300",
"currentTimestamp" : "2",
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"code" : "0x424443444243434383f0155af055",
"nonce" : "0",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "1000000000000000000",
"code" : "0x",
"nonce" : "0",
"storage" : {
}
}
},
"transaction" : {
"data" : "",
"gasLimit" : "10000",
"gasPrice" : "1",
"nonce" : "0",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"value" : "100000"
}
},
"createWithInvalidOpcode": {
"env" : {
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"currentDifficulty" : "115792089237316195423570985008687907853269984665640564039457584007913129639935",
"currentGasLimit" : "1000000",
"currentNumber" : "300",
"currentTimestamp" : "2",
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"
},
"pre" : {
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "0x444242424245434253f0",
"storage": {}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "",
"storage": {}
}
},
"transaction" : {
"nonce" : "0",
"gasPrice" : "1",
"gasLimit" : "10000",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "100000",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"data" : ""
}
},
"createNameRegistratorOOG_MemExpansionInsufficientBalance": { "createNameRegistratorOOG_MemExpansionInsufficientBalance": {
"env" : { "env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",

View File

@ -169,7 +169,7 @@
}, },
"pre" : "pre" :
{ {
"b94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "1000", "balance" : "1000",
"code" : "", "code" : "",
"nonce" : "0", "nonce" : "0",
@ -189,6 +189,68 @@
} }
}, },
"TransactionFromCoinbaseHittingBlockGasLimit" : {
"env" : {
"currentCoinbase" : "a94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"currentDifficulty" : "45678256",
"currentGasLimit" : "1100",
"currentNumber" : "0",
"currentTimestamp" : 1,
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"
},
"pre" :
{
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "1000000",
"code" : "",
"nonce" : "0",
"storage" : {
}
}
},
"transaction" :
{
"data" : "",
"gasLimit" : "1100",
"gasPrice" : "1",
"nonce" : "",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "b94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"value" : "10"
}
},
"TransactionFromCoinbaseHittingBlockGasLimit1" : {
"env" : {
"currentCoinbase" : "a94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"currentDifficulty" : "45678256",
"currentGasLimit" : "1100",
"currentNumber" : "0",
"currentTimestamp" : 1,
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"
},
"pre" :
{
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "100000",
"code" : "",
"nonce" : "0",
"storage" : {
}
}
},
"transaction" :
{
"data" : "",
"gasLimit" : "1101",
"gasPrice" : "1",
"nonce" : "",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "b94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"value" : "10"
}
},
"ContractStoreClearsSuccess" : { "ContractStoreClearsSuccess" : {
"env" : { "env" : {
"currentCoinbase" : "b94f5374fce5edbc8e2a8697c15331677e6ebf0b", "currentCoinbase" : "b94f5374fce5edbc8e2a8697c15331677e6ebf0b",

View File

@ -24,7 +24,7 @@
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include "JsonSpiritHeaders.h" #include "JsonSpiritHeaders.h"
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libethereum/BlockChain.h> #include <libethereum/CanonBlockChain.h>
#include <libethereum/State.h> #include <libethereum/State.h>
#include <libethereum/ExtVM.h> #include <libethereum/ExtVM.h>
#include <libethereum/Defaults.h> #include <libethereum/Defaults.h>

View File

@ -22,7 +22,7 @@
#include <boost/filesystem/operations.hpp> #include <boost/filesystem/operations.hpp>
#include <secp256k1/secp256k1.h> #include <secp256k1/secp256k1.h>
#include <libethereum/BlockChain.h> #include <libethereum/CanonBlockChain.h>
#include <libethereum/State.h> #include <libethereum/State.h>
#include <libethereum/Defaults.h> #include <libethereum/Defaults.h>
using namespace std; using namespace std;
@ -40,7 +40,7 @@ int stateTest()
Defaults::setDBPath(boost::filesystem::temp_directory_path().string()); Defaults::setDBPath(boost::filesystem::temp_directory_path().string());
OverlayDB stateDB = State::openDB(); OverlayDB stateDB = State::openDB();
BlockChain bc; CanonBlockChain bc;
State s(myMiner.address(), stateDB); State s(myMiner.address(), stateDB);
cout << bc; cout << bc;
@ -75,7 +75,8 @@ int stateTest()
// Mine to get some ether and set in stone. // Mine to get some ether and set in stone.
s.commitToMine(bc); s.commitToMine(bc);
while (!s.mine(100).completed) {} s.commitToMine(bc);
while (!s.mine(50).completed) { s.commitToMine(bc); }
s.completeMine(); s.completeMine();
bc.attemptImport(s.blockData(), stateDB); bc.attemptImport(s.blockData(), stateDB);

View File

@ -23,7 +23,7 @@
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <boost/filesystem/operations.hpp> #include <boost/filesystem/operations.hpp>
#include <libethereum/Client.h> #include <libethereum/Client.h>
#include <libethereum/BlockChain.h> #include <libethereum/CanonBlockChain.h>
#include <libethereum/EthereumHost.h> #include <libethereum/EthereumHost.h>
#include "TestHelper.h" #include "TestHelper.h"
using namespace std; using namespace std;

View File

@ -193,5 +193,89 @@
"gasPrice" : "100000000000000", "gasPrice" : "100000000000000",
"gas" : "10000" "gas" : "10000"
} }
},
"sha3_bigSize": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"nonce" : 0,
"code" : "{ [[ 0 ]] (SHA3 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)}",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"data" : "",
"gasPrice" : "1",
"gas" : "0x10000000000"
}
},
"sha3_bigOffset": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"nonce" : 0,
"code" : "{ [[ 0 ]] (SHA3 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 2)}",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"data" : "",
"gasPrice" : "1",
"gas" : "0x10000000000"
}
},
"sha3_bigOffset2": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"nonce" : 0,
"code" : "{ [[ 0 ]] (SHA3 0x1000000 2)}",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"data" : "",
"gasPrice" : "1",
"gas" : "0x100000000"
}
} }
} }

View File

@ -213,6 +213,16 @@ class WebThreeStubClient : public jsonrpc::Client
else else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
} }
bool eth_flush() throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("eth_flush",p);
if (result.isBool())
return result.asBool();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_blockByHash(const std::string& param1) throw (jsonrpc::JsonRpcException) Json::Value eth_blockByHash(const std::string& param1) throw (jsonrpc::JsonRpcException)
{ {
Json::Value p; Json::Value p;
@ -347,13 +357,13 @@ class WebThreeStubClient : public jsonrpc::Client
else else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
} }
bool eth_changed(const int& param1) throw (jsonrpc::JsonRpcException) Json::Value eth_changed(const int& param1) throw (jsonrpc::JsonRpcException)
{ {
Json::Value p; Json::Value p;
p.append(param1); p.append(param1);
Json::Value result = this->CallMethod("eth_changed",p); Json::Value result = this->CallMethod("eth_changed",p);
if (result.isBool()) if (result.isArray())
return result.asBool(); return result;
else else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
} }
@ -377,6 +387,26 @@ class WebThreeStubClient : public jsonrpc::Client
else else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
} }
Json::Value eth_getWork() throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("eth_getWork",p);
if (result.isArray())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool eth_submitWork(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_submitWork",p);
if (result.isBool())
return result.asBool();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool db_put(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException) bool db_put(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException)
{ {
Json::Value p; Json::Value p;

View File

@ -50,6 +50,7 @@ BOOST_AUTO_TEST_CASE(topic)
auto w = wh->installWatch(BuildTopicMask("odd")); auto w = wh->installWatch(BuildTopicMask("odd"));
started = true; started = true;
set<unsigned> received;
for (int iterout = 0, last = 0; iterout < 200 && last < 81; ++iterout) for (int iterout = 0, last = 0; iterout < 200 && last < 81; ++iterout)
{ {
@ -57,6 +58,9 @@ BOOST_AUTO_TEST_CASE(topic)
{ {
Message msg = wh->envelope(i).open(wh->fullTopic(w)); Message msg = wh->envelope(i).open(wh->fullTopic(w));
last = RLP(msg.payload()).toInt<unsigned>(); last = RLP(msg.payload()).toInt<unsigned>();
if (received.count(last))
continue;
received.insert(last);
cnote << "New message from:" << msg.from().abridged() << RLP(msg.payload()).toInt<unsigned>(); cnote << "New message from:" << msg.from().abridged() << RLP(msg.payload()).toInt<unsigned>();
result += last; result += last;
} }