From 39f90683e3b9f89630c2277a589c96c0a3915b1f Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 7 Nov 2014 03:32:37 +0100 Subject: [PATCH 1/2] solidity endToEnd testing gets equivalent CPP contracts - Just testing the waters of our codebase by introducing C++ version of the contract functions in the end to end solidity tests - This way there is no need to check for some specific output but instead strive for consistency between the C++ and solidity code. --- solidityEndToEndTest.cpp | 163 +++++++++++++++++++++++++++++++-------- 1 file changed, 130 insertions(+), 33 deletions(-) diff --git a/solidityEndToEndTest.cpp b/solidityEndToEndTest.cpp index 35c2a3b02..e4ab7b876 100644 --- a/solidityEndToEndTest.cpp +++ b/solidityEndToEndTest.cpp @@ -60,6 +60,16 @@ public: return callFunction(_index, toBigEndian(_argument1)); } + bool testSolidityAgainstCpp(byte _index, std::function const& _cppfun, u256 const& _argument1) + { + return toBigEndian(_cppfun(_argument1)) == callFunction(_index, toBigEndian(_argument1)); + } + + bool testSolidityAgainstCpp(byte _index, std::function const& _cppfun) + { + return toBigEndian(_cppfun()) == callFunction(_index, bytes()); + } + private: void sendMessage(bytes const& _data, bool _isCreation) { @@ -123,11 +133,18 @@ BOOST_AUTO_TEST_CASE(recursive_calls) " }\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))); + std::function recursive_calls_cpp = [&recursive_calls_cpp] (u256 const& n) -> u256 { + if (n <= 1) + return 1; + else + return n * recursive_calls_cpp(n - 1); + }; + + BOOST_CHECK(testSolidityAgainstCpp(0, recursive_calls_cpp, u256(0))); + BOOST_CHECK(testSolidityAgainstCpp(0, recursive_calls_cpp, u256(1))); + BOOST_CHECK(testSolidityAgainstCpp(0, recursive_calls_cpp, u256(2))); + BOOST_CHECK(testSolidityAgainstCpp(0, recursive_calls_cpp, u256(3))); + BOOST_CHECK(testSolidityAgainstCpp(0, recursive_calls_cpp, u256(4))); } BOOST_AUTO_TEST_CASE(while_loop) @@ -140,11 +157,21 @@ BOOST_AUTO_TEST_CASE(while_loop) " }\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))); + + auto while_loop_cpp = [] (u256 const& n) -> u256 { + u256 nfac = 1; + u256 i = 2; + while (i <= n) + nfac *= i++; + + return nfac; + }; + + BOOST_CHECK(testSolidityAgainstCpp(0, while_loop_cpp, u256(0))); + BOOST_CHECK(testSolidityAgainstCpp(0, while_loop_cpp, u256(1))); + BOOST_CHECK(testSolidityAgainstCpp(0, while_loop_cpp, u256(2))); + BOOST_CHECK(testSolidityAgainstCpp(0, while_loop_cpp, u256(3))); + BOOST_CHECK(testSolidityAgainstCpp(0, while_loop_cpp, u256(4))); } BOOST_AUTO_TEST_CASE(break_outside_loop) @@ -182,18 +209,42 @@ BOOST_AUTO_TEST_CASE(nested_loops) "}\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(1))); - 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))); + + auto nested_loops_cpp = [] (u256 n) -> u256 { + while (n > 1) + { + if (n == 10) + break; + while (n > 5) + { + if (n == 8) + break; + n--; + if (n == 6) + continue; + return n; + } + n--; + if (n == 3) + continue; + break; + } + + return n; + }; + + BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(0))); + BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(1))); + BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(2))); + BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(3))); + BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(4))); + BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(5))); + BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(6))); + BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(7))); + BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(8))); + BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(9))); + BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(10))); + BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(11))); } BOOST_AUTO_TEST_CASE(calling_other_functions) @@ -214,11 +265,32 @@ BOOST_AUTO_TEST_CASE(calling_other_functions) " }\n" "}\n"; 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))); + + auto evenStep_cpp = [] (u256 const& n) -> u256 { + return n / 2; + }; + + auto oddStep_cpp = [] (u256 const& n) -> u256 { + return 3 * n + 1; + }; + + auto collatz_cpp = [&evenStep_cpp, &oddStep_cpp] (u256 n) -> u256 { + u256 y; + while ((y = n) > 1) + { + if (n % 2 == 0) + n = evenStep_cpp(n); + else + n = oddStep_cpp(n); + } + return y; + }; + + BOOST_CHECK(testSolidityAgainstCpp(2, collatz_cpp, u256(0))); + BOOST_CHECK(testSolidityAgainstCpp(2, collatz_cpp, u256(1))); + BOOST_CHECK(testSolidityAgainstCpp(2, collatz_cpp, u256(2))); + BOOST_CHECK(testSolidityAgainstCpp(2, collatz_cpp, u256(8))); + BOOST_CHECK(testSolidityAgainstCpp(2, collatz_cpp, u256(127))); } BOOST_AUTO_TEST_CASE(many_local_variables) @@ -270,8 +342,14 @@ BOOST_AUTO_TEST_CASE(short_circuiting) " }\n" "}\n"; compileAndRun(sourceCode); - BOOST_CHECK(callFunction(0, u256(0)) == toBigEndian(u256(0))); - BOOST_CHECK(callFunction(0, u256(1)) == toBigEndian(u256(8))); + + auto short_circuiting_cpp = [] (u256 n) -> u256 { + n == 0 || (n = 8) > 0; + return n; + }; + + BOOST_CHECK(testSolidityAgainstCpp(0, short_circuiting_cpp, u256(0))); + BOOST_CHECK(testSolidityAgainstCpp(0, short_circuiting_cpp, u256(1))); } BOOST_AUTO_TEST_CASE(high_bits_cleaning) @@ -284,7 +362,13 @@ BOOST_AUTO_TEST_CASE(high_bits_cleaning) " }\n" "}\n"; compileAndRun(sourceCode); - BOOST_CHECK(callFunction(0, bytes()) == toBigEndian(u256(9))); + auto high_bits_cleaning_cpp = []() -> u256 { + uint32_t x = uint32_t(0xffffffff) + 10; + if (x >= 0xffffffff) + return 0; + return x; + }; + BOOST_CHECK(testSolidityAgainstCpp(0, high_bits_cleaning_cpp)); } BOOST_AUTO_TEST_CASE(sign_extension) @@ -297,7 +381,13 @@ BOOST_AUTO_TEST_CASE(sign_extension) " }\n" "}\n"; compileAndRun(sourceCode); - BOOST_CHECK(callFunction(0, bytes()) == toBigEndian(u256(0xff))); + auto sign_extension_cpp = []() -> u256 { + int64_t x = -int32_t(0xff); + if (x >= 0xff) + return 0; + return u256(x) * -1; + }; + BOOST_CHECK(testSolidityAgainstCpp(0, sign_extension_cpp)); } BOOST_AUTO_TEST_CASE(small_unsigned_types) @@ -309,7 +399,11 @@ BOOST_AUTO_TEST_CASE(small_unsigned_types) " }\n" "}\n"; compileAndRun(sourceCode); - BOOST_CHECK(callFunction(0, bytes()) == toBigEndian(u256(0xfe0000))); + auto small_unsigned_types_cpp = []() -> u256 { + uint32_t x = uint32_t(0xffffff) * 0xffffff; + return x / 0x100; + }; + BOOST_CHECK(testSolidityAgainstCpp(0, small_unsigned_types_cpp)); } BOOST_AUTO_TEST_CASE(small_signed_types) @@ -320,7 +414,10 @@ BOOST_AUTO_TEST_CASE(small_signed_types) " }\n" "}\n"; compileAndRun(sourceCode); - BOOST_CHECK(callFunction(0, bytes()) == toBigEndian(u256(200))); + auto small_signed_types_cpp = []() -> u256 { + return -int32_t(10) * -int64_t(20); + }; + BOOST_CHECK(testSolidityAgainstCpp(0, small_signed_types_cpp)); } BOOST_AUTO_TEST_SUITE_END() From e75bf227337732bf22f359dd08929051dc717c4a Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Sun, 9 Nov 2014 13:22:47 +0100 Subject: [PATCH 2/2] style fixes --- solidityEndToEndTest.cpp | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/solidityEndToEndTest.cpp b/solidityEndToEndTest.cpp index e4ab7b876..53798ca95 100644 --- a/solidityEndToEndTest.cpp +++ b/solidityEndToEndTest.cpp @@ -133,7 +133,8 @@ BOOST_AUTO_TEST_CASE(recursive_calls) " }\n" "}\n"; compileAndRun(sourceCode); - std::function recursive_calls_cpp = [&recursive_calls_cpp] (u256 const& n) -> u256 { + std::function recursive_calls_cpp = [&recursive_calls_cpp](u256 const& n) -> u256 + { if (n <= 1) return 1; else @@ -158,7 +159,8 @@ BOOST_AUTO_TEST_CASE(while_loop) "}\n"; compileAndRun(sourceCode); - auto while_loop_cpp = [] (u256 const& n) -> u256 { + auto while_loop_cpp = [](u256 const& n) -> u256 + { u256 nfac = 1; u256 i = 2; while (i <= n) @@ -210,7 +212,8 @@ BOOST_AUTO_TEST_CASE(nested_loops) ExecutionFramework framework; framework.compileAndRun(sourceCode); - auto nested_loops_cpp = [] (u256 n) -> u256 { + auto nested_loops_cpp = [](u256 n) -> u256 + { while (n > 1) { if (n == 10) @@ -266,11 +269,13 @@ BOOST_AUTO_TEST_CASE(calling_other_functions) "}\n"; compileAndRun(sourceCode); - auto evenStep_cpp = [] (u256 const& n) -> u256 { + auto evenStep_cpp = [](u256 const& n) -> u256 + { return n / 2; }; - auto oddStep_cpp = [] (u256 const& n) -> u256 { + auto oddStep_cpp = [](u256 const& n) -> u256 + { return 3 * n + 1; }; @@ -343,7 +348,8 @@ BOOST_AUTO_TEST_CASE(short_circuiting) "}\n"; compileAndRun(sourceCode); - auto short_circuiting_cpp = [] (u256 n) -> u256 { + auto short_circuiting_cpp = [](u256 n) -> u256 + { n == 0 || (n = 8) > 0; return n; }; @@ -362,7 +368,8 @@ BOOST_AUTO_TEST_CASE(high_bits_cleaning) " }\n" "}\n"; compileAndRun(sourceCode); - auto high_bits_cleaning_cpp = []() -> u256 { + auto high_bits_cleaning_cpp = []() -> u256 + { uint32_t x = uint32_t(0xffffffff) + 10; if (x >= 0xffffffff) return 0; @@ -381,7 +388,8 @@ BOOST_AUTO_TEST_CASE(sign_extension) " }\n" "}\n"; compileAndRun(sourceCode); - auto sign_extension_cpp = []() -> u256 { + auto sign_extension_cpp = []() -> u256 + { int64_t x = -int32_t(0xff); if (x >= 0xff) return 0; @@ -399,7 +407,8 @@ BOOST_AUTO_TEST_CASE(small_unsigned_types) " }\n" "}\n"; compileAndRun(sourceCode); - auto small_unsigned_types_cpp = []() -> u256 { + auto small_unsigned_types_cpp = []() -> u256 + { uint32_t x = uint32_t(0xffffff) * 0xffffff; return x / 0x100; }; @@ -414,7 +423,8 @@ BOOST_AUTO_TEST_CASE(small_signed_types) " }\n" "}\n"; compileAndRun(sourceCode); - auto small_signed_types_cpp = []() -> u256 { + auto small_signed_types_cpp = []() -> u256 + { return -int32_t(10) * -int64_t(20); }; BOOST_CHECK(testSolidityAgainstCpp(0, small_signed_types_cpp));