Merge pull request #1157 from chriseth/sol_arrayShortening

Copying arrays and shortening of dynamic arrays.
This commit is contained in:
chriseth 2015-03-02 12:51:58 +01:00
commit 1ec4deff01
2 changed files with 233 additions and 0 deletions

View File

@ -2768,6 +2768,184 @@ BOOST_AUTO_TEST_CASE(dynamic_out_of_bounds_array_access)
BOOST_CHECK(callContractFunction("length()") == encodeArgs(4));
}
BOOST_AUTO_TEST_CASE(fixed_array_cleanup)
{
char const* sourceCode = R"(
contract c {
uint spacer1;
uint spacer2;
uint[20] data;
function fill() {
for (uint i = 0; i < data.length; ++i) data[i] = i+1;
}
function clear() { delete data; }
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(m_state.storage(m_contractAddress).empty());
BOOST_CHECK(callContractFunction("fill()") == bytes());
BOOST_CHECK(!m_state.storage(m_contractAddress).empty());
BOOST_CHECK(callContractFunction("clear()") == bytes());
BOOST_CHECK(m_state.storage(m_contractAddress).empty());
}
BOOST_AUTO_TEST_CASE(short_fixed_array_cleanup)
{
char const* sourceCode = R"(
contract c {
uint spacer1;
uint spacer2;
uint[3] data;
function fill() {
for (uint i = 0; i < data.length; ++i) data[i] = i+1;
}
function clear() { delete data; }
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(m_state.storage(m_contractAddress).empty());
BOOST_CHECK(callContractFunction("fill()") == bytes());
BOOST_CHECK(!m_state.storage(m_contractAddress).empty());
BOOST_CHECK(callContractFunction("clear()") == bytes());
BOOST_CHECK(m_state.storage(m_contractAddress).empty());
}
BOOST_AUTO_TEST_CASE(dynamic_array_cleanup)
{
char const* sourceCode = R"(
contract c {
uint[20] spacer;
uint[] dynamic;
function fill() {
dynamic.length = 21;
for (uint i = 0; i < dynamic.length; ++i) dynamic[i] = i+1;
}
function halfClear() { dynamic.length = 5; }
function fullClear() { delete dynamic; }
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(m_state.storage(m_contractAddress).empty());
BOOST_CHECK(callContractFunction("fill()") == bytes());
BOOST_CHECK(!m_state.storage(m_contractAddress).empty());
BOOST_CHECK(callContractFunction("halfClear()") == bytes());
BOOST_CHECK(!m_state.storage(m_contractAddress).empty());
BOOST_CHECK(callContractFunction("fullClear()") == bytes());
BOOST_CHECK(m_state.storage(m_contractAddress).empty());
}
BOOST_AUTO_TEST_CASE(dynamic_multi_array_cleanup)
{
char const* sourceCode = R"(
contract c {
struct s { uint[][] d; }
s[] data;
function fill() returns (uint) {
data.length = 3;
data[2].d.length = 4;
data[2].d[3].length = 5;
data[2].d[3][4] = 8;
return data[2].d[3][4];
}
function clear() { delete data; }
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(m_state.storage(m_contractAddress).empty());
BOOST_CHECK(callContractFunction("fill()") == encodeArgs(8));
BOOST_CHECK(!m_state.storage(m_contractAddress).empty());
BOOST_CHECK(callContractFunction("clear()") == bytes());
BOOST_CHECK(m_state.storage(m_contractAddress).empty());
}
BOOST_AUTO_TEST_CASE(array_copy_storage_storage_dyn_dyn)
{
char const* sourceCode = R"(
contract c {
uint[] data1;
uint[] data2;
function setData1(uint length, uint index, uint value) {
data1.length = length; if (index < length) data1[index] = value;
}
function copyStorageStorage() { data2 = data1; }
function getData2(uint index) returns (uint len, uint val) {
len = data2.length; if (index < len) val = data2[index];
}
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("setData1(uint256,uint256,uint256)", 10, 5, 4) == bytes());
BOOST_CHECK(callContractFunction("copyStorageStorage()") == bytes());
BOOST_CHECK(callContractFunction("getData2(uint256)", 5) == encodeArgs(10, 4));
BOOST_CHECK(callContractFunction("setData1(uint256,uint256,uint256)", 0, 0, 0) == bytes());
BOOST_CHECK(callContractFunction("copyStorageStorage()") == bytes());
BOOST_CHECK(callContractFunction("getData2(uint256)", 0) == encodeArgs(0, 0));
BOOST_CHECK(m_state.storage(m_contractAddress).empty());
}
BOOST_AUTO_TEST_CASE(array_copy_storage_storage_static_static)
{
char const* sourceCode = R"(
contract c {
uint[40] data1;
uint[20] data2;
function test() returns (uint x, uint y){
data1[30] = 4;
data1[2] = 7;
data1[3] = 9;
data2[3] = 8;
data1 = data2;
x = data1[3];
y = data1[30]; // should be cleared
}
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("test()") == encodeArgs(8, 0));
}
BOOST_AUTO_TEST_CASE(array_copy_storage_storage_static_dynamic)
{
char const* sourceCode = R"(
contract c {
uint[9] data1;
uint[] data2;
function test() returns (uint x, uint y){
data1[8] = 4;
data2 = data1;
x = data2.length;
y = data2[8];
}
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("test()") == encodeArgs(9, 4));
}
BOOST_AUTO_TEST_CASE(array_copy_storage_storage_struct)
{
char const* sourceCode = R"(
contract c {
struct Data { uint x; uint y; }
Data[] data1;
Data[] data2;
function test() returns (uint x, uint y) {
data1.length = 9;
data1[8].x = 4;
data1[8].y = 5;
data2 = data1;
x = data2[8].x;
y = data2[8].y;
data1.length = 0;
data2 = data1;
}
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("test()") == encodeArgs(4, 5));
BOOST_CHECK(m_state.storage(m_contractAddress).empty());
}
BOOST_AUTO_TEST_SUITE_END()
}

View File

@ -1185,6 +1185,61 @@ BOOST_AUTO_TEST_CASE(array_with_nonconstant_length)
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(array_copy_with_different_types1)
{
char const* text = R"(
contract c {
bytes a;
uint[] b;
function f() { b = a; }
})";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(array_copy_with_different_types2)
{
char const* text = R"(
contract c {
uint32[] a;
uint8[] b;
function f() { b = a; }
})";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(array_copy_with_different_types_conversion_possible)
{
char const* text = R"(
contract c {
uint32[] a;
uint8[] b;
function f() { a = b; }
})";
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
}
BOOST_AUTO_TEST_CASE(array_copy_with_different_types_static_dynamic)
{
char const* text = R"(
contract c {
uint32[] a;
uint8[80] b;
function f() { a = b; }
})";
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
}
BOOST_AUTO_TEST_CASE(array_copy_with_different_types_dynamic_static)
{
char const* text = R"(
contract c {
uint[] a;
uint[80] b;
function f() { b = a; }
})";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_SUITE_END()
}