From ce7bbca1e5bd043252d9708302303326604442ca Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 27 Nov 2014 15:21:22 +0100 Subject: [PATCH 01/10] Solidity function AST nodes get documentation attribute --- solidityParser.cpp | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/solidityParser.cpp b/solidityParser.cpp index 9319a02c5..88a1fd5f0 100644 --- a/solidityParser.cpp +++ b/solidityParser.cpp @@ -37,13 +37,14 @@ namespace test namespace { -ASTPointer parseText(std::string const& _source) +ASTPointer parseText(std::string const& _source) { Parser parser; return parser.parse(std::make_shared(CharStream(_source))); } } + BOOST_AUTO_TEST_SUITE(SolidityParser) BOOST_AUTO_TEST_CASE(smoke_test) @@ -91,6 +92,36 @@ BOOST_AUTO_TEST_CASE(single_function_param) BOOST_CHECK_NO_THROW(parseText(text)); } +BOOST_AUTO_TEST_CASE(function_natspec_documentation) +{ + ASTPointer contract; + ASTPointer function; + char const* text = "contract test {\n" + " uint256 stateVar;\n" + " /// This is a test function\n" + " function functionName(hash hashin) returns (hash hashout) {}\n" + "}\n"; + BOOST_CHECK_NO_THROW(contract = parseText(text)); + auto functions = contract->getDefinedFunctions(); + BOOST_CHECK_NO_THROW(function = functions.at(0)); + BOOST_CHECK_EQUAL(function->getDocumentation(), " This is a test function"); +} + +BOOST_AUTO_TEST_CASE(function_normal_comments) +{ + ASTPointer contract; + ASTPointer function; + char const* text = "contract test {\n" + " uint256 stateVar;\n" + " // We won't see this comment\n" + " function functionName(hash hashin) returns (hash hashout) {}\n" + "}\n"; + BOOST_CHECK_NO_THROW(contract = parseText(text)); + auto functions = contract->getDefinedFunctions(); + BOOST_CHECK_NO_THROW(function = functions.at(0)); + BOOST_CHECK_EQUAL(function->getDocumentation(), ""); +} + BOOST_AUTO_TEST_CASE(struct_definition) { char const* text = "contract test {\n" From de5ca561f868d24b0750c871c57130078580e651 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 27 Nov 2014 18:57:50 +0100 Subject: [PATCH 02/10] Solidity work for documentation strings - Still a work in progress - Parser now properly gets each function's doc comment - Small changes in the scanner - Multiline comments are considered --- solidityParser.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/solidityParser.cpp b/solidityParser.cpp index 88a1fd5f0..bda820b98 100644 --- a/solidityParser.cpp +++ b/solidityParser.cpp @@ -122,6 +122,58 @@ BOOST_AUTO_TEST_CASE(function_normal_comments) BOOST_CHECK_EQUAL(function->getDocumentation(), ""); } +BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation) +{ + ASTPointer contract; + ASTPointer function; + char const* text = "contract test {\n" + " uint256 stateVar;\n" + " /// This is test function 1\n" + " function functionName1(hash hashin) returns (hash hashout) {}\n" + " /// This is test function 2\n" + " function functionName2(hash hashin) returns (hash hashout) {}\n" + " // nothing to see here\n" + " function functionName3(hash hashin) returns (hash hashout) {}\n" + " /// This is test function 4\n" + " function functionName4(hash hashin) returns (hash hashout) {}\n" + "}\n"; + BOOST_CHECK_NO_THROW(contract = parseText(text)); + auto functions = contract->getDefinedFunctions(); + + BOOST_CHECK_NO_THROW(function = functions.at(0)); + BOOST_CHECK_EQUAL(function->getDocumentation(), " This is test function 1"); + + BOOST_CHECK_NO_THROW(function = functions.at(1)); + BOOST_CHECK_EQUAL(function->getDocumentation(), " This is test function 2"); + + BOOST_CHECK_NO_THROW(function = functions.at(2)); + BOOST_CHECK_EQUAL(function->getDocumentation(), ""); + + BOOST_CHECK_NO_THROW(function = functions.at(3)); + BOOST_CHECK_EQUAL(function->getDocumentation(), " This is test function 4"); +} + +#if 0 /* Work in progress - currently fails*/ +BOOST_AUTO_TEST_CASE(multiline_function_documentation) +{ + ASTPointer contract; + ASTPointer function; + char const* text = "contract test {\n" + " uint256 stateVar;\n" + " /// This is a test function\n" + " /// and it has 2 lines\n" + " function functionName1(hash hashin) returns (hash hashout) {}\n" + "}\n"; + BOOST_CHECK_NO_THROW(contract = parseText(text)); + auto functions = contract->getDefinedFunctions(); + + BOOST_CHECK_NO_THROW(function = functions.at(0)); + BOOST_CHECK_EQUAL(function->getDocumentation(), + " This is a test function\n" + " and it has 2 lines"); +} +#endif + BOOST_AUTO_TEST_CASE(struct_definition) { char const* text = "contract test {\n" From 2b30e1ef2c23cf5574d7d7a9155150c6063c9c9c Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 28 Nov 2014 00:06:38 +0100 Subject: [PATCH 03/10] Fixing multiline comment parsing in solidity --- solidityParser.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/solidityParser.cpp b/solidityParser.cpp index bda820b98..e05b88580 100644 --- a/solidityParser.cpp +++ b/solidityParser.cpp @@ -153,7 +153,6 @@ BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation) BOOST_CHECK_EQUAL(function->getDocumentation(), " This is test function 4"); } -#if 0 /* Work in progress - currently fails*/ BOOST_AUTO_TEST_CASE(multiline_function_documentation) { ASTPointer contract; @@ -172,7 +171,6 @@ BOOST_AUTO_TEST_CASE(multiline_function_documentation) " This is a test function\n" " and it has 2 lines"); } -#endif BOOST_AUTO_TEST_CASE(struct_definition) { From c8fa23735f7023dd342fe41aa864aa9b91a4845d Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 28 Nov 2014 00:40:00 +0100 Subject: [PATCH 04/10] Adding solidity natspec comment inside function body --- solidityParser.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/solidityParser.cpp b/solidityParser.cpp index e05b88580..3a95ec065 100644 --- a/solidityParser.cpp +++ b/solidityParser.cpp @@ -172,6 +172,36 @@ BOOST_AUTO_TEST_CASE(multiline_function_documentation) " and it has 2 lines"); } +BOOST_AUTO_TEST_CASE(natspec_comment_in_function_body) +{ + ASTPointer contract; + ASTPointer function; + char const* text = "contract test {\n" + " /// fun1 description\n" + " function fun1(uint256 a) {\n" + " var b;\n" + " /// I should not interfere with actual natspec comments\n" + " uint256 c;\n" + " mapping(address=>hash) d;\n" + " string name = \"Solidity\";" + " }\n" + " uint256 stateVar;\n" + " /// This is a test function\n" + " /// and it has 2 lines\n" + " function fun(hash hashin) returns (hash hashout) {}\n" + "}\n"; + BOOST_CHECK_NO_THROW(contract = parseText(text)); + auto functions = contract->getDefinedFunctions(); + + BOOST_CHECK_NO_THROW(function = functions.at(0)); + BOOST_CHECK_EQUAL(function->getDocumentation(), " fun1 description"); + + BOOST_CHECK_NO_THROW(function = functions.at(1)); + BOOST_CHECK_EQUAL(function->getDocumentation(), + " This is a test function\n" + " and it has 2 lines"); +} + BOOST_AUTO_TEST_CASE(struct_definition) { char const* text = "contract test {\n" From 263e1be34e08c720fccbc2532a7adda728ecee6e Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 28 Nov 2014 01:26:37 +0100 Subject: [PATCH 05/10] Solidity FunctionDefinition used ASTString shared ptr for docstrings --- solidityParser.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/solidityParser.cpp b/solidityParser.cpp index 3a95ec065..89ef0ac0f 100644 --- a/solidityParser.cpp +++ b/solidityParser.cpp @@ -104,7 +104,7 @@ BOOST_AUTO_TEST_CASE(function_natspec_documentation) BOOST_CHECK_NO_THROW(contract = parseText(text)); auto functions = contract->getDefinedFunctions(); BOOST_CHECK_NO_THROW(function = functions.at(0)); - BOOST_CHECK_EQUAL(function->getDocumentation(), " This is a test function"); + BOOST_CHECK_EQUAL(*function->getDocumentation().get(), " This is a test function"); } BOOST_AUTO_TEST_CASE(function_normal_comments) @@ -119,7 +119,8 @@ BOOST_AUTO_TEST_CASE(function_normal_comments) BOOST_CHECK_NO_THROW(contract = parseText(text)); auto functions = contract->getDefinedFunctions(); BOOST_CHECK_NO_THROW(function = functions.at(0)); - BOOST_CHECK_EQUAL(function->getDocumentation(), ""); + BOOST_CHECK_MESSAGE(function->getDocumentation().get() == nullptr, + "Should not have gotten a Natspect comment for this function"); } BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation) @@ -141,16 +142,17 @@ BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation) auto functions = contract->getDefinedFunctions(); BOOST_CHECK_NO_THROW(function = functions.at(0)); - BOOST_CHECK_EQUAL(function->getDocumentation(), " This is test function 1"); + BOOST_CHECK_EQUAL(*function->getDocumentation().get(), " This is test function 1"); BOOST_CHECK_NO_THROW(function = functions.at(1)); - BOOST_CHECK_EQUAL(function->getDocumentation(), " This is test function 2"); + BOOST_CHECK_EQUAL(*function->getDocumentation().get(), " This is test function 2"); BOOST_CHECK_NO_THROW(function = functions.at(2)); - BOOST_CHECK_EQUAL(function->getDocumentation(), ""); + BOOST_CHECK_MESSAGE(function->getDocumentation().get() == nullptr, + "Should not have gotten natspec comment for functionName3()"); BOOST_CHECK_NO_THROW(function = functions.at(3)); - BOOST_CHECK_EQUAL(function->getDocumentation(), " This is test function 4"); + BOOST_CHECK_EQUAL(*function->getDocumentation().get(), " This is test function 4"); } BOOST_AUTO_TEST_CASE(multiline_function_documentation) @@ -167,7 +169,7 @@ BOOST_AUTO_TEST_CASE(multiline_function_documentation) auto functions = contract->getDefinedFunctions(); BOOST_CHECK_NO_THROW(function = functions.at(0)); - BOOST_CHECK_EQUAL(function->getDocumentation(), + BOOST_CHECK_EQUAL(*function->getDocumentation().get(), " This is a test function\n" " and it has 2 lines"); } @@ -194,10 +196,10 @@ BOOST_AUTO_TEST_CASE(natspec_comment_in_function_body) auto functions = contract->getDefinedFunctions(); BOOST_CHECK_NO_THROW(function = functions.at(0)); - BOOST_CHECK_EQUAL(function->getDocumentation(), " fun1 description"); + BOOST_CHECK_EQUAL(*function->getDocumentation().get(), " fun1 description"); BOOST_CHECK_NO_THROW(function = functions.at(1)); - BOOST_CHECK_EQUAL(function->getDocumentation(), + BOOST_CHECK_EQUAL(*function->getDocumentation().get(), " This is a test function\n" " and it has 2 lines"); } From 9e80ec9e7a790ba06ee2f8f1c1fdfe963b0a28c2 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 28 Nov 2014 11:17:18 +0100 Subject: [PATCH 06/10] Solidity natspec docstring test improvements - Adding a test for docstring being between function signature and function body - Properly checking for exceptions in parsing - Small parser fix --- solidityParser.cpp | 70 +++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/solidityParser.cpp b/solidityParser.cpp index 89ef0ac0f..e4db2ece7 100644 --- a/solidityParser.cpp +++ b/solidityParser.cpp @@ -101,10 +101,10 @@ BOOST_AUTO_TEST_CASE(function_natspec_documentation) " /// This is a test function\n" " function functionName(hash hashin) returns (hash hashout) {}\n" "}\n"; - BOOST_CHECK_NO_THROW(contract = parseText(text)); + BOOST_REQUIRE_NO_THROW(contract = parseText(text)); auto functions = contract->getDefinedFunctions(); - BOOST_CHECK_NO_THROW(function = functions.at(0)); - BOOST_CHECK_EQUAL(*function->getDocumentation().get(), " This is a test function"); + BOOST_REQUIRE_NO_THROW(function = functions.at(0)); + BOOST_CHECK_EQUAL(*function->getDocumentation(), " This is a test function"); } BOOST_AUTO_TEST_CASE(function_normal_comments) @@ -116,10 +116,10 @@ BOOST_AUTO_TEST_CASE(function_normal_comments) " // We won't see this comment\n" " function functionName(hash hashin) returns (hash hashout) {}\n" "}\n"; - BOOST_CHECK_NO_THROW(contract = parseText(text)); + BOOST_REQUIRE_NO_THROW(contract = parseText(text)); auto functions = contract->getDefinedFunctions(); - BOOST_CHECK_NO_THROW(function = functions.at(0)); - BOOST_CHECK_MESSAGE(function->getDocumentation().get() == nullptr, + BOOST_REQUIRE_NO_THROW(function = functions.at(0)); + BOOST_CHECK_MESSAGE(function->getDocumentation() == nullptr, "Should not have gotten a Natspect comment for this function"); } @@ -138,21 +138,21 @@ BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation) " /// This is test function 4\n" " function functionName4(hash hashin) returns (hash hashout) {}\n" "}\n"; - BOOST_CHECK_NO_THROW(contract = parseText(text)); + BOOST_REQUIRE_NO_THROW(contract = parseText(text)); auto functions = contract->getDefinedFunctions(); - BOOST_CHECK_NO_THROW(function = functions.at(0)); - BOOST_CHECK_EQUAL(*function->getDocumentation().get(), " This is test function 1"); + BOOST_REQUIRE_NO_THROW(function = functions.at(0)); + BOOST_CHECK_EQUAL(*function->getDocumentation(), " This is test function 1"); - BOOST_CHECK_NO_THROW(function = functions.at(1)); - BOOST_CHECK_EQUAL(*function->getDocumentation().get(), " This is test function 2"); + BOOST_REQUIRE_NO_THROW(function = functions.at(1)); + BOOST_CHECK_EQUAL(*function->getDocumentation(), " This is test function 2"); - BOOST_CHECK_NO_THROW(function = functions.at(2)); - BOOST_CHECK_MESSAGE(function->getDocumentation().get() == nullptr, + BOOST_REQUIRE_NO_THROW(function = functions.at(2)); + BOOST_CHECK_MESSAGE(function->getDocumentation() == nullptr, "Should not have gotten natspec comment for functionName3()"); - BOOST_CHECK_NO_THROW(function = functions.at(3)); - BOOST_CHECK_EQUAL(*function->getDocumentation().get(), " This is test function 4"); + BOOST_REQUIRE_NO_THROW(function = functions.at(3)); + BOOST_CHECK_EQUAL(*function->getDocumentation(), " This is test function 4"); } BOOST_AUTO_TEST_CASE(multiline_function_documentation) @@ -165,11 +165,11 @@ BOOST_AUTO_TEST_CASE(multiline_function_documentation) " /// and it has 2 lines\n" " function functionName1(hash hashin) returns (hash hashout) {}\n" "}\n"; - BOOST_CHECK_NO_THROW(contract = parseText(text)); + BOOST_REQUIRE_NO_THROW(contract = parseText(text)); auto functions = contract->getDefinedFunctions(); - BOOST_CHECK_NO_THROW(function = functions.at(0)); - BOOST_CHECK_EQUAL(*function->getDocumentation().get(), + BOOST_REQUIRE_NO_THROW(function = functions.at(0)); + BOOST_CHECK_EQUAL(*function->getDocumentation(), " This is a test function\n" " and it has 2 lines"); } @@ -192,18 +192,42 @@ BOOST_AUTO_TEST_CASE(natspec_comment_in_function_body) " /// and it has 2 lines\n" " function fun(hash hashin) returns (hash hashout) {}\n" "}\n"; - BOOST_CHECK_NO_THROW(contract = parseText(text)); + BOOST_REQUIRE_NO_THROW(contract = parseText(text)); auto functions = contract->getDefinedFunctions(); - BOOST_CHECK_NO_THROW(function = functions.at(0)); - BOOST_CHECK_EQUAL(*function->getDocumentation().get(), " fun1 description"); + BOOST_REQUIRE_NO_THROW(function = functions.at(0)); + BOOST_CHECK_EQUAL(*function->getDocumentation(), " fun1 description"); - BOOST_CHECK_NO_THROW(function = functions.at(1)); - BOOST_CHECK_EQUAL(*function->getDocumentation().get(), + BOOST_REQUIRE_NO_THROW(function = functions.at(1)); + BOOST_CHECK_EQUAL(*function->getDocumentation(), " This is a test function\n" " and it has 2 lines"); } +BOOST_AUTO_TEST_CASE(natspec_docstring_after_signature) +{ + ASTPointer contract; + ASTPointer function; + char const* text = "contract test {\n" + " uint256 stateVar;\n" + " function fun1(uint256 a) {\n" + " /// I should have been above the function signature" + " {\n" + " var b;\n" + " /// I should not interfere with actual natspec comments\n" + " uint256 c;\n" + " mapping(address=>hash) d;\n" + " string name = \"Solidity\";" + " }\n" + "}\n"; + BOOST_REQUIRE_NO_THROW(contract = parseText(text)); + auto functions = contract->getDefinedFunctions(); + + BOOST_REQUIRE_NO_THROW(function = functions.at(0)); + BOOST_CHECK_MESSAGE(!function->getDocumentation(), + "Shouldn't get natspec docstring for this function"); +} + BOOST_AUTO_TEST_CASE(struct_definition) { char const* text = "contract test {\n" From 366514a72577d9e9b1c58fc768d084e73ef4f3a5 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Sun, 30 Nov 2014 23:33:04 +0100 Subject: [PATCH 07/10] Adding natspec comment test being between keyword and signature --- solidityParser.cpp | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/solidityParser.cpp b/solidityParser.cpp index e4db2ece7..6a97a5d99 100644 --- a/solidityParser.cpp +++ b/solidityParser.cpp @@ -204,6 +204,29 @@ BOOST_AUTO_TEST_CASE(natspec_comment_in_function_body) " and it has 2 lines"); } +BOOST_AUTO_TEST_CASE(natspec_docstring_between_keyword_and_signature) +{ + ASTPointer contract; + ASTPointer function; + char const* text = "contract test {\n" + " uint256 stateVar;\n" + " function ///I am in the wrong place \n" + " fun1(uint256 a) {\n" + " var b;\n" + " /// I should not interfere with actual natspec comments\n" + " uint256 c;\n" + " mapping(address=>hash) d;\n" + " string name = \"Solidity\";" + " }\n" + "}\n"; + BOOST_REQUIRE_NO_THROW(contract = parseText(text)); + auto functions = contract->getDefinedFunctions(); + + BOOST_REQUIRE_NO_THROW(function = functions.at(0)); + BOOST_CHECK_MESSAGE(!function->getDocumentation(), + "Shouldn't get natspec docstring for this function"); +} + BOOST_AUTO_TEST_CASE(natspec_docstring_after_signature) { ASTPointer contract; @@ -211,8 +234,7 @@ BOOST_AUTO_TEST_CASE(natspec_docstring_after_signature) char const* text = "contract test {\n" " uint256 stateVar;\n" " function fun1(uint256 a) {\n" - " /// I should have been above the function signature" - " {\n" + " /// I should have been above the function signature\n" " var b;\n" " /// I should not interfere with actual natspec comments\n" " uint256 c;\n" From d952833c1b86ce45c6da826ce2a9877ffa795d9e Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Mon, 1 Dec 2014 22:04:09 +0100 Subject: [PATCH 08/10] added logs to state tests --- TestHelper.cpp | 43 +++++++++++++++++++++++++++++++++++++++++++ TestHelper.h | 2 ++ stExampleFiller.json | 37 +++++++++++++++++++++++++++++++++++++ state.cpp | 3 +++ vm.cpp | 39 ++------------------------------------- vm.h | 2 -- 6 files changed, 87 insertions(+), 39 deletions(-) create mode 100644 stExampleFiller.json diff --git a/TestHelper.cpp b/TestHelper.cpp index b3d1bbe80..b9575ad2b 100644 --- a/TestHelper.cpp +++ b/TestHelper.cpp @@ -72,6 +72,7 @@ ImportTest::ImportTest(json_spirit::mObject& _o, bool isFiller): m_TestObject(_o if (!isFiller) { importState(_o["post"].get_obj(), m_statePost); + m_environment.sub.logs = importLog(_o["logs"].get_obj()); } } @@ -95,6 +96,7 @@ void ImportTest::importEnv(json_spirit::mObject& _o) m_statePre.m_currentBlock = m_environment.currentBlock; } + void ImportTest::importState(json_spirit::mObject& _o, State& _state) { for (auto& i: _o) @@ -148,6 +150,9 @@ void ImportTest::exportTest(bytes _output, State& _statePost) // export output m_TestObject["out"] = "0x" + toHex(_output); + // export logs + m_TestObject["logs"] = exportLog(_statePost.pending().size() ? _statePost.log(0) : LogEntries()); + // export post state json_spirit::mObject postState; @@ -255,6 +260,44 @@ bytes importCode(json_spirit::mObject& _o) return code; } +LogEntries importLog(json_spirit::mObject& _o) +{ + LogEntries logEntries; + for (auto const& l: _o) + { + json_spirit::mObject o = l.second.get_obj(); + // cant use BOOST_REQUIRE, because this function is used outside boost test (createRandomTest) + assert(o.count("address") > 0); + assert(o.count("topics") > 0); + assert(o.count("data") > 0); + LogEntry log; + log.address = Address(o["address"].get_str()); + for (auto const& t: o["topics"].get_array()) + log.topics.insert(h256(t.get_str())); + log.data = importData(o); + logEntries.push_back(log); + } + return logEntries; +} + +json_spirit::mObject exportLog(eth::LogEntries _logs) +{ + json_spirit::mObject ret; + if (_logs.size() == 0) return ret; + for (LogEntry const& l: _logs) + { + json_spirit::mObject o; + o["address"] = toString(l.address); + json_spirit::mArray topics; + for (auto const& t: l.topics) + topics.push_back(toString(t)); + o["topics"] = topics; + o["data"] = "0x" + toHex(l.data); + ret[toString(l.bloom())] = o; + } + return ret; +} + void checkOutput(bytes const& _output, json_spirit::mObject& _o) { int j = 0; diff --git a/TestHelper.h b/TestHelper.h index 7a2b8da51..c5c3a083d 100644 --- a/TestHelper.h +++ b/TestHelper.h @@ -68,6 +68,8 @@ u256 toInt(json_spirit::mValue const& _v); byte toByte(json_spirit::mValue const& _v); bytes importCode(json_spirit::mObject& _o); bytes importData(json_spirit::mObject& _o); +eth::LogEntries importLog(json_spirit::mObject& _o); +json_spirit::mObject exportLog(eth::LogEntries _logs); void checkOutput(bytes const& _output, json_spirit::mObject& _o); void checkStorage(std::map _expectedStore, std::map _resultStore, Address _expectedAddr); void checkLog(eth::LogEntries _resultLogs, eth::LogEntries _expectedLogs); diff --git a/stExampleFiller.json b/stExampleFiller.json new file mode 100644 index 000000000..7acf695ed --- /dev/null +++ b/stExampleFiller.json @@ -0,0 +1,37 @@ +{ + "add11" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "code" : "0x6001600101600055", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "", + "gasLimit" : "10000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000" + } + } +} diff --git a/state.cpp b/state.cpp index 8ee7b2e96..c2b41fca5 100644 --- a/state.cpp +++ b/state.cpp @@ -81,6 +81,9 @@ void doStateTests(json_spirit::mValue& v, bool _fillin) // check output checkOutput(output, o); + // check logs + checkLog(theState.pending().size() ? theState.log(0) : LogEntries(), importer.m_environment.sub.logs); + // check addresses auto expectedAddrs = importer.m_statePost.addresses(); auto resultAddrs = theState.addresses(); diff --git a/vm.cpp b/vm.cpp index edb983714..0d61bf6ba 100644 --- a/vm.cpp +++ b/vm.cpp @@ -120,41 +120,6 @@ void FakeExtVM::importEnv(mObject& _o) currentBlock.coinbaseAddress = Address(_o["currentCoinbase"].get_str()); } -mObject FakeExtVM::exportLog() -{ - mObject ret; - for (LogEntry const& l: sub.logs) - { - mObject o; - o["address"] = toString(l.address); - mArray topics; - for (auto const& t: l.topics) - topics.push_back(toString(t)); - o["topics"] = topics; - o["data"] = "0x" + toHex(l.data); - ret[toString(l.bloom())] = o; - } - return ret; -} - -void FakeExtVM::importLog(mObject& _o) -{ - for (auto const& l: _o) - { - mObject o = l.second.get_obj(); - // cant use BOOST_REQUIRE, because this function is used outside boost test (createRandomTest) - assert(o.count("address") > 0); - assert(o.count("topics") > 0); - assert(o.count("data") > 0); - LogEntry log; - log.address = Address(o["address"].get_str()); - for (auto const& t: o["topics"].get_array()) - log.topics.insert(h256(t.get_str())); - log.data = importData(o); - sub.logs.push_back(log); - } -} - mObject FakeExtVM::exportState() { mObject ret; @@ -384,7 +349,7 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) o["callcreates"] = fev.exportCallCreates(); o["out"] = "0x" + toHex(output); fev.push(o, "gas", gas); - o["logs"] = mValue(fev.exportLog()); + o["logs"] = mValue(exportLog(fev.sub.logs)); } } else @@ -402,7 +367,7 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) dev::test::FakeExtVM test; test.importState(o["post"].get_obj()); test.importCallCreates(o["callcreates"].get_array()); - test.importLog(o["logs"].get_obj()); + test.sub.logs = importLog(o["logs"].get_obj()); checkOutput(output, o); diff --git a/vm.h b/vm.h index eb98aa0ab..a52a02e31 100644 --- a/vm.h +++ b/vm.h @@ -66,8 +66,6 @@ public: u256 doPosts(); json_spirit::mObject exportEnv(); void importEnv(json_spirit::mObject& _o); - json_spirit::mObject exportLog(); - void importLog(json_spirit::mObject& _o); json_spirit::mObject exportState(); void importState(json_spirit::mObject& _object); json_spirit::mObject exportExec(); From 057553a0a08f473c3580782cbba3bc18b71966fa Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Mon, 1 Dec 2014 22:26:13 +0100 Subject: [PATCH 09/10] updated createRandomTest to correct exception behavior --- createRandomTest.cpp | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/createRandomTest.cpp b/createRandomTest.cpp index 60a2039c8..1647ce810 100644 --- a/createRandomTest.cpp +++ b/createRandomTest.cpp @@ -121,14 +121,14 @@ void doMyTests(json_spirit::mValue& v) { for (auto& i: v.get_obj()) { + cnote << i.first; mObject& o = i.second.get_obj(); assert(o.count("env") > 0); assert(o.count("pre") > 0); assert(o.count("exec") > 0); - eth::VM vm; - test::FakeExtVM fev; + dev::test::FakeExtVM fev; fev.importEnv(o["env"].get_obj()); fev.importState(o["pre"].get_obj()); @@ -141,17 +141,20 @@ void doMyTests(json_spirit::mValue& v) fev.code = fev.thisTxCode; } - vm.reset(fev.gas); bytes output; + eth::VM vm(fev.gas); + u256 gas; + bool vmExceptionOccured = false; try { - output = vm.go(fev).toBytes(); + output = vm.go(fev, fev.simpleTrace()).toBytes(); + gas = vm.gas(); } catch (eth::VMException const& _e) { cnote << "VM did throw an exception: " << diagnostic_information(_e); - gas = 0; + vmExceptionOccured = true; } catch (Exception const& _e) { @@ -180,9 +183,13 @@ void doMyTests(json_spirit::mValue& v) o["env"] = mValue(fev.exportEnv()); o["exec"] = mValue(fev.exportExec()); - o["post"] = mValue(fev.exportState()); - o["callcreates"] = fev.exportCallCreates(); - o["out"] = "0x" + toHex(output); - fev.push(o, "gas", gas); + if (!vmExceptionOccured) + { + o["post"] = mValue(fev.exportState()); + o["callcreates"] = fev.exportCallCreates(); + o["out"] = "0x" + toHex(output); + fev.push(o, "gas", gas); + o["logs"] = mValue(test::exportLog(fev.sub.logs)); + } } } From fb7c3bb302e5d309b500e2929a565b427de23a8b Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Mon, 1 Dec 2014 22:44:31 +0100 Subject: [PATCH 10/10] style Conflicts: libevm/VM.h --- TestHelper.cpp | 67 +++++++++++++++++++++++++------------------------- state.cpp | 4 +-- vm.cpp | 4 +-- 3 files changed, 37 insertions(+), 38 deletions(-) diff --git a/TestHelper.cpp b/TestHelper.cpp index b9575ad2b..bfdd393d7 100644 --- a/TestHelper.cpp +++ b/TestHelper.cpp @@ -72,7 +72,7 @@ ImportTest::ImportTest(json_spirit::mObject& _o, bool isFiller): m_TestObject(_o if (!isFiller) { importState(_o["post"].get_obj(), m_statePost); - m_environment.sub.logs = importLog(_o["logs"].get_obj()); + m_environment.sub.logs = importLog(_o["logs"].get_obj()); } } @@ -96,7 +96,6 @@ void ImportTest::importEnv(json_spirit::mObject& _o) m_statePre.m_currentBlock = m_environment.currentBlock; } - void ImportTest::importState(json_spirit::mObject& _o, State& _state) { for (auto& i: _o) @@ -150,8 +149,8 @@ void ImportTest::exportTest(bytes _output, State& _statePost) // export output m_TestObject["out"] = "0x" + toHex(_output); - // export logs - m_TestObject["logs"] = exportLog(_statePost.pending().size() ? _statePost.log(0) : LogEntries()); + // export logs + m_TestObject["logs"] = exportLog(_statePost.pending().size() ? _statePost.log(0) : LogEntries()); // export post state json_spirit::mObject postState; @@ -262,40 +261,40 @@ bytes importCode(json_spirit::mObject& _o) LogEntries importLog(json_spirit::mObject& _o) { - LogEntries logEntries; - for (auto const& l: _o) - { - json_spirit::mObject o = l.second.get_obj(); - // cant use BOOST_REQUIRE, because this function is used outside boost test (createRandomTest) - assert(o.count("address") > 0); - assert(o.count("topics") > 0); - assert(o.count("data") > 0); - LogEntry log; - log.address = Address(o["address"].get_str()); - for (auto const& t: o["topics"].get_array()) - log.topics.insert(h256(t.get_str())); - log.data = importData(o); - logEntries.push_back(log); - } - return logEntries; + LogEntries logEntries; + for (auto const& l: _o) + { + json_spirit::mObject o = l.second.get_obj(); + // cant use BOOST_REQUIRE, because this function is used outside boost test (createRandomTest) + assert(o.count("address") > 0); + assert(o.count("topics") > 0); + assert(o.count("data") > 0); + LogEntry log; + log.address = Address(o["address"].get_str()); + for (auto const& t: o["topics"].get_array()) + log.topics.insert(h256(t.get_str())); + log.data = importData(o); + logEntries.push_back(log); + } + return logEntries; } json_spirit::mObject exportLog(eth::LogEntries _logs) { - json_spirit::mObject ret; - if (_logs.size() == 0) return ret; - for (LogEntry const& l: _logs) - { - json_spirit::mObject o; - o["address"] = toString(l.address); - json_spirit::mArray topics; - for (auto const& t: l.topics) - topics.push_back(toString(t)); - o["topics"] = topics; - o["data"] = "0x" + toHex(l.data); - ret[toString(l.bloom())] = o; - } - return ret; + json_spirit::mObject ret; + if (_logs.size() == 0) return ret; + for (LogEntry const& l: _logs) + { + json_spirit::mObject o; + o["address"] = toString(l.address); + json_spirit::mArray topics; + for (auto const& t: l.topics) + topics.push_back(toString(t)); + o["topics"] = topics; + o["data"] = "0x" + toHex(l.data); + ret[toString(l.bloom())] = o; + } + return ret; } void checkOutput(bytes const& _output, json_spirit::mObject& _o) diff --git a/state.cpp b/state.cpp index c2b41fca5..5fc23f149 100644 --- a/state.cpp +++ b/state.cpp @@ -81,8 +81,8 @@ void doStateTests(json_spirit::mValue& v, bool _fillin) // check output checkOutput(output, o); - // check logs - checkLog(theState.pending().size() ? theState.log(0) : LogEntries(), importer.m_environment.sub.logs); + // check logs + checkLog(theState.pending().size() ? theState.log(0) : LogEntries(), importer.m_environment.sub.logs); // check addresses auto expectedAddrs = importer.m_statePost.addresses(); diff --git a/vm.cpp b/vm.cpp index 0d61bf6ba..8c9810a2c 100644 --- a/vm.cpp +++ b/vm.cpp @@ -349,7 +349,7 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) o["callcreates"] = fev.exportCallCreates(); o["out"] = "0x" + toHex(output); fev.push(o, "gas", gas); - o["logs"] = mValue(exportLog(fev.sub.logs)); + o["logs"] = mValue(exportLog(fev.sub.logs)); } } else @@ -367,7 +367,7 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) dev::test::FakeExtVM test; test.importState(o["post"].get_obj()); test.importCallCreates(o["callcreates"].get_array()); - test.sub.logs = importLog(o["logs"].get_obj()); + test.sub.logs = importLog(o["logs"].get_obj()); checkOutput(output, o);