diff options
author | chriseth <c@ethdev.com> | 2016-01-25 04:43:48 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2016-01-25 04:43:48 +0800 |
commit | 194679f77ada30b04f483e96197e890e41a0c22c (patch) | |
tree | 82ed4cec81cb9dd81cbdc3b8134b80fb7e3de780 /test | |
parent | 67c855c583042ddee6261a9921239a3afd086c14 (diff) | |
parent | 51caa04238ce78420e6efc2ce15842effddf3856 (diff) | |
download | dexon-solidity-194679f77ada30b04f483e96197e890e41a0c22c.tar dexon-solidity-194679f77ada30b04f483e96197e890e41a0c22c.tar.gz dexon-solidity-194679f77ada30b04f483e96197e890e41a0c22c.tar.bz2 dexon-solidity-194679f77ada30b04f483e96197e890e41a0c22c.tar.lz dexon-solidity-194679f77ada30b04f483e96197e890e41a0c22c.tar.xz dexon-solidity-194679f77ada30b04f483e96197e890e41a0c22c.tar.zst dexon-solidity-194679f77ada30b04f483e96197e890e41a0c22c.zip |
Merge pull request #326 from guanqun/cond-expr
support conditional expression _ ? _ : _
Diffstat (limited to 'test')
-rw-r--r-- | test/libsolidity/SolidityEndToEndTest.cpp | 186 | ||||
-rw-r--r-- | test/libsolidity/SolidityNameAndTypeResolution.cpp | 176 | ||||
-rw-r--r-- | test/libsolidity/SolidityParser.cpp | 67 |
3 files changed, 429 insertions, 0 deletions
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 3ef5ebbe..73e2d662 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -86,6 +86,192 @@ BOOST_AUTO_TEST_CASE(exp_operator_const_signed) BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(-8))); } +BOOST_AUTO_TEST_CASE(conditional_expression_true_literal) +{ + char const* sourceCode = R"( + contract test { + function f() returns(uint d) { + return true ? 5 : 10; + } + })"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(5))); +} + +BOOST_AUTO_TEST_CASE(conditional_expression_false_literal) +{ + char const* sourceCode = R"( + contract test { + function f() returns(uint d) { + return false ? 5 : 10; + } + })"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(10))); +} + +BOOST_AUTO_TEST_CASE(conditional_expression_multiple) +{ + char const* sourceCode = R"( + contract test { + function f(uint x) returns(uint d) { + return x > 100 ? + x > 1000 ? 1000 : 100 + : + x > 50 ? 50 : 10; + } + })"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("f(uint256)", u256(1001)) == toBigEndian(u256(1000))); + BOOST_CHECK(callContractFunction("f(uint256)", u256(500)) == toBigEndian(u256(100))); + BOOST_CHECK(callContractFunction("f(uint256)", u256(80)) == toBigEndian(u256(50))); + BOOST_CHECK(callContractFunction("f(uint256)", u256(40)) == toBigEndian(u256(10))); +} + +BOOST_AUTO_TEST_CASE(conditional_expression_with_return_values) +{ + char const* sourceCode = R"( + contract test { + function f(bool cond, uint v) returns (uint a, uint b) { + cond ? a = v : b = v; + } + })"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("f(bool,uint256)", true, u256(20)) == encodeArgs(u256(20), u256(0))); + BOOST_CHECK(callContractFunction("f(bool,uint256)", false, u256(20)) == encodeArgs(u256(0), u256(20))); +} + +BOOST_AUTO_TEST_CASE(conditional_expression_storage_memory_1) +{ + char const* sourceCode = R"( + contract test { + bytes2[2] data1; + function f(bool cond) returns (uint) { + bytes2[2] memory x; + x[0] = "aa"; + bytes2[2] memory y; + y[0] = "bb"; + + data1 = cond ? x : y; + + uint ret = 0; + if (data1[0] == "aa") + { + ret = 1; + } + + if (data1[0] == "bb") + { + ret = 2; + } + + return ret; + } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(u256(2))); +} + +BOOST_AUTO_TEST_CASE(conditional_expression_storage_memory_2) +{ + char const* sourceCode = R"( + contract test { + bytes2[2] data1; + function f(bool cond) returns (uint) { + data1[0] = "cc"; + + bytes2[2] memory x; + bytes2[2] memory y; + y[0] = "bb"; + + x = cond ? y : data1; + + uint ret = 0; + if (x[0] == "bb") + { + ret = 1; + } + + if (x[0] == "cc") + { + ret = 2; + } + + return ret; + } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(u256(2))); +} + +BOOST_AUTO_TEST_CASE(conditional_expression_different_types) +{ + char const* sourceCode = R"( + contract test { + function f(bool cond) returns (uint) { + uint8 x = 0xcd; + uint16 y = 0xabab; + return cond ? x : y; + } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(u256(0xcd))); + BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(u256(0xabab))); +} + +/* let's add this back when I figure out the correct type conversion. +BOOST_AUTO_TEST_CASE(conditional_expression_string_literal) +{ + char const* sourceCode = R"( + contract test { + function f(bool cond) returns (bytes32) { + return cond ? "true" : "false"; + } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(string("true", 4))); + BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(string("false", 5))); +} +*/ + +BOOST_AUTO_TEST_CASE(conditional_expression_tuples) +{ + char const* sourceCode = R"( + contract test { + function f(bool cond) returns (uint, uint) { + return cond ? (1, 2) : (3, 4); + } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(u256(1), u256(2))); + BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(u256(3), u256(4))); +} + +BOOST_AUTO_TEST_CASE(conditional_expression_functions) +{ + char const* sourceCode = R"( + contract test { + function x() returns (uint) { return 1; } + function y() returns (uint) { return 2; } + + function f(bool cond) returns (uint) { + var z = cond ? x : y; + return z(); + } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(u256(2))); +} + BOOST_AUTO_TEST_CASE(recursive_calls) { char const* sourceCode = "contract test {\n" diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index c8e901e4..820fd7d0 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -2960,6 +2960,182 @@ BOOST_AUTO_TEST_CASE(continue_not_in_loop_2) BOOST_CHECK(expectError(text) == Error::Type::SyntaxError); } +BOOST_AUTO_TEST_CASE(invalid_different_types_for_conditional_expression) +{ + char const* text = R"( + contract C { + function f() { + true ? true : 2; + } + } + )"; + BOOST_CHECK(expectError(text) == Error::Type::TypeError); +} + +BOOST_AUTO_TEST_CASE(left_value_in_conditional_expression_not_supported_yet) +{ + char const* text = R"( + contract C { + function f() { + uint x; + uint y; + (true ? x : y) = 1; + } + } + )"; + BOOST_CHECK(expectError(text) == Error::Type::TypeError); +} + +BOOST_AUTO_TEST_CASE(conditional_expression_with_different_struct) +{ + char const* text = R"( + contract C { + struct s1 { + uint x; + } + struct s2 { + uint x; + } + function f() { + s1 x; + s2 y; + true ? x : y; + } + } + )"; + BOOST_CHECK(expectError(text) == Error::Type::TypeError); +} + +BOOST_AUTO_TEST_CASE(conditional_expression_with_different_function_type) +{ + char const* text = R"( + contract C { + function x(bool) {} + function y() {} + + function f() { + true ? x : y; + } + } + )"; + BOOST_CHECK(expectError(text) == Error::Type::TypeError); +} + +BOOST_AUTO_TEST_CASE(conditional_expression_with_different_enum) +{ + char const* text = R"( + contract C { + enum small { A, B, C, D } + enum big { A, B, C, D } + + function f() { + small x; + big y; + + true ? x : y; + } + } + )"; + BOOST_CHECK(expectError(text) == Error::Type::TypeError); +} + +BOOST_AUTO_TEST_CASE(conditional_expression_with_different_mapping) +{ + char const* text = R"( + contract C { + mapping(uint8 => uint8) table1; + mapping(uint32 => uint8) table2; + + function f() { + true ? table1 : table2; + } + } + )"; + BOOST_CHECK(expectError(text) == Error::Type::TypeError); +} + +BOOST_AUTO_TEST_CASE(conditional_with_all_types) +{ + char const* text = R"( + contract C { + struct s1 { + uint x; + } + s1 struct_x; + s1 struct_y; + + function fun_x() {} + function fun_y() {} + + enum small { A, B, C, D } + + mapping(uint8 => uint8) table1; + mapping(uint8 => uint8) table2; + + function f() { + // integers + uint x; + uint y; + true ? x : y; + + // integer constants + true ? 1 : 3; + + // string literal + true ? "hello" : "world"; + + // bool + true ? true : false; + + // real is not there yet. + + // array + byte[2] memory a; + byte[2] memory b; + true ? a : b; + + bytes memory e; + bytes memory f; + true ? e : f; + + // fixed bytes + bytes2 c; + bytes2 d; + true ? c : d; + + // contract doesn't fit in here + + // struct + true ? struct_x : struct_y; + + // function + true ? fun_x : fun_y; + + // enum + small enum_x; + small enum_y; + true ? enum_x : enum_y; + + // tuple + true ? (1, 2) : (3, 4); + + // mapping + true ? table1 : table2; + + // typetype + true ? uint32(1) : uint32(2); + + // modifier doesn't fit in here + + // magic doesn't fit in here + + // module doesn't fit in here + } + } + )"; + BOOST_CHECK(success(text)); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index 8e0bf77e..055fae49 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -1111,6 +1111,73 @@ BOOST_AUTO_TEST_CASE(inline_array_empty_cells_check_without_lvalue) BOOST_CHECK(!successParse(text)); } +BOOST_AUTO_TEST_CASE(conditional_true_false_literal) +{ + char const* text = R"( + contract A { + function f() { + uint x = true ? 1 : 0; + uint y = false ? 0 : 1; + } + } + )"; + BOOST_CHECK(successParse(text)); +} + +BOOST_AUTO_TEST_CASE(conditional_with_constants) +{ + char const* text = R"( + contract A { + function f() { + uint x = 3 > 0 ? 3 : 0; + uint y = (3 > 0) ? 3 : 0; + } + } + )"; + BOOST_CHECK(successParse(text)); +} + +BOOST_AUTO_TEST_CASE(conditional_with_variables) +{ + char const* text = R"( + contract A { + function f() { + uint x = 3; + uint y = 1; + uint z = (x > y) ? x : y; + uint w = x > y ? x : y; + } + } + )"; + BOOST_CHECK(successParse(text)); +} + +BOOST_AUTO_TEST_CASE(conditional_multiple) +{ + char const* text = R"( + contract A { + function f() { + uint x = 3 < 0 ? 2 > 1 ? 2 : 1 : 7 > 2 ? 7 : 6; + } + } + )"; + BOOST_CHECK(successParse(text)); +} + +BOOST_AUTO_TEST_CASE(conditional_with_assignment) +{ + char const* text = R"( + contract A { + function f() { + uint y = 1; + uint x = 3 < 0 ? x = 3 : 6; + true ? x = 3 : 4; + } + } + )"; + BOOST_CHECK(successParse(text)); +} + BOOST_AUTO_TEST_SUITE_END() } |