diff options
author | Paweł Bylica <pawel.bylica@imapp.pl> | 2015-05-21 02:14:38 +0800 |
---|---|---|
committer | Paweł Bylica <pawel.bylica@imapp.pl> | 2015-05-21 02:14:38 +0800 |
commit | d67cacfcba60de5099c19c802398268ac462ed1c (patch) | |
tree | 4d5306d451cd46a59cdd157402273dbb0f49352b | |
parent | 3108f4efe96cf22501227b71b261dfda4f20599c (diff) | |
parent | e5a4a8fca4832dff79227dc6ed667b7f1c879faf (diff) | |
download | dexon-solidity-d67cacfcba60de5099c19c802398268ac462ed1c.tar.gz dexon-solidity-d67cacfcba60de5099c19c802398268ac462ed1c.tar.zst dexon-solidity-d67cacfcba60de5099c19c802398268ac462ed1c.zip |
Merge remote-tracking branch 'upstream/develop' into feature/vm_gas_counter_refactor
-rw-r--r-- | libsolidity/GasMeter.cpp (renamed from GasMeter.cpp) | 60 | ||||
-rw-r--r-- | libsolidity/SolidityEndToEndTest.cpp | 86 | ||||
-rw-r--r-- | libsolidity/solidityExecutionFramework.h | 11 |
3 files changed, 152 insertions, 5 deletions
diff --git a/GasMeter.cpp b/libsolidity/GasMeter.cpp index 0ffe4171..43eb3f95 100644 --- a/GasMeter.cpp +++ b/libsolidity/GasMeter.cpp @@ -21,6 +21,8 @@ */ #include <test/libsolidity/solidityExecutionFramework.h> +#include <libevmasm/GasMeter.h> +#include <libevmasm/KnownState.h> #include <libsolidity/AST.h> #include <libsolidity/StructuralGasEstimator.h> #include <libsolidity/SourceReferenceFormatter.h> @@ -55,8 +57,21 @@ public: ); } + void testCreationTimeGas(string const& _sourceCode, string const& _contractName = "") + { + compileAndRun(_sourceCode); + auto state = make_shared<KnownState>(); + GasMeter meter(state); + GasMeter::GasConsumption gas; + for (AssemblyItem const& item: *m_compiler.getAssemblyItems(_contractName)) + gas += meter.estimateMax(item); + u256 bytecodeSize(m_compiler.getRuntimeBytecode(_contractName).size()); + gas += bytecodeSize * c_createDataGas; + BOOST_REQUIRE(!gas.isInfinite); + BOOST_CHECK(gas.value == m_gasUsed); + } + protected: - dev::solidity::CompilerStack m_compiler; map<ASTNode const*, eth::GasMeter::GasConsumption> m_gasCosts; }; @@ -91,6 +106,49 @@ BOOST_AUTO_TEST_CASE(non_overlapping_filtered_costs) } } +BOOST_AUTO_TEST_CASE(simple_contract) +{ + // Tests a simple "deploy contract" code without constructor. The actual contract is not relevant. + char const* sourceCode = R"( + contract test { + bytes32 public shaValue; + function f(uint a) { + shaValue = sha3(a); + } + } + )"; + testCreationTimeGas(sourceCode); +} + +BOOST_AUTO_TEST_CASE(store_sha3) +{ + char const* sourceCode = R"( + contract test { + bytes32 public shaValue; + function test(uint a) { + shaValue = sha3(a); + } + } + )"; + testCreationTimeGas(sourceCode); +} + +BOOST_AUTO_TEST_CASE(updating_store) +{ + char const* sourceCode = R"( + contract test { + uint data; + uint data2; + function test() { + data = 1; + data = 2; + data2 = 0; + } + } + )"; + testCreationTimeGas(sourceCode); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/libsolidity/SolidityEndToEndTest.cpp b/libsolidity/SolidityEndToEndTest.cpp index 90ce20d2..503615a5 100644 --- a/libsolidity/SolidityEndToEndTest.cpp +++ b/libsolidity/SolidityEndToEndTest.cpp @@ -4023,6 +4023,92 @@ BOOST_AUTO_TEST_CASE(overwriting_inheritance) BOOST_CHECK(callContractFunction("checkOk()") == encodeArgs(6)); } +BOOST_AUTO_TEST_CASE(struct_assign_reference_to_struct) +{ + char const* sourceCode = R"( + contract test { + struct testStruct + { + uint m_value; + } + testStruct data1; + testStruct data2; + testStruct data3; + function test() + { + data1.m_value = 2; + } + function assign() returns (uint ret_local, uint ret_global, uint ret_global3, uint ret_global1) + { + testStruct x = data1; //x is a reference data1.m_value == 2 as well as x.m_value = 2 + data2 = data1; // should copy data. data2.m_value == 2 + + ret_local = x.m_value; // = 2 + ret_global = data2.m_value; // = 2 + + x.m_value = 3; + data3 = x; //should copy the data. data3.m_value == 3 + ret_global3 = data3.m_value; // = 3 + ret_global1 = data1.m_value; // = 3. Changed due to the assignment to x.m_value + } + } + )"; + compileAndRun(sourceCode, 0, "test"); + BOOST_CHECK(callContractFunction("assign()") == encodeArgs(2, 2, 3, 3)); +} + +BOOST_AUTO_TEST_CASE(struct_delete_member) +{ + char const* sourceCode = R"( + contract test { + struct testStruct + { + uint m_value; + } + testStruct data1; + function test() + { + data1.m_value = 2; + } + function deleteMember() returns (uint ret_value) + { + testStruct x = data1; //should not copy the data. data1.m_value == 2 but x.m_value = 0 + x.m_value = 4; + delete x.m_value; + ret_value = data1.m_value; + } + } + )"; + compileAndRun(sourceCode, 0, "test"); + auto res = callContractFunction("deleteMember()"); + BOOST_CHECK(callContractFunction("deleteMember()") == encodeArgs(0)); +} + +BOOST_AUTO_TEST_CASE(struct_delete_struct_in_mapping) +{ + char const* sourceCode = R"( + contract test { + struct testStruct + { + uint m_value; + } + mapping (uint => testStruct) campaigns; + + function test() + { + campaigns[0].m_value = 2; + } + function deleteIt() returns (uint) + { + delete campaigns[0]; + return campaigns[0].m_value; + } + } + )"; + compileAndRun(sourceCode, 0, "test"); + auto res = callContractFunction("deleteIt()"); + BOOST_CHECK(callContractFunction("deleteIt()") == encodeArgs(0)); +} BOOST_AUTO_TEST_SUITE_END() diff --git a/libsolidity/solidityExecutionFramework.h b/libsolidity/solidityExecutionFramework.h index f76465f2..fa25fb12 100644 --- a/libsolidity/solidityExecutionFramework.h +++ b/libsolidity/solidityExecutionFramework.h @@ -44,11 +44,11 @@ public: bytes const& compileAndRun(std::string const& _sourceCode, u256 const& _value = 0, std::string const& _contractName = "") { - dev::solidity::CompilerStack compiler(m_addStandardSources); - compiler.addSource("", _sourceCode); - ETH_TEST_REQUIRE_NO_THROW(compiler.compile(m_optimize), "Compiling contract failed"); + m_compiler.reset(false, m_addStandardSources); + m_compiler.addSource("", _sourceCode); + ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(m_optimize), "Compiling contract failed"); - bytes code = compiler.getBytecode(_contractName); + bytes code = m_compiler.getBytecode(_contractName); sendMessage(code, true, _value); BOOST_REQUIRE(!m_output.empty()); return m_output; @@ -160,12 +160,14 @@ protected: BOOST_REQUIRE(executive.go()); m_state.noteSending(m_sender); executive.finalize(); + m_gasUsed = executive.gasUsed(); m_output = executive.out().toVector(); m_logs = executive.logs(); } bool m_optimize = false; bool m_addStandardSources = false; + dev::solidity::CompilerStack m_compiler; Address m_sender; Address m_contractAddress; eth::State m_state; @@ -173,6 +175,7 @@ protected: u256 const m_gas = 100000000; bytes m_output; eth::LogEntries m_logs; + u256 m_gasUsed; }; } |