aboutsummaryrefslogtreecommitdiffstats
path: root/solidityEndToEndTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'solidityEndToEndTest.cpp')
-rw-r--r--solidityEndToEndTest.cpp192
1 files changed, 147 insertions, 45 deletions
diff --git a/solidityEndToEndTest.cpp b/solidityEndToEndTest.cpp
index b28b8499..35c2a3b0 100644
--- a/solidityEndToEndTest.cpp
+++ b/solidityEndToEndTest.cpp
@@ -41,31 +41,31 @@ class ExecutionFramework
public:
ExecutionFramework() { g_logVerbosity = 0; }
- bytes compileAndRun(std::string const& _sourceCode)
+ bytes const& compileAndRun(std::string const& _sourceCode)
{
bytes code = dev::solidity::CompilerStack::compile(_sourceCode);
sendMessage(code, true);
+ BOOST_REQUIRE(!m_output.empty());
return m_output;
}
- bytes callFunction(byte _index, bytes const& _data)
+ bytes const& callFunction(byte _index, bytes const& _data)
{
sendMessage(bytes(1, _index) + _data, false);
return m_output;
}
- bytes callFunction(byte _index, u256 const& _argument1)
+ bytes const& callFunction(byte _index, u256 const& _argument1)
{
- callFunction(_index, toBigEndian(_argument1));
- return m_output;
+ return callFunction(_index, toBigEndian(_argument1));
}
private:
void sendMessage(bytes const& _data, bool _isCreation)
{
eth::Executive executive(m_state);
- eth::Transaction t = _isCreation ? eth::Transaction(0, m_gasPrice, m_gas, _data)
- : eth::Transaction(0, m_gasPrice, m_gas, m_contractAddress, _data);
+ eth::Transaction t = _isCreation ? eth::Transaction(0, m_gasPrice, m_gas, _data, 0, KeyPair::create().sec())
+ : eth::Transaction(0, m_gasPrice, m_gas, m_contractAddress, _data, 0, KeyPair::create().sec());
bytes transactionRLP = t.rlp();
try
{
@@ -77,13 +77,14 @@ private:
{
BOOST_REQUIRE(!executive.create(Address(), 0, m_gasPrice, m_gas, &_data, Address()));
m_contractAddress = executive.newAddress();
+ BOOST_REQUIRE(m_contractAddress);
BOOST_REQUIRE(m_state.addressHasCode(m_contractAddress));
}
else
BOOST_REQUIRE(!executive.call(m_contractAddress, Address(), 0, m_gasPrice, &_data, m_gas, Address()));
BOOST_REQUIRE(executive.go());
executive.finalize();
- m_output = executive.out().toBytes();
+ m_output = executive.out().toVector();
}
Address m_contractAddress;
@@ -93,27 +94,24 @@ private:
bytes m_output;
};
-BOOST_AUTO_TEST_SUITE(SolidityCompilerEndToEndTest)
+BOOST_FIXTURE_TEST_SUITE(SolidityCompilerEndToEndTest, ExecutionFramework)
BOOST_AUTO_TEST_CASE(smoke_test)
{
char const* sourceCode = "contract test {\n"
" function f(uint a) returns(uint d) { return a * 7; }\n"
"}\n";
- ExecutionFramework framework;
- framework.compileAndRun(sourceCode);
+ compileAndRun(sourceCode);
u256 a = 0x200030004;
- bytes result = framework.callFunction(0, a);
- BOOST_CHECK(result == toBigEndian(a * 7));
+ BOOST_CHECK(callFunction(0, a) == toBigEndian(a * 7));
}
BOOST_AUTO_TEST_CASE(empty_contract)
{
char const* sourceCode = "contract test {\n"
"}\n";
- ExecutionFramework framework;
- framework.compileAndRun(sourceCode);
- BOOST_CHECK(framework.callFunction(0, bytes()).empty());
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFunction(0, bytes()).empty());
}
BOOST_AUTO_TEST_CASE(recursive_calls)
@@ -124,13 +122,12 @@ BOOST_AUTO_TEST_CASE(recursive_calls)
" else return n * f(n - 1);\n"
" }\n"
"}\n";
- ExecutionFramework framework;
- framework.compileAndRun(sourceCode);
- BOOST_CHECK(framework.callFunction(0, u256(0)) == toBigEndian(u256(1)));
- BOOST_CHECK(framework.callFunction(0, u256(1)) == toBigEndian(u256(1)));
- BOOST_CHECK(framework.callFunction(0, u256(2)) == toBigEndian(u256(2)));
- BOOST_CHECK(framework.callFunction(0, u256(3)) == toBigEndian(u256(6)));
- BOOST_CHECK(framework.callFunction(0, u256(4)) == toBigEndian(u256(24)));
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFunction(0, u256(0)) == toBigEndian(u256(1)));
+ BOOST_CHECK(callFunction(0, u256(1)) == toBigEndian(u256(1)));
+ BOOST_CHECK(callFunction(0, u256(2)) == toBigEndian(u256(2)));
+ BOOST_CHECK(callFunction(0, u256(3)) == toBigEndian(u256(6)));
+ BOOST_CHECK(callFunction(0, u256(4)) == toBigEndian(u256(24)));
}
BOOST_AUTO_TEST_CASE(while_loop)
@@ -142,13 +139,61 @@ BOOST_AUTO_TEST_CASE(while_loop)
" while (i <= n) nfac *= i++;\n"
" }\n"
"}\n";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFunction(0, u256(0)) == toBigEndian(u256(1)));
+ BOOST_CHECK(callFunction(0, u256(1)) == toBigEndian(u256(1)));
+ BOOST_CHECK(callFunction(0, u256(2)) == toBigEndian(u256(2)));
+ BOOST_CHECK(callFunction(0, u256(3)) == toBigEndian(u256(6)));
+ BOOST_CHECK(callFunction(0, u256(4)) == toBigEndian(u256(24)));
+}
+
+BOOST_AUTO_TEST_CASE(break_outside_loop)
+{
+ // break and continue outside loops should be simply ignored
+ char const* sourceCode = "contract test {\n"
+ " function f(uint x) returns(uint y) {\n"
+ " break; continue; return 2;\n"
+ " }\n"
+ "}\n";
+ ExecutionFramework framework;
+ framework.compileAndRun(sourceCode);
+ BOOST_CHECK(framework.callFunction(0, u256(0)) == toBigEndian(u256(2)));
+}
+
+BOOST_AUTO_TEST_CASE(nested_loops)
+{
+ // tests that break and continue statements in nested loops jump to the correct place
+ char const* sourceCode = "contract test {\n"
+ " function f(uint x) returns(uint y) {\n"
+ " while (x > 1) {\n"
+ " if (x == 10) break;\n"
+ " while (x > 5) {\n"
+ " if (x == 8) break;\n"
+ " x--;\n"
+ " if (x == 6) continue;\n"
+ " return x;\n"
+ " }\n"
+ " x--;\n"
+ " if (x == 3) continue;\n"
+ " break;\n"
+ " }\n"
+ " return x;\n"
+ " }\n"
+ "}\n";
ExecutionFramework framework;
framework.compileAndRun(sourceCode);
- BOOST_CHECK(framework.callFunction(0, u256(0)) == toBigEndian(u256(1)));
+ BOOST_CHECK(framework.callFunction(0, u256(0)) == toBigEndian(u256(0)));
BOOST_CHECK(framework.callFunction(0, u256(1)) == toBigEndian(u256(1)));
- BOOST_CHECK(framework.callFunction(0, u256(2)) == toBigEndian(u256(2)));
- BOOST_CHECK(framework.callFunction(0, u256(3)) == toBigEndian(u256(6)));
- BOOST_CHECK(framework.callFunction(0, u256(4)) == toBigEndian(u256(24)));
+ BOOST_CHECK(framework.callFunction(0, u256(2)) == toBigEndian(u256(1)));
+ BOOST_CHECK(framework.callFunction(0, u256(3)) == toBigEndian(u256(2)));
+ BOOST_CHECK(framework.callFunction(0, u256(4)) == toBigEndian(u256(2)));
+ BOOST_CHECK(framework.callFunction(0, u256(5)) == toBigEndian(u256(4)));
+ BOOST_CHECK(framework.callFunction(0, u256(6)) == toBigEndian(u256(5)));
+ BOOST_CHECK(framework.callFunction(0, u256(7)) == toBigEndian(u256(5)));
+ BOOST_CHECK(framework.callFunction(0, u256(8)) == toBigEndian(u256(7)));
+ BOOST_CHECK(framework.callFunction(0, u256(9)) == toBigEndian(u256(8)));
+ BOOST_CHECK(framework.callFunction(0, u256(10)) == toBigEndian(u256(10)));
+ BOOST_CHECK(framework.callFunction(0, u256(11)) == toBigEndian(u256(10)));
}
BOOST_AUTO_TEST_CASE(calling_other_functions)
@@ -168,13 +213,12 @@ BOOST_AUTO_TEST_CASE(calling_other_functions)
" return 3 * x + 1;\n"
" }\n"
"}\n";
- ExecutionFramework framework;
- framework.compileAndRun(sourceCode);
- BOOST_CHECK(framework.callFunction(2, u256(0)) == toBigEndian(u256(0)));
- BOOST_CHECK(framework.callFunction(2, u256(1)) == toBigEndian(u256(1)));
- BOOST_CHECK(framework.callFunction(2, u256(2)) == toBigEndian(u256(1)));
- BOOST_CHECK(framework.callFunction(2, u256(8)) == toBigEndian(u256(1)));
- BOOST_CHECK(framework.callFunction(2, u256(127)) == toBigEndian(u256(1)));
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFunction(2, u256(0)) == toBigEndian(u256(0)));
+ BOOST_CHECK(callFunction(2, u256(1)) == toBigEndian(u256(1)));
+ BOOST_CHECK(callFunction(2, u256(2)) == toBigEndian(u256(1)));
+ BOOST_CHECK(callFunction(2, u256(8)) == toBigEndian(u256(1)));
+ BOOST_CHECK(callFunction(2, u256(127)) == toBigEndian(u256(1)));
}
BOOST_AUTO_TEST_CASE(many_local_variables)
@@ -186,12 +230,25 @@ BOOST_AUTO_TEST_CASE(many_local_variables)
" y += b + x2;\n"
" }\n"
"}\n";
- ExecutionFramework framework;
- framework.compileAndRun(sourceCode);
- BOOST_CHECK(framework.callFunction(0, toBigEndian(u256(0x1000)) + toBigEndian(u256(0x10000)) + toBigEndian(u256(0x100000)))
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFunction(0, toBigEndian(u256(0x1000)) + toBigEndian(u256(0x10000)) + toBigEndian(u256(0x100000)))
== toBigEndian(u256(0x121121)));
}
+BOOST_AUTO_TEST_CASE(packing_unpacking_types)
+{
+ char const* sourceCode = "contract test {\n"
+ " function run(bool a, uint32 b, uint64 c) returns(uint256 y) {\n"
+ " if (a) y = 1;\n"
+ " y = y * 0x100000000 | ~b;\n"
+ " y = y * 0x10000000000000000 | ~c;\n"
+ " }\n"
+ "}\n";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFunction(0, fromHex("01""0f0f0f0f""f0f0f0f0f0f0f0f0"))
+ == fromHex("00000000000000000000000000000000000000""01""f0f0f0f0""0f0f0f0f0f0f0f0f"));
+}
+
BOOST_AUTO_TEST_CASE(multiple_return_values)
{
char const* sourceCode = "contract test {\n"
@@ -199,9 +256,8 @@ BOOST_AUTO_TEST_CASE(multiple_return_values)
" y1 = x2; y2 = x1;\n"
" }\n"
"}\n";
- ExecutionFramework framework;
- framework.compileAndRun(sourceCode);
- BOOST_CHECK(framework.callFunction(0, bytes(1, 1) + toBigEndian(u256(0xcd)))
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFunction(0, bytes(1, 1) + toBigEndian(u256(0xcd)))
== toBigEndian(u256(0xcd)) + bytes(1, 1) + toBigEndian(u256(0)));
}
@@ -213,13 +269,59 @@ BOOST_AUTO_TEST_CASE(short_circuiting)
" return x;"
" }\n"
"}\n";
- ExecutionFramework framework;
- framework.compileAndRun(sourceCode);
- BOOST_CHECK(framework.callFunction(0, u256(0)) == toBigEndian(u256(0)));
- BOOST_CHECK(framework.callFunction(0, u256(1)) == toBigEndian(u256(8)));
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFunction(0, u256(0)) == toBigEndian(u256(0)));
+ BOOST_CHECK(callFunction(0, u256(1)) == toBigEndian(u256(8)));
+}
+
+BOOST_AUTO_TEST_CASE(high_bits_cleaning)
+{
+ char const* sourceCode = "contract test {\n"
+ " function run() returns(uint256 y) {\n"
+ " uint32 x = uint32(0xffffffff) + 10;\n"
+ " if (x >= 0xffffffff) return 0;\n"
+ " return x;"
+ " }\n"
+ "}\n";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFunction(0, bytes()) == toBigEndian(u256(9)));
}
-//@todo test smaller types
+BOOST_AUTO_TEST_CASE(sign_extension)
+{
+ char const* sourceCode = "contract test {\n"
+ " function run() returns(uint256 y) {\n"
+ " int64 x = -int32(0xff);\n"
+ " if (x >= 0xff) return 0;\n"
+ " return -uint256(x);"
+ " }\n"
+ "}\n";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFunction(0, bytes()) == toBigEndian(u256(0xff)));
+}
+
+BOOST_AUTO_TEST_CASE(small_unsigned_types)
+{
+ char const* sourceCode = "contract test {\n"
+ " function run() returns(uint256 y) {\n"
+ " uint32 x = uint32(0xffffff) * 0xffffff;\n"
+ " return x / 0x100;"
+ " }\n"
+ "}\n";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFunction(0, bytes()) == toBigEndian(u256(0xfe0000)));
+}
+
+BOOST_AUTO_TEST_CASE(small_signed_types)
+{
+ char const* sourceCode = "contract test {\n"
+ " function run() returns(int256 y) {\n"
+ " return -int32(10) * -int64(20);\n"
+ " }\n"
+ "}\n";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFunction(0, bytes()) == toBigEndian(u256(200)));
+}
BOOST_AUTO_TEST_SUITE_END()